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

« back to all changes in this revision

Viewing changes to com/sun/electric/tool/drc/DRC.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:
27
27
import com.sun.electric.database.ImmutableArcInst;
28
28
import com.sun.electric.database.ImmutableNodeInst;
29
29
import com.sun.electric.database.Snapshot;
 
30
import com.sun.electric.database.network.Netlist;
30
31
import com.sun.electric.database.constraint.Layout;
31
 
import com.sun.electric.database.geometry.GeometryHandler;
32
 
import com.sun.electric.database.geometry.PolyBase;
33
 
import com.sun.electric.database.geometry.GenMath;
 
32
import com.sun.electric.database.geometry.*;
34
33
import com.sun.electric.database.hierarchy.Cell;
35
34
import com.sun.electric.database.hierarchy.Library;
 
35
import com.sun.electric.database.hierarchy.HierarchyEnumerator;
 
36
import com.sun.electric.database.hierarchy.Nodable;
36
37
import com.sun.electric.database.id.CellId;
37
38
import com.sun.electric.database.prototype.NodeProto;
38
39
import com.sun.electric.database.text.Pref;
39
40
import com.sun.electric.database.text.TextUtils;
40
41
import com.sun.electric.database.text.Version;
41
 
import com.sun.electric.database.topology.ArcInst;
42
 
import com.sun.electric.database.topology.Geometric;
43
 
import com.sun.electric.database.topology.NodeInst;
 
42
import com.sun.electric.database.topology.*;
44
43
import com.sun.electric.database.variable.Variable;
45
 
import com.sun.electric.technology.DRCRules;
46
 
import com.sun.electric.technology.DRCTemplate;
47
 
import com.sun.electric.technology.Foundry;
48
 
import com.sun.electric.technology.Layer;
49
 
import com.sun.electric.technology.PrimitiveNode;
50
 
import com.sun.electric.technology.Technology;
 
44
import com.sun.electric.technology.*;
51
45
import com.sun.electric.technology.technologies.Artwork;
52
46
import com.sun.electric.technology.technologies.Generic;
53
47
import com.sun.electric.technology.technologies.Schematics;
57
51
import com.sun.electric.tool.user.ErrorLogger;
58
52
import com.sun.electric.tool.user.User;
59
53
 
 
54
import java.awt.geom.Area;
60
55
import java.awt.geom.Rectangle2D;
61
 
import java.awt.geom.Area;
 
56
import java.awt.geom.AffineTransform;
 
57
import java.awt.geom.Point2D;
62
58
import java.util.*;
63
59
import java.util.prefs.Preferences;
 
60
import java.io.Serializable;
64
61
 
65
62
/**
66
63
 * This is the Design Rule Checker tool.
67
64
 */
68
65
public class DRC extends Listener
69
66
{
70
 
        /** the DRC tool. */                                                            protected static DRC tool = new DRC();
71
 
        /** overrides of rules for each technology. */          private static HashMap<Technology,Pref> prefDRCOverride = new HashMap<Technology,Pref>();
72
 
        /** map of cells and their objects to DRC */            private static HashMap<Cell,HashSet<Geometric>> cellsToCheck = new HashMap<Cell,HashSet<Geometric>>();
73
 
    /** to temporary store DRC dates for spacing checking */                 private static HashMap<Cell,StoreDRCInfo> storedSpacingDRCDate = new HashMap<Cell,StoreDRCInfo>();
74
 
    /** to temporary store DRC dates for area checking */                 private static HashMap<Cell,StoreDRCInfo> storedAreaDRCDate = new HashMap<Cell,StoreDRCInfo>();
75
 
    /** for logging incremental errors */               private static ErrorLogger errorLoggerIncremental = ErrorLogger.newInstance("DRC (incremental)", true);
 
67
        /** the DRC tool. */                                                                 protected static DRC tool = new DRC();
 
68
        /** overrides of rules for each technology. */               private static Map<Technology,Pref> prefDRCOverride = new HashMap<Technology,Pref>();
 
69
        /** map of cells and their objects to DRC */                 private static Map<Cell,Set<Geometric>> cellsToCheck = new HashMap<Cell,Set<Geometric>>();
 
70
    /** to temporary store DRC dates for spacing checking */ private static Map<Cell,StoreDRCInfo> storedSpacingDRCDate = new HashMap<Cell,StoreDRCInfo>();
 
71
    /** to temporary store DRC dates for area checking */    private static Map<Cell,StoreDRCInfo> storedAreaDRCDate = new HashMap<Cell,StoreDRCInfo>();
 
72
    /** for logging incremental errors */                    private static ErrorLogger errorLoggerIncremental = ErrorLogger.newInstance("DRC (incremental)", true);
 
73
    static final double TINYDELTA = DBMath.getEpsilon()*1.1;
 
74
    /** key of Variable holding DRC Cell annotations. */        static final Variable.Key DRC_ANNOTATION_KEY = Variable.newKey("ATTR_DRC");
76
75
 
77
 
    public static Layer.Function.Set getMultiLayersSet(Layer layer)
 
76
    static Layer.Function.Set getMultiLayersSet(Layer layer)
78
77
    {
79
78
        Layer.Function.Set thisLayerFunction = (layer.getFunction().isPoly()) ?
80
79
        new Layer.Function.Set(Layer.Function.POLY1, Layer.Function.GATE) :
82
81
        return thisLayerFunction;
83
82
    }
84
83
 
 
84
    /**
 
85
         * Method to see if polygons in "pList" (describing arc "ai") should be cropped against a
 
86
     * connecting transistor.  Crops the polygon if so.
 
87
     */
 
88
    static void cropActiveArc(ArcInst ai, boolean ignoreCenterCuts, Poly [] pList)
 
89
    {
 
90
        // look for an active layer in this arc
 
91
        int tot = pList.length;
 
92
        int diffPoly = -1;
 
93
        for(int j=0; j<tot; j++)
 
94
        {
 
95
            Poly poly = pList[j];
 
96
            Layer layer = poly.getLayer();
 
97
            if (layer == null) continue;
 
98
            Layer.Function fun = layer.getFunction();
 
99
            if (fun.isDiff()) { diffPoly = j;   break; }
 
100
        }
 
101
        if (diffPoly < 0) return;
 
102
        Poly poly = pList[diffPoly];
 
103
 
 
104
        // must be manhattan
 
105
        Rectangle2D polyBounds = poly.getBox();
 
106
        if (polyBounds == null) return;
 
107
        polyBounds = new Rectangle2D.Double(polyBounds.getMinX(), polyBounds.getMinY(), polyBounds.getWidth(), polyBounds.getHeight());
 
108
 
 
109
        // search for adjoining transistor in the cell
 
110
        boolean cropped = false;
 
111
        boolean halved = false;
 
112
        for(int i=0; i<2; i++)
 
113
        {
 
114
            PortInst pi = ai.getPortInst(i);
 
115
            NodeInst ni = pi.getNodeInst();
 
116
            if (!ni.getFunction().isFET()) continue;
 
117
 
 
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++)
 
124
            {
 
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);
 
135
 
 
136
                if (result == 1)
 
137
                {
 
138
                    // remove this polygon from consideration
 
139
                    poly.setLayer(null);
 
140
                    return;
 
141
                }
 
142
                cropped = true;
 
143
                halved = true;
 
144
            }
 
145
        }
 
146
        if (cropped)
 
147
        {
 
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;
 
154
        }
 
155
    }
 
156
 
 
157
    /**
 
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.
 
163
     */
 
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)
 
169
    {
 
170
        int j;
 
171
        Rectangle2D newBounds = new Rectangle2D.Double();  // Sept 30
 
172
 
 
173
        for (Iterator<RTBounds> it = cell.searchIterator(bounds); it.hasNext();)
 
174
        {
 
175
            RTBounds g = it.next();
 
176
 
 
177
            // You can't skip the same geometry otherwise layers in the same Geometric won't
 
178
            // be tested.
 
179
            // But it is necessary while testing flat geometries... in minWidthInternal
 
180
            if (ignoreSameGeometry && (g == geo1 || g == geo2))
 
181
                continue;
 
182
 
 
183
            // I can't skip geometries to exclude from the search
 
184
            if (g instanceof NodeInst)
 
185
            {
 
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())
 
190
                {
 
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);
 
197
 
 
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))
 
203
                        return true;
 
204
                    continue;
 
205
                }
 
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++)
 
214
                {
 
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))
 
218
                    {
 
219
                        continue;
 
220
                    }
 
221
 
 
222
                    // Should be the transform before?
 
223
                    poly.transform(bound);
 
