82
81
return thisLayerFunction;
85
* Method to see if polygons in "pList" (describing arc "ai") should be cropped against a
86
* connecting transistor. Crops the polygon if so.
88
static void cropActiveArc(ArcInst ai, boolean ignoreCenterCuts, Poly [] pList)
90
// look for an active layer in this arc
91
int tot = pList.length;
93
for(int j=0; j<tot; j++)
96
Layer layer = poly.getLayer();
97
if (layer == null) continue;
98
Layer.Function fun = layer.getFunction();
99
if (fun.isDiff()) { diffPoly = j; break; }
101
if (diffPoly < 0) return;
102
Poly poly = pList[diffPoly];
105
Rectangle2D polyBounds = poly.getBox();
106
if (polyBounds == null) return;
107
polyBounds = new Rectangle2D.Double(polyBounds.getMinX(), polyBounds.getMinY(), polyBounds.getWidth(), polyBounds.getHeight());
109
// search for adjoining transistor in the cell
110
boolean cropped = false;
111
boolean halved = false;
112
for(int i=0; i<2; i++)
114
PortInst pi = ai.getPortInst(i);
115
NodeInst ni = pi.getNodeInst();
116
if (!ni.getFunction().isFET()) continue;
118
// crop the arc against this transistor
119
AffineTransform trans = ni.rotateOut();
120
Technology tech = ni.getProto().getTechnology();
121
Poly [] activeCropPolyList = tech.getShapeOfNode(ni, false, ignoreCenterCuts, null);
122
int nTot = activeCropPolyList.length;
123
for(int k=0; k<nTot; k++)
125
Poly nPoly = activeCropPolyList[k];
126
if (nPoly.getLayer() != poly.getLayer()) continue;
127
nPoly.transform(trans);
128
Rectangle2D nPolyBounds = nPoly.getBox();
129
if (nPolyBounds == null) continue;
130
// @TODO Why only one half is half crop?
131
// Should I change cropBox by cropBoxComplete?
132
int result = (halved) ?
133
Poly.cropBox(polyBounds, nPolyBounds) :
134
Poly.halfCropBox(polyBounds, nPolyBounds);
138
// remove this polygon from consideration
148
Poly.Type style = poly.getStyle();
149
Layer layer = poly.getLayer();
150
poly = new Poly(polyBounds);
151
poly.setStyle(style);
152
poly.setLayer(layer);
153
pList[diffPoly] = poly;
158
* Method to examine cell "cell" in the area (lx<=X<=hx, ly<=Y<=hy) for objects
159
* on layer "layer". Apply transformation "moreTrans" to the objects. If polygons are
160
* found at (xf1,yf1) or (xf2,yf2) or (xf3,yf3) then sets "p1found/p2found/p3found" to 1.
161
* If poly1 or poly2 is not null, ignore geometries that are identical to them.
162
* If all locations are found, returns true.
164
static boolean lookForLayerCoverage(Geometric geo1, Poly poly1, Geometric geo2, Poly poly2, Cell cell,
165
Layer layer, AffineTransform moreTrans, Rectangle2D bounds,
166
Point2D pt1, Point2D pt2, Point2D pt3, boolean[] pointsFound,
167
boolean overlap, Layer.Function.Set layerFunction, boolean ignoreSameGeometry,
168
boolean ignoreCenterCuts)
171
Rectangle2D newBounds = new Rectangle2D.Double(); // Sept 30
173
for (Iterator<RTBounds> it = cell.searchIterator(bounds); it.hasNext();)
175
RTBounds g = it.next();
177
// You can't skip the same geometry otherwise layers in the same Geometric won't
179
// But it is necessary while testing flat geometries... in minWidthInternal
180
if (ignoreSameGeometry && (g == geo1 || g == geo2))
183
// I can't skip geometries to exclude from the search
184
if (g instanceof NodeInst)
186
NodeInst ni = (NodeInst) g;
187
if (NodeInst.isSpecialNode(ni))
188
continue; // Nov 16, no need for checking pins or other special nodes;
189
if (ni.isCellInstance())
191
// compute bounding area inside of sub-cell
192
AffineTransform rotI = ni.rotateIn();
193
AffineTransform transI = ni.translateIn();
194
rotI.preConcatenate(transI);
195
newBounds.setRect(bounds);
196
DBMath.transformRect(newBounds, rotI);
198
// compute new matrix for sub-cell examination
199
AffineTransform trans = ni.translateOut(ni.rotateOut());
200
trans.preConcatenate(moreTrans);
201
if (lookForLayerCoverage(geo1, poly1, geo2, poly2, (Cell) ni.getProto(), layer, trans, newBounds,
202
pt1, pt2, pt3, pointsFound, overlap, layerFunction, false, ignoreCenterCuts))
206
AffineTransform bound = ni.rotateOut();
207
bound.preConcatenate(moreTrans);
208
Technology tech = ni.getProto().getTechnology();
209
// I have to ask for electrical layers otherwise it will retrieve one polygon for polysilicon
210
// and poly.polySame(poly1) will never be true. CONTRADICTION!
211
Poly[] layerLookPolyList = tech.getShapeOfNode(ni, false, ignoreCenterCuts, layerFunction); // consistent change!);
212
int tot = layerLookPolyList.length;
213
for (int i = 0; i < tot; i++)
215
Poly poly = layerLookPolyList[i];
216
// sameLayer test required to check if Active layer is not identical to thick active layer
217
if (!tech.sameLayer(poly.getLayer(), layer))
222
// Should be the transform before?
223
poly.transform(bound);
225
if (poly1 != null && !overlap && poly.polySame(poly1))
227
if (poly2 != null && !overlap && poly.polySame(poly2))
230
if (!pointsFound[0] && poly.isInside(pt1))
231
pointsFound[0] = true; // @TODO Should still evaluate isInside if pointsFound[i] is already valid?
232
if (!pointsFound[1] && poly.isInside(pt2)) pointsFound[1] = true;
233
if (pt3 != null && !pointsFound[2] && poly.isInside(pt3)) pointsFound[2] = true;
234
for (j = 0; j < pointsFound.length && pointsFound[j]; j++) ;
235
if (j == pointsFound.length) return true;
236
// No need of checking rest of the layers
237
break; // assuming only 1 polygon per layer (non-electrical)
241
ArcInst ai = (ArcInst) g;
242
Technology tech = ai.getProto().getTechnology();
243
Poly[] layerLookPolyList = tech.getShapeOfArc(ai, layerFunction); // consistent change!);
244
int tot = layerLookPolyList.length;
245
for (int i = 0; i < tot; i++)
247
Poly poly = layerLookPolyList[i];
248
// sameLayer test required to check if Active layer is not identical to thich actice layer
249
if (!tech.sameLayer(poly.getLayer(), layer))
253
poly.transform(moreTrans); // @TODO Should still evaluate isInside if pointsFound[i] is already valid?
254
if (!pointsFound[0] && poly.isInside(pt1)) pointsFound[0] = true;
255
if (!pointsFound[1] && poly.isInside(pt2)) pointsFound[1] = true;
256
if (pt3 != null && !pointsFound[2] && poly.isInside(pt3)) pointsFound[2] = true;
257
for (j = 0; j < pointsFound.length && pointsFound[j]; j++) ;
258
if (j == pointsFound.length) return true;
259
// No need of checking rest of the layers
264
for (j = 0; j < pointsFound.length && pointsFound[j]; j++) ;
265
if (j == pointsFound.length)
267
assert (false); // test when otherwise the calculation is useless! System.out.println("When?");
275
* Method to determine if neighbor would help to cover the minimum conditions
277
* @return true if error was found (not warning)
279
static boolean checkExtensionWithNeighbors(Cell cell, Geometric geom, Poly poly, Layer layer, Rectangle2D bounds,
280
DRCTemplate minWidthRule, int dir, boolean onlyOne, boolean reportError,
281
Layer.Function.Set layerFunction, ReportInfo reportInfo)
284
Point2D left1, left2, left3, right1, right2, right3;
285
//if (bounds.getWidth() < minWidthRule.value)
288
// potential problem along X
291
actual = bounds.getWidth();
293
double leftW = bounds.getMinX() - TINYDELTA;
294
left1 = new Point2D.Double(leftW, bounds.getMinY());
295
left2 = new Point2D.Double(leftW, bounds.getMaxY());
296
left3 = new Point2D.Double(leftW, bounds.getCenterY());
297
double rightW = bounds.getMaxX() + TINYDELTA;
298
right1 = new Point2D.Double(rightW, bounds.getMinY());
299
right2 = new Point2D.Double(rightW, bounds.getMaxY());
300
right3 = new Point2D.Double(rightW, bounds.getCenterY());
303
actual = bounds.getHeight();
305
double leftH = bounds.getMinY() - TINYDELTA;
306
left1 = new Point2D.Double(bounds.getMinX(), leftH);
307
left2 = new Point2D.Double(bounds.getMaxX(), leftH);
308
left3 = new Point2D.Double(bounds.getCenterX(), leftH);
309
double rightH = bounds.getMaxY() + TINYDELTA;
310
right1 = new Point2D.Double(bounds.getMinX(), rightH);
311
right2 = new Point2D.Double(bounds.getMaxX(), rightH);
312
right3 = new Point2D.Double(bounds.getCenterX(), rightH);
314
// see if there is more of this layer adjoining on either side
315
boolean[] pointsFound = new boolean[3];
316
pointsFound[0] = pointsFound[1] = pointsFound[2] = false;
317
Rectangle2D newBounds = new Rectangle2D.Double(bounds.getMinX() - TINYDELTA, bounds.getMinY() - TINYDELTA,
318
bounds.getWidth() + TINYDELTA * 2, bounds.getHeight() + TINYDELTA * 2);
319
boolean zeroWide = (bounds.getWidth() == 0 || bounds.getHeight() == 0);
321
boolean overlapLayer = lookForLayer(poly, cell, layer, DBMath.MATID, newBounds,
322
left1, left2, left3, pointsFound, layerFunction, reportInfo.ignoreCenterCuts); //) return false;
323
// if (overlapLayer && !zeroWide) return false;
324
if (overlapLayer) return false;
326
// Try the other corner
327
pointsFound[0] = pointsFound[1] = pointsFound[2] = false;
328
overlapLayer = lookForLayer(poly, cell, layer, DBMath.MATID, newBounds,
329
right1, right2, right3, pointsFound, layerFunction, reportInfo.ignoreCenterCuts); //) return false;
330
// if (overlapLayer && !zeroWide) return false;
331
if (overlapLayer) return false;
333
DRCErrorType errorType = DRCErrorType.MINWIDTHERROR;
334
String extraMsg = msg;
335
String rule = minWidthRule.ruleName;
337
// Only when the flat element is fully covered send the warning
338
// otherwise it is considered an error.
339
if (zeroWide && overlapLayer)
341
extraMsg = " but covered by other layer";
342
errorType = DRCErrorType.ZEROLENGTHARCWARN;
347
createDRCErrorLogger(reportInfo, errorType, extraMsg, cell, minWidthRule.getValue(0), actual, rule,
348
(onlyOne) ? null : poly, geom, layer, null, null, null);
349
return !overlapLayer;
353
* Method to examine cell "cell" in the area (lx<=X<=hx, ly<=Y<=hy) for objects
354
* on layer "layer". Apply transformation "moreTrans" to the objects. If polygons are
355
* found at (xf1,yf1) or (xf2,yf2) or (xf3,yf3) then sets "p1found/p2found/p3found" to 1.
356
* If all locations are found, returns true.
358
static boolean lookForLayer(Poly thisPoly, Cell cell, Layer layer, AffineTransform moreTrans,
359
Rectangle2D bounds, Point2D pt1, Point2D pt2, Point2D pt3, boolean[] pointsFound,
360
Layer.Function.Set layerFunction, boolean ignoreCenterCuts)
363
boolean skip = false;
364
Rectangle2D newBounds = new Rectangle2D.Double(); // sept 30
366
for (Iterator<RTBounds> it = cell.searchIterator(bounds); it.hasNext();)
368
RTBounds g = it.next();
369
if (g instanceof NodeInst)
371
NodeInst ni = (NodeInst) g;
372
if (NodeInst.isSpecialNode(ni))
373
continue; // Nov 16, no need for checking pins or other special nodes;
374
if (ni.isCellInstance())
376
// compute bounding area inside of sub-cell
377
AffineTransform rotI = ni.rotateIn();
378
AffineTransform transI = ni.translateIn();
379
rotI.preConcatenate(transI);
380
newBounds.setRect(bounds);
381
DBMath.transformRect(newBounds, rotI);
383
// compute new matrix for sub-cell examination
384
AffineTransform trans = ni.translateOut(ni.rotateOut());
385
trans.preConcatenate(moreTrans);
386
if (lookForLayer(thisPoly, (Cell) ni.getProto(), layer, trans, newBounds,
387
pt1, pt2, pt3, pointsFound, layerFunction, ignoreCenterCuts))
391
AffineTransform bound = ni.rotateOut();
392
bound.preConcatenate(moreTrans);
393
Technology tech = ni.getProto().getTechnology();
394
Poly[] layerLookPolyList = tech.getShapeOfNode(ni, false, ignoreCenterCuts, layerFunction); // consistent change!
395
// layerLookPolyList = tech.getShapeOfNode(ni, false, ignoreCenterCuts, null);
396
int tot = layerLookPolyList.length;
397
for (int i = 0; i < tot; i++)
399
Poly poly = layerLookPolyList[i];
400
// sameLayer test required to check if Active layer is not identical to thich actice layer
401
if (!tech.sameLayer(poly.getLayer(), layer))
406
if (thisPoly != null && poly.polySame(thisPoly)) continue;
407
poly.transform(bound);
408
if (poly.isInside(pt1)) pointsFound[0] = true;
409
if (poly.isInside(pt2)) pointsFound[1] = true;
410
if (pt3 != null && poly.isInside(pt3)) pointsFound[2] = true;
411
for (j = 0; j < pointsFound.length && pointsFound[j]; j++) ;
412
boolean newR = (j == pointsFound.length);
417
// No need of checking rest of the layers?
422
ArcInst ai = (ArcInst) g;
423
Technology tech = ai.getProto().getTechnology();
424
Poly[] layerLookPolyList = tech.getShapeOfArc(ai, layerFunction); // consistent change!);
425
int tot = layerLookPolyList.length;
426
for (int i = 0; i < tot; i++)
428
Poly poly = layerLookPolyList[i];
429
// sameLayer test required to check if Active layer is not identical to thich actice layer
430
if (!tech.sameLayer(poly.getLayer(), layer))
435
poly.transform(moreTrans);
436
if (poly.isInside(pt1)) pointsFound[0] = true;
437
if (poly.isInside(pt2)) pointsFound[1] = true;
438
if (pt3 != null && poly.isInside(pt3)) pointsFound[2] = true;
439
for (j = 0; j < pointsFound.length && pointsFound[j]; j++) ;
440
boolean newR = (j == pointsFound.length);
443
// No need of checking rest of the layers
448
for (j = 0; j < pointsFound.length && pointsFound[j]; j++) ;
449
if (j == pointsFound.length)
451
System.out.println("When?");
455
if (skip) System.out.println("This case in lookForLayerNew antes");
460
static boolean checkMinWidthInternal(Geometric geom, Layer layer, Poly poly, boolean onlyOne,
461
DRCTemplate minWidthRule, boolean reportError,
462
Layer.Function.Set layerFunction, ReportInfo reportInfo)
464
Cell cell = geom.getParent();
465
if (minWidthRule == null) return false;
467
double minWidthValue = minWidthRule.getValue(0);
468
// simpler analysis if manhattan
469
Rectangle2D bounds = poly.getBox();
471
// only in case of flat elements represented by a line
472
// most likely an flat arc, vertical or horizontal.
473
// It doesn't consider arbitrary angled lines.
474
// If bounds is null, it might have area if it is non-manhattan
475
boolean flatPoly = ((bounds == null && GenMath.doublesEqual(poly.getArea(), 0)));
478
Point2D [] points = poly.getPoints();
479
Point2D from = points[0];
480
Point2D to = points[1];
482
// Assuming it is a single segment the flat region
483
// looking for two distinct points
484
if (DBMath.areEquals(from, to))
486
boolean found = false;
487
for (int i = 2; i < points.length; i++)
489
if (!DBMath.areEquals(from, points[i]))
496
if (!found) // single segment where to == from
498
return false; // skipping this case.
502
Point2D center = new Point2D.Double((from.getX() + to.getX()) / 2, (from.getY() + to.getY()) / 2);
504
// looking if points around the overlapping area are inside another region
505
// to avoid the error
506
boolean [] pointsFound = new boolean[3];
507
pointsFound[0] = pointsFound[1] = pointsFound[2] = false;
508
boolean found = lookForLayerCoverage(geom, poly, null, null, cell, layer, DBMath.MATID, poly.getBounds2D(),
509
from, to, center, pointsFound, true, null, true, reportInfo.ignoreCenterCuts);
510
if (found) return false; // no error, flat element covered by othe elements.
513
createDRCErrorLogger(reportInfo, DRCErrorType.MINWIDTHERROR, null, cell, minWidthValue, 0, minWidthRule.ruleName,
514
(onlyOne) ? null : poly, geom, layer, null, null, null);
520
boolean tooSmallWidth = DBMath.isGreaterThan(minWidthValue, bounds.getWidth());
521
boolean tooSmallHeight = DBMath.isGreaterThan(minWidthValue, bounds.getHeight());
522
if (!tooSmallWidth && !tooSmallHeight) return false;
524
boolean foundError = false;
525
if (tooSmallWidth && checkExtensionWithNeighbors(cell, geom, poly, layer, bounds, minWidthRule,
526
0, onlyOne, reportError, layerFunction, reportInfo))
528
if (tooSmallHeight && checkExtensionWithNeighbors(cell, geom, poly, layer, bounds, minWidthRule,
529
1, onlyOne, reportError, layerFunction, reportInfo))
534
// nonmanhattan polygon: stop now if it has no size
535
Poly.Type style = poly.getStyle();
536
if (style != Poly.Type.FILLED && style != Poly.Type.CLOSED && style != Poly.Type.CROSSED &&
537
style != Poly.Type.OPENED && style != Poly.Type.OPENEDT1 && style != Poly.Type.OPENEDT2 &&
538
style != Poly.Type.OPENEDT3 && style != Poly.Type.VECTORS) return false;
540
// simple check of nonmanhattan polygon for minimum width
541
bounds = poly.getBounds2D();
542
double actual = Math.min(bounds.getWidth(), bounds.getHeight());
543
if (actual < minWidthValue)
546
createDRCErrorLogger(reportInfo, DRCErrorType.MINWIDTHERROR, null, cell, minWidthValue, actual, minWidthRule.ruleName,
547
(onlyOne) ? null : poly, geom, layer, null, null, null);
551
// check distance of each line's midpoint to perpendicular opposite point
552
Point2D[] points = poly.getPoints();
553
int count = points.length;
554
for (int i = 0; i < count; i++)
557
if (i == 0) from = points[count - 1];
559
from = points[i - 1];
560
Point2D to = points[i];
561
if (from.equals(to)) continue;
563
double ang = DBMath.figureAngleRadians(from, to);
564
Point2D center = new Point2D.Double((from.getX() + to.getX()) / 2, (from.getY() + to.getY()) / 2);
565
double perpang = ang + Math.PI / 2;
566
for (int j = 0; j < count; j++)
568
if (j == i) continue;
570
if (j == 0) oFrom = points[count - 1];
572
oFrom = points[j - 1];
573
Point2D oTo = points[j];
574
if (oFrom.equals(oTo)) continue;
575
double oAng = DBMath.figureAngleRadians(oFrom, oTo);
577
while (rAng > Math.PI) rAng -= Math.PI;
579
while (rOAng > Math.PI) rOAng -= Math.PI;
580
if (DBMath.doublesEqual(rAng, rOAng))
582
// lines are parallel: see if they are colinear
583
if (DBMath.isOnLine(from, to, oFrom)) continue;
584
if (DBMath.isOnLine(from, to, oTo)) continue;
585
if (DBMath.isOnLine(oFrom, oTo, from)) continue;
586
if (DBMath.isOnLine(oFrom, oTo, to)) continue;
588
Point2D inter = DBMath.intersectRadians(center, perpang, oFrom, oAng);
589
if (inter == null) continue;
590
if (inter.getX() < Math.min(oFrom.getX(), oTo.getX()) || inter.getX() > Math.max(oFrom.getX(), oTo.getX()))
592
if (inter.getY() < Math.min(oFrom.getY(), oTo.getY()) || inter.getY() > Math.max(oFrom.getY(), oTo.getY()))
594
double fdx = center.getX() - inter.getX();
595
double fdy = center.getY() - inter.getY();
596
actual = DBMath.round(Math.sqrt(fdx * fdx + fdy * fdy));
598
if (actual < minWidthValue)
602
// look between the points to see if it is minimum width or notch
603
if (poly.isInside(new Point2D.Double((center.getX() + inter.getX()) / 2, (center.getY() + inter.getY()) / 2)))
605
createDRCErrorLogger(reportInfo, DRCErrorType.MINWIDTHERROR, null, cell, minWidthValue,
606
actual, minWidthRule.ruleName, (onlyOne) ? null : poly, geom, layer, null, null, null);
609
createDRCErrorLogger(reportInfo, DRCErrorType.NOTCHERROR, null, cell, minWidthValue,
610
actual, minWidthRule.ruleName, (onlyOne) ? null : poly, geom, layer, poly, geom, layer);
621
* Method to determine if it is allowed to have both layers touching.
622
* special rule for allowing touching:
623
* the layers are the same and either:
624
* they connect and are *NOT* contact layers
626
* they don't connect and are implant layers (substrate/well)
631
* @return true if the layer may touch
633
static boolean mayTouch(Technology tech, boolean con, Layer layer1, Layer layer2)
635
boolean maytouch = false;
636
if (tech.sameLayer(layer1, layer2))
638
Layer.Function fun = layer1.getFunction();
641
if (!fun.isContact()) maytouch = true;
644
if (fun.isSubstrate()) maytouch = true;
645
// Special cases for thick actives
648
// Searching for THICK bit
649
int funExtras = layer1.getFunctionExtras();
650
if (fun.isDiff() && (funExtras&Layer.Function.THICK) != 0)
652
if (Job.LOCALDEBUGFLAG) System.out.println("Thick active found in Quick.checkDist");
662
* Method to check if a PrimitiveNode contains a layer that is forbidden in the current technology
663
* @param ni node to analyze
664
* @param reportInfo data for the report
665
* @return True if the node is forbidden
667
static boolean checkNodeAgainstCombinationRules(NodeInst ni, ReportInfo reportInfo)
669
Cell cell = ni.getParent();
670
NodeProto np = ni.getProto();
671
Technology tech = np.getTechnology();
672
if (np instanceof PrimitiveNode)
674
DRCTemplate forbidRule =
675
DRC.isForbiddenNode(((PrimitiveNode)np).getPrimNodeIndexInTech(), -1,
676
DRCTemplate.DRCRuleType.FORBIDDEN, tech);
677
if (forbidRule != null)
679
DRC.createDRCErrorLogger(reportInfo, DRC.DRCErrorType.FORBIDDEN, " is not allowed by selected foundry", cell,
680
-1, -1, forbidRule.ruleName, null, ni, null, null, null, null);
688
* Method to check which combination of OD2 layers are allowed
690
* @return true if there is an invalid combination of OD2 layers
692
static boolean checkOD2Combination(Technology tech, NodeInst ni, Layer layer, Map<Layer,NodeInst> od2Layers,
693
ReportInfo reportInfo)
695
int funExtras = layer.getFunctionExtras();
696
boolean notOk = false;
698
if (layer.getFunction().isImplant() && (funExtras&Layer.Function.THICK) != 0)
700
// Only stores first node found
701
od2Layers.put(layer, ni);
703
// More than one type used.
704
if (od2Layers.size() != 1)
706
for (Map.Entry<Layer,NodeInst> e : od2Layers.entrySet())
708
Layer lay1 = e.getKey();
709
if (lay1 == layer) continue;
710
DRCTemplate rule = isForbiddenNode(lay1.getIndex(), layer.getIndex(), DRCTemplate.DRCRuleType.FORBIDDEN, tech);
713
NodeInst node = e.getValue(); // od2Layers.get(lay1);
714
String message = "- combination of layers '" + layer.getName() + "' and '" + lay1.getName() + "' (in '" +
715
node.getParent().getName() + ":" + node.getName() +"') not allowed by selected foundry";
716
createDRCErrorLogger(reportInfo, DRCErrorType.FORBIDDEN, message, ni.getParent(),
717
-1, -1, rule.ruleName, null, ni, null, null, node, null);
85
727
/*********************************** QUICK DRC ERROR REPORTING ***********************************/
86
728
public static enum DRCErrorType
88
730
// the different types of errors
89
731
SPACINGERROR, MINWIDTHERROR, NOTCHERROR, MINSIZEERROR, BADLAYERERROR, LAYERSURROUNDERROR,
90
732
MINAREAERROR, ENCLOSEDAREAERROR, SURROUNDERROR, FORBIDDEN, RESOLUTION, CUTERROR, SLOTSIZEERROR,
91
// Different types of warnings
734
// Different types of warnings
92
735
ZEROLENGTHARCWARN, TECHMIXWARN
95
public static void createDRCErrorLogger(ErrorLogger errorLogger, Map<Cell, Area> exclusionMap,
96
DRCCheckMode errorTypeSearch, boolean interactiveLogger,
738
public static class ReportInfo
741
/** error type search */ DRC.DRCCheckMode errorTypeSearch;
742
/** minimum output grid resolution */ double minAllowedResolution;
743
/** true to ignore center cuts in large contacts. */ boolean ignoreCenterCuts = DRC.isIgnoreCenterCuts();;
744
/** maximum area to examine (the worst spacing rule). */ double worstInteractionDistance;
745
/** time stamp for numbering networks. */ int checkTimeStamp;
746
/** for numbering networks. */ int checkNetNumber;
747
/** total errors found in all threads. */ int totalSpacingMsgFound;
748
/** for logging errors */ ErrorLogger errorLogger;
749
/** for interactive error logging */ boolean interactiveLogger = DRC.isInteractiveLoggingOn();
750
/** to cache current extra bits */ int activeSpacingBits = 0;
751
Map<Cell, Area> exclusionMap = new HashMap<Cell,Area>(); // The DRCExclusion object lists areas where Generic:DRC-Nodes exist to ignore errors.
752
boolean inMemory = DRC.isDatesStoredInMemory();
754
public ReportInfo(ErrorLogger eL, Technology tech, boolean specificGeoms)
757
activeSpacingBits = DRC.getActiveBits(tech);
758
worstInteractionDistance = DRC.getWorstSpacingDistance(tech, -1);
759
// minimim resolution different from zero if flag is on otherwise stays at zero (default)
760
minAllowedResolution = tech.getResolution();
762
errorTypeSearch = DRC.getErrorType();
765
errorTypeSearch = DRC.DRCCheckMode.ERROR_CHECK_CELL;
770
public static void createDRCErrorLogger(ReportInfo reportInfo,
97
771
DRCErrorType errorType, String msg,
98
772
Cell cell, double limit, double actual, String rule,
99
773
PolyBase poly1, Geometric geom1, Layer layer1,
100
774
PolyBase poly2, Geometric geom2, Layer layer2)
102
if (errorLogger == null) return;
776
ErrorLogger errorLogger = reportInfo.errorLogger;
778
if (errorLogger == null) return;
104
780
// if this error is in an ignored area, don't record it
105
781
StringBuffer DRCexclusionMsg = new StringBuffer();
106
if (exclusionMap != null && exclusionMap.get(cell) != null)
782
if (reportInfo.exclusionMap != null && reportInfo.exclusionMap.get(cell) != null)
108
784
// determine the bounding box of the error
109
785
List<PolyBase> polyList = new ArrayList<PolyBase>(2);
2332
/**************************************************************************************************************
2333
* CellLayersContainer class
2334
**************************************************************************************************************/
2335
class CellLayersContainer implements Serializable
2337
private Map<NodeProto, Set<String>> cellLayersMap;
2339
CellLayersContainer() {
2340
cellLayersMap = new HashMap<NodeProto, Set<String>>();
2343
Set<String> getLayersSet(NodeProto cell) {
2344
return cellLayersMap.get(cell);
2347
void addCellLayers(Cell cell, Set<String> set) {
2348
cellLayersMap.put(cell, set);
2351
boolean addCellLayers(Cell cell, Layer layer) {
2352
Set<String> set = cellLayersMap.get(cell);
2354
// first time the cell is accessed
2356
set = new HashSet<String>(1);
2357
cellLayersMap.put(cell, set);
2359
return set.add(layer.getName());
2363
/**************************************************************************************************************
2364
* CheckCellLayerEnumerator class
2365
**************************************************************************************************************/
2368
* Class to collect which layers are available in the design
2370
class CheckCellLayerEnumerator extends HierarchyEnumerator.Visitor {
2371
private Map<Cell, Cell> cellsMap;
2372
private CellLayersContainer cellLayersCon;
2374
CheckCellLayerEnumerator(CellLayersContainer cellLayersC) {
2375
cellsMap = new HashMap<Cell, Cell>();
2376
cellLayersCon = cellLayersC;
2380
* When the cell should be visited. Either it is the first time or the number of layers hasn't reached
2386
private boolean skipCell(Cell cell) {
2387
return cellsMap.get(cell) != null;
2390
public boolean enterCell(HierarchyEnumerator.CellInfo info) {
2391
Cell cell = info.getCell();
2392
if (skipCell(cell)) return false; // skip
2393
cellsMap.put(cell, cell);
2397
private Set<String> getLayersInCell(Cell cell) {
2398
Map<NodeProto, NodeProto> tempNodeMap = new HashMap<NodeProto, NodeProto>();
2399
Map<ArcProto, ArcProto> tempArcMap = new HashMap<ArcProto, ArcProto>();
2400
Set<String> set = new HashSet<String>();
2403
for (Iterator<NodeInst> it = cell.getNodes(); it.hasNext();) {
2404
NodeInst ni = it.next();
2405
NodeProto np = ni.getProto();
2406
if (ni.isCellInstance()) {
2407
Set<String> s = cellLayersCon.getLayersSet(np);
2409
assert (s != null); // it must have layers? unless is empty
2411
if (tempNodeMap.get(np) != null)
2412
continue; // done with this PrimitiveNode
2413
tempNodeMap.put(np, np);
2415
if (NodeInst.isSpecialNode(ni)) // like pins
2418
PrimitiveNode pNp = (PrimitiveNode) np;
2419
for (Technology.NodeLayer nLayer : pNp.getLayers()) {
2420
Layer layer = nLayer.getLayer();
2421
set.add(layer.getName());
2427
for (Iterator<ArcInst> it = cell.getArcs(); it.hasNext();) {
2428
ArcInst ai = it.next();
2429
ArcProto ap = ai.getProto();
2430
if (tempArcMap.get(ap) != null)
2431
continue; // done with this arc primitive
2432
tempArcMap.put(ap, ap);
2433
for (int i = 0; i < ap.getNumArcLayers(); i++) {
2434
Layer layer = ap.getLayer(i);
2435
set.add(layer.getName());
2441
public void exitCell(HierarchyEnumerator.CellInfo info) {
2442
Cell cell = info.getCell();
2443
Set<String> set = getLayersInCell(cell);
2444
assert (cellLayersCon.getLayersSet(cell) == null);
2445
cellLayersCon.addCellLayers(cell, set);
2448
public boolean visitNodeInst(Nodable no, HierarchyEnumerator.CellInfo info) {
2449
NodeInst ni = no.getNodeInst();
2451
// true only for Cells
2452
return ni.isCellInstance();
2456
/***************** LAYER INTERACTIONS ******************/
2458
/**************************************************************************************************************
2459
* ValidationLayers class
2460
**************************************************************************************************************/
2461
class ValidationLayers
2463
/* for figuring out which layers are valid for DRC */
2464
private Technology layersValidTech = null;
2465
private boolean [] layersValid;
2467
/* for tracking which layers interact with which nodes */
2468
private Technology layerInterTech = null;
2469
private HashMap<PrimitiveNode, boolean[]> layersInterNodes = null;
2470
private HashMap<ArcProto, boolean[]> layersInterArcs = null;
2472
private ErrorLogger errorLogger;
2473
private Cell topCell;
2474
private DRCRules currentRules;
2477
* Class to determine which layers in a Technology are valid.
2479
ValidationLayers(ErrorLogger logger, Cell cell, DRCRules rules)
2482
errorLogger = logger;
2483
currentRules = rules;
2484
layersValidTech = rules.getTechnology();
2485
// determine the layers that are being used
2486
int numLayers = layersValidTech.getNumLayers();
2487
layersValid = new boolean[numLayers];
2488
for(int i=0; i < numLayers; i++)
2489
layersValid[i] = false;
2491
for(Iterator<PrimitiveNode> it = layersValidTech.getNodes(); it.hasNext(); )
2493
PrimitiveNode np = it.next();
2494
if (np.isNotUsed()) continue;
2495
Technology.NodeLayer [] layers = np.getLayers();
2496
for(int i=0; i<layers.length; i++)
2498
Layer layer = layers[i].getLayer();
2499
layersValid[layer.getIndex()] = true;
2502
for(Iterator<ArcProto> it = layersValidTech.getArcs(); it.hasNext(); )
2504
ArcProto ap = it.next();
2505
if (ap.isNotUsed()) continue;
2506
for (Iterator<Layer> lIt = ap.getLayerIterator(); lIt.hasNext(); )
2508
Layer layer = lIt.next();
2509
layersValid[layer.getIndex()] = true;
2513
cacheValidLayers(layersValidTech);
2514
buildLayerInteractions(layersValidTech);
2517
boolean isABadLayer(Technology tech, int layerNumber)
2519
return (tech == layersValidTech && !layersValid[layerNumber]);
2523
* Method to determine which layers in a Technology are valid.
2525
void cacheValidLayers(Technology tech)
2527
if (tech == null) return;
2528
if (layersValidTech == tech) return;
2530
layersValidTech = tech;
2532
// determine the layers that are being used
2533
int numLayers = tech.getNumLayers();
2534
layersValid = new boolean[numLayers];
2535
for (int i = 0; i < numLayers; i++)
2536
layersValid[i] = false;
2537
for (Iterator<PrimitiveNode> it = tech.getNodes(); it.hasNext();)
2539
PrimitiveNode np = it.next();
2540
if (np.isNotUsed()) continue;
2541
Technology.NodeLayer[] layers = np.getLayers();
2542
for (int i = 0; i < layers.length; i++)
2544
Layer layer = layers[i].getLayer();
2545
layersValid[layer.getIndex()] = true;
2548
for (Iterator<ArcProto> it = tech.getArcs(); it.hasNext();)
2550
ArcProto ap = it.next();
2551
if (ap.isNotUsed()) continue;
2552
for (Iterator<Layer> lIt = ap.getLayerIterator(); lIt.hasNext();)
2554
Layer layer = lIt.next();
2555
layersValid[layer.getIndex()] = true;
2561
* Method to build the internal data structures that tell which layers interact with
2562
* which primitive nodes in technology "tech".
2564
void buildLayerInteractions(Technology tech)
2566
Technology old = layerInterTech;
2567
if (layerInterTech == tech) return;
2569
layerInterTech = tech;
2570
int numLayers = tech.getNumLayers();
2572
// build the node table
2573
if (layersInterNodes != null && old != null)
2575
errorLogger.logWarning("Switching from '" + old.getTechName() +
2576
"' to '" + tech.getTechName() + "' in DRC process. Check for non desired nodes in ",
2580
layersInterNodes = new HashMap<PrimitiveNode, boolean[]>();
2581
for (Iterator<PrimitiveNode> it = tech.getNodes(); it.hasNext();)
2583
PrimitiveNode np = it.next();
2584
if (np.isNotUsed()) continue;
2585
boolean[] layersInNode = new boolean[numLayers];
2586
Arrays.fill(layersInNode, false);
2588
Technology.NodeLayer[] layers = np.getLayers();
2589
Technology.NodeLayer[] eLayers = np.getElectricalLayers();
2590
if (eLayers != null) layers = eLayers;
2591
for (Technology.NodeLayer l : layers)
2593
Layer layer = l.getLayer();
2594
if (layer.isNonElectrical())
2595
continue; // such as pseudo
2596
for (Iterator<Layer> lIt = tech.getLayers(); lIt.hasNext();)
2598
Layer oLayer = lIt.next();
2599
if (oLayer.isNonElectrical())
2600
continue; // such as pseudo
2601
if (currentRules.isAnySpacingRule(layer, oLayer))
2602
layersInNode[oLayer.getIndex()] = true;
2605
layersInterNodes.put(np, layersInNode);
2608
// build the arc table
2609
layersInterArcs = new HashMap<ArcProto, boolean[]>();
2610
for (Iterator<ArcProto> it = tech.getArcs(); it.hasNext();)
2612
ArcProto ap = it.next();
2613
boolean[] layersInArc = new boolean[numLayers];
2614
Arrays.fill(layersInArc, false);
2616
for (Iterator<Layer> alIt = ap.getLayerIterator(); alIt.hasNext();)
2618
Layer layer = alIt.next();
2619
for (Iterator<Layer> lIt = tech.getLayers(); lIt.hasNext();)
2621
Layer oLayer = lIt.next();
2622
if (currentRules.isAnySpacingRule(layer, oLayer))
2623
layersInArc[oLayer.getIndex()] = true;
2626
layersInterArcs.put(ap, layersInArc);
2631
* Method to determine whether layer "layer" interacts in any way with a node of type "np".
2632
* If not, returns FALSE.
2634
boolean checkLayerWithNode(Layer layer, NodeProto np)
2636
buildLayerInteractions(np.getTechnology());
2638
// find this node in the table
2639
boolean[] validLayers = layersInterNodes.get(np);
2640
if (validLayers == null) return false;
2641
return validLayers[layer.getIndex()];
2645
* Method to determine whether layer "layer" interacts in any way with an arc of type "ap".
2646
* If not, returns FALSE.
2648
boolean checkLayerWithArc(Layer layer, ArcProto ap)
2650
buildLayerInteractions(ap.getTechnology());
2652
// find this node in the table
2653
boolean[] validLayers = layersInterArcs.get(ap);
2654
if (validLayers == null) return false;
2655
return validLayers[layer.getIndex()];
2660
* The CheckInst object is associated with every cell instance in the library.
2661
* It helps determine network information on a global scale.
2662
* It takes a "global-index" parameter, inherited from above (intially zero).
2663
* It then computes its own index number as follows:
2664
* thisindex = global-index * multiplier + localIndex + offset
2665
* This individual index is used to lookup an entry on each network in the cell
2666
* (an array is stored on each network, giving its global net number).
2676
* The CheckProto object is placed on every cell and is used only temporarily
2677
* to number the instances.
2681
/** time stamp for counting within a particular parent */ int timeStamp;
2682
/** number of instances of this cell in a particular parent */ int instanceCount;
2683
/** total number of instances of this cell, hierarchically */ int hierInstanceCount;
2684
/** number of instances of this cell in a particular parent */ int totalPerCell;
2685
/** true if this cell has been checked */ boolean cellChecked;
2686
/** true if this cell has parameters */ boolean cellParameterized;
2687
/** list of instances in a particular parent */ List<CheckInst> nodesInCell;
2688
/** netlist of this cell */ Netlist netlist;
2692
* The InstanceInter object records interactions between two cell instances and prevents checking
2693
* them multiple times.
2697
/** the two cell instances being compared */ Cell cell1, cell2;
2698
/** orientation of cell instance 1 */ Orientation or1;
2699
/** orientation of cell instance 2 */ Orientation or2;
2700
/** distance from instance 1 to instance 2 */ double dx, dy;
2701
/** the two NodeInst parents */ NodeInst n1Parent, n2Parent, triggerNi;
b'\\ No newline at end of file'