~ubuntu-branches/ubuntu/jaunty/electric/jaunty

« back to all changes in this revision

Viewing changes to com/sun/electric/tool/drc/Quick.java

  • Committer: Bazaar Package Importer
  • Author(s): Onkar Shinde
  • Date: 2009-01-08 02:05:08 UTC
  • mfrom: (1.1.2 upstream) (3.1.4 sid)
  • Revision ID: james.westby@ubuntu.com-20090108020508-0h3li7zt9mu5gf0i
Tags: 8.08-1
New upstream version.

Show diffs side-by-side

added added

removed removed

Lines of Context:
86
86
 
87
87
public class Quick
88
88
{
89
 
        private static final double TINYDELTA = DBMath.getEpsilon()*1.1;
90
 
    /** key of Variable holding DRC Cell annotations. */        private static final Variable.Key DRC_ANNOTATION_KEY = Variable.newKey("ATTR_DRC");
91
 
 
92
 
    /**
93
 
         * The CheckInst object is associated with every cell instance in the library.
94
 
         * It helps determine network information on a global scale.
95
 
         * It takes a "global-index" parameter, inherited from above (intially zero).
96
 
         * It then computes its own index number as follows:
97
 
         *   thisindex = global-index * multiplier + localIndex + offset
98
 
         * This individual index is used to lookup an entry on each network in the cell
99
 
         * (an array is stored on each network, giving its global net number).
100
 
         */
101
 
        private static class CheckInst
102
 
        {
103
 
                int localIndex;
104
 
                int multiplier;
105
 
                int offset;
106
 
        }
107
89
        private HashMap<NodeInst,CheckInst> checkInsts = null;
108
 
 
109
 
 
110
 
        /**
111
 
         * The CheckProto object is placed on every cell and is used only temporarily
112
 
         * to number the instances.
113
 
         */
114
 
        private static class CheckProto
115
 
        {
116
 
                /** time stamp for counting within a particular parent */               int timeStamp;
117
 
                /** number of instances of this cell in a particular parent */  int instanceCount;
118
 
                /** total number of instances of this cell, hierarchically */   int hierInstanceCount;
119
 
                /** number of instances of this cell in a particular parent */  int totalPerCell;
120
 
                /** true if this cell has been checked */                                               boolean cellChecked;
121
 
                /** true if this cell has parameters */                                                 boolean cellParameterized;
122
 
                /** list of instances in a particular parent */                                 List<CheckInst> nodesInCell;
123
 
                /** netlist of this cell */                                                                             Netlist netlist;
124
 
        }
125
 
 
126
90
    private HashMap<Cell,CheckProto> checkProtos = null;
127
91
        private HashMap<Network,Integer[]> networkLists = null;
128
92
        private HashMap<Layer,DRCTemplate> minAreaLayerMap = new HashMap<Layer,DRCTemplate>();    // For minimum area checking
132
96
    private DRC.CheckDRCJob job; // Reference to running job
133
97
        private HashMap<Cell,Cell> cellsMap = new HashMap<Cell,Cell>(); // for cell caching
134
98
    private HashMap<Geometric,Geometric> nodesMap = new HashMap<Geometric,Geometric>(); // for node caching
135
 
    private int activeSpacingBits = 0; // to cache current extra bits
136
 
    private boolean inMemory = DRC.isDatesStoredInMemory();
137
99
    private GeometryHandler.GHMode mergeMode = GeometryHandler.GHMode.ALGO_SWEEP; // .ALGO_QTREE;
138
100
    private Map<Layer,NodeInst> od2Layers = new HashMap<Layer,NodeInst>(3);  /** to control OD2 combination in the same die according to foundries */
139
101
 
143
105
        this.mergeMode = mode;
144
106
        }
145
107
 
146
 
        /**
147
 
         * The InstanceInter object records interactions between two cell instances and prevents checking
148
 
         * them multiple times.
149
 
         */
150
 
        private static class InstanceInter
151
 
        {
152
 
                /** the two cell instances being compared */    Cell cell1, cell2;
153
 
        /** orientation of cell instance 1 */           Orientation or1;
154
 
        /** orientation of cell instance 2 */           Orientation or2;
155
 
                /** distance from instance 1 to instance 2 */   double dx, dy;
156
 
        /** the two NodeInst parents */                 NodeInst n1Parent, n2Parent, triggerNi;
157
 
        }
158
 
 
159
108
    private List<InstanceInter> instanceInteractionList = new ArrayList<InstanceInter>();
160
109
 
161
 
 
162
 
        /**
163
 
         * The DRCExclusion object lists areas where Generic:DRC-Nodes exist to ignore errors.
164
 
         */
165
 
    private Map<Cell,Area> exclusionMap = new HashMap<Cell,Area>();
166
 
 
167
 
 
168
 
        /** error type search */                                                    private DRC.DRCCheckMode errorTypeSearch;
169
 
    /** minimum output grid resolution */                                       private double minAllowedResolution;
170
 
        /** true to ignore center cuts in large contacts. */            private boolean ignoreCenterCuts;
171
 
        /** maximum area to examine (the worst spacing rule). */        private double worstInteractionDistance;
172
 
        /** time stamp for numbering networks. */                                       private int checkTimeStamp;
173
 
        /** for numbering networks. */                                                          private int checkNetNumber;
174
 
        /** total errors found in all threads. */                                       private int totalSpacingMsgFound;
175
110
        /** a NodeInst that is too tiny for its connection. */          private NodeInst tinyNodeInst;
176
111
        /** the other Geometric in "tiny" errors. */                            private Geometric tinyGeometric;
177
112
        /** for tracking the time of good DRC. */                                       private HashSet<Cell> goodSpacingDRCDate = new HashSet<Cell>();
178
113
        /** for tracking cells that need to clean good DRC vars */      private HashSet<Cell> cleanSpacingDRCDate = new HashSet<Cell>();
179
114
        /** for tracking the time of good DRC. */                                       private HashSet<Cell> goodAreaDRCDate = new HashSet<Cell>();
180
115
        /** for tracking cells that need to clean good DRC vars */      private HashSet<Cell> cleanAreaDRCDate = new HashSet<Cell>();
181
 
        /** for logging errors */                                   private ErrorLogger errorLogger;
182
 
    /** for interactive error logging */                        private boolean interactiveLogger = false;
183
116
        /** Top cell for DRC */                                     private Cell topCell;
184
 
 
185
 
        /* for figuring out which layers are valid for DRC */
186
 
        private Technology layersValidTech = null;
187
 
        private boolean [] layersValid;
188
 
 
189
 
        /* for tracking which layers interact with which nodes */
190
 
        private Technology layerInterTech = null;
191
 
        private HashMap<PrimitiveNode, boolean[]> layersInterNodes = null;
192
 
        private HashMap<ArcProto, boolean[]> layersInterArcs = null;
 
117
    /** Miscellanous data for DRC */                            private DRC.ReportInfo reportInfo;
 
118
 
 
119
//    /* for figuring out which layers are valid for DRC */
 
120
    // To speed up the layer process
 
121
    private ValidationLayers validLayers;
193
122
 
194
123
    public static ErrorLogger checkDesignRules(ErrorLogger errorLog, Cell cell, Geometric[] geomsToCheck, boolean[] validity,
195
124
                                               Rectangle2D bounds)
225
154
                // Check if there are DRC rules for particular tech
226
155
        Technology tech = cell.getTechnology();
227
156
                DRCRules rules = DRC.getRules(tech);
228
 
                errorLogger = errorLog;
 
157
 
 
158
        // if checking specific instances, adjust options and processor count
 
159
        int count = (geomsToCheck != null) ? geomsToCheck.length : 0;
 
160
 
 
161
        reportInfo = new DRC.ReportInfo(errorLog, tech, (count > 0));
 
162
        ErrorLogger errorLogger = errorLog;
229
163
 
230
164
        // caching bits
231
 
        activeSpacingBits = DRC.getActiveBits(tech);
232
 
        System.out.println("Running DRC with " + DRC.explainBits(activeSpacingBits));
233
 
 
234
 
        // caching memory setting
235
 
        inMemory = DRC.isDatesStoredInMemory();
236
 
        interactiveLogger = DRC.isInteractiveLoggingOn();
237
 
 
238
 
        // minimim resolution different from zero if flag is on otherwise stays at zero (default)
239
 
        minAllowedResolution = tech.getResolution();
 
165
        System.out.println("Running DRC with " + DRC.explainBits(reportInfo.activeSpacingBits));
240
166
 
241
167
                // Nothing to check for this particular technology
242
168
                if (rules == null || rules.getNumberOfRules() == 0) return errorLogger;
243
169
 
244
 
                // get the current DRC options
245
 
                errorTypeSearch = DRC.getErrorType();
246
 
                ignoreCenterCuts = DRC.isIgnoreCenterCuts();
247
170
            topCell = cell; /* Especially important for minArea checking */
248
171
 
249
 
                // if checking specific instances, adjust options and processor count
250
 
        int count = (geomsToCheck != null) ? geomsToCheck.length : 0;
251
 
                if (count > 0)
252
 
                {
253
 
                        errorTypeSearch = DRC.DRCCheckMode.ERROR_CHECK_CELL;
254
 
                }
255
 
 
256
172
                // cache valid layers for this technology
257
 
                cacheValidLayers(tech);
258
 
                buildLayerInteractions(tech);
 
173
        validLayers = new ValidationLayers(reportInfo.errorLogger, topCell, rules);
259
174
 
260
175
                // clean out the cache of instances
261
176
            instanceInteractionList.clear();
262
177
 
263
178
                // determine maximum DRC interaction distance
264
 
                worstInteractionDistance = DRC.getWorstSpacingDistance(tech, -1);
 
179
//              worstInteractionDistance = DRC.getWorstSpacingDistance(tech, -1);
265
180
 
266
181
            // determine if min area must be checked (if any layer got valid data)
267
182
            minAreaLayerMap.clear();
272
187
            nodesMap.clear();
273
188
 
274
189
            // No incremental neither per Cell
275
 
            if (!DRC.isIgnoreAreaChecking() && errorTypeSearch != DRC.DRCCheckMode.ERROR_CHECK_CELL)
 
190
            if (!DRC.isIgnoreAreaChecking() && reportInfo.errorTypeSearch != DRC.DRCCheckMode.ERROR_CHECK_CELL)
276
191
            {
277
192
                    for(Iterator<Layer> it = tech.getLayers(); it.hasNext(); )
278
193
                        {
320
235
 
321
236
                // now recursively examine, setting information on all instances
322
237
                cp.hierInstanceCount = 1;
323
 
                checkTimeStamp = 0;
 
238
                reportInfo.checkTimeStamp = 0;
324
239
                checkEnumerateInstances(cell);
325
240
 
326
241
                // now allocate space for hierarchical network arrays
355
270
                                CheckProto ocp = getCheckProto((Cell)np);
356
271
                                ci.offset = ocp.totalPerCell;
357
272
                        }
358
 
                        checkTimeStamp++;
 
273
                        reportInfo.checkTimeStamp++;
359
274
                        for(Iterator<NodeInst> nIt = libCell.getNodes(); nIt.hasNext(); )
360
275
                        {
361
276
                                NodeInst ni = nIt.next();
366
281
                                if (ni.isIconOfParent()) continue;
367
282
 
368
283
                                CheckProto ocp = getCheckProto((Cell)np);
369
 
                                if (ocp.timeStamp != checkTimeStamp)
 
284
                                if (ocp.timeStamp != reportInfo.checkTimeStamp)
370
285
                                {
371
286
                                        CheckInst ci = checkInsts.get(ni);
372
 
                                        ocp.timeStamp = checkTimeStamp;
 
287
                                        ocp.timeStamp = reportInfo.checkTimeStamp;
373
288
                                        ocp.totalPerCell += subCP.hierInstanceCount * ci.multiplier;
374
289
                                }
375
290
                        }
376
291
                }
377
292
 
378
293
                // now fill in the hierarchical network arrays
379
 
                checkTimeStamp = 0;
380
 
                checkNetNumber = 1;
 
294
                reportInfo.checkTimeStamp = 0;
 
295
                int checkNetNumber = 1;
381
296
 
382
297
                HashMap<Network,Integer> enumeratedNets = new HashMap<Network,Integer>();
383
298
                for(Iterator<Network> nIt = cp.netlist.getNetworks(); nIt.hasNext(); )
392
307
                        System.out.println("Found " + checkNetNumber + " networks");
393
308
 
394
309
                // now search for DRC exclusion areas
395
 
        exclusionMap.clear();
 
310
        reportInfo.exclusionMap.clear();
396
311
                accumulateExclusion(cell);
397
312
 
398
313
                // now do the DRC
433
348
        // This is only going to happen if job was not aborted.
434
349
            if ((job == null || !job.checkAbort()))