224
 
 
225
                    if (poly1 != null && !overlap && poly.polySame(poly1))
 
226
                        continue;
 
227
                    if (poly2 != null && !overlap && poly.polySame(poly2))
 
228
                        continue;
 
229
 
 
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)
 
238
                }
 
239
            } else
 
240
            {
 
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++)
 
246
                {
 
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))
 
250
                    {
 
251
                        continue;
 
252
                    }
 
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
 
260
                    break;
 
261
                }
 
262
            }
 
263
 
 
264
            for (j = 0; j < pointsFound.length && pointsFound[j]; j++) ;
 
265
            if (j == pointsFound.length)
 
266
            {
 
267
                assert (false); // test when otherwise the calculation is useless! System.out.println("When?");
 
268
                return true;
 
269
            }
 
270
        }
 
271
        return false;
 
272
    }
 
273
 
 
274
    /**
 
275
         * Method to determine if neighbor would help to cover the minimum conditions
 
276
 *
 
277
 * @return true if error was found (not warning)
 
278
 */
 
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)
 
282
{
 
283
    double actual = 0;
 
284
    Point2D left1, left2, left3, right1, right2, right3;
 
285
    //if (bounds.getWidth() < minWidthRule.value)
 
286
    String msg = "";
 
287
 
 
288
    // potential problem along X
 
289
    if (dir == 0)
 
290
    {
 
291
        actual = bounds.getWidth();
 
292
        msg = "(X axis)";
 
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());
 
301
    } else
 
302
    {
 
303
        actual = bounds.getHeight();
 
304
        msg = "(Y axis)";
 
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);
 
313
    }
 
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);
 
320
 
 
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;
 
325
 
 
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;
 
332
 
 
333
    DRCErrorType errorType = DRCErrorType.MINWIDTHERROR;
 
334
    String extraMsg = msg;
 
335
    String rule = minWidthRule.ruleName;
 
336
 
 
337
    // Only when the flat element is fully covered send the warning
 
338
    // otherwise it is considered an error.
 
339
    if (zeroWide && overlapLayer)
 
340
    {
 
341
        extraMsg = " but covered by other layer";
 
342
        errorType = DRCErrorType.ZEROLENGTHARCWARN;
 
343
        rule = null;
 
344
    }
 
345
 
 
346
    if (reportError)
 
347
        createDRCErrorLogger(reportInfo, errorType, extraMsg, cell, minWidthRule.getValue(0), actual, rule,
 
348
            (onlyOne) ? null : poly, geom, layer, null, null, null);
 
349
    return !overlapLayer;
 
350
}
 
351
 
 
352
    /**
 
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.
 
357
     */
 
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)
 
361
    {
 
362
        int j;
 
363
        boolean skip = false;
 
364
        Rectangle2D newBounds = new Rectangle2D.Double();  // sept 30
 
365
 
 
366
        for (Iterator<RTBounds> it = cell.searchIterator(bounds); it.hasNext();)
 
367
        {
 
368
            RTBounds g = it.next();
 
369
            if (g instanceof NodeInst)
 
370
            {
 
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())
 
375
                {
 
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);
 
382
 
 
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))
 
388
                        return true;
 
389
                    continue;
 
390
                }
 
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++)
 
398
                {
 
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))
 
402
                    {
 
403
                        continue;
 
404
                    }
 
405
 
 
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);
 
413
                    if (newR)
 
414
                    {
 
415
                        return true;
 
416
                    }
 
417
                    // No need of checking rest of the layers?
 
418
                    //break;
 
419
                }
 
420
            } else
 
421
            {
 
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++)
 
427
                {
 
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))
 
431
                    {
 
432
                        continue;
 
433
                    }
 
434
 
 
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);
 
441
                    if (newR)
 
442
                        return true;
 
443
                    // No need of checking rest of the layers
 
444
                    //break;
 
445
                }
 
446
            }
 
447
 
 
448
            for (j = 0; j < pointsFound.length && pointsFound[j]; j++) ;
 
449
            if (j == pointsFound.length)
 
450
            {
 
451
                System.out.println("When?");
 
452
                return true;
 
453
            }
 
454
        }
 
455
        if (skip) System.out.println("This case in lookForLayerNew antes");
 
456
 
 
457
        return false;
 
458
    }
 
459
 
 
460
    static boolean checkMinWidthInternal(Geometric geom, Layer layer, Poly poly, boolean onlyOne,
 
461
                                          DRCTemplate minWidthRule, boolean reportError,
 
462
                                          Layer.Function.Set layerFunction, ReportInfo reportInfo)
 
463
    {
 
464
        Cell cell = geom.getParent();
 
465
        if (minWidthRule == null) return false;
 
466
 
 
467
        double minWidthValue = minWidthRule.getValue(0);
 
468
        // simpler analysis if manhattan
 
469
        Rectangle2D bounds = poly.getBox();
 
470
 
 
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)));
 
476
        if (flatPoly)
 
477
        {
 
478
            Point2D [] points = poly.getPoints();
 
479
            Point2D from = points[0];
 
480
            Point2D to = points[1];
 
481
 
 
482
            // Assuming it is a single segment the flat region
 
483
            // looking for two distinct points
 
484
            if (DBMath.areEquals(from, to))
 
485
            {
 
486
                boolean found = false;
 
487
                for (int i = 2; i < points.length; i++)
 
488
                {
 
489
                    if (!DBMath.areEquals(from, points[i]))
 
490
                    {
 
491
                        to = points[i];
 
492
                        found = true;
 
493
                        break;
 
494
                    }
 
495
                }
 
496
                if (!found) // single segment where to == from
 
497
                {
 
498
                    return false; // skipping this case.
 
499
                }
 
500
            }
 
501
 
 
502
            Point2D center = new Point2D.Double((from.getX() + to.getX()) / 2, (from.getY() + to.getY()) / 2);
 
503
 
 
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.
 
511
 
 
512
            if (reportError)
 
513
                createDRCErrorLogger(reportInfo, DRCErrorType.MINWIDTHERROR, null, cell, minWidthValue, 0, minWidthRule.ruleName,
 
514
                    (onlyOne) ? null : poly, geom, layer, null, null, null);
 
515
            return true;
 
516
        }
 
517
 
 
518
        if (bounds != null)
 
519
        {
 
520
            boolean tooSmallWidth = DBMath.isGreaterThan(minWidthValue, bounds.getWidth());
 
521
            boolean tooSmallHeight = DBMath.isGreaterThan(minWidthValue, bounds.getHeight());
 
522
            if (!tooSmallWidth && !tooSmallHeight) return false;
 
523
 
 
524
            boolean foundError = false;
 
525
            if (tooSmallWidth && checkExtensionWithNeighbors(cell, geom, poly, layer, bounds, minWidthRule,
 
526
                0, onlyOne, reportError, layerFunction, reportInfo))
 
527
                foundError = true;
 
528
            if (tooSmallHeight && checkExtensionWithNeighbors(cell, geom, poly, layer, bounds, minWidthRule,
 
529
                1, onlyOne, reportError, layerFunction, reportInfo))
 
530
                foundError = true;
 
531
            return foundError;
 
532
        }
 
533
 
 
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;
 
539
 
 
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)
 
544
        {
 
545
            if (reportError)
 
546
                createDRCErrorLogger(reportInfo, DRCErrorType.MINWIDTHERROR, null, cell, minWidthValue, actual, minWidthRule.ruleName,
 
547
                    (onlyOne) ? null : poly, geom, layer, null, null, null);
 
548
            return true;
 
549
        }
 
550
 
 
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++)
 
555
        {
 
556
            Point2D from;
 
557
            if (i == 0) from = points[count - 1];
 
558
            else
 
559
                from = points[i - 1];
 
560
            Point2D to = points[i];
 
561
            if (from.equals(to)) continue;
 
562
 
 
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++)
 
567
            {
 
568
                if (j == i) continue;
 
569
                Point2D oFrom;
 
570
                if (j == 0) oFrom = points[count - 1];
 
571
                else
 
572
                    oFrom = points[j - 1];
 
573
                Point2D oTo = points[j];
 
574
                if (oFrom.equals(oTo)) continue;
 
575
                double oAng = DBMath.figureAngleRadians(oFrom, oTo);
 
576
                double rAng = ang;
 
577
                while (rAng > Math.PI) rAng -= Math.PI;
 
578
                double rOAng = oAng;
 
579
                while (rOAng > Math.PI) rOAng -= Math.PI;
 
580
                if (DBMath.doublesEqual(rAng, rOAng))
 
581
                {
 
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;
 
587
                }
 
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()))
 
591
                    continue;
 
