DIRECTORY BasicTime USING [GMT, Now, Period], CD USING [CreateDrawRef, Design, DrawProc, DrawRectProc, DrawRef, Instance, InstanceList, Layer, LayerKey, Number, Object, ObjectClass, Orientation, Position, Rect, Technology], CDBasics USING [Extend, NonEmpty], CDCommandOps USING [CallWithResource], CDErrors USING [IncludeMessage, RemoveMessages], CDEvents USING [EventProc, RegisterEventProc], CDMenus USING [CreateEntry], CDOps USING [ObjectInfo, InstList], CDProperties USING [CopyVal, GetObjectProp, InstallProcs, PutObjectProp, RegisterProperty], CDSequencer USING [Command, ImplementCommand], CMosB USING [cmosB, ndif, nwell, pdif, pwell, lambda], CStitching USING [ChangeRect, Rect, ResetTesselation, ChangeEnumerateArea, ListArea, NewTesselation, RectProc, Region, Tesselation, Tile], CSMonitor USING [Monitor, PaintPredicate, Reset], DiffInWell USING [ErrorList, Rule], IO USING [int, PutFR, PutFR1, rope], PrincOpsUtils USING [], Process USING [priorityBackground, SetPriority], Rope USING [Cat, ROPE], TerminalIO USING [WriteChar, WriteRope], ViewerClasses USING [Viewer]; DiffInWellImpl: CEDAR PROGRAM IMPORTS BasicTime, CD, CDBasics, CDCommandOps, CDErrors, CDEvents, CDMenus, CDOps, CDProperties, CDSequencer, CMosB, CSMonitor, CStitching, IO, Process, Rope, TerminalIO EXPORTS DiffInWell ~ 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 ~ $GismoDIW; -- used in traffic with external packages checkedKey: ATOM ~ $GismoDIWChecked; -- used to mark checked cells errorKey: ATOM ~ $GismoDIWError; doNotAnalyse: ATOM = $DoNotDRC; State: TYPE ~ REF StateRec; StateRec: TYPE ~ RECORD [design: CD.Design, abort: REF BOOL, wellTess: Tess, errors: ErrorList, errorTotal: INT _ 0]; ErrorList: TYPE ~ DiffInWell.ErrorList; fieldOxide: ATOM ~ NIL; pWell: ATOM ~ CD.LayerKey [CMosB.pwell]; nWell: ATOM ~ CD.LayerKey [CMosB.nwell]; Rule: TYPE ~ DiffInWell.Rule; nWellSurround: Rule ~ [5 * l, "n-well too small or p-diffusion too close to p-well"]; pWellSurround: Rule ~ [5 * l, "n-diffusion too close to n-well or p-well too small"]; wellConflict: Rule ~ [2 * l, "p-well overlaps n-well"]; NinN: Rule ~ [2 * l, "n-diffusion in n-well"]; PinP: Rule ~ [2 * l, "p-diffusion in p-well"]; 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]]; debuggingViewer: ViewerClasses.Viewer; 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 debuggingViewer _ CSMonitor.Monitor [state.wellTess, "Well Tesselation", DarkNwell] END; EnumerateDesign [inst: c, state: state, wells: TRUE]; CSMonitor.Reset [debuggingViewer]; EnumerateDesign [inst: c, state: state, wells: FALSE]; 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 well surround.\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 > 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 ["Well surround 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 ExtractWells: CD.DrawRectProc ~ BEGIN state: State ~ NARROW [pr.devicePrivate, State]; IF (l = CMosB.nwell) OR (l = CMosB.pwell) THEN InsertWell [r: r, type: CD.LayerKey[l], state: state] END; -- ExtractWells ExtractDiff: CD.DrawRectProc ~ BEGIN state: State ~ NARROW [pr.devicePrivate, State]; IF (l = CMosB.ndif) OR (l = CMosB.pdif) THEN Inquire [r, l, state] END; -- ExtractDiff EnumerateDesign: PROC [inst: CD.Instance, state: State, wells: BOOL] ~ BEGIN dr: CD.DrawRef = CD.CreateDrawRef [[]]; dr.drawRect _ IF wells THEN ExtractWells ELSE ExtractDiff; 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.wellTess _ CStitching.NewTesselation [stopFlag: state.abort] END; -- CreateTess DestroyTess: PROC [state: State] ~ BEGIN CStitching.ResetTesselation [state.wellTess] END; -- DestroyTess InsertWell: PROC [r: CD.Rect, state: State, type: ATOM] ~ BEGIN wellSpacingViolation: BOOL _ FALSE; errorRect: CD.Rect; OccupyByWell: CStitching.RectProc = BEGIN WITH oldValue SELECT FROM well: ATOM => IF well=NIL THEN ERROR ELSE IF (well # type) THEN {wellSpacingViolation _ TRUE; errorRect _ rect}; ENDCASE => -- by Cedar definition we always come here if oldValue is NIL CStitching.ChangeRect [plane: state.wellTess, rect: rect, new: type] END; -- OccupyByWell IF state.abort^ THEN ERROR ABORTED; CStitching.ChangeEnumerateArea [state.wellTess, r, OccupyByWell, type, nothing]; IF wellSpacingViolation THEN FlagViolation [wellConflict, errorRect, state] END; -- InsertWell DeleteTile: CStitching.RectProc ~ BEGIN CStitching.ChangeRect [plane, rect, empty] END; -- DeleteTile Inquire: PROC [r: CD.Rect, layer: CD.Layer, state: State] = BEGIN bloatedRect: CD.Rect; wells: Region; ispDiff: BOOL = (layer = CMosB.pdif); IF NOT CDBasics.NonEmpty[r] THEN RETURN; -- empty rectangle IF state.abort^ THEN ERROR ABORTED; wells _ CStitching.ListArea [plane: state.wellTess, rect: r]; FOR w: Region _ wells, w.rest WHILE w # NIL DO well: ATOM _ NARROW [w.first.value]; IF (ispDiff AND (well = fieldOxide)) OR (ispDiff AND (well = pWell)) THEN FlagViolation [PinP, w.first.rect, state]; IF ((NOT ispDiff) AND (well = nWell)) THEN FlagViolation [NinN, w.first.rect, state] ENDLOOP; bloatedRect _ CDBasics.Extend [r, nWellSurround.extent]; wells _ CStitching.ListArea [plane: state.wellTess, rect: bloatedRect]; FOR w: Region _ wells, w.rest WHILE w # NIL DO well: ATOM _ NARROW [w.first.value]; IF (ispDiff AND (well = fieldOxide)) OR (ispDiff AND (well = pWell)) THEN FlagViolation [nWellSurround, w.first.rect, state]; IF ((NOT ispDiff) AND (well = nWell)) THEN FlagViolation [pWellSurround, w.first.rect, state] ENDLOOP END; -- Inquire 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 DarkNwell: CSMonitor.PaintPredicate ~ BEGIN RETURN [(val # NIL) AND (NARROW [val, ATOM] = nWell)] END; -- DarkNwell ClearDIWData: 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; -- ClearDIWData [] _ CDProperties.RegisterProperty [externalKey, $gbb]; CDProperties.InstallProcs [prop: externalKey, new: [makeCopy: CDProperties.CopyVal]]; [] _ CDProperties.RegisterProperty [errorKey, $gbb]; [] _ CDProperties.RegisterProperty [checkedKey, $gbb]; CDEvents.RegisterEventProc [proc: ClearDIWData, event: $AfterCellReplacement]; CDEvents.RegisterEventProc [proc: ClearDIWData, event: $AfterChange]; CDSequencer.ImplementCommand [key: $GismoDIWSel, proc: InteractiveCall, queue: doQueue]; CDMenus.CreateEntry [menu: $ProgramMenu, entry: "Diffusion in well (Gismo)", key: $GismoDIWSel]; TerminalIO.WriteRope ["Diffusion in well checker loaded.\n"]; END. ͺDiffInWellImpl.mesa Copyright c 1986 by Xerox Corporation. All rights reserved. Giordano Bruno Beretta, May 27, 1986 1:59:07 pm PDT gbb June 13, 1986 4:02:10 pm PDT Checks that diffusion is in the correct well. This implementation is "flat", because wells are not layed out hierarchically anyway. 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 wells into a flat tesselation of interesting areas. Enumerate all diffusion rectangles and perform a query with bloated rectangles. For n-diff, an n-well is an a violation, while for p-dif both a pwell and fieldOxide are a violation. 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 [r: Rect, l: Layer, pr: DrawRef] [r: Rect, l: Layer, pr: DrawRef] If wells is false, diffusion rectangles are enumerated. Operations on the corner-stitched plane Initialises the tesselations. Disposes the tesselations. Inserts a well. This procedure ensures that wells do not overlap. [plane: REF Tesselation, rect: Rect, oldValue: REF, data: REF] [plane: REF Tesselation, rect: Rect, oldValue: REF, data: REF] Implementation Algorithm: If there is antagonist material in a wellSurround-sphere from diffusion, then the a violation is flagged. Verify diffusion type. Verify surround. 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 diffufion in well checker data from a cell when it has been edited. Initialisation Κ l˜codešœ™Kšœ Οmœ1™—Iunitšœ žœžœ˜Kšœžœžœ˜(Kšœžœžœ˜(—head™ Lšœ œC™Gšœžœ˜Kšžœžœ žœžœ™1—Mšœ œ9˜UMšœ œ9˜UM™_Mšœ œ˜7Mšœ œ˜.Mšœ œ˜.—™EšΟnœžœžœžœžœ žœ žœžœžœžœ!žœž˜„K™UKšœ ˜ Kšœžœ˜Kšœ žœ1žœ˜CKšœžœ/˜LKšœ&˜&šžœ žœž˜Kšœžœ˜2Kšžœ˜—šžœ1žœžœž˜BKšœžœ˜2Kšžœ˜—šžœžœž˜*KšœP˜PKšžœžœ˜Kšžœ˜—Kšžœžœžœ*˜;Kšœžœ˜%Kšœžœ žœžœžœžœžœžœ˜BKšœ˜šžœžœž˜KšœS˜SKšžœ˜—K™9Kšœ/žœ˜5Kšœ"˜"KšœΆ™ΆKšœ/žœ˜6KšœΟe œ™5Kšžœžœžœ˜&Kšœ7˜7Kšœ:˜:Kšžœ!˜'Kšžœ‘˜—š’œžœž˜9K™3Kš œžœžœžœžœžœ˜%Kšœžœ‘˜7Kš œžœžœžœ žœžœ˜4š’œžœž˜8K™3Kšžœ4˜;š žœžœ7žœžœž˜Tšžœžœž˜ Kšžœžœ7žœ˜IKšœžœ#Ÿœ<˜xKšœ˜Kšž˜—Kšž˜—Kšžœ‘˜Mšœ3˜3Kšœ˜KšœN˜NKšœ˜šžœžœžœž˜"Kšœ,˜,šžœžœžœžœ žœžœžœžœž˜Tšžœž˜Kšœžœžœžœ˜T—Kšž˜—Kšžœ‘˜—Kšœ<˜šžœ žœž˜š œžœžœžœžœžœž˜*Kšžœžœžœ˜F—šžœ‘.Πce‘˜HKšœD˜D——Kšžœ‘˜—Mšžœžœžœžœ˜#KšœP˜PKšžœžœ/˜KKšžœ‘ ˜—š’ œž˜'Kšœžœ$žœžœ™>Kšœ*˜*Kšžœ‘ ˜——™š ’œžœžœžœž˜AKšœt™tKšœ žœ˜Kšœ˜Kšœ žœ˜%Mš žœžœžœžœ‘˜;Kšžœžœžœžœ˜#M™Kšœ=˜=šžœžœžœž˜.Kšœžœžœ˜$š žœ žœžœ žœž˜IKšœ*˜*—šžœžœ žœž˜*Kšœ)˜)—Jšžœ˜—M™Kšœ8˜8KšœG˜Gšžœžœžœž˜.Kšœžœžœ˜$š žœ žœžœ žœž˜IKšœ3˜3—šžœžœ žœž˜*Kšœ2˜2—Jšž˜—Kšžœ‘ ˜—š’ œžœžœž˜EK™OKšœžœ˜1Kšœ$žœ˜)šžœžœžœž˜"Kš œžœžœ$žœžœžœ˜sKšœ˜Kšž˜—šžœž˜ Kšœ8žœQ˜ŒKšžœžœ˜9Kšž˜—Kšžœ‘ ˜—š’ œž˜+Kš žœ žœžœžœžœ ˜5Kšžœ‘ ˜—š’ œž˜(Kš œžœ žœ žœžœžœžœ™DK™OKšœžœ žœžœ ˜(Kšœ?žœ˜DKšœ@žœ˜DKšžœ‘˜——™Lšœ7˜7KšœU˜UKšœ4˜4Kšœ6˜6LšœN˜NKšœE˜ELšœX˜XKšœ`˜`Kšœ=˜=—Lšžœ˜—…—'n<„