IFUPWImpl:
CEDAR
PROGRAM
IMPORTS CD, CDCells, CDExtras, CDFrame, CDIO, CDOps, CDPinObjects, CDProperties, CDRects, CDSequencer, CDSil, CDSimpleOps, CDViewer, Convert, IO, IFUPW, PW, PWPins, Rope
EXPORTS IFUPW =
BEGIN OPEN IFUPW;
Error: PUBLIC ERROR[msg: ROPE] = CODE;
log: PUBLIC IO.STREAM ← CDFrame.GetLog[];
GND: PUBLIC Rope.ROPE ← "GND";
VDD: PUBLIC Rope.ROPE ← "VDD";
IFUDataColSeq: PUBLIC RowParams ← NEW[RowParamsRec ← [seq: TRUE] ];
IFUDataColNSeq: PUBLIC RowParams ← NEW[RowParamsRec ← [seq: FALSE] ];
ChangePinName:
PUBLIC
PROC[obj:
CD.Object, oldName, newName:
ROPE] = {
pins: CD.InstanceList ← 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.Object]
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.Object,
top: List,
in: List,
out: List,
bot: List,
refcell: CD.Object,
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.Object;
IF ~Same[idx, tIdx] AND ~Same[idx, bIdx] THEN RETURN;
wLoc.y ← connSpec[idx].y;
ctct ← Contact[cmosPoly];
wire ← CDRects.CreateRect[[wLen, polW], cmosPoly];
[] ←
PW.IncludeInCell[cell, ctct,
[wLoc.x-(cnctSize-metW)/2, wLoc.y-(cnctSize-polW)/2]];
[] ← PW.IncludeInCell[cell, wire, wLoc] };
wLen: INT ← (nofVWires-1-i)*metPitch + cnctSize;
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.Object, top, bot: List, refX, topY, botY: INT, realNames: BOOL] = {
length: INT ← MAX[ListLength[top], ListLength[bot]];
FOR i:
INT
IN [0..length)
DO
tName: ROPE ← ListIndexItem[top, i];
bName: ROPE ← ListIndexItem[bot, i];
size: Size ← [metW, metW];
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 };
AddRet:
PUBLIC
PROC [cell:
CD.Object, 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;
[] ← PW.IncludeInCell[cell, CDRects.CreateRect[size, level], loc]};
PutPin:
PUBLIC
PROC[cell:
CD.Object, size:Size, loc:Location, level:
CD.Layer, name:
ROPE] = {
pinApl:
CD.Instance
← PW.IncludeInCell[cell, CDPinObjects.CreatePinOb[size], loc];
CDPinObjects.SetName[pinApl, name];
CDPinObjects.SetLayer[pinApl, level]};
SizeOf: PUBLIC PROC[design: CD.Design, cell: CD.Object] RETURNS[size: Size] = {
RETURN[CD.InterestSize[cell ] ]};
Merge: PUBLIC PROC[design: CD.Design, side: Side, cell1, cell2: PW.ObjName]
RETURNS[cell: PW.ObjName] = {
obj: CD.Object ← CDCells.CreateEmptyCell[];
obj1: CD.Object ← PWBasics.ObjFromName[design, cell1];
obj2: CD.Object ← PWBasics.ObjFromName[design, cell2];
size1: Size ← CD.InterestSize[obj1];
size2: Size ← CD.InterestSize[obj2];
[ ] ← PW.IncludeInCell[obj, obj1, [0, 0]];
SELECT side FROM
top => [ ] ← PW.IncludeInCell[obj, obj2, [0, size1.y-size2.y]];
bottom => [ ] ← PW.IncludeInCell[obj, obj2, [0, 0]];
right => [ ] ← PW.IncludeInCell[obj, obj2, [0, size1.x-size2.x]];
left => [ ] ← PW.IncludeInCell[obj, obj2, [0, 0]];
ENDCASE;
PW.IncludeInDirectory[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: 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: 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:
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:
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: ROPE ← NIL ]
RETURNS[list: List] = {
refs:
ARRAY [0..16)
OF
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};
ListConcat:
PUBLIC
PROC [list1, list2: List]
RETURNS[new: List] = {
FOR i:
INT
DECREASING
IN [0..ListLength[list2])
DO
new ← CONS[ ListIndexItem[list2, i], new] ENDLOOP;
FOR i:
INT
DECREASING
IN [0..ListLength[list1])
DO
new ← CONS[ ListIndexItem[list1, i], new] 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:
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:
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:
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:
ROPE]
-- If last char is '.
RETURNS[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: 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] ]};
UniqueIndex: INT ← 0;
UniqueCellName:
PUBLIC
PROC[type:
ROPE, top, bot, ins, outs: List]
RETURNS[name: ROPE] = {
Index:
PROC[rope:
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: ROPE ← ListIndexItem[top, ii];
botN: 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 };
WriteOutNewDesign:
PUBLIC
PROC[design:
CD.Design, newName:
ROPE] = {
CDSimpleOps.RenameDesign[design, newName];
[ ] ← CDIO.WriteDesign[design, newName] };
GetDesign:
PUBLIC
PROC[ref:
REF]
RETURNS[design:
CD.Design] = {
WITH ref
SELECT
FROM
text: REF TEXT => design ← CDIO.ReadDesign[Rope.FromRefText[text]];
designFile: Rope.ROPE => design ← CDIO.ReadDesign[designFile];
designRef: CD.Design => design ← designRef;
ENDCASE => ERROR};
NFS, NewFrameSeq:
PUBLIC
PROC[
module: ROPE,
xory: XorY,
listTopLt: LIST OF Frame,
orient: CD.Orientation ← CD.original ]
RETURNS[frame: Frame] = {
count: INT ← 0;
FOR list:
LIST
OF Frame ← listTopLt, list.rest
WHILE list #
NIL
DO
IF list.first=NIL THEN LOOP;
count ← count+1 ENDLOOP;
frame ← NEW[CDFrame.FrameSeq[count]];
frame.xory ← xory;
frame.orient ← orient;
frame.shell ← NEW[CDFrame.ShellRec ← [name: module]];
count ← (IF xory=x THEN 0 ELSE count-1);
FOR list:
LIST
OF Frame ← listTopLt, list.rest
WHILE list #
NIL
DO
IF list.first=NIL THEN LOOP;
frame[count] ← list.first;
count ← count + (IF xory=x THEN 1 ELSE -1) ENDLOOP};
NFSFUP, NewFrameSeqFromListUserProc:
PUBLIC
PROC[
module: ROPE,
xory: XorY,
listTopLt: LIST OF UserProc,
orient: CD.Orientation ← CD.original ]
RETURNS[frame: Frame] = {
count: INT ← 0;
FOR list:
LIST
OF UserProc ← listTopLt, list.rest
WHILE list #
NIL
DO
IF list.first=NIL THEN LOOP;
count ← count+1 ENDLOOP;
frame ← NEW[CDFrame.FrameSeq[count]];
frame.xory ← xory;
frame.orient ← orient;
frame.shell ← NEW[CDFrame.ShellRec ← [name: module]];
count ← (IF xory=x THEN 0 ELSE count-1);
FOR list:
LIST
OF UserProc ← listTopLt, list.rest
WHILE list #
NIL
DO
refProc: REF UserProc ← NEW[UserProc ← list.first];
IF list.first=NIL THEN LOOP;
frame[count] ← NEW[CDFrame.FrameSeq[0]];
frame[count].data ← refProc;
count ← count + (IF xory=x THEN 1 ELSE -1) ENDLOOP};
ShowObject:
PUBLIC
PROC[cell:
CD.Object] = {
design: CD.Design ← CDOps.CreateDesign[IFUPW.cmos];
viewer: ViewerClasses.Viewer ← CDViewer.CreateViewer[design];
CDOps.AddAnObject[design, cell, [0, 0]];
CDViewer.ShowAndScale[viewer, CDExtras.BoundingBox[design]]};
Show5Objects:
PUBLIC PROC [bottom, right, top, left, middle:
CD.Object] = {
design: CD.Design ← CDOps.CreateDesign[IFUPW.cmos];
viewer: ViewerClasses.Viewer ← CDViewer.CreateViewer[design];
maxX:
INT ←
MAX[
IF top=NIL THEN 0 ELSE CD.InterestSize[top].x,
IF bottom=NIL THEN 0 ELSE CD.InterestSize[bottom].x];
maxY:
INT ←
MAX[
IF left=NIL THEN 0 ELSE CD.InterestSize[left].y,
IF right=NIL THEN 0 ELSE CD.InterestSize[right].y];
CDOps.SetInstList[design, NIL];
CDOps.AddAnObject[design, left, [-CD.InterestSize[left].x, 0]];
CDOps.AddAnObject[design, bottom, [0, -CD.InterestSize[bottom].y]];
CDOps.AddAnObject[design, top, [0, maxY]];
CDOps.AddAnObject[design, right, [maxX, 0]];
CDOps.AddAnObject[design, middle, [0, 0]];
CDViewer.ShowAndScale[viewer, CDExtras.BoundingBox[design]]};
ShowFrameBlock:
PUBLIC PROC[frame: Frame] ~ {
designB: CD.Design ← CDOps.CreateDesign[CDSil.cdsil];
viewerB: ViewerClasses.Viewer ← CDViewer.CreateViewer[designB];
cellB: CD.Object ← CDFrame.FrameToObject[frame, designB, FALSE];
CDSimpleOps.RenameDesign[designB, "ShowFrameBlock"];
CDOps.AddAnObject[designB, cellB, [0, 0]];
RepositionDesignViewer[designB, viewerB]};
AssembleFrame:
PUBLIC
PROC[
ref: REF,
frame: REF CDFrame.FrameSeq,
cmd: Commander.Handle,
name: ROPE ← NIL ] = {
design, designB: CD.Design;
cell, cellB: CD.Object;
done: BOOL ← FALSE;
impl: BOOL ← TRUE;
block: BOOL ← TRUE;
write: BOOL ← FALSE;
plot: BOOL ← FALSE;
IF name=NIL AND frame.shell#NIL THEN name ← frame.shell.name;
IF frame.shell=
NIL
OR
NOT Rope.Equal[frame.shell.name, name]
THEN {
FOR index:
INT
IN [0..frame.seqSize)
DO
AssembleFrame[ref, frame[index], cmd, name] ENDLOOP;
RETURN};
design ← GetDesign[ref];
IF cmd#
NIL
AND cmd.commandLine#
NIL
THEN {
IF Rope.Find[cmd.commandLine,"-i", 0,FALSE]#-1 THEN impl ← NOT impl;
IF Rope.Find[cmd.commandLine,"-b", 0,FALSE]#-1 THEN block ← NOT block;
IF Rope.Find[cmd.commandLine,"-w", 0,FALSE]#-1 THEN write ← NOT write;
IF Rope.Find[cmd.commandLine,"-p", 0,FALSE]#-1 THEN plot ← NOT plot };
IF impl
THEN {
viewer: ViewerClasses.Viewer ← CDViewer.CreateViewer[design];
CDSimpleOps.RenameDesign[design, name];
CDOps.SetInstList[design, NIL];
cell ← CDFrame.FrameToObject[frame, design];
CDOps.AddAnObject[design, cell, [0, 0]];
RepositionDesignViewer[design, viewer]};
IF block
THEN {
designB: CD.Design ← CDOps.CreateDesign[CDSil.cdsil];
viewerB: ViewerClasses.Viewer ← CDViewer.CreateViewer[designB];
CDSimpleOps.RenameDesign[designB, name.Cat["Block"]];
cellB ← CDFrame.FrameToObject[frame, designB];
CDOps.AddAnObject[designB, cellB, [0, 0]];
RepositionDesignViewer[designB, viewerB]};
IF cell=NIL THEN {cell ← cellB; design ← designB};
IF write THEN WriteOutNewDesign[design, name];
IF plot
THEN PlotDesign[design, [0,0],
CD.InterestSize[cell]] };
Register: PUBLIC PROC [userProc: PWUserProc, name: ROPE] = {PW.Register[userProc, name]};
ByteBitFromIndex:
PUBLIC
PROC[index:
INT, rp: RowParams]
RETURNS[byte, bit: INT] = {
byte ← IF rp.seq THEN index / rp.rngBit ELSE index MOD rp.rngByte;
bit ← IF rp.seq THEN index MOD rp.rngBit ELSE index / rp.rngByte };
ByteBitToIndex:
PUBLIC
PROC[byte, bit:
INT, rp: RowParams]
RETURNS[index: INT] = {
RETURN[
IF rp.seq
THEN byte * rp.rngBit + bit
ELSE bit * rp.rngByte + byte]};
RepositionDesignViewer:
PUBLIC
PROC[design:
CD.Design, viewer: ViewerClasses.Viewer] =
{CDViewer.ShowAndScale[viewer, CDExtras.BoundingBox[design]]};
PlotDesign:
PUBLIC
PROC[design:
CD.Design, pos: Location, sPos: Size ← [0, 0]] = {
command: CDSequencer.Command ←
NEW[CDSequencer.CommandRec ←
[design: design, pos: pos, sPos: sPos, a: $VersatecAutoPlot]];
CDSequencer.ExecuteCommand[command, design, $VersatecAutoPlot]};
RenameObjAndAssignRowPins:
PUBLIC
PROC[
design: CD.Design,
row: CD.Object,
newObjName: ROPE,
identity: BOOL ← TRUE,
top: LIST OF REF ← NIL,
bot: LIST OF REF ← NIL,
leftCtl: List ← NIL,
rightCtl: List ← NIL,
rp: RowParams ← IFUDataColNSeq ]
RETURNS[newObject: CD.Object] = {
AssignNames: PinNameProc = {
oldPinName: ROPE ← CDPinObjects.GetName[pin];
IF identity THEN RETURN[oldPinName];
SELECT side
FROM
left => {
index: INT ← Rope.SkipTo[oldPinName, 0, "0123456789"];
IF oldPinName.Find[VDD]>=0 THEN RETURN[oldPinName];
IF oldPinName.Find[GND]>=0 THEN RETURN[oldPinName];
index ← Convert.IntFromRope[Rope.Substr[oldPinName, index]];
name ← ListIndexItem[leftCtl, index]};
right => {
index: INT ← Rope.SkipTo[oldPinName, 0, "0123456789"];
IF oldPinName.Find[VDD]>=0 THEN RETURN[oldPinName];
IF oldPinName.Find[GND]>=0 THEN RETURN[oldPinName];
index ← Convert.IntFromRope[Rope.Substr[oldPinName, index]] - ListLength[leftCtl];
name ← ListIndexItem[rightCtl, index]};
top, bottom => {
list: List;
byte, bit: INT;
column: INT ← ((pin.location.x MOD cellWidth)-leftTail)/metPitch;
[byte, bit] ← ByteBitFromIndex[pin.location.x/cellWidth, rp];
list ← ExpandList[byte, bit, IF side=top THEN top ELSE bot];
list ← FixGVInList[list];
name ← ListIndexItem[list, column];
IF name=NIL THEN ERROR};
ENDCASE => ERROR};
newObject ← RenameObjAndPins[design, row, newObjName, AssignNames]};
RenameObjAndPins:
PUBLIC
PROC[
design: CD.Design,
object: CD.Object,
newObjName: ROPE,
pinNameProc: PinNameProc]
RETURNS[newObject: CD.Object] = {
KeepPinOnEdge: CDPinObjects.InstanceEnumerator = {
newRope: ROPE;
newInst: CD.Instance;
side: CDFrame.Side5;
side ← PWPins.GetSide[object, inst];
IF side=none THEN RETURN;
newRope ← pinNameProc[inst, side];
IF Rope.IsEmpty[newRope] THEN RETURN;
newInst ←
NEW[
CD.InstanceRep ← [
ob: CDPinObjects.CreatePinOb[inst.ob.size],
location: inst.location,
orientation: inst.orientation ]];
CDProperties.CopyProps[inst.properties, newInst];
CDPinObjects.SetName[newInst, newRope];
newCellPtr.contents ← CONS[newInst, newCellPtr.contents];
};
newCellPtr: CD.CellPtr;
inst: CD.Instance ← NEW[CD.InstanceRep ← [ob: object]];
CDProperties.PutPropOnInstance[inst, $StopEnumerateDeepPins, $StopEnumerateDeepPins];
newObject ← CDCells.CreateEmptyCell[];
newCellPtr ← NARROW[newObject.specificRef];
[] ← PWPins.EnumerateDeepPins[object, KeepPinOnEdge];
newCellPtr.contents ← CONS[inst, newCellPtr.contents];
CDCells.SetInterestRect[newObject, CD.InterestRect[object]];
PW.IncludeInDirectory[design, newObject, newObjName];
RETURN[newObject] };
FillerCell:
PUBLIC
PROC
[design: CD.Design, obj: CD.Object, objSide: Side, width: INT, copyPins: BOOL ← FALSE]
RETURNS [cell: CD.Object] = {
KeepPinOnEdge: PWPins.InstanceEnumerator = {
side: Side;
layer: CD.Layer ← CDPinObjects.GetLayer[inst];
name: ROPE ← CDPinObjects.GetName[inst];
side ← PWPins.GetSide[obj, inst];
IF side#objSide THEN RETURN[FALSE];
SELECT side
FROM
top, bottom => {
locX: INT ← inst.location.x-rRect.x1;
AddRet[cell, [inst.ob.size.x, width], [locX, 0], layer];
IF copyPins
THEN {
PutPin[cell, [inst.ob.size.x, pinDim], [locX, 0], layer, name];
PutPin[cell, [inst.ob.size.x, pinDim], [locX, width-pinDim], layer, name]}};
ENDCASE => {
locY: INT ← inst.location.y-rRect.y1;
AddRet[cell, [width, inst.ob.size.y], [0, locY], layer];
IF copyPins
THEN {
PutPin[cell, [pinDim, inst.ob.size.y], [0, locY], layer, name];
PutPin[cell, [pinDim, inst.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
top, bottom => [0, 0, rRect.x2-rRect.x1, width],
left, right => [0, 0, width, rRect.y2-rRect.y1],
ENDCASE => ERROR;
CDCells.SetInterestRect[cell, fRect];
[] ← PWPins.EnumerateDeepPins[obj, KeepPinOnEdge];
[] ← PW.IncludeInDirectory[design, cell, "Filler"] };
END.