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 [Info, InstList], CDOrient USING [MapRect], CDProperties USING [CopyVal, GetProp, GetPropFromObject, InstallProcs, PutProp, PutPropOnObject, RegisterProperty], CDSequencer USING [Command, ImplementCommand], CDSimpleRules USING [GetLayer], CMosB USING [cmosB, cut2, lambda], CornerStitching USING [all, Area, ChangeRect, CsRect, EnumerateArea, FreeTesselation, FuncChangeRect, ListArea, NewTesselation, PerTileChangeProc, PerTileProc, 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, CornerStitching, CSMonitor, IO, Process, Rope, TerminalIO EXPORTS ViaFlatness ~ BEGIN debug: BOOL _ FALSE; timing: BOOL _ FALSE; Region: TYPE ~ LIST OF REF CornerStitching.Region; Tess: TYPE ~ REF CornerStitching.Tesselation; Tile: TYPE ~ REF CornerStitching.Tile; empty: REF ~ NIL; 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; 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.GetPropFromObject [o, checkedKey] # NIL); oldErrors: ErrorList = NARROW [CDProperties.GetPropFromObject [o, externalKey]]; IF checked THEN BEGIN TerminalIO.WriteRope ["This object had already been analysed.\n"]; 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]; CornerStitching.EnumerateArea [plane: state.viaTess, rect: CornerStitching.all, perTile: LookUnderneath, data: state, skipValue: empty]; IF NOT debug THEN DestroyTess [state]; CDProperties.PutPropOnObject [o, checkedKey, checkedKey]; CDProperties.PutPropOnObject [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.PutPropOnObject [all.first.ob, checkedKey, NIL]; errorSummary _ CONS [[CDOps.Info[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:\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]]] ELSE 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: REF 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 _ CornerStitching.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]; CornerStitching.FuncChangeRect [state.viaTess, bloatedRect, DeleteTile]; RETURN END ENDLOOP; bloatedRect _ CDBasics.Extend [r, diffSurroundsViaOnDiff.extent]; vias _ CornerStitching.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 _ CornerStitching.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]; CornerStitching.FuncChangeRect [state.viaTess, bloatedRect, DeleteTile]; RETURN END ENDLOOP; bloatedRect _ CDBasics.Extend [r, viaOnFieldOxideAvoidsPoly.extent]; vias _ CornerStitching.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]; CornerStitching.FuncChangeRect [state.viaTess, bloatedRect, DeleteTile]; RETURN END ENDLOOP; bloatedRect _ CDBasics.Extend [r, polySurroundsViaOnPoly.extent]; vias _ CornerStitching.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 [NIL]; 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 _ CornerStitching.NewTesselation [stopFlag: state.abort]; state.materialTess _ CornerStitching.NewTesselation [stopFlag: state.abort] END; -- CreateTess DestroyTess: PROC [state: State] ~ BEGIN CornerStitching.FreeTesselation [state.viaTess]; CornerStitching.FreeTesselation [state.materialTess] END; -- DestroyTess InsertVia: PROC [r: CD.Rect, state: State, data: ViaTileData] ~ BEGIN viaSpacingViolation, splitVia: BOOL _ FALSE; errorRect: CD.Rect; OccupyByVia: CornerStitching.PerTileChangeProc = 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 CornerStitching.ChangeRect [plane: state.viaTess, rect: rect, newValue: data] END; -- OccupyByVia CornerStitching.FuncChangeRect [state.viaTess, r, OccupyByVia, data]; IF viaSpacingViolation THEN BEGIN CornerStitching.FuncChangeRect [state.viaTess, r, DeleteTile, data]; 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: CornerStitching.PerTileChangeProc = BEGIN WITH oldValue SELECT FROM m: MatTileData => IF (m.layerKey # mat) THEN BEGIN viaOverGateViolation _ TRUE; errorRect _ rect END; ENDCASE => IF NOT viaOverGateViolation THEN CornerStitching.ChangeRect [plane: state.materialTess, rect: rect, newValue: data] END; -- OccupyByMaterial CornerStitching.FuncChangeRect [state.materialTess, rect, OccupyByMaterial, data]; IF viaOverGateViolation THEN BEGIN CornerStitching.FuncChangeRect [state.viaTess, rect, DeleteTile, data]; FlagViolation [viaOnPolyAndDiff, errorRect, state] END END; -- InsertMat DeleteTile: CornerStitching.PerTileChangeProc ~ BEGIN CornerStitching.ChangeRect [plane, rect, empty] END; -- DeleteTile LookUnderneath: CornerStitching.PerTileProc ~ BEGIN -- PROC [tile: REF Tile, data: REF] state: State ~ NARROW [data]; via: ViaTileData ~ NARROW [tile.value]; rect: CornerStitching.CsRect ~ CornerStitching.Area [tile]; IsOnFieldOxide: PROC RETURNS [d: BOOL _ TRUE] ~ INLINE BEGIN FOR cut: Region _ CornerStitching.ListArea [state.materialTess, rect], cut.rest WHILE cut # NIL DO IF (cut.first.value # NIL) THEN RETURN [FALSE] ENDLOOP END; -- IsOnFieldOxide Accumulate: CornerStitching.PerTileProc ~ 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 CornerStitching.EnumerateArea [plane: state.materialTess, rect: CDBasics.Extend [rect, diffSurroundsViaOnDiff.extent], perTile: Accumulate, data: via, skipValue: $doNotSkipAnything]; IF via.hasFOx THEN IF IsOnFieldOxide[] THEN FlagViolation [viaOnFieldOxideAvoidsDiff, rect, state] ELSE FlagViolation [diffSurroundsViaOnDiff, rect, state] END; via.hasPoly => BEGIN CornerStitching.EnumerateArea [plane: state.materialTess, rect: CDBasics.Extend [rect, polySurroundsViaOnPoly.extent], perTile: Accumulate, data: via, skipValue: $doNotSkipAnything]; IF via.hasFOx THEN IF IsOnFieldOxide[] THEN FlagViolation [viaOnFieldOxideAvoidsPoly, rect, state] ELSE FlagViolation [polySurroundsViaOnPoly, rect, state] END; via.hasFOx => BEGIN CornerStitching.EnumerateArea [plane: state.materialTess, rect: CDBasics.Extend [rect, fieldOxideSurroundsViaOnFieldOxide.extent], perTile: Accumulate, data: via, skipValue: $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 [tileVal, MatTileData]) AND (NARROW[tileVal,MatTileData].layerKey = polyKey)] END; -- DarkPoly ClearVFData: CDEvents.EventProc ~ BEGIN cell: CD.Object = NARROW [x, CD.Object]; CDProperties.PutPropOnObject [onto: cell, prop: checkedKey, val: NIL]; CDProperties.PutPropOnObject [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 [a: $GismoVFSel, p: InteractiveCall, queue: doQueue]; CDMenus.CreateEntry [menu: $ProgramMenu, entry: "Via flatness", key: $GismoVFSel]; TerminalIO.WriteRope ["Via flatness checker loaded.\n"]; END. 4ViaFlatnessImpl.mesa Copyright c 1986 by Xerox Corporation. All rights reserved. Giordano Bruno Beretta, January 21, 1986 2:54:32 pm PST gbb March 15, 1986 3:07:52 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 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. 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: CsRect, 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: CsRect, oldValue: REF, data: REF] [plane: REF Tesselation, rect: CsRect, 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 ΚU˜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šœ žœ5žœ˜GKšœžœ3˜Pšžœ žœž˜KšœB˜BKšžœ˜Kšžœ˜—šžœžœž˜*KšœP˜PKšžœžœ˜Kšžœ˜—Kšžœžœžœ*˜;Kšœžœ˜%Kšœžœ žœžœžœžœžœžœ˜BKšœ˜šžœžœž˜Kšœ5žœ˜:KšœH˜HKšžœ˜—K™8Kšœžœ˜!Kšœ+Οe œ‡™ΎKšœžœ˜"Kšœ£ œ™5Kšœ‰˜‰Kšžœžœžœ˜&Kšœ9˜9Kšœ<˜