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: INT ← MAX[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: CARDINAL ← LOOPHOLE[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: CARDINAL ← LOOPHOLE[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: BOOL ← FALSE;
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:
REF ←
NIL ]
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.ROPE ← NIL ]
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.ROPE ← NIL;
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#NIL THEN item2 ← AppendIndexToRope[index1, item1];
IF item2#NIL THEN 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#
NIL
DO
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#
NIL
DO
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.ROPE ← NIL,
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.ROPE ← NIL;
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:
BOOL ←
IF cmd=
NIL
OR cmd.commandLine=
NIL
THEN
FALSE
ELSE
IF Rope.Find[cmd.commandLine,"-w",0,
FALSE]=-1
THEN FALSE ELSE TRUE;
print:
BOOL ←
IF 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: BOOL ← FALSE]
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: INT ← MIN[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.