592
                if (inter.getY() < Math.min(oFrom.getY(), oTo.getY()) || inter.getY() > Math.max(oFrom.getY(), oTo.getY()))
 
593
                    continue;
 
594
                double fdx = center.getX() - inter.getX();
 
595
                double fdy = center.getY() - inter.getY();
 
596
                actual = DBMath.round(Math.sqrt(fdx * fdx + fdy * fdy));
 
597
 
 
598
                if (actual < minWidthValue)
 
599
                {
 
600
                    if (reportError)
 
601
                    {
 
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)))
 
604
                        {
 
605
                            createDRCErrorLogger(reportInfo, DRCErrorType.MINWIDTHERROR, null, cell, minWidthValue,
 
606
                                actual, minWidthRule.ruleName, (onlyOne) ? null : poly, geom, layer, null, null, null);
 
607
                        } else
 
608
                        {
 
609
                            createDRCErrorLogger(reportInfo, DRCErrorType.NOTCHERROR, null, cell, minWidthValue,
 
610
                                actual, minWidthRule.ruleName, (onlyOne) ? null : poly, geom, layer, poly, geom, layer);
 
611
                        }
 
612
                    }
 
613
                    return true;
 
614
                }
 
615
            }
 
616
        }
 
617
        return false;
 
618
    }
 
619
 
 
620
    /**
 
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
 
625
         *   or:
 
626
         *     they don't connect and are implant layers (substrate/well)
 
627
     * @param tech
 
628
     * @param con
 
629
     * @param layer1
 
630
     * @param layer2
 
631
     * @return true if the layer may touch
 
632
     */
 
633
    static boolean mayTouch(Technology tech, boolean con, Layer layer1, Layer layer2)
 
634
    {
 
635
        boolean maytouch = false;
 
636
                if (tech.sameLayer(layer1, layer2))
 
637
                {
 
638
                        Layer.Function fun = layer1.getFunction();
 
639
                        if (con)
 
640
                        {
 
641
                                if (!fun.isContact()) maytouch = true;
 
642
                        } else
 
643
                        {
 
644
                                if (fun.isSubstrate()) maytouch = true;
 
645
                                // Special cases for thick actives
 
646
                                else
 
647
                                {
 
648
                                        // Searching for THICK bit
 
649
                                        int funExtras = layer1.getFunctionExtras();
 
650
                                        if (fun.isDiff() && (funExtras&Layer.Function.THICK) != 0)
 
651
                                        {
 
652
                                                if (Job.LOCALDEBUGFLAG) System.out.println("Thick active found in Quick.checkDist");
 
653
                                                maytouch = true;
 
654
                                        }
 
655
                                }
 
656
                        }
 
657
                }
 
658
        return maytouch;
 
659
    }
 
660
 
 
661
    /**
 
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
 
666
     */
 
667
    static boolean checkNodeAgainstCombinationRules(NodeInst ni, ReportInfo reportInfo)
 
668
    {
 
669
        Cell cell = ni.getParent();
 
670
        NodeProto np = ni.getProto();
 
671
                Technology tech = np.getTechnology();
 
672
        if (np instanceof PrimitiveNode)
 
673
        {
 
674
            DRCTemplate forbidRule =
 
675
            DRC.isForbiddenNode(((PrimitiveNode)np).getPrimNodeIndexInTech(), -1,
 
676
                DRCTemplate.DRCRuleType.FORBIDDEN, tech);
 
677
            if (forbidRule != null)
 
678
            {
 
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);
 
681
                return true;
 
682
            }
 
683
        }
 
684
        return false;
 
685
    }
 
686
 
 
687
    /**
 
688
     * Method to check which combination of OD2 layers are allowed
 
689
     * @param layer
 
690
     * @return true if there is an invalid combination of OD2 layers
 
691
     */
 
692
    static boolean checkOD2Combination(Technology tech, NodeInst ni, Layer layer, Map<Layer,NodeInst> od2Layers,
 
693
                                       ReportInfo reportInfo)
 
694
    {
 
695
        int funExtras = layer.getFunctionExtras();
 
696
        boolean notOk = false;
 
697
 
 
698
        if (layer.getFunction().isImplant() && (funExtras&Layer.Function.THICK) != 0)
 
699
        {
 
700
            // Only stores first node found
 
701
            od2Layers.put(layer, ni);
 
702
 
 
703
            // More than one type used.
 
704
            if (od2Layers.size() != 1)
 
705
            {
 
706
                for (Map.Entry<Layer,NodeInst> e : od2Layers.entrySet())
 
707
                {
 
708
                    Layer lay1 = e.getKey();
 
709
                    if (lay1 == layer) continue;
 
710
                    DRCTemplate rule = isForbiddenNode(lay1.getIndex(), layer.getIndex(), DRCTemplate.DRCRuleType.FORBIDDEN, tech);
 
711
                    if (rule != null)
 
712
                    {
 
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);
 
718
 
 
719
                        return true;
 
720
                    }
 
721
                }
 
722
            }
 
723
        }
 
724
        return notOk;
 
725
    }
 
726
 
85
727
    /*********************************** QUICK DRC ERROR REPORTING ***********************************/
86
728
    public static enum DRCErrorType
87
729
    {
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
 
733
        CROOKEDERROR,
 
734
        // Different types of warnings
92
735
        ZEROLENGTHARCWARN, TECHMIXWARN
93
736
    }
94
737
 
95
 
    public static void createDRCErrorLogger(ErrorLogger errorLogger, Map<Cell, Area> exclusionMap,
96
 
                                            DRCCheckMode errorTypeSearch, boolean interactiveLogger,
 
738
    public static class ReportInfo
 
739
    {
 
740
 
 
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();
 
753
 
 
754
        public ReportInfo(ErrorLogger eL, Technology tech, boolean specificGeoms)
 
755
        {
 
756
            errorLogger = eL;
 
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();
 
761
 
 
762
            errorTypeSearch = DRC.getErrorType();
 
763
            if (specificGeoms)
 
764
            {
 
765
                errorTypeSearch = DRC.DRCCheckMode.ERROR_CHECK_CELL;
 
766
            }
 
767
        }
 
768
    }
 
769
 
 
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)
101
775
    {
102
 
                if (errorLogger == null) return;
 
776
        ErrorLogger errorLogger = reportInfo.errorLogger;
 
777
 
 
778
        if (errorLogger == null) return;
103
779
 
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)
107
783
                {
108
784
                        // determine the bounding box of the error
109
785
                        List<PolyBase> polyList = new ArrayList<PolyBase>(2);
114
790
                                polyList.add(poly2);
115
791
                                geomList.add(geom2);
116
792
                        }
117
 
            boolean found = checkExclusionMap(exclusionMap, cell, polyList, geomList, DRCexclusionMsg);
 
793
            boolean found = checkExclusionMap(reportInfo.exclusionMap, cell, polyList, geomList, DRCexclusionMsg);
118
794
 
119
795
            // At least one DRC exclusion that contains both
120
796
            if (found) return;
127
803
                // Message already logged
128
804
        boolean onlyWarning = (errorType == DRCErrorType.ZEROLENGTHARCWARN || errorType == DRCErrorType.TECHMIXWARN);
129
805
        // Until a decent algorithm is in place for detecting repeated errors, ERROR_CHECK_EXHAUSTIVE might report duplicate errros
130
 
                if ( geom2 != null && errorTypeSearch != DRCCheckMode.ERROR_CHECK_EXHAUSTIVE && errorLogger.findMessage(cell, geom1, geom2.getParent(), geom2, !onlyWarning))
 
806
                if ( geom2 != null && reportInfo.errorTypeSearch != DRCCheckMode.ERROR_CHECK_EXHAUSTIVE &&
 
807
            errorLogger.findMessage(cell, geom1, geom2.getParent(), geom2, !onlyWarning))
131
808
            return;
132
809
 
133
810
                StringBuffer errorMessage = new StringBuffer();
180
857
                        StringBuffer errorMessagePart2 = null;
181
858
                        switch (errorType)
182
859
                        {
 
860
                case CROOKEDERROR:
 
861
                    errorMessage.append("Crooked error:");
 
862
                                        errorMessagePart2 = new StringBuffer(" is not horizontal nor vertical");
 
863
                    break;
183
864
                case RESOLUTION:
184
865
                    errorMessage.append("Resolution error:");
185
866
                                        errorMessagePart2 = new StringBuffer(msg);
233
914
                    String layerName = (layer2 != null) ? layer2.getName() : "Select";
234
915
                                        errorMessagePart2.append(" NEEDS SURROUND OF LAYER '" + layerName + "' BY " + limit);
235
916
                    break;
236
 
                        }
 
