DrcCmosbGapHackImpl.Mesa
Copyright Ó 1988 by Xerox Corporation. All rights reserved.
Opera di Giordano Bruno Beretta January 21, 1988 5:36:16 pm PST
gbb January 21, 1988 5:36:46 pm PST
Spinned out of DrcCMOSBimpl.Mesa because of "Storage overflow in pass 4" of compiler.
DIRECTORY
CD USING [Number],
CDBasics USING [empty, NonEmpty],
CDBasicsInline USING [MapRect],
CMosB USING [lambda, ndif, nwellCont, pdif, pol, pwellCont],
CoreGeometry USING [EachInstanceProc, EnumerateGeometry, FlattenInstance, InlineBBox],
CStitching USING [all, ChangeEnumerateArea, ChangeRect, IsEmpty, ListArea, NewTesselation, Rect, RectProc, Region, Tesselation, TrustedDisposeTesselation],
Drc USING [Rect, State, Transf, Wire, WireInstance, WireSet],
DrcCmosbGapHack USING [notChannel],
DrcUtilities USING [Bloat, Contains, Intersecting, Intersection, Layer, SameLayer],
Saguaro USING [gate];
DrcCmosbGapHackImpl: CEDAR PROGRAM
IMPORTS CDBasics, CDBasicsInline, CMosB, CoreGeometry, CStitching, DrcUtilities, Saguaro
EXPORTS DrcCmosbGapHack
SHARES Drc
~ BEGIN OPEN CMosB, Drc, DrcCmosbGapHack, DrcUtilities;
Region: TYPE ~ LIST OF REF CStitching.Region;
Tess: TYPE ~ CStitching.Tesselation;
empty: REF ~ NIL;
nothing: REF INT ~ NEW [INT];
universe: Rect ~ CStitching.all;
gate: Layer ~ Saguaro.gate;
lambda: CD.Number ~ CMosB.lambda;
rectClass: ATOM ~ $Rect;
wellRectClass: ATOM ~ $WellRect;
pinClass: ATOM ~ $PinOb0;
markClass: ATOM ~ $AlignmentMarkOb;
segmentClass: ATOM ~ $SymbolicSegment;
GapIsFilled: PUBLIC PROC [gap: Rect, l: Layer, w: WireInstance, state: State, additionalWire: WireInstance ← notChannel, additionalCells: LIST OF WireSet ← NIL] RETURNS [notch: LIST OF Rect] ~ BEGIN
Interim hack. Enumerates a two wire to determine whether the gap is filled somewhere. First the common case where the gap is filled by a single rectangle is examined.
cracker: Tess ← CStitching.NewTesselation [stopFlag: state.abort];
nibbledCracker: Region; notchBB: Rect ← CDBasics.empty;
transf: Transf ← w.transf;
Nibble: CStitching.RectProc ~ BEGIN
[plane: REF Tesselation, rect: Rect, oldValue: REF, data: REF]
WITH oldValue SELECT FROM
any: ATOM => cracker.ChangeRect [rect: rect, new: empty];
ENDCASE => NULL
END; -- Nibble
Bite: CStitching.RectProc ~ BEGIN
[plane: REF Tesselation, rect: Rect, oldValue: REF, data: REF]
WITH oldValue SELECT FROM
any: ATOM => NULL;
ENDCASE => cracker.ChangeRect [rect: rect, new: data]
END; -- Bite
FindPatch: CoreGeometry.EachInstanceProc ~ BEGIN
PROC [instance: CdInsts] RETURNS [quit: BOOLFALSE]
This is the common case.
SELECT instance.obj.class.objectType FROM
rectClass, wellRectClass =>
IF (SameLayer [instance.obj.layer, l] OR (SameLayer [instance.obj.layer, gate] AND ((l = pdif) OR (l = ndif)))) THEN BEGIN
r: Rect ← CDBasicsInline.MapRect [CoreGeometry.InlineBBox [instance], transf];
La lunghezza minima di una griglia e 2, mentre la separazione della diffusione e di 3 e mezzo. Tanto per simplificare le cose, ingrandisco di uno per lato, arrivando a 4. Questo solve pure il problema dell'estensione della griglia che va trattata come una griglia per la regola di separazione tra polisilicio e diffusione.
IF (instance.obj.layer = gate) THEN r ← Bloat [r, lambda];
IF Contains [r, gap] THEN {quit ← TRUE; notch ← NIL}
END;
markClass, segmentClass, pinClass => NULL;
ENDCASE => quit ← CoreGeometry.FlattenInstance [instance, FindPatch]
END; -- FindPatch
FindFancyPatch: CoreGeometry.EachInstanceProc ~ BEGIN
PROC [instance: CdInsts] RETURNS [quit: BOOLFALSE]
SELECT instance.obj.class.objectType FROM
rectClass, wellRectClass =>
IF (SameLayer [instance.obj.layer, l] OR (SameLayer [instance.obj.layer, gate] AND ((l = pdif) OR (l = ndif)))) THEN BEGIN
r: Rect ← CDBasicsInline.MapRect [CoreGeometry.InlineBBox [instance], transf];
Recognize the case of osculating rectangles on two adjacent edges.
IF (instance.obj.layer = gate) THEN r ← Bloat [r, lambda] ELSE r ← Bloat [r, 1];
IF Intersecting [r, gap] THEN
cracker.ChangeEnumerateArea [Intersection [r, gap], Nibble, NIL, empty];
IF cracker.IsEmpty [] THEN quit ← TRUE
END;
markClass, segmentClass, pinClass => NULL;
ENDCASE => quit ← CoreGeometry.FlattenInstance [instance, FindFancyPatch]
END; -- FindFancyPatch
IF (gap.x1 = gap.x2) OR (gap.y1 = gap.y2) THEN RETURN [NIL];
notch ← LIST [gap]; IF (w.local = NIL) THEN RETURN [notch];
IF state.attributes.EnumerateGeometry [w.local, FindPatch] THEN RETURN [NIL];
cracker ← CStitching.NewTesselation [stopFlag: state.abort];
cracker.ChangeEnumerateArea [gap, Bite, $gap, nothing];
IF state.attributes.EnumerateGeometry [w.local, FindFancyPatch] THEN RETURN [NIL];
IF (additionalWire.local # NIL) THEN BEGIN
transf ← additionalWire.transf;
IF state.attributes.EnumerateGeometry [additionalWire.local, FindPatch] THEN
RETURN [NIL];
IF state.attributes.EnumerateGeometry [additionalWire.local, FindFancyPatch] THEN RETURN [NIL]
END;
Gap might need more than one subcell to be fixed:
FOR cl: LIST OF WireSet ← additionalCells, cl.rest WHILE cl # NIL DO
FOR i: NAT IN [0 .. cl.first.size) DO
transf ← cl.first[i].transf;
IF state.attributes.EnumerateGeometry [cl.first[i].local, FindFancyPatch] THEN RETURN [NIL]
ENDLOOP
ENDLOOP;
nibbledCracker ← cracker.ListArea [universe];notch ← NIL;
FOR n: Region ← nibbledCracker, n.rest WHILE n # NIL DO
notchBB.x1 ← MIN [notchBB.x1, n.first.rect.x1];
notchBB.y1 ← MIN [notchBB.y1, n.first.rect.y1];
notchBB.x2 ← MAX [notchBB.x2, n.first.rect.x2];
notchBB.y2 ← MAX [notchBB.y2, n.first.rect.y2];
notch ← CONS [n.first.rect, notch]
ENDLOOP;
IF CDBasics.NonEmpty [notchBB] THEN BEGIN
nibbledEdges: CARDINAL ← 0;
s, w, n, e: BOOLFALSE;
IF notchBB.x1 > gap.x1 THEN {w ← TRUE; nibbledEdges ← nibbledEdges.SUCC};
IF notchBB.y1 > gap.y1 THEN {s ← TRUE; nibbledEdges ← nibbledEdges.SUCC};
IF notchBB.x2 < gap.x2 THEN {e ← TRUE; nibbledEdges ← nibbledEdges.SUCC};
IF notchBB.y2 < gap.y2 THEN {n ← TRUE; nibbledEdges ← nibbledEdges.SUCC};
IF (nibbledEdges = 2) AND ((w AND s) OR (s AND e) OR (e AND n) OR (n AND w)) THEN notch ← NIL
END;
cracker.TrustedDisposeTesselation []
END; -- GapIsFilled
END.