DrcCommandImpl.mesa
Copyright Ó 1987 by Xerox Corporation. All rights reserved.
Rewritten by gbb January 12, 1987 11:53:06 am PST
gbb March 30, 1987 5:18:53 pm PST
Interface to ChipNDale.
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];
DrcCommandImpl: CEDAR PROGRAM
IMPORTS BasicTime, CD, CDBasics, CDCommandOps, CDDirectory, CDErrors, CDInstances, CDIO, CDOps, CDProperties, CDSequencer, CoreClasses, CoreGeometry, CoreOps, CoreProperties, CoreView, CStitching, Drc, DrcCMOSB, DrcDebug, IO, Process, Rope, Sinix, SinixOps, TerminalIO, UserProfile
~ 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 BOOLNEW [BOOLFALSE];
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 CARDINALNIL;
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 ANYNIL];
EnumerateCore: PROC [cell: Drc.CoreCell, action: EachCell, data: REF ANYNIL, 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 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]];
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 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 [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 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 [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 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];
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 [BOOLFALSE];
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
END.