917
                default:
 
918
                    assert(false); // it should not happen
 
919
            }
237
920
 
238
921
                        errorMessage.append(" " + cell + " ");
239
922
                        if (geom1 != null)
274
957
        else
275
958
                    errorLogger.logError(errorMessage.toString(), geomList, null, null, null, polyList, cell, sortKey);
276
959
        // Temporary display of errors.
277
 
        if (interactiveLogger)
 
960
        if (reportInfo.interactiveLogger)
278
961
            Job.getUserInterface().termLogging(errorLogger, false, false);
279
962
        }
280
963
 
391
1074
 
392
1075
        synchronized (cellsToCheck)
393
1076
                {
394
 
                        HashSet<Geometric> cellSet = cellsToCheck.get(cell);
 
1077
                        Set<Geometric> cellSet = cellsToCheck.get(cell);
395
1078
                        if (cellSet == null)
396
1079
                        {
397
1080
                                cellSet = new HashSet<Geometric>();
401
1084
                }
402
1085
    }
403
1086
 
404
 
//      private static void removeGeometric(Geometric geom)
405
 
//      {
406
 
//              if (!isIncrementalDRCOn()) return;
407
 
//              Cell cell = geom.getParent();
408
 
//              synchronized (cellsToCheck)
409
 
//              {
410
 
//                      HashSet<Geometric> cellSet = cellsToCheck.get(cell);
411
 
//                      if (cellSet != null) cellSet.remove(geom);
412
 
//              }
413
 
//      }
414
 
 
415
 
        private static void doIncrementalDRCTask()
 
1087
    private static void doIncrementalDRCTask()
416
1088
        {
417
1089
                if (!isIncrementalDRCOn()) return;
418
1090
                if (incrementalRunning) return;
420
1092
                Library curLib = Library.getCurrent();
421
1093
                if (curLib == null) return;
422
1094
                Cell cellToCheck = Job.getUserInterface().getCurrentCell(curLib);
423
 
                HashSet<Geometric> cellSet = null;
 
1095
                Set<Geometric> cellSet = null;
424
1096
 
425
1097
                // get a cell to check
426
1098
                synchronized (cellsToCheck)
490
1162
                doIncrementalDRCTask();
491
1163
        }
492
1164
 
493
 
//      /**
494
 
//       * Method to announce a change to a NodeInst.
495
 
//       * @param ni the NodeInst that was changed.
496
 
//       * @param oD the old contents of the NodeInst.
497
 
//       */
498
 
//      public void modifyNodeInst(NodeInst ni, ImmutableNodeInst oD)
499
 
//      {
500
 
//              includeGeometric(ni);
501
 
//      }
502
 
//
503
 
//      /**
504
 
//       * Method to announce a change to an ArcInst.
505
 
//       * @param ai the ArcInst that changed.
506
 
//     * @param oD the old contents of the ArcInst.
507
 
//       */
508
 
//      public void modifyArcInst(ArcInst ai, ImmutableArcInst oD)
509
 
//      {
510
 
//              includeGeometric(ai);
511
 
//      }
512
 
//
513
 
//      /**
514
 
//       * Method to announce the creation of a new ElectricObject.
515
 
//       * @param obj the ElectricObject that was just created.
516
 
//       */
517
 
//      public void newObject(ElectricObject obj)
518
 
//      {
519
 
//              if (obj instanceof Geometric)
520
 
//              {
521
 
//                      includeGeometric((Geometric)obj);
522
 
//              }
523
 
//      }
524
 
//
525
 
//      /**
526
 
//       * Method to announce the deletion of an ElectricObject.
527
 
//       * @param obj the ElectricObject that was just deleted.
528
 
//       */
529
 
//      public void killObject(ElectricObject obj)
530
 
//      {
531
 
//              if (obj instanceof Geometric)
532
 
//              {
533
 
//                      removeGeometric((Geometric)obj);
534
 
//              }
535
 
//      }
536
 
 
537
1165
        /****************************** DRC INTERFACE ******************************/
538
1166
    public static ErrorLogger getDRCErrorLogger(boolean layout, boolean incremental, String extraMsg)
