IFUPWUtils.mesa
Copyright c 1985 by Xerox Corporation. All rights reserved.
Last Edited by Curry, June 22, 1985 3:30:39 pm PDT
DIRECTORY
CD,
CDAbuts,
CDCells,
CDDirectory,
CDExtras,
CDIO,
CDOps,
CDPinObjects,
CDProperties,
CDRects USING [CreateRect],
CDSequencer,
CDSimpleOps,
CDViewer,
Convert,
Commander,
DragOpsCross,
IFUPW,
IO,
PW,
PWBasics,
PWPins,
Rope,
ViewerClasses,
VMStatistics,
WatchStats;
IFUPWUtils: CEDAR PROGRAM
IMPORTS CD, CDAbuts, CDCells, CDDirectory, CDExtras, CDIO, CDOps, CDPinObjects, CDProperties, CDRects, CDSequencer, CDSimpleOps, CDViewer, Convert, IO, IFUPW, PW, PWBasics, PWPins, Rope, VMStatistics, WatchStats
EXPORTS IFUPW =
BEGIN OPEN IFUPW;
Error: PUBLIC ERROR[msg: PW.ROPE] = CODE;
GND: PUBLIC Rope.ROPE ← "GND";
VDD: PUBLIC Rope.ROPE ← "VDD";
rngByte:  PUBLIC INT ← 4;
rngBit:  PUBLIC INT ← 8;
GVTypeList: PUBLIC List ← LIST["latch", "triDr", "buf", "inv", "nor", "nand", "xor"];
ChangePinNames: PUBLIC PROC[obj: CD.ObPtr, oldName, newName: PW.ROPE] = {
pins: CD.ApplicationList ← CDPinObjects.FindPins[obj, oldName];
FOR pins ← pins, pins.rest WHILE pins#NIL DO
CDPinObjects.SetName[pins.first, newName] ENDLOOP };
ConnSpec: TYPE = REF ConnSeqRec;
ConnSeqRec: TYPE = RECORD[SEQUENCE size: CARDINAL OF CnntRec];
CnntRec:  TYPE = RECORD[name: Rope.ROPE, y: INT];
BuildConnSpec: PROC[in, out: List, topY, botY, refY: INT, refCell: CD.ObPtr]
RETURNS[connSpec: ConnSpec] = {
done: BOOL     ← FALSE;
size, index: CARDINAL ← ListLength[in] + ListLength[out] + 2;
connSpec ← NEW[ConnSeqRec[size]];
connSpec[size-1].name ← NIL; connSpec[size-1].y ← topY;
connSpec[0].name  ← NIL; connSpec[0].y  ← botY;
index ← 1;
FOR ii: INT IN [0..ListLength[in]) DO
connSpec[index].name ← in.first; in ← in.rest;
connSpec[index].y  ← refY +
CDPinObjects.FindPins[refCell, IO.PutFR["In%g", IO.int[ii]]].first.location.y;
index ← index + 1 ENDLOOP;
FOR ii: INT IN [0..ListLength[out]) DO
connSpec[index].name ← out.first; out ← out.rest;
connSpec[index].y  ← refY +
CDPinObjects.FindPins[refCell, IO.PutFR["Out%g", IO.int[ii]]].first.location.y;
index ← index + 1 ENDLOOP;
WHILE NOT done DO
done ← TRUE;
FOR ii: INT IN [0..size-1) DO
ty:   INT   ← connSpec[ii].y;
tname: Rope.ROPE ← connSpec[ii].name;
IF connSpec[ii].y <= connSpec[ii+1].y THEN LOOP;
done      ← FALSE;
connSpec[ii].y   ← connSpec[ii+1].y;
connSpec[ii].name  ← connSpec[ii+1].name;
connSpec[ii+1].y  ← ty;
connSpec[ii+1].name ← tname ENDLOOP ENDLOOP };
IOConnect: PUBLIC PROC[
design: CD.Design,
cell:  CD.ObPtr,
top:  List,
in:   List,
out:  List,
bot:  List,
refcell: CD.ObPtr,
refX:  INT,
refY:  INT,
topY:  INT,
botY:  INT ] = {
PurgeNILLsFromList: PUBLIC PROC [list: List] RETURNS[clean: List] = {
IF list = NIL THEN RETURN[NIL];
clean ← PurgeNILLsFromList[list.rest];
IF list.first#NIL THEN clean ← CONS[list.first, clean]};
Same: PROC[idx1, idx2: CARDINAL] RETURNS[BOOL] =
{RETURN[Rope.Equal[connSpec[idx1].name, connSpec[idx2].name]]};
connSpec: ConnSpec;
tIdx, bIdx: CARDINAL ← 0;
in  ← PurgeNILLsFromList[in];
out ← PurgeNILLsFromList[out];
connSpec ← BuildConnSpec[in, out, topY, botY, refY, refcell];
tIdx ← connSpec.size-1;
bIdx ← 0;
FOR i: INT IN [0..nofVWires) DO
Add: PROC[idx1, idx2: CARDINAL] RETURNS[BOOL] = {
IF ~Same[idx1, idx2] THEN RETURN[FALSE];
loc.y ← connSpec[idx1].y;
size.y ← connSpec[idx2].y - connSpec[idx1].y;
IF size.y < 0 THEN ERROR;
AddRet[cell:cell, size: size, loc: loc, level: cmosMet];
RETURN[TRUE]};
size: Size  ← [metW, 0];
loc: Location ← [refX+i*metPitch+leftTail, 0];
connSpec[tIdx].name ← ListIndexItem[top,  i];
connSpec[bIdx].name  ← ListIndexItem[bot,  i];
IF connSpec[tIdx].name#NIL THEN FOR ii: INT IN [bIdx..tIdx) DO
IF Add[ ii, tIdx] THEN EXIT; REPEAT FINISHED => ERROR Error
[IO.PutFR["Orphan top signal: %g", IO.rope[connSpec[tIdx].name]]] ENDLOOP;
IF connSpec[bIdx].name#NIL THEN FOR ii: INT DECREASING IN (bIdx..tIdx) DO
IF Add[ bIdx, ii] THEN EXIT; REPEAT FINISHED => IF ~Same[bIdx, tIdx] THEN ERROR
Error[IO.PutFR["Orphan bottom signal: %g", IO.rope[connSpec[bIdx].name]]] ENDLOOP;
ENDLOOP;
Horizontal connections
IF ListLength[out]#0 THEN FOR i: INT IN [0..nofVWires) DO
AddCnt: PROC[idx: CARDINAL] = {
ctct, wire: CD.ObPtr;
IF ~Same[idx, tIdx] AND ~Same[idx, bIdx] THEN RETURN;
wLoc.y ← connSpec[idx].y;
ctct ← MetalCntctObPtr[design, cmosPoly];
wire ← CDRects.CreateRect[[wLen, 4], cmosPoly];
[] ← PWBasics.IncludeApplication[cell, ctct,  [wLoc.x-2, wLoc.y-2]];
[] ← PWBasics.IncludeApplication[cell, wire, wLoc] };
wLen: INT ← (nofVWires-1-i)*metPitch + 8;
wLoc: Location ← [refX+i * metPitch +leftTail, 0];
connSpec[tIdx].name ← ListIndexItem[top,  i];
connSpec[bIdx].name  ← ListIndexItem[bot,  i];
FOR ii: INT IN (bIdx..tIdx) DO AddCnt[ii] ENDLOOP;
ENDLOOP };
AddMetalPins: PUBLIC PROC
[cell: CD.ObPtr, top, bot: List, refX, topY, botY: INT, realNames: BOOL] = {
length: INTMAX[ListLength[top], ListLength[bot]];
FOR i: INT IN [0..length) DO
tName: PW.ROPE ← ListIndexItem[top, i];
bName: PW.ROPE ← ListIndexItem[bot, i];
size: Size  ← [6, 6];
loc: Location ← [refX+i*metPitch+leftTail, topY-size.y];
IF tName #NIL THEN PutPin [cell, size, loc,   cmosMet,
(IF realNames THEN tName ELSE NIL)];
IF bName #NIL THEN PutPin [cell, size, [loc.x, botY], cmosMet,
(IF realNames THEN bName ELSE NIL)];
ENDLOOP };
ProcessorRegToList: PUBLIC PROC [reg: DragOpsCross.ProcessorRegister] RETURNS[list: List] = {
val: CARDINALLOOPHOLE[reg];
list ← NIL;
FOR bit: INT IN [0..rngBit) DO
list ← CONS[(IF (val MOD 2 = 1) THEN VDD ELSE GND), list];
val ← val/2;
ENDLOOP };
AddRet: PUBLIC PROC [cell: CD.ObPtr, size: Size, loc: Location, level: CD.Layer] = {
IF (size.x MOD 2)=1 OR (size.y MOD 2)=1 OR size.x<0 OR size.y<0
IF size.x<0 OR size.y<0
THEN ERROR Error[IO.PutFR
["Strange rectangle size [%g, %g]", IO.int[size.x], IO.int[size.y]]];
IF size.x=0 OR size.y=0 THEN RETURN;
[] ← PWBasics.IncludeApplication[cell, CDRects.CreateRect[size, level], loc]};
PutPin: PUBLIC PROC[cell:CD.ObPtr, size:Size, loc:Location, level:CD.Layer, name:PW.ROPE] = {
pinApl: CD.ApplicationPtr
← PWBasics.IncludeApplication[cell, CDPinObjects.CreatePinOb[size], loc];
CDPinObjects.SetName[pinApl, name];
CDPinObjects.SetLayer[pinApl, level]};
SizeOf: PUBLIC PROC[design: CD.Design, cell: PW.ObjName] RETURNS[size: Size] = {
RETURN[PWBasics.GetISize[PWBasics.ObjFromName[design, cell] ] ]};
Merge: PUBLIC PROC[design: CD.Design, side: Side, cell1, cell2: PW.ObjName]
RETURNS[cell: PW.ObjName] = {
obj: CD.ObPtr ← CDCells.CreateEmptyCell[];
obj1: CD.ObPtr ← PWBasics.ObjFromName[design, cell1];
obj2: CD.ObPtr ← PWBasics.ObjFromName[design, cell2];
size1: Size ← PWBasics.GetISize[obj1];
size2: Size ← PWBasics.GetISize[obj2];
[ ] ← PWBasics.IncludeApplication[obj, obj1, [0, 0]];
SELECT side FROM
TopSide  => [ ] ← PWBasics.IncludeApplication[obj, obj2, [0, size1.y-size2.y]];
BotSide => [ ] ← PWBasics.IncludeApplication[obj, obj2, [0, 0]];
RtSide  => [ ] ← PWBasics.IncludeApplication[obj, obj2, [0, size1.x-size2.x]];
LtSide  => [ ] ← PWBasics.IncludeApplication[obj, obj2, [0, 0]];
ENDCASE;
PWBasics.RepositionCell[design, obj];
cell ← PWBasics.NameFromObj[obj]};
ProcRegToList: PUBLIC PROC [reg: ProcessorReg] RETURNS[new: List] =
{val: CARDINALLOOPHOLE[reg]; RETURN[CardToList8[val]]};
CardToList8: PUBLIC PROC [val: CARDINAL] RETURNS[new: List] = {
new ← NIL;
THROUGH [0..8) DO
new ← CONS[(IF (val MOD 2)=1 THEN VDD ELSE GND), new];
val ← val/2;
ENDLOOP};
FixGVInList: PUBLIC PROC [list: List] RETURNS[new: List] =
{RETURN[AddGVToList[DelGVFromList[list]]]};
DelGVFromList: PUBLIC PROC [list: List] RETURNS[new: List] = {
nonNilItemAdded: BOOLFALSE;
IF list=NIL THEN RETURN[NIL];
FOR ii: INT DECREASING IN [0..ListLength[list]) DO
item: PW.ROPE ← ListIndexItem[list, ii];
IF Rope.Equal[item, GND] OR Rope.Equal[item, VDD] THEN item ← NIL;
IF item=NIL AND NOT nonNilItemAdded THEN LOOP;
nonNilItemAdded ← TRUE;
new ← CONS[item, new] ENDLOOP};
AddGVToList: PUBLIC PROC [list: List] RETURNS[new: List] = {
FOR ii: INT DECREASING IN [0..MAX[nofVWires, ListLength[list]]) DO
item: PW.ROPE ← ListIndexItem[list, ii];
IF ii=nofVWires-1 THEN item ← VDD;
IF ii=nofVWires-2 THEN item ← GND;
new ← CONS[item, new] ENDLOOP};
AddGVToLIST: PUBLIC PROC [list: LIST OF REF, indexGV: BOOL]
RETURNS[new: LIST OF REF] = {
FOR ii: INT DECREASING IN [0..MAX[nofVWires, LISTLength[list]]) DO
item: REF ← LISTIndexItem[list, ii];
IF ii=nofVWires-1 THEN item ← IF indexGV THEN VDD.Cat["."] ELSE VDD;
IF ii=nofVWires-2 THEN item ← IF indexGV THEN GND.Cat["."] ELSE GND;
new ← CONS[item, new] ENDLOOP};
ListAllNil: PUBLIC PROC [list: List] RETURNS[allNIL: BOOL] =
{FOR list ← list, list.rest WHILE list#NIL DO
IF list.first#NIL THEN RETURN[FALSE]; ENDLOOP; RETURN[TRUE]};
LISTAllNil: PUBLIC PROC [list: LIST OF REF] RETURNS[allNIL: BOOL] =
{FOR list ← list, list.rest WHILE list#NIL DO
IF list.first#NIL THEN RETURN[FALSE]; ENDLOOP; RETURN[TRUE]};
List4: PUBLIC PROC [r0, r1, r2, r3: PW.ROPE] RETURNS[list: List] = {
list ← CONS[r0, CONS[r1, CONS[r2, CONS[r3, NIL]]]]};
List8: PUBLIC PROC [r0, r1, r2, r3, r4, r5, r6, r7: PW.ROPE] RETURNS[list: List] = {
list ← CONS[r0,CONS[r1,CONS[r2,CONS[r3,CONS[r4,CONS[r5,CONS[r6,CONS[r7, NIL]]]]]]]]};
LISTn: PUBLIC PROC [r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15: REFNIL ]
RETURNS[list: LIST OF REF] = {
refs: ARRAY [0..16) OF REF ← [r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15];
index: INT;
FOR index DECREASING IN [0..16) WHILE refs[index]=NIL DO ENDLOOP;
FOR index←index, index-1 WHILE index>=0 DO
IF refs[index]#NIL AND ISTYPE[refs[index], REF TEXT]
THEN list ← CONS[Rope.FromRefText[NARROW[refs[index]]], list ]
ELSE list ← CONS[refs[index], list] ENDLOOP};
Listn: PUBLIC PROC
[r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15: PW.ROPENIL ]
RETURNS[list: List] = {
refs: ARRAY [0..16) OF PW.ROPE
[r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15];
index: INT;
FOR index DECREASING IN [0..16) WHILE refs[index]=NIL DO ENDLOOP;
FOR index←index, index-1 WHILE index>=0 DO list ← CONS[refs[index], list] ENDLOOP};
ListLength: PUBLIC PROC [list: List] RETURNS[size: INT] =
{FOR size ← 0, size+1 WHILE list#NIL DO list←list.rest ENDLOOP};
LISTLength: PUBLIC PROC [list: LIST OF REF] RETURNS[size: INT] =
{FOR size ← 0, size+1 WHILE list#NIL DO list←list.rest ENDLOOP};
ListIndexItem: PUBLIC PROC [list: List, index: INT] RETURNS[item: PW.ROPE] = {
FOR index ← index, index-1 WHILE index#0 AND list#NIL DO list←list.rest ENDLOOP;
RETURN[IF list=NIL THEN NIL ELSE list.first]};
LISTIndexItem: PUBLIC PROC[list: LIST OF REF, index: INT] RETURNS[item: REF] = {
FOR index ← index, index-1 WHILE index#0 AND list#NIL DO list←list.rest ENDLOOP;
RETURN[IF list=NIL THEN NIL ELSE list.first]};
ListItemIndexMin: PUBLIC PROC [list: List, item: PW.ROPE] RETURNS[index: INT] = {
IF item=NIL THEN RETURN[-1];
FOR index ← 0, index+1 WHILE list#NIL DO
IF Rope.Equal[list.first, item] THEN RETURN[index];
list←list.rest ENDLOOP;
RETURN[-1]};
ListNonNILIndexMin: PUBLIC PROC [list: List] RETURNS[index: INT] = {
FOR index ← 0, index+1 WHILE list#NIL DO
IF list.first#NIL THEN RETURN[index];
list←list.rest ENDLOOP;
RETURN[-1]};
ListItemIndexMax: PUBLIC PROC [list: List, item: PW.ROPE] RETURNS[index: INT] = {
count: INT ← -1;
index ← -1;
IF item=NIL THEN RETURN[-1];
FOR list ← list, list.rest WHILE list#NIL DO
count ← count+1;
IF Rope.Equal[list.first, item] THEN index ← count ENDLOOP};
ListNonNILIndexMax: PUBLIC PROC [list: List] RETURNS[index: INT] = {
count: INT ← -1;
index ← -1;
FOR list ← list, list.rest WHILE list#NIL DO
count ← count+1;
IF list.first#NIL THEN index ← count ENDLOOP};
ReverseList: PUBLIC PROC [list: List] RETURNS [new: List] =
{FOR list ← list, list.rest WHILE list#NIL DO new ← CONS[list.first, new] ENDLOOP};
ReverseLIST: PUBLIC PROC [list: LIST OF REF] RETURNS [new: LIST OF REF] =
{FOR list ← list, list.rest WHILE list#NIL DO new ← CONS[list.first, new] ENDLOOP};
AppendIndexToRope: PUBLIC PROC[index: INT, item: PW.ROPE] -- If last char is '.
RETURNS[PW.ROPE] = {
IF Rope.Find[item, ".", 0]=-1 THEN RETURN[item];
RETURN[Rope.Cat[item, Convert.RopeFromInt[index, 36, FALSE] ] ] };
ExpandList: PUBLIC PROC[index1, index2: INT, list: LIST OF REF]
RETURNS[new: List] ={
item1, item2, item3: PW.ROPENIL;
IF list = NIL THEN RETURN[NIL];
new ← ExpandList[index1, index2, list.rest];
IF list.first = NIL THEN RETURN[CONS[NIL, new]];
WITH list.first SELECT FROM
first: Rope.ROPE    => item1 ← first;
first: REF TEXT    => item1 ← Rope.FromRefText[first];
first: LIST OF REF   => {
WITH LISTIndexItem[first, index1] SELECT FROM
second: Rope.ROPE    => item2 ← second;
second: REF TEXT    => item2 ← Rope.FromRefText[second];
second: LIST OF REF   => {
WITH LISTIndexItem[second, index2] SELECT FROM
third: Rope.ROPE    => item3 ← third;
third: REF TEXT    => item3 ← Rope.FromRefText[third];
third: REF     => IF third#NIL THEN ERROR;
ENDCASE      => ERROR };
second: List     => item3 ← ListIndexItem[second, index2];
second: REF     => IF second#NIL THEN ERROR;
ENDCASE      => ERROR };
first: LIST OF List   => TRUSTED {
second: List ← LOOPHOLE[LISTIndexItem[LOOPHOLE[first], index1]];
item3   ← ListIndexItem[second, index2]};
first: List      => item2 ← ListIndexItem[first, index1];
first: REF      => IF first#NIL THEN ERROR;
ENDCASE      => ERROR;
IF item1#NILTHEN item2 ← AppendIndexToRope[index1, item1];
IF item2#NILTHEN item3 ← AppendIndexToRope[index2, item2];
RETURN[CONS[item3, new] ]};
OldGetMDS: PUBLIC PROC RETURNS[newMDS: INT] = TRUSTED {
pagesAllocated, pagesFreed, pagesInPartition: INT;
[pagesAllocated, pagesFreed, pagesInPartition]← VMStatistics.VirtualAllocation[mds];
newMDS ← MAX[0, pagesInPartition - pagesAllocated + pagesFreed]};
AbutListX: PUBLIC PROC[design: CD.Design, list: LIST OF PW.ObjName]
RETURNS[new: PW.ObjName] = {
objList:  LIST OF CD.ObPtr ← ListObjFromObjNames[design, list];
newAbut: CD.ObPtr    ← CDAbuts.CreateNewAbutX[objList];
PWBasics.Include[design, newAbut];
new ← PWBasics.NameFromObj[newAbut]};
AbutListY: PUBLIC PROC[design: CD.Design, list: LIST OF PW.ObjName]
RETURNS[new: PW.ObjName] = {
objList:  LIST OF CD.ObPtr ← ListObjFromObjNames[design, list];
newAbut: CD.ObPtr    ← CDAbuts.CreateNewAbutY[objList];
PWBasics.Include[design, newAbut];
new ← PWBasics.NameFromObj[newAbut]};
AbutX: PUBLIC PROC[design: CD.Design, cell1, cell2: PW.ObjName]
RETURNS[new: PW.ObjName] = {RETURN[
IF cell1=NIL THEN cell2
ELSE IF cell2=NIL THEN cell1
ELSE AbutListX[design, LIST[cell1, cell2]]]};
AbutY: PUBLIC PROC[design: CD.Design, cell1, cell2: PW.ObjName]
RETURNS[new: PW.ObjName] = {RETURN[
IF cell1=NIL THEN cell2
ELSE IF cell2=NIL THEN cell1
ELSE AbutListY[design, LIST[cell1, cell2]]]};
ListObjFromObjNames: PROC [design: CD.Design, names: LIST OF PW.ObjName]
RETURNS [LIST OF CD.ObPtr] = {
revList, list: LIST OF CD.ObPtr ← NIL;
WHILE names#NIL DO
revList ← CONS[PWBasics.ObjFromName[design, names.first], revList];
names ← names.rest;
ENDLOOP;
WHILE revList#NIL DO
list ← CONS[revList.first, list];
revList ← revList.rest;
ENDLOOP;
RETURN[list] };
UniqueIndex: INT ← 0;
UniqueCellName: PUBLIC PROC[type: PW.ROPE, top, bot, ins, outs: List]
RETURNS[name: PW.ROPE] = {
Index: PROC[rope: PW.ROPE] RETURNS[index: INT] = {
IF Rope.Equal[rope, "GND"] THEN RETURN[6];
IF Rope.Equal[rope, "VDD"] THEN RETURN[7];
index ← ListItemIndexMax[top, rope];
IF index IN [6..8) THEN ERROR Error["Impossible"];
IF index IN [0..12) THEN RETURN[index];
IF index # -1  THEN ERROR Error["Impossible"];
index ← ListItemIndexMax[bot, rope];
IF index IN [6..8) THEN ERROR Error["Impossible"];
IF index IN [0..12) THEN RETURN[index+12];
IF index = -1   THEN RETURN[31];
ERROR Error["Impossible"]};
topSig, botSig, tbEq, val: INT ← 0;
IF MAX[ListLength[top], ListLength[bot]] > 12 THEN {
UniqueIndex ← UniqueIndex+1;
RETURN[IO.PutFR["%g-Lrg-%g", IO.rope[type], IO.int[UniqueIndex]]]};
FOR ii: INT IN [0..12) DO
topN: PW.ROPE ← ListIndexItem[top, ii];
botN: PW.ROPE ← ListIndexItem[bot, ii];
IF ii IN [6..7] THEN LOOP;
topSig    ← (topSig*2) +(IF topN#NIL THEN 1 ELSE 0);
botSig    ← (botSig*2) +(IF botN#NIL THEN 1 ELSE 0);
tbEq    ← (tbEq*2) +(IF Rope.Equal[topN, botN] THEN 1 ELSE 0);
ENDLOOP;
val ← (topSig*1024+botSig)*1024+tbEq;
name ← type.Cat["-"];
name ← name.Cat[Convert.RopeFromInt[from: val, base: 32, showRadix: FALSE]];
FOR ins ← ins,  ins.rest WHILE ins#NILDO
val ← Index[ins.first];
name ← name.Cat[Convert.RopeFromInt[from: val, base: 32, showRadix: FALSE]] ENDLOOP;
name ← name.Cat["-"];
FOR outs ← outs, outs.rest WHILE outs#NILDO
val ← Index[outs.first];
name ← name.Cat[Convert.RopeFromInt[from: val, base: 32, showRadix: FALSE]] ENDLOOP };
RegisterDesignWithPW: PUBLIC PROC[design: CD.Design] = {
command: CDSequencer.Command ← NEW[CDSequencer.CommandRec ← [a: $FlushCaches]];
command ← NEW[CDSequencer.CommandRec ← [design: design, a: $FlushCaches]];
CDSequencer.ExecuteCommand[comm: command, queue: dontQueue] };
WriteOutNewDesign: PUBLIC PROC[design: CD.Design, newName: PW.ROPE] = {
CDSimpleOps.RenameDesign[design, newName];
[ ] ← CDIO.WriteDesign[design, newName] };
AssembleList: PUBLIC PROC[
ref: REF,
rowProc: LIST OF IFUPW.UserProc,
newDesignName: PW.ROPENIL,
cmd: Commander.Handle ← NIL]
RETURNS[cellName: PW.ObjName] = {
design: CD.Design;
length: INT ← 0;
size: Size;
viewer: ViewerClasses.Viewer;
vmold, vmnew: WatchStats.WatchStatsRecord;
cellList: LIST OF PW.ROPENIL;
WITH ref SELECT FROM
designFile: Rope.ROPE => design ← CDIO.ReadDesign[designFile];
designRef: CD.Design => design ← designRef;
ENDCASE      => ERROR;
RegisterDesignWithPW[design];
viewer ← CDViewer.CreateViewer[design];
ViewerOps.ChangeColumn[viewer, color];
PWBasics.Output[ IO.PutFR["\n\n%g\n", IO.time[]]];
vmold ← WatchStats.GetWatchStats[];
FOR rowProc ← rowProc, rowProc.rest WHILE rowProc#NIL DO
cellN: PW.ROPE;
obj: CD.ObPtr;
IF rowProc.first=NIL THEN LOOP;
cellN  ← rowProc.first[design];
obj  ← CDDirectory.Fetch[design, cellN].object;
size  ← PWBasics.GetISize[obj];
length ← length + size.y;
cellList ← CONS[cellN, cellList];
vmnew ← WatchStats.GetWatchStats[];
PWBasics.Output[IO.PutFR["\n %5g %5g %5g %g",
IO.int[length/2],
IO.int[size.y/2],
IO.int[vmold.vmFree - vmnew.vmFree],
IO.rope[cellN] ] ];
vmold ← vmnew;
ENDLOOP;
 cellName ← AbutListY[design, cellList ];
PWBasics.Output[ IO.PutFR["\n%g\n", IO.time[]]];
IF newDesignName # NIL THEN { -- Called from Command Tool
write: BOOLIF cmd=NIL OR cmd.commandLine=NIL
THEN FALSE ELSE IF Rope.Find[cmd.commandLine,"-w",0,FALSE]=-1
THEN FALSE ELSE TRUE;
print: BOOLIF cmd.commandLine=NIL
THEN FALSE ELSE IF Rope.Find[cmd.commandLine,"-p",0,FALSE]=-1
THEN FALSE ELSE TRUE;
newCellName: PW.ROPE ← newDesignName.Cat["Cell"];
obPtr: CD.ObPtr ← CDDirectory.Fetch[design, cellName].object;
IF obPtr= NIL THEN ERROR;
IF CDDirectory.Rename[design, obPtr, newCellName, TRUE].done
THEN cellName ← newCellName
ELSE cellName ← PW.ReName[cellName, newCellName];
obPtr ← CDDirectory.Fetch[design, cellName].object;
size ← PWBasics.GetISize[obPtr];
CDOps.SetAppList[design, NIL];
CDOps.AddAnObject[design, obPtr, [0, 0]];
RepositionDesignViewer[design, viewer];
PWBasics.Output[cellName]; PWBasics.Output[" included in design\n\n" ];
IF write THEN WriteOutNewDesign[design, newDesignName];
IF print THEN PlotDesign[design, size]};
RETURN[cellName]};
Register: PUBLIC PROC [userProc: UserProc, name: ROPE] = {PW.Register[userProc, name]};
ByteBitFromIndex: PUBLIC PROC[index: INT, seq: BOOL]
RETURNS[byte, bit: INT] = {
byte ← IF seq THEN index / rngBit ELSE index MOD rngByte;
bit  ← IF seq THEN index MOD rngBit ELSE index / rngByte };
ByteBitToIndex: PUBLIC PROC[byte, bit: INT, seq: BOOL]
RETURNS[index: INT] = {
RETURN[IF seq
THEN byte * rngBit  + bit
ELSE bit  * rngByte + byte]};
RepositionDesignViewer: PUBLIC PROC[design: CD.Design, viewer: ViewerClasses.Viewer] =
{CDViewer.ShowAndScale[viewer, CDExtras.BoundingBox[design]]};
PlotDesign: PUBLIC PROC[design: CD.Design, pos, sPos: Location ← [0, 0]] = {
command: CDSequencer.Command ← NEW[CDSequencer.CommandRec ←
[design: design, pos: pos, sPos: sPos, a: $VersatecAutoPlot]];
CDSequencer.ExecuteCommand[command, design, $VersatecAutoPlot]};
AssignRowPinsAndRename: PUBLIC PROC[
design:  CD.Design,
rowName:  PW.ObjName,
newName: PW.ObjName,
identity:  BOOL   ← TRUE,
top:   LIST OF REF ← NIL,
bot:   LIST OF REF ← NIL,
ctl:   List   ← NIL,
seq:   BOOL   ← FALSE ]
RETURNS[cellName: PW.ObjName] = {
AssignNames: PinNameProc = {
oldPinName: PW.ROPE ← CDPinObjects.GetName[pin];
IF identity THEN RETURN[oldPinName];
SELECT side FROM
LtSide, RtSide  => {
IF oldPinName.Find[VDD]>=0 THEN RETURN[oldPinName];
IF oldPinName.Find[GND]>=0 THEN RETURN[oldPinName];
name ← ListIndexItem[ctl, Convert.IntFromRope[oldPinName]]};
TopSide, BotSide => {
list:  List;
byte, bit: INT;
column: INT ← ((pin.location.x MOD cellWidth)-leftTail)/metPitch;
[byte, bit]  ← ByteBitFromIndex[pin.location.x/cellWidth, seq];
list    ← ExpandList[byte, bit, IF side=TopSide THEN top ELSE bot];
list    ← FixGVInList[list];
name    ← ListIndexItem[list, column];
IF name=NIL THEN ERROR};
ENDCASE   => ERROR};
cellName ← RenamePins[design, rowName, newName, AssignNames]};
PinNameProc: TYPE = PROC[pin: CD.ApplicationPtr, side: Side]
RETURNS[name: PW.ObjName];
RenamePins: PUBLIC PROC[
design:   CD.Design,
refObjName:  PW.ObjName,
newObjName: PW.ObjName,
pinNameProc: PinNameProc]
RETURNS [cellName: PW.ObjName] = {
KeepPinOnEdge: CDPinObjects.AppEnumerator = {
newRope: PW.ROPE;
newApp: CD.ApplicationPtr;
side: Side;
isOnBorder: BOOL;
[isOnBorder, side] ← PWPins.GetSide[refObj, app];
IF ~isOnBorder THEN RETURN;
newRope ← pinNameProc[app, side];
IF Rope.IsEmpty[newRope] THEN RETURN;
newApp ← NEW[CD.Application ← [
ob: CDPinObjects.CreatePinOb[app.ob.size],
location: app.location, orientation: app.orientation,
properties: CDProperties.CopyProps[app.properties]]];
CDPinObjects.SetName[newApp, newRope];
newCellPtr.contents ← CONS[newApp, newCellPtr.contents];
};
refObj:  CD.ObPtr ← CDDirectory.Fetch[design, refObjName].object;
newObj:  CD.ObPtr ← NIL;
newCellPtr: CD.CellPtr;
app:   CD.ApplicationPtr ← NEW[CD.Application ← [ob: refObj]];
CDProperties.PutPropOnApplication[app, $StopEnumerateDeepPins, $StopEnumerateDeepPins];
newObj  ← CDCells.CreateEmptyCell[];
newCellPtr ← NARROW[newObj.specificRef];
[] ← PWPins.EnumerateDeepPins[refObj, KeepPinOnEdge];
newCellPtr.contents ← CONS[app, newCellPtr.contents];
CDCells.SetInterestRect[newObj, CD.InterestRect[refObj]];
[] ← PWBasics.RepositionCell[design, newObj, newObjName];
cellName ← CDDirectory.Name[newObj];
RETURN[cellName] };
FillerCell: PUBLIC PROC
[design: CD.Design, obj: CD.ObPtr, objSide: Side, width: INT, copyPins: BOOLFALSE]
RETURNS [cell: CD.ObPtr] = {
KeepPinOnEdge: PWPins.AppEnumerator = {
isOnIt: BOOL;
side:  Side;
layer:  CD.Layer ← CDPinObjects.GetLayer[app];
name:  PW.ROPE ← CDPinObjects.GetName[app];
[isOnIt, side] ← PWPins.GetSide[obj, app];
IF ~isOnIt OR side#objSide THEN RETURN[FALSE];
SELECT side FROM
TopSide, BotSide => {
locX: INT ← app.location.x-rRect.x1;
AddRet[cell, [app.ob.size.x, width], [locX, 0], layer];
IF copyPins THEN {
PutPin[cell, [app.ob.size.x, pinDim], [locX, 0],     layer, name];
PutPin[cell, [app.ob.size.x, pinDim], [locX, width-pinDim], layer, name]}};
ENDCASE => {
locY: INT ← app.location.y-rRect.y1;
AddRet[cell, [width, app.ob.size.y], [0, locY], layer];
IF copyPins THEN {
PutPin[cell, [pinDim, app.ob.size.y], [0,    locY], layer, name];
PutPin[cell, [pinDim, app.ob.size.y], [width-pinDim, locY], layer, name]}}};
rRect, fRect: CD.Rect;
pinDim: INTMIN[8, width/2]; IF copyPins AND pinDim = 0 THEN ERROR;
cell ← CDCells.CreateEmptyCell[];
rRect ← CD.InterestRect[obj];
fRect ← SELECT objSide FROM
TopSide, BotSide => [0, 0, rRect.x2-rRect.x1, width],
LtSide, RtSide => [0, 0, width, rRect.y2-rRect.y1],
ENDCASE => ERROR;
CDCells.SetInterestRect[cell, fRect];
[] ← PWPins.EnumerateDeepPins[obj, KeepPinOnEdge];
[] ← PWBasics.RepositionCell[design, cell, "Filler"] };
END.