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: 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]; 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]; diffKey: ATOM ~ $ndif; polyKey: ATOM ~ $pol; diffLayer, 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]]; 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 [BOOL _ FALSE]; CreateTess [state]; IF debug THEN BEGIN [] _ CSMonitor.Monitor [state.viaTess, "Via Tesselation", NIL]; [] _ CSMonitor.Monitor [state.materialTess, "Material Tesselation", DarkPoly] END; EnumerateDesign [c, state, TRUE]; EnumerateDesign [c, state, FALSE]; 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 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.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 > 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 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, pos: CD.Position, orient: CD.Orientation, 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]; diffLayer _ CDSimpleRules.GetLayer [tech, diffKey]; polyLayer _ CDSimpleRules.GetLayer [tech, polyKey] END; -- ExchangeCDInfo ConvertVia: ObjConversionProc = BEGIN 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 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; bloatedRect _ CDBasics.Extend [v.first.rect, diffSurroundsViaOnDiff.extent]; InsertMat [diffKey, 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]; 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; 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, 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 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.location, inst.orientation, 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] 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 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 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 CStitching.ChangeEnumerateArea [state.viaTess, rect, DeleteTile, data, nothing]; FlagViolation [viaOnPolyAndDiff, errorRect, state] END END; -- InsertMat DeleteTile: CStitching.RectProc ~ BEGIN CStitching.ChangeRect [plane, rect, empty] END; -- DeleteTile 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 diffKey => 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 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 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, 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. ÞViaFlatnessImpl.mesa Copyright c 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". ErrorList: TYPE ~ LIST OF RECORD [rule: Rule; where: CD.Rect]; The rules In l 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.WriteRope [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, pos: CD.Position, orient: CD.Orientation, 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] [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 gbb March 25, 1986 10:40:13 am PST Changed labels of menu entries. Ê–˜codešœ™Kšœ Ïmœ1™žœ˜‚šœ žœ˜(Kš œ žœžœžœžœžœ™>—Iunitšœ žœžœ˜'Kšœžœžœ¡œ žœžœ¡ œ žœžœ¡œžœžœ¡˜Kšœ žœžœ˜'Kšœžœžœ žœ˜AMšœ žœ ˜Kšœ žœ˜Mšœžœ˜Mšœ žœžœžœ˜—head™ Lšœ œC™Gšœžœ˜Kšžœžœ žœžœ™1—Mšœ' œ#˜KMšœ' œ˜@Mšœ,žœe˜”Mšœ$ œ+˜PMšœ$ œ ˜EM™_Mšœ œ¡˜YMšœ œ¡˜PMšœ œ˜9Mšœ œ˜9—™EšÏnœžœžœžœžœ žœ žœžœžœžœ!žœž˜„K™UKšœ ˜ Kšœžœ˜Kšœ žœ1žœ˜CKšœžœ/˜Lšžœ žœž˜Kšœžœ˜2Kšžœ˜—šžœ1žœžœž˜BKšœžœ˜2Kšžœ˜—šžœžœž˜*KšœP˜PKšžœžœ˜Kšžœ˜—Kšžœžœžœ*˜;Kšœžœ˜%Kšœžœ žœžœžœžœžœžœ˜BKšœ˜šžœžœž˜Kšœ:žœ˜?KšœM˜MKšžœ˜—K™8Kšœžœ˜!Kšœ+Ïe œ‡™¾Kšœžœ˜"Kšœ£ œ™5Kšœ{˜{Kšžœžœžœ˜&Kšœ7˜7Kšœ:˜:Kšžœ!˜'Kšžœ¡˜—š¢œžœž˜9K™3Kš œžœžœžœžœžœ˜%Kšœžœ¡˜7Kš œžœžœžœ žœžœ˜4š¢œžœž˜8K™3Kšžœ4˜;š žœžœ7žœžœž˜Tšžœžœž˜ Kšžœžœ7žœ˜IKšœžœ#Ïlœ<˜xKšœ˜Kšž˜—Kšž˜—Kšžœ¡˜Mšœ2˜2Kšœ˜KšœN˜NKšœ˜šžœžœžœž˜"Kšœ;˜;šžœžœžœžœ žœžœžœžœž˜Tšžœž™Kšœžœ&žœ™R—šžœž˜Kšœžœžœžœ˜T—Kšž˜—Kšžœ¡˜—Kšœ;˜;Kšžœžœa˜o—Kšžœ¡˜—š ¢ œžœžœžœ žœž˜LKšœ Ðekœ £œ¥œ%¥£œ£ œ£œ1™ÍKšœ žœ˜Kšœžœ˜'Kšœžœ ˜Kšœžœ ˜Mšœžœžœ ˜$Kšœžœžœ+žœ˜NMšœžœžœ žœ˜-Kšœžœžœ+žœ ˜fMšœžœžœ žœ˜-Kšœžœžœ+žœ˜eKšžœ¡ ˜——™Lš œžœž œžœžœžœ˜pš¢œžœž˜K™MKšœžœ˜"š ¢œžœžœžœž˜RKšœžœžœ8˜OKšžœžœžœžœ*˜=KšœCžœ˜`Kšžœ¡˜—Mšœ$˜$Kšœ)˜)Kšœ3˜3Kšœ2˜2Kšžœ¡˜—š¢ œž˜%Kšœžœžœžœ™KKšœžœ˜)š žœ"žœFžœžœž˜„šžœž˜šœž˜Kšœžœv˜{Kšœ*˜*Kšžœ˜—Kšžœž˜—Kšž˜—Kšžœ¡ ˜—š ¢ œžœžœžœž˜DKšœ‰£œS™ÝKšœ žœ˜Kšœ ˜ Kš žœžœžœžœ¡˜;Kšžœžœžœžœ˜#šžœž˜šœ ž˜KšœD˜DKšœE˜Ešžœžœžœž˜-Kšœžœ˜*šžœ žœž˜Kšœ1˜1KšœS˜SKšž˜Kšž˜—Jšžœ˜—JšœA˜AKšœE˜Ešžœžœžœž˜-Kšœžœ˜*Kšžœ&žœžœ˜@K™8KšœL˜LKšœF˜FKšœ £œk™xJšž˜—Jšžœ˜—šœ ž˜Kšœ;˜;šžœžœžœž˜-Kšœžœ˜*šžœžœž˜Kšœ1˜1KšœS˜SKšž˜Kšž˜—Jšžœ˜—KšœD˜DKšœE˜Ešžœžœžœž˜-Kšœžœ˜*šžœ žœž˜Kšœ1˜1KšœS˜SKšž˜Kšž˜—Jšžœ˜—JšœA˜AKšœE˜Ešžœžœžœž˜-Kšœžœ˜*Kšžœ&žœžœ˜@K™8KšœL˜LKšœF˜FKšœ £œk™xJšž˜—Jšžœ˜—Kšžœž˜—Kšžœ¡ ˜—š¢ œžœ ž˜"Kšœ9žœ™MKšœ žœ˜ Kšœžœ˜)Mšžœžœžœžœ˜#šžœž˜$Kšœ žœ˜Kšœ7˜7šžœž˜Kšœ žœLžœ˜tKšžœ žœžœ$˜:Kšžœ-˜1Kšž˜——Kšžœ¡ ˜—š¢ œžœž˜$Kšœ ™ Kšœžœ˜0Kšœ˜Kšžœ¡ ˜—š ¢œžœžœžœž˜KKšœ£œ%™,Kšœžœ žœ˜'Mšžœžœžœ˜IKšœ˜Kšœ˜Kšœ@˜@Kšžœ¡˜——™'š¢ œžœž˜'K™KšœB˜BKšœF˜FKšžœ¡ ˜—š¢ œžœž˜(K™Kšœ,˜,Kšœ0˜0Kšžœ¡ ˜—š¢ œžœžœ*ž˜EK™JKšœžœžœ˜,Kšœ žœ˜š¢ œž˜(Kšœžœ$žœžœ™>š ¢œžœžœžœžœž˜)Kšžœžœžœžœ˜TKšžœ¡˜ —šžœ žœž˜šœ˜Kšžœ žœ ž˜ Kšžœžœ˜4—š žœžœžœžœ ž˜8KšœC˜C——Kšžœ¡˜—MšœN˜Nšžœžœž˜!KšœM˜MKšœ/˜/Kšž˜—Kšžœ¡ ˜—š ¢ œžœžœžœ)ž˜RK™òKšœžœ˜6Kšœžœžœ˜#Kšœ žœ˜š¢œž˜-Kšœžœ$žœžœ™>šžœ žœž˜šœžœžœž˜2Kšœžœ˜.Kšžœ˜—šžœžœžœž˜+KšœH˜H——Kšžœ¡˜—Mšœ[˜[šžœžœž˜"KšœP˜PKšœ2˜2Kšž˜—Kšžœ¡ ˜—š¢ œž˜'Kšœžœ$žœžœ™>Kšœ*˜*Kšžœ¡ ˜——™š¢œžœ¡#˜OK™Kšœžœ˜Kšœžœ˜'Kšœ/˜/š ¢œžœžœžœžœžœž˜