539
1167
    {
557
1185
    /**
558
1186
     * This method generates a DRC job from the GUI or for a bash script.
559
1187
     */
560
 
    public static void checkDRCHierarchically(Cell cell, Rectangle2D bounds, GeometryHandler.GHMode mode, boolean onlyArea)
 
1188
    public static void checkDRCHierarchically(Cell cell, List<Geometric> objs, Rectangle2D bounds,
 
1189
                                              GeometryHandler.GHMode mode, boolean onlyArea)
561
1190
    {
562
1191
        if (cell == null) return;
563
1192
        boolean isLayout = true; // hierarchical check of layout by default
567
1196
                        isLayout = false;
568
1197
 
569
1198
        if (mode == null) mode = GeometryHandler.GHMode.ALGO_SWEEP;
570
 
        new CheckDRCHierarchically(cell, isLayout, bounds, mode, onlyArea);
 
1199
        new CheckDRCHierarchically(cell, isLayout, objs, bounds, mode, onlyArea);
571
1200
    }
572
1201
 
573
1202
        /**
599
1228
                Rectangle2D bounds;
600
1229
        private GeometryHandler.GHMode mergeMode; // to select the merge algorithm
601
1230
        private boolean onlyArea;
 
1231
        private Geometric[] geoms;
602
1232
 
603
1233
        /**
604
1234
         * Check bounds within cell. If bounds is null, check entire cell.
606
1236
         * @param layout
607
1237
         * @param bounds
608
1238
         */
609
 
                protected CheckDRCHierarchically(Cell cell, boolean layout, Rectangle2D bounds, GeometryHandler.GHMode mode,
 
1239
                protected CheckDRCHierarchically(Cell cell, boolean layout, List<Geometric> objs,
 
1240
                                         Rectangle2D bounds, GeometryHandler.GHMode mode,
610
1241
                                         boolean onlyA)
611
1242
                {
612
1243
                        super(cell, tool, Job.Priority.USER, layout);
613
1244
                        this.bounds = bounds;
614
1245
            this.mergeMode = mode;
615
1246
            this.onlyArea = onlyA;
 
1247
            if (objs != null)
 
1248
            {
 
1249
                this.geoms = new Geometric[objs.size()];
 
1250
                objs.toArray(this.geoms);
 
1251
            }
616
1252
            startJob();
617
1253
                }
618
1254
 
622
1258
            ErrorLogger errorLog = getDRCErrorLogger(isLayout, false, null);
623
1259
            checkNetworks(errorLog, cell, isLayout);
624
1260
            if (isLayout)
625
 
                Quick.checkDesignRules(errorLog, cell, null, null, bounds, this, mergeMode, onlyArea);
 
1261
                Quick.checkDesignRules(errorLog, cell, geoms, null, bounds, this, mergeMode, onlyArea);
626
1262
            else
627
 
                Schematic.doCheck(errorLog, cell, null);
 
1263
                Schematic.doCheck(errorLog, cell, geoms);
628
1264
            long endTime = System.currentTimeMillis();
629
1265
            int errorCount = errorLog.getNumErrors();
630
1266
            int warnCount = errorLog.getNumWarnings();
676
1312
         */
677
1313
        public static DRCRules getRules(Technology tech)
678
1314
        {
679
 
        DRCRules currentRules = tech.getCachedRules();
 
1315
        XMLRules currentRules = tech.getCachedRules();
680
1316
                if (currentRules != null && tech == currentTechnology) return currentRules;
681
1317
 
682
1318
                // constructing design rules: start with factory rules
861
1497
     * Determine if node represented by index in DRC mapping table is forbidden under
862
1498
     * this foundry.
863
1499
     */
864
 
    public static boolean isForbiddenNode(int index1, int index2, DRCTemplate.DRCRuleType type, Technology tech)
 
1500
    public static DRCTemplate isForbiddenNode(int index1, int index2, DRCTemplate.DRCRuleType type, Technology tech)
865
1501
    {
866
1502
        DRCRules rules = getRules(tech);
867
 
        if (rules == null) return false;
 
1503
        if (rules == null) return null;
868
1504
        return isForbiddenNode(rules, index1, index2, type);
869
1505
    }
870
1506
 
871
 
    public static boolean isForbiddenNode(DRCRules rules, int index1, int index2, DRCTemplate.DRCRuleType type)
 
1507
    public static DRCTemplate isForbiddenNode(DRCRules rules, int index1, int index2, DRCTemplate.DRCRuleType type)
872
1508
    {
873
1509
        int index = index1; // In case of primitive nodes
874
1510
        if (index2 != -1 )
940
1576
    public static void cleanCellsDueToFoundryChanges(Technology tech, Foundry f)
941
1577
    {
942
1578
        // Need to clean cells using this foundry because the rules might have changed.
943
 
        System.out.println("Cleaning good DRC dates in cells using '" + f.getType().name() +
 
1579
        System.out.println("Cleaning good DRC dates in cells using '" + f.getType().getName() +
944
1580
                "' in '" + tech.getTechName() + "'");
945
 
        HashSet<Cell> cleanSpacingDRCDate = new HashSet<Cell>();
946
 
        HashSet<Cell> cleanAreaDRCDate = new HashSet<Cell>();
947
 
 
948
 
        int bit = 0;
949
 
        switch(f.getType())
950
 
        {
951
 
            case MOSIS:
952
 
                bit = DRC_BIT_MOSIS_FOUNDRY;
953
 
                break;
954
 
            case TSMC:
955
 
                bit = DRC_BIT_TSMC_FOUNDRY;
956
 
                break;
957
 
            case ST:
958
 
                bit = DRC_BIT_ST_FOUNDRY;
959
 
                break;
960
 
        }
961
 
 
 
1581
        Set<Cell> cleanSpacingDRCDate = new HashSet<Cell>();
 
1582
        Set<Cell> cleanAreaDRCDate = new HashSet<Cell>();
 
1583
 
 
1584
        int bit = f.getType().getBit();
962
1585
        boolean inMemory = isDatesStoredInMemory();
963
1586
 
964
1587
        for (Iterator<Library> it = Library.getLibraries(); it.hasNext();)
1012
1635
            long lastDRCDateInSecondsLow = lastDRCDateAsInts[1].intValue();
1013
1636
            lastDRCDateInMilliseconds = (lastDRCDateInSecondsHigh << 32) | (lastDRCDateInSecondsLow & 0xFFFFFFFFL);
1014
1637
        }
1015
 
//        Variable varSpacingDate = cell.getVar(key, Long.class); // new strategy
1016
 
//        if (varSpacingDate == null)
1017
 
//            varSpacingDate = cell.getVar(key, Integer[].class);
1018
 
//        if (varSpacingDate == null) return false;
1019
 
//        Object lastDRCDateObject = varSpacingDate.getObject();
1020
 
//        if (lastDRCDateObject instanceof Integer[]) {
1021
 
//            Integer[] lastDRCDateAsInts = (Integer [])lastDRCDateObject;
1022
 
//            long lastDRCDateInSecondsHigh = lastDRCDateAsInts[0].intValue();
1023
 
//            long lastDRCDateInSecondsLow = lastDRCDateAsInts[1].intValue();
1024
 
//            lastDRCDateInMilliseconds = (lastDRCDateInSecondsHigh << 32) | (lastDRCDateInSecondsLow & 0xFFFFFFFFL);
1025
 
//        } else {
1026
 
//            lastDRCDateInMilliseconds = ((Long)lastDRCDateObject).longValue();
1027
 
//        }
1028
1638
        date.setValue(lastDRCDateInMilliseconds);
1029
1639
        return true;
1030
1640
    }
1038
1648
     */
1039
1649
    private static StoreDRCInfo getCellGoodDRCDateAndBits(Cell cell, boolean spacingCheck, boolean fromDisk)
1040
1650
    {
1041
 
        HashMap<Cell,StoreDRCInfo> storedDRCDate = storedSpacingDRCDate;
 
1651
        Map<Cell,StoreDRCInfo> storedDRCDate = storedSpacingDRCDate;
1042
1652
        Variable.Key dateKey = Layout.DRC_LAST_GOOD_DATE_SPACING;
1043
1653
        Variable.Key bitKey = Layout.DRC_LAST_GOOD_BIT_SPACING;
1044
1654
 
1083
1693
                    else
1084
1694
                        System.out.println("No valid bit associated to DRC data was found as cell variable");
1085
1695
                }
1086
 
//                Variable varBits = cell.getVar(bitKey, Integer.class);
1087
 
//                if (varBits == null) // old Byte class
1088
 
//                {
1089
 
//                    varBits = cell.getVar(bitKey, Byte.class);
1090
 
//                    if (varBits != null)
1091
 
//                        thisByte =((Byte)varBits.getObject()).byteValue();
1092
 
//                    else
1093
 
//                        System.out.println("No valid bit associated to DRC data was found as cell variable");
1094
 
//                }
1095
 
//                else
1096
 
//                    thisByte = ((Integer)varBits.getObject()).intValue();
1097
1696
            }
1098
1697
            data.bits = thisByte;
1099
1698
            data.date = lastDRCDateInMilliseconds.longValue();
1201
1800
        Foundry foundry = tech.getSelectedFoundry();
1202
1801
        if (foundry != null)
1203
1802
        {
1204
 
                switch(foundry.getType())
1205
 
                {
1206
 
                    case MOSIS:
1207
 
                        bits |= DRC_BIT_MOSIS_FOUNDRY;
1208
 
                        break;
1209
 
                    case TSMC:
1210
 
                        bits |= DRC_BIT_TSMC_FOUNDRY;
1211
 
                        break;
1212
 
                    case ST:
1213
 
                        bits |= DRC_BIT_ST_FOUNDRY;
1214
 
                        break;
1215
 
                }
 
1803
            bits |= foundry.getType().getBit();
1216
1804
        }
1217
1805
        return bits;
1218
1806
    }
1221
1809
     * Check networks rules of this Cell.
1222
1810
     * @param errorLog error logger
1223
1811
     * @param cell cell to check
1224
 
     * @param true if this is layout cell.
1225
1812
     */
1226
1813
    private static void checkNetworks(ErrorLogger errorLog, Cell cell, boolean isLayout) {
1227
1814
        final int errorSortNetworks = 0;
1228
1815
        final int errorSortNodes = 1;
1229
 
        HashMap<NodeProto,ArrayList<NodeInst>> strangeNodes = null;
1230
 
        HashMap<NodeProto,ArrayList<NodeInst>> unconnectedPins = null;
 
1816
        Map<NodeProto,ArrayList<NodeInst>> strangeNodes = null;
 
1817
        Map<NodeProto,ArrayList<NodeInst>> unconnectedPins = null;
1231
1818
        for (int i = 0, numNodes = cell.getNumNodes(); i < numNodes; i++) {
1232
1819
            NodeInst ni = cell.getNode(i);
1233
1820
            NodeProto np = ni.getProto();
1298
1885
        }
1299
1886
    }
1300
1887
 
 
1888
    static boolean checkNodeSize(NodeInst ni, Cell cell, ReportInfo reportInfo)
 
1889
    {
 
1890
        boolean errorsFound = false;
 
1891
        // check node for minimum size
 
1892
        NodeProto np = ni.getProto();
 
1893
        PrimitiveNode.NodeSizeRule sizeRule = getMinSize(np);
 
1894
                if (sizeRule != null)
 
1895
                {
 
1896
            PrimitiveNodeSize npSize = ni.getNodeInstSize(null);
 
1897
            List<PrimitiveNode.NodeSizeRule.NodeSizeRuleError> errorsList = sizeRule.checkSize(npSize);
 
1898
//            EPoint niSize = new EPoint(ni.getXSize(), ni.getYSize());
 
1899
//            EPoint niBase = new EPoint(ni.getLambdaBaseXSize(), ni.getLambdaBaseYSize());
 
1900
//            List<PrimitiveNode.NodeSizeRule.NodeSizeRuleError> errorsLis = sizeRule.checkSize(niSize, niBase);
 
1901
 
 
1902
            if (errorsList != null)
 
1903
            {
 
1904
                for (PrimitiveNode.NodeSizeRule.NodeSizeRuleError e : errorsList)
 
1905
                {
 
1906
                    createDRCErrorLogger(reportInfo, DRC.DRCErrorType.MINSIZEERROR, e.message, cell,
 
1907
                        e.minSize, e.actual, sizeRule.getRuleName(), null, ni, null, null, null, null);
 
1908
                    errorsFound = true;
 
1909
                }
 
1910
            }
 
1911
        }
 
1912
        return errorsFound;
 
1913
    }
 
1914
 
1301
1915
    /****************************** OPTIONS ******************************/
1302
1916
 
1303
1917
        private static Pref cacheIncrementalDRCOn = Pref.makeBooleanPref("IncrementalDRCOn", tool.prefs, false);
1312
1926
         * @param on true if DRC should be done incrementally.
1313
1927
         */
1314
1928
        public static void setIncrementalDRCOn(boolean on) { cacheIncrementalDRCOn.setBoolean(on); }
 
1929
        /**
 
1930
         * Method to tell whether DRC should be done incrementally, by default.
 
1931
         * @return true if DRC should be done incrementally, by default.
 
1932
         */
 
1933
        public static boolean isFactoryIncrementalDRCOn() { return cacheIncrementalDRCOn.getBooleanFactoryValue(); }
1315
1934
 
1316
1935
        private static Pref cacheInteractiveDRCDragOn = Pref.makeBooleanPref("InteractiveDRCDrag", tool.prefs, true);
1317
1936
        /**
1325
1944
         * @param on true if DRC violations should be shown while nodes and arcs are dragged.
1326
1945
         */
1327
1946
        public static void setInteractiveDRCDragOn(boolean on) { cacheInteractiveDRCDragOn.setBoolean(on); }
 
1947
        /**
 
1948
         * Method to tell whether DRC violations should be shown while nodes and arcs are dragged, by default.
 
1949
         * @return true if DRC violations should be shown while nodes and arcs are dragged, by default.
 
1950
         */
 
1951
        public static boolean isFactoryInteractiveDRCDragOn() { return cacheInteractiveDRCDragOn.getBooleanFactoryValue(); }
1328
1952
 
1329
1953
    /** Logging Type **/
1330
1954
    private static Pref cacheErrorLoggingType = Pref.makeStringPref("ErrorLoggingType", tool.prefs,
1335
1959
         * @return integer representing error type
1336
1960
         */
1337
1961
        public static DRCCheckLogging getErrorLoggingType() {return DRCCheckLogging.valueOf(cacheErrorLoggingType.getString());}
1338
 
 
1339
1962
        /**
1340
1963
         * Method to set DRC logging type.
1341
 
         * @param type representing error logging mode
 
1964
         * @param type representing error logging mode.
1342
1965
         */
1343
1966
        public static void setErrorLoggingType(DRCCheckLogging type) { cacheErrorLoggingType.setString(type.name()); }
 
1967
        /**
 
1968
         * Method to retrieve logging type in DRC, by default.
 
1969
         * @return integer representing error type, by default.
 
1970
         */
 
1971
        public static DRCCheckLogging getFactoryErrorLoggingType() {return DRCCheckLogging.valueOf(cacheErrorLoggingType.getStringFactoryValue());}
1344
1972
 
1345
1973
    /** ErrorLevel **/
1346
1974
    private static Pref cacheErrorCheckLevel = Pref.makeIntPref("ErrorCheckLevel", tool.prefs,
1347
1975
            DRCCheckMode.ERROR_CHECK_DEFAULT.mode());
1348
1976
        /**
1349
 
         * Method to retrieve checking level in DRC
 
1977
         * Method to retrieve checking level in DRC.
1350
1978
         * The default is "ERROR_CHECK_DEFAULT".
1351
 
         * @return integer representing error type
 
1979
         * @return integer representing error type.
1352
1980
         */
1353
1981
        public static DRCCheckMode getErrorType()
1354
1982
    {
1359
1987
        }
1360
1988
        return null;
1361
1989
    }
1362
 
 
1363
1990
        /**
1364
1991
         * Method to set DRC error type.
1365
 
         * @param type representing error level
 
1992
         * @param type representing error level.
1366
1993
         */
1367
1994
        public static void setErrorType(DRCCheckMode type) { cacheErrorCheckLevel.setInt(type.mode()); }
 
1995
        /**
 
1996
         * Method to retrieve checking level in DRC, by default.
 
1997
         * @return integer representing error type, by default.
 
1998
         */
 
1999
        public static DRCCheckMode getFactoryErrorType()
 
2000
    {
 
2001
        int val = cacheErrorCheckLevel.getIntFactoryValue();
 
2002
        for (DRCCheckMode p : DRCCheckMode.values())
 
2003
        {
 
2004
            if (p.mode() == val) return p;
 
2005
        }
 
2006
        return null;
 
2007
    }
1368
2008
 
1369
2009
        private static Pref cacheIgnoreCenterCuts = Pref.makeBooleanPref("IgnoreCenterCuts", tool.prefs, false);
1370
2010
//    static { cacheIgnoreCenterCuts.attachToObject(tool, "Tools/DRC tab", "DRC ignores center cuts in large contacts"); }
1381
2021
         * @param on true if DRC should ignore center cuts in large contacts.
1382
2022
         */
1383
2023
        public static void setIgnoreCenterCuts(boolean on) { cacheIgnoreCenterCuts.setBoolean(on); }
 
2024
        /**
 
2025
         * Method to tell whether DRC should ignore center cuts in large contacts, by default.
 
2026
         * Only the perimeter of cuts will be checked.
 
2027
         * @return true if DRC should ignore center cuts in large contacts, by default.
 
2028
         */
 
2029
        public static boolean isFactoryIgnoreCenterCuts() { return cacheIgnoreCenterCuts.getBooleanFactoryValue(); }
1384
2030
 
1385
2031
    private static Pref cacheIgnoreAreaChecking = Pref.makeBooleanPref("IgnoreAreaCheck", tool.prefs, false);
1386
2032
//    static { cacheIgnoreAreaChecking.attachToObject(tool, "Tools/DRC tab", "DRC ignores area checking"); }
1395
2041
         * @param on true if DRC should ignore minimum/enclosed area checking.
1396
2042
         */
1397
2043
        public static void setIgnoreAreaChecking(boolean on) { cacheIgnoreAreaChecking.setBoolean(on); }
 
2044
        /**
 
2045
         * Method to tell whether DRC should ignore minimum/enclosed area checking, by default.
 
2046
         * @return true if DRC should ignore minimum/enclosed area checking, by default.
 
2047
         */
 
2048
        public static boolean isFactoryIgnoreAreaChecking() { return cacheIgnoreAreaChecking.getBooleanFactoryValue(); }
1398
2049
 
1399
2050
    private static Pref cacheIgnoreExtensionRuleChecking = Pref.makeBooleanPref("IgnoreExtensionRuleCheck", tool.prefs, false);
1400
2051
//    static { cacheIgnoreExtensionRuleChecking.attachToObject(tool, "Tools/DRC tab", "DRC extension rule checking"); }
1409
2060
         * @param on true if DRC should check extension rules.
1410
2061
         */
1411
2062
        public static void setIgnoreExtensionRuleChecking(boolean on) { cacheIgnoreExtensionRuleChecking.setBoolean(on); }
 
2063
        /**
 
2064
         * Method to tell whether DRC should check extension rules, by default.
 
2065
         * @return true if DRC should check extension rules, by default.
 
2066
         */
 
2067
        public static boolean isFactoryIgnoreExtensionRuleChecking() { return cacheIgnoreExtensionRuleChecking.getBooleanFactoryValue(); }
1412
2068
 
1413
2069
    private static Pref cacheStoreDatesInMemory = Pref.makeBooleanPref("StoreDatesInMemory", tool.prefs, false);
1414
2070
    /**
1422
2078
     * @param on true if DRC dates should be stored in memory or not.
1423
2079
     */
1424
2080
    public static void setDatesStoredInMemory(boolean on) { cacheStoreDatesInMemory.setBoolean(on); }
 
2081
    /**
 
2082
     * Method to tell whether DRC dates should be stored in memory or not, by default.
 
2083
     * @return true if DRC dates should be stored in memory or not, by default.
 
2084
     */
 
2085
    public static boolean isFactoryDatesStoredInMemory() { return cacheStoreDatesInMemory.getBooleanFactoryValue(); }
1425
2086
 
1426
2087
    private static Pref cacheInteractiveLog = Pref.makeBooleanPref("InteractiveLog", tool.prefs, false);
1427
2088
    /**
1435
2096
     * @param on true if DRC loggers should be displayed in Explorer immediately.
1436
2097
     */
1437
2098
    public static void setInteractiveLogging(boolean on) { cacheInteractiveLog.setBoolean(on); }
 
2099
    /**
 
2100
     * Method to tell whether DRC loggers should be displayed in Explorer immediately, by default.
 
2101
     * @return true if DRC loggers should be displayed in Explorer immediately or not, by default.
 
2102
     */
 
2103
    public static boolean isFactoryInteractiveLoggingOn() { return cacheInteractiveLog.getBooleanFactoryValue(); }
1438
2104
 
1439
2105
    private static Pref cacheMinAreaAlgo = Pref.makeStringPref("MinAreaAlgorithm", tool.prefs, DRCCheckMinArea.AREA_LOCAL.name());
1440
2106
    /**
1448
2114
     * @param mode DRCCheckMinArea type to set
1449
2115
     */
1450
2116
    public static void setMinAreaAlgoOption(DRCCheckMinArea mode) { cacheMinAreaAlgo.setString(mode.name()); }
 
2117
    /**
 
2118
     * Method to tell which min area algorithm to use, by default.
 
2119
     * @return true if DRC loggers should be displayed in Explorer immediately or not, by default.
 
2120
     */
 
2121
    public static DRCCheckMinArea getFactoryMinAreaAlgoOption() { return DRCCheckMinArea.valueOf(cacheMinAreaAlgo.getStringFactoryValue()); }
1451
2122
 
1452
2123
    private static Pref cacheMultiThread = Pref.makeBooleanPref("MinMultiThread", tool.prefs, false);
1453
2124
    /**
1461
2132
     * @param mode True if it will run a multi-threaded version.
1462
2133
     */
1463
2134
    public static void setMultiThreaded(boolean mode) { cacheMultiThread.setBoolean(mode); }
 
2135
    /**
 
2136
     * Method to tell whether DRC should run in a single thread or multi-threaded, by default.
 
2137
     * @return true if DRC run in a multi-threaded fashion, by default.
 
2138
     */
 
2139
    public static boolean isFactoryMultiThreaded() { return cacheMultiThread.getBooleanFactoryValue(); }
1464
2140
 
1465
2141
    /****************************** END OF OPTIONS ******************************/
1466
2142
 
1471
2147
    static void addDRCUpdate(int spacingBits,
1472
2148
                             Set<Cell> goodSpacingDRCDate, Set<Cell> cleanSpacingDRCDate,
1473
2149
                             Set<Cell> goodAreaDRCDate, Set<Cell> cleanAreaDRCDate,
1474
 
                             HashMap<Geometric, List<Variable>> newVariables)
 
2150
                             Map<Geometric, List<Variable>> newVariables)
1475
2151
    {
1476
2152
        boolean goodSpace = (goodSpacingDRCDate != null && goodSpacingDRCDate.size() > 0);
1477
2153
        boolean cleanSpace = (cleanSpacingDRCDate != null && cleanSpacingDRCDate.size() > 0);
1492
2168
        new DRCReset(startJob);
1493
2169
        }
1494
2170
 
 
2171
    /***********************************
 
2172
     * DRCReset class
 
2173
     ***********************************/
1495
2174
    private static class DRCReset extends Job
1496
2175
    {
1497
2176
        DRCReset(boolean startJob)
1525
2204
        }
1526
2205
    }
