<> <> <> <> <> DIRECTORY CD, CDBasics, CDCommandOps, CDErrors, CDOps, CDProperties, CDSequencer, CDSimpleRules, CStitching, Imager, IO, Rope, TerminalIO; CDWellTestCommand: CEDAR PROGRAM IMPORTS CD, CDBasics, CDErrors, CDOps, CDProperties, CDSequencer, CDSimpleRules, CStitching, IO, TerminalIO = BEGIN wellContMaxDistInLambda: INT _ 75; --in lambda (assume 75 mu, 1 lambda = 1 mu) nothing: REF INT = NEW [INT]; StateRec: TYPE = RECORD [ <<--the original nwell tesselation>> nwell: CD.Layer, wellTess: CStitching.Tesselation _ NIL, <<--for unify Node>> nodeFound: REF NodeRec _ NIL, <<--the copied nwell tesselation>> wellTess2: CStitching.Tesselation _ NIL, <<--the wellcontact>> nwellcont: CD.Layer, growDist: CD.Number, <<-- Diffusion>> diff: CD.Layer, diffTess: CStitching.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 <> <> <> FOR all: CD.InstanceList _ CDOps.InstList [comm.design], all.rest WHILE all # NIL DO IF all.first.selected THEN BEGIN no: INT; no _ CheckAGlobalInstance[comm.design, all.first].errNo; IF no > 0 THEN BEGIN TerminalIO.PutF["\n%g: ", IO.rope[CDOps.ToRope[all.first.ob]]]; TerminalIO.PutF["Well contact check found %g problems.\n", IO.int[no]] END END ENDLOOP; TerminalIO.PutRope ["\nWellCheckCommand done.\n"] <<};>> END; DrawInstance: PROC [pr: CD.DrawRef, inst: CD.Instance] = BEGIN pr.drawChild[pr, inst.ob, inst.trans]; END; DoNotDrawContext: CD.DrawContextProc ~ {}; DoNotDrawObject: CD.DrawProc ~ {}; CheckAGlobalInstance: PROC [design: CD.Design, inst: CD.Instance] RETURNS [errNo: INT] = BEGIN <> cf: REF CD.ContextFilter = NEW [CD.ContextFilter _ ALL[FALSE]]; dist: CD.Number _ wellContMaxDistInLambda*design.technology.lambda; pr: CD.DrawRef _ CD.CreateDrawRef[[design: design]]; state: REF StateRec _ NEW[StateRec_[ nwell: CDSimpleRules.GetLayer[design.technology, $nwel], nwellcont: CDSimpleRules.GetLayer[design.technology, $nwelCont], growDist: dist, wellTess: CStitching.NewTesselation[], diff: CDSimpleRules.GetLayer[design.technology, $pdif], diffTess: CStitching.NewTesselation[], design: design, inst: inst, errorCount: 0 ]]; cf[state.nwell] _ cf[state.nwellcont] _ cf[state.diff] _ TRUE; CDErrors.RemoveMessages[design: state.design, ob: state.inst.ob, owner: errorOwner]; pr.contextFilter _ cf; pr.devicePrivate _ state; pr.drawRect _ DrawNWellTess; -- and p-diffusion pr.drawContext _ DoNotDrawContext; DrawInstance[pr, inst]; TerminalIO.PutRope["."]; state.wellTess2 _ MakeCopy[state.wellTess]; pr.drawRect _ SubtractBlownContact; DrawInstance[pr, inst]; TerminalIO.PutRope["."]; RestrictToDiff[tess: state.wellTess, restrict: state.diffTess]; TerminalIO.PutRope["."]; CStitching.EnumerateArea[plane: state.wellTess, rect: CDBasics.universe, eachTile: 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: CStitching.TileProc = 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 [pr: CD.DrawRef, r: CD.Rect, l: CD.Layer] = BEGIN state: REF StateRec _ NARROW[pr.devicePrivate]; IF state.nwell=l THEN { state.nodeFound _ NIL; CStitching.EnumerateArea[plane: state.wellTess, rect: CDBasics.Extend[r, 1], eachTile: UnifyNodes, data: state]; IF state.nodeFound=NIL THEN state.nodeFound _ NEW[NodeRec]; CStitching.ChangeRect[plane: state.wellTess, rect: r, new: GetRealNode[state.nodeFound]]; } ELSE IF state.diff=l THEN { CStitching.ChangeRect[plane: state.diffTess, rect: CDBasics.Extend[r, state.growDist], new: $pdiff] }; END; SubtractBlownContact: PROC [pr: CD.DrawRef, r: CD.Rect, l: CD.Layer] = BEGIN state: REF StateRec _ NARROW[pr.devicePrivate]; IF l=state.nwellcont THEN { t: CStitching.Tile _ CStitching.FindTile[state.wellTess2, CDBasics.Center[r]]; WITH t.value SELECT FROM rn: REF NodeRec => { state.nodeFound _ rn; CStitching.ChangeEnumerateArea[plane: state.wellTess, rect: CDBasics.Extend[r, state.growDist], eachRect: SubtractConnection, data: state, skip: nothing]; }; ENDCASE => IncludeErrorMessage[state, r, "well missing"] }; END; SubtractConnection: CStitching.RectProc = BEGIN state: REF StateRec _ NARROW[data]; WITH oldValue SELECT FROM rn: REF NodeRec => { IF GetRealNode[rn]=GetRealNode[state.nodeFound] THEN { CStitching.ChangeRect[plane: state.wellTess, rect: rect, new: NIL]; } }; ENDCASE => NULL; END; RestrictToDiff: PROC [tess, restrict: CStitching.Tesselation] ~ BEGIN <> CStitching.EnumerateArea[plane: restrict, rect: CDBasics.universe, eachTile: RestictPerTile, data: tess, skip: NEW[INT]] END; -- RestrictToDiff RestictPerTile: CStitching.TileProc ~ BEGIN <> IF tile.value=NIL THEN BEGIN r: CD.Rect _ CDBasics.Intersection [CStitching.Area[tile], CDBasics.universe]; CStitching.ChangeRect[plane: NARROW[data], rect: r, new: NIL] END END; -- RestictPerTile ReportError: CStitching.TileProc = BEGIN state: REF StateRec _ NARROW[data]; IncludeErrorMessage[state, CStitching.Area[tile], "N-Well contact missing"]; END; MakeCopy: PROC [t: CStitching.Tesselation] RETURNS [new: CStitching.Tesselation] = BEGIN new _ CStitching.NewTesselation[]; CStitching.EnumerateArea[plane: t, rect: CDBasics.universe, eachTile: CopyTile, data: new] END; CopyTile: CStitching.TileProc = BEGIN into: CStitching.Tesselation _ NARROW[data]; nr: REF NodeRec _ NARROW[tile.value]; CStitching.ChangeRect[plane: into, rect: CStitching.Area[tile], new: GetRealNode[nr]] END; IncludeErrorMessage: PROC [state: REF StateRec, rect: CD.Rect, msg: Rope.ROPE] = <<--rect in world coordinates>> BEGIN r: CD.Rect _ CDBasics.DeMapRect [itemInWorld: rect, cellInWorld: state.inst.trans]; 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]; <> CDSequencer.ImplementCommand[key: $WellContactsCheck, proc: WellCheckCommand, queue: doQueue]; END. <> <> <> <> <> <> <> <> <> <> <> <<>>