ViaFlatnessImpl.mesa
Copyright © 1986 by Xerox Corporation. All rights reserved.
Giordano Bruno Beretta, January 21, 1986 2:54:32 pm PST
gbb June 13, 1986 4:00:48 pm PDT
Checks that vias are are on flat topology. The following flat topologies are accepted: diffusion (may be partial), poly, and field oxide. For the moment this implementation is "flat".
DIRECTORY
BasicTime USING [GMT, Now, Period],
CD USING [CreateDrawRef, Design, DrawProc, DrawRectProc, DrawRef, Error, FetchObjectClass, Instance, InstanceList, Layer, Number, Object, ObjectClass, Orientation, Position, Rect, Technology],
CDAtomicObjects USING [AtomicObsPtr, DrawList],
CDBasics USING [Extend, Intersect, Intersection, NonEmpty],
CDCommandOps USING [CallWithResource],
CDErrors USING [IncludeMessage, RemoveMessages],
CDEvents USING [EventProc, RegisterEventProc],
CDMenus USING [CreateEntry],
CDOps USING [ObjectInfo, InstList],
CDOrient USING [MapRect],
CDProperties USING [CopyVal, GetProp, GetObjectProp, InstallProcs, PutProp, PutObjectProp, RegisterProperty],
CDSequencer USING [Command, ImplementCommand],
CDSimpleRules USING [GetLayer],
CMosB USING [cmosB, cut2, lambda],
CStitching USING [all, Area, ChangeRect, Rect, EnumerateArea, ResetTesselation, ChangeEnumerateArea, ListArea, NewTesselation, RectProc, TileProc, Region, Tesselation, Tile],
CSMonitor USING [Monitor, PaintPredicate],
IO USING [int, PutFR, PutFR1, rope],
PrincOpsUtils USING [],
Process USING [priorityBackground, SetPriority],
Rope USING [Cat, ROPE],
TerminalIO USING [WriteChar, WriteRope],
ViaFlatness USING [ErrorList, Rule];
ViaFlatnessImpl: CEDAR PROGRAM
IMPORTS BasicTime, CD, CDBasics, CDCommandOps, CDErrors, CDEvents, CDMenus, CDOps, CDOrient, CDProperties, CDSequencer, CDSimpleRules, CMosB, CStitching, CSMonitor, IO, Process, Rope, TerminalIO
EXPORTS ViaFlatness
~ BEGIN
debug: BOOLFALSE;
timing: BOOLFALSE;
Region: TYPE ~ LIST OF REF CStitching.Region;
Tess: TYPE ~ CStitching.Tesselation;
Tile: TYPE ~ CStitching.Tile;
empty: REF ~ NIL;
nothing: REF INT ~ NEW [INT];
l: CD.Number ~ CMosB.lambda;
externalKey: ATOM ~ $GismoVF;  -- used in traffic with external packages
checkedKey: ATOM ~ $GismoVFChecked; -- used to mark checked cells
errorKey: ATOM ~ $GismoVFError;
doNotAnalyse: ATOM = $DoNotDRC;
State: TYPE ~ REF StateRec;
StateRec: TYPE ~ RECORD [design: CD.Design,
abort: REF BOOL,
viaTess, materialTess: Tess,
errors: ErrorList,
errorTotal: INT ← 0];
ErrorList: TYPE ~ ViaFlatness.ErrorList;
ErrorList: TYPE ~ LIST OF RECORD [rule: Rule; where: CD.Rect];
ViaTileData: TYPE ~ REF ViaTileDataRec;
ViaTileDataRec: TYPE ~ RECORD [
hasDiff: BOOLFALSE, -- diffusion
hasPoly: BOOLFALSE, -- polysilicide
hasFOx: BOOLFALSE]; -- field oxide
MatTileData: TYPE ~ REF MatTileDataRec;
MatTileDataRec: TYPE ~ RECORD [layerKey: ATOM, via: ViaTileData];
diffKey: ATOM ~ $ndif;
polyKey: ATOM ~ $pol;
diffLayer, polyLayer: CD.Layer;
fieldOxide: REF ANY ~ NIL;
The rules
In l units from the minimal metal border of the via (not from the cut).
Rule: TYPE ~ ViaFlatness.Rule;
TYPE ~ RECORD [extent: CD.Number, msg: Rope.ROPE]
viaOnFieldOxideAvoidsDiff: Rule ~ [2 * l, "separation to diff (advisory)"];
viaOnFieldOxideAvoidsPoly: Rule ~ [2 * l, "separation to poly"];
fieldOxideSurroundsViaOnFieldOxide: Rule ~ [MAX [viaOnFieldOxideAvoidsDiff.extent, viaOnFieldOxideAvoidsPoly.extent], "separation to poly or diff"];
diffSurroundsViaOnDiff: Rule ~ [2 * l, "insufficient diff surround (advisory)"];
polySurroundsViaOnPoly: Rule ~ [3 * l, "insufficient poly surround"];
In the following rules the extent is used only to determine the overlap of the error rectangle.
viaOnPolyAndDiff: Rule ~ [1 * l, "topology not flat"]; -- more for the sake of robustness
viaSeparation: Rule ~ [1 * l, "via to via separation"]; -- only overlaps checked
viaOverGate: Rule ~ [1 * l, "via not allowed over gate"];
viaOverPoly: Rule ~ [1 * l, "via not allowed over poly"];
Environment: public procedures and interactive interface to ChipNDale
Verify: PUBLIC PROC [c: CD.Instance, d: CD.Design ← NIL, abort: REF BOOLNIL] RETURNS [errors: ErrorList, errorTotal: INT] ~ BEGIN
If a design is not provided, the error messages are displayed in the terminal viewer.
state: State;
o: CD.Object = c.ob;
checked: BOOL = (CDProperties.GetObjectProp [o, checkedKey] # NIL);
oldErrors: ErrorList = NARROW [CDProperties.GetObjectProp [o, externalKey]];
IF checked THEN BEGIN
TerminalIO.WriteChar [':]; RETURN [oldErrors, -1]
END;
IF (CDProperties.GetObjectProp [o, doNotAnalyse] # NIL) THEN BEGIN
TerminalIO.WriteChar [' ]; RETURN [oldErrors, -1]
END;
IF (d.technology # CMosB.cmosB) THEN BEGIN
TerminalIO.WriteRope [Rope.Cat ["Technology is not ", CMosB.cmosB.name, ".\n"]];
RETURN [NIL, -1]
END;
IF (d # NIL) THEN CDErrors.RemoveMessages [d, o, errorKey];
state ← NEW [StateRec ← [design: d]];
state.abort ← IF (abort # NIL) THEN abort ELSE NEW [BOOLFALSE];
CreateTess [state];
IF debug THEN BEGIN
[] ← CSMonitor.Monitor [state.viaTess, "Via Tesselation", NIL];
[] ← CSMonitor.Monitor [state.materialTess, "Material Tesselation", DarkPoly]
END;
Smash vias into a flat tesselation of interesting areas.
EnumerateDesign [c, state, TRUE];
Throw intersecting diffusion and poly into materialTess. Conflicts are resolved on the fly by marking an error and discarding the interesting area (we are not interested in multiple errors).
EnumerateDesign [c, state, FALSE];
Enumerate the materialTess and check it for flatness.
CStitching.EnumerateArea [plane: state.viaTess,
rect: CStitching.all,
eachTile: LookUnderneath,
data: state,
skip: empty];
IF NOT debug THEN DestroyTess [state];
CDProperties.PutObjectProp [o, checkedKey, checkedKey];
CDProperties.PutObjectProp [o, externalKey, state.errors];
RETURN [state.errors, state.errorTotal]
END; -- Verify
InteractiveCall: PROC [comm: CDSequencer.Command] ~ BEGIN
Called by ChipNDale upon activation of the command.
abort: REF BOOLNEW [BOOLFALSE];
startTime, stopTime: BasicTime.GMT; -- for internal use
errorSummary: LIST OF RECORD [c: Rope.ROPE, n: INT];
VerifySelected: PROC [comm: CDSequencer.Command] ~ BEGIN
Verifies all selected cells in background priority.
TRUSTED {Process.SetPriority [Process.priorityBackground]};
FOR all: CD.InstanceList ← CDOps.InstList [comm.design], all.rest WHILE all # NIL DO
IF all.first.selected THEN BEGIN
IF debug THEN CDProperties.PutObjectProp [all.first.ob, checkedKey, NIL];
errorSummary ← CONS [[CDOps.ObjectInfo[all.first.ob], Verify [all.first, comm.design, abort].errorTotal], errorSummary];
TerminalIO.WriteChar ['.]
END
ENDLOOP
END; -- VerifySelected
TerminalIO.WriteRope ["Checking via flatness.\n"];
startTime ← BasicTime.Now [];
[] ← CDCommandOps.CallWithResource [VerifySelected, comm, externalKey, abort];
stopTime ← BasicTime.Now [];
IF (errorSummary # NIL) THEN BEGIN
TerminalIO.WriteRope ["\nError summary (via flatness):\n"];
FOR e: LIST OF RECORD [c: Rope.ROPE, n: INT] ← errorSummary, e.rest WHILE e # NIL DO
IF (e.first.n = -1) THEN
TerminalIO.WriteRope [IO.PutFR ["%g: previously analysed.\n", IO.rope[e.first.c]]]
IF (e.first.n > 0) THEN
TerminalIO.WriteRope [IO.PutFR ["%g: %g.\n", IO.rope[e.first.c], IO.int[e.first.n]]]
ENDLOOP
END; -- write error summary
TerminalIO.WriteRope ["Via flatness verification done.\n"];
IF timing THEN TerminalIO.WriteRope [Rope.Cat ["Total elapsed time: ", TimeToRope [startTime, stopTime], "\n"]]
END; -- InteractiveCall
TimeToRope: PROC [from, to: BasicTime.GMT] RETURNS [time: Rope.ROPE] ~ BEGIN
Although the INT returned BasicTime.Period is the same as GMT and might hence be loopholed to use IO.time from Conversions, the latter uses BasicTime.Unpack which allows only values that give a valid date.
tmp: Rope.ROPE;
sec: INT = BasicTime.Period [from, to];
min: INT = sec / 60;
h: INT = min / 60;
tmp ← IO.PutFR1 [value: IO.int [h]];
time ← SELECT h FROM
= 0 => "00",
< 10 => Rope.Cat ["0", tmp],
ENDCASE => tmp;
tmp ← IO.PutFR1 [value: IO.int [min MOD 60]];
time ← Rope.Cat [time, ":", SELECT min FROM
= 0 => "00",
< 10 => Rope.Cat ["0", tmp],
ENDCASE => tmp];
tmp ← IO.PutFR1 [value: IO.int [sec MOD 60]];
time ← Rope.Cat [time, ":", SELECT sec FROM
= 0 => "00",
< 10 => Rope.Cat ["0", tmp],
ENDCASE => tmp]
END; -- TimeToRope
Operations on ChipNDale objects
ObjConversionProc: TYPE = PROCEDURE [inst: CD.Instance, pos: CD.Position, orient: CD.Orientation, state: State];
ExchangeCDInfo: PROC ~ BEGIN
Registers the procedures to extract vias from the design and gets the layers.
tech: CD.Technology = CMosB.cmosB;
Register: PROC [tech: CD.Technology, class: ATOM, proc: ObjConversionProc] ~ BEGIN
cl: CD.ObjectClass ← CD.FetchObjectClass [objectType: class, technology: tech];
IF cl = NIL THEN CD.Error [explanation: "Version mismatch."];
CDProperties.PutProp [onto: cl.properties,
prop: externalKey,
val: NEW [ObjConversionProc←proc]]
END; -- Register
Register [tech, $C2Via, ConvertVia];
Register [tech, $C2LargeVia, ConvertVia];
diffLayer ← CDSimpleRules.GetLayer [tech, diffKey];
polyLayer ← CDSimpleRules.GetLayer [tech, polyKey]
END; -- ExchangeCDInfo
ConvertVia: ObjConversionProc = BEGIN
[inst: CD.Instance, pos: CD.Position, orient: CD.Orientation, state: State]
data: ViaTileData ← NEW [ViaTileDataRec];
FOR geom: CDAtomicObjects.DrawList ← NARROW [inst.ob.specificRef, CDAtomicObjects.AtomicObsPtr].rList, geom.rest WHILE geom # NIL DO
SELECT geom.first.lev FROM
CMosB.cut2 => BEGIN
r: CD.Rect = CDOrient.MapRect [itemInCell: geom.first.r,
cellSize: inst.ob.size,
cellInstOrient: orient,
cellInstPos: pos];
InsertVia [r: r, state: state, data: data]
END;
ENDCASE => NULL
ENDLOOP
END; -- ConvertVia
ConvertMat: PROC [r: CD.Rect, layer: CD.Layer, state: State] = BEGIN
Algorithm: 1. If there is antagonist material in a viaOnFieldOxideAvoidsDiff-sphere from a via, then the topology cannot be flat. 2. If r is in a minSurround-sphere from a via, then insert it in the material tesselation.
bloatedRect: CD.Rect;
vias: Region;
IF NOT CDBasics.NonEmpty[r] THEN RETURN; -- empty rectangle
IF state.abort^ THEN ERROR ABORTED;
SELECT layer FROM
diffLayer => BEGIN
bloatedRect ← CDBasics.Extend [r, viaOnFieldOxideAvoidsDiff.extent];
vias ← CStitching.ListArea [plane: state.viaTess, rect: bloatedRect];
FOR v: Region ← vias, v.rest WHILE v # NIL DO
via: ViaTileData ← NARROW [v.first.value];
IF via.hasPoly THEN BEGIN
FlagViolation [viaOverGate, v.first.rect, state];
CStitching.ChangeEnumerateArea [state.viaTess, bloatedRect, DeleteTile, , nothing];
RETURN
END
ENDLOOP;
bloatedRect ← CDBasics.Extend [r, diffSurroundsViaOnDiff.extent];
vias ← CStitching.ListArea [plane: state.viaTess, rect: bloatedRect];
FOR v: Region ← vias, v.rest WHILE v # NIL DO
via: ViaTileData = NARROW [v.first.value];
IF CDBasics.Intersect [v.first.rect, r] THEN via.hasDiff ← TRUE;
We insert material in the whole influence area of a via.
bloatedRect ← CDBasics.Extend [v.first.rect, diffSurroundsViaOnDiff.extent];
InsertMat [diffKey, CDBasics.Intersection[bloatedRect, r], via, state]
Note that via always is a single and non-degenerated via, since collisions of vias are detected when the vias are input.
ENDLOOP
END;
polyLayer => BEGIN
vias ← CStitching.ListArea [plane: state.viaTess, rect: r];
FOR v: Region ← vias, v.rest WHILE v # NIL DO
via: ViaTileData = NARROW [v.first.value];
IF (via # empty) THEN BEGIN
FlagViolation [viaOverPoly, v.first.rect, state];
CStitching.ChangeEnumerateArea [state.viaTess, bloatedRect, DeleteTile, , nothing];
RETURN
END
ENDLOOP;
bloatedRect ← CDBasics.Extend [r, viaOnFieldOxideAvoidsPoly.extent];
vias ← CStitching.ListArea [plane: state.viaTess, rect: bloatedRect];
FOR v: Region ← vias, v.rest WHILE v # NIL DO
via: ViaTileData = NARROW [v.first.value];
IF via.hasDiff THEN BEGIN
FlagViolation [viaOverGate, v.first.rect, state];
CStitching.ChangeEnumerateArea [state.viaTess, bloatedRect, DeleteTile, , nothing];
RETURN
END
ENDLOOP;
bloatedRect ← CDBasics.Extend [r, polySurroundsViaOnPoly.extent];
vias ← CStitching.ListArea [plane: state.viaTess, rect: bloatedRect];
FOR v: Region ← vias, v.rest WHILE v # NIL DO
via: ViaTileData = NARROW [v.first.value];
IF CDBasics.Intersect [v.first.rect, r] THEN via.hasPoly ← TRUE;
We insert material in the whole influence area of a via.
bloatedRect ← CDBasics.Extend [v.first.rect, polySurroundsViaOnPoly.extent];
InsertMat [polyKey, CDBasics.Intersection[bloatedRect, r], via, state]
Note that via always is a single and non-degenerated via, since collisions of vias are detected when the vias are input.
ENDLOOP
END;
ENDCASE => NULL
END; -- ConvertMat
ExtractObject: CD.DrawProc ~ BEGIN
[inst: Instance, pos: Position, orient: Orientation, pr: REF DrawInformation]
convProc: REF ObjConversionProc;
state: State = NARROW [pr.devicePrivate];
IF state.abort^ THEN ERROR ABORTED;
SELECT inst.ob.class.objectType FROM
$Rect => NULL;
$Cell => inst.ob.class.drawMe [inst, pos, orient , pr];
ENDCASE => BEGIN
convProc ← NARROW [CDProperties.GetProp [from: inst.ob.class.properties, prop: externalKey], REF ObjConversionProc];
IF convProc # NIL THEN convProc^[inst, pos, orient, state]
ELSE inst.ob.class.drawMe [inst, pos, orient, pr]
END
END; -- ExtractObject
ExtractRect: CD.DrawRectProc ~ BEGIN
[r: Rect, l: Layer, pr: DrawRef]
state: State ~ NARROW [pr.devicePrivate, State];
ConvertMat [r, l, state]
END; -- ExtractRect
EnumerateDesign: PROC [inst: CD.Instance, state: State, vias: BOOL] ~ BEGIN
If vias is false, rectangles are enumerated.
dr: CD.DrawRef = CD.CreateDrawRef [[]];
IF vias THEN dr.drawChild ← ExtractObject ELSE dr.drawRect ← ExtractRect;
dr.devicePrivate ← state;
dr.stopFlag ← state.abort;
inst.ob.class.drawMe [inst, inst.location, inst.orientation, dr]
END; -- EnumerateDesign
Operations on the corner-stitched plane
CreateTess: PROC [state: State] ~ BEGIN
Initialises the tesselations.
state.viaTess ← CStitching.NewTesselation [stopFlag: state.abort];
state.materialTess ← CStitching.NewTesselation [stopFlag: state.abort]
END; -- CreateTess
DestroyTess: PROC [state: State] ~ BEGIN
Disposes the tesselations.
CStitching.ResetTesselation [state.viaTess];
CStitching.ResetTesselation [state.materialTess]
END; -- DestroyTess
InsertVia: PROC [r: CD.Rect, state: State, data: ViaTileData] ~ BEGIN
Inserts a via rectangle. This procedure ensures that vias do not overlap.
viaSpacingViolation, splitVia: BOOLFALSE;
errorRect: CD.Rect;
OccupyByVia: CStitching.RectProc = BEGIN
[plane: REF Tesselation, rect: Rect, oldValue: REF, data: REF]
Split: PROC RETURNS [BOOL] ~ INLINE BEGIN
RETURN [(rect.x1= r.x1) AND (rect.y1= r.y1) AND (rect.x2= r.x2) AND (rect.y2= r.y2)]
END; -- Split
WITH oldValue SELECT FROM
v: ViaTileData =>
IF Split [] THEN splitVia ← TRUE
ELSE {viaSpacingViolation ← TRUE; errorRect ← rect};
ENDCASE => IF NOT (viaSpacingViolation OR splitVia) THEN
CStitching.ChangeRect [plane: state.viaTess, rect: rect, new: data]
END; -- OccupyByVia
CStitching.ChangeEnumerateArea [state.viaTess, r, OccupyByVia, data, nothing];
IF viaSpacingViolation THEN BEGIN
CStitching.ChangeEnumerateArea [state.viaTess, r, DeleteTile, data, nothing];
FlagViolation [viaSeparation, errorRect, state]
END
END; -- InsertVia
InsertMat: PROC [mat: ATOM, rect: CD.Rect, via: ViaTileData, state: State] ~ BEGIN
Inserts a rectangle of material and does a weak check for via over gate. The latter is here only because it is easy. In practice a via over a gate is discovered before entering here. (Note that this check for via over gate is not sufficient.)
data: MatTileData = NEW [MatTileDataRec ← [mat, via]];
viaOverGateViolation: BOOLFALSE;
errorRect: CD.Rect;
OccupyByMaterial: CStitching.RectProc = BEGIN
[plane: REF Tesselation, rect: Rect, oldValue: REF, data: REF]
WITH oldValue SELECT FROM
m: MatTileData => IF (m.layerKey # mat) THEN BEGIN
viaOverGateViolation ← TRUE; errorRect ← rect
END;
ENDCASE => IF NOT viaOverGateViolation THEN
CStitching.ChangeRect [plane: state.materialTess, rect: rect, new: data]
END; -- OccupyByMaterial
CStitching.ChangeEnumerateArea [state.materialTess, rect, OccupyByMaterial, data, nothing];
IF viaOverGateViolation THEN BEGIN
CStitching.ChangeEnumerateArea [state.viaTess, rect, DeleteTile, data, nothing];
FlagViolation [viaOnPolyAndDiff, errorRect, state]
END
END; -- InsertMat
DeleteTile: CStitching.RectProc ~ BEGIN
[plane: REF Tesselation, rect: Rect, oldValue: REF, data: REF]
CStitching.ChangeRect [plane, rect, empty]
END; -- DeleteTile
Implementation
LookUnderneath: CStitching.TileProc ~ BEGIN -- PROC [tile: REF Tile, data: REF]
Looks what is under a via cut.
state: State ~ NARROW [data];
via: ViaTileData ~ NARROW [tile.value];
rect: CStitching.Rect ~ CStitching.Area [tile];
IsOnFieldOxide: PROC RETURNS [d: BOOLTRUE] ~ INLINE BEGIN
Is the via on field oxide ?
FOR cut: Region ← CStitching.ListArea [state.materialTess, rect], cut.rest WHILE cut # NIL DO
IF (cut.first.value # NIL) THEN RETURN [FALSE]
ENDLOOP
END; -- IsOnFieldOxide
Accumulate: CStitching.TileProc ~ BEGIN
via: ViaTileData ~ NARROW [data];
mat: MatTileData ~ NARROW [tile.value];
IF (mat = fieldOxide) THEN via.hasFOx ← TRUE-- [field oxide is represented by L]
ELSE BEGIN
IF (mat.via # via) THEN ERROR; -- Consistency test: Tesselation screwed up
SELECT mat.layerKey FROM
diffKey => via.hasDiff ← TRUE;
polyKey => via.hasPoly ← TRUE;
ENDCASE => ERROR
END
END; -- Accumulate
IF state.abort^ THEN ERROR ABORTED;
At this point we know, what is immediately under the via cut and that there the rule viaOverGate is not violated.
via.hasFOx ← NOT (via.hasDiff OR via.hasPoly);
SELECT TRUE FROM
via.hasDiff => BEGIN
CStitching.EnumerateArea [plane: state.materialTess,
rect: CDBasics.Extend [rect, diffSurroundsViaOnDiff.extent],
eachTile: Accumulate,
data: via,
skip: $doNotSkipAnything];
IF via.hasFOx THEN
IF IsOnFieldOxide[] THEN FlagViolation [viaOnFieldOxideAvoidsDiff, rect, state]
ELSE FlagViolation [diffSurroundsViaOnDiff, rect, state]
END;
via.hasPoly => BEGIN
CStitching.EnumerateArea [plane: state.materialTess,
rect: CDBasics.Extend [rect, polySurroundsViaOnPoly.extent],
eachTile: Accumulate,
data: via,
skip: $doNotSkipAnything];
IF via.hasFOx THEN
IF IsOnFieldOxide[] THEN FlagViolation [viaOnFieldOxideAvoidsPoly, rect, state]
ELSE FlagViolation [polySurroundsViaOnPoly, rect, state]
END;
via.hasFOx => BEGIN
CStitching.EnumerateArea [plane: state.materialTess,
rect: CDBasics.Extend [rect, fieldOxideSurroundsViaOnFieldOxide.extent],
eachTile: Accumulate,
data: via,
skip: $doNotSkipAnything];
IF via.hasDiff THEN FlagViolation [viaOnFieldOxideAvoidsDiff, rect, state];
IF via.hasPoly THEN FlagViolation [viaOnFieldOxideAvoidsPoly, rect, state]
END;
ENDCASE => NULL-- no violation
END; -- LookUnderneath
FlagViolation: PROC [rule: Rule, rect: CD.Rect, state: State] ~ BEGIN
Deletes the via from the tesselation and puts an error rectangle in the design.
state.errors ← CONS [[rule, rect], state.errors];
state.errorTotal ← state.errorTotal.SUCC;
IF (state.design = NIL) THEN BEGIN
longMsg: Rope.ROPE = IO.PutFR ["Error: %g at [%g, %g].\n",
IO.rope [rule.msg], IO.int [rect.x1], IO.int [rect.y1]];
TerminalIO.WriteRope [longMsg]
END
ELSE BEGIN
[] ← CDErrors.IncludeMessage [design: state.design,
ob: NIL,
rect: CDBasics.Extend [rect, rule.extent],
message: rule.msg,
owner: errorKey];
IF (state.errorTotal < 30) THEN TerminalIO.WriteChar ['|]
END
END; -- FlagViolation
DarkPoly: CSMonitor.PaintPredicate ~ BEGIN
RETURN [(ISTYPE [val, MatTileData]) AND (NARROW[val,MatTileData].layerKey = polyKey)]
END; -- DarkPoly
ClearVFData: CDEvents.EventProc ~ BEGIN
[event: REF, design: CD.Design, x: REF] RETURNS [dont: BOOLFALSE]
Deletes the via flatenes checker data from a cell when it has been edited.
cell: CD.Object = NARROW [x, CD.Object];
CDProperties.PutObjectProp [onto: cell, prop: checkedKey, val: NIL];
CDProperties.PutObjectProp [onto: cell, prop: externalKey, val: NIL]
END; -- ClearVFData
Initialisation
[] ← CDProperties.RegisterProperty [externalKey, $gbb];
CDProperties.InstallProcs [prop: externalKey, new: [makeCopy: CDProperties.CopyVal]];
[] ← CDProperties.RegisterProperty [errorKey, $gbb];
[] ← CDProperties.RegisterProperty [checkedKey, $gbb];
ExchangeCDInfo;
CDEvents.RegisterEventProc [proc: ClearVFData, event: $AfterCellReplacement];
CDEvents.RegisterEventProc [proc: ClearVFData, event: $AfterChange];
CDSequencer.ImplementCommand [key: $GismoVFSel, proc: InteractiveCall, queue: doQueue];
CDMenus.CreateEntry [menu: $ProgramMenu, entry: "Via Flatness (Gismo)", key: $GismoVFSel];
TerminalIO.WriteRope ["Via flatness checker loaded.\n"];
END.
gbb March 25, 1986 10:40:13 am PST
Changed labels of menu entries.