1527
2206
 
 
2207
    /***********************************
 
2208
     * DRCUpdate class
 
2209
     ***********************************/
1528
2210
    /**
1529
2211
         * Class to save good Layout DRC dates in a new thread or add new variables in Schematic DRC
1530
2212
         */
1534
2216
                Set<Cell> cleanSpacingDRCDate;
1535
2217
        Set<Cell> goodAreaDRCDate;
1536
2218
                Set<Cell> cleanAreaDRCDate;
1537
 
        HashMap<Geometric,List<Variable>> newVariables;
 
2219
        Map<Geometric,List<Variable>> newVariables;
1538
2220
        int activeBits = Layout.DRC_LAST_GOOD_BIT_DEFAULT;
1539
2221
 
1540
2222
                public DRCUpdate(int bits,
1541
2223
                         Set<Cell> goodSpacingDRCD, Set<Cell> cleanSpacingDRCD,
1542
2224
                         Set<Cell> goodAreaDRCD, Set<Cell> cleanAreaDRCD,
1543
 
                         HashMap<Geometric, List<Variable>> newVars)
 
2225
                         Map<Geometric, List<Variable>> newVars)
1544
2226
                {
1545
2227
                        super("Update DRC data", tool, Type.CHANGE, null, null, Priority.USER);
1546
2228
            this.goodSpacingDRCDate = goodSpacingDRCD;
1562
2244
         * Template method to set DAte and bits information for a given map.
1563
2245
         * @param inMemory
1564
2246
         */
1565
 
        private static void setInformation(HashMap<Cell,StoreDRCInfo> storedDRCDate,
 
2247
        private static void setInformation(Map<Cell,StoreDRCInfo> storedDRCDate,
1566
2248
                                           Set<Cell> goodDRCDate, Set<Cell> cleanDRCDate,
1567
2249
                                           Variable.Key key, int bits, boolean inMemory)
1568
2250
        {
1569
 
            HashSet<Cell> goodDRCCells = new HashSet<Cell>();
1570
 
            Long time = System.currentTimeMillis();
 
2251
            Set<Cell> goodDRCCells = new HashSet<Cell>();
 
2252
            long time = System.currentTimeMillis();
1571
2253
 
1572
2254
            if (goodDRCDate != null)
1573
2255
            {
1644
2326
        return true;
1645
2327
    }
1646
2328
}
 
2329
 
 
2330
 
 
2331
 
 
2332
/**************************************************************************************************************
 
2333
         *  CellLayersContainer class
 
2334
 **************************************************************************************************************/
 
2335
class CellLayersContainer implements Serializable
 
2336
{
 
2337
    private Map<NodeProto, Set<String>> cellLayersMap;
 
2338
 
 
2339
    CellLayersContainer() {
 
2340
        cellLayersMap = new HashMap<NodeProto, Set<String>>();
 
2341
    }
 
2342
 
 
2343
    Set<String> getLayersSet(NodeProto cell) {
 
2344
        return cellLayersMap.get(cell);
 
2345
    }
 
2346
 
 
2347
    void addCellLayers(Cell cell, Set<String> set) {
 
2348
        cellLayersMap.put(cell, set);
 
2349
    }
 
2350
 
 
2351
    boolean addCellLayers(Cell cell, Layer layer) {
 
2352
        Set<String> set = cellLayersMap.get(cell);
 
2353
 
 
2354
        // first time the cell is accessed
 
2355
        if (set == null) {
 
2356
            set = new HashSet<String>(1);
 
2357
            cellLayersMap.put(cell, set);
 
2358
        }
 
2359
        return set.add(layer.getName());
 
2360
    }
 
2361
}
 
2362
 
 
2363
/**************************************************************************************************************
 
2364
 *  CheckCellLayerEnumerator class
 
2365
 **************************************************************************************************************/
 
2366
 
 
2367
/**
 
2368
 * Class to collect which layers are available in the design
 
2369
 */
 
2370
class CheckCellLayerEnumerator extends HierarchyEnumerator.Visitor {
 
2371
    private Map<Cell, Cell> cellsMap;
 
2372
    private CellLayersContainer cellLayersCon;
 
2373
 
 
2374
    CheckCellLayerEnumerator(CellLayersContainer cellLayersC) {
 
2375
        cellsMap = new HashMap<Cell, Cell>();
 
2376
        cellLayersCon = cellLayersC;
 
2377
    }
 
2378
 
 
2379
    /**
 
2380
     * When the cell should be visited. Either it is the first time or the number of layers hasn't reached
 
2381
     * the maximum
 
2382
     *
 
2383
     * @param cell
 
2384
     * @return
 
2385
     */
 
2386
    private boolean skipCell(Cell cell) {
 
2387
        return cellsMap.get(cell) != null;
 
2388
    }
 
2389
 
 
2390
    public boolean enterCell(HierarchyEnumerator.CellInfo info) {
 
2391
        Cell cell = info.getCell();
 
2392
        if (skipCell(cell)) return false; // skip
 
2393
        cellsMap.put(cell, cell);
 
2394
        return true;
 
2395
    }
 
2396
 
 
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>();
 
2401
 
 
2402
        // Nodes
 
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);
 
2408
                set.addAll(s);
 
2409
                assert (s != null); // it must have layers? unless is empty
 
2410
            } else {
 
2411
                if (tempNodeMap.get(np) != null)
 
2412
                    continue; // done with this PrimitiveNode
 
2413
                tempNodeMap.put(np, np);
 
2414
 
 
2415
                if (NodeInst.isSpecialNode(ni)) // like pins
 
2416
                    continue;
 
2417
 
 
2418
                PrimitiveNode pNp = (PrimitiveNode) np;
 
2419
                for (Technology.NodeLayer nLayer : pNp.getLayers()) {
 
2420
                    Layer layer = nLayer.getLayer();
 
2421
                    set.add(layer.getName());
 
2422
                }
 
2423
            }
 
2424
        }
 
