DIRECTORY CD USING [CreateDrawRef, Design, DrawProc, DrawRectProc, DrawRef, Instance, Layer, LayerKey, Number, Object, ObjectClass], CDBasics USING [Extend, Intersection, NonEmpty], CDInstances USING [NewInst], 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, CDInstances, CDSimpleRules, CMosB, CoreGeometry, CStitching, Drc, DrcCMOSB SHARES Drc, DrcCMOSB ~ BEGIN OPEN CMosB, Drc, DrcCMOSB; GenistaCMosBwells: PUBLIC Tech; 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 !!! 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)"]; 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"]; VerifyWells: CellProc ~ BEGIN localState: LocalState ~ NEW [LocalStateRec _ [state, cell, NIL]]; cornerData: CornerCheckData ~ NEW [CornerCheckDataRec _ [state: localState]]; c: CD.Instance ~ CDInstances.NewInst [CoreGeometry.GetObject [state.attributes, cell]]; localState.wellTess _ IF (cachedTess # NIL) THEN cachedTess ELSE CStitching.NewTesselation [stopFlag: state.abort]; EnumerateChipNDale [inst: c, 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]; EnumerateChipNDale [inst: c, state: localState, how: $sex]; EnumerateChipNDale [inst: c, state: localState, how: $contactsPos]; EnumerateChipNDale [inst: c, state: localState, how: $connection]; localState.wellTess.ChangeEnumerateArea [universe, FlagIsland, localState, empty]; EnumerateChipNDale [inst: c, state: localState, how: $contactsInfl]; localState.wellTess.ChangeEnumerateArea [universe, FlagUnconnected, localState, empty]; CStitching.ResetTesselation [localState.wellTess] END; -- VerifyWells ExtractWells: CD.DrawRectProc ~ BEGIN 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 state: LocalState ~ NARROW [pr.devicePrivate]; IF (l = pwellCont) OR (l = nwellCont) THEN ConnectTile [r: r, state: state] END; -- InsertContact PropagateContact: CD.DrawRectProc ~ BEGIN state: LocalState ~ NARROW [pr.devicePrivate]; IF (l = pwellCont) OR (l = nwellCont) THEN PercolateContact [r: r, state: state] END; -- PropagateContact DeleteContact: CD.DrawRectProc ~ BEGIN state: LocalState ~ NARROW [pr.devicePrivate]; IF (l = pwellCont) OR (l = nwellCont) THEN DeleteConnected [r: r, state: state] END; -- DeleteContact ExtractDiff: CD.DrawRectProc ~ BEGIN 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 [inst: CD.Instance, state: LocalState, how: ATOM] ~ BEGIN 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; inst.ob.class.drawMe [inst, inst.trans, dr] END; -- EnumerateChipNDale InsertWell: PROC [r: Rect, state: LocalState, type: ATOM] ~ BEGIN wellSpacingViolation: BOOL _ FALSE; errorRect: Rect; OccupyByWell: CStitching.RectProc ~ BEGIN 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 Contact: CStitching.RectProc ~ BEGIN 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 DoTile: CStitching.RectProc ~ BEGIN 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 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 DeleteRectangle: CStitching.RectProc ~ BEGIN 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 Inquire: PROC [r: Rect, layer: CD.Layer, state: LocalState] ~ BEGIN 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 wells _ state.wellTess.ListArea [rect: r, skip: nothing]; FOR w: Region _ wells, w.rest WHILE w # NIL DO well: ATOM _ NARROW [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; 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: ATOM _ NARROW [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: ATOM _ NARROW [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 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 state: LocalState ~ NARROW [data]; value: ATOM _ NARROW [oldValue]; IF (value = nWell) OR (value = pWell) THEN MarkError [state.obj, state.globalState, [rect, isolatedWell.msg]] END; -- FlagIsland FlagUnconnected: CStitching.RectProc ~ BEGIN state: LocalState ~ NARROW [data]; MarkError [state.obj, state.globalState, [rect, contactSpacing.msg]] END; -- FlagUnconnected FlagIfNot: CStitching.TileProc ~ BEGIN 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 AddDrcProcs [tech: cMosBcomplete.checkedBy, c: VerifyWells] END. \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. Types and constants Verifies the wells and related stuff taking its information from the ChipNDale design. The rules In the following rules the extent is used only to determine the overlap of the error rectangle. Interface 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. Smash wells into a flat tesselation of interesting areas. 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. Operations on ChipNDale objects [r: Rect, l: Layer, pr: DrawRef] [r: Rect, l: Layer, pr: DrawRef] Ignores sex of contacts since it already has been verified. [r: Rect, l: Layer, pr: DrawRef] Ignores sex of contacts since it already has been verified. [r: Rect, l: Layer, pr: DrawRef] Ignores sex of contacts since it already has been verified. [r: Rect, l: Layer, pr: DrawRef] If wells is false, diffusion rectangles are enumerated. Operations on the corner-stitched plane Inserts a well. This procedure ensures that wells do not overlap. [plane: REF Tesselation, rect: Rect, oldValue: REF, data: REF] Changes the value of the tile with a contact into a contact. Ignores sex of contacts since it already has been verified. [plane: REF Tesselation, rect: Rect, oldValue: REF, data: REF] Propagates the connectedness of a tile in order to isolate islands. [plane: REF Tesselation, rect: Rect, oldValue: REF, data: REF] [tile: Tile, data: REF] DESTRUCTIVE !!! Verifies that the maximum well contact spacing is fulfilled. Ignores sex of contacts since it already has been verified. [plane: REF Tesselation, rect: Rect, oldValue: REF, data: REF] Implementation Algorithm: If there is antagonist material in a wellSurround-sphere from diffusion, then the a violation is flagged. Verify diffusion type. Verify surround. [tile: Tile, data: REF] for EnumerateArea [plane: REF Tesselation, rect: Rect, oldValue: REF, data: REF] [plane: REF Tesselation, rect: Rect, oldValue: REF, data: REF] [tile: Tile, data: REF] Initialisation Κ ˜codešœ™Kšœ<™šœ œ˜Kš œœœœœ˜Tšœ .Πce ˜HKšœD˜D——Kšœ ˜—NšœD˜DKšœœH˜dKšœ  ˜—š£ œœ ˜6Kšœx™xš£œ˜$Kšœœ$œœ™>šœ œ˜Kšœœ>˜HKšœœ ˜‘—Kšœ  ˜—Nšœ0œ˜;Kšœ ˜—š£œœ ˜;KšœC™Cš£œ˜#Kšœœ$œœ™>Kšœ>˜>šœ œ˜šœœœœ˜0Kšœ˜Kšœ4œ ˜@Kšœ˜Kšœ˜—Kšœ˜—Kšœ  ˜—š£œ˜#Kšœœ™šœ œ˜š œœœœœ˜Dšœ˜ Kšœ˜Kšœ4œ ˜@Kšœ˜Kšœ˜——Kšœœ ˜,—Kšœ  ˜—Nšœ/œ˜:Kšœ ˜—š£œœ ˜:KšΟbœz™‰š£œ˜,Kšœœ$œœ™>šœ œ˜Kšœœ8˜AKšœ˜—Kšœ ˜—Nšœaœ˜lKšœ ˜——™š£œœœ˜CKšœt™tKšœ˜Kšœ˜Kšœ œœ˜DKšœ œœ˜DKš œœ œœ œ ˜CNš œœœœ ˜;N™Kšœ9˜9šœœœ˜.Kšœœœ˜$š œœœœ˜AKšœC˜C—šœœ˜ KšœB˜B—Jšœ˜—N™šœ œ œ˜"Kšœ8˜8KšœC˜Cšœœœ˜.Kšœœœ˜$š œ œœ œ˜IKšœL˜L—šœ œ˜$KšœK˜K—Jš˜——Jš˜šœœ  ˜Kšœ7˜7KšœC˜Cšœœœ˜.Kšœœœ˜$š œ œœ œ˜IKšœK˜K—šœ œ˜$KšœJ˜J—Jš˜—Jš˜—Kšœ  ˜—š£ œ˜(Kšœœ™)Kšœœœ˜Kšœœ˜&šœ˜š œœœœœ˜KKšœe˜eKšœI˜IKšœ˜—š œœœœœ˜KKšœe˜eKšœI˜IKš˜——Kšœ ˜—š£ œ˜'Kšœœ$œœ™>Kšœœ˜"Kšœœœ ˜ KšœœœC˜mKšœ  ˜—š£œ˜,Kšœœ$œœ™>Kšœœ˜"KšœD˜DKšœ ˜—š£ œ˜&Kšœœ™Kšœœ˜&šœœ˜%Kšœ9˜9KšœF˜FKš˜—Kšœ  ˜——™Lšœ;˜;—Lšœ˜—…—) BŒ