DIRECTORY CD, CDBasics, CDCommandOps, CDErrors, CDMenus, CDOps, CDOrient, CDProperties, CDSequencer, CDSimpleRules, CStitching, Imager, IO, Rope, TerminalIO; CDWellTestCommand: CEDAR PROGRAM IMPORTS CD, CDBasics, CDErrors, CDMenus, CDOps, CDOrient, 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 [ nwell: CD.Layer, wellTess: CStitching.Tesselation _ NIL, nodeFound: REF NodeRec _ NIL, wellTess2: CStitching.Tesselation _ NIL, nwellcont: CD.Layer, growDist: CD.Number, diff: CD.Layer, diffTess: CStitching.Tesselation _ NIL, 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.WriteF["\n%g: ", IO.rope[CDOps.ObjectInfo[all.first.ob]]]; TerminalIO.WriteF["Well contact check found %g problems.\n", IO.int[no]] END END ENDLOOP; TerminalIO.WriteRope ["\nWellCheckCommand done.\n"] 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[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 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['.]; 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] = 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] = 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 [r: CD.Rect, l: CD.Layer, pr: CD.DrawRef] = 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 [r: CD.Rect, l: CD.Layer, pr: CD.DrawRef] = 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] = 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 (Gismo)", key: $WellContactsCheck]; CDSequencer.ImplementCommand[key: $WellContactsCheck, proc: WellCheckCommand, queue: doQueue]; END. CDWellTestCommand.mesa Jacobi, November 16, 1985 4:02:43 pm PST Jacobi, January 15, 1986 6:52:06 pm PST gbb June 12, 1986 5:10:47 pm PDT --the original nwell tesselation --for unify Node --the copied nwell tesselation --the wellcontact -- Diffusion --reporting errors inst: CD.Instance; inst _ CDCommandOps.TheInstance[comm: comm, text: "check well contacts"]; IF inst#NIL THEN { }; The tessellation for p-diff is created at the same time as the one of the wells. If there should be memory problems, do the following. Dispose wellTess2 after the blown contacts have been subtracted and construct the tesselation for the p-diff. --and simplify refer path --both#NIL, a#b tess is the modified tesselation. PROC [tile: REF Tile, data: REF]; --rect in world coordinates gbb March 20, 1986 3:46:40 pm PST Converted to CStitching2 changes to: DIRECTORY, CDWellTestCommand, wellContMaxDistInLambda, nothing, StateRec, CheckAGlobalInstance, UnifyNodes, DrawNWellTess, SubtractBlownContact, rn, rn, RestrictToDiff, RestictPerTile (local of RestrictToDiff), ReportError, MakeCopy, CDSequencer gbb March 25, 1986 10:41:09 am PST Changed labels of menu entries. gbb May 20, 1986 5:34:04 pm PDT Tracked change from $nwell to $nwel in ChipNDale changes to: CheckAGlobalInstance. gbb June 12, 1986 3:07:15 pm PDT Changed command to loop over all selected cells. changes to: WellCheckCommand: traded TheInstance for a for list loop Κ ˜codešœ™K™(K™'K™ K˜—šΟk ˜ Kšœ˜Kšœ ˜ K˜ K˜ K˜K˜K˜ K˜ K˜ K˜Kšœ ˜ Kšœ˜Kšœ˜Kšœ˜Kšœ ˜ —K˜šΠblœœ˜ Kšœœgœ˜—Kšœ˜K˜KšœœΟc+˜NKš œ œœœœ˜K˜šœ œœ˜šœ ™ Kšœœ˜Kšœ#œ˜'šœ™Kšœ œ œ˜——šœ™Kšœ$œ˜(—šœ™Kšœ œ˜Kšœ˜—šœ ™ Kšœœ˜Kšœ#œ˜'—šœ™Kšœœ˜Kšœœ ˜Kšœ œ˜—Kšœ˜—K˜šœ œœ˜Kšœœ ˜Kšœ˜K˜—šΟnœœ˜4Kš˜Kšœœ ™KšœI™IKšœœœ™š œœ7œœ˜Tšœœ˜ Kšœœ˜Kšœ8˜8šœœ˜Kšœœ'˜EKšœ=œ ˜HKš˜—Kš˜—Kšœ˜—šœ3˜3Kšœ™—Kšœ˜—K˜š  œœœœ ˜8Kš˜Kšœ8˜8Kšœ˜—K˜š  œœ œœ œ œ˜XKš˜KšœΟe œ[™τKš œœœœœœœ˜?Kšœœ;˜CKšœœ œ!˜4šœœ œ ˜$Kšœ8˜8Kšœ@˜@Kšœ˜Kšœ&˜&Kšœ7˜7Kšœ&˜&Kšœ˜Kšœ ˜ Kšœ ˜ Kšœ˜—Kšœ9œ˜>KšœT˜TKšœ˜Kšœ˜KšœŸ˜/Kšœ˜K˜Kšœ+˜+Kšœ#˜#Kšœ˜K˜Kšœ?˜?K˜Kšœm˜mKšœ˜Kšœ˜—K˜š   œœœ œœ œ˜BKšœ™Kš˜šœœœ˜Kšœ œœ˜šœ˜Kšœ˜Kšœ ˜ K˜—Kšœ˜—Kšœ˜K˜—š  œœœ œœ ˜7Kšœ™Kš˜Kšœœ˜!Kšœœ˜!Kšœœ˜Kšœ˜ Kšœ˜—K˜šΟb œ˜!Kš˜Kšœœ œ˜#šœ œ˜šœœ ˜Kšœœœ˜0Kšœœœ-˜LK˜—Kšœ˜—Kšœ˜—K˜š Πbn œœœ œ œ ˜?Kš˜Kšœœ œ˜/šœœ˜Kšœœ˜Kšœp˜pKšœœœœ ˜;KšœY˜YKšœ˜—šœœœ˜Kšœc˜cKšœ˜—Kšœ˜K˜—š £œœœ œ œ ˜FKš˜Kšœœ œ˜/šœœ˜Kšœœ<˜Nšœ œ˜šœœ ˜Kšœ˜Kšœš˜šK˜—Kšœ1˜8—Kšœ˜—Kšœ˜K˜š’œ˜)Kš˜Kšœœ œ˜#šœ  ˜šœœ ˜šœ.œ˜6Kšœ>œ˜CK˜—K˜—Kšœœ˜—Kšœ˜——K˜š œœœ˜EKš‘œ™!Kšœoœœ˜xKšœŸ˜š’œ˜+Kšœœ œ™!šœ œ ˜KšœœI˜NKšœœœ˜=Kš˜—KšœŸ˜——K˜š’ œ˜"Kš˜Kšœœ œ˜#KšœL˜LKšœ˜K˜—š£œœœœ˜RKš˜Kšœ"˜"KšœZ˜Zšœ˜K˜š’œ˜Kš˜Kšœœœ˜,Kšœœ œ ˜%KšœU˜UKšœ˜—K˜——K˜š  œœ œœœ˜PKšœ™Kš˜šœœ-˜2Kšœ˜Kšœ'˜'Kšœ ˜ Kšœ˜—K˜&Kšœp˜pKšœ˜—K˜Kšœ œ˜!Kšœ5˜5Kšœg˜gKšœ^˜^Kšœ˜™!K™Kšœ Οr·œ€$™—™"K™—™Kšœ0™0Kšœ €œ™!—™ K™0Kšœ €œ(™D—K™—…—:'Χ