435
350
            {
436
 
            DRC.addDRCUpdate(activeSpacingBits, goodSpacingDRCDate, cleanSpacingDRCDate, 
 
351
            DRC.addDRCUpdate(reportInfo.activeSpacingBits, goodSpacingDRCDate, cleanSpacingDRCDate,
437
352
                goodAreaDRCDate, cleanAreaDRCDate, null);
438
353
            }
439
354
 
463
378
                // Previous # of errors/warnings
464
379
                int prevErrors = 0;
465
380
                int prevWarns = 0;
466
 
                if (errorLogger != null)
 
381
                if (reportInfo.errorLogger != null)
467
382
                {
468
 
                        prevErrors = errorLogger.getNumErrors();
469
 
                        prevWarns = errorLogger.getNumWarnings();
 
383
                        prevErrors = reportInfo.errorLogger.getNumErrors();
 
384
                        prevWarns = reportInfo.errorLogger.getNumWarnings();
470
385
                }
471
386
 
472
387
                cellsMap.put(cell, cell);
473
388
 
474
389
        // Check if cell doesn't have special annotation
475
 
        Variable drcVar = cell.getVar(DRC_ANNOTATION_KEY);
 
390
        Variable drcVar = cell.getVar(DRC.DRC_ANNOTATION_KEY);
476
391
        if (drcVar != null && drcVar.getObject().toString().startsWith("black"))
477
392
        {
478
393
            // Skipping this one
479
 
            assert(totalSpacingMsgFound == 0); // get rid of this variable.
480
 
            return totalSpacingMsgFound;
 
394
            assert(reportInfo.totalSpacingMsgFound == 0); // get rid of this variable.
 
395
            return reportInfo.totalSpacingMsgFound;
481
396
        }
482
397
 
483
398
                // first check all subcells
484
399
                boolean allSubCellsStillOK = true;
485
 
        Area area = exclusionMap.get(cell);
 
400
        Area area = reportInfo.exclusionMap.get(cell);
486
401
 
487
402
                for(Iterator<NodeInst> it = cell.getNodes(); it.hasNext(); )
488
403
                {
489
 
                        NodeInst ni = it.next();
 
404
            if (job != null && job.checkAbort()) return -1;
 
405
 
 
406
            NodeInst ni = it.next();
490
407
                        NodeProto np = ni.getProto();
491
408
                        if (!ni.isCellInstance()) continue;
492
409
 
532
449
                // prepare to check cell
533
450
                CheckProto cp = getCheckProto(cell);
534
451
                cp.cellChecked = true;
535
 
        boolean checkArea = (cell == topCell && !DRC.isIgnoreAreaChecking() && errorTypeSearch != DRC.DRCCheckMode.ERROR_CHECK_CELL);
 
452
        boolean checkArea = (cell == topCell && !DRC.isIgnoreAreaChecking() && reportInfo.errorTypeSearch != DRC.DRCCheckMode.ERROR_CHECK_CELL);
536
453
 
537
454
        // if the cell hasn't changed since the last good check, stop now
538
 
        Date lastSpacingGoodDate = DRC.getLastDRCDateBasedOnBits(cell, true, activeSpacingBits, !inMemory);
539
 
        Date lastAreaGoodDate = DRC.getLastDRCDateBasedOnBits(cell, false, -1, !inMemory);
 
455
        Date lastSpacingGoodDate = DRC.getLastDRCDateBasedOnBits(cell, true, reportInfo.activeSpacingBits, !reportInfo.inMemory);
 
456
        Date lastAreaGoodDate = DRC.getLastDRCDateBasedOnBits(cell, false, -1, !reportInfo.inMemory);
540
457
        if (allSubCellsStillOK && DRC.isCellDRCDateGood(cell, lastSpacingGoodDate) &&
541
458
            (!checkArea || DRC.isCellDRCDateGood(cell, lastAreaGoodDate)))
542
459
                {
548
465
                System.out.println("Checking " + cell);
549
466
 
550
467
                // now look at every node and arc here
551
 
                totalSpacingMsgFound = 0;
 
468
                reportInfo.totalSpacingMsgFound = 0;
552
469
 
553
470
                // Check the area first but only when is not incremental
554
471
                // Only for the most top cell
555
472
                if (checkArea)
556
473
        {
557
474
//            totalMsgFound = checkMinArea(cell);
558
 
            assert(totalSpacingMsgFound == 0);
 
475
            assert(reportInfo.totalSpacingMsgFound == 0);
559
476
            int totalAreaMsgFound = checkMinAreaSlow(cell);
560
477
            if (totalAreaMsgFound == 0)
561
478
                goodAreaDRCDate.add(cell);
565
482
 
566
483
        for(Iterator<NodeInst> it = cell.getNodes(); it.hasNext(); )
567
484
                {
568
 
                        NodeInst ni = it.next();
 
485
            if (job != null && job.checkAbort()) return -1;
 
486
 
 
487
            NodeInst ni = it.next();
569
488
                        if (bounds != null)
570
489
                        {
571
490
                                if (!ni.getBounds().intersects(bounds)) continue;
582
501
                                checkNodeInst(ni, globalIndex);
583
502
                        if (ret)
584
503
                        {
585
 
                                totalSpacingMsgFound++;
586
 
                                if (errorTypeSearch == DRC.DRCCheckMode.ERROR_CHECK_CELL) break;
 
504
                                reportInfo.totalSpacingMsgFound++;
 
505
                                if (reportInfo.errorTypeSearch == DRC.DRCCheckMode.ERROR_CHECK_CELL) break;
587
506
                        }
588
507
                }
589
508
                Technology cellTech = cell.getTechnology();
590
 
                for(Iterator it = cell.getArcs(); it.hasNext(); )
 
509
                for(Iterator<ArcInst> it = cell.getArcs(); it.hasNext(); )
591
510
                {
592
 
                        ArcInst ai = (ArcInst)it.next();
 
511
            if (job != null && job.checkAbort()) return -1;
 
512
 
 
513
            ArcInst ai = it.next();
593
514
                        Technology tech = ai.getProto().getTechnology();
594
515
                        if (tech != cellTech)
595
516
                        {
596
 
                                reportError(DRC.DRCErrorType.TECHMIXWARN, " belongs to " + tech.getTechName(), cell, 0, 0, null, null, ai, null, null, null, null);
 
517
                                DRC.createDRCErrorLogger(reportInfo, DRC.DRCErrorType.TECHMIXWARN, " belongs to " + tech.getTechName(),
 
518
                    cell, 0, 0, null, null, ai, null, null, null, null);
597
519
                                continue;
598
520
                        }
599
521
                        if (bounds != null)
602
524
                        }
603
525
                        if (checkArcInst(cp, ai, globalIndex))
604
526
                        {
605
 
                                totalSpacingMsgFound++;
606
 
                                if (errorTypeSearch == DRC.DRCCheckMode.ERROR_CHECK_CELL) break;
 
527
                                reportInfo.totalSpacingMsgFound++;
 
528
                                if (reportInfo.errorTypeSearch == DRC.DRCCheckMode.ERROR_CHECK_CELL) break;
607
529
                        }
608
530
                }
609
531
 
610
532
                // If message founds, then remove any possible good date
611
533
        // !allSubCellsStillOK disconnected on April 18, 2006. totalMsgFound should
612
534
        // dictate if this cell is re-marked.
613
 
                if (totalSpacingMsgFound > 0) //  || !allSubCellsStillOK)
 
535
                if (reportInfo.totalSpacingMsgFound > 0) //  || !allSubCellsStillOK)
614
536
                {
615
537
                        cleanSpacingDRCDate.add(cell);
616
538
                }
624
546
                }
625
547
 
626
548
                // if there were no errors, remember that
627
 
                if (errorLogger != null)
 
549
                if (reportInfo.errorLogger != null)
628
550
                {
629
 
                        int localErrors = errorLogger.getNumErrors() - prevErrors;
630
 
                        int localWarnings = errorLogger.getNumWarnings() - prevWarns;
 
551
                        int localErrors = reportInfo.errorLogger.getNumErrors() - prevErrors;
 
552
                        int localWarnings = reportInfo.errorLogger.getNumWarnings() - prevWarns;
631
553
            long endTime = System.currentTimeMillis();
632
554
                        if (localErrors == 0 &&  localWarnings == 0)
633
555
                        {
643
565
                System.out.println("\t(took " + TextUtils.getElapsedTime(endTime - startTime) + ")");
644
566
                }
645
567
 
646
 
                return totalSpacingMsgFound;
 
568
                return reportInfo.totalSpacingMsgFound;
647
569
        }
648
570
 
649
571
    /**
655
577
     */
656
578
    private boolean checkResolution(PolyBase poly, Cell cell, Geometric geom)
657
579
        {
658
 
                if (minAllowedResolution == 0) return false;
 
580
        double minAllowedResolution = reportInfo.minAllowedResolution;
 
581
        if (minAllowedResolution == 0) return false;
659
582
        int count = 0;
660
583
        String resolutionError = "";
661
584
                Point2D [] points = poly.getPoints();
680
603
 
681
604
        // there was an error, for now print error
682
605
        Layer layer = poly.getLayer();
683
 
        reportError(DRC.DRCErrorType.RESOLUTION, " resolution of " + resolutionError + " less than " + minAllowedResolution +
 
606
        DRC.createDRCErrorLogger(reportInfo,DRC.DRCErrorType.RESOLUTION, " resolution of " + resolutionError + " less than " + minAllowedResolution +
684
607
                " on layer " + layer.getName(), cell, 0, 0, "Resolution", null, geom, null, null, null, null);
685
608
        return true;
686
609
        }
693
616
    private boolean coverByExclusion(Geometric geo)
694
617
    {
695
618
        Cell cell = geo.getParent();
696
 
        Area area = exclusionMap.get(cell);
 
619
        Area area = reportInfo.exclusionMap.get(cell);
697
620
        if (area != null && area.contains(geo.getBounds()))
698
621
        {
699
622
//            System.out.println("DRC Exclusion found");
710
633
     */
711
634
    private boolean coverByExclusion(Poly poly, Cell parent)
712
635
    {
713
 
        Area area = exclusionMap.get(parent);
 
636
        Area area = reportInfo.exclusionMap.get(parent);
714
637
        if (area == null) return false;
715
638
 
716
639
        Point2D[] pts = poly.getPoints();
721
644
                return false;
722
645
            }
723
646
        }
724
 
//        System.out.println("DRC Exclusion found in coverByExclusion");
725
647
        return true;
726
648
    }
727
649
 
755
677
                        return (false);
756
678
                nodesMap.put(ni, ni);
757
679
 
758
 
        if (np instanceof PrimitiveNode && DRC.isForbiddenNode(((PrimitiveNode)np).getPrimNodeIndexInTech(), -1,
759
 
                DRCTemplate.DRCRuleType.FORBIDDEN, tech))
 
680
        if (DRC.checkNodeAgainstCombinationRules(ni, reportInfo))
760
681
        {
761
 
            reportError(DRC.DRCErrorType.FORBIDDEN, " is not allowed by selected foundry", cell, -1, -1, null, null, ni, null, null, null, null);
762
 
            if (errorTypeSearch == DRC.DRCCheckMode.ERROR_CHECK_CELL) return true;
 
682
            if (reportInfo.errorTypeSearch == DRC.DRCCheckMode.ERROR_CHECK_CELL) return true;
763
683
            errorsFound = true;
764
684
        }
 
685
//        if (np instanceof PrimitiveNode)
 
686
//        {
 
687
//            DRCTemplate forbidRule =
 
688
//            DRC.isForbiddenNode(((PrimitiveNode)np).getPrimNodeIndexInTech(), -1,
 
689
//                DRCTemplate.DRCRuleType.FORBIDDEN, tech);
 
690
//            if (forbidRule != null)
 
691
//            {
 
692
//                DRC.createDRCErrorLogger(reportInfo, DRC.DRCErrorType.FORBIDDEN, " is not allowed by selected foundry", cell,
 
693
//                    -1, -1, forbidRule.nodeName, null, ni, null, null, null, null);
 
694
//                if (reportInfo.errorTypeSearch == DRC.DRCCheckMode.ERROR_CHECK_CELL) return true;
 
695
//                errorsFound = true;
 
696
//            }
 
697
//        }
765
698
 
766
 
                // get all of the polygons on this node
767
 
                Poly [] nodeInstPolyList = tech.getShapeOfNode(ni, true, ignoreCenterCuts, null);
 
699
        // get all of the polygons on this node
 
700
                Poly [] nodeInstPolyList = tech.getShapeOfNode(ni, true, reportInfo.ignoreCenterCuts, null);
768
701
                convertPseudoLayers(ni, nodeInstPolyList);
769
702
                int tot = nodeInstPolyList.length;
770
703
        boolean isTransistor =  np.getFunction().isTransistor();
 
704
        Technology.MultiCutData multiCutData = tech.getMultiCutData(ni);
771
705
 
772
706
        // examine the polygons on this node
773
707
                for(int j=0; j<tot; j++)
780
714
                continue;
781
715
 
782
716
            // Checking combination
783
 
            boolean ret = checkOD2Combination(tech, ni, layer);
 
717
            boolean ret = DRC.checkOD2Combination(tech, ni, layer, od2Layers, reportInfo);
784
718
            if (ret)
785
719
            {
786
720
                // panic errors -> return regarless errorTypeSearch
793
727
            ret = checkResolution(poly, cell, ni);
794
728
            if (ret)
795
729
                        {
796
 
                                if (errorTypeSearch == DRC.DRCCheckMode.ERROR_CHECK_CELL) return true;
 
730
                                if (reportInfo.errorTypeSearch == DRC.DRCCheckMode.ERROR_CHECK_CELL) return true;
797
731
                                errorsFound = true;
798
732
                        }
799
733
 
800
734
                        // determine network for this polygon
801
735
                        int netNumber = getDRCNetNumber(netlist, poly.getPort(), ni, globalIndex);
802
736
 
803
 
                        ret = badBox(poly, layer, netNumber, tech, ni, trans, cell, globalIndex);
 
737
                        ret = badBox(poly, layer, netNumber, tech, ni, trans, cell, globalIndex, multiCutData);
804
738
                        if (ret)
805
739
                        {
806
 
                                if (errorTypeSearch == DRC.DRCCheckMode.ERROR_CHECK_CELL) return true;
 
740
                                if (reportInfo.errorTypeSearch == DRC.DRCCheckMode.ERROR_CHECK_CELL) return true;
807
741
                                errorsFound = true;
808
742
                        }
809
743
                        ret = checkMinWidth(ni, layer, poly, tot==1);
810
744
                        if (ret)
811
745
                        {
812
 
                                if (errorTypeSearch == DRC.DRCCheckMode.ERROR_CHECK_CELL) return true;
 
746
                                if (reportInfo.errorTypeSearch == DRC.DRCCheckMode.ERROR_CHECK_CELL) return true;
813
747
                                errorsFound = true;
814
748
                        }
815
749
                        // Check select over transistor poly
818
752
            ret = !isTransistor && checkExtensionRules(ni, layer, poly, cell);
819
753
            if (ret)
820
754
                        {
821
 
                                if (errorTypeSearch == DRC.DRCCheckMode.ERROR_CHECK_CELL) return true;
 
755
                                if (reportInfo.errorTypeSearch == DRC.DRCCheckMode.ERROR_CHECK_CELL) return true;
822
756
                                errorsFound = true;
823
757
                        }
824
758
//            ret = checkExtensionRule(ni, layer, poly, cell);
827
761
//                              if (errorTypeSearch == DRC.DRCCheckMode.ERROR_CHECK_CELL) return true;
828
762
//                              errorsFound = true;
829
763
//                      }
830
 
                        if (tech == layersValidTech && !layersValid[layer.getIndex()])
 
764
            if (validLayers.isABadLayer(tech, layer.getIndex()))
831
765
                        {
832
 
                                reportError(DRC.DRCErrorType.BADLAYERERROR, null, cell, 0, 0, null,
 
766
                                DRC.createDRCErrorLogger(reportInfo, DRC.DRCErrorType.BADLAYERERROR, null, cell, 0, 0, null,
833
767
                                        poly, ni, layer, null, null, null);
834
 
                                if (errorTypeSearch == DRC.DRCCheckMode.ERROR_CHECK_CELL) return true;
 
768
                                if (reportInfo.errorTypeSearch == DRC.DRCCheckMode.ERROR_CHECK_CELL) return true;
835
769
                                errorsFound = true;
836
770
                        }
837
771
                }
838
772
 
839
773
                // check node for minimum size
840
 
                PrimitiveNode.NodeSizeRule sizeRule = DRC.getMinSize(np);
841
 
                if (sizeRule != null)
842
 
                {
843
 
                        if (DBMath.isGreaterThan(sizeRule.getWidth(), ni.getXSize()) ||
844
 
                DBMath.isGreaterThan(sizeRule.getHeight(), ni.getYSize()))
845
 
                        {
846
 
//                              SizeOffset so = ni.getSizeOffset();
847
 
                                double minSize = 0, actual = 0;
848
 
                String msg = "X axis";
849
 
                                if (sizeRule.getWidth() - ni.getXSize() > sizeRule.getHeight() - ni.getYSize())
850
 
                                {
851
 
                    actual = ni.getLambdaBaseXSize();
852
 
                    minSize = actual + sizeRule.getWidth() - ni.getXSize();
853
 
//                                      minSize = sizeRule.getWidth() - so.getLowXOffset() - so.getHighXOffset();
854
 
//                                      actual = ni.getXSize() - so.getLowXOffset() - so.getHighXOffset();
855
 
                                } else
856
 
                                {
857
 
                    msg = "Y axis";
858
 
                    actual = ni.getLambdaBaseYSize();
859
 
                                        minSize = actual + sizeRule.getHeight() - ni.getYSize();
860
 
//                                      minSize = sizeRule.getHeight() - so.getLowYOffset() - so.getHighYOffset();
861
 
//                                      actual = ni.getYSize() - so.getLowYOffset() - so.getHighYOffset();
862
 
                                }
863
 
                                reportError(DRC.DRCErrorType.MINSIZEERROR, msg, cell, minSize, actual, sizeRule.getRuleName(),
864
 
                                        null, ni, null, null, null, null);
865
 
                errorsFound = true;
866
 
                        }
867
 
                }
 
774
        if (DRC.checkNodeSize(ni, cell, reportInfo))
 
775
            errorsFound = true;
 
776
 
868
777
                return errorsFound;
869
778
        }
870
779
 
871
780
    /**
872
 
     * Method to check which combination of OD2 layers are allowed
873
 
     * @param layer
874
 
     * @return true if there is an invalid combination of OD2 layers
875
 
     */
876
 
    private boolean checkOD2Combination(Technology tech, NodeInst ni, Layer layer)
877
 
    {
878
 
        int funExtras = layer.getFunctionExtras();
879
 
        boolean notOk = false;
880
 
 
881
 
        if (layer.getFunction().isImplant() && (funExtras&Layer.Function.THICK) != 0)
882
 
        {
883
 
            // Only stores first node found
884
 
            od2Layers.put(layer, ni);
885
 
 
886
 
            // More than one type used.
887
 
            if (od2Layers.size() != 1)
888
 
            {
889
 
                for (Map.Entry<Layer,NodeInst> e : od2Layers.entrySet())
890
 
                {
891
 
                    Layer lay1 = e.getKey();
892
 
                    if (lay1 == layer) continue;
893
 
                    if (DRC.isForbiddenNode(lay1.getIndex(), layer.getIndex(), DRCTemplate.DRCRuleType.FORBIDDEN, tech))
894
 
                    {
895
 
                        NodeInst node = e.getValue(); // od2Layers.get(lay1);
896
 
                        String message = "- combination of layers '" + layer.getName() + "' and '" + lay1.getName() + "' (in '" +
897
 
                                node.getParent().getName() + ":" + node.getName() +"') not allowed by selected foundry";
898
 
                        reportError(DRC.DRCErrorType.FORBIDDEN, message, ni.getParent(), -1, -1, null, null, ni, null, null, node, null);
899
 
 
900
 
                        return true;
901
 
                    }
902
 
                }
903
 
            }
904
 
        }
905
 
        return notOk;
906
 
    }
907
 
 
908
 
        /**
909
781
         * Method to check the design rules about arcinst "ai".
910
782
         * Returns true if errors were found.
911
783
         */
927
799
//        if (coverByExclusion(ai))
928
800
//            return false; // no error
929
801
 
930
 
                // get all of the polygons on this arc
 
802
                boolean errorsFound = false;
 
803
        // Checking if the arc is horizontal or vertical
 
804
        Point2D from = ai.getHeadLocation();
 
805
        Point2D to = ai.getTailLocation();
 
806
 
 
807
        if (!DBMath.areEquals(from.getX(), to.getX()) && !DBMath.areEquals(from.getY(), to.getY()))
 
808
        {
 
809
            DRC.createDRCErrorLogger(reportInfo, DRC.DRCErrorType.CROOKEDERROR, null, ai.getParent(),
 
810
                -1, -1, null, null, ai, null, null, null, null);
 
811
            if (reportInfo.errorTypeSearch == DRC.DRCCheckMode.ERROR_CHECK_CELL) return true;
 
812
                                errorsFound = true;
 
813
        }
 
814
        
 
815
        // get all of the polygons on this arc
931
816
                Technology tech = ai.getProto().getTechnology();
932
817
                Poly [] arcInstPolyList = tech.getShapeOfArc(ai);
933
 
                boolean errorsFound = false;
934
818
 
935
819
        // Check resolution before cropping the
936
820
        for(Poly poly : arcInstPolyList)
942
826
            boolean ret = checkResolution(poly, ai.getParent(), ai);
943
827
            if (ret)
944
828
                        {
945
 
                                if (errorTypeSearch == DRC.DRCCheckMode.ERROR_CHECK_CELL) return true;
 
829
                                if (reportInfo.errorTypeSearch == DRC.DRCCheckMode.ERROR_CHECK_CELL) return true;
946
830
                                errorsFound = true;
947
831
                        }
948
832
        }
949
833
 
950
 
                cropActiveArc(ai, arcInstPolyList);
 
834
                DRC.cropActiveArc(ai, reportInfo.ignoreCenterCuts, arcInstPolyList);
951
835
                int tot = arcInstPolyList.length;
952
836
                // examine the polygons on this arc
953
837
                for(int j=0; j<tot; j++)
959
843
 
960
844
                        int layerNum = layer.getIndex();
961
845
                        int netNumber = netNumbers[globalIndex]; // autoboxing
962
 
                        boolean ret = badBox(poly, layer, netNumber, tech, ai, DBMath.MATID, ai.getParent(), globalIndex);
 
846
                        boolean ret = badBox(poly, layer, netNumber, tech, ai, DBMath.MATID, ai.getParent(), globalIndex, null);
963
847
                        if (ret)
964
848
                        {
965
 
                                if (errorTypeSearch == DRC.DRCCheckMode.ERROR_CHECK_CELL) return true;
 
849
                                if (reportInfo.errorTypeSearch == DRC.DRCCheckMode.ERROR_CHECK_CELL) return true;
966
850
                                errorsFound = true;
967
851
                        }
968
852
                        ret = checkMinWidth(ai, layer, poly, tot==1);
969
853
                        if (ret)
970
854
                        {
971
 
                                if (errorTypeSearch == DRC.DRCCheckMode.ERROR_CHECK_CELL) return true;
 
855
                                if (reportInfo.errorTypeSearch == DRC.DRCCheckMode.ERROR_CHECK_CELL) return true;
972
856
                                errorsFound = true;
973
857
                        }
974
858
                        // Check select over transistor poly
976
860
            ret = checkExtensionRules(ai, layer, poly, ai.getParent());
977
861
            if (ret)
978
862
                        {
979
 
                                if (errorTypeSearch == DRC.DRCCheckMode.ERROR_CHECK_CELL) return true;
 
863
                                if (reportInfo.errorTypeSearch == DRC.DRCCheckMode.ERROR_CHECK_CELL) return true;
980
864
                                errorsFound = true;
981
865
                        }
982
 
                        if (tech == layersValidTech && !layersValid[layerNum])
 
866
            if (validLayers.isABadLayer(tech, layerNum))
983
867
                        {
984
 
                                reportError(DRC.DRCErrorType.BADLAYERERROR, null, ai.getParent(), 0, 0, null,
 
868
                                DRC.createDRCErrorLogger(reportInfo, DRC.DRCErrorType.BADLAYERERROR, null, ai.getParent(), 0, 0, null,
985
869
                                        (tot==1)?null:poly, ai, layer, null, null, null);
986
 
                                if (errorTypeSearch == DRC.DRCCheckMode.ERROR_CHECK_CELL) return true;
 
870
                                if (reportInfo.errorTypeSearch == DRC.DRCCheckMode.ERROR_CHECK_CELL) return true;
987
871
                                errorsFound = true;
988
872
                        }
989
873
                }
1011
895
 
1012
896
        // look for other instances surrounding this one
1013
897
                Rectangle2D nodeBounds = ni.getBounds();
1014
 
                Rectangle2D searchBounds = new Rectangle2D.Double(
 
898
        double worstInteractionDistance = reportInfo.worstInteractionDistance;
 
899
        Rectangle2D searchBounds = new Rectangle2D.Double(
1015
900
                        nodeBounds.getMinX()-worstInteractionDistance,
1016
901
                        nodeBounds.getMinY()-worstInteractionDistance,
1017
902
                        nodeBounds.getWidth() + worstInteractionDistance*2,
1106
991
                            (triggerNi==null)?ni:triggerNi);
1107
992
                                        if (ret)
1108
993
                                        {
1109
 
                                                if (errorTypeSearch == DRC.DRCCheckMode.ERROR_CHECK_CELL) return true;
 
994
                                                if (reportInfo.errorTypeSearch == DRC.DRCCheckMode.ERROR_CHECK_CELL) return true;
1110
995
                                                logsFound = true;
1111
996
                                        }
1112
997
                                } else
1114
999
                                        AffineTransform rTrans = ni.rotateOut();
1115
1000
                                        rTrans.preConcatenate(upTrans);
1116
1001
                                        Technology tech = np.getTechnology();
1117
 
                                        Poly [] primPolyList = tech.getShapeOfNode(ni, true, ignoreCenterCuts, null);
 
1002
                                        Poly [] primPolyList = tech.getShapeOfNode(ni, true, reportInfo.ignoreCenterCuts, null);
1118
1003
                                        convertPseudoLayers(ni, primPolyList);
1119
1004
                                        int tot = primPolyList.length;
1120
 
                                        for(int j=0; j<tot; j++)
 
1005
                    Technology.MultiCutData multiCutData = tech.getMultiCutData(ni);
 
1006
 
 
1007
                    for(int j=0; j<tot; j++)
1121
1008
                                        {
1122
1009
                                                Poly poly = primPolyList[j];
1123
1010
                                                Layer layer = poly.getLayer();
1132
1019
                                                // determine network for this polygon
1133
1020
                                                int net = getDRCNetNumber(netlist, poly.getPort(), ni, globalIndex);
1134
1021
                                                boolean ret = badSubBox(poly, layer, net, tech, ni, rTrans,
1135
 
                                                        globalIndex, oNi, topGlobalIndex);
 
1022
                                                        globalIndex, oNi, topGlobalIndex, multiCutData);
1136
1023
                                                if (ret)
1137
1024
                                                {
1138
 
                                                        if (errorTypeSearch == DRC.DRCCheckMode.ERROR_CHECK_CELL) return true;
 
1025
                                                        if (reportInfo.errorTypeSearch == DRC.DRCCheckMode.ERROR_CHECK_CELL) return true;
1139
1026
                                                        logsFound = true;
1140
1027
                                                }
1141
1028
                                        }
1147
1034
 
1148
1035
                                if (tech != cellTech)
1149
1036
                                {
1150
 
                                        reportError(DRC.DRCErrorType.TECHMIXWARN, " belongs to " + tech.getTechName(), cell, 0, 0, null, null, ai, null, null, null, null);
 
1037
                                        DRC.createDRCErrorLogger(reportInfo, DRC.DRCErrorType.TECHMIXWARN, " belongs to " + tech.getTechName(),
 
1038
                        cell, 0, 0, null, null, ai, null, null, null, null);
1151
1039
                                        continue;
1152
1040
                                }
1153
1041
 
1155
1043
                                int tot = arcPolyList.length;
1156
1044
                                for(int j=0; j<tot; j++)
1157
1045
                                        arcPolyList[j].transform(upTrans);
1158
 
                                cropActiveArc(ai, arcPolyList);
 
1046
                                DRC.cropActiveArc(ai, reportInfo.ignoreCenterCuts, arcPolyList);
1159
1047
                                for(int j=0; j<tot; j++)
1160
1048
                                {
1161
1049
                                        Poly poly = arcPolyList[j];
1170
1058
                                                net = netList[globalIndex].intValue();
1171
1059
                                        }
1172
1060
                                        boolean ret = badSubBox(poly, layer, net, tech, ai, upTrans,
1173
 
                                                globalIndex, oNi, topGlobalIndex);
 
1061
                                                globalIndex, oNi, topGlobalIndex, null);
1174
1062
                                        if (ret)
1175
1063
                                        {
1176
 
                                                if (errorTypeSearch == DRC.DRCCheckMode.ERROR_CHECK_CELL) return true;
 
1064
                                                if (reportInfo.errorTypeSearch == DRC.DRCCheckMode.ERROR_CHECK_CELL) return true;
1177
1065
                                                logsFound = true;
1178
1066
                                        }
1179
1067
                                }
