WellsEtcImpl.mesa
Copyright Ó 1987 by Xerox Corporation. All rights reserved.
Giordano Bruno Beretta, March 10, 1987 1:29:25 pm PST
gbb March 30, 1987 6:16:34 pm PST
Does the checks concerning wells that cannot be made by Genista because of the lack of wells in the Core data structure. This implementation is "flat", because wells are not layed out hierarchically anyway.
Warning: while I am writing this code I am physically exausted. It starts out to work for n-, p-, and twin-wells. I am making compromises to get the thing flying. Do not try to understand this code.
DIRECTORY
CD USING [CreateDrawRef, Design, DrawProc, DrawRectProc, DrawRef, Layer, LayerKey, Number, Object, ObjectClass],
CDBasics USING [Extend, Intersection, NonEmpty],
CDSimpleRules USING [MinDist, MinWidth],
CMosB USING [lambda, ndif, nwell, nwellCont, pdif, pwell, pwellCont],
CoreGeometry USING [GetObject],
CStitching USING [all, Area, ChangeRect, ChangeEnumerateArea, EEdge, EN, EnumerateArea, EnumerateNeighborhood, FindTile, ListArea, NE, NEdge, NewTesselation, RectProc, Region, ResetTesselation, SEdge, SW, Tesselation, Tile, TileProc, WEdge, WS],
Drc USING [CellProc, CoreCell, MarkError, Rect, State, Tech, WirePairProc, WireProc],
DrcCMOSB USING [cMosBcomplete, AddDrcProcs],
Rope USING [ROPE];
WellsEtcImpl: CEDAR PROGRAM
IMPORTS CD, CDBasics, CDSimpleRules, CMosB, CoreGeometry, CStitching, Drc, DrcCMOSB
SHARES Drc, DrcCMOSB
~ BEGIN OPEN CMosB, Drc, DrcCMOSB;
Types and constants
GenistaCMosBwells: PUBLIC Tech;
Verifies the wells and related stuff taking its information from the ChipNDale design.
LocalState: TYPE ~ REF LocalStateRec;  -- needed to mark errors
LocalStateRec: TYPE ~ RECORD [globalState: State, obj: CoreCell, wellTess: Tess];
CornerCheckData: TYPE ~ REF CornerCheckDataRec;
CornerCheckDataRec: TYPE ~ RECORD [state: LocalState, key: ATOM, rule: Rule, detail: Rect ← universe];
doNotAnalyse: ATOM = $DoNotDRC;
Region: TYPE ~ LIST OF REF CStitching.Region;
Tess: TYPE ~ CStitching.Tesselation;
Tile: TYPE ~ CStitching.Tile;
empty: REF ~ NIL;
none: ATOM ~ NIL;
nothing: REF INT ~ NEW [INT];
universe: Rect ~ CStitching.all;
l: CD.Number ~ lambda;
fieldOxide: ATOM ~ NIL;
pWell: ATOM ~ CD.LayerKey [CMosB.pwell];
nWell: ATOM ~ CD.LayerKey [CMosB.nwell];
cachedTess: Tess; -- Assume: no concurrency !!!
The rules
Rule: TYPE ~ RECORD [extent: CD.Number, msg: Rope.ROPE];
nWellSurround: Rule ~ [5 * l, "n-well too small or p-diffusion too close to p-well"];
pWellSurround: Rule ~ [5 * l, "n-diffusion too close to n-well or p-well too small"];
nWellContact: Rule ~ [4 * l, "n-well contact too close to p-well or field oxide"];
pWellContact: Rule ~ [4 * l, "p-well contact too close to n-well"];
contactSpacing: Rule ~ [75 * l, "well contact required"];
wellSpacing: Rule ~ [CDSimpleRules.MinDist [nwell, nwell], "well spacing or notch"];
wellWidth: Rule ~ [CDSimpleRules.MinWidth [nwell], "missing well (well width)"];
In the following rules the extent is used only to determine the overlap of the error rectangle.
wellConflict: Rule ~ [2 * l, "p-well overlaps n-well"];
NinN: Rule ~ [2 * l, "n-diffusion in n-well"];
PinP: Rule ~ [2 * l, "p-diffusion in p-well"];
isolatedWell: Rule ~ [2 * l, "isolated well"];
Interface
VerifyWells: CellProc ~ BEGIN
In principio questa e una gran coglionata, pi u di natura politica che tecnica. Nella struttura Core non ci sono i cassoni, sostanzialmente perch e l'implentatore dell'estrattore sostiene che non servono a niente. A parte il fatto che non e vero (fanno parte di VDD fintanto che sono connessi), non essendo accessiblili ai clienti (CoreGeometry.EachInstanceProc, ecc. non chiamano i clienti sui cassoni) non possono venir verificati. Dato che nel C-MOS la meta della diffusione e in un cassone e che l'IFU ha dimostrato che errori del genere di diffusione e contatti del tipo sbagliato sono abbastanza frequenti, e vitale verificare queste cose.
In pratica i cassoni di soliti non seguono la gerarchia, per cui questo modulo e "piatto". Dato che i cassoni di solito sono grandi aree connesse, questo non dovrebbe essere troppo grave per la memoria.
localState: LocalState ~ NEW [LocalStateRec ← [state, cell, NIL]];
cornerData: CornerCheckData ~ NEW [CornerCheckDataRec ← [state: localState]];
o: CD.Object ~ CoreGeometry.GetObject [state.attributes, cell];
localState.wellTess ← IF (cachedTess # NIL) THEN cachedTess ELSE CStitching.NewTesselation [stopFlag: state.abort];
Smash wells into a flat tesselation of interesting areas.
EnumerateChipNDale [obj: o, state: localState, how: $getWells];
cornerData.key ← nWell; cornerData.rule ← wellWidth;
localState.wellTess.EnumerateArea [universe, CheckCorner, cornerData, none];
cornerData.key ← none; cornerData.rule ← wellSpacing;
localState.wellTess.EnumerateArea [universe, CheckCorner, cornerData, nWell];
Enumerate all diffusion rectangles and perform a query with bloated rectangles. For n-diff, an n-well is an a violation, while for p-dif both a pwell and fieldOxide are a violation.
EnumerateChipNDale [obj: o, state: localState, how: $sex];
EnumerateChipNDale [obj: o, state: localState, how: $contactsPos];
EnumerateChipNDale [obj: o, state: localState, how: $connection];
localState.wellTess.ChangeEnumerateArea [universe, FlagIsland, localState, empty];
EnumerateChipNDale [obj: o, state: localState, how: $contactsInfl];
localState.wellTess.ChangeEnumerateArea [universe, FlagUnconnected, localState, empty];
CStitching.ResetTesselation [localState.wellTess]
END; -- VerifyWells
Operations on ChipNDale objects
ExtractWells: CD.DrawRectProc ~ BEGIN
[r: Rect, l: Layer, pr: DrawRef]
state: LocalState ~ NARROW [pr.devicePrivate];
IF (l = nwell) OR (l = pwell) THEN InsertWell [r: r, type: CD.LayerKey[l], state: state]
END; -- ExtractWells
InsertContact: CD.DrawRectProc ~ BEGIN
[r: Rect, l: Layer, pr: DrawRef]
Ignores sex of contacts since it already has been verified.
state: LocalState ~ NARROW [pr.devicePrivate];
IF (l = pwellCont) OR (l = nwellCont) THEN ConnectTile [r: r, state: state]
END; -- InsertContact
PropagateContact: CD.DrawRectProc ~ BEGIN
[r: Rect, l: Layer, pr: DrawRef]
Ignores sex of contacts since it already has been verified.
state: LocalState ~ NARROW [pr.devicePrivate];
IF (l = pwellCont) OR (l = nwellCont) THEN PercolateContact [r: r, state: state]
END; -- PropagateContact
DeleteContact: CD.DrawRectProc ~ BEGIN
[r: Rect, l: Layer, pr: DrawRef]
Ignores sex of contacts since it already has been verified.
state: LocalState ~ NARROW [pr.devicePrivate];
IF (l = pwellCont) OR (l = nwellCont) THEN DeleteConnected [r: r, state: state]
END; -- DeleteContact
ExtractDiff: CD.DrawRectProc ~ BEGIN
[r: Rect, l: Layer, pr: DrawRef]
state: LocalState ~ NARROW [pr.devicePrivate];
IF (l = ndif) OR (l = pdif) OR (l = pwellCont) OR (l = nwellCont) THEN Inquire [r, l, state]
END; -- ExtractDiff
EnumerateChipNDale: PROC [obj: CD.Object, state: LocalState, how: ATOM] ~ BEGIN
If wells is false, diffusion rectangles are enumerated.
dr: CD.DrawRef = CD.CreateDrawRef [[]];
dr.drawRect ← SELECT how FROM
$getWells => ExtractWells,
$sex => ExtractDiff,
$contactsPos => InsertContact,
$connection => PropagateContact,
$contactsInfl => DeleteContact,
ENDCASE => ERROR;
dr.devicePrivate ← state; dr.stopFlag ← state.globalState.abort;
obj.class.drawMe [dr, obj]
END; -- EnumerateChipNDale
Operations on the corner-stitched plane
InsertWell: PROC [r: Rect, state: LocalState, type: ATOM] ~ BEGIN
Inserts a well. This procedure ensures that wells do not overlap.
wellSpacingViolation: BOOLFALSE;
errorRect: Rect;
OccupyByWell: CStitching.RectProc ~ BEGIN
[plane: REF Tesselation, rect: Rect, oldValue: REF, data: REF]
WITH oldValue SELECT FROM
well: ATOM => IF (well # type) THEN {wellSpacingViolation ← TRUE; errorRect ← rect};
ENDCASE => -- by Cedar definition we always come here if oldValue is NIL
CStitching.ChangeRect [plane: state.wellTess, rect: rect, new: type]
END; -- OccupyByWell
state.wellTess.ChangeEnumerateArea [r, OccupyByWell, type, nothing];
IF wellSpacingViolation THEN MarkError [state.obj, state.globalState, [errorRect, wellConflict.msg]]
END; -- InsertWell
ConnectTile: PROC [r: Rect, state: LocalState] ~ BEGIN
Changes the value of the tile with a contact into a contact. Ignores sex of contacts since it already has been verified.
Contact: CStitching.RectProc ~ BEGIN
[plane: REF Tesselation, rect: Rect, oldValue: REF, data: REF]
WITH oldValue SELECT FROM
well: ATOM => state.wellTess.ChangeRect [rect: rect, new: $hasContact];
ENDCASE => NULL-- a well contact on substrate gave an error in the sex check, maximum separation of substrate contacts not checkd for the moment
END; -- Contact
state.wellTess.ChangeEnumerateArea [r, Contact, NIL, empty]
END; -- ConnectTile
PercolateContact: PROC [r: Rect, state: LocalState] ~ BEGIN
Propagates the connectedness of a tile in order to isolate islands.
DoTile: CStitching.RectProc ~ BEGIN
[plane: REF Tesselation, rect: Rect, oldValue: REF, data: REF]
tile: Tile ~ state.wellTess.FindTile [[rect.x1+1, rect.y1+1]];
WITH oldValue SELECT FROM
cond: ATOM => IF (cond = $hasContact) THEN BEGIN
tile.value ← $expanding;
state.wellTess.EnumerateNeighborhood [tile, Expand, NIL, empty];
tile.value ← $expanded
END;
ENDCASE => ERROR
END; -- DoTile
Expand: CStitching.TileProc ~ BEGIN
[tile: Tile, data: REF]
WITH tile.value SELECT FROM
cond: ATOM => IF (cond = $expanded) OR (cond = $expanding) THEN NULL
ELSE BEGIN
tile.value ← $expanding;
state.wellTess.EnumerateNeighborhood [tile, Expand, NIL, empty];
tile.value ← $expanded
END;
ENDCASE => NULL-- substrate stops expansion
END; -- Expand
state.wellTess.ChangeEnumerateArea [r, DoTile, NIL, empty]
END; -- PercolateContact
DeleteConnected: PROC [r: Rect, state: LocalState] ~ BEGIN
DESTRUCTIVE !!! Verifies that the maximum well contact spacing is fulfilled. Ignores sex of contacts since it already has been verified.
DeleteRectangle: CStitching.RectProc ~ BEGIN
[plane: REF Tesselation, rect: Rect, oldValue: REF, data: REF]
WITH oldValue SELECT FROM
any: ATOM => state.wellTess.ChangeRect [rect: rect, new: empty];
ENDCASE => ERROR
END; -- DeleteRectangle
state.wellTess.ChangeEnumerateArea [CDBasics.Extend [r, contactSpacing.extent], DeleteRectangle, NIL, empty]
END; -- DeleteConnected
Implementation
Inquire: PROC [r: Rect, layer: CD.Layer, state: LocalState] ~ BEGIN
Algorithm: If there is antagonist material in a wellSurround-sphere from diffusion, then the a violation is flagged.
bloatedRect: Rect;
wells: Region;
ispDiff: BOOL ~ (layer = pdif); ispCont: BOOL ~ (layer = nwellCont);
isnDiff: BOOL ~ (layer = ndif); isnCont: BOOL ~ (layer = pwellCont);
isP: BOOL ~ (ispDiff OR ispCont); isN: BOOL ~ (isnDiff OR isnCont);
IF NOT CDBasics.NonEmpty[r] THEN RETURN; -- empty rectangle
Verify diffusion type.
wells ← state.wellTess.ListArea [rect: r, skip: nothing];
FOR w: Region ← wells, w.rest WHILE w # NIL DO
well: ATOMNARROW [w.first.value];
IF (isP AND (well = fieldOxide)) OR (isP AND (well = pWell)) THEN
MarkError [state.obj, state.globalState, [w.first.rect, PinP.msg]];
IF (isN AND (well = nWell)) THEN
MarkError [state.obj, state.globalState, [w.first.rect, NinN.msg]]
ENDLOOP;
Verify surround.
IF (ispDiff OR isnDiff) THEN BEGIN
bloatedRect ← CDBasics.Extend [r, nWellSurround.extent];
wells ← state.wellTess.ListArea [rect: bloatedRect, skip: nothing];
FOR w: Region ← wells, w.rest WHILE w # NIL DO
well: ATOMNARROW [w.first.value];
IF (ispDiff AND (well = fieldOxide)) OR (ispDiff AND (well = pWell)) THEN
MarkError [state.obj, state.globalState, [w.first.rect, nWellSurround.msg]];
IF (isnDiff AND (well = nWell)) THEN
MarkError [state.obj, state.globalState, [w.first.rect, pWellSurround.msg]]
ENDLOOP
END
ELSE BEGIN-- is contact
bloatedRect ← CDBasics.Extend [r, nWellContact.extent];
wells ← state.wellTess.ListArea [rect: bloatedRect, skip: nothing];
FOR w: Region ← wells, w.rest WHILE w # NIL DO
well: ATOMNARROW [w.first.value];
IF (ispCont AND (well = fieldOxide)) OR (ispCont AND (well = pWell)) THEN
MarkError [state.obj, state.globalState, [w.first.rect, nWellContact.msg]];
IF (isnCont AND (well = nWell)) THEN
MarkError [state.obj, state.globalState, [w.first.rect, pWellContact.msg]]
ENDLOOP
END
END; -- Inquire
CheckCorner: CStitching.TileProc ~ BEGIN
[tile: Tile, data: REF] for EnumerateArea
t: ATOM ~ NARROW [tile.value];
task: CornerCheckData ~ NARROW [data];
IF (t = task.key) THEN
IF (tile.value # tile.SW.value) AND (tile.value # tile.WS.value) THEN BEGIN
task.detail ← [tile.WEdge, tile.SEdge, tile.WEdge + task.rule.extent, tile.SEdge + task.rule.extent];
task.state.wellTess.EnumerateArea [task.detail, FlagIfNot, task, nothing]
END;
IF (tile.value # tile.EN.value) AND (tile.value # tile.NE.value) THEN BEGIN
task.detail ← [tile.EEdge - task.rule.extent, tile.NEdge - task.rule.extent, tile.EEdge, tile.NEdge];
task.state.wellTess.EnumerateArea [task.detail, FlagIfNot, task, nothing]
END
END; -- CheckCorner
FlagIsland: CStitching.RectProc ~ BEGIN
[plane: REF Tesselation, rect: Rect, oldValue: REF, data: REF]
state: LocalState ~ NARROW [data];
value: ATOMNARROW [oldValue];
IF (value = nWell) OR (value = pWell) THEN MarkError [state.obj, state.globalState, [rect, isolatedWell.msg]]
END; -- FlagIsland
FlagUnconnected: CStitching.RectProc ~ BEGIN
[plane: REF Tesselation, rect: Rect, oldValue: REF, data: REF]
state: LocalState ~ NARROW [data];
MarkError [state.obj, state.globalState, [rect, contactSpacing.msg]]
END; -- FlagUnconnected
FlagIfNot: CStitching.TileProc ~ BEGIN
[tile: Tile, data: REF]
task: CornerCheckData ~ NARROW [data];
IF (tile.value # task.key) THEN BEGIN
r: Rect ~ CDBasics.Intersection [tile.Area, task.detail];
MarkError [task.state.obj, task.state.globalState, [r, task.rule.msg]]
END
END; -- FlagIfNot
Initialisation
AddDrcProcs [tech: cMosBcomplete.checkedBy, c: VerifyWells]
END.