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: BOOL ← FALSE]
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: BOOL ← FALSE]
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: BOOL ← FALSE;
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