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; 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; Rule: TYPE ~ ViaFlatness.Rule; 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"]; 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"]; Verify: PUBLIC PROC [c: CD.Instance, d: CD.Design _ NIL, abort: REF BOOL _ NIL] RETURNS [errors: ErrorList, errorTotal: INT] ~ BEGIN 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; EnumerateDesign [c, state, TRUE]; IF debug THEN CSMonitor.Reset [viaViewer]; EnumerateDesign [c, state, FALSE]; IF debug THEN CSMonitor.Reset [matViewer]; 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 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 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 > 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 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 ObjConversionProc: TYPE = PROCEDURE [inst: CD.Instance, transf: CD.Transformation, state: State]; ExchangeCDInfo: PROC ~ BEGIN 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 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 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; bloatedRect _ CDBasics.Extend [v.first.rect, diffSurroundsViaOnDiff.extent]; InsertMat [genericDiff, CDBasics.Intersection[bloatedRect, r], via, state] 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; bloatedRect _ CDBasics.Extend [v.first.rect, polySurroundsViaOnPoly.extent]; InsertMat [polyKey, CDBasics.Intersection[bloatedRect, r], via, state] ENDLOOP END; ENDCASE => NULL END; -- ConvertMat ExtractObject: CD.DrawProc ~ BEGIN 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 state: State ~ NARROW [pr.devicePrivate, State]; ConvertMat [r, l, state] END; -- ExtractRect EnumerateDesign: PROC [inst: CD.Instance, state: State, vias: BOOL] ~ BEGIN 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 CreateTess: PROC [state: State] ~ BEGIN state.viaTess _ CStitching.NewTesselation [stopFlag: state.abort]; state.materialTess _ CStitching.NewTesselation [stopFlag: state.abort] END; -- CreateTess DestroyTess: PROC [state: State] ~ BEGIN 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 viaSpacingViolation, splitVia: BOOL _ FALSE; errorRect: CD.Rect; OccupyByVia: CStitching.RectProc = BEGIN 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 data: MatTileData = NEW [MatTileDataRec _ [mat, via]]; viaOverGateViolation: BOOL _ FALSE; errorRect: CD.Rect; OccupyByMaterial: CStitching.RectProc = BEGIN 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 LookUnderneath: CStitching.TileProc ~ BEGIN -- PROC [tile: REF Tile, data: REF] state: State ~ NARROW [data]; via: ViaTileData ~ NARROW [tile.value]; rect: CStitching.Rect ~ CStitching.Area [tile]; IsOnFieldOxide: PROC RETURNS [d: BOOL _ TRUE] ~ INLINE BEGIN 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; 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 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 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 [] _ 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]; TerminalIO.PutRope ["Via flatness checker loaded.\n"]; END. LViaFlatnessImpl.mesa Copyright c 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". ErrorList: TYPE ~ LIST OF RECORD [rule: Rule; where: CD.Rect]; The rules In  units from the minimal metal border of the via (not from the cut). TYPE ~ RECORD [extent: CD.Number, msg: Rope.ROPE] In the following rules the extent is used only to determine the overlap of the error rectangle. Environment: public procedures and interactive interface to ChipNDale If a design is not provided, the error messages are displayed in the terminal viewer. Smash vias into a flat tesselation of interesting areas. 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). Enumerate the materialTess and check it for flatness. Called by ChipNDale upon activation of the command. Verifies all selected cells in background priority. IF (e.first.n = -1) THEN TerminalIO.PutRope [IO.PutFR ["%g: previously analysed.\n", IO.rope[e.first.c]]] 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. Operations on ChipNDale objects Registers the procedures to extract vias from the design and gets the layers. [inst: CD.Instance, transf: CD.Transformation, state: State] 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. We insert material in the whole influence area of a via. Note that via always is a single and non-degenerated via, since collisions of vias are detected when the vias are input. We insert material in the whole influence area of a via. Note that via always is a single and non-degenerated via, since collisions of vias are detected when the vias are input. [inst: Instance, pos: Position, orient: Orientation, pr: REF DrawInformation] [r: Rect, l: Layer, pr: DrawRef] If vias is false, rectangles are enumerated. Operations on the corner-stitched plane Initialises the tesselations. Disposes the tesselations. Inserts a via rectangle. This procedure ensures that vias do not overlap. [plane: REF Tesselation, rect: Rect, oldValue: REF, data: REF] 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.) [plane: REF Tesselation, rect: Rect, oldValue: REF, data: REF] Implementation Looks what is under a via cut. Is the via on field oxide ? At this point we know, what is immediately under the via cut and that there the rule viaOverGate is not violated. Deletes the via from the tesselation and puts an error rectangle in the design. [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. Initialisation CDMenus.CreateEntry [menu: $ProgramMenu, entry: "Via Flatness (Gismo)", key: $GismoVFSel]; 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 Ê”˜codešœ™Kšœ Ïmœ1™žœžœžœ˜—šœ žœ˜(Kš œ žœžœžœžœžœ™>—Iunitšœ žœžœ˜'Kšœžœžœ¡œ žœžœ¡ œ žœžœ¡œžœžœ¡˜Kšœ žœžœ˜'Kšœžœžœ žœ˜AMšœ žœ ¡Ðbc¡&˜IMšœ žœžœžœ(˜PKšœ žœ ˜Kšœ žœ˜Mšœ žœžœžœ˜/Kšœ žœ˜Mšœ žœžœžœ˜—head™ LšœG™Gšœžœ˜Kšžœžœ žœžœ™1—Mšœ' œ#˜KMšœ' œ˜@Mšœ,žœe˜”Mšœ$ œ+˜PMšœ$ œ ˜EM™_Mšœ œ¡˜YMšœ œ¡˜PMšœ œ˜9Mšœ œ˜9—™EšÏnœžœžœžœžœ žœ žœžœžœžœ!žœž˜„K™UKšœ ˜ Kšœžœ˜Kšœ žœ1žœ˜CKšœžœ/˜LKš œžœžœžœžœžœ˜?Kšœ+˜+šžœ žœž˜Kšœžœ˜1Kšžœ˜—šžœ1žœžœž˜BKšœžœ˜1Kšžœ˜—šžœžœž˜*KšœN˜NKšžœžœ˜Kšžœ˜—Kšžœžœžœ*˜;Kšœžœ˜%Kšœžœ žœžœžœžœžœžœ˜BKš œžœgžœžœžœ¡'˜ÆKšœCžœ˜YKšœ˜šžœžœž˜KšœAžœ˜FKšœT˜TKšžœ˜—K™8Kšœžœ˜!Kšžœžœ˜*Kšœ+Ïe œ‡™¾Kšœžœ˜"Kšžœžœ˜*Kšœ¤ œ™5Kšœ{˜{Kšžœžœ<˜IKšžœ˜Kšœ7˜7Kšœ:˜:KšœO˜OKšžœ!˜'Kšžœ¡˜—š£œžœž˜9K™3Kš œžœžœžœžœžœ˜%Kšœžœ¡˜7Kš œžœžœžœ žœžœ˜4š£œžœž˜8K™3Kšžœ4˜;š žœžœ7žœžœž˜Tšžœžœž˜ Kšžœžœ7žœ˜IKšœžœ#Ïlœ<˜xKšœ˜Kšž˜—Kšž˜—Kšžœ¡˜Mšœ0˜0Kšœ˜Kšœ.˜.KšœE˜EKšœ˜šžœžœžœž˜"Kšœ9˜9šžœžœžœžœ žœžœžœžœž˜Tšžœž™Kšœžœ&žœ™P—šžœž˜Kšœžœžœžœ˜R—Kšž˜—Kšžœ¡˜—Kšœ9˜9Kšžœžœ_˜m—Kšžœ¡˜—š £ œžœžœžœ žœž˜LKšœ Ðekœ ¤œ¦œ%¦¤œ¤ œ¤œ1™ÍKšœ žœ˜Kšœžœ˜'Kšœžœ ˜Kšœžœ ˜Mšœžœžœ ˜$Kšœžœžœ+žœ˜NMšœžœžœ žœ˜-Kšœžœžœ+žœ ˜fMšœžœžœ žœ˜-Kšœžœžœ+žœ˜eKšžœ¡ ˜——™Lš œžœž œžœžœ˜aš£œžœž˜K™MKšœžœ˜"š £œžœžœžœž˜RKšœžœžœ8˜OKšžœžœžœžœ*˜=KšœCžœ˜`Kšžœ¡˜—Mšœ$˜$Kšœ)˜)šžœžœžœž˜'Kšœ8˜8Kšžœ˜—Kšœ2˜2Kšžœ¡˜—š£ œž˜%Kšœžœžœ™ž˜AKšžœ¡ ˜—š£ œžœžœ*ž˜EK™JKšœžœžœ˜,Kšœ žœ˜š£ œž˜(Kšœžœ$žœžœ™>š £œžœžœžœžœž˜)Kšžœžœžœžœ˜TKšžœ¡˜ —šžœ žœž˜šœ˜Kšžœ žœ ž˜ Kšžœžœ˜4—š žœžœžœžœ ž˜8KšœC˜C——Kšžœ¡˜—MšœN˜Nšžœžœž˜!Kšœ˜Kšœ/˜/Kšž˜—Kšžœ¡ ˜—š £ œžœžœžœ)ž˜RK™òKšœžœ˜6Kšœžœžœ˜#Kšœ žœ˜š£œž˜-Kšœžœ$žœžœ™>šžœ žœž˜šœžœžœž˜2Kšœžœ˜.Kšžœ˜—šžœžœžœž˜+KšœH˜H——Kšžœ¡˜—Mšœ[˜[šžœžœž˜"Kšœ!˜!Kšœ2˜2Kšž˜—Kšžœ¡ ˜—š£ œžœžœ ž˜5Kšœ˜Kšžœ¡ ˜——™š£œžœ¡#˜OK™Kšœžœ˜Kšœžœ˜'Kšœ/˜/š £œžœžœžœžœžœž˜