DIRECTORY
AMBridge USING [TVForSignal],
BasicTime USING [GMT, Now, Period],
CD USING [CreateDrawRef, Design, DrawProc, DrawRef, Instance, InstanceList, Layer, Number, Object, Technology],
CDBasics USING [Extend, MapRect],
CDCommandOps USING [DoWithResource, RegisterWithMenu],
CDDirectory USING [Fetch, Name],
CDErrors USING [IncludeMessage, RemoveMessages],
CDIO USING [ReadDesign],
CDOps USING [InstList, LayerRope, ToRope],
CDProperties USING [GetDesignProp, GetObjectProp, PutDesignProp, RegisterProperty],
CDSequencer USING [Command, ImplementCommand, UseAbortFlag],
CDValue USING [Fetch],
CDViewer USING [CreateViewer, ViewerList, ViewersOf],
Commander USING [CommandProc, Register],
CommandTool USING [NextArgument],
Core USING [Wire],
CoreClasses USING [recordCellClass, RecordCellType],
CoreGeometry USING [GetObject],
CoreIO USING [PropReadProc, PropWriteProc, ReadAtom, ReadRope, RegisterProperty, ReportSaveCellType, RestoreCellType, WriteAtom, WriteRope],
CoreOps USING [CopyWire, GetCellTypeName, GetShortWireName, PrintCellType, SetShortWireName],
CoreProperties USING [GetProp, propPrint, PropPrintProc, Props, PutProp, RegisterProperty, StoreProperties],
CoreView USING [debugViewer, DestroyView, GeometryView, StartIncrementalView, Viewer],
CStitching USING [DumpCache],
DesignRules USING [DesignRuleError, GetRuleSet, FetchRulesID, Rules],
Drc USING [CheckDesignRules, CoreCell, coreInconsistent, DRV, DRVkey, ErrorRect, Layout, Tech, Wire],
DrcCmosb USING [cMosBcompleteKey, cMosBsimpleKey, FlushTechCache, NewTechnology],
DrcDebug USING [debug, dLog],
ExtractOps USING [IsSchematic],
FS USING [ComponentPositions, Error, ExpandName],
IO USING [atom, card, GetID, int, PutF, PutF1, PutFR, PutFR1, RIS, ROS, rope, RopeFromROS, STREAM, time],
PrincOpsUtils USING [],
PrintTV USING [Print],
Process USING [priorityBackground, SetPriority],
Rope USING [Cat, Equal, IsEmpty, ROPE, Substr],
RuntimeError USING [UNCAUGHT],
SimpleMailer USING [SendMessage],
Sinix USING [Extract, Mode],
SinixOps USING [GetExtractMode],
SinixRawCMosB USING [mode],
TerminalIO USING [PutRope, PutRopes, PutF, PutF1],
UserCredentials USING [Get],
UserProfile USING [Boolean, CallWhenProfileChanges, ProfileChangedProc],
ViewerOps USING [SetNewVersion];
~
BEGIN
OPEN DrcCmosb;
ROPE: TYPE ~ Rope.ROPE;
tryRaw: BOOL ← FALSE; violationsInTopCell: BOOL ← FALSE;
timing: BOOL ← UserProfile.Boolean ["Genista.Timing", FALSE];
religion: BOOL ← UserProfile.Boolean ["Genista.EmulateSoS", FALSE];
failureReason: ROPE; failureTorch: REF ANY;
failureSignal: UNSAFE ERROR ANY RETURNS ANY;
Misc: TYPE ~ REF Stuff;
Stuff: TYPE ~ RECORD [design: CD.Design, geom: Drc.Layout, inst: CD.Instance ← NIL];
TimeStamp: TYPE ~ REF Titius;
Titius: TYPE ~ RECORD [caius: BasicTime.GMT];
regressionDesign: ROPE ← "[DATools]<DATools7.0>Saguaro>DragonRules.dale";
layoutViewer: CoreView.Viewer;
stateHandle: Misc ← NEW [Stuff ← [NIL, SinixOps.GetExtractMode[$cmosB].decoration, NIL]];
lastCore: Drc.CoreCell ← NIL;
lastKey: ATOM;
status: RECORD [errors: REF CARDINAL, start: BasicTime.GMT, currentCell: REF ROPE];
comesFromCdFile: ATOM ~ CoreProperties.RegisterProperty [$DrcComesFromCdFile];
ruleKey: ATOM ~ CoreProperties.RegisterProperty [$DrcRules];
sessionKey: ATOM ~ CoreProperties.RegisterProperty [$DrcEnumerationSession];
notMe: BOOL ~NOT UserCredentials.Get[].name.Equal ["Beretta.pa", FALSE];
neverEver: ERROR [signal: SIGNAL ANY RETURNS ANY] ~ CODE; -- a signal never ever raised
Execute:
PROC [comm: CDSequencer.Command] ~
BEGIN
Called by ChipNDale upon activation of the command.
ENABLE
BEGIN
Drc.coreInconsistent =>
BEGIN
failureReason ← reason; failureTorch ← torch;
GOTO failure
END;
neverEver
--RuntimeError.UNCAUGHT-- =>
BEGIN
TRUSTED {failureSignal ← LOOPHOLE [signal, SIGNAL ANY RETURNS ANY]};
GOTO alienFailure
END
END;
state: Misc ~ NEW [Stuff];
abort: REF BOOL ← NEW [BOOL ← FALSE];
ExtractAndCheck:
PROC [comm: CDSequencer.Command] ~
BEGIN
Protected procedure.
startTime1, startTime2, lapTime, stopTime: BasicTime.GMT;
usedRuleKey: ATOM ← DesignRules.FetchRulesID [state.design]; -- saved in Core
rules: DesignRules.Rules;
techE: Sinix.Mode ← SinixOps.GetExtractMode [state.design.technology];
techD: Drc.Tech;
violations: CARDINAL ← 0;
cDFileName: ROPE ~ NARROW [CDValue.Fetch [state.design, $CDxLastFile]];
coreFileName: ROPE;
state.design.name ← BuildId [state.design.name, cDFileName, "Design"];
coreFileName ← Rope.Cat ["[]<>Temp>DRC>PreGenista>", state.design.name];
IF (techE =
NIL)
THEN
BEGIN
TerminalIO.PutRope [Rope.Cat ["The technology ", state.design.technology.name, " is not implemented in Sinix or Drc.\n"]];
RETURN
END;
IF tryRaw THEN techE ← SinixRawCMosB.mode;
state.geom ← stateHandle.geom ← techE.decoration;
rules ← DesignRules.GetRuleSet [usedRuleKey ! DesignRules.DesignRuleError => CONTINUE];
IF (rules =
NIL)
THEN
BEGIN
TerminalIO.PutRope ["The design does not specify a set of design rules. Using VTI rule set.\n"];
usedRuleKey ← $vti;
rules ← DesignRules.GetRuleSet [usedRuleKey ! DesignRules.DesignRuleError => CONTINUE];
usedRuleKey ← $Vti;
IF (rules = NIL) THEN rules ← DesignRules.GetRuleSet [usedRuleKey ! DesignRules.DesignRuleError => CONTINUE];
usedRuleKey ← $VTI;
IF (rules = NIL) THEN rules ← DesignRules.GetRuleSet [usedRuleKey]
END;
techD ← DrcCmosb.NewTechnology [IF religion THEN cMosBsimpleKey ELSE cMosBcompleteKey, rules];
IF (comm.key = $DrcSelMinimal) THEN techD.verifyCell ← NIL;
FOR all:
CD.InstanceList ← CDOps.InstList [state.design], all.rest
WHILE all #
NIL
DO
IF all.first.selected
THEN
BEGIN
whatTheUserMeant: ROPE ← CDDirectory.Name [all.first.ob, state.design];
rickThinksItsSchematics: BOOL ~ ExtractOps.IsSchematic [state.design, all.first.ob];
pos: FS.ComponentPositions;
IF
NOT whatTheUserMeant.IsEmpty
THEN
BEGIN
[whatTheUserMeant, pos] ← FS.ExpandName [whatTheUserMeant ! FS.Error => GOTO illegalName];
whatTheUserMeant ← whatTheUserMeant.Substr [start: pos.ext.start, len: pos.ext.length];
EXITS
illegalName =>
BEGIN
TerminalIO.PutF ["\nThe name %g is illegal or a non-allowed pattern. Suggested replacement: %g.mask\n", IO.rope [whatTheUserMeant], IO.rope [BuildId [whatTheUserMeant, "Cell", "Cell"]]];
whatTheUserMeant ← NIL
END
END;
SELECT
TRUE
FROM
whatTheUserMeant.Equal ["mask", FALSE] => NULL; -- c'est bon
whatTheUserMeant.Equal ["sch",
FALSE], whatTheUserMeant.Equal ["icon",
FALSE] =>
BEGIN
TerminalIO.PutRope ["\nCells with extension <sch> and <icon> are ignored unless Rick thinks it is not schematics.\n"];
IF rickThinksItsSchematics THEN LOOP
END;
ENDCASE =>
BEGIN
start: ROPE ~ UserCredentials.Get[].name.Cat [" is a user out there, who has a design ", comm.design.name, " on file ", cDFileName];
extendedName: ROPE ~ CDOps.ToRope[all.first.ob].Cat[" (the user meant ", CDDirectory.Name [all.first.ob, state.design], ")"];
IF rickThinksItsSchematics
THEN
BEGIN
TerminalIO.PutF1 ["\nIn theory, cells without an extension are not allowed.\nIn this case, however, Rick thinks that %g is a schematics cell, so it is ignored.\n", IO.rope [extendedName]];
LOOP
END;
TerminalIO.PutF1 ["\nIn theory, cells without extension <mask> are not allowed.\nIn this case, however, Rick thinks that %g is not a schematics cell, so it is checked anyway.\n", IO.rope [extendedName]]
[] ← CDErrors.IncludeMessage [design: state.design, ob: all.first.ob, rect: CDBasics.MapRect [all.first.ob.bbox, all.first.trans], message: "Cells without extension <mask> are not allowed and not checked", owner: Drc.DRVkey];
IF notMe THEN [] ← SimpleMailer.SendMessage [from: "Genista", to: LIST ["Barth.PA"], subject: "Bad Guy", body: start.Cat [" which contains a cell named ", extendedName, ". This time I did not cut the wires on his backplane and I even checked his cell because Don was completely pissed off by having to rename cells before he can run a DRC on them. If you do not agree see Don Curry."]]
END;
TRUSTED {Process.SetPriority [Process.priorityBackground]};
startTime1 ← BasicTime.Now [];
WITH Sinix.
Extract [obj: all.first.ob, mode: techE].result
SELECT FROM
coreCell: Drc.CoreCell =>
BEGIN
v: REF CARDINAL ← NIL;
fakeActual: Drc.Wire ~ CoreOps.CopyWire [coreCell.public];
stamp: TimeStamp ← NEW [Titius];
lapTime ← BasicTime.Now [];
lastCore ← coreCell; lastKey ← techD.checkedBy;
coreCell.properties ← CoreProperties.PutProp [coreCell.properties, comesFromCdFile, cDFileName];
coreCell.properties ← CoreProperties.PutProp [coreCell.properties, ruleKey, usedRuleKey];
IF (comm.key # $DrcSel)
THEN
BEGIN
If the user does a full check, it is likely he is doing a set af many small cells, so do not bother saving them.
compositeName: ROPE ~ coreFileName.Cat ["-", BuildId [CDDirectory.Name [all.first.ob, state.design], CDOps.ToRope [all.first.ob], "Cell"], ".Core"];
[] ← CoreIO.ReportSaveCellType [cellType: coreCell, fileName: compositeName];
TerminalIO.PutF ["\nExtraction saved on %g\n", IO.rope [compositeName]]
END;
FOR i:
NAT
IN [0 .. fakeActual.size)
DO
givenName: ROPE ~ CoreOps.GetShortWireName [fakeActual[i]];
fakeActual[i] ← CoreOps.SetShortWireName [fakeActual[i], IF givenName.IsEmpty THEN IO.PutFR1 ["External", IO.int [i]] ELSE givenName]
ENDLOOP;
IF DrcDebug.debug
THEN
BEGIN
IF (layoutViewer # NIL) THEN CoreView.DestroyView [layoutViewer];
IF (CoreView.debugViewer # NIL) THEN CoreView.DestroyView [CoreView.debugViewer];
layoutViewer ← CoreView.GeometryView [coreCell, techE.decoration, abort];
CoreView.debugViewer ← CoreView.StartIncrementalView [coreCell, techE.decoration, abort]
END;
CDProperties.PutDesignProp [state.design, $DrcCoreCircularity]; -- remove
IF DrcDebug.debug
THEN
BEGIN
CoreOps.PrintCellType [coreCell, DrcDebug.dLog];
DrcDebug.dLog.PutF ["\n"];
END;
status.errors ← NEW [CARDINAL ← 0]; status.currentCell ← NEW [ROPE];
status.start ← startTime2 ← BasicTime.Now[];
violations ← Drc.CheckDesignRules [cell: coreCell,
external: fakeActual,
viaFlatness: (comm.key = $DrcSel),
tech: techD,
stopFlag: abort,
lap: status.errors,
currentCell: status.currentCell,
layout: state.geom];
stopTime ← BasicTime.Now [];
IF timing THEN TerminalIO.PutF [
format: "\nNumber of new design violations found: %l%g%l\n",
v1: IO.rope ["b"],
v2: IO.card [violations],
v3: IO.rope ["B"]];
IF DrcDebug.debug THEN VerifyObjects [state.design, all.first.ob];
IF timing
THEN
BEGIN
TerminalIO.PutF1 ["\nElapsed time for extraction: %g",
IO.rope [TimeToRope [startTime1, lapTime]]];
TerminalIO.PutF1 ["\nElapsed time for DRC: %g",
IO.rope [TimeToRope [startTime2, stopTime]]];
TerminalIO.PutF1 ["\nTotal elapsed time: %g\n",
IO.rope [TimeToRope [startTime1, stopTime]]]
END;
IF (violations > 0) THEN v ← NEW [CARDINAL ← violations];
CDProperties.PutDesignProp [state.design, $DrcNr, v];
CDProperties.PutDesignProp [state.design, $DrcCoreCircularity, coreCell]; -- a circularity, but I do not have a better idea at the moment
CStitching.DumpCache [];
stamp.caius ← BasicTime.Now [];
IF (violations > 0)
THEN
BEGIN
Do it only if new errors are found. You might object with that and are welcome to change it.
FOR vl: CDViewer.ViewerList ← CDViewer.ViewersOf [state.design], vl.rest
WHILE vl #
NIL
DO
ViewerOps.SetNewVersion [vl.first]
ENDLOOP
END;
state.inst ← all.first;
IF violationsInTopCell
THEN
CDErrors.RemoveMessages [design: state.design,
ob: state.inst.ob,
owner: Drc.DRVkey];
EnumerateCore [coreCell, BackAnnotation, stamp, state, abort];
status.errors ← NIL; status.currentCell ← NIL
END;
w: Core.Wire => ERROR;
ENDCASE => NULL -- e.g., cell contains text or schematics
END -- if selected
ENDLOOP
END; -- ExtractAndCheck
TerminalIO.PutF1 ["DRC (Genista). %g\n", IO.rope [SELECT comm.key FROM
$DrcSel => "Verify all rules.",
$DrcSelVia => "Do not verify via flatness rules.",
$DrcSelMinimal => "Do not verify via flatness nor well rules.",
ENDCASE => "There is an implementation error"]];
state.design ← comm.design;
CDSequencer.UseAbortFlag [state.design, abort];
[] ← CDCommandOps.DoWithResource [ExtractAndCheck, comm, $Drc];
TerminalIO.PutRope ["Drc done.\n"];
EXITS
failure =>
BEGIN
TerminalIO.PutRopes [failureReason, ". Core structure inconsistent. DRC aborted.\n"]
END;
alienFailure =>
TRUSTED
BEGIN
msg: ROPE;
ros: IO.STREAM ~ IO.ROS [];
lastCore.properties ← CoreProperties.PutProp [lastCore.properties, lastKey, NIL];
PrintTV.Print [tv: AMBridge.TVForSignal [failureSignal], put: ros, verbose: TRUE];
msg ← ros.RopeFromROS [];
TerminalIO.PutRopes [msg, "\n\t*** Session miscarried ***\n"];
IF notMe THEN [] ← SimpleMailer.SendMessage [from: "Genista", to: LIST ["Beretta.PA"], subject: "Crash", body: msg]
ELSE ERROR
END
END; -- Execute
EachCell: TYPE ~ PROC [cell: Drc.CoreCell, data: REF ANY ← NIL];
EnumerateCore:
PROC [cell: Drc.CoreCell, action: EachCell, session: TimeStamp, data:
REF
ANY ←
NIL, stopFlag:
REF
BOOL] ~
BEGIN
Enumerates the cell and does action on each subcell. If session ` NIL a cell is visited only once, otherwise it is visited on every instance.
IF (session #
NIL)
THEN
BEGIN
visited: TimeStamp ~ NARROW [CoreProperties.GetProp [cell.properties, sessionKey], TimeStamp];
IF (visited =
NIL)
OR (session.caius # visited.caius)
THEN
cell.properties ← CoreProperties.PutProp [cell.properties, sessionKey, session]
ELSE RETURN
END;
SELECT cell.class
FROM
CoreClasses.recordCellClass =>
BEGIN
cellData: CoreClasses.RecordCellType ~ NARROW [cell.data];
FOR sub:
NAT
IN [0 .. cellData.size)
DO
IF stopFlag^ THEN ERROR ABORTED;
EnumerateCore [cellData.instances[sub].type, action, session, data, stopFlag]
ENDLOOP;
action [cell, data]
END;
ENDCASE => NULL
END; -- EnumerateCore
BackAnnotation: EachCell ~
BEGIN
[cell: Drc.CoreCell, data: REF ANY ← NIL]
Annotates the ChipNDale design with the design rule violations.
state: Misc ~ NARROW [data];
cdCell: CD.Object ~ CoreGeometry.GetObject [state.geom, cell];
drv: Drc.DRV ~ NARROW [CoreProperties.GetProp [cell.properties, Drc.DRVkey]];
IF
NOT violationsInTopCell
THEN
CDErrors.RemoveMessages [design: state.design, ob: cdCell, owner: Drc.DRVkey];
IF (drv #
NIL)
THEN
FOR v:
LIST
OF Drc.ErrorRect ← drv.places, v.rest
WHILE v #
NIL
DO
IF violationsInTopCell
THEN
[] ← CDErrors.IncludeMessage [design: state.design, ob: state.inst.ob, rect: CDBasics.MapRect [CDBasics.Extend [v.first.r, 4], state.inst.trans], message: v.first.msg, owner: Drc.DRVkey]
ELSE
[] ← CDErrors.IncludeMessage [design: state.design, ob: cdCell, rect: CDBasics.Extend [v.first.r, 4], message: v.first.msg, owner: Drc.DRVkey]
ENDLOOP
END; -- BackAnnotation
ProblemMessage: EachCell ~
BEGIN
[cell: Drc.CoreCell, data: REF ANY ← NIL]
Asserts that correct cells are not flagged for violations
state: Misc ~ NARROW [data];
cdCell: CD.Object ~ CoreGeometry.GetObject [state.geom, cell];
IF (CoreProperties.GetProp [cell.properties, Drc.DRVkey] #
NIL)
THEN
BEGIN
TerminalIO.PutRopes [CDDirectory.Name [cdCell, state.design], " is not verified correctly ("];
TerminalIO.PutRopes [NARROW [CDProperties.GetObjectProp [cdCell, $rule], ROPE], ")\n"]
END
END; -- ProblemMessage
UncheckedMessage: EachCell ~
BEGIN
[cell: Drc.CoreCell, data: REF ANY ← NIL]
Asserts that correct cells are not flagged for violations
state: Misc ~ NARROW [data];
cdCell: CD.Object ~ CoreGeometry.GetObject [state.geom, cell];
drv: Drc.DRV ~ NARROW [CoreProperties.GetProp [cell.properties, Drc.DRVkey]];
IF (drv =
NIL)
OR (drv.count # 1)
THEN
BEGIN
description: ROPE ~ NARROW [CDProperties.GetObjectProp [cdCell, $rule]];
flat: BOOL ~ (CDProperties.GetObjectProp [cdCell, $flat] # NIL);
IF flat THEN TerminalIO.PutF ["%g is verified flat (%g)\n", IO.rope [CDDirectory.Name [cdCell, state.design]], IO.rope [description]]
ELSE TerminalIO.PutF ["%g is not verified correctly (%g)\n", IO.rope [CDDirectory.Name [cdCell, state.design]], IO.rope [description]]
END
END; -- UncheckedMessage
Repeal: EachCell ~
BEGIN
[cell: Drc.CoreCell, data: REF ANY ← NIL]
cell.properties ← CoreProperties.PutProp [cell.properties, lastKey];
cell.properties ← CoreProperties.PutProp [cell.properties, Drc.DRVkey]
END; -- Repeal
RemoveCdErrors:
PROC [comm: CDSequencer.Command] ~
BEGIN
Called by ChipNDale upon activation of the command.
TerminalIO.PutRope ["Removing Genista's error rectangles from selected cells.\n"];
FOR all:
CD.InstanceList ← CDOps.InstList [comm.design], all.rest
WHILE all #
NIL
DO
IF all.first.selected
THEN
CDErrors.RemoveMessages [design: comm.design, ob: all.first.ob, owner: Drc.DRVkey]
ENDLOOP
END; -- RemoveCdErrors
List:
PROC [comm: CDSequencer.Command] ~
BEGIN
Called by ChipNDale upon activation of the command.
violations: REF CARDINAL ~ NARROW [CDProperties.GetDesignProp [comm.design, $DrcNr]];
IF (violations = NIL) THEN TerminalIO.PutRope ["No new violations found last time.\n"]
ELSE TerminalIO.PutF1 ["Number of design rule violations found last time: %g\n", IO.card[violations^]];
END; -- List
PrintDRV: EachCell ~
BEGIN
[cell: Drc.CoreCell, data: REF ANY ← NIL]
drv: Drc.DRV ~ NARROW [CoreProperties.GetProp [cell.properties, Drc.DRVkey]];
IF (drv #
NIL)
THEN
BEGIN
cellName: ROPE ~ CoreOps.GetCellTypeName [cell];
l: CD.Number ~ NARROW [data, CD.Technology].lambda;
TerminalIO.PutF ["\ncell %g, %g violations:\n", IO.rope [cellName], IO.int [drv.count]];
FOR e:
LIST
OF Drc.ErrorRect ← drv.places, e.rest
WHILE e #
NIL
DO
TerminalIO.PutF ["%g at [(%g, %g); (%g, %g)] \n", IO.rope [e.first.msg], IO.int [e.first.r.x1/l], IO.int [e.first.r.y1/l], IO.int [e.first.r.x2/l], IO.int [e.first.r.y2/l]]
ENDLOOP
END
END; -- PrintDRV
ListAll:
PROC [comm: CDSequencer.Command] ~
BEGIN
Called by ChipNDale upon activation of the command.
coreCell: Drc.CoreCell ~ NARROW [CDProperties.GetDesignProp [comm.design, $DrcCoreCircularity]];
abort: REF BOOL ← NEW [BOOL ← FALSE];
stamp: TimeStamp ← NEW [Titius];
ListDRV:
PROC [comm: CDSequencer.Command] ~
BEGIN
Protected procedure.
EnumerateCore [coreCell, PrintDRV, stamp, comm.design.technology, abort]
END; -- ListDRV
TerminalIO.PutRope ["Design rule violations stored in Core:\n"];
CDSequencer.UseAbortFlag [comm.design, abort];
stamp.caius ← BasicTime.Now [];
IF (coreCell = NIL) THEN TerminalIO.PutRope ["None recorded.\n"]
ELSE [] ← CDCommandOps.DoWithResource [ListDRV, comm, $Drc]
END; -- ListAll
RegressionTest:
PROC ~
BEGIN
Makes a DRC run over the test file to assess the correctness of the implementation. The test file is not ready as yet.
state: Misc ~ NEW [Stuff];
dummy: REF BOOL ~ NEW [BOOL ← FALSE];
test: CD.Design ~ CDIO.ReadDesign [regressionDesign];
usedRuleKey: ATOM; rules: DesignRules.Rules;
techE: Sinix.Mode; techD: Drc.Tech;
ok, ko: CD.Object;
IF (test = NIL) THEN GOTO maintenanceProblem;
techE ← SinixOps.GetExtractMode [test.technology];
usedRuleKey ← DesignRules.FetchRulesID [test];
IF (usedRuleKey = NIL) THEN usedRuleKey ← $Dragon;
rules ← DesignRules.GetRuleSet [usedRuleKey];
techD ← DrcCmosb.NewTechnology [IF religion THEN cMosBsimpleKey ELSE cMosBcompleteKey, rules];
IF (techD = NIL) THEN GOTO maintenanceProblem;
state.geom ← techE.decoration;
ok ← CDDirectory.Fetch [test, "ok.mask"].object;
IF (ok = NIL) THEN GOTO maintenanceProblem;
TerminalIO.PutRope ["\n"];
WITH Sinix.Extract [obj: ok, mode: techE].result
SELECT
FROM
coreCell: Drc.CoreCell =>
BEGIN
status.errors ← NEW [CARDINAL ← 0]; status.start ← BasicTime.Now [];
status.currentCell ← NEW [ROPE];
IF (Drc.CheckDesignRules [cell: coreCell, tech: techD, viaFlatness: TRUE, external: coreCell.public, stopFlag: dummy, lap: status.errors, currentCell: status.currentCell, layout: state.geom] > 0) THEN EnumerateCore [coreCell, ProblemMessage, NIL, state, dummy]
END;
ENDCASE => ERROR;
TerminalIO.PutRope ["\n"];
ko ← CDDirectory.Fetch [test, "ko.mask"].object;
IF (ko = NIL) THEN GOTO maintenanceProblem;
WITH Sinix.Extract [obj: ko, mode: techE].result
SELECT
FROM
coreCell: Drc.CoreCell =>
BEGIN
status.errors ← NEW [CARDINAL ← 0]; status.start ← BasicTime.Now [];
status.currentCell ← NEW [ROPE];
[] ← Drc.CheckDesignRules [cell: coreCell, tech: techD, viaFlatness: TRUE, external: coreCell.public, stopFlag: dummy, lap: status.errors, currentCell: status.currentCell, layout: state.geom];
EnumerateCore [coreCell, UncheckedMessage, NIL, state, dummy]
END;
ENDCASE => ERROR;
status.errors ← NIL; status.currentCell ← NIL;
EXITS
maintenanceProblem =>
BEGIN
TerminalIO.PutRope ["Please inform DRC maintainers that the self verification is broken.\n"]
END
END; -- RegressionTest
VerifyRect:
CD.DrawProc ~
BEGIN
[pr: CD.DrawRef, ob: CD.Object, trans: CD.Transformation←[], readOnlyInstProps: CD.PropList←NIL]
specialLayers: CD.Layer = 5; -- combined, highLightShade, highLightError, pinRepresentation
lambda: CD.Number ~ pr.design.technology.lambda;
IF (ob.class.objectType = $Rect)
AND (ob.layer >= specialLayers)
AND (CDProperties.GetObjectProp [ob, $DrcTrace] =
NIL)
THEN
DrcDebug.dLog.PutF [format: "Failed to check rectangle at [%g, %g] %l %g%l\n",
v1: IO.int [trans.off.x / lambda],
v2: IO.int [trans.off.y / lambda],
v3: IO.rope ["b"],
v4: IO.rope [CDOps.LayerRope[ob.layer]],
v5: IO.rope ["B"]]
END; -- VerifyRect
VerifyObjects:
PROC [design:
CD.Design, obj:
CD.Object] ~
BEGIN
Traverses the cell and reports undiscovered rectangles.
drawRef: CD.DrawRef ← CD.CreateDrawRef [[design: design]];
drawRef.drawChild ← VerifyRect;
obj.class.drawMe [drawRef, obj]
END; -- VerifyObjects
EmulateSoS: UserProfile.ProfileChangedProc ~
BEGIN
religion ← UserProfile.Boolean ["Genista.EmulateSoS", FALSE]
END; -- EmulateSoS
Timing: UserProfile.ProfileChangedProc ~
BEGIN
timing ← UserProfile.Boolean ["Genista.Timing", FALSE]
END; -- Timing
RedoDrc: Commander.CommandProc ~
BEGIN
[cmd: Commander.Handle] RETURNS [result: REF ANY ← NIL, msg: ROPE ← NIL]
fileName: ROPE ~ CommandTool.NextArgument [cmd];
usedRules: ATOM;
IF fileName.IsEmpty THEN RETURN [$Failure, "Please specify a full path file name, such as []<>Temp>DRC>PreGenista>designName"];
lastCore ← CoreIO.RestoreCellType [fileName];
IF (lastCore = NIL) THEN RETURN [$Failure, "There is no Core data structure with this name (specify a full name, like []<>Temp>DRC>PreGenista>designName)"];
usedRules ← NARROW [CoreProperties.GetProp [lastCore.properties, ruleKey], ATOM];
IF (usedRules = NIL) THEN RETURN [$Failure, "The Core data structure does not specify a design rule set."];
BEGIN
violations: CARDINAL ← 0;
rules: DesignRules.Rules ← DesignRules.GetRuleSet [usedRules];
fakeActual: Drc.Wire ~ CoreOps.CopyWire [lastCore.public];
techD: Drc.Tech ← DrcCmosb.NewTechnology [cMosBcompleteKey, rules];
startTime: BasicTime.GMT;
cDFileName: ROPE ~ NARROW [CoreProperties.GetProp [lastCore.properties, comesFromCdFile]];
IF
NOT (CommandTool.NextArgument[cmd].Equal ["wells",
FALSE])
THEN
techD.verifyCell ← NIL;
lastCore ← lastCore.class.recast [lastCore];
FOR i:
NAT
IN [0 .. fakeActual.size)
DO
givenName: ROPE ~ CoreOps.GetShortWireName [fakeActual[i]];
fakeActual[i] ← CoreOps.SetShortWireName [fakeActual[i], IF givenName.IsEmpty THEN IO.PutFR1 ["External", IO.int [i]] ELSE givenName]
ENDLOOP;
status.errors ← NEW [CARDINAL ← 0]; status.start ← startTime ← BasicTime.Now [];
status.currentCell ← NEW [ROPE];
[] ← Drc.CheckDesignRules [cell: lastCore, external: fakeActual, tech: techD, layout: stateHandle.geom, stopFlag: NIL, lap: status.errors, currentCell: status.currentCell];
msg ← Rope.Cat ["Elapsed time for DRC: ", TimeToRope [startTime, BasicTime.Now []]];
CStitching.DumpCache [];
IF
NOT cDFileName.IsEmpty
THEN
BEGIN
abort: REF BOOL ← NEW [BOOL ← FALSE];
stateHandle.design ← CDIO.ReadDesign [cDFileName];
IF (stateHandle.design #
NIL)
THEN
BEGIN
stamp: TimeStamp ← NEW [Titius];
stamp.caius ← BasicTime.Now [];
EnumerateCore [lastCore, BackAnnotation, stamp, stateHandle, abort];
[] ← CDViewer.CreateViewer [design: stateHandle.design]
END
END;
status.errors ← NIL; status.currentCell ← NIL;
END
END; -- RedoDrc
Hack:
PROC ~
BEGIN
Having a menu entry is a privilege that is not easily received.
CDCommandOps.RegisterWithMenu [menu: $DRCMenu, entry: "Small input DRC (Genista)", key: $DrcSel, proc: Execute, queue: doQueue];
CDCommandOps.RegisterWithMenu [menu: $DRCMenu, entry: "Large input DRC (Genista)", key: $DrcSelVia, proc: Execute, queue: doQueue];
CDCommandOps.RegisterWithMenu [menu: $DRCMenu, entry: "Minimal DRC (Genista)", key: $DrcSelMinimal, proc: Execute, queue: doQueue];
CDCommandOps.RegisterWithMenu [menu: $DRCMenu, entry: "List violations (Genista)", key: $DrcAll, proc: ListAll, queue: doQueue];
CDCommandOps.RegisterWithMenu [menu: $DRCMenu, entry: "Violation count (Genista)", key: $DrcDir, proc: List, queue: doQueue];
CDCommandOps.RegisterWithMenu [menu: $DRCMenu, entry: "Remove error rects (Genista)", key: $DrcRemove, proc: RemoveCdErrors, queue: doQueue]
CDSequencer.ImplementCommand [key: $GismoVFSel, proc: Execute, queue: doQueue];
CDSequencer.ImplementCommand [key: $WellContactsCheck, proc: List, queue: doQueue];
CDSequencer.ImplementCommand [key: $GismoDIWSel, proc: ListAll, queue: doQueue];
TerminalIO.PutRope ["Genista: DRC via ViaFlatness; errors via DiffInWell. Do not Install Gismos !\n"]
END; -- Hack
StatusReport: Commander.CommandProc ~
BEGIN
[cmd: Commander.Handle] RETURNS [result: REF ANY ← NIL, msg: ROPE ← NIL]
IF (status.errors = NIL) THEN msg ← "Drc is idle."
ELSE
BEGIN
msg ← IO.PutFR ["Last drc started %g\nelapsed time: %g,\nworking on: %g\nproblems found so far: %g.",
IO.time [status.start],
IO.rope [TimeToRope [status.start, BasicTime.Now[]]],
IO.rope [status.currentCell^],
IO.card [status.errors^]]
END
END; -- StatusReport
RepealDrcFlags: Commander.CommandProc ~
BEGIN
[cmd: Commander.Handle] RETURNS [result: REF ANY ← NIL, msg: ROPE ← NIL]
IF (lastCore = NIL) THEN msg ← "There is no Core data structure"
ELSE
BEGIN
abort: REF BOOL ~ NEW [BOOL ← FALSE];
EnumerateCore [lastCore, Repeal, NIL, , abort];
msg ← "Design rule violations stored in Core repealed"
END
END; -- RepealDrcFlags
BuildId:
PROC [pretendent, alternative, ifAllFails:
ROPE]
RETURNS [id:
ROPE] ~
BEGIN
Build an old fashioned hansome name.
ifAllFails ← IO.GetID [IO.RIS [ifAllFails] ! RuntimeError.UNCAUGHT =>
{ifAllFails ← "Foo"; CONTINUE}];
alternative ← IO.GetID [IO.RIS [alternative] ! RuntimeError.UNCAUGHT =>
{alternative ← ifAllFails; CONTINUE}];
id ← IO.GetID [IO.RIS [pretendent] ! RuntimeError.UNCAUGHT =>
{id ← IO.GetID [IO.RIS [UserCredentials.Get[].name]].Cat ["-", alternative]; CONTINUE}]
END; -- BuildId
TimeToRope:
PROC [from, to: BasicTime.
GMT]
RETURNS [time:
ROPE] ~
BEGIN
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.
TwoPosInt:
PROC [i:
INT]
RETURNS [
ROPE] ~
BEGIN
RETURN [SELECT i FROM
= 0 => "00",
< 10 => Rope.Cat ["0", IO.PutFR1 [value: IO.int [i]]],
ENDCASE => IO.PutFR1 [value: IO.int [i]]]
END;
sec: INT ← BasicTime.Period [from, to];
min: INT ← sec / 60; h: INT ~ min / 60;
min ← min MOD 60; sec ← sec MOD 60;
RETURN [TwoPosInt[h].Cat [":", TwoPosInt[min], ":", TwoPosInt[sec]]]
END; -- TimeToRope
PrintCdFileName: CoreProperties.PropPrintProc ~
BEGIN
to.PutF1 [format: "Cell extracted from %g. ", value: IO.rope [NARROW[val,ROPE]]]
END; -- PrintCdFileName
RopeReadWrapping: CoreIO.PropReadProc ~
BEGIN
RETURN [CoreIO.ReadRope [h]]
END; -- RopeReadWrapping
RopeWriteWrapping: CoreIO.PropWriteProc ~
BEGIN
CoreIO.WriteRope [h, NARROW [value, ROPE]]
END; -- RopeWriteWrapping
PrintRuleKey: CoreProperties.PropPrintProc ~
BEGIN
to.PutF1 [format: "Design rules: %g. ", value: IO.atom [NARROW[val,ATOM]]]
END; -- PrintRuleKey
AtomReadWrapping: CoreIO.PropReadProc ~
BEGIN
RETURN [CoreIO.ReadAtom [h]]
END; -- AtomReadWrapping
AtomWriteWrapping: CoreIO.PropWriteProc ~
BEGIN
CoreIO.WriteAtom [h, NARROW [value, ATOM]]
END; -- AtomWriteWrapping
Registrations:
PROC ~
BEGIN
IF NOT CDProperties.RegisterProperty [$DrcNr, $gbb] THEN DrcCmosb.FlushTechCache;
[] ← CDProperties.RegisterProperty [$DrcCoreCircularity, $gbb];
CoreProperties.StoreProperties [prop: comesFromCdFile, properties: CoreProperties.Props [[CoreProperties.propPrint, NEW [CoreProperties.PropPrintProc ← PrintCdFileName]]]];
[] ← CoreIO.RegisterProperty [prop: comesFromCdFile, write: RopeWriteWrapping, read: RopeReadWrapping];
CoreProperties.StoreProperties [prop: ruleKey, properties: CoreProperties.Props [[CoreProperties.propPrint, NEW [CoreProperties.PropPrintProc ← PrintRuleKey]]]];
[] ← CoreIO.RegisterProperty [prop: ruleKey, write: AtomWriteWrapping, read: AtomReadWrapping];
CDSequencer.ImplementCommand [key: $DrcSel, proc: Execute, queue: doQueue];
CDSequencer.ImplementCommand [key: $DrcSelVia, proc: Execute, queue: doQueue];
CDSequencer.ImplementCommand [key: $DrcSelMinimal, proc: Execute, queue: doQueue];
CDSequencer.ImplementCommand [key: $DrcAll, proc: ListAll, queue: doQueue];
CDSequencer.ImplementCommand [key: $DrcDir, proc: List, queue: doQueue];
CDSequencer.ImplementCommand [key: $DrcRemove, proc: RemoveCdErrors, queue: doQueue];
Commander.Register [key: "DrcRepeal", proc: RepealDrcFlags, doc: "undoes last DRC by Genista"];
Commander.Register [key: "DrcEmpty", proc: RepealDrcFlags, doc: "undoes last DRC by Genista"];
Commander.Register [key: "DrcRedo", proc: RedoDrc, doc: "runs Genista on a Core file. Typical file names are of the form []<>Temp>DRC>PreGenista>designName"];
Commander.Register [key: "DrcCdCmosB", proc: RedoDrc, doc: "runs Genista on a Core file. Typical file names are of the form []<>Temp>DRC>PreGenista>designName"];
Commander.Register [key: "DrcStatus", proc: StatusReport, doc: "reports the current status of the drc"];
UserProfile.CallWhenProfileChanges [EmulateSoS];
UserProfile.CallWhenProfileChanges [Timing]
END; -- Registrations
Registrations;
IF DrcDebug.debug THEN Hack;
TerminalIO.PutRope ["DRC package Genista installed.\n"];
IF UserProfile.Boolean ["Genista.RegressionTest", FALSE] THEN RegressionTest