DrcCommandImpl.mesa
Copyright Ó 1987, 1988 by Xerox Corporation. All rights reserved.
Rewritten by gbb January 12, 1987 11:53:06 am PST
gbb January 22, 1988 10:18:32 am PST
Jean-Marc Frailong December 7, 1987 9:28:41 pm PST
Interface to ChipNDale.
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];
DrcCommandImpl: CEDAR PROGRAM
IMPORTS AMBridge, BasicTime, CD, CDBasics, CDCommandOps, CDDirectory, CDErrors, CDIO, CDOps, CDProperties, CDSequencer, CDValue, CDViewer, Commander, CommandTool, CoreClasses, CoreGeometry, CoreIO, CoreOps, CoreProperties, CoreView, CStitching, DesignRules, Drc, DrcCmosb, DrcDebug, ExtractOps, FS, IO, PrintTV, Process, Rope, RuntimeError, SimpleMailer, Sinix, SinixOps, SinixRawCMosB, TerminalIO, UserCredentials, UserProfile, ViewerOps
~ BEGIN OPEN DrcCmosb; 
ROPE: TYPE ~ Rope.ROPE;
tryRaw: BOOLFALSE; violationsInTopCell: BOOLFALSE;
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 BOOLNEW [BOOLFALSE];
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.nameBuildId [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 CARDINALNIL;
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 ANYNIL];
EnumerateCore: PROC [cell: Drc.CoreCell, action: EachCell, session: TimeStamp, data: REF ANYNIL, 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 ANYNIL]
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 ANYNIL]
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 ANYNIL]
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 ANYNIL]
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 ANYNIL]
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 BOOLNEW [BOOLFALSE];
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 [BOOLFALSE];
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 ANYNIL, msg: ROPENIL]
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 BOOLNEW [BOOLFALSE];
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 ANYNIL, msg: ROPENIL]
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 [BOOLFALSE];
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
END.
gbb May 1, 1987 4:26:11 pm PDT
Added check of cell name convention and automatic notification to Rick Barth of trepassers.
changes to: DIRECTORY, IMPORTS, ~, ExtractAndCheck (local of Execute), coreCell (local of ExtractAndCheck, local of Execute), RedoDrc, PrintCdFileName, Registrations
gbb May 13, 1987 4:35:30 pm PDT
Optimized back-annotation and error queries.
Key to used design rules is now stored into Core data structure and retrieved from there by the Redo command.
changes to: DIRECTORY, ~, ExtractAndCheck (local of Execute), coreCell (local of ExtractAndCheck, local of Execute), EnumerateCore, BackAnnotation, ListDRV (local of ListAll), RegressionTest, coreCell (local of RegressionTest), RedoDrc, RepealDrcFlags, PrintRuleKey, AtomReadWrapping, AtomWriteWrapping, Registrations
gbb May 21, 1987 4:23:31 pm PDT
Catching all uncaught signals and reporting them in a user-friendlier way,i.e., byting the implementor instead of the user.
changes to: DIRECTORY, IMPORTS, ~, Execute
gbb May 27, 1987 11:57:42 am PDT
Uses raw exrtract in all cases except minimal DRC.
changes to: DIRECTORY, IMPORTS, ExtractAndCheck (local of Execute)
gbb September 18, 1987 5:40:33 pm PDT
Added procedure to remove ChipNDale error rectangles from selected cells
changes to: RemoveCdErrors, List, Hack, Registrations
gbb October 26, 1987 1:44:30 pm PST
Date: 26 Oct 87 10:45:41 PST
From: Barth.pa
Subject: Bad Guy
To: Beretta
Reply-To: Barth
Extract.df has an interface, ExtractOps, which has a routine, IsSchematic which given an object decides if it is a schematic cell. The current heuristic is fairly stupid but please change Genista to use it so that these bad guy messages stop coming. We can improve the heuristic, e.g. by looking at the name, as people complain. You should probably emit a warning message on TerminalIO saying that the cell has not been checked.
  Rick
changes to: ~, ExtractAndCheck (local of Execute), DIRECTORY, IMPORTS, Reply, Rick
gbb January 20, 1988 6:54:04 pm PST
Annotate back all violations in the same cell.
changes to: ~, coreCell (local of ExtractAndCheck, local of Execute), BackAnnotation