SCUtilsImpl.mesa
Copyright © 1986 by Xerox Corporation. All rights reserved.
Written by: Pradeep Sindhu, October 2, 1986 10:52:55 pm PDT
Pradeep Sindhu, September 10, 1987 4:57:23 pm PDT
DIRECTORY
CD, CDEvents, CDIO, CDViewer, CommandTool, Convert, CoreGeometry, CoreOps, GList, IO, Rope, Sinix, Sisyph, SCUtils, TerminalIO, TilingClass;
SCUtilsImpl: CEDAR PROGRAM
IMPORTS CDEvents, CDViewer, CommandTool, CDIO, Convert, CoreGeometry, CoreOps, GList, IO, Rope, Sinix, Sisyph, TerminalIO, TilingClass
EXPORTS SCUtils
~ BEGIN OPEN SCUtils;
myDesign: PUBLIC CD.Design ← NIL;
workingDirectory: ROPE ← CommandTool.CurrentWorkingDirectory[];
Exported Procs
Log2: PUBLIC PROC [n: INT] RETURNS [log: INT ← 0] ~ {
WHILE n > 1 DO n ← n/2; log ← log+1 ENDLOOP
};
ComRecord: PUBLIC PROC [pattern: ROPE, cx: Sisyph.Context, ctName: ROPE] RETURNS [ct: CellType] ~ {
n: Names ← NIL;
FOR i: INT DECREASING IN [0..Rope.Length[pattern]) DO
SELECT Rope.Fetch[pattern, i] FROM
'0 => n ← CONS["ComCell0.icon", n];
'1 => n ← CONS["ComCell1.icon", n];
'X => n ← CONS["ComCellX.icon", n];
'N => n ← CONS["ComCellN.icon", n];
'E => n ← CONS["ComCellE.icon", n];
ENDCASE => ERROR;
ENDLOOP;
ct ← RecordX[n, cx, Rope.Cat[ctName, pattern]];
};
This procedure constructs a tiling row from a list of object names. It is assumed that the publics of each of the objects are the same.
RecordX: PUBLIC PROC [obNames: Names, cx: Sisyph.Context, ctName: ROPE] RETURNS [ct: CellType] ~ {
count: NAT ← GList.Length[obNames];
Index: TYPE = {ComCell0, ComCell1, ComCellX, ComCellN, ComCellE};
baseCTs: CellTypes ← NIL;
public: Wire; -- public of cellType to be returned
tileRow: TilingClass.TileRow ← NEW [TilingClass.TileRowRec[count]];
tileArray: TilingClass.TileArray ← NEW [TilingClass.TileArrayRec[1]];
publicElements, arrayedWires, leftSideOnlyWires, rightSideOnlyWires, globalWires: Wires ← NIL;
EachWire: CoreOps.EachWireProc = {
sides: CoreGeometry.Sides = WireSide[wire, baseCTs.first];
vertical: BOOL = sides[top] OR sides[bottom];
IF vertical AND (sides[right] OR sides[left]) THEN WireSideProblem[wire, "touches adjacent sides", baseCTs.first];
IF vertical
THEN {
newPublic: Wire ← CoreOps.CreateWires[count, CoreOps.GetShortWireName[wire]];
arrayedWires ← CONS[wire, arrayedWires];
FOR i: INT IN [0..count) DO
newPublic[i] ← CoreOps.SetShortWireName[CoreOps.CopyWire[wire], NIL];
ENDLOOP;
publicElements ← CONS[newPublic, publicElements];
}
ELSE {
IF sides=CoreGeometry.noSide
THEN {
IF IsGlobal[wire, cx] THEN {
globalWires ← CONS [wire, globalWires];
publicElements ← CONS [wire, publicElements]
}
}
ELSE {
IF sides[left] THEN leftSideOnlyWires ← CONS[wire, leftSideOnlyWires];
IF sides[right] THEN rightSideOnlyWires ← CONS[wire, rightSideOnlyWires];
publicElements ← CONS [wire, publicElements]
}
}
};
Make the baseCellTypes
FOR l: Names ← obNames, l.rest WHILE l#NIL DO
baseCTs ← CONS[Sisyph.ExtractSchematicByName[l.first, cx], baseCTs];
ENDLOOP;
baseCTs ← NARROW[GList.Reverse[baseCTs]];
Compute the public of the cellType to be returned
[] ← CoreOps.VisitWireSeq[baseCTs.first.public, EachWire];
public ← CoreOps.CreateWire[publicElements];
Fill in the cellTypes
FOR i: INT IN [0..count) DO
tileRow[i] ← NEW [TilingClass.TileRec ← [type: baseCTs.first]];
baseCTs ← baseCTs.rest;
ENDLOOP;
Define the renaming for wires that touch the left side
FOR wl: Wires ← leftSideOnlyWires, wl.rest WHILE wl#NIL DO
wireName: ROPE ← CoreOps.GetShortWireName[wl.first];
tileRow[0].renaming ← CONS[[wireName, wireName], tileRow[0].renaming];
ENDLOOP;
Define the renaming for wires that touch the right side
FOR wl: Wires ← rightSideOnlyWires, wl.rest WHILE wl#NIL DO
wireName: ROPE ← CoreOps.GetShortWireName[wl.first];
tileRow[count-1].renaming ← CONS[[wireName, wireName], tileRow[count-1].renaming];
ENDLOOP;
Define the renaming for global wires
FOR wl: Wires ← globalWires, wl.rest WHILE wl#NIL DO
wireName: ROPE ← CoreOps.GetShortWireName[wl.first];
FOR i: NAT IN [0..count) DO
tileRow[i].renaming ← CONS[[wireName, wireName], tileRow[i].renaming];
ENDLOOP;
ENDLOOP;
Define the renaming for arrayed wires
FOR wl: Wires ← arrayedWires, wl.rest WHILE wl#NIL DO
wireName: ROPE ← CoreOps.GetShortWireName[wl.first];
FOR i: NAT IN [0..count) DO
tileRow[i].renaming ← CONS[[wireName, Rope.Cat[wireName, "[", Convert.RopeFromInt[i], "]"]], tileRow[i].renaming];
ENDLOOP;
ENDLOOP;
tileArray[0] ← tileRow;
Copying the public is necessary to avoid sharing of wires between cellTypes
ct ← TilingClass.CreateTiling[CoreOps.CopyWire[public], tileArray, TilingClass.SchematicsNeighborX, TilingClass.SchematicsNeighborY, Rope.Cat[ctName, ".RecordX"]];
};
LayoutDesign: PUBLIC PROC [] RETURNS [design: CD.Design] = {
name: ROPE ← "CacheCells";
design ← CDViewer.FindDesign[name];
IF design=NIL THEN design ← CDIO.ReadDesign[name, NIL, workingDirectory];
IF design = NIL THEN ERROR;
};
Internal Utilities
IsGlobal: PROC [w: Wire, cx: Sisyph.Context] RETURNS [BOOLFALSE] = {
name: ROPE ← CoreOps.GetShortWireName[w];
FOR lr: LIST OF ROPE ← Sisyph.GetGlobalNames[cx], lr.rest WHILE lr#NIL DO
IF Rope.Equal[name, lr.first] THEN RETURN [TRUE]
ENDLOOP;
};
WireSide: PROC [wire: Wire, baseCT: CellType] RETURNS [sides: CoreGeometry.Sides ← CoreGeometry.noSide] ~ {
Finds the sides on which wire touches baseCT (of which it is a public). CoreGeometry.noSide will be returned if the wire has no pins. This should be in CoreGeometry.
EachPin: CoreGeometry.EachPinProc = {
sides[side] ← TRUE;
};
[] ← CoreGeometry.EnumerateSides[Sisyph.mode.decoration, baseCT, wire, EachPin];
};
WireSideProblem: PROC [wire: Wire, msg: ROPE, baseCT: CellType] ~ {
TerminalIO.PutF["\n*** Wire %g %g in cell %g\n",
IO.rope[CoreOps.GetFullWireName[baseCT.public, wire]],
IO.rope[msg],
IO.rope[CoreOps.GetCellTypeName[baseCT]]];
SIGNAL Sinix.CallerBug[];
};
AfterInput: CDEvents.EventProc = {
IF myDesign=NIL THEN myDesign ← design;
};
CDEvents.RegisterEventProc[$AfterInput, AfterInput];
END.