<> <> <> <> <> DIRECTORY BasicTime USING [GMT, Now, Period], CD USING [CreateDrawRef, Design, DrawProc, DrawRectProc, DrawRef, Instance, InstanceList, Layer, LayerKey, Number, Object, ObjectClass, Rect, Technology], CDBasics USING [Extend, NonEmpty], CDCommandOps USING [DoWithResource], CDErrors USING [IncludeMessage, RemoveMessages], CDEvents USING [EventProc, RegisterEventProc], CDOps USING [ToRope, InstList], CDProperties USING [CopyVal, GetObjectProp, InstallProcs, PutObjectProp, RegisterProperty], CDSequencer USING [Command, ImplementCommand, UseAbortFlag], CMosB USING [cmosB, lambda, ndif, nwell, nwellCont, pdif, pwell, pwellCont], CStitching USING [ChangeRect, DumpCache, Rect, ResetTesselation, ChangeEnumerateArea, ListArea, NewTesselation, RectProc, Region, Tesselation, Tile], CSMonitor USING [Monitor, PaintPredicate, Reset], DiffInWell USING [ErrorList, Rule], 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], ViewerClasses USING [Viewer]; DiffInWellImpl: CEDAR PROGRAM IMPORTS BasicTime, CD, CDBasics, CDCommandOps, CDErrors, CDEvents, CDOps, CDProperties, CDSequencer, CMosB, CSMonitor, CStitching, FS, 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, errorLog: IO.STREAM]; 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 * nWellContact: Rule ~ [4 * pWellContact: Rule ~ [4 * <> 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; designName: Rope.ROPE = IF d#NIL THEN d.name ELSE "in the sky"; 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>DiffInWell.log", accessOptions: create, keep: 5, extendFileProc: NIL, remoteCheck: FALSE, wDir: NIL]; -- keep is 5 because of incremental use state.errorLog.PutF1 ["Error log by DiffInWell. Design: %g\n\n", IO.rope [designName]]; 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]; 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.ToRope[all.first.ob], Verify [all.first, comm.design, abort].errorTotal], errorSummary]; TerminalIO.PutRope ["."] END ENDLOOP END; -- VerifySelected TerminalIO.PutRope ["Checking well surround.\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:\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 ["Well surround 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 <> 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) OR (l = CMosB.pwellCont) OR (l = CMosB.nwellCont) 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 [dr, inst.ob, inst.trans] 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]; CStitching.DumpCache []; state.wellTess _ NIL 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 <> Inquire: PROC [r: CD.Rect, layer: CD.Layer, state: State] = BEGIN <> bloatedRect: CD.Rect; wells: Region; ispDiff: BOOL ~ (layer = CMosB.pdif); isnDiff: BOOL ~ (layer = CMosB.ndif); ispCont: BOOL ~ (layer = CMosB.nwellCont); isnCont: BOOL ~ (layer = CMosB.pwellCont); isP: BOOL ~ (ispDiff OR ispCont); isN: BOOL ~ (isnDiff OR isnCont); IF NOT CDBasics.NonEmpty[r] THEN RETURN; -- empty rectangle IF state.abort^ THEN ERROR ABORTED; <> wells _ state.wellTess.ListArea [rect: r, skip: nothing]; FOR w: Region _ wells, w.rest WHILE w # NIL DO well: ATOM _ NARROW [w.first.value]; IF (isP AND (well = fieldOxide)) OR (isP AND (well = pWell)) THEN FlagViolation [PinP, w.first.rect, state]; IF (isN AND (well = nWell)) THEN FlagViolation [NinN, w.first.rect, state] ENDLOOP; <> IF (ispDiff OR isnDiff) THEN BEGIN bloatedRect _ CDBasics.Extend [r, nWellSurround.extent]; wells _ state.wellTess.ListArea [rect: bloatedRect, skip: nothing]; 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 (isnDiff AND (well = nWell)) THEN FlagViolation [pWellSurround, w.first.rect, state] ENDLOOP END ELSE BEGIN -- is contact bloatedRect _ CDBasics.Extend [r, nWellContact.extent]; wells _ state.wellTess.ListArea [rect: bloatedRect, skip: nothing]; FOR w: Region _ wells, w.rest WHILE w # NIL DO well: ATOM _ NARROW [w.first.value]; IF (ispCont AND (well = fieldOxide)) OR (ispCont AND (well = pWell)) THEN FlagViolation [nWellContact, w.first.rect, state]; IF (isnCont AND (well = nWell)) THEN FlagViolation [pWellContact, w.first.rect, state] ENDLOOP END END; -- Inquire 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 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, procs: [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]; <> TerminalIO.PutRope ["Diffusion in well checker loaded.\n"]; END. <> <> <> <> <> <> <> <> <<>>