CDWellTestCommand.mesa
Jacobi, November 16, 1985 4:02:43 pm PST
Jacobi, November 18, 1985 12:15:14 pm PST
copy /indigo/chipndale/temp/CDWellTestCommand.mesa ← CDWellTestCommand.mesa
DIRECTORY
CD,
CDBasics,
CDCommandOps,
CDErrors,
CDMenus,
CDOrient,
CDProperties,
CDSequencer,
CDSimpleRules,
CornerStitching,
IO,
Rope,
TerminalIO;
CDWellTestCommand: CEDAR PROGRAM
IMPORTS CD, CDBasics, CDCommandOps, CDErrors, CDMenus, CDOrient, CDProperties, CDSequencer, CDSimpleRules, CornerStitching, 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,
--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
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[],
design: design,
inst: inst,
errorCount: 0
]];
CDErrors.RemoveMessages[design: state.design, ob: state.inst.ob, owner: errorOwner];
pr.devicePrivate ← state;
pr.drawRect ← DrawNWellTess;
DrawInstance[pr, inst];
state.wellTess2 ← MakeCopy[state.wellTess];
pr.drawRect ← SubtractBlownContact;
DrawInstance[pr, inst];
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]];
};
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;
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.