<> <> <> <> <> 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]; 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 * pWellSurround: Rule ~ [5 * <> wellConflict: Rule ~ [2 * NinN: Rule ~ [2 * PinP: Rule ~ [2 * <> 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 <<[r: Rect, l: Layer, pr: DrawRef]>> 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 <<[r: Rect, l: Layer, pr: DrawRef]>> 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 <<[plane: REF Tesselation, rect: Rect, oldValue: REF, data: REF]>> 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 <<[plane: REF Tesselation, rect: Rect, oldValue: REF, data: REF]>> 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 <<[event: REF, design: CD.Design, x: REF] RETURNS [dont: BOOL _ FALSE]>> <> 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.