DIRECTORY
BasicTime USING [GMT, Now, Period],
CD USING [CreateDrawRef, Design, DrawProc, DrawRef, Instance, InstanceList, Layer, Number, Object, Technology],
CDBasics USING [Extend],
CDCommandOps USING [DoWithResource],
CDDirectory USING [Fetch],
CDErrors USING [IncludeMessage, RemoveMessages],
CDInstances USING [NewInst],
CDIO USING [ReadDesign],
CDOps USING [InstList, LayerRope, ObjectRope],
CDProperties USING [GetDesignProp, GetObjectProp, PutDesignProp, RegisterProperty],
CDSequencer USING [Command, ImplementCommand, UseAbortFlag],
Core USING [Wire],
CoreClasses USING [recordCellClass, RecordCellType],
CoreGeometry USING [GetObject],
CoreOps USING [CopyWire, GetCellTypeName, GetShortWireName, PrintCellType, SetShortWireName],
CoreProperties USING [GetProp],
CoreView USING [debugViewer, DestroyView, GeometryView, StartIncrementalView, Viewer],
CStitching USING [DumpCache],
Drc USING [CheckDesignRules, CoreCell, coreInconsistent, DRV, DRVkey, ErrorRect, Layout, Wire],
DrcCMOSB USING [cMosBcomplete, cMosBsimple],
DrcDebug USING [debug, dLog],
IO USING [card, int, PutF, PutFR1, rope],
PrincOpsUtils USING [],
Process USING [priorityBackground, SetPriority],
Rope USING [Cat, IsEmpty, ROPE],
Sinix USING [Extract, Mode],
SinixOps USING [GetExtractMode],
TerminalIO USING [PutRope, PutRopes, PutF, PutF1],
UserProfile USING [Boolean, CallWhenProfileChanges, ProfileChangedProc];
~
BEGIN
OPEN DrcCMOSB;
ROPE: TYPE ~ Rope.ROPE;
timing: BOOL ← UserProfile.Boolean ["Genista.Timing", FALSE];
religion: BOOL ← UserProfile.Boolean ["Genista.EmulateSoS", FALSE];
failureReason: ROPE; failureTorch: REF ANY;
regressionDesign: ROPE ← "[DATools]<DATools6.1>Genista>DragonRules.dale";
layoutViewer: CoreView.Viewer;
Misc: TYPE ~ REF Stuff;
Stuff: TYPE ~ RECORD [design: CD.Design, geom: Drc.Layout];
Execute:
PROC [comm: CDSequencer.Command] ~
BEGIN
Called by ChipNDale upon activation of the command.
ENABLE Drc.coreInconsistent =>
BEGIN
failureReason ← reason; failureTorch ← torch;
GOTO failure
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;
tech: Sinix.Mode ← SinixOps.GetExtractMode [state.design.technology];
violations: CARDINAL ← 0;
IF (tech =
NIL)
THEN
BEGIN
TerminalIO.PutRope [Rope.Cat ["The technology ", comm.design.technology.name, " is not implemented in Sinix or Drc.\n"]];
RETURN
END;
state.geom ← tech.decoration;
FOR all:
CD.InstanceList ← CDOps.InstList [state.design], all.rest
WHILE all #
NIL
DO
IF all.first.selected
THEN
BEGIN
TRUSTED {Process.SetPriority [Process.priorityBackground]};
startTime1 ← BasicTime.Now [];
WITH Sinix.
Extract [obj: all.first.ob, mode: tech].result
SELECT FROM
coreCell: Drc.CoreCell =>
BEGIN
v: REF CARDINAL ← NIL;
fakeActual: Drc.Wire ~ CoreOps.CopyWire [coreCell.public];
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, tech.decoration, abort];
CoreView.debugViewer ← CoreView.StartIncrementalView [coreCell, tech.decoration, abort]
END;
CDProperties.PutDesignProp [state.design, $DrcCoreCircularity]; -- remove
lapTime ← BasicTime.Now [];
IF DrcDebug.debug
THEN
BEGIN
CoreOps.PrintCellType [coreCell, DrcDebug.dLog];
DrcDebug.dLog.PutF ["\n"];
END;
startTime2 ← BasicTime.Now [];
violations ← Drc.CheckDesignRules [cell: coreCell,
external: fakeActual,
tech: IF religion THEN cMosBsimple ELSE cMosBcomplete,
stopFlag: abort,
layout: state.geom];
stopTime ← BasicTime.Now [];
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.int [startTime1.Period [lapTime]]];
TerminalIO.PutF1 ["\nElapsed time for DRC: %g", IO.int [startTime2.Period [stopTime]]];
TerminalIO.PutF1 ["\nTotal elapsed time: %g\n", IO.int [startTime1.Period [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 don not have a better idea at the moment
CStitching.DumpCache [];
EnumerateCore [coreCell, BackAnnotation, state, abort]
END;
w: Core.Wire => ERROR;
ENDCASE => NULL -- e.g., cell contains text or schematics
END -- if selected
ENDLOOP
END; -- ExtractAndCheck
TerminalIO.PutRope ["DRC (Genista).\n"];
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
END; -- Execute
EachCell: TYPE ~ PROC [cell: Drc.CoreCell, data: REF ANY ← NIL];
EnumerateCore:
PROC [cell: Drc.CoreCell, action: EachCell, data:
REF
ANY ←
NIL, stopFlag:
REF
BOOL] ~
BEGIN
Enumerates the cell and does action on each subcell.
SELECT cell.class
FROM
CoreClasses.recordCellClass =>
BEGIN
cellData: CoreClasses.RecordCellType ~ NARROW [cell.data];
IF stopFlag^ THEN ERROR ABORTED;
FOR sub:
NAT
IN [0 .. cellData.size)
DO
EnumerateCore [cellData.instances[sub].type, action, 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]];
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
[] ← 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 [CDOps.ObjectRope [cdCell], " 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 [CDOps.ObjectRope [cdCell]], IO.rope [description]]
ELSE TerminalIO.PutF ["%g is not verified correctly (%g)\n", IO.rope [CDOps.ObjectRope [cdCell]], IO.rope [description]]
END
END; -- UncheckedMessage
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];
ListDRV:
PROC [comm: CDSequencer.Command] ~
BEGIN
Protected procedure.
EnumerateCore [coreCell, PrintDRV, comm.design.technology, abort]
END; -- ListDRV
TerminalIO.PutRope ["Design rule violations stored in Core:\n"];
CDSequencer.UseAbortFlag [comm.design, abort];
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 correctnes 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];
tech: Sinix.Mode;
ok, ko: CD.Object;
IF (test = NIL) THEN GOTO maintenanceProblem;
tech ← SinixOps.GetExtractMode [test.technology];
state.geom ← tech.decoration;
ok ← CDDirectory.Fetch [test, "ok"].object;
IF (ok = NIL) THEN GOTO maintenanceProblem;
TerminalIO.PutRope ["\n"];
WITH Sinix.Extract [obj: ok, mode: tech].result
SELECT
FROM
coreCell: Drc.CoreCell =>
IF (Drc.CheckDesignRules [cell: coreCell, tech: IF religion THEN cMosBsimple ELSE cMosBcomplete, external: coreCell.public, stopFlag: dummy, layout: state.geom] > 0) THEN EnumerateCore [coreCell, ProblemMessage, state, dummy];
ENDCASE => ERROR;
TerminalIO.PutRope ["\n"];
ko ← CDDirectory.Fetch [test, "ko"].object;
IF (ko = NIL) THEN GOTO maintenanceProblem;
WITH Sinix.Extract [obj: ko, mode: tech].result
SELECT
FROM
coreCell: Drc.CoreCell =>
BEGIN
[] ← Drc.CheckDesignRules [cell: coreCell, tech: IF religion THEN cMosBsimple ELSE cMosBcomplete, external: coreCell.public, stopFlag: dummy, layout: state.geom];
EnumerateCore [coreCell, UncheckedMessage, state, dummy]
END;
ENDCASE => ERROR;
EXITS
maintenanceProblem =>
BEGIN
TerminalIO.PutRope ["Please inform DRC maintainers that the self verification is broken.\n"]
END
END; -- RegressionTest
VerifyRect:
CD.DrawProc ~
BEGIN
[inst: Instance, trans: Transformation, pr: REF DrawInformation]
specialLayers: CD.Layer = 5; -- combined, highLightShade, highLightError, pinRepresentation
lambda: CD.Number ~ pr.design.technology.lambda;
IF (inst.ob.class.objectType = $Rect)
AND (inst.ob.layer >= specialLayers)
AND (CDProperties.GetObjectProp [inst.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[inst.ob.layer]],
v5: IO.rope ["B"]]
END; -- VerifyRect
VerifyObjects:
PROC [design:
CD.Design, obj:
CD.Object] ~
BEGIN
Traverses the cell and reports undiscovered rectangles.
envelope: CD.Instance = CDInstances.NewInst [obj];
drawRef: CD.DrawRef ← CD.CreateDrawRef [[design: design]];
drawRef.drawChild ← VerifyRect;
envelope.trans.off ← [0, 0];
obj.class.drawMe [envelope, envelope.trans, drawRef]
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
[] ← CDProperties.RegisterProperty [$DrcNr, $gbb];
[] ← CDProperties.RegisterProperty [$DrcCoreCircularity, $gbb];
CDSequencer.ImplementCommand [key: $DrcSel, proc: Execute, queue: doQueue];
CDSequencer.ImplementCommand [key: $DrcDir, proc: List, queue: doQueue];
CDSequencer.ImplementCommand [key: $DrcAll, proc: ListAll, queue: doQueue];
UserProfile.CallWhenProfileChanges [EmulateSoS];
UserProfile.CallWhenProfileChanges [Timing];
TerminalIO.PutRope ["DRC package Genista installed.\n"];
IF UserProfile.Boolean ["Genista.RegressionTest", TRUE] THEN RegressionTest