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");
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).
101
private static class CheckInst
107
89
private HashMap<NodeInst,CheckInst> checkInsts = null;
111
* The CheckProto object is placed on every cell and is used only temporarily
112
* to number the instances.
114
private static class CheckProto
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;
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
143
105
this.mergeMode = mode;
147
* The InstanceInter object records interactions between two cell instances and prevents checking
148
* them multiple times.
150
private static class InstanceInter
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;
159
108
private List<InstanceInter> instanceInteractionList = new ArrayList<InstanceInter>();
163
* The DRCExclusion object lists areas where Generic:DRC-Nodes exist to ignore errors.
165
private Map<Cell,Area> exclusionMap = new HashMap<Cell,Area>();
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;
185
/* for figuring out which layers are valid for DRC */
186
private Technology layersValidTech = null;
187
private boolean [] layersValid;
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;
119
// /* for figuring out which layers are valid for DRC */
120
// To speed up the layer process
121
private ValidationLayers validLayers;
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;
158
// if checking specific instances, adjust options and processor count
159
int count = (geomsToCheck != null) ? geomsToCheck.length : 0;
161
reportInfo = new DRC.ReportInfo(errorLog, tech, (count > 0));
162
ErrorLogger errorLogger = errorLog;
231
activeSpacingBits = DRC.getActiveBits(tech);
232
System.out.println("Running DRC with " + DRC.explainBits(activeSpacingBits));
234
// caching memory setting
235
inMemory = DRC.isDatesStoredInMemory();
236
interactiveLogger = DRC.isInteractiveLoggingOn();
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));
241
167
// Nothing to check for this particular technology
242
168
if (rules == null || rules.getNumberOfRules() == 0) return errorLogger;
244
// get the current DRC options
245
errorTypeSearch = DRC.getErrorType();
246
ignoreCenterCuts = DRC.isIgnoreCenterCuts();
247
170
topCell = cell; /* Especially important for minArea checking */
249
// if checking specific instances, adjust options and processor count
250
int count = (geomsToCheck != null) ? geomsToCheck.length : 0;
253
errorTypeSearch = DRC.DRCCheckMode.ERROR_CHECK_CELL;
256
172
// cache valid layers for this technology
257
cacheValidLayers(tech);
258
buildLayerInteractions(tech);
173
validLayers = new ValidationLayers(reportInfo.errorLogger, topCell, rules);
260
175
// clean out the cache of instances
261
176
instanceInteractionList.clear();
263
178
// determine maximum DRC interaction distance
264
worstInteractionDistance = DRC.getWorstSpacingDistance(tech, -1);
179
// worstInteractionDistance = DRC.getWorstSpacingDistance(tech, -1);
266
181
// determine if min area must be checked (if any layer got valid data)
267
182
minAreaLayerMap.clear();
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)
468
prevErrors = errorLogger.getNumErrors();
469
prevWarns = errorLogger.getNumWarnings();
383
prevErrors = reportInfo.errorLogger.getNumErrors();
384
prevWarns = reportInfo.errorLogger.getNumWarnings();
472
387
cellsMap.put(cell, cell);
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"))
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;
483
398
// first check all subcells
484
399
boolean allSubCellsStillOK = true;
485
Area area = exclusionMap.get(cell);
400
Area area = reportInfo.exclusionMap.get(cell);
487
402
for(Iterator<NodeInst> it = cell.getNodes(); it.hasNext(); )
489
NodeInst ni = it.next();
404
if (job != null && job.checkAbort()) return -1;
406
NodeInst ni = it.next();
490
407
NodeProto np = ni.getProto();
491
408
if (!ni.isCellInstance()) continue;
582
501
checkNodeInst(ni, globalIndex);
585
totalSpacingMsgFound++;
586
if (errorTypeSearch == DRC.DRCCheckMode.ERROR_CHECK_CELL) break;
504
reportInfo.totalSpacingMsgFound++;
505
if (reportInfo.errorTypeSearch == DRC.DRCCheckMode.ERROR_CHECK_CELL) break;
589
508
Technology cellTech = cell.getTechnology();
590
for(Iterator it = cell.getArcs(); it.hasNext(); )
509
for(Iterator<ArcInst> it = cell.getArcs(); it.hasNext(); )
592
ArcInst ai = (ArcInst)it.next();
511
if (job != null && job.checkAbort()) return -1;
513
ArcInst ai = it.next();
593
514
Technology tech = ai.getProto().getTechnology();
594
515
if (tech != cellTech)
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);
599
521
if (bounds != null)
756
678
nodesMap.put(ni, ni);
758
if (np instanceof PrimitiveNode && DRC.isForbiddenNode(((PrimitiveNode)np).getPrimNodeIndexInTech(), -1,
759
DRCTemplate.DRCRuleType.FORBIDDEN, tech))
680
if (DRC.checkNodeAgainstCombinationRules(ni, reportInfo))
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;
685
// if (np instanceof PrimitiveNode)
687
// DRCTemplate forbidRule =
688
// DRC.isForbiddenNode(((PrimitiveNode)np).getPrimNodeIndexInTech(), -1,
689
// DRCTemplate.DRCRuleType.FORBIDDEN, tech);
690
// if (forbidRule != null)
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;
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);
772
706
// examine the polygons on this node
773
707
for(int j=0; j<tot; j++)
793
727
ret = checkResolution(poly, cell, ni);
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;
800
734
// determine network for this polygon
801
735
int netNumber = getDRCNetNumber(netlist, poly.getPort(), ni, globalIndex);
803
ret = badBox(poly, layer, netNumber, tech, ni, trans, cell, globalIndex);
737
ret = badBox(poly, layer, netNumber, tech, ni, trans, cell, globalIndex, multiCutData);
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;
809
743
ret = checkMinWidth(ni, layer, poly, tot==1);
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;
815
749
// Check select over transistor poly
827
761
// if (errorTypeSearch == DRC.DRCCheckMode.ERROR_CHECK_CELL) return true;
828
762
// errorsFound = true;
830
if (tech == layersValidTech && !layersValid[layer.getIndex()])
764
if (validLayers.isABadLayer(tech, layer.getIndex()))
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;
839
773
// check node for minimum size
840
PrimitiveNode.NodeSizeRule sizeRule = DRC.getMinSize(np);
841
if (sizeRule != null)
843
if (DBMath.isGreaterThan(sizeRule.getWidth(), ni.getXSize()) ||
844
DBMath.isGreaterThan(sizeRule.getHeight(), ni.getYSize()))
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())
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();
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();
863
reportError(DRC.DRCErrorType.MINSIZEERROR, msg, cell, minSize, actual, sizeRule.getRuleName(),
864
null, ni, null, null, null, null);
774
if (DRC.checkNodeSize(ni, cell, reportInfo))
868
777
return errorsFound;
872
* Method to check which combination of OD2 layers are allowed
874
* @return true if there is an invalid combination of OD2 layers
876
private boolean checkOD2Combination(Technology tech, NodeInst ni, Layer layer)
878
int funExtras = layer.getFunctionExtras();
879
boolean notOk = false;
881
if (layer.getFunction().isImplant() && (funExtras&Layer.Function.THICK) != 0)
883
// Only stores first node found
884
od2Layers.put(layer, ni);
886
// More than one type used.
887
if (od2Layers.size() != 1)
889
for (Map.Entry<Layer,NodeInst> e : od2Layers.entrySet())
891
Layer lay1 = e.getKey();
892
if (lay1 == layer) continue;
893
if (DRC.isForbiddenNode(lay1.getIndex(), layer.getIndex(), DRCTemplate.DRCRuleType.FORBIDDEN, tech))
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);
909
781
* Method to check the design rules about arcinst "ai".
910
782
* Returns true if errors were found.
927
799
// if (coverByExclusion(ai))
928
800
// return false; // no error
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();
807
if (!DBMath.areEquals(from.getX(), to.getX()) && !DBMath.areEquals(from.getY(), to.getY()))
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;
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;
935
819
// Check resolution before cropping the
936
820
for(Poly poly : arcInstPolyList)
1629
1519
// Checking A-B distance
1630
1520
double actual = lowB.distance(highB);
1631
if (actual != 0 && DBMath.isGreaterThan(minWidth, actual) &&
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))
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;
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();
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));
1664
1557
// Looking for two corners not inside bounding boxes A and B
1665
1558
if (pd == 0) // flat bounding box
1799
1651
if (isBox1 != null && isBox2 != null)
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
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))
1659
overlap = DBMath.isLessThan(pd, 0);
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))
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;
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);
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));
1875
if (pdx == 0 && pdy == 0)
1728
if (DBMath.areEquals(pdx, 0) && DBMath.areEquals(pdy, 0))
1876
1729
pd = 0; // they are touching!!
1879
1732
// They are overlapping if pdx < 0 && pdy < 0
1880
pd = DBMath.round(Math.max(pdx, pdy));
1733
pd = (Math.max(pdx, pdy));
1882
if (pd < theRule.getValue(0) && pd > 0)
1735
if (pd < theRule.getValue(0) && DBMath.isGreaterThan(pd, 0))
1884
1737
pd = poly1.separation(poly2);
2446
2300
/*********************************** QUICK DRC SUPPORT ***********************************/
2449
* Method to determine if neighbor would help to cover the minimum conditions
2450
* @return true if error was found (not warning)
2452
private boolean checkExtensionWithNeighbors(Cell cell, Geometric geom, Poly poly, Layer layer, Rectangle2D bounds,
2453
DRCTemplate minWidthRule, int dir, boolean onlyOne, boolean reportError)
2456
Point2D left1, left2, left3, right1, right2, right3;
2457
//if (bounds.getWidth() < minWidthRule.value)
2460
// potential problem along X
2463
actual = bounds.getWidth();
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());
2475
actual = bounds.getHeight();
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);
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);
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;
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;
2505
DRC.DRCErrorType errorType = DRC.DRCErrorType.MINWIDTHERROR;
2506
String extraMsg = msg;
2507
String rule = minWidthRule.ruleName;
2510
if (overlapLayer) extraMsg = " but covered by other layer";
2511
errorType = DRC.DRCErrorType.ZEROLENGTHARCWARN;
2516
reportError(errorType, extraMsg, cell, minWidthRule.getValue(0), actual, rule,
2517
(onlyOne) ? null : poly, geom, layer, null, null, null);
2518
return !overlapLayer;
2522
2303
* Function to look for conditional layers that will 100% overlap with the given region.
2307
* @param ignoreCenterCuts
2528
2308
* @return true if conditional layers are found for the test points
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)
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,
2328
boolean found = DRC.lookForLayerCoverage(geom, poly, null, null, cell, layer, DBMath.MATID, bnd, pt1, pt2, pt3,
2329
pointsFound, true, null, false, ignoreCenterCuts);
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,
2336
found = DRC.lookForLayerCoverage(geom, poly, null, null, cell, layer, DBMath.MATID, bnd, pt1, pt2, null,
2337
pointsFound, true, null, false, ignoreCenterCuts);
2593
2374
for (String la : layers)
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);
2598
2379
break; // no need to check the next layer
2600
2381
// If condition is met then the new rule applied.
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;
2608
private boolean checkMinWidthInternal(Geometric geom, Layer layer, Poly poly, boolean onlyOne,
2609
DRCTemplate minWidthRule, boolean reportError)
2611
Cell cell = geom.getParent();
2612
if (minWidthRule == null) return false;
2614
double minWidthValue = minWidthRule.getValue(0);
2615
// simpler analysis if manhattan
2616
Rectangle2D bounds = poly.getBox();
2619
boolean tooSmallWidth = DBMath.isGreaterThan(minWidthValue, bounds.getWidth());
2620
boolean tooSmallHeight = DBMath.isGreaterThan(minWidthValue, bounds.getHeight());
2621
if (!tooSmallWidth && !tooSmallHeight) return false;
2623
boolean foundError = false;
2624
if (tooSmallWidth && checkExtensionWithNeighbors(cell, geom, poly, layer, bounds, minWidthRule,
2625
0, onlyOne, reportError))
2627
if (tooSmallHeight && checkExtensionWithNeighbors(cell, geom, poly, layer, bounds, minWidthRule,
2628
1, onlyOne, reportError))
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;
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)
2645
reportError(DRC.DRCErrorType.MINWIDTHERROR, null, cell, minWidthValue, actual, minWidthRule.ruleName,
2646
(onlyOne) ? null : poly, geom, layer, null, null, null);
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++)
2656
if (i == 0) from = points[count-1]; else
2658
Point2D to = points[i];
2659
if (from.equals(to)) continue;
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++)
2666
if (j == i) continue;
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))
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;
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));
2691
if (actual < minWidthValue)
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)))
2698
reportError(DRC.DRCErrorType.MINWIDTHERROR, null, cell, minWidthValue,
2699
actual, minWidthRule.ruleName, (onlyOne) ? null : poly, geom, layer, null, null, null);
2702
reportError(DRC.DRCErrorType.NOTCHERROR, null, cell, minWidthValue,
2703
actual, minWidthRule.ruleName, (onlyOne) ? null : poly, geom, layer, poly, geom, layer);
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)
2716
2392
// int errorFound = 0;
2834
2510
if (bnd.getWidth() < spacingRule.getValue(0))
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);
2840
2516
if (bnd.getHeight() < spacingRule.getValue(1))
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);
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.
3127
// private boolean lookForPoints(Point2D pt1, Point2D pt2, Layer layer, Cell cell, boolean needBoth)
3129
// Point2D pt3 = new Point2D.Double((pt1.getX()+pt2.getX()) / 2, (pt1.getY()+pt2.getY()) / 2);
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);
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);
3143
// if (allFound) return true;
3146
// if (pointsFound[0] || pointsFound[1]) return true;
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
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);
3177
2824
return allFound;
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.
3186
private boolean lookForLayer(Poly thisPoly, Cell cell, Layer layer, AffineTransform moreTrans,
3187
Rectangle2D bounds, Point2D pt1, Point2D pt2, Point2D pt3, boolean [] pointsFound)
3190
boolean skip = false;
3191
Rectangle2D newBounds = new Rectangle2D.Double(); // sept 30
3193
for(Iterator<RTBounds> it = cell.searchIterator(bounds); it.hasNext(); )
3195
RTBounds g = it.next();
3196
if (g instanceof NodeInst)
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())
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);
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))
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++)
3224
Poly poly = layerLookPolyList[i];
3226
if (!tech.sameLayer(poly.getLayer(), layer)) continue;
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);
3239
// No need of checking rest of the layers?
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++)
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);
3260
// No need of checking rest of the layers
3265
for (j = 0; j < pointsFound.length && pointsFound[j]; j++);
3266
if (j == pointsFound.length)
3268
System.out.println("When?");
3272
if (skip) System.out.println("This case in lookForLayerNew antes");
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.
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.
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,
3393
Rectangle2D newBounds = new Rectangle2D.Double(); // Sept 30
3395
for(Iterator<RTBounds> it = cell.searchIterator(bounds); it.hasNext(); )
3397
RTBounds g = it.next();
3399
// You can't skip the same geometry otherwise layers in the same Geometric won't
3401
// if (ignoreSameGeometry && (g == geo1 || g == geo2))
3404
// I can't skip geometries to exclude from the search
3405
if (g instanceof NodeInst)
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())
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);
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))
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++)
3435
Poly poly = layerLookPolyList[i];
3436
if (!tech.sameLayer(poly.getLayer(), layer)) continue;
3438
// Should be the transform before?
3439
poly.transform(bound);
3441
if (poly1 != null && !overlap && poly.polySame(poly1))
3443
if (poly2 != null && !overlap && poly.polySame(poly2))
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)
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++)
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
3475
for (j = 0; j < pointsFound.length && pointsFound[j]; j++);
3476
if (j == pointsFound.length)
3478
assert(false); // test when otherwise the calculation is useless! System.out.println("When?");
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)
3523
2972
String ruleName = (rule != null) ? rule.ruleName : "for contacts";
3524
2973
if (DBMath.isGreaterThan(rect.getWidth(), cutSizeX))
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;
3531
2980
if (DBMath.isGreaterThan(rect.getHeight(), cutSizeY))
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;
4454
* Method to see if polygons in "pList" (describing arc "ai") should be cropped against a
4455
* connecting transistor. Crops the polygon if so.
4457
private void cropActiveArc(ArcInst ai, Poly [] pList)
4459
// look for an active layer in this arc
4460
int tot = pList.length;
4462
for(int j=0; j<tot; j++)
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; }
4470
if (diffPoly < 0) return;
4471
Poly poly = pList[diffPoly];
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());
4478
// search for adjoining transistor in the cell
4479
boolean cropped = false;
4480
boolean halved = false;
4481
for(int i=0; i<2; i++)
4483
PortInst pi = ai.getPortInst(i);
4484
NodeInst ni = pi.getNodeInst();
4485
if (!ni.isFET()) continue;
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++)
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);
4507
// remove this polygon from consideration
4508
poly.setLayer(null);
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;
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.
4552
* Method to determine which layers in a Technology are valid.
4554
private void cacheValidLayers(Technology tech)
4556
if (tech == null) return;
4557
if (layersValidTech == tech) return;
4559
layersValidTech = tech;
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(); )
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++)
4573
Layer layer = layers[i].getLayer();
4574
layersValid[layer.getIndex()] = true;
4577
for(Iterator it = tech.getArcs(); it.hasNext(); )
4579
ArcProto ap = (ArcProto)it.next();
4580
if (ap.isNotUsed()) continue;
4581
for (Iterator<Layer> lIt = ap.getLayerIterator(); lIt.hasNext(); )
4583
Layer layer = lIt.next();
4584
layersValid[layer.getIndex()] = true;
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
4668
4011
return nets[globalIndex].intValue();
4671
/***************** LAYER INTERACTIONS ******************/
4674
* Method to build the internal data structures that tell which layers interact with
4675
* which primitive nodes in technology "tech".
4677
private void buildLayerInteractions(Technology tech)
4679
Technology old = layerInterTech;
4680
if (layerInterTech == tech) return;
4682
layerInterTech = tech;
4683
int numLayers = tech.getNumLayers();
4685
// build the node table
4686
if (layersInterNodes != null && old != null && job != null)
4688
errorLogger.logWarning("Switching from '" + old.getTechName() +
4689
"' to '" + tech.getTechName() + "' in DRC process. Check for non desired nodes in ",
4693
layersInterNodes = new HashMap<PrimitiveNode, boolean[]>();
4694
for(Iterator<PrimitiveNode> it = tech.getNodes(); it.hasNext(); )
4696
PrimitiveNode np = it.next();
4697
if (np.isNotUsed()) continue;
4698
boolean [] layersInNode = new boolean[numLayers];
4699
Arrays.fill(layersInNode, false);
4701
Technology.NodeLayer [] layers = np.getLayers();
4702
Technology.NodeLayer [] eLayers = np.getElectricalLayers();
4703
if (eLayers != null) layers = eLayers;
4704
for(Technology.NodeLayer l : layers)
4706
Layer layer = l.getLayer();
4707
if (layer.isNonElectrical())
4708
continue; // such as pseudo
4709
for(Iterator<Layer> lIt = tech.getLayers(); lIt.hasNext(); )
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;
4718
layersInterNodes.put(np, layersInNode);
4721
// build the arc table
4722
layersInterArcs = new HashMap<ArcProto, boolean[]>();
4723
for(Iterator<ArcProto> it = tech.getArcs(); it.hasNext(); )
4725
ArcProto ap = it.next();
4726
boolean [] layersInArc = new boolean[numLayers];
4727
Arrays.fill(layersInArc, false);
4729
for(Iterator<Layer> alIt = ap.getLayerIterator(); alIt.hasNext(); )
4731
Layer layer = alIt.next();
4732
for(Iterator<Layer> lIt = tech.getLayers(); lIt.hasNext(); )
4734
Layer oLayer = lIt.next();
4735
if (DRC.isAnySpacingRule(layer, oLayer))
4736
layersInArc[oLayer.getIndex()] = true;
4739
layersInterArcs.put(ap, layersInArc);
4744
* Method to determine whether layer "layer" interacts in any way with a node of type "np".
4745
* If not, returns FALSE.
4747
private boolean checkLayerWithNode(Layer layer, NodeProto np)
4749
buildLayerInteractions(np.getTechnology());
4751
// find this node in the table
4752
boolean [] validLayers = layersInterNodes.get(np);
4753
if (validLayers == null) return false;
4754
return validLayers[layer.getIndex()];
4758
* Method to determine whether layer "layer" interacts in any way with an arc of type "ap".
4759
* If not, returns FALSE.
4761
private boolean checkLayerWithArc(Layer layer, ArcProto ap)
4763
buildLayerInteractions(ap.getTechnology());
4765
// find this node in the table
4766
boolean [] validLayers = layersInterArcs.get(ap);
4767
if (validLayers == null) return false;
4768
return validLayers[layer.getIndex()];
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);
4805
exclusionMap.put(cell, area);
4048
reportInfo.exclusionMap.put(cell, area);
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)
4814
DRC.createDRCErrorLogger(errorLogger, exclusionMap, errorTypeSearch, interactiveLogger,
4815
errorType, msg, cell, limit, actual, rule, poly1, geom1, layer1,
4816
poly2, geom2, layer2);
4819
4051
/**************************************************************************************************************
4820
4052
* QuickAreaEnumerator abstract class
4821
4053
**************************************************************************************************************/