1188
1076
         * The polygon is compared against things inside node "oNi", and that node's parent has global index "topGlobalIndex".
1189
1077
         */
1190
1078
        private boolean badSubBox(Poly poly, Layer layer, int net, Technology tech, Geometric geom, AffineTransform trans,
1191
 
                              int globalIndex, NodeInst oNi, int topGlobalIndex)
 
1079
                              int globalIndex, NodeInst oNi, int topGlobalIndex, Technology.MultiCutData multiCutData)
1192
1080
        {
1193
1081
                // see how far around the box it is necessary to search
1194
1082
                double maxSize = poly.getMaxSize();
1209
1097
                int localIndex = topGlobalIndex * ci.multiplier + ci.localIndex + ci.offset;
1210
1098
 
1211
1099
                // determine if original object has multiple contact cuts
1212
 
        Technology.MultiCutData multiCutData = null;
1213
 
                if (geom instanceof NodeInst)
1214
 
        {
1215
 
            multiCutData = tech.getMultiCutData((NodeInst)geom);
1216
 
        }
 
1100
//        Technology.MultiCutData multiCutData = null;
 
1101
//              if (geom instanceof NodeInst)
 
1102
//        {
 
1103
//            multiCutData = tech.getMultiCutData((NodeInst)geom);
 
1104
//        }
1217
1105
//        boolean baseMulti = tech.isMultiCutInTechnology(multiCutData);
1218
1106
 
1219
1107
                // search in the area surrounding the box
1233
1121
         * this hierarchical level.
1234
1122
         */
1235
1123
        private boolean badBox(Poly poly, Layer layer, int net, Technology tech, Geometric geom,
1236
 
                           AffineTransform trans, Cell cell, int globalIndex)
 
1124
                           AffineTransform trans, Cell cell, int globalIndex, Technology.MultiCutData multiCutData)
1237
1125
        {
1238
1126
                // see how far around the box it is necessary to search
1239
1127
                double maxSize = poly.getMaxSize();
1245
1133
                bounds.setRect(poly.getBounds2D());
1246
1134
 
1247
1135
                // determine if original object has multiple contact cuts
1248
 
        Technology.MultiCutData multiCutData = null;
1249
 
                if (geom instanceof NodeInst)
1250
 
        {
1251
 
            multiCutData = tech.getMultiCutData((NodeInst)geom);
1252
 
        }
 
1136
//        Technology.MultiCutData multiCutData = null;
 
1137
//              if (geom instanceof NodeInst)
 
1138
//        {
 
1139
//            multiCutData = tech.getMultiCutData((NodeInst)geom);
 
1140
//        }
1253
1141
//        boolean baseMulti = tech.isMultiCutInTechnology(multiCutData);
1254
1142
 
1255
1143
        // search in the area surrounding the box
1329
1217
                                                             topCell, topGlobalIndex, subTrans, multiCutData, sameInstance))
1330
1218
                    {
1331
1219
                        foundError = true;
1332
 
                        if (errorTypeSearch != DRC.DRCCheckMode.ERROR_CHECK_EXHAUSTIVE) return true;
 
1220
                        if (reportInfo.errorTypeSearch != DRC.DRCCheckMode.ERROR_CHECK_EXHAUSTIVE) return true;
1333
1221
                    }
1334
1222
                                } else
1335
1223
                                {
1337
1225
                                        if (np.getTechnology() != tech) continue;
1338
1226
 
1339
1227
                                        // see if this type of node can interact with this layer
1340
 
                                        if (!checkLayerWithNode(layer, np)) continue;
 
1228
                                        if (!validLayers.checkLayerWithNode(layer, np)) continue;
1341
1229
 
1342
1230
                    // see if the objects directly touch but they are not
1343
1231
                    // coming from different NodeInst (not from checkCellInstContents
1349
1237
                                        rTrans.preConcatenate(upTrans);
1350
1238
 
1351
1239
                                        // get the shape of each nodeinst layer
1352
 
                                        Poly [] subPolyList = tech.getShapeOfNode(ni, true, ignoreCenterCuts, null);
 
1240
                                        Poly [] subPolyList = tech.getShapeOfNode(ni, true, reportInfo.ignoreCenterCuts, null);
1353
1241
                                        convertPseudoLayers(ni, subPolyList);
1354
1242
                                        int tot = subPolyList.length;
1355
1243
                                        for(int i=0; i<tot; i++)
1415
1303
                        if (ret)
1416
1304
                        {
1417
1305
                            foundError = true;
1418
 
                            if (errorTypeSearch != DRC.DRCCheckMode.ERROR_CHECK_EXHAUSTIVE) return true;
 
1306
                            if (reportInfo.errorTypeSearch != DRC.DRCCheckMode.ERROR_CHECK_EXHAUSTIVE) return true;
1419
1307
                        }
1420
1308
 
1421
1309
                        // check if both polys are cut and if the combine area doesn't excess cut sizes
1424
1312
                        if (ret)
1425
1313
                        {
1426
1314
                            foundError = true;
1427
 
                            if (errorTypeSearch != DRC.DRCCheckMode.ERROR_CHECK_EXHAUSTIVE) return true;
 
1315
                            if (reportInfo.errorTypeSearch != DRC.DRCCheckMode.ERROR_CHECK_EXHAUSTIVE) return true;
1428
1316
                        }
1429
1317
 
1430
1318
                                                // if they connect electrically and adjoin, don't check
1431
1319
                                                if (con && touch)
1432
1320
                        {
1433
1321
                            // Check if there are minimum size defects
1434
 
                            boolean maytouch = mayTouch(tech, con, layer, nLayer);
 
1322
                            boolean maytouch = DRC.mayTouch(tech, con, layer, nLayer);
1435
1323
                            Rectangle2D trueBox1 = poly.getBox();
1436
1324
                            if (trueBox1 == null) trueBox1 = poly.getBounds2D();
1437
1325
                            Rectangle2D trueBox2 = npoly.getBox();
1441
1329
                            if (ret)
1442
1330
                            {
1443
1331
                                foundError = true;
1444
 
                                if (errorTypeSearch != DRC.DRCCheckMode.ERROR_CHECK_EXHAUSTIVE) return true;
 
1332
                                if (reportInfo.errorTypeSearch != DRC.DRCCheckMode.ERROR_CHECK_EXHAUSTIVE) return true;
1445
1333
                            }
1446
1334
                            continue;
1447
1335
                        }
1466
1354
                        if (ret)
1467
1355
                        {
1468
1356
                            foundError = true;
1469
 
                            if (errorTypeSearch != DRC.DRCCheckMode.ERROR_CHECK_EXHAUSTIVE) return true;
 
1357
                            if (reportInfo.errorTypeSearch != DRC.DRCCheckMode.ERROR_CHECK_EXHAUSTIVE) return true;
1470
1358
                        }
1471
1359
                    }
1472
1360
                                }
1479
1367
                                if (ap.getTechnology() != tech) continue;
1480
1368
 
1481
1369
                                // see if this type of arc can interact with this layer
1482
 
                                if (!checkLayerWithArc(layer, ap)) continue;
 
1370
                                if (!validLayers.checkLayerWithArc(layer, ap)) continue;
1483
1371
 
1484
1372
                // see if the objects directly touch
1485
1373
                                boolean touch = sameInstance && nGeom.isConnected(geom);
1499
1387
                                int tot = subPolyList.length;
1500
1388
                                for(int i=0; i<tot; i++)
1501
1389
                                        subPolyList[i].transform(upTrans);
1502
 
                                cropActiveArc(ai, subPolyList);
 
1390
                                DRC.cropActiveArc(ai, reportInfo.ignoreCenterCuts, subPolyList);
1503
1391
                                boolean multi = baseMulti; // this condition is not very relevant for arcs because no cut/via is used in arcs
1504
1392
                int multiInt = (multi) ? 1 : 0;
1505
1393
 
1526
1414
                                    if (con && touch)
