<> <> <> <> DIRECTORY CD, CDBasics, CDCommandOps, CDErrors, CDMenus, CDOrient, CDProperties, CDSequencer, CDSimpleRules, CornerStitching, Imager, IO, Rope, TerminalIO; CDWellTestCommand: CEDAR PROGRAM IMPORTS CD, CDBasics, CDCommandOps, CDErrors, CDMenus, CDOrient, CDProperties, CDSequencer, CDSimpleRules, CornerStitching, Imager, IO, TerminalIO = BEGIN wellContMaxDistInLambda: INT _ 75; --in lambda (assume 75 mu, 1 lambda = 1 mu) StateRec: TYPE = RECORD [ <<--the original nwell tesselation>> nwell: CD.Layer, wellTess: REF CornerStitching.Tesselation _ NIL, <<--for unify Node>> nodeFound: REF NodeRec _ NIL, <<--the copied nwell tesselation>> wellTess2: REF CornerStitching.Tesselation _ NIL, <<--the wellcontact>> nwellcont: CD.Layer, growDist: CD.Number, <<-- Diffusion>> diff: CD.Layer, diffTess: REF CornerStitching.Tesselation _ NIL, <<--reporting errors>> design: CD.Design, inst: CD.Instance, errorCount: INT _ 0 ]; NodeRec: TYPE = RECORD [ refer: REF NodeRec _ NIL ]; WellCheckCommand: PROC [comm: CDSequencer.Command] = BEGIN inst: CD.Instance; inst _ CDCommandOps.TheInstance[comm: comm, text: "check well contacts"]; IF inst#NIL THEN { no: INT; no _ CheckAGlobalInstance[comm.design, inst].errNo; TerminalIO.WriteF[" well contact check found %g problems\n", IO.int[no]]; }; END; DrawInstance: PROC [pr: CD.DrawRef, inst: CD.Instance] = BEGIN pr.drawChild[inst, inst.location, inst.orientation, pr]; END; CheckAGlobalInstance: PROC [design: CD.Design, inst: CD.Instance] RETURNS [errNo: INT] = BEGIN <> cf: REF CD.ContextFilter = NEW[CD.ContextFilter_ALL[NIL]]; dist: CD.Number _ wellContMaxDistInLambda*design.technology.lambda; pr: CD.DrawRef _ CD.CreateDrawRef[design]; state: REF StateRec _ NEW[StateRec_[ nwell: CDSimpleRules.GetLayer[design.technology, $nwell], nwellcont: CDSimpleRules.GetLayer[design.technology, $nwelCont], growDist: dist, wellTess: CornerStitching.NewTesselation[], diff: CDSimpleRules.GetLayer[design.technology, $pdif], diffTess: CornerStitching.NewTesselation[], design: design, inst: inst, errorCount: 0 ]]; cf[state.nwell] _ cf[state.nwellcont] _ cf[state.diff] _ Imager.black; CDErrors.RemoveMessages[design: state.design, ob: state.inst.ob, owner: errorOwner]; pr.contextFilter _ cf; pr.devicePrivate _ state; pr.drawRect _ DrawNWellTess; -- and p-diffusion DrawInstance[pr, inst]; TerminalIO.WriteChar['.]; state.wellTess2 _ MakeCopy[state.wellTess]; pr.drawRect _ SubtractBlownContact; DrawInstance[pr, inst]; TerminalIO.WriteChar['.]; RestrictToDiff[tess: state.wellTess, restrict: state.diffTess]; TerminalIO.WriteChar['.]; CornerStitching.EnumerateArea[plane: state.wellTess, rect: CDBasics.universe, perTile: ReportError, data: state]; errNo _ state.errorCount; END; GetRealNode: PROC [n: REF NodeRec] RETURNS [rn: REF NodeRec_NIL] = <<--and simplify refer path>> BEGIN IF n#NIL THEN { IF n.refer=NIL THEN rn _ n ELSE { rn _ GetRealNode[n.refer]; n.refer _ rn } }; END; Unify: PROC [a, b: REF NodeRec] RETURNS [REF NodeRec] = <<--both#NIL, a#b>> BEGIN ra: REF NodeRec _ GetRealNode[a]; rb: REF NodeRec _ GetRealNode[b]; IF ra#rb THEN ra.refer _ rb; RETURN [rb]; END; UnifyNodes: CornerStitching.PerTileProc = BEGIN state: REF StateRec _ NARROW[data]; WITH tile.value SELECT FROM nd: REF NodeRec => { IF state.nodeFound=NIL THEN state.nodeFound _ nd ELSE IF state.nodeFound#nd THEN state.nodeFound _ Unify[state.nodeFound, nd] }; ENDCASE => NULL END; DrawNWellTess: PROC [r: CD.Rect, l: CD.Layer, pr: CD.DrawRef] = BEGIN state: REF StateRec _ NARROW[pr.devicePrivate]; IF state.nwell=l THEN { state.nodeFound _ NIL; CornerStitching.EnumerateArea[plane: state.wellTess, rect: CDBasics.Extend[r, 1], perTile: UnifyNodes, data: state]; IF state.nodeFound=NIL THEN state.nodeFound _ NEW[NodeRec]; CornerStitching.ChangeRect[plane: state.wellTess, rect: r, newValue: GetRealNode[state.nodeFound]]; } ELSE IF state.diff=l THEN { CornerStitching.ChangeRect[plane: state.diffTess, rect: CDBasics.Extend[r, state.growDist], newValue: $pdiff] }; END; SubtractBlownContact: PROC [r: CD.Rect, l: CD.Layer, pr: CD.DrawRef] = BEGIN state: REF StateRec _ NARROW[pr.devicePrivate]; IF l=state.nwellcont THEN { t: REF CornerStitching.Tile _ CornerStitching.TileAt[state.wellTess2, CDBasics.Center[r]]; WITH t.value SELECT FROM rn: REF NodeRec => { state.nodeFound _ rn; CornerStitching.FuncChangeRect[plane: state.wellTess, rect: CDBasics.Extend[r, state.growDist], perTile: SubtractConnection, data: state]; }; ENDCASE => IncludeErrorMessage[state, r, "well missing"] }; END; SubtractConnection: CornerStitching.PerTileChangeProc = BEGIN state: REF StateRec _ NARROW[data]; WITH oldValue SELECT FROM rn: REF NodeRec => { IF GetRealNode[rn]=GetRealNode[state.nodeFound] THEN { CornerStitching.ChangeRect[plane: state.wellTess, rect: rect, newValue: NIL]; } }; ENDCASE => NULL; END; RestrictToDiff: PROC [tess, restrict: REF CornerStitching.Tesselation] ~ BEGIN <> CornerStitching.EnumerateArea[plane: restrict, rect: CDBasics.universe, perTile: RestictPerTile, data: tess, skipValue: NEW[INT]] END; -- RestrictToDiff RestictPerTile: CornerStitching.PerTileProc ~ BEGIN <> IF tile.value=NIL THEN BEGIN r: CD.Rect _ CDBasics.Intersection [CornerStitching.Area[tile], CDBasics.universe]; CornerStitching.ChangeRect[plane: NARROW[data], rect: r, newValue: NIL] END END; -- RestictPerTile ReportError: CornerStitching.PerTileProc = BEGIN state: REF StateRec _ NARROW[data]; IncludeErrorMessage[state, CornerStitching.Area[tile], "N-Well contact missing"]; END; MakeCopy: PROC [t: REF CornerStitching.Tesselation] RETURNS [new: REF CornerStitching.Tesselation] = BEGIN new _ CornerStitching.NewTesselation[]; CornerStitching.EnumerateArea[plane: t, rect: CDBasics.universe, perTile: CopyTile, data: new] END; CopyTile: CornerStitching.PerTileProc = BEGIN into: REF CornerStitching.Tesselation _ NARROW[data]; nr: REF NodeRec _ NARROW[tile.value]; CornerStitching.ChangeRect[plane: into, rect: CornerStitching.Area[tile], newValue: GetRealNode[nr]] END; IncludeErrorMessage: PROC [state: REF StateRec, rect: CD.Rect, msg: Rope.ROPE] = <<--rect in world coordinates>> BEGIN r: CD.Rect _ CDOrient.DeMapRect[itemInWorld: rect, cellSize: state.inst.ob.size, cellInstOrient: state.inst.orientation, cellInstPos: state.inst.location ]; state.errorCount _ state.errorCount+1; [] _ CDErrors.IncludeMessage[design: state.design, ob: state.inst.ob, rect: r, message: msg, owner: errorOwner]; END; errorOwner: ATOM _ $WellProblem; [] _ CDProperties.RegisterProperty[errorOwner, $chj]; CDMenus.CreateEntry[menu: $ProgramMenu, entry: "Check well contacts", key: $WellContactsCheck]; CDSequencer.ImplementCommand[a: $WellContactsCheck, p: WellCheckCommand, queue: doQueue]; END.