ViaFlatnessImpl.mesa
Copyright © 1986 by Xerox Corporation. All rights reserved.
Giordano Bruno Beretta, January 21, 1986 2:54:32 pm PST
gbb December 8, 1986 4:48:59 pm PST
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, Rect, Technology, Transformation],
CDAtomicObjects USING [AtomicObsSpecific, DrawList],
CDBasics USING [Extend, Intersect, Intersection, MapRect, NonEmpty],
CDCommandOps USING [DoWithResource],
CDErrors USING [IncludeMessage, RemoveMessages],
CDEvents USING [EventProc, RegisterEventProc],
CDOps USING [ObjectRope, InstList],
CDProperties USING [CopyVal, GetProp, GetObjectProp, InstallProcs, PutProp, PutObjectProp, RegisterProperty],
CDSequencer USING [Command, ImplementCommand, UseAbortFlag],
CDSimpleRules USING [GetLayer],
CMosB USING [cmosB, cut2, lambda],
CStitching USING [all, Area, ChangeRect, DumpCache, Rect, EnumerateArea, ResetTesselation, ChangeEnumerateArea, ListArea, NewTesselation, RectProc, TileProc, Region, Tesselation, Tile],
CSMonitor USING [Monitor, PaintPredicate, Reset],
FS USING [StreamOpen],
IO USING [Close, int, PutF1, PutFR, PutFR1, PutRope, rope, STREAM],
PrincOpsUtils USING [],
Process USING [priorityBackground, SetPriority],
Rope USING [Cat, ROPE],
TerminalIO USING [PutRope],
ViaFlatness USING [ErrorList, Rule],
ViewerClasses USING [Viewer];
ViaFlatnessImpl: CEDAR PROGRAM
IMPORTS BasicTime, CD, CDBasics, CDCommandOps, CDErrors, CDEvents, CDOps, CDProperties, CDSequencer, CDSimpleRules, CMosB, CStitching, CSMonitor, FS, IO, Process, Rope, TerminalIO
EXPORTS ViaFlatness
~
BEGIN
debug: BOOL ← FALSE;
timing: BOOL ← FALSE;
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,
errorLog: IO.STREAM];
ErrorList:
TYPE ~ ViaFlatness.ErrorList;
ErrorList: TYPE ~ LIST OF RECORD [rule: Rule; where: CD.Rect];
ViaTileData: TYPE ~ REF ViaTileDataRec;
ViaTileDataRec: TYPE ~ RECORD [
hasDiff: BOOL ← FALSE, -- diffusion
hasPoly: BOOL ← FALSE, -- polysilicide
hasFOx: BOOL ← FALSE]; -- field oxide
MatTileData: TYPE ~ REF MatTileDataRec;
MatTileDataRec: TYPE ~ RECORD [layerKey: ATOM, via: ViaTileData];
diffLayers: CD.Layer ~ 4; -- DANGER: if you changes this, see ConvertMat.
diffKey: ARRAY [0 .. diffLayers) OF ATOM ~ [$ndif, $pdif, $nwelCont, $pwelCont];
genericDiff: ATOM ~ $diff;
polyKey: ATOM ~ $pol;
diffLayer: ARRAY [0 .. diffLayers) OF CD.Layer;
polyLayer: CD.Layer;
fieldOxide: REF ANY ~ NIL;
The rules
In 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
BOOL ←
NIL]
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]];
designName: Rope.ROPE = IF d#NIL THEN d.name ELSE "in the sky";
viaViewer, matViewer: ViewerClasses.Viewer;
IF checked
THEN
BEGIN
TerminalIO.PutRope [":"]; RETURN [oldErrors, -1]
END;
IF (CDProperties.GetObjectProp [o, doNotAnalyse] #
NIL)
THEN
BEGIN
TerminalIO.PutRope [" "]; RETURN [oldErrors, -1]
END;
IF (d.technology # CMosB.cmosB)
THEN
BEGIN
TerminalIO.PutRope [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 [BOOL ← FALSE];
state.errorLog ← FS.StreamOpen [fileName: "[]<>Temp>DRC>ViaFlatness.log", accessOptions: create, keep: 5, extendFileProc: NIL, remoteCheck: FALSE, wDir: NIL]; -- keep is 5 because of incremental use
state.errorLog.PutF1 ["Error log by ViaFlatness. Design: %g\n\n", IO.rope [designName]];
CreateTess [state];
IF debug
THEN
BEGIN
viaViewer ← CSMonitor.Monitor [state.viaTess, "Via Tesselation", NIL];
matViewer ← CSMonitor.Monitor [state.materialTess, "Material Tesselation", DarkPoly]
END;
Smash vias into a flat tesselation of interesting areas.
EnumerateDesign [c, state, TRUE];
IF debug THEN CSMonitor.Reset [viaViewer];
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];
IF debug THEN CSMonitor.Reset [matViewer];
Enumerate the materialTess and check it for flatness.
CStitching.EnumerateArea [plane: state.viaTess,
rect: CStitching.all,
eachTile: LookUnderneath,
data: state,
skip: empty];
IF debug THEN {CSMonitor.Reset [viaViewer]; CSMonitor.Reset [matViewer]}
ELSE DestroyTess [state];
CDProperties.PutObjectProp [o, checkedKey, checkedKey];
CDProperties.PutObjectProp [o, externalKey, state.errors];
state.errorLog.PutRope ["\nDRC terminated normally."]; state.errorLog.Close [];
RETURN [state.errors, state.errorTotal]
END; -- Verify
InteractiveCall:
PROC [comm: CDSequencer.Command] ~
BEGIN
Called by ChipNDale upon activation of the command.
abort: REF BOOL ← NEW [BOOL ← FALSE];
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.ObjectRope[all.first.ob], Verify [all.first, comm.design, abort].errorTotal], errorSummary];
TerminalIO.PutRope ["."]
END
ENDLOOP
END; -- VerifySelected
TerminalIO.PutRope ["Checking via flatness.\n"];
startTime ← BasicTime.Now [];
CDSequencer.UseAbortFlag [comm.design, abort];
[] ← CDCommandOps.DoWithResource [VerifySelected, comm, externalKey];
stopTime ← BasicTime.Now [];
IF (errorSummary #
NIL)
THEN
BEGIN
TerminalIO.PutRope ["\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.PutRope [IO.PutFR ["%g: previously analysed.\n", IO.rope[e.first.c]]]
IF (e.first.n > 0)
THEN
TerminalIO.PutRope [IO.PutFR ["%g: %g.\n", IO.rope[e.first.c], IO.int[e.first.n]]]
ENDLOOP
END; -- write error summary
TerminalIO.PutRope ["Via flatness verification done.\n"];
IF timing THEN TerminalIO.PutRope [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, transf: CD.Transformation, 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];
FOR l:
CD.Layer
IN [0 .. diffLayers)
DO
diffLayer[l] ← CDSimpleRules.GetLayer [tech, diffKey[l]]
ENDLOOP;
polyLayer ← CDSimpleRules.GetLayer [tech, polyKey]
END; -- ExchangeCDInfo
ConvertVia: ObjConversionProc =
BEGIN
[inst: CD.Instance, transf: CD.Transformation, state: State]
data: ViaTileData ← NEW [ViaTileDataRec];
FOR geom: CDAtomicObjects.DrawList ←
NARROW [inst.ob.specific, CDAtomicObjects.AtomicObsSpecific].rList, geom.rest
WHILE geom #
NIL
DO
SELECT geom.first.layer
FROM
CMosB.cut2 =>
BEGIN
r: CD.Rect = CDBasics.MapRect [itemInCell: geom.first.r, cellInWorld: transf];
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[0], diffLayer[1], diffLayer[2], diffLayer[3] =>
BEGIN
--
DANGER
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];
DeleteRect [state.viaTess, v.first.rect]
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 [genericDiff, 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];
DeleteRect [state.viaTess, v.first.rect]
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];
DeleteRect [state.viaTess, v.first.rect]
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, trans , pr];
ENDCASE =>
BEGIN
convProc ← NARROW [CDProperties.GetProp [from: inst.ob.class.properties, prop: externalKey], REF ObjConversionProc];
IF convProc # NIL THEN convProc^[inst, trans, state]
ELSE inst.ob.class.drawMe [inst, trans, 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.trans, 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];
CStitching.DumpCache []; state.viaTess ← state.materialTess ← NIL
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: BOOL ← FALSE;
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
DeleteRect [state.viaTess, r];
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: BOOL ← FALSE;
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
DeleteRect [state.viaTess, rect];
FlagViolation [viaOnPolyAndDiff, errorRect, state]
END
END; -- InsertMat
DeleteRect:
PROC [plane: Tess, rect:
CD.Rect] ~
BEGIN
plane.ChangeRect [rect, empty]
END; -- DeleteRect
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:
BOOL ←
TRUE] ~
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
genericDiff => 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.
longMsg: Rope.ROPE = IO.PutFR ["Error: %g at [%g, %g].\n",
IO.rope [rule.msg], IO.int [rect.x1], IO.int [rect.y1]];
state.errorLog.PutF1 ["%g\n", IO.rope [longMsg]];
state.errors ← CONS [[rule, rect], state.errors];
state.errorTotal ← state.errorTotal.SUCC;
IF (state.design = NIL) THEN TerminalIO.PutRope [longMsg]
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.PutRope ["|"]
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: BOOL ← FALSE]
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, procs: [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.PutRope ["Via flatness checker loaded.\n"];
END.
gbb March 25, 1986 10:40:13 am PST
Changed labels of menu entries.
gbb July 31, 1986 6:17:41 pm PDT
changes to: DIRECTORY, DestroyTess: now really disposes the tiles.
gbb September 2, 1986 1:00:28 pm PDT
Added an error log.
changes to: DIRECTORY, IMPORTS, Verify, FlagViolation: puts long message in error log.
gbb October 17, 1986 1:29:13 pm PDT
Fixed the fact, that diffusion can be in different ChipNDale layers, but it counts all as being the same for the flatness test.
changes to: ExchangeCDInfo, ConvertMat
gbb October 20, 1986 5:51:28 pm PDT
Fixed an uninitialized variable. Tuned performance.
changes to: ConvertMat, InsertVia, InsertMat, DeleteTile, LookUnderneath