CDWellTestCommand.mesa
Jacobi, November 16, 1985 4:02:43 pm PST
Jacobi, January 15, 1986 6:52:06 pm PST
gbb November 18, 1985 6:53:32 pm PST
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
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.
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
tess is the modified tesselation.
CornerStitching.EnumerateArea[plane: restrict, rect: CDBasics.universe, perTile: RestictPerTile, data: tess, skipValue: NEW[INT]]
END; -- RestrictToDiff
RestictPerTile: CornerStitching.PerTileProc ~ BEGIN
PROC [tile: REF Tile, data: REF];
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.