DIRECTORY
BasicTime USING [GMT, Now, Period],
CD USING [CreateDrawRef, Design, DrawProc, DrawRef, Instance, InstanceList, Layer, Number, Object],
CDCommandOps USING [CallWithResource],
CDDirectory USING [Fetch, Name],
CDEvents USING [EventProc, RegisterEventProc],
CDInstances USING [NewInst],
CDMenus USING [CreateEntry],
CDMenuSpecials USING [SelectOneOf],
CDOps USING [InstList, LayerName],
CDProperties USING [GetDesignProp, GetObjectProp, PutDesignProp, RegisterProperty],
CDSequencer USING [Command, CommandRec, ExecuteCommand, ImplementCommand],
Core USING [CellType, Wire],
CoreClasses USING [recordCellClass, RecordCellType],
CoreGeometry,
CoreOps USING [GetCellTypeName, PrintCellType],
CoreProperties USING [GetProp],
IO USING [int, noWhereStream, PutF, PutFR, PutFR1, rope, STREAM],
PrincOpsUtils USING [],
Process USING [priorityBackground, SetPriority],
Rope USING [Cat, ROPE],
Sinix USING [Extract, Mode],
SinixCMos USING [extractAMode, extractBMode],
SinixNMos USING [extractMode],
Mayday USING [CheckDesignRules, coreInconsistent, DRV, DRVkey, ErrorRect],
SymTab USING [Create, Delete, EachPairAction, Fetch, GetSize, Insert, Pairs, Ref],
TerminalIO USING [WriteRope, WriteLn],
ViewerIO USING [CreateViewerStreams],
ViewerTools USING [FindExistingViewer, Viewer];
~
BEGIN
debug: BOOL ← FALSE; -- to start debugging enter: ← MaydayCommandImpl.Debug[]
timing: BOOL ← FALSE; -- turn off fast mouse
failureReason: Rope.ROPE; failureTorch: REF ANY;
dLog: IO.STREAM ← IO.noWhereStream;
currentLambda: CD.Number; -- sorry for the hack instead of using the handle
DRVSummary: TYPE = SymTab.Ref;
Execute:
PROC [comm: CDSequencer.Command] ~
BEGIN
Called by ChipNDale upon activation of the command.
ENABLE Mayday.coreInconsistent [failureReason, failureTorch] => GOTO failure;
violations: DRVSummary = SymTab.Create [];
abort: REF BOOL ← NEW [BOOL ← FALSE];
ExtractAndCheck:
PROC [comm: CDSequencer.Command] ~
BEGIN
Protected procedure.
startTime1, startTime2, lapTime, stopTime: BasicTime.GMT;
tech: Sinix.Mode;
cdObjHint: ATOM ← $PWCoreLayout;
SELECT comm.design.technology.key
FROM
$cmos => tech ← SinixCMos.extractAMode;
$cmosB => tech ← SinixCMos.extractBMode;
$nmos => tech ← SinixNMos.extractMode;
ENDCASE =>
BEGIN
TerminalIO.WriteRope [Rope.Cat ["The technology ", comm.design.technology.name, " is not implemented in Sinix or Mayday.\n"]];
RETURN
END;
FOR all:
CD.InstanceList ← CDOps.InstList [comm.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: Core.CellType =>
BEGIN
lapTime ← BasicTime.Now [];
IF debug THEN CoreOps.PrintCellType [coreCell, dLog];
startTime2 ← BasicTime.Now [];
[] ← Mayday.CheckDesignRules [cell: coreCell,
design: comm.design,
abortFlag: abort,
cdObjKey: cdObjHint,
decoration: tech.decoration];
stopTime ← BasicTime.Now [];
IF debug
THEN
BEGIN
currentLambda ← comm.design.technology.lambda;
VerifyObjects [comm.design, all.first.ob]
END;
IF timing
THEN
BEGIN
TerminalIO.WriteRope [Rope.Cat ["\nElapsed time for extraction: ", TimeToRope [startTime1, lapTime]]];
TerminalIO.WriteRope [Rope.Cat [". Elapsed time for DRC: ", TimeToRope [startTime2, stopTime]]];
TerminalIO.WriteRope [Rope.Cat ["\nTotal elapsed time: ", TimeToRope [startTime1, stopTime], "\n"]]
END;
UpdateDRVDirectory [coreCell, violations]
END;
w: Core.Wire => NULL;
ENDCASE => NULL
END -- if selected
ENDLOOP
END; -- ExtractAndCheck
TerminalIO.WriteRope ["Mayday.\n"];
CDProperties.PutDesignProp [comm.design, $MaydayCmdDir];
[] ← CDCommandOps.CallWithResource [ExtractAndCheck, comm, $Mayday, abort];
TerminalIO.WriteRope ["Mayday done.\n"];
IF (violations.GetSize[] > 0)
THEN
BEGIN
TerminalIO.WriteRope ["Summary of design rule violations:\n"];
CDProperties.PutDesignProp [comm.design, $MaydayCmdDir, violations];
[] ← violations.Pairs [PrintDRVSummary]
END;
EXITS
failure =>
BEGIN
TerminalIO.WriteRope [failureReason];
TerminalIO.WriteRope [". Core structure inconsistent. Mayday aborted.\n"]
END
END; -- Execute
List:
PROC [comm: CDSequencer.Command] ~
BEGIN
Called by ChipNDale upon activation of the command.
violations: DRVSummary = NARROW [CDProperties.GetDesignProp [comm.design, $MaydayCmdDir]];
abort: REF BOOL ← NEW [BOOL←FALSE];
ListDRV:
PROC [comm: CDSequencer.Command] ~
BEGIN
Protected procedure.
existsInCD: BOOL; drv: Mayday.DRV;
cell: Rope.
ROPE ← CDMenuSpecials.SelectOneOf [violations, "Cells with errors"];
muss Variable sein nicht Konstante [Compiler].
IF (cell = NIL) THEN RETURN; -- no selection
drv ← NARROW [SymTab.Fetch[violations, cell].val, Mayday.DRV];
FOR e:
LIST
OF Mayday.ErrorRect ← drv.places, e.rest
WHILE e #
NIL
DO
TerminalIO.WriteRope [e.first.msg]; TerminalIO.WriteLn;
IF abort^ THEN ERROR ABORTED
ENDLOOP;
existsInCD ← CDDirectory.Fetch [comm.design, cell].found;
IF
NOT existsInCD
THEN
TerminalIO.WriteRope ["No ChipNDale correspondent found for this cell.\n"]
ELSE
BEGIN
nestedCmd: CDSequencer.Command ← NEW [CDSequencer.CommandRec ← [key: $PushNamed, design: comm.design, data: cell, ref: comm.ref]];
TerminalIO.WriteRope ["Trying to push into ChipNDale correspondent for this cell. Pop out of current cell if it fails.\n"];
CDSequencer.ExecuteCommand [comm: nestedCmd, queue: dontQueue];
IF (ISTYPE [comm.ref, CDVPrivate.VRef]) THEN BEGIN
Display error messages in the layout.
viewer: ViewerClasses.Viewer = NARROW [comm.ref, CDVPrivate.VRef].viewer;
IF (viewer # NIL) THEN ViewerOps.PaintViewer [viewer, client, FALSE, $DrawInstanceNames]
END
END
END; -- ListDRV
TerminalIO.WriteRope ["List design rule violations.\n"];
IF (violations = NIL) THEN TerminalIO.WriteRope ["None available.\n"]
ELSE [] ← CDCommandOps.CallWithResource [ListDRV, comm, $Mayday, abort];
TerminalIO.WriteRope ["Design rule violations listed.\n"]
END; -- List
ListAll:
PROC [comm: CDSequencer.Command] ~
BEGIN
Called by ChipNDale upon activation of the command.
violations: DRVSummary = NARROW [CDProperties.GetDesignProp [comm.design, $MaydayCmdDir]];
abort: REF BOOL ← NEW [BOOL←FALSE];
PrintDRV: SymTab.EachPairAction ~
BEGIN
[key: Key, val: Val] RETURNS [quit: BOOL]
drv: Mayday.DRV = NARROW [val];
TerminalIO.WriteRope [IO.PutFR ["cell %g, %g violations:\n", IO.rope [key], IO.int [drv.count]]];
FOR e:
LIST
OF Mayday.ErrorRect ← drv.places, e.rest
WHILE e #
NIL
DO
TerminalIO.WriteRope [e.first.msg]; TerminalIO.WriteLn;
IF abort^ THEN ERROR ABORTED
ENDLOOP;
RETURN [abort^]
END; -- PrintDRV
ListDRV:
PROC [comm: CDSequencer.Command] ~
BEGIN
Protected procedure.
IF violations.Pairs [PrintDRV] THEN TerminalIO.WriteRope ["Aborted.\n"]
END; -- ListDRV
TerminalIO.WriteRope ["List all design rule violations.\n"];
IF (violations = NIL) THEN TerminalIO.WriteRope ["None available.\n"]
ELSE [] ← CDCommandOps.CallWithResource [ListDRV, comm, $Mayday, abort];
TerminalIO.WriteRope ["All design rule violations listed.\n"]
END; -- ListAll
UpdateDRVDirectory:
PROC [cell: Core.CellType, dir: DRVSummary] ~
BEGIN
Enumerates the cell and puts the DesignRuleViolations in the directory.
name: Rope.ROPE = CoreOps.GetCellTypeName[cell];
IF SymTab.Fetch[dir, name].found THEN RETURN; -- prune
SELECT cell.class
FROM
CoreClasses.recordCellClass =>
BEGIN
data: CoreClasses.RecordCellType = NARROW [cell.data];
drv: Mayday.DRV = NARROW [CoreProperties.GetProp [cell.properties, Mayday.DRVkey]];
FOR sub:
NAT
IN [0 .. data.size)
DO
UpdateDRVDirectory [data.instances[sub].type, dir]
ENDLOOP;
IF (drv # NIL) THEN [] ← dir.Insert [name, drv]
END;
ENDCASE => NULL
END; -- UpdateDRVDirectory
PrintDRVSummary: SymTab.EachPairAction ~
BEGIN
[key: Key, val: Val] RETURNS [quit: BOOL]
drv: Mayday.DRV = NARROW [val];
TerminalIO.WriteRope [IO.PutFR ["cell %g: %g\n", IO.rope [key], IO.int [drv.count]]];
RETURN [FALSE]
END; -- PrintDRVSummary
InvalidateDRV: CDEvents.EventProc ~
BEGIN
[event: REF, design: CD.Design, x: REF] RETURNS [dont: BOOL ← FALSE]
Deletes a cell from the table when the cell has been edited. violations is NIL if the design has not yet been checked by Mayday.
violations: DRVSummary = NARROW [CDProperties.GetDesignProp [design, $MaydayCmdDir]];
cellName: Rope.ROPE = CDDirectory.Name [NARROW [x, CD.Object]];
IF (violations # NIL) AND (cellName # NIL) THEN [] ← violations.Delete [cellName]
END; -- InvalidateDRV
VerifyRect:
CD.DrawProc ~
BEGIN
[inst: Instance, pos: Position, orient: Orientation, pr: REF DrawInformation]
specialLayers: CD.Layer = 5; -- combined, highLightShade, highLightError, pinRepresentation
IF (inst.ob.class.objectType = $Rect)
AND (inst.ob.layer >= specialLayers)
AND (CDProperties.GetObjectProp [inst.ob, $MaydaySeparationChecked] =
NIL)
THEN
IO.PutF [stream: dLog, format: "Failed to check rectangle at [%g, %g] %l %g%l\n",
v1: IO.int [pos.x / currentLambda],
v2: IO.int [pos.y / currentLambda],
v3: IO.rope ["b"],
v4: IO.rope [CDOps.LayerName[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.location ← [0, 0];
obj.class.drawMe [envelope, envelope.location, 0, drawRef]
END; -- VerifyObjects
TimeToRope:
PROC [from, to: BasicTime.
GMT]
RETURNS [time: Rope.
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.
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
Debug:
PROC ~
BEGIN
For convenience in debugging. Call this procedure in the Interpreter.
viewer: ViewerTools.Viewer;
dummy: IO.STREAM;
debug ← TRUE; -- Get all in one
viewer ← ViewerTools.FindExistingViewer ["Mayday debug"];
IF viewer #
NIL THEN
[in: dummy, out: dLog] ← ViewerIO.CreateViewerStreams ["Mayday debug", viewer]
ELSE
BEGIN
viewer ← ViewerTools.FindExistingViewer ["Terminal"];
[in: dummy, out: dLog] ← ViewerIO.CreateViewerStreams ["Terminal", viewer]
END
END; -- Debug
[] ← CDProperties.RegisterProperty [$MaydayCmdDir, $gbb];
CDSequencer.ImplementCommand [key: $MaydaySel, proc: Execute, queue: doQueue];
CDMenus.CreateEntry [menu: $ProgramMenu, entry: "Extract & DRC (Sinix & Mayday)", key: $MaydaySel];
CDSequencer.ImplementCommand [key: $MaydayDir, proc: List, queue: doQueue];
CDMenus.CreateEntry [menu: $ProgramMenu, entry: "List Violations (Mayday)", key: $MaydayDir];
CDSequencer.ImplementCommand [key: $MaydayAll, proc: ListAll, queue: doQueue];
CDMenus.CreateEntry [menu: $ProgramMenu, entry: "List All Violations (Mayday)", key: $MaydayAll];
CDEvents.RegisterEventProc [proc: InvalidateDRV, event: $AfterCellReplacement];
CDEvents.RegisterEventProc [proc: InvalidateDRV, event: $AfterChange];
IF debug THEN Debug [];
TerminalIO.WriteRope ["Mayday package loaded.\n"]