2425
 
 
2426
        // Arcs
 
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());
 
2436
            }
 
2437
        }
 
2438
        return set;
 
2439
    }
 
2440
 
 
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);
 
2446
    }
 
2447
 
 
2448
    public boolean visitNodeInst(Nodable no, HierarchyEnumerator.CellInfo info) {
 
2449
        NodeInst ni = no.getNodeInst();
 
2450
 
 
2451
        // true only for Cells
 
2452
        return ni.isCellInstance();
 
2453
    }
 
2454
}
 
2455
 
 
2456
/***************** LAYER INTERACTIONS ******************/
 
2457
 
 
2458
/**************************************************************************************************************
 
2459
 *  ValidationLayers class
 
2460
 **************************************************************************************************************/
 
2461
class ValidationLayers
 
2462
{
 
2463
    /* for figuring out which layers are valid for DRC */
 
2464
        private Technology layersValidTech = null;
 
2465
        private boolean [] layersValid;
 
2466
 
 
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;
 
2471
 
 
2472
    private ErrorLogger errorLogger;
 
2473
    private Cell topCell;
 
2474
    private DRCRules currentRules;
 
2475
 
 
2476
    /**
 
2477
         * Class to determine which layers in a Technology are valid.
 
2478
         */
 
2479
        ValidationLayers(ErrorLogger logger, Cell cell, DRCRules rules)
 
2480
        {
 
2481
        topCell = cell;
 
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;
 
2490
 
 
2491
        for(Iterator<PrimitiveNode> it = layersValidTech.getNodes(); it.hasNext(); )
 
2492
                {
 
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++)
 
2497
                        {
 
2498
                                Layer layer = layers[i].getLayer();
 
2499
                                layersValid[layer.getIndex()] = true;
 
2500
                        }
 
2501
                }
 
2502
                for(Iterator<ArcProto> it = layersValidTech.getArcs(); it.hasNext(); )
 
2503
                {
 
2504
                        ArcProto ap = it.next();
 
2505
                        if (ap.isNotUsed()) continue;
 
2506
                        for (Iterator<Layer> lIt = ap.getLayerIterator(); lIt.hasNext(); )
 
2507
                        {
 
2508
                                Layer layer = lIt.next();
 
2509
                                layersValid[layer.getIndex()] = true;
 
2510
                        }
 
2511
                }
 
2512
 
 
2513
        cacheValidLayers(layersValidTech);
 
2514
        buildLayerInteractions(layersValidTech);
 
2515
    }
 
