<> <> <> <> <> <> 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; <> 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; 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 * pWellSurround: Rule ~ [5 * nWellContact: Rule ~ [4 * pWellContact: Rule ~ [4 * contactSpacing: Rule ~ [75 * wellSpacing: Rule ~ [CDSimpleRules.MinDist [nwell, nwell], "well spacing or notch"]; wellWidth: Rule ~ [CDSimpleRules.MinWidth [nwell], "missing well (well width)"]; <> wellConflict: Rule ~ [2 * NinN: Rule ~ [2 * PinP: Rule ~ [2 * isolatedWell: Rule ~ [2 * <> VerifyWells: CellProc ~ BEGIN <> <> 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]; <> 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]; <> 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 <> 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]>> <> 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]>> <> 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]>> <> 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 <> 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 <> InsertWell: PROC [r: Rect, state: LocalState, type: ATOM] ~ BEGIN <> wellSpacingViolation: BOOL _ FALSE; 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 <> 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 <> 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 <> 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 <> 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 <<[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: ATOM _ NARROW [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 <> AddDrcProcs [tech: cMosBcomplete.checkedBy, c: VerifyWells] END.