1527
1415
                    {
1528
1416
                        // Check if there are minimum size defects
1529
 
                        boolean maytouch = mayTouch(tech, con, layer, nLayer);
 
1417
                        boolean maytouch = DRC.mayTouch(tech, con, layer, nLayer);
1530
1418
                        Rectangle2D trueBox1 = poly.getBox();
1531
1419
                        if (trueBox1 == null) trueBox1 = poly.getBounds2D();
1532
1420
                        Rectangle2D trueBox2 = nPoly.getBox();
1536
1424
                        if (ret)
1537
1425
                        {
1538
1426
                            foundError = true;
1539
 
                            if (errorTypeSearch != DRC.DRCCheckMode.ERROR_CHECK_EXHAUSTIVE) return true;
 
1427
                            if (reportInfo.errorTypeSearch != DRC.DRCCheckMode.ERROR_CHECK_EXHAUSTIVE) return true;
1540
1428
                        }
1541
1429
                        continue;
1542
1430
                    }
1558
1446
                                        if (ret)
1559
1447
                    {
1560
1448
                        foundError = true;
1561
 
                        if (errorTypeSearch != DRC.DRCCheckMode.ERROR_CHECK_EXHAUSTIVE) return true;
 
1449
                        if (reportInfo.errorTypeSearch != DRC.DRCCheckMode.ERROR_CHECK_EXHAUSTIVE) return true;
1562
1450
                    }
1563
1451
 
1564
1452
                    // Checking extension, it could be slow
1566
1454
                    if (ret)
1567
1455
                    {
1568
1456
                        foundError = true;
1569
 
                        if (errorTypeSearch != DRC.DRCCheckMode.ERROR_CHECK_EXHAUSTIVE) return true;
 
1457
                        if (reportInfo.errorTypeSearch != DRC.DRCCheckMode.ERROR_CHECK_EXHAUSTIVE) return true;
1570
1458
                    }
1571
1459
                                }
1572
1460
                        }
1585
1473
        if (trueBox1 == null || trueBox2 == null) return false;
1586
1474
        if (!maytouch) return false;
1587
1475
        // manhattan
1588
 
        double pdx = Math.max(trueBox2.getMinX()-trueBox1.getMaxX(), trueBox1.getMinX()-trueBox2.getMaxX());
1589
 
        double pdy = Math.max(trueBox2.getMinY()-trueBox1.getMaxY(), trueBox1.getMinY()-trueBox2.getMaxY());
 
1476
        double pdx = DBMath.round(Math.max(trueBox2.getMinX()-trueBox1.getMaxX(), trueBox1.getMinX()-trueBox2.getMaxX()));
 
1477
        double pdy = DBMath.round(Math.max(trueBox2.getMinY()-trueBox1.getMaxY(), trueBox1.getMinY()-trueBox2.getMaxY()));
1590
1478
        double pd = Math.max(pdx, pdy);
1591
 
        if (pdx == 0 && pdy == 0) pd = 0; // touching
 
1479
 
 
1480
        if (DBMath.areEquals(pdx, 0) && DBMath.areEquals(pdy, 0))
 
1481
            pd = 0; // touching
1592
1482
        boolean foundError = false;
1593
1483
 
1594
1484
        // They have to overlap
1595
 
                if (pd > 0) return false;
 
1485
        if (DBMath.isGreaterThan(pd, 0)) return false;
1596
1486
 
1597
1487
        // they are electrically connected and they overlap: look for minimum size errors
1598
1488
        // of the overlapping region.
1600
1490
        if (wRule == null) return false; // no rule
1601
1491
 
1602
1492
        double minWidth = wRule.getValue(0);
1603
 
        double lxb = Math.max(trueBox1.getMinX(), trueBox2.getMinX());
1604
 
        double hxb = Math.min(trueBox1.getMaxX(), trueBox2.getMaxX());
1605
 
        double lyb = Math.max(trueBox1.getMinY(), trueBox2.getMinY());
1606
 
        double hyb = Math.min(trueBox1.getMaxY(), trueBox2.getMaxY());
 
1493
        double lxb = DBMath.round(Math.max(trueBox1.getMinX(), trueBox2.getMinX()));
 
1494
        double hxb = DBMath.round(Math.min(trueBox1.getMaxX(), trueBox2.getMaxX()));
 
1495
        double lyb = DBMath.round(Math.max(trueBox1.getMinY(), trueBox2.getMinY()));
 
1496
        double hyb = DBMath.round(Math.min(trueBox1.getMaxY(), trueBox2.getMaxY()));
1607
1497
        Point2D lowB = new Point2D.Double(lxb, lyb);
1608
1498
        Point2D highB = new Point2D.Double(hxb, hyb);
1609
1499
        Rectangle2D bounds = new Rectangle2D.Double(lxb, lyb, hxb-lxb, hyb-lyb);
1628
1518
 
1629
1519
        // Checking A-B distance
1630
1520
        double actual = lowB.distance(highB);
1631
 
        if (actual != 0 && DBMath.isGreaterThan(minWidth, actual) &&
 
1521
 
 
1522
        // !DBMath.areEquals(actual, 0) is on, it skips cases where A==B.
 
1523
        // Condition off as of July 2nd 2008. Bugzilla 1745
 
1524
        if (/*!DBMath.areEquals(actual, 0) &&*/ DBMath.isGreaterThan(minWidth, actual) &&
1632
1525
            foundSmallSizeDefect(cell, geom1, poly1, layer1, geom2, poly2, pd, lxb, lyb, hxb, hyb))
1633
1526
        {
1634
1527
            // you can't pass geom1 or geom2 becuase they could be in different cells and therefore the message
1635
1528
            // could mislead
1636
 
            reportError(DRC.DRCErrorType.MINWIDTHERROR, null, topCell, minWidth, actual, wRule.ruleName, new Poly(bounds),
 
1529
            DRC.createDRCErrorLogger(reportInfo, DRC.DRCErrorType.MINWIDTHERROR, null, topCell, minWidth, actual, wRule.ruleName, new Poly(bounds),
1637
1530
                            null, layer1, null, null, layer2);
1638
1531
            foundError = true;
1639
1532
        }
1651
1544
        Point2D highB = new Point2D.Double(hxb, hyb);
1652
1545
        Rectangle2D bounds = new Rectangle2D.Double(lxb, lyb, hxb-lxb, hyb-lyb);
1653
1546
        Poly rebuild = new Poly(bounds);
1654
 
        Point2D pt1 = new Point2D.Double(lxb-TINYDELTA, lyb-TINYDELTA);
1655
 
        Point2D pt2 = new Point2D.Double(lxb-TINYDELTA, hyb+TINYDELTA);
1656
 
        Point2D pt1d = (Point2D)pt1.clone();
1657
 
        Point2D pt2d = (Point2D)pt2.clone();
 
1547
        Point2D pt1 = null; //new Point2D.Double(lxb-TINYDELTA, lyb-TINYDELTA);
 
1548
        Point2D pt2 = null; //new Point2D.Double(lxb-TINYDELTA, hyb+TINYDELTA);
 
1549
        Point2D pt1d = null;//(Point2D)pt1.clone();
 
1550
        Point2D pt2d = null; //(Point2D)pt2.clone();
1658
1551
 
1659
1552
        // Search area should be bigger than bounding box otherwise it might not get the cells due to
1660
1553
        // rounding errors.
1661
 
        Rectangle2D search = new Rectangle2D.Double(DBMath.round(lxb-TINYDELTA), DBMath.round(lyb-TINYDELTA),
1662
 
                DBMath.round(hxb-lxb+2*TINYDELTA), DBMath.round(hyb-lyb+2*TINYDELTA));
 
1554
        Rectangle2D search = new Rectangle2D.Double(DBMath.round(lxb- DRC.TINYDELTA), DBMath.round(lyb- DRC.TINYDELTA),
 
1555
                DBMath.round(hxb-lxb+2* DRC.TINYDELTA), DBMath.round(hyb-lyb+2* DRC.TINYDELTA));
1663
1556
 
1664
1557
        // Looking for two corners not inside bounding boxes A and B
1665
1558
        if (pd == 0) // flat bounding box
1692
1585
            if (pt1.getX() < pt2.getX())
1693
1586
            {
1694
1587
                // (y2-y1)/(x2-x1)(x1-tinydelta-x1) + y1
1695
 
                pt1d = new Point2D.Double(pt1.getX()-TINYDELTA, -delta*TINYDELTA+pt1.getY());
 
1588
                pt1d = new Point2D.Double(pt1.getX()- DRC.TINYDELTA, -delta* DRC.TINYDELTA+pt1.getY());
1696
1589
                // (y2-y1)/(x2-x1)(x2+tinydelta-x2) + y2
1697
 
                pt2d = new Point2D.Double(pt2.getX()+TINYDELTA, delta*TINYDELTA+pt2.getY());
 
1590
                pt2d = new Point2D.Double(pt2.getX()+ DRC.TINYDELTA, delta* DRC.TINYDELTA+pt2.getY());
1698
1591
            }
1699
1592
            else
1700
1593
            {
1701
 
                pt1d = new Point2D.Double(pt2.getX()-TINYDELTA, -delta*TINYDELTA+pt2.getY());
1702
 
                pt2d = new Point2D.Double(pt1.getX()+TINYDELTA, delta*TINYDELTA+pt1.getY());
 
1594
                pt1d = new Point2D.Double(pt2.getX()- DRC.TINYDELTA, -delta* DRC.TINYDELTA+pt2.getY());
 
1595
                pt2d = new Point2D.Double(pt1.getX()+ DRC.TINYDELTA, delta* DRC.TINYDELTA+pt1.getY());
1703
1596
            }
1704
1597
            if (DBMath.areEquals(pt1.getX(), pt2.getX()) || DBMath.areEquals(pt1.getY(), pt2.getY()))
1705
1598
            {    
1708
1601
        }
1709
1602
        // looking if points around the overlapping area are inside another region
1710
1603
        // to avoid the error
1711
 
        lookForLayerNew(geom1, poly1, geom2, poly2, cell, layer1, DBMath.MATID, search,
1712
 
                pt1d, pt2d, null, pointsFound, false);
 
1604
        DRC.lookForLayerCoverage(geom1, poly1, geom2, poly2, cell, layer1, DBMath.MATID, search,
 
1605
                pt1d, pt2d, null, pointsFound, false, null, false, reportInfo.ignoreCenterCuts);
1713
1606
        // Nothing found
1714
1607
        if (!pointsFound[0] && !pointsFound[1])
1715
1608
        {
1719
1612
    }
1720
1613
 
1721
1614
    /**
1722
 
     * Method to determine if it is allowed to have both layers touching.
1723
 
     * special rule for allowing touching:
1724
 
     *   the layers are the same and either:
1725
 
     *     they connect and are *NOT* contact layers
1726
 
         *   or:
1727
 
         *     they don't connect and are implant layers (substrate/well)
1728
 
     * @param tech
1729
 
     * @param con
1730
 
     * @param layer1
1731
 
     * @param layer2
1732
 
     * @return true if the layer may touch
1733
 
     */
1734
 
    private boolean mayTouch(Technology tech, boolean con, Layer layer1, Layer layer2)
1735
 
    {
1736
 
        boolean maytouch = false;
1737
 
                if (tech.sameLayer(layer1, layer2))
1738
 
                {
1739
 
                        Layer.Function fun = layer1.getFunction();
1740
 
                        if (con)
1741
 
                        {
1742
 
                                if (!fun.isContact()) maytouch = true;
1743
 
                        } else
1744
 
                        {
1745
 
                                if (fun.isSubstrate()) maytouch = true;
1746
 
                                // Special cases for thick actives
1747
 
                                else
1748
 
                                {
1749
 
                                        // Searching for THICK bit
1750
 
                                        int funExtras = layer1.getFunctionExtras();
1751
 
                                        if (fun.isDiff() && (funExtras&Layer.Function.THICK) != 0)
1752
 
                                        {
1753
 
                                                if (Job.LOCALDEBUGFLAG) System.out.println("Thick active found in Quick.checkDist");
1754
 
                                                maytouch = true;
1755
 
                                        }
1756
 
                                }
1757
 
                        }
1758
 
                }
1759
 
        return maytouch;
1760
 
    }
1761
 
 
1762
 
        /**
1763
1615
         * Method to compare:
1764
1616
         *    polygon "poly1" layer "layer1" network "net1" object "geom1"
1765
1617
         * with:
1791
1643
                Rectangle2D trueBox2 = isBox2;
1792
1644
                if (trueBox2 == null) trueBox2 = poly2.getBounds2D();
1793
1645
        boolean errorFound = false;  // remember if there was a min defect error
1794
 
                boolean maytouch = mayTouch(tech, con, layer1, layer2);
 
1646
                boolean maytouch = DRC.mayTouch(tech, con, layer1, layer2);
1795
1647
 
1796
1648
                // special code if both polygons are manhattan
1797
1649
                double pd = 0;
1799
1651
                if (isBox1 != null && isBox2 != null)
1800
1652
                {
1801
1653
                        // manhattan
1802
 
                        double pdx = Math.max(trueBox2.getMinX()-trueBox1.getMaxX(), trueBox1.getMinX()-trueBox2.getMaxX());
1803
 
                        double pdy = Math.max(trueBox2.getMinY()-trueBox1.getMaxY(), trueBox1.getMinY()-trueBox2.getMaxY());
1804
 
                        pd = DBMath.round(Math.max(pdx, pdy));
1805
 
                        if (DBMath.areEquals(pdx, 0) && DBMath.areEquals(pdy,0)) pd = 0; // touching
1806
 
                        overlap = (pd < 0);
1807
 
                        if (maytouch)
 
1654
                        double pdx = DBMath.round(Math.max(trueBox2.getMinX()-trueBox1.getMaxX(), trueBox1.getMinX()-trueBox2.getMaxX()));
 
1655
                        double pdy = DBMath.round(Math.max(trueBox2.getMinY()-trueBox1.getMaxY(), trueBox1.getMinY()-trueBox2.getMaxY()));
 
1656
                        pd = Math.max(pdx, pdy);
 
1657
                        if (DBMath.areEquals(pdx, 0) && DBMath.areEquals(pdy,0))
 
1658
                pd = 0; // touching
 
1659
                        overlap = DBMath.isLessThan(pd, 0);
 
1660
            if (maytouch)
1808
1661
                        {
1809
1662
                                // they are electrically connected: see if they touch
1810
1663
                if (checkMinDefects(cell, maytouch, geom1, poly1, trueBox1, layer2, geom2, poly2, trueBox2, layer2, cell))
1811
1664
                {
1812
 
                    if (errorTypeSearch != DRC.DRCCheckMode.ERROR_CHECK_EXHAUSTIVE) return true;
 
1665
                    if (reportInfo.errorTypeSearch != DRC.DRCCheckMode.ERROR_CHECK_EXHAUSTIVE) return true;
1813
1666
                    errorFound = true;
1814
1667
                }
1815
1668
                        }
1863
1716
                        if (edge)
1864
1717
                        {
1865
1718
                                // calculate the spacing between the box edges
1866
 
                                double pdedge = Math.min(
 
1719
                                double pdedge = DBMath.round(Math.min(
1867
1720
                                        Math.min(Math.min(Math.abs(lX1-lX2), Math.abs(lX1-hX2)), Math.min(Math.abs(hX1-lX2), Math.abs(hX1-hX2))),
1868
 
                                        Math.min(Math.min(Math.abs(lY1-lY2), Math.abs(lY1-hY2)), Math.min(Math.abs(hY1-lY2), Math.abs(hY1-hY2))));
 
1721
                                        Math.min(Math.min(Math.abs(lY1-lY2), Math.abs(lY1-hY2)), Math.min(Math.abs(hY1-lY2), Math.abs(hY1-hY2)))));
1869
1722
                                pd = Math.max(pd, pdedge);
1870
1723
                        } else
1871
1724
                        {
1872
 
                                pdx = Math.max(lX2-hX1, lX1-hX2);
1873
 
                                pdy = Math.max(lY2-hY1, lY1-hY2);
 
1725
                                pdx = DBMath.round(Math.max(lX2-hX1, lX1-hX2));
 
1726
                                pdy = DBMath.round(Math.max(lY2-hY1, lY1-hY2));
1874
1727
 
1875
 
                                if (pdx == 0 && pdy == 0)
 
1728
                if (DBMath.areEquals(pdx, 0) && DBMath.areEquals(pdy, 0))
1876
1729
                                        pd = 0; // they are touching!!
1877
1730
                                else
1878
1731
                                {
1879
1732
                                        // They are overlapping if pdx < 0 && pdy < 0
1880
 
                                        pd = DBMath.round(Math.max(pdx, pdy));
 
1733
                                        pd = (Math.max(pdx, pdy));
1881
1734
 
1882
 
                                        if (pd < theRule.getValue(0) && pd > 0)
 
1735
                    if (pd < theRule.getValue(0) && DBMath.isGreaterThan(pd, 0))
1883
1736
                                        {
1884
1737
                                                pd = poly1.separation(poly2);
1885
1738
                                        }
1903
1756
                        // make sure polygons don't intersect
1904
1757
            //@TODO combine this calculation otherwise Poly.intersects is called twice!
1905
1758
            double pd1 = poly1.separation(poly2);
1906
 
                        if (poly1.intersects(poly2)) pd = 0;
 
1759
                        if (poly1.intersects(poly2))
 
1760
                pd = 0;
1907
1761
            else
1908
1762
                        {
1909
1763
                                // find distance between polygons
1910
1764
                                pd = poly1.separation(poly2);
1911
1765
                        }
1912
 
            if (pd1 != pd)
 
1766
//            if (pd1 != pd)
 
1767
            if (!DBMath.areEquals(pd1, pd))
1913
1768
                System.out.println("Wrong case in non-nonmanhattan, Quick.");
1914
1769
                }
1915
1770
 
1916
1771
                DRC.DRCErrorType errorType = DRC.DRCErrorType.SPACINGERROR;
1917
1772
        if (theRule.ruleType == DRCTemplate.DRCRuleType.SURROUND)
1918
1773
        {
1919
 
            if (pd > 0) // layers don't overlap -> no condition to check
 
1774
            if (DBMath.isGreaterThan(pd, 0)) // layers don't overlap -> no condition to check
1920
1775
                return errorFound;
1921
1776
            pd = Math.abs(pd);
1922
1777
            errorType = DRC.DRCErrorType.SURROUNDERROR;
1941
1796
             * part of a VTH-transistors. Not very elegant solution but should work for now.
1942
1797
             */
1943
1798
            if (polyCoverByAnyVTLayer(cell, theRule, tech, new Poly[]{poly1, poly2}, new Layer[]{layer1, layer2},
1944
 
                    new Geometric[]{geom1, geom2}, ignoreCenterCuts))
 
1799
                    new Geometric[]{geom1, geom2}, reportInfo.ignoreCenterCuts))