2516
 
 
2517
    boolean isABadLayer(Technology tech, int layerNumber)
 
2518
    {
 
2519
        return (tech == layersValidTech && !layersValid[layerNumber]);
 
2520
    }
 
2521
 
 
2522
   /**
 
2523
     * Method to determine which layers in a Technology are valid.
 
2524
     */
 
2525
    void cacheValidLayers(Technology tech)
 
2526
    {
 
2527
        if (tech == null) return;
 
2528
        if (layersValidTech == tech) return;
 
2529
 
 
2530
        layersValidTech = tech;
 
2531
 
 
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();)
 
2538
        {
 
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++)
 
2543
            {
 
2544
                Layer layer = layers[i].getLayer();
 
2545
                layersValid[layer.getIndex()] = true;
 
2546
            }
 
2547
        }
 
2548
        for (Iterator<ArcProto> it = tech.getArcs(); it.hasNext();)
 
2549
        {
 
2550
            ArcProto ap = it.next();
 
2551
            if (ap.isNotUsed()) continue;
 
2552
            for (Iterator<Layer> lIt = ap.getLayerIterator(); lIt.hasNext();)
 
2553
            {
 
2554
                Layer layer = lIt.next();
 
2555
                layersValid[layer.getIndex()] = true;
 
2556
            }
 
2557
        }
 
2558
    }
 
2559
 
 
2560
    /**
 
2561
     * Method to build the internal data structures that tell which layers interact with
 
2562
     * which primitive nodes in technology "tech".
 
2563
     */
 
2564
    void buildLayerInteractions(Technology tech)
 
2565
    {
 
2566
        Technology old = layerInterTech;
 
2567
        if (layerInterTech == tech) return;
 
2568
 
 
2569
        layerInterTech = tech;
 
2570
        int numLayers = tech.getNumLayers();
 
2571
 
 
2572
        // build the node table
 
2573
        if (layersInterNodes != null && old != null)
 
2574
        {
 
2575
            errorLogger.logWarning("Switching from '" + old.getTechName() +
 
2576
                "' to '" + tech.getTechName() + "' in DRC process. Check for non desired nodes in ",
 
2577
                topCell, -1);
 
2578
        }
 
2579
 
 
2580
        layersInterNodes = new HashMap<PrimitiveNode, boolean[]>();
 
2581
        for (Iterator<PrimitiveNode> it = tech.getNodes(); it.hasNext();)
 
2582
        {
 
2583
            PrimitiveNode np = it.next();
 
2584
            if (np.isNotUsed()) continue;
 
2585
            boolean[] layersInNode = new boolean[numLayers];
 
2586
            Arrays.fill(layersInNode, false);
 
2587
 
 
2588
            Technology.NodeLayer[] layers = np.getLayers();
 
2589
            Technology.NodeLayer[] eLayers = np.getElectricalLayers();
 
2590
            if (eLayers != null) layers = eLayers;
 
2591
            for (Technology.NodeLayer l : layers)
 
2592
            {
 
2593
                Layer layer = l.getLayer();
 
2594
                if (layer.isNonElectrical())
 
2595
                    continue; // such as pseudo
 
2596
                for (Iterator<Layer> lIt = tech.getLayers(); lIt.hasNext();)
 
2597
                {
 
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;
 
2603
                }
 
2604
            }
 
2605
            layersInterNodes.put(np, layersInNode);
 
2606
        }
 
2607
 
 
2608
        // build the arc table
 
2609
        layersInterArcs = new HashMap<ArcProto, boolean[]>();
 
2610
        for (Iterator<ArcProto> it = tech.getArcs(); it.hasNext();)
 
2611
        {
 
2612
            ArcProto ap = it.next();
 
2613
            boolean[] layersInArc = new boolean[numLayers];
 
2614
            Arrays.fill(layersInArc, false);
 
2615
 
 
2616
            for (Iterator<Layer> alIt = ap.getLayerIterator(); alIt.hasNext();)
 
2617
            {
 
2618
                Layer layer = alIt.next();
 
2619
                for (Iterator<Layer> lIt = tech.getLayers(); lIt.hasNext();)
 
2620
                {
 
2621
                    Layer oLayer = lIt.next();
 
2622
                    if (currentRules.isAnySpacingRule(layer, oLayer))
 
2623
                        layersInArc[oLayer.getIndex()] = true;
 
2624
                }
 
2625
            }
 
2626
            layersInterArcs.put(ap, layersInArc);
 
2627
        }
 
2628
    }
 
2629
 
 
2630
    /**
 
2631
     * Method to determine whether layer "layer" interacts in any way with a node of type "np".
 
2632
     * If not, returns FALSE.
 
2633
     */
 
2634
    boolean checkLayerWithNode(Layer layer, NodeProto np)
 
2635
    {
 
2636
        buildLayerInteractions(np.getTechnology());
 
2637
 
 
2638
        // find this node in the table
 
2639
        boolean[] validLayers = layersInterNodes.get(np);
 
2640
        if (validLayers == null) return false;
 
2641
        return validLayers[layer.getIndex()];
 
2642
    }
 
2643
 
 
2644
    /**
 
2645
     * Method to determine whether layer "layer" interacts in any way with an arc of type "ap".
 
2646
     * If not, returns FALSE.
 
2647
     */
 
2648
    boolean checkLayerWithArc(Layer layer, ArcProto ap)
 
2649
    {
 
2650
        buildLayerInteractions(ap.getTechnology());
 
2651
 
 
2652
        // find this node in the table
 
2653
        boolean[] validLayers = layersInterArcs.get(ap);
 
2654
        if (validLayers == null) return false;
 
2655
        return validLayers[layer.getIndex()];
 
2656
    }
 
2657
}
 
2658
 
 
2659
    /**
 
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).
 
2667
         */
 
2668
        class CheckInst
 
2669
        {
 
2670
                int localIndex;
 
2671
                int multiplier;
 
2672
                int offset;
 
2673
        }
 
2674
 
 
2675
        /**
 
2676
         * The CheckProto object is placed on every cell and is used only temporarily
 
2677
         * to number the instances.
 
2678
         */
 
2679
        class CheckProto
 
2680
        {
 
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;
 
2689
        }
 
2690
 
 
2691
        /**
 
2692
         * The InstanceInter object records interactions between two cell instances and prevents checking
 
2693
         * them multiple times.
 
2694
         */
 
2695
        class InstanceInter
 
2696
        {
 
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;
 
2702
        }
 
 
b'\\ No newline at end of file'