1945
1800
                return errorFound;
1946
1801
 
1947
1802
            // special cases if the layers are the same
1951
1806
                if (maytouch)
1952
1807
                {
1953
1808
                    // if they touch, it is acceptable
1954
 
                    if (pd <= 0) return errorFound;
 
1809
                    if (DBMath.isLessThanOrEqualTo(pd, 0))
 
1810
                        return errorFound;
1955
1811
 
1956
1812
                    // see if the notch is filled
1957
1813
                    boolean newR = lookForCrossPolygons(geom1, poly1, geom2, poly2, layer1, cell, overlap);
2008
1864
                        }
2009
1865
                }
2010
1866
 
2011
 
                reportError(errorType, msg, cell, theRule.getValue(0), pd, theRule.ruleName, origPoly1, geom1, layer1, origPoly2, geom2, layer2);
 
1867
                DRC.createDRCErrorLogger(reportInfo, errorType, msg, cell, theRule.getValue(0), pd, theRule.ruleName,
 
1868
            origPoly1, geom1, layer1, origPoly2, geom2, layer2);
2012
1869
                return true;
2013
1870
        }
2014
1871
 
2062
1919
 
2063
1920
                // look for other objects surrounding this one
2064
1921
                Rectangle2D nodeBounds = ni.getBounds();
2065
 
                Rectangle2D searchBounds = new Rectangle2D.Double(
 
1922
        double worstInteractionDistance = reportInfo.worstInteractionDistance;
 
1923
        Rectangle2D searchBounds = new Rectangle2D.Double(
2066
1924
                        nodeBounds.getMinX() - worstInteractionDistance,
2067
1925
                        nodeBounds.getMinY() - worstInteractionDistance,
2068
1926
                        nodeBounds.getWidth() + worstInteractionDistance*2,
2127
1985
 
2128
1986
                        tech = oNi.getProto().getTechnology();
2129
1987
                        trans = oNi.rotateOut();
2130
 
                        nodeInstPolyList = tech.getShapeOfNode(oNi, true, ignoreCenterCuts, null);
 
1988
                        nodeInstPolyList = tech.getShapeOfNode(oNi, true, reportInfo.ignoreCenterCuts, null);
2131
1989
                        convertPseudoLayers(oNi, nodeInstPolyList);
2132
1990
            multiCutData = tech.getMultiCutData(oNi);
2133
1991
//            baseMulti = tech.isMultiCutCase(oNi);
2196
2054
        private boolean checkInteraction(NodeInst ni1, NodeInst n1Parent,
2197
2055
                                     NodeInst ni2, NodeInst n2Parent, NodeInst triggerNi)
2198
2056
        {
2199
 
        if (errorTypeSearch == DRC.DRCCheckMode.ERROR_CHECK_EXHAUSTIVE) return false;
 
2057
        if (reportInfo.errorTypeSearch == DRC.DRCCheckMode.ERROR_CHECK_EXHAUSTIVE) return false;
2200
2058
 
2201
2059
                // must recheck parameterized instances always
2202
2060
                CheckProto cp = getCheckProto((Cell)ni1.getProto());
2341
2199
                if (job != null && job.checkAbort()) return;
2342
2200
 
2343
2201
                // number all of the instances in this cell
2344
 
                checkTimeStamp++;
 
2202
                reportInfo.checkTimeStamp++;
2345
2203
                List<CheckProto> subCheckProtos = new ArrayList<CheckProto>();
2346
2204
                for(Iterator<NodeInst> it = cell.getNodes(); it.hasNext(); )
2347
2205
                {
2353
2211
                        if (ni.isIconOfParent()) continue;
2354
2212
 
2355
2213
                        CheckProto cp = getCheckProto((Cell)np);
2356
 
                        if (cp.timeStamp != checkTimeStamp)
 
2214
                        if (cp.timeStamp != reportInfo.checkTimeStamp)
2357
2215
                        {
2358
 
                                cp.timeStamp = checkTimeStamp;
 
2216
                                cp.timeStamp = reportInfo.checkTimeStamp;
2359
2217
                                cp.instanceCount = 0;
2360
2218
                                cp.nodesInCell = new ArrayList<CheckInst>();
2361
2219
                                subCheckProtos.add(cp);
2367
2225
                }
2368
2226
 
2369
2227
                // update the counts for this cell
2370
 
//              for(Iterator it = subCheckProtos.iterator(); it.hasNext(); )
2371
2228
        for (CheckProto cp : subCheckProtos)
2372
2229
                {
2373
 
//                      CheckProto cp = (CheckProto)it.next();
2374
2230
                        cp.hierInstanceCount += cp.instanceCount;
2375
 
//                      for(Iterator nIt = cp.nodesInCell.iterator(); nIt.hasNext(); )
2376
2231
            for (CheckInst ci : cp.nodesInCell)
2377
2232
                        {
2378
 
//                              CheckInst ci = (CheckInst)nIt.next();
2379
2233
                                ci.multiplier = cp.instanceCount;
2380
2234
                        }
2381
2235
                }
2437
2291
                        {
2438
2292
                                Network net = nIt.next();
2439
2293
                                if (subEnumeratedNets.get(net) == null)
2440
 
                                        subEnumeratedNets.put(net, new Integer(checkNetNumber++));
 
2294
                                        subEnumeratedNets.put(net, new Integer(reportInfo.checkNetNumber++));
2441
2295
                        }
2442
2296
                        checkEnumerateNetworks(subCell, subCP, localIndex, subEnumeratedNets);
2443
2297
                }
2446
2300
        /*********************************** QUICK DRC SUPPORT ***********************************/
2447
2301
 
2448
2302
    /**
2449
 
     * Method to determine if neighbor would help to cover the minimum conditions
2450
 
     * @return true if error was found (not warning)
2451
 
     */
2452
 
    private boolean checkExtensionWithNeighbors(Cell cell, Geometric geom, Poly poly, Layer layer, Rectangle2D bounds,
2453
 
                                                DRCTemplate minWidthRule, int dir, boolean onlyOne, boolean reportError)
2454
 
    {
2455
 
        double actual = 0;
2456
 
        Point2D left1, left2, left3, right1, right2, right3;
2457
 
        //if (bounds.getWidth() < minWidthRule.value)
2458
 
        String msg = "";
2459
 
 
2460
 
        // potential problem along X
2461
 
        if (dir == 0)
2462
 
        {
2463
 
            actual = bounds.getWidth();
2464
 
            msg = "(X axis)";
2465
 
            double leftW = bounds.getMinX() - TINYDELTA;
2466
 
            left1 = new Point2D.Double(leftW, bounds.getMinY());
2467
 
            left2 = new Point2D.Double(leftW, bounds.getMaxY());
2468
 
            left3 = new Point2D.Double(leftW, bounds.getCenterY());
2469
 
            double rightW = bounds.getMaxX() + TINYDELTA;
2470
 
            right1 = new Point2D.Double(rightW, bounds.getMinY());
2471
 
            right2 = new Point2D.Double(rightW, bounds.getMaxY());
2472
 
            right3 = new Point2D.Double(rightW, bounds.getCenterY());
2473
 
        } else
2474
 
        {
2475
 
            actual = bounds.getHeight();
2476
 
            msg = "(Y axis)";
2477
 
            double leftH = bounds.getMinY() - TINYDELTA;
2478
 
            left1 = new Point2D.Double(bounds.getMinX(), leftH);
2479
 
            left2 = new Point2D.Double(bounds.getMaxX(), leftH);
2480
 
            left3 = new Point2D.Double(bounds.getCenterX(), leftH);
2481
 
            double rightH = bounds.getMaxY() + TINYDELTA;
2482
 
            right1 = new Point2D.Double(bounds.getMinX(), rightH);
2483
 
            right2 = new Point2D.Double(bounds.getMaxX(), rightH);
2484
 
            right3 = new Point2D.Double(bounds.getCenterX(), rightH);
2485
 
        }
2486
 
        // see if there is more of this layer adjoining on either side
2487
 
        boolean [] pointsFound = new boolean[3];
2488
 
        pointsFound[0] = pointsFound[1] = pointsFound[2] = false;
2489
 
        Rectangle2D newBounds = new Rectangle2D.Double(bounds.getMinX()-TINYDELTA, bounds.getMinY()-TINYDELTA,
2490
 
                bounds.getWidth()+TINYDELTA*2, bounds.getHeight()+TINYDELTA*2);
2491
 
        boolean zeroWide = (bounds.getWidth() == 0 || bounds.getHeight() == 0);
2492
 
 
2493
 
        boolean overlapLayer = lookForLayer(poly, cell, layer, DBMath.MATID, newBounds,
2494
 
                left1, left2, left3, pointsFound); //) return false;
2495
 
//        if (overlapLayer && !zeroWide) return false;
2496
 
        if (overlapLayer) return false;
2497
 
 
2498
 
        // Try the other corner
2499
 
        pointsFound[0] = pointsFound[1] = pointsFound[2] = false;
2500
 
        overlapLayer = lookForLayer(poly, cell, layer, DBMath.MATID, newBounds,
2501
 
                right1, right2, right3, pointsFound); //) return false;
2502
 
//        if (overlapLayer && !zeroWide) return false;
2503
 
        if (overlapLayer) return false;
2504
 
 
2505
 
        DRC.DRCErrorType errorType = DRC.DRCErrorType.MINWIDTHERROR;
2506
 
        String extraMsg = msg;
2507
 
        String rule = minWidthRule.ruleName;
2508
 
        if (zeroWide)
2509
 
        {
2510
 
            if (overlapLayer) extraMsg = " but covered by other layer";
2511
 
            errorType = DRC.DRCErrorType.ZEROLENGTHARCWARN;
2512
 
            rule = null;
2513
 
        }
2514
 
 
2515
 
        if (reportError)
2516
 
            reportError(errorType, extraMsg, cell, minWidthRule.getValue(0), actual, rule,
2517
 
                (onlyOne) ? null : poly, geom, layer, null, null, null);
2518
 
        return !overlapLayer;
2519
 
    }
2520
 
 
2521
 
    /**
2522
2303
     * Function to look for conditional layers that will 100% overlap with the given region.
2523
2304
     * @param poly
2524
2305
     * @param layer
2525
2306
     * @param cell
2526
 
     * @param bounds
2527
 
     * @param upTrans
 
2307
     * @param ignoreCenterCuts
2528
2308
     * @return true if conditional layers are found for the test points
2529
2309
     */
2530
 
    private boolean searchForCondLayer(Geometric geom, Poly poly, Layer layer, Cell cell, Rectangle2D bounds, AffineTransform upTrans)
 
2310
    private boolean searchForCondLayer(Geometric geom, Poly poly, Layer layer, Cell cell,
 
2311
                                       boolean ignoreCenterCuts)
2531
2312
    {
2532
2313
        Rectangle2D polyBnd = poly.getBounds2D();
2533
2314
        double midPointX = (polyBnd.getMinX() + polyBnd.getMaxX())/2;
2536
2317
        Point2D pt2 = new Point2D.Double(midPointX, polyBnd.getMaxY());
2537
2318
        Point2D pt3 = new Point2D.Double(midPointX, midPointY);
2538
2319
        // compute bounds for searching inside the given polygon
2539
 
                Rectangle2D bnd = new Rectangle2D.Double(DBMath.round(polyBnd.getMinX()-TINYDELTA),
2540
 
                DBMath.round(polyBnd.getMinY()-TINYDELTA),
2541
 
                DBMath.round(polyBnd.getWidth()+2*TINYDELTA), DBMath.round(polyBnd.getHeight()+2*TINYDELTA));
 
2320
                Rectangle2D bnd = new Rectangle2D.Double(DBMath.round(polyBnd.getMinX()- DRC.TINYDELTA),
 
2321
                DBMath.round(polyBnd.getMinY()- DRC.TINYDELTA),
 
2322
                DBMath.round(polyBnd.getWidth()+2* DRC.TINYDELTA), DBMath.round(polyBnd.getHeight()+2* DRC.TINYDELTA));
2542
2323
        // looking if points around the overlapping area are inside another region
2543
2324
        // to avoid the error
2544
2325
        boolean [] pointsFound = new boolean[3];
2545
2326
                pointsFound[0] = pointsFound[1] = pointsFound[2] = false;
2546
2327
        // Test first with a vertical line
2547
 
        boolean found = lookForLayerNew(geom, poly, null, null, cell, layer, DBMath.MATID, bnd, pt1, pt2, pt3,
2548
 
                pointsFound, true);
 
2328
        boolean found = DRC.lookForLayerCoverage(geom, poly, null, null, cell, layer, DBMath.MATID, bnd, pt1, pt2, pt3,
 
2329
                pointsFound, true, null, false, ignoreCenterCuts);
2549
2330
        if (!found)
2550
2331
            return found; // no need of checking horizontal line if the vertical test was not positive
2551
2332
        pt1.setLocation(polyBnd.getMinX(), midPointY);
2552
2333
        pt2.setLocation(polyBnd.getMaxX(), midPointY);
2553
2334
        pointsFound[0] = pointsFound[1] = false;
2554
2335
        pointsFound[2] = true; // no testing pt3 again
2555
 
        found = lookForLayerNew(geom, poly, null, null, cell, layer, DBMath.MATID, bnd, pt1, pt2, null,
2556
 
                pointsFound, true);
 
2336
        found = DRC.lookForLayerCoverage(geom, poly, null, null, cell, layer, DBMath.MATID, bnd, pt1, pt2, null,
 
2337
                pointsFound, true, null, false, ignoreCenterCuts);
2557
2338
        return found;
2558
2339
    }
2559
2340
 
2571
2352
        // Only if there is one default size
2572
2353
        if (minWidthRule != null)
2573
2354
        {
2574
 
            errorDefault = checkMinWidthInternal(geom, layer, poly, onlyOne, minWidthRule, false);
 
2355
            errorDefault = DRC.checkMinWidthInternal(geom, layer, poly, onlyOne, minWidthRule, false, null, reportInfo);
2575
2356
            if (!errorDefault) return false; // the default condition is the valid one.
2576
2357
        }
2577
2358
 
2581
2362
        {
2582
2363
            // Now the error is reporte. Not very efficient
2583
2364
            if (errorDefault)
2584
 
                checkMinWidthInternal(geom, layer, poly, onlyOne, minWidthRule, true);
 
2365
                DRC.checkMinWidthInternal(geom, layer, poly, onlyOne, minWidthRule, true, null, reportInfo);
2585
2366
            return errorDefault;
2586
2367
        }
2587
2368
 
2593
2374
        for (String la : layers)
2594
2375
        {
2595
2376
            Layer l = layer.getTechnology().findLayer(la);
2596
 
            found = searchForCondLayer(geom, poly, l, geom.getParent(), null, null);
 
2377
            found = searchForCondLayer(geom, poly, l, geom.getParent(), reportInfo.ignoreCenterCuts);
2597
2378
            if (!found)
2598
2379
                break; // no need to check the next layer
2599
2380
        }
2600
2381
        // If condition is met then the new rule applied.
2601
2382
        if (found)
2602
 
           errorDefault = checkMinWidthInternal(geom, layer, poly, onlyOne, minWidthRuleCond, true);
 
2383
           errorDefault = DRC.checkMinWidthInternal(geom, layer, poly, onlyOne, minWidthRuleCond, true, null, reportInfo);
2603
2384
        else if (errorDefault) // report the errors here in case of default values
2604
 
            checkMinWidthInternal(geom, layer, poly, onlyOne, minWidthRule, true);
 
2385
            DRC.checkMinWidthInternal(geom, layer, poly, onlyOne, minWidthRule, true, null, reportInfo);
2605
2386
        return errorDefault;
2606
2387
    }
2607
2388
 
2608
 
    private boolean checkMinWidthInternal(Geometric geom, Layer layer, Poly poly, boolean onlyOne,
2609
 
                                          DRCTemplate minWidthRule, boolean reportError)
2610
 
        {
2611
 
                Cell cell = geom.getParent();
2612
 
        if (minWidthRule == null) return false;
2613
 
 
2614
 
        double minWidthValue = minWidthRule.getValue(0);
2615
 
                // simpler analysis if manhattan
2616
 
                Rectangle2D bounds = poly.getBox();
2617
 
                if (bounds != null)
2618
 
                {
2619
 
                        boolean tooSmallWidth = DBMath.isGreaterThan(minWidthValue, bounds.getWidth());
2620
 
                        boolean tooSmallHeight = DBMath.isGreaterThan(minWidthValue, bounds.getHeight());
2621
 
                        if (!tooSmallWidth && !tooSmallHeight) return false;
2622
 
 
2623
 
            boolean foundError = false;
2624
 
            if (tooSmallWidth && checkExtensionWithNeighbors(cell, geom, poly, layer, bounds, minWidthRule,
2625
 
                    0, onlyOne, reportError))
2626
 
                foundError = true;
2627
 
            if (tooSmallHeight && checkExtensionWithNeighbors(cell, geom, poly, layer, bounds, minWidthRule,
2628
 
                    1, onlyOne, reportError))
2629
 
                foundError = true;
2630
 
            return foundError;
2631
 
                }
2632
 
 
2633
 
                // nonmanhattan polygon: stop now if it has no size
2634
 
                Poly.Type style = poly.getStyle();
2635
 
                if (style != Poly.Type.FILLED && style != Poly.Type.CLOSED && style != Poly.Type.CROSSED &&
2636
 
                        style != Poly.Type.OPENED && style != Poly.Type.OPENEDT1 && style != Poly.Type.OPENEDT2 &&
2637
 
                        style != Poly.Type.OPENEDT3 && style != Poly.Type.VECTORS) return false;
2638
 
 
2639
 
                // simple check of nonmanhattan polygon for minimum width
2640
 
                bounds = poly.getBounds2D();
2641
 
                double actual = Math.min(bounds.getWidth(), bounds.getHeight());
2642
 
                if (actual < minWidthValue)
2643
 
                {
2644
 
            if (reportError)
2645
 
                reportError(DRC.DRCErrorType.MINWIDTHERROR, null, cell, minWidthValue, actual, minWidthRule.ruleName,
2646
 
                                (onlyOne) ? null : poly, geom, layer, null, null, null);
2647
 
                        return true;
2648
 
                }
2649
 
 
2650
 
                // check distance of each line's midpoint to perpendicular opposite point
2651
 
                Point2D [] points = poly.getPoints();
2652
 
                int count = points.length;
2653
 
                for(int i=0; i<count; i++)
2654
 
                {
2655
 
                        Point2D from;
2656
 
                        if (i == 0) from = points[count-1]; else
2657
 
                                from = points[i-1];
2658
 
                        Point2D to = points[i];
2659
 
                        if (from.equals(to)) continue;
2660
 
 
2661
 
                        double ang = DBMath.figureAngleRadians(from, to);
2662
 
                        Point2D center = new Point2D.Double((from.getX() + to.getX()) / 2, (from.getY() + to.getY()) / 2);
2663
 
                        double perpang = ang + Math.PI / 2;
2664
 
                        for(int j=0; j<count; j++)
2665
 
                        {
2666
 
                                if (j == i) continue;
2667
 
                                Point2D oFrom;
2668
 
                                if (j == 0) oFrom = points[count-1]; else
2669
 
                                        oFrom = points[j-1];
2670
 
                                Point2D oTo = points[j];
2671
 
                                if (oFrom.equals(oTo)) continue;
2672
 
                                double oAng = DBMath.figureAngleRadians(oFrom, oTo);
2673
 
                                double rAng = ang;   while (rAng > Math.PI) rAng -= Math.PI;
2674
 
                                double rOAng = oAng;   while (rOAng > Math.PI) rOAng -= Math.PI;
2675
 
                                if (DBMath.doublesEqual(rAng, rOAng))
2676
 
                                {
2677
 
                                        // lines are parallel: see if they are colinear
2678
 
                                        if (DBMath.isOnLine(from, to, oFrom)) continue;
2679
 
                                        if (DBMath.isOnLine(from, to, oTo)) continue;
2680
 
                                        if (DBMath.isOnLine(oFrom, oTo, from)) continue;
2681
 
                                        if (DBMath.isOnLine(oFrom, oTo, to)) continue;
2682
 
                                }
2683
 
                                Point2D inter = DBMath.intersectRadians(center, perpang, oFrom, oAng);
2684
 
                                if (inter == null) continue;
2685
 
                                if (inter.getX() < Math.min(oFrom.getX(), oTo.getX()) || inter.getX() > Math.max(oFrom.getX(), oTo.getX())) continue;
2686
 
                                if (inter.getY() < Math.min(oFrom.getY(), oTo.getY()) || inter.getY() > Math.max(oFrom.getY(), oTo.getY())) continue;
2687
 
                                double fdx = center.getX() - inter.getX();
2688
 
                                double fdy = center.getY() - inter.getY();
2689
 
                                actual = DBMath.round(Math.sqrt(fdx*fdx + fdy*fdy));
2690
 
 
2691
 
                                if (actual < minWidthValue)
2692
 
                                {
2693
 
                    if (reportError)
2694
 
                    {
2695
 
                        // look between the points to see if it is minimum width or notch
2696
 
                        if (poly.isInside(new Point2D.Double((center.getX()+inter.getX())/2, (center.getY()+inter.getY())/2)))
2697
 
                        {
2698
 
                            reportError(DRC.DRCErrorType.MINWIDTHERROR, null, cell, minWidthValue,
2699
 
                                actual, minWidthRule.ruleName, (onlyOne) ? null : poly, geom, layer, null, null, null);
2700
 
                        } else
2701
 
                        {
2702
 
                            reportError(DRC.DRCErrorType.NOTCHERROR, null, cell, minWidthValue,
2703
 
                                actual, minWidthRule.ruleName, (onlyOne) ? null : poly, geom, layer, poly, geom, layer);
2704
 
                        }
2705
 
                    }
2706
 
                    return true;
2707
 
                                }
2708
 
                        }
2709
 
                }
2710
 
                return false;
2711
 
        }
2712
 
 
2713
 
//      private int checkMinAreaLayer(GeometryHandler merge, Cell cell, Layer layer, boolean addError,
 
2389
    //  private int checkMinAreaLayer(GeometryHandler merge, Cell cell, Layer layer, boolean addError,
2714
2390
//                                  HashMap<Layer, Layer> minAreaLayerMapDone, HashMap<Layer, Layer> enclosedAreaLayerMapDone)
2715
2391
//      {
2716
2392
//              int errorFound = 0;
2824
2500
            // isGreaterThan doesn't consider equals condition therefore negate condition is used
2825
2501
            if (!DBMath.isGreaterThan(minVal, area)) return; // larger than the min value
2826
2502
            count.increment();
2827
 
            reportError(errorType, null, cell, minVal, area, ruleName,
 
2503
            DRC.createDRCErrorLogger(reportInfo, errorType, null, cell, minVal, area, ruleName,
2828
2504
                        poly, null, layer, null, null, null);
2829
2505
        }
2830
2506
        if (checkNotch)
2834
2510
            if (bnd.getWidth() < spacingRule.getValue(0))
2835
2511
            {
2836
2512
                count.increment();
2837
 
                reportError(DRC.DRCErrorType.NOTCHERROR, "(X axis)", cell, spacingRule.getValue(0), bnd.getWidth(),
2838
 
                        spacingRule.ruleName, poly, null, layer, null, null, layer);
 
2513
                DRC.createDRCErrorLogger(reportInfo, DRC.DRCErrorType.NOTCHERROR, "(X axis)", cell,
 
2514
                    spacingRule.getValue(0), bnd.getWidth(), spacingRule.ruleName, poly, null, layer, null, null, layer);
2839
2515
            }
2840
2516
            if (bnd.getHeight() < spacingRule.getValue(1))
2841
2517
            {
2842
2518
                count.increment();
2843
 
                reportError(DRC.DRCErrorType.NOTCHERROR, "(Y axis)", cell, spacingRule.getValue(1), bnd.getHeight(),
2844
 
                        spacingRule.ruleName, poly, null, layer, null, null, layer);
 
2519
                DRC.createDRCErrorLogger(reportInfo, DRC.DRCErrorType.NOTCHERROR, "(Y axis)", cell,
 
2520
                    spacingRule.getValue(1), bnd.getHeight(), spacingRule.ruleName, poly, null, layer, null, null, layer);
2845
2521
            }
2846
2522
        }
2847
2523
    }
2873
2549
                        return 0;
2874
2550
 
2875
2551
        // remember number of errors before the min area checking
2876
 
        int errorFound = errorLogger.getNumErrors();
 
2552
        int errorFound = reportInfo.errorLogger.getNumErrors();
2877
2553
 
2878
2554
                // Get merged areas.
2879
2555
        DRC.DRCCheckMinArea algoType = DRC.getMinAreaAlgoOption();
2890
2566
        }
2891
2567
        HierarchyEnumerator.enumerateCell(cell, VarContext.globalContext, quickArea);
2892
2568
        
2893
 
        errorFound = errorLogger.getNumErrors() - errorFound;
 
2569
        errorFound = reportInfo.errorLogger.getNumErrors() - errorFound;
2894
2570
 
2895
2571
        return errorFound;
2896
2572
        }
3067
2743
                                if (isBox1.getMinX() == isBox2.getMaxX()) xc = isBox1.getMinX();
3068
2744
                                double yc = isBox2.getMinY();
3069
2745
                                if (isBox1.getMinY() == isBox2.getMaxY()) yc = isBox1.getMinY();
3070
 
                                double xPlus = xc + TINYDELTA;
3071
 
                                double yPlus = yc + TINYDELTA;
 
2746
                                double xPlus = xc + DRC.TINYDELTA;
 
2747
                                double yPlus = yc + DRC.TINYDELTA;
3072
2748
                                pt1.setLocation(xPlus, yPlus);
3073
2749
                                pt2.setLocation(xPlus, yPlus);
3074
2750
                                if ((xPlus < isBox1.getMinX() || xPlus > isBox1.getMaxX() || yPlus < isBox1.getMinY() || yPlus > isBox1.getMaxY()) &&
3075
2751
                                        (xPlus < isBox2.getMinX() || xPlus > isBox2.getMaxX() || yPlus < isBox2.getMinY() || yPlus > isBox2.getMaxY())) return 1;
3076
 
                                pt1.setLocation(xc + TINYDELTA, yc - TINYDELTA);
3077
 
                                pt2.setLocation(xc - TINYDELTA, yc + TINYDELTA);
 
2752
                                pt1.setLocation(xc + DRC.TINYDELTA, yc - DRC.TINYDELTA);
 
2753
                                pt2.setLocation(xc - DRC.TINYDELTA, yc + DRC.TINYDELTA);
3078
2754
                                return 1;
3079
2755
                        }
3080
2756
 
3119
2795
                return 1;
3120
2796
        }
3121
2797
 
3122
 
        /**
3123
 
         * Method to explore the points (xf1,yf1) and (xf2,yf2) to see if there is
3124
 
         * geometry on layer "layer" (in or below cell "cell").  Returns true if there is.
3125
 
         * If "needBoth" is true, both points must have geometry, otherwise only 1 needs it.
3126
 
         */
3127
 
//      private boolean lookForPoints(Point2D pt1, Point2D pt2, Layer layer, Cell cell, boolean needBoth)
3128
 
//      {
3129
 
//              Point2D pt3 = new Point2D.Double((pt1.getX()+pt2.getX()) / 2, (pt1.getY()+pt2.getY()) / 2);
3130
 
//
3131
 
//              // compute bounds for searching inside cells
3132
 
//              double flx = Math.min(pt1.getX(), pt2.getX());   double fhx = Math.max(pt1.getX(), pt2.getX());
3133
 
//              double fly = Math.min(pt1.getY(), pt2.getY());   double fhy = Math.max(pt1.getY(), pt2.getY());
3134
 
//              Rectangle2D bounds = new Rectangle2D.Double(flx, fly, fhx-flx, fhy-fly);
3135
 
//
3136
 
//              // search the cell for geometry that fills the notch
3137
 
//              boolean [] pointsFound = new boolean[3];
3138
 
//              pointsFound[0] = pointsFound[1] = pointsFound[2] = false;
3139
 
//              boolean allFound = lookForLayer(null, cell, layer, DBMath.MATID, bounds,
3140
 
//                      pt1, pt2, pt3, pointsFound);
3141
 
//              if (needBoth)
3142
 
//              {
3143
 
//                      if (allFound) return true;
3144
 
//              } else
3145
 
//              {
3146
 
//                      if (pointsFound[0] || pointsFound[1]) return true;
3147
 
//              }
3148
 
//              return false;
3149
 
//      }
3150
 
 
3151
 
                /**
 
2798
    /**
3152
2799
         * Method to explore the points (xf1,yf1) and (xf2,yf2) to see if there is
3153
2800
         * geometry on layer "layer" (in or below cell "cell").  Returns true if there is.
3154
2801
         * If "needBoth" is true, both points must have geometry, otherwise only 1 needs it.
3163
2810
                // compute bounds for searching inside cells
3164
2811
                double flx = Math.min(pt1.getX(), pt2.getX());   double fhx = Math.max(pt1.getX(), pt2.getX());
3165
2812
                double fly = Math.min(pt1.getY(), pt2.getY());   double fhy = Math.max(pt1.getY(), pt2.getY());
3166
 
                Rectangle2D bounds = new Rectangle2D.Double(DBMath.round(flx-TINYDELTA), DBMath.round(fly-TINYDELTA),
3167
 
                DBMath.round(fhx-flx+2*TINYDELTA), DBMath.round(fhy-fly+2*TINYDELTA));
 
2813
                Rectangle2D bounds = new Rectangle2D.Double(DBMath.round(flx- DRC.TINYDELTA), DBMath.round(fly- DRC.TINYDELTA),
 
2814
                DBMath.round(fhx-flx+2* DRC.TINYDELTA), DBMath.round(fhy-fly+2* DRC.TINYDELTA));
3168
2815
            // Adding delta otherwise it won't consider points along edges.
3169
2816
        // Mind bounding boxes could have zero width or height
3170
2817
 
3171
2818
                // search the cell for geometry that fills the notch
3172
2819
                boolean [] pointsFound = new boolean[2];
3173
2820
                pointsFound[0] = pointsFound[1] = false;
3174
 
                boolean allFound = lookForLayerNew(geo1, poly1, geo2, poly2, cell, layer, DBMath.MATID, bounds,
3175
 
                        pt1, pt2, null, pointsFound, overlap);
 
2821
                boolean allFound = DRC.lookForLayerCoverage(geo1, poly1, geo2, poly2, cell, layer, DBMath.MATID, bounds,
 
2822
                        pt1, pt2, null, pointsFound, overlap, null, false, reportInfo.ignoreCenterCuts);
3176
2823
 
3177
2824
                return allFound;
3178
2825
        }
3179
2826
 
3180
 
        /**
3181
 
         * Method to examine cell "cell" in the area (lx<=X<=hx, ly<=Y<=hy) for objects
3182
 
         * on layer "layer".  Apply transformation "moreTrans" to the objects.  If polygons are
3183
 
         * found at (xf1,yf1) or (xf2,yf2) or (xf3,yf3) then sets "p1found/p2found/p3found" to 1.
3184
 
         * If all locations are found, returns true.
3185
 
         */
3186
 
        private boolean lookForLayer(Poly thisPoly, Cell cell, Layer layer, AffineTransform moreTrans,
3187
 
                Rectangle2D bounds, Point2D pt1, Point2D pt2, Point2D pt3, boolean [] pointsFound)
3188
 
        {
3189
 
                int j;
3190
 
        boolean skip = false;
3191
 
        Rectangle2D newBounds = new Rectangle2D.Double();  // sept 30
3192
 
 
3193
 
                for(Iterator<RTBounds> it = cell.searchIterator(bounds); it.hasNext(); )
3194
 
                {
3195
 
                        RTBounds g = it.next();
3196
 
                        if (g instanceof NodeInst)
3197
 
                        {
3198
 
                                NodeInst ni = (NodeInst)g;
3199
 
                                if (NodeInst.isSpecialNode(ni)) continue; // Nov 16, no need for checking pins or other special nodes;
3200
 
                                if (ni.isCellInstance())
3201
 
                                {
3202
 
                                        // compute bounding area inside of sub-cell
3203
 
                                        AffineTransform rotI = ni.rotateIn();
3204
 
                                        AffineTransform transI = ni.translateIn();
3205
 
                                        rotI.preConcatenate(transI);
3206
 
                                        newBounds.setRect(bounds);
3207
 
                                        DBMath.transformRect(newBounds, rotI);
3208
 
 
3209
 
                                        // compute new matrix for sub-cell examination
3210
 
                                        AffineTransform trans = ni.translateOut(ni.rotateOut());
3211
 
                                        trans.preConcatenate(moreTrans);
3212
 
                                        if (lookForLayer(thisPoly, (Cell)ni.getProto(), layer, trans, newBounds,
3213
 
                                                pt1, pt2, pt3, pointsFound))
3214
 
                                                        return true;
3215
 
                                        continue;
3216
 
                                }
3217
 
                                AffineTransform bound = ni.rotateOut();
3218
 
                                bound.preConcatenate(moreTrans);
3219
 
                                Technology tech = ni.getProto().getTechnology();
3220
 
                                Poly [] layerLookPolyList = tech.getShapeOfNode(ni, false, ignoreCenterCuts, null);
3221
 
                                int tot = layerLookPolyList.length;
3222
 
                                for(int i=0; i<tot; i++)
3223
 
                                {
3224
 
                                        Poly poly = layerLookPolyList[i];
3225
 
 
3226
 
                                        if (!tech.sameLayer(poly.getLayer(), layer)) continue;
3227
 
 
3228
 
                                        if (thisPoly != null && poly.polySame(thisPoly)) continue;
3229
 
                                        poly.transform(bound);
3230
 
                                        if (poly.isInside(pt1)) pointsFound[0] = true;
3231
 
                                        if (poly.isInside(pt2)) pointsFound[1] = true;
3232
 
                                        if (pt3 != null && poly.isInside(pt3)) pointsFound[2] = true;
3233
 
                                        for (j = 0; j < pointsFound.length && pointsFound[j]; j++);
3234
 
                                        boolean newR = (j == pointsFound.length);
3235
 
                                        if (newR)
3236
 
                    {
3237
 
                                                return true;
3238
 
                    }
3239
 
                    // No need of checking rest of the layers?
3240
 
                    //break;
3241
 
                                }
3242
 
                        } else
3243
 
                        {
3244
 
                                ArcInst ai = (ArcInst)g;
3245
 
                                Technology tech = ai.getProto().getTechnology();
3246
 
                                Poly [] layerLookPolyList = tech.getShapeOfArc(ai);
3247
 
                                int tot = layerLookPolyList.length;
3248
 
                                for(int i=0; i<tot; i++)
3249
 
                                {
3250
 
                                        Poly poly = layerLookPolyList[i];
3251
 
                                        if (!tech.sameLayer(poly.getLayer(), layer)) continue;
3252
 
                                        poly.transform(moreTrans);
3253
 
                                        if (poly.isInside(pt1)) pointsFound[0] = true;
3254
 
                                        if (poly.isInside(pt2)) pointsFound[1] = true;
3255
 
                                        if (pt3 != null && poly.isInside(pt3)) pointsFound[2] = true;
3256
 
                                        for (j = 0; j < pointsFound.length && pointsFound[j]; j++);
3257
 
                                        boolean newR = (j == pointsFound.length);
3258
 
                                        if (newR)
3259
 
                                                return true;
3260
 
                    // No need of checking rest of the layers
3261
 
                    //break;
3262
 
                                }
3263
 
                        }
3264
 
 
3265
 
                        for (j = 0; j < pointsFound.length && pointsFound[j]; j++);
3266
 
            if (j == pointsFound.length)
3267
 
            {
3268
 
                System.out.println("When?");
3269
 
                return true;
3270
 
            }
3271
 
                }
3272
 
        if (skip) System.out.println("This case in lookForLayerNew antes");
3273
 
 
3274
 
                return false;
3275
 
        }
3276
 
 
3277
 
        /**
 
2827
    /**
3278
2828
         * Method to examine cell "cell" in the area (lx<=X<=hx, ly<=Y<=hy) for objects
3279
2829
         * on layer "layer".  Apply transformation "moreTrans" to the objects.  If polygons are
3280
2830
         * found at (xf1,yf1) or (xf2,yf2) or (xf3,yf3) then sets "p1found/p2found/p3found" to 1.
3326
2876
                                Technology tech = ni.getProto().getTechnology();
3327
2877
                // I have to ask for electrical layers otherwise it will retrieve one polygon for polysilicon
3328
2878
                // and poly.polySame(poly1) will never be true. CONTRADICTION!
3329
 
                                Poly [] layerLookPolyList = tech.getShapeOfNode(ni, false, ignoreCenterCuts, null);
 
2879
                                Poly [] layerLookPolyList = tech.getShapeOfNode(ni, false, reportInfo.ignoreCenterCuts, null);
3330
2880
                                int tot = layerLookPolyList.length;
3331
2881
                                for(int i=0; i<tot; i++)
3332
2882
                                {
3378
2928
                return false;
3379
2929
        }
3380
2930
 
3381
 
    /**
3382
 
         * Method to examine cell "cell" in the area (lx<=X<=hx, ly<=Y<=hy) for objects
3383
 
         * on layer "layer".  Apply transformation "moreTrans" to the objects.  If polygons are
3384
 
         * found at (xf1,yf1) or (xf2,yf2) or (xf3,yf3) then sets "p1found/p2found/p3found" to 1.
3385
 
         * If all locations are found, returns true.
3386
 
         */
3387
 
        private boolean lookForLayerNew(Geometric geo1, Poly poly1, Geometric geo2, Poly poly2, Cell cell,
3388
 
                                    Layer layer, AffineTransform moreTrans, Rectangle2D bounds,
3389
 
                                    Point2D pt1, Point2D pt2, Point2D pt3, boolean[] pointsFound,
3390
 
                                    boolean overlap)
3391
 
        {
3392
 
                int j;
3393
 
        Rectangle2D newBounds = new Rectangle2D.Double();  // Sept 30
3394
 
 
3395
 
                for(Iterator<RTBounds> it = cell.searchIterator(bounds); it.hasNext(); )
3396
 
                {
3397
 
                        RTBounds g = it.next();
3398
 
 
3399
 
            // You can't skip the same geometry otherwise layers in the same Geometric won't
3400
 
            // be tested.
3401
 
//                      if (ignoreSameGeometry && (g == geo1 || g == geo2))
3402
 
//                continue;
3403
 
 
3404
 
            // I can't skip geometries to exclude from the search
3405
 
                        if (g instanceof NodeInst)
3406
 
                        {
3407
 
                                NodeInst ni = (NodeInst)g;
3408
 
                                if (NodeInst.isSpecialNode(ni)) continue; // Nov 16, no need for checking pins or other special nodes;
3409
 
                                if (ni.isCellInstance())
3410
 
                                {
3411
 
                                        // compute bounding area inside of sub-cell
3412
 
                                        AffineTransform rotI = ni.rotateIn();
3413
 
                                        AffineTransform transI = ni.translateIn();
3414
 
                                        rotI.preConcatenate(transI);
3415
 
                                        newBounds.setRect(bounds);
3416
 
                                        DBMath.transformRect(newBounds, rotI);
3417
 
 
3418
 
                                        // compute new matrix for sub-cell examination
3419
 
                                        AffineTransform trans = ni.translateOut(ni.rotateOut());
3420
 
                                        trans.preConcatenate(moreTrans);
3421
 
                                        if (lookForLayerNew(geo1, poly1, geo2, poly2, (Cell)ni.getProto(), layer, trans, newBounds,
3422
 
                                                pt1, pt2, pt3, pointsFound, overlap))
3423
 
                                                        return true;
3424
 
                                        continue;
3425
 
                                }
3426
 
                                AffineTransform bound = ni.rotateOut();
3427
 
                                bound.preConcatenate(moreTrans);
3428
 
                                Technology tech = ni.getProto().getTechnology();
3429
 
                // I have to ask for electrical layers otherwise it will retrieve one polygon for polysilicon
3430
 
                // and poly.polySame(poly1) will never be true. CONTRADICTION!
3431
 
                                Poly [] layerLookPolyList = tech.getShapeOfNode(ni, false, ignoreCenterCuts, null);
3432
 
                                int tot = layerLookPolyList.length;
3433
 
                                for(int i=0; i<tot; i++)
3434
 
                                {
3435
 
                                        Poly poly = layerLookPolyList[i];
3436
 
                                        if (!tech.sameLayer(poly.getLayer(), layer)) continue;
3437
 
 
3438
 
                    // Should be the transform before?
3439
 
                                        poly.transform(bound);
3440
 
 
3441
 
                                        if (poly1 != null && !overlap && poly.polySame(poly1))
3442
 
                                                continue;
3443
 
                                        if (poly2 != null && !overlap && poly.polySame(poly2))
3444
 
                                                continue;
3445
 
 
3446
 
                                        if (!pointsFound[0] && poly.isInside(pt1)) pointsFound[0] = true; // @TODO Should still evaluate isInside if pointsFound[i] is already valid?
3447
 
                                        if (!pointsFound[1] && poly.isInside(pt2)) pointsFound[1] = true;
3448
 
                                        if (pt3 != null && !pointsFound[2] && poly.isInside(pt3)) pointsFound[2] = true;
3449
 
                                        for (j = 0; j < pointsFound.length && pointsFound[j]; j++);
3450
 
                                        if (j == pointsFound.length) return true;
3451
 
                    // No need of checking rest of the layers
3452
 
                    break; // assuming only 1 polygon per layer (non-electrical)
3453
 
                                }
3454
 
                        } else
3455
 
                        {
3456
 
                                ArcInst ai = (ArcInst)g;
3457
 
                                Technology tech = ai.getProto().getTechnology();
3458
 
                                Poly [] layerLookPolyList = tech.getShapeOfArc(ai);
3459
 
                                int tot = layerLookPolyList.length;
3460
 
                                for(int i=0; i<tot; i++)
3461
 
                                {
3462
 
                                        Poly poly = layerLookPolyList[i];
3463
 
                                        if (!tech.sameLayer(poly.getLayer(), layer)) continue;
3464
 
                                        poly.transform(moreTrans);  // @TODO Should still evaluate isInside if pointsFound[i] is already valid?
3465
 
                                        if (!pointsFound[0] && poly.isInside(pt1)) pointsFound[0] = true;
3466
 
                                        if (!pointsFound[1] && poly.isInside(pt2)) pointsFound[1] = true;
3467
 
                                        if (pt3 != null && !pointsFound[2] && poly.isInside(pt3)) pointsFound[2] = true;
3468
 
                                        for (j = 0; j < pointsFound.length && pointsFound[j]; j++);
3469
 
                                        if (j == pointsFound.length) return true;
3470
 
                    // No need of checking rest of the layers
3471
 
                    break;
3472
 
                                }
3473
 
                        }
3474
 
 
3475
 
                        for (j = 0; j < pointsFound.length && pointsFound[j]; j++);
3476
 
                        if (j == pointsFound.length)
3477
 
            {
3478
 
                assert(false); // test when otherwise the calculation is useless! System.out.println("When?");
3479
 
                return true;
3480
 
            }
3481
 
                }
3482
 
                return false;
3483
 
        }
3484
 
 
3485
2931
    /****************************** Cut Rule Functions ***************************/
3486
2932
    private boolean checkCutSizes(NodeProto np, Geometric geom, Layer layer, Poly poly,
3487
2933
                                  Geometric nGeom, Layer nLayer, Poly nPoly, Cell topCell)
3503
2949
        Rectangle2D box1 = poly.getBounds2D();
3504
2950
        Rectangle2D box2 = nPoly.getBounds2D();
3505
2951
 
3506
 
        double pdx = Math.max(box2.getMinX()-box1.getMaxX(), box1.getMinX()-box2.getMaxX());
3507
 
        double pdy = Math.max(box2.getMinY()-box1.getMaxY(), box1.getMinY()-box2.getMaxY());
 
2952
        double pdx = DBMath.round(Math.max(box2.getMinX()-box1.getMaxX(), box1.getMinX()-box2.getMaxX()));
 
2953
        double pdy = DBMath.round(Math.max(box2.getMinY()-box1.getMaxY(), box1.getMinY()-box2.getMaxY()));
3508
2954
        double pd = Math.max(pdx, pdy);
3509
 
        if (pdx == 0 && pdy == 0) pd = 0; // touching
 
2955
 
 
2956
        if (DBMath.areEquals(pdx, 0) && DBMath.areEquals(pdy, 0))
 
2957
            pd = 0; // touching
3510
2958
 
3511
2959
        // They have to overlap
3512
 
                if (pd > 0) return false;
 
2960
        if (DBMath.isGreaterThan(pd, 0))
 
2961
            return false;
3513
2962
        boolean foundError = false;
3514
2963
        double minX = Math.min(box1.getMinX(), box2.getMinX());
3515
2964
        double minY = Math.min(box1.getMinY(), box2.getMinY());
3523
2972
        String ruleName = (rule != null) ? rule.ruleName : "for contacts";
3524
2973
        if (DBMath.isGreaterThan(rect.getWidth(), cutSizeX))
3525
2974
        {
3526
 
            reportError(DRC.DRCErrorType.CUTERROR, "along X", topCell, cutSizeX, rect.getWidth(),
 
2975
            DRC.createDRCErrorLogger(reportInfo, DRC.DRCErrorType.CUTERROR, "along X", topCell, cutSizeX, rect.getWidth(),
3527
2976
                    ruleName, new Poly(rect), null, layer, null, null, nLayer);
3528
2977
            foundError = true;
3529
2978
 
3530
2979
        }
3531
2980
        if (DBMath.isGreaterThan(rect.getHeight(), cutSizeY))
3532
2981
        {
3533
 
            reportError(DRC.DRCErrorType.CUTERROR, "along Y", topCell, cutSizeY, rect.getHeight(),
 
2982
            DRC.createDRCErrorLogger(reportInfo, DRC.DRCErrorType.CUTERROR, "along Y", topCell, cutSizeY, rect.getHeight(),
3534
2983
                    ruleName, new Poly(rect), null, layer, null, null, layer);
3535
2984
            foundError = true;
3536
2985
 
3855
3304
                basicFound[0] = false;
3856
3305
                basicPts[0] = basePts[j];
3857
3306
 
3858
 
                Rectangle2D basicBnd = new Rectangle2D.Double(DBMath.round(basicPts[0].getX()-TINYDELTA),
3859
 
                                DBMath.round(basicPts[0].getY()-TINYDELTA),
3860
 
                                2*(TINYDELTA), 2*(TINYDELTA));
 
3307
                Rectangle2D basicBnd = new Rectangle2D.Double(DBMath.round(basicPts[0].getX()- DRC.TINYDELTA),
 
3308
                                DBMath.round(basicPts[0].getY()- DRC.TINYDELTA),
 
3309
                                2*(DRC.TINYDELTA), 2*(DRC.TINYDELTA));
3861
3310
                boolean f = false;
3862
3311
                for (int i = 0; i < layers.length; i++)
3863
3312
                {
3909
3358
                        basicBndPoint = basicPts[2];
3910
3359
                        break;
3911
3360
                }
3912
 
                basicBnd = new Rectangle2D.Double(DBMath.round(basicBndPoint.getX()-TINYDELTA),
3913
 
                                DBMath.round(basicBndPoint.getY()-TINYDELTA),
3914
 
                                DBMath.round(xValue+2*(TINYDELTA)), DBMath.round(yValue+2*(TINYDELTA)));
 
3361
                basicBnd = new Rectangle2D.Double(DBMath.round(basicBndPoint.getX()- DRC.TINYDELTA),
 
3362
                                DBMath.round(basicBndPoint.getY()- DRC.TINYDELTA),
 
3363
                                DBMath.round(xValue+2*(DRC.TINYDELTA)), DBMath.round(yValue+2*(DRC.TINYDELTA)));
3915
3364
 
3916
3365
                for (int i = 0; i < layers.length; i++)
3917
3366
                {
3923
3372
 
3924
3373
                if (!f)
3925
3374
                {
3926
 
                    reportError(DRC.DRCErrorType.LAYERSURROUNDERROR, "No enough surround of " + rule.condition + ", ", geom.getParent(), rule.getValue(0),
3927
 
                            -1, rule.ruleName, poly, geom, layer, null, null, null);
3928
 
                    if (errorTypeSearch != DRC.DRCCheckMode.ERROR_CHECK_EXHAUSTIVE) return true; // no need of checking other combinations
 
3375
                    DRC.createDRCErrorLogger(reportInfo, DRC.DRCErrorType.LAYERSURROUNDERROR,
 
3376
                        "No enough surround of " + rule.condition + ", ",
 
3377
                        geom.getParent(), rule.getValue(0), -1, rule.ruleName, poly, geom, layer, null, null, null);
 
3378
                    if (reportInfo.errorTypeSearch != DRC.DRCCheckMode.ERROR_CHECK_EXHAUSTIVE) return true; // no need of checking other combinations
3929
3379
                    break; // with next rule
3930
3380
                }
3931
3381
            }
4185
3635
         basePts[1] = new Point2D.Double(polyBounds.getMinX(), polyBounds.getMaxY());
4186
3636
         basePts[2] = new Point2D.Double(polyBounds.getMaxX(), polyBounds.getMaxY());
4187
3637
         basePts[3] = new Point2D.Double(polyBounds.getMaxX(), polyBounds.getMinY());
4188
 
         Rectangle2D basicBnd = new Rectangle2D.Double(DBMath.round(basePts[0].getX()-TINYDELTA),
4189
 
                 DBMath.round(basePts[0].getY()-TINYDELTA),
4190
 
                 DBMath.round(2*(TINYDELTA)+polyBounds.getWidth()),
4191
 
                 DBMath.round(2*(TINYDELTA)+polyBounds.getHeight()));
 
3638
         Rectangle2D basicBnd = new Rectangle2D.Double(DBMath.round(basePts[0].getX()- DRC.TINYDELTA),
 
3639
                 DBMath.round(basePts[0].getY()- DRC.TINYDELTA),
 
3640
                 DBMath.round(2*(DRC.TINYDELTA)+polyBounds.getWidth()),
 
3641
                 DBMath.round(2*(DRC.TINYDELTA)+polyBounds.getHeight()));
4192
3642
         // Searches for any posible VTH/VTH that fully covers the polysilicon.
4193
3643
         // It has to be recursive and could be expensive
4194
3644
         boolean found = lookForLayerWithPoints(null, polys[polyIndex], null, null, cell, layers[vtIndex],
4259
3709
                        }
4260
3710
 
4261
3711
                        // must be a transistor
4262
 
                        if (!ni.isFET()) continue;
 
3712
                        if (!ni.getFunction().isFET()) continue;
4263
3713
 
4264
3714
                        // must be inside of the bounding box of the desired layers
4265
3715
                        Rectangle2D nodeBounds = ni.getBounds();
4324
3774
                                     Layer nLayer, int nNet, Geometric nGeom, Rectangle2D bound)
4325
3775
        {
4326
3776
                Technology tech = ni.getProto().getTechnology();
4327
 
                Poly [] cropNodePolyList = tech.getShapeOfNode(ni, true, ignoreCenterCuts, null);
 
3777
        assert(ni.getProto().getFunction() != PrimitiveNode.Function.PIN);
 
3778
        Poly [] cropNodePolyList = tech.getShapeOfNode(ni, true, reportInfo.ignoreCenterCuts, null);
4328
3779
                convertPseudoLayers(ni, cropNodePolyList);
4329
3780
                int tot = cropNodePolyList.length;
4330
3781
                if (tot < 0) return false;
4390
3841
                {
4391
3842
                        // find the primitive nodeinst at the true end of the portinst
4392
3843
                        PortInst pi = ai.getPortInst(i);
4393
 
 
4394
 
                        PortOriginal fp = new PortOriginal(pi, inTrans);
 
3844
            PortOriginal fp = new PortOriginal(pi, inTrans);
4395
3845
                        NodeInst ni = fp.getBottomNodeInst();
4396
 
                        NodeProto np = ni.getProto();
 
3846
            
 
3847
            if (NodeInst.isSpecialNode(ni))
 
3848
                continue; // Dec 08 -> is a pin so ignore it
 
3849
 
 
3850
            NodeProto np = ni.getProto();
4397
3851
                        AffineTransform trans = fp.getTransformToTop();
4398
3852
 
4399
3853
                        Technology tech = np.getTechnology();
4427
3881
//                }
4428
3882
//            }
4429
3883
//            else
4430
 
                cropArcPolyList = tech.getShapeOfNode(ni, false, ignoreCenterCuts, null);
 
3884
                cropArcPolyList = tech.getShapeOfNode(ni, false, reportInfo.ignoreCenterCuts, null);
4431
3885
                        int tot = cropArcPolyList.length;
4432
3886
                        for(int j=0; j<tot; j++)
4433
3887
                        {
4450
3904
                return false;
4451
3905
        }
4452
3906
 
4453
 
        /**
4454
 
         * Method to see if polygons in "pList" (describing arc "ai") should be cropped against a
4455
 
         * connecting transistor.  Crops the polygon if so.
4456
 
         */
4457
 
        private void cropActiveArc(ArcInst ai, Poly [] pList)
4458
 
        {
4459
 
                // look for an active layer in this arc
4460
 
                int tot = pList.length;
4461
 
                int diffPoly = -1;
4462
 
                for(int j=0; j<tot; j++)
4463
 
                {
4464
 
                        Poly poly = pList[j];
4465
 
                        Layer layer = poly.getLayer();
4466
 
                        if (layer == null) continue;
4467
 
                        Layer.Function fun = layer.getFunction();
4468
 
                        if (fun.isDiff()) { diffPoly = j;   break; }
4469
 
                }
4470
 
                if (diffPoly < 0) return;
4471
 
                Poly poly = pList[diffPoly];
4472
 
 
4473
 
                // must be manhattan
4474
 
                Rectangle2D polyBounds = poly.getBox();
4475
 
                if (polyBounds == null) return;
4476
 
                polyBounds = new Rectangle2D.Double(polyBounds.getMinX(), polyBounds.getMinY(), polyBounds.getWidth(), polyBounds.getHeight());
4477
 
 
4478
 
                // search for adjoining transistor in the cell
4479
 
                boolean cropped = false;
4480
 
                boolean halved = false;
4481
 
                for(int i=0; i<2; i++)
4482
 
                {
4483
 
                        PortInst pi = ai.getPortInst(i);
4484
 
                        NodeInst ni = pi.getNodeInst();
4485
 
                        if (!ni.isFET()) continue;
4486
 
 
4487
 
                        // crop the arc against this transistor
4488
 
                        AffineTransform trans = ni.rotateOut();
4489
 
                        Technology tech = ni.getProto().getTechnology();
4490
 
                        Poly [] activeCropPolyList = tech.getShapeOfNode(ni, false, ignoreCenterCuts, null);
4491
 
                        int nTot = activeCropPolyList.length;
4492
 
                        for(int k=0; k<nTot; k++)
4493
 
                        {
4494
 
                                Poly nPoly = activeCropPolyList[k];
4495
 
                                if (nPoly.getLayer() != poly.getLayer()) continue;
4496
 
                                nPoly.transform(trans);
4497
 
                                Rectangle2D nPolyBounds = nPoly.getBox();
4498
 
                                if (nPolyBounds == null) continue;
4499
 
                                // @TODO Why only one half is half crop?
4500
 
                                // Should I change cropBox by cropBoxComplete?
4501
 
                                int result = (halved) ?
4502
 
                                                Poly.cropBox(polyBounds, nPolyBounds) :
4503
 
                                        Poly.halfCropBox(polyBounds, nPolyBounds);
4504
 
 
4505
 
                                if (result == 1)
4506
 
                                {
4507
 
                                        // remove this polygon from consideration
4508
 
                                        poly.setLayer(null);
4509
 
                                        return;
4510
 
                                }
4511
 
                                cropped = true;
4512
 
                                halved = true;
4513
 
                        }
4514
 
                }
4515
 
                if (cropped)
4516
 
                {
4517
 
                        Poly.Type style = poly.getStyle();
4518
 
                        Layer layer = poly.getLayer();
4519
 
                        poly = new Poly(polyBounds);
4520
 
                        poly.setStyle(style);
4521
 
                        poly.setLayer(layer);
4522
 
                        pList[diffPoly] = poly;
4523
 
                }
4524
 
        }
4525
 
 
4526
 
        /**
 
3907
    /**
4527
3908
         * Method to convert all Layer information in the Polys to be non-pseudo.
4528
3909
         * This is only done for pins that have exports but no arcs.
4529
3910
         * @param ni the NodeInst being converted.
4549
3930
        }
4550
3931
 
4551
3932
        /**
4552
 
         * Method to determine which layers in a Technology are valid.
4553
 
         */
4554
 
        private void cacheValidLayers(Technology tech)
4555
 
        {
4556
 
                if (tech == null) return;
4557
 
                if (layersValidTech == tech) return;
4558
 
 
4559
 
                layersValidTech = tech;
4560
 
 
4561
 
                // determine the layers that are being used
4562
 
                int numLayers = tech.getNumLayers();
4563
 
                layersValid = new boolean[numLayers];
4564
 
                for(int i=0; i < numLayers; i++)
4565
 
                        layersValid[i] = false;
4566
 
                for(Iterator it = tech.getNodes(); it.hasNext(); )
4567
 
                {
4568
 
                        PrimitiveNode np = (PrimitiveNode)it.next();
4569
 
                        if (np.isNotUsed()) continue;
4570
 
                        Technology.NodeLayer [] layers = np.getLayers();
4571
 
                        for(int i=0; i<layers.length; i++)
4572
 
                        {
4573
 
                                Layer layer = layers[i].getLayer();
4574
 
                                layersValid[layer.getIndex()] = true;
4575
 
                        }
4576
 
                }
4577
 
                for(Iterator it = tech.getArcs(); it.hasNext(); )
4578
 
                {
4579
 
                        ArcProto ap = (ArcProto)it.next();
4580
 
                        if (ap.isNotUsed()) continue;
4581
 
                        for (Iterator<Layer> lIt = ap.getLayerIterator(); lIt.hasNext(); )
4582
 
                        {
4583
 
                                Layer layer = lIt.next();
4584
 
                                layersValid[layer.getIndex()] = true;
4585
 
                        }
4586
 
                }
4587
 
        }
4588
 
 
4589
 
        /**
4590
3933
         * Method to determine the minimum distance between "layer1" and "layer2" in technology
4591
3934
         * "tech" and library "lib".  If "con" is true, the layers are connected.  Also forces
4592
3935
         * connectivity for same-implant layers. Returns conditional rules if not standard rules were found
4622
3965
            else
4623
3966
            {
4624
3967
                Layer l = layer1.getTechnology().findLayer(layerName2);
4625
 
                boolean found = searchForCondLayer(geo1, poly1, l, geo1.getParent(), null, null);
 
3968
                boolean found = searchForCondLayer(geo1, poly1, l, geo1.getParent(), reportInfo.ignoreCenterCuts);
4626
3969
                if (found)
4627
3970
                    theRule = null; // doesn't apply
4628
3971
            }
4668
4011
                return nets[globalIndex].intValue();
4669
4012
        }
4670
4013
 
4671
 
        /***************** LAYER INTERACTIONS ******************/
4672
 
 
4673
 
        /**
4674
 
         * Method to build the internal data structures that tell which layers interact with
4675
 
         * which primitive nodes in technology "tech".
4676
 
         */
4677
 
        private void buildLayerInteractions(Technology tech)
4678
 
        {
4679
 
                Technology old = layerInterTech;
4680
 
                if (layerInterTech == tech) return;
4681
 
 
4682
 
                layerInterTech = tech;
4683
 
                int numLayers = tech.getNumLayers();
4684
 
 
4685
 
                // build the node table
4686
 
        if (layersInterNodes != null && old != null && job != null)
4687
 
        {
4688
 
                errorLogger.logWarning("Switching from '" + old.getTechName() +
4689
 
                        "' to '" +  tech.getTechName() + "' in DRC process. Check for non desired nodes in ",
4690
 
                        job.cell, -1);
4691
 
        }
4692
 
 
4693
 
                layersInterNodes = new HashMap<PrimitiveNode, boolean[]>();
4694
 
                for(Iterator<PrimitiveNode> it = tech.getNodes(); it.hasNext(); )
4695
 
                {
4696
 
                        PrimitiveNode np = it.next();
4697
 
            if (np.isNotUsed()) continue;
4698
 
                        boolean [] layersInNode = new boolean[numLayers];
4699
 
            Arrays.fill(layersInNode, false);
4700
 
 
4701
 
                        Technology.NodeLayer [] layers = np.getLayers();
4702
 
                        Technology.NodeLayer [] eLayers = np.getElectricalLayers();
4703
 
                        if (eLayers != null) layers = eLayers;
4704
 
                        for(Technology.NodeLayer l : layers)
4705
 
                        {
4706
 
                                Layer layer = l.getLayer();
4707
 
                if (layer.isNonElectrical())
4708
 
                    continue; // such as pseudo
4709
 
                for(Iterator<Layer> lIt = tech.getLayers(); lIt.hasNext(); )
4710
 
                                {
4711
 
                                        Layer oLayer = lIt.next();
4712
 
                    if (oLayer.isNonElectrical())
4713
 
                        continue; // such as pseudo
4714
 
                    if (DRC.isAnySpacingRule(layer, oLayer))
4715
 
                        layersInNode[oLayer.getIndex()] = true;
4716
 
                                }
4717
 
                        }
4718
 
                        layersInterNodes.put(np, layersInNode);
4719
 
                }
4720
 
 
4721
 
                // build the arc table
4722
 
                layersInterArcs = new HashMap<ArcProto, boolean[]>();
4723
 
                for(Iterator<ArcProto> it = tech.getArcs(); it.hasNext(); )
4724
 
                {
4725
 
                        ArcProto ap = it.next();
4726
 
                        boolean [] layersInArc = new boolean[numLayers];
4727
 
            Arrays.fill(layersInArc, false);
4728
 
 
4729
 
                        for(Iterator<Layer> alIt = ap.getLayerIterator(); alIt.hasNext(); )
4730
 
                        {
4731
 
                                Layer layer = alIt.next();
4732
 
                                for(Iterator<Layer> lIt = tech.getLayers(); lIt.hasNext(); )
4733
 
                                {
4734
 
                                        Layer oLayer = lIt.next();
4735
 
                                        if (DRC.isAnySpacingRule(layer, oLayer))
4736
 
                                                layersInArc[oLayer.getIndex()] = true;
4737
 
                                }
4738
 
                        }
4739
 
                        layersInterArcs.put(ap, layersInArc);
4740
 
                }
4741
 
        }
4742
 
 
4743
 
        /**
4744
 
         * Method to determine whether layer "layer" interacts in any way with a node of type "np".
4745
 
         * If not, returns FALSE.
4746
 
         */
4747
 
        private boolean checkLayerWithNode(Layer layer, NodeProto np)
4748
 
        {
4749
 
                buildLayerInteractions(np.getTechnology());
4750
 
 
4751
 
                // find this node in the table
4752
 
                boolean [] validLayers = layersInterNodes.get(np);
4753
 
                if (validLayers == null) return false;
4754
 
        return validLayers[layer.getIndex()];
4755
 
        }
4756
 
 
4757
 
        /**
4758
 
         * Method to determine whether layer "layer" interacts in any way with an arc of type "ap".
4759
 
         * If not, returns FALSE.
4760
 
         */
4761
 
        private boolean checkLayerWithArc(Layer layer, ArcProto ap)
4762
 
        {
4763
 
                buildLayerInteractions(ap.getTechnology());
4764
 
 
4765
 
                // find this node in the table
4766
 
                boolean [] validLayers = layersInterArcs.get(ap);
4767
 
                if (validLayers == null) return false;
4768
 
                return validLayers[layer.getIndex()];
4769
 
        }
4770
 
 
4771
4014
        /**
4772
4015
         * Method to recursively scan cell "cell" (transformed with "trans") searching
4773
4016
         * for DRC Exclusion nodes.  Each node is added to the global list "exclusionList".
4802
4045
                                accumulateExclusion((Cell)np);
4803
4046
                        }
4804
4047
                };
4805
 
        exclusionMap.put(cell, area);
 
4048
        reportInfo.exclusionMap.put(cell, area);
4806
4049
        }
4807
4050
 
4808
 
    /* Adds details about an error to the error list */
4809
 
        private void reportError(DRC.DRCErrorType errorType, String msg,
4810
 
                                 Cell cell, double limit, double actual, String rule,
4811
 
                                 PolyBase poly1, Geometric geom1, Layer layer1,
4812
 
                                 PolyBase poly2, Geometric geom2, Layer layer2)
4813
 
    {
4814
 
        DRC.createDRCErrorLogger(errorLogger, exclusionMap, errorTypeSearch, interactiveLogger,
4815
 
                errorType, msg, cell, limit, actual, rule, poly1, geom1, layer1,
4816
 
                poly2, geom2, layer2);
4817
 
    }
4818
 
 
4819
4051
    /**************************************************************************************************************
4820
4052
         *  QuickAreaEnumerator abstract class
4821
4053
         **************************************************************************************************************/