IFUPWAdder.mesa
Copyright c 1985 by Xerox Corporation. All rights reserved.
Last Edited by Curry, November 20, 1985 3:42:02 pm PST
DIRECTORY
Basics,
CD,
CDCells,
CDDirectory,
Convert,
IFUPW,
PW,
Rope;
IFUPWAdder: CEDAR PROGRAM
IMPORTS CD, CDCells, CDDirectory, Convert, IFUPW, PW, Rope
EXPORTSIFUPW =
BEGIN
List: TYPE = IFUPW.List;
ROPE: TYPE = Rope.ROPE;
IFUAdderRow: PUBLIC PROC[
design:   CD.Design,
name:    Rope.ROPE,
leftCtl:   List    ← NIL,
rightCtl:   List    ← NIL,
top:    LIST OF REF  ← NIL,
in:     LIST OF REF  ← NIL,
out:    LIST OF REF  ← NIL,
bot:    LIST OF REF  ← NIL,
sums:    INT    ← 1,
rp:     IFUPW.RowParams ← IFUPW.IFUDataColNSeq ]
RETURNS[cell: CD.Object]= { -- positive bus on top
controlOnRt: BOOL ← leftCtl=NIL;
controlOnTop: BOOLPW.ODD[PW.Log2[rp.rngByte*rp.rngBit/sums]];
wdA: InterfaceWdLIST;
wdIn: LIST OF List;
list1, list2: LIST OF REFNIL;
ctls:     IFUPW.List ← NIL;
cellList, mainList: PW.ListOb ← NIL;
size: IFUPW.Size;
gpcRow, sumRow, refCell, met2Box, polyBox, switchbox: CD.Object;
[wdA, wdIn] ← GenInterleavedSplitTreeNames
[sums, (IF rp.seq THEN rp.rngByte ELSE 1), rp];
FOR ii: INT DECREASING IN [0..sums) DO
ctls ← CONS[Rope.Cat["C", Convert.RopeFromInt[ii]], ctls] ENDLOOP;
list1 ← list2 ← NIL;
list2 ← ConsGPCCopyOnLIST [rp, list2, wdA[top][lng][rt], FALSE, TRUE, FALSE];
list2 ← ConsGPCCopyOnLIST [rp, list2, wdA[top][lng][lt], FALSE, TRUE, FALSE];
list2 ← ConsNILsOnLIST  [8, list2];
met2Box ← IFUPW.SwitchBoxRow[
design: design,
name:  name.Cat["TopMet2"],
rowType: IFUPW.cmosMet2,
topRP:  rp,
top:  list1,
left:  IF controlOnTop AND ~controlOnRt THEN ctls ELSE NIL,
right:  IF controlOnTop AND controlOnRt THEN ctls ELSE NIL,
bot:  list2,
botRP:  rp ];
list1 ← list2 ← NIL;
list2 ← ConsGPCCopyOnLIST [rp, list2, wdA[top][srt][rt], FALSE, TRUE, FALSE];
list2 ← ConsGPCCopyOnLIST [rp, list2, wdA[top][srt][lt], FALSE, TRUE, FALSE];
list2 ← ConsNILsOnLIST  [8, list2];
polyBox ← IFUPW.SwitchBoxRow[
design: design,
name:  name.Cat["TopPoly"],
rowType: IFUPW.cmosPoly,
topRP:  rp,
top:  list1,
left:  NIL,
right:  NIL,
bot:  list2,
botRP:  rp,
m2Pitch: TRUE ];
switchbox ← ShiftMergeFill[design, polyBox, met2Box, name.Cat["SwitchTop"]];
mainList ← CONS[switchbox, mainList];
cellList ← NIL;
FOR index: INT DECREASING IN [0..rp.rngByte*rp.rngBit) DO
byte, bit, numIndex, level: INT ← 0;
[byte, bit] ← IFUPW.ByteBitFromIndex[index, rp];
numIndex ← (byte*8+bit) MOD (rp.rngByte*rp.rngBit/sums);
FOR val: INT ← numIndex, val/2 WHILE (val MOD 2) = 1 DO level ← level+1 ENDLOOP;
cellList ← CONS[
(IF numIndex+1 = (rp.rngByte*rp.rngBit/sums)
THEN CDDirectory.Fetch[design, "GPAdderGPCBlank"].object
ELSE IF (level MOD 2)=0
THEN CDDirectory.Fetch[design, "GPAdderGPC0"].object
ELSE CDDirectory.Fetch[design, "GPAdderGPC1"].object),
cellList];
ENDLOOP;
gpcRow ← PW.AbutListX[design, cellList];
PW.RenameObject[design, gpcRow, name.Cat["GPC"]];
mainList ← CONS[gpcRow, mainList];
list1 ← list2 ← NIL;
list1 ← ConsGPCCopyOnLIST [rp, list1, wdA[bot][lng][rt]];
list1 ← ConsGPCCopyOnLIST [rp, list1, wdA[bot][lng][lt]];
list1 ← ConsNILsOnLIST   [8,  list1];
met2Box ← IFUPW.SwitchBoxRow[
design: design,
name:  name.Cat["BotMet2"],
rowType: IFUPW.cmosMet2,
topRP:  rp,
top:  list1,
left:  IF ~controlOnTop AND ~controlOnRt THEN ctls ELSE NIL,
right:  IF ~controlOnTop AND controlOnRt THEN ctls ELSE NIL,
bot:  list2,
botRP:  rp ];
list1 ← list2 ← NIL;
list1 ← ConsGPCCopyOnLIST [rp, list1, wdA[bot][srt][rt]];
list1 ← ConsGPCCopyOnLIST [rp, list1, wdA[bot][srt][lt]];
list1 ← ConsNILsOnLIST  [8,  list1];
list2 ← ConsGPCCopyOnLIST [rp, list2, wdIn];
list2 ← ConsNILsOnLIST  [8, list2];
polyBox ← IFUPW.SwitchBoxRow[
design: design,
name:  name.Cat["BotPoly"],
rowType: IFUPW.cmosPoly,
topRP:  rp,
top:  list1,
left:  NIL,
right:  NIL,
bot:  list2,
botRP:  rp,
m2Pitch: TRUE ];
switchbox ← ShiftMergeFill[design, polyBox, met2Box, name.Cat["SwitchBot"]];
mainList ← CONS[switchbox, mainList];
cellList ← NIL;
FOR index: INT DECREASING IN [0..rp.rngByte*rp.rngBit) DO
cellList ← CONS[CDDirectory.Fetch[design, "GPAdderSum"].object, cellList] ENDLOOP;
sumRow ← PW.AbutListX[design, cellList];
PW.RenameObject[design, sumRow, name.Cat["XOR"]];
mainList ← CONS[sumRow, mainList];
sumRow ← PW.AbutListY[design, mainList];
size ← CD.InterestSize[sumRow];
cell ← CDCells.CreateEmptyCell[];
[]←PW.IncludeInCell[cell, sumRow];
refCell ← CDDirectory.Fetch[design, "GPAdderSum"].object;
FOR index: INT IN [0..rp.rngBit) DO
FOR byte: INT IN [0..rp.rngByte) DO
refX: INTIFUPW.cellWidth*IFUPW.ByteBitToIndex[byte, index, rp];
topl: IFUPW.List ← IFUPW.FixGVInList[IFUPW.ExpandList[byte, index, top]];
botl: IFUPW.List ← IFUPW.FixGVInList[IFUPW.ExpandList[byte, index, bot]];
inl: IFUPW.List ← IFUPW.ExpandList[byte, index, in];
outl: IFUPW.List ← IFUPW.ExpandList[byte, index, out];
IF outl = NIL OR outl.first = NIL THEN inl ← outl ← NIL;
IFUPW.IOConnect[
design: design,
cell:  cell,
top:  topl,
in:   inl,
out:  outl,
bot:  botl,
refcell: refCell,
refX:  refX,
refY:  0,
topY:  size.y,
botY:  0 ];
IFUPW.AddMetalPins[cell, topl, botl, refX, size.y, 0, TRUE];
ENDLOOP;
ENDLOOP;
PW.IncludeInDirectory[design, cell];
cell ← IFUPW.RenameObjAndAssignRowPins
[design, cell, name, FALSE, top, bot, leftCtl, rightCtl, rp]};
PW.RenameObject[design, cell, name]};
TopBot: TYPE = {top,  bot};
LngSrt: TYPE = {lng,  srt};
LtRt:  TYPE = {lt,  rt};
InterfaceWdLIST: TYPE =
ARRAY TopBot OF
ARRAY LngSrt OF
ARRAY LtRt OFLIST OF List ← ALL[ALL[ALL[NIL]]];
InterfaceByteLIST: TYPE =
ARRAY TopBot OF
ARRAY LngSrt OF
ARRAY LtRt OF List ← ALL[ALL[ALL[NIL]]];
InterfaceNameLIST: TYPE =
ARRAY TopBot OF
ARRAY LngSrt OF
ARRAY LtRt OF ROPEALL[ALL[ALL[NIL]]];
GenInterleavedSplitTreeNames: PROC[
nofResults: INT,   -- rngByte,
longThres: INT,   -- rngByte,    differences <= to this are short wires
rp:    IFUPW.RowParams] -- IFUDataColNSeq  implies partitioning of result lists
RETURNS[wdA: InterfaceWdLIST, wdIn: LIST OF List] = {
AddIndices: PROC[rope: ROPE, int1, int2: INT] RETURNS[ROPE] = {
rope ← IFUPW.AppendIndexToRope[int1, rope];
rope ← IFUPW.AppendIndexToRope[int2, rope];
RETURN[rope]};
insOnTop: BOOLFALSE;
secLength: INT ← (rp.rngByte * rp.rngBit) / nofResults;
FOR byte: INT DECREASING IN [0..rp.rngByte) DO
byteA: InterfaceByteLIST; byteIn: List ← NIL;
FOR bit: INT DECREASING IN [0..rp.rngBit) DO
longWire: BOOLTRUE;
nameA: InterfaceNameLIST; nameIn: ROPENIL;
size: INT ← 1; -- will be length of output
level: INT ← 0;
section: INT ← ((byte * rp.rngBit) + bit) / secLength;
index:  INT ← ((byte * rp.rngBit) + bit) MOD secLength;
topln, botln: LngSrt;
FOR val: INT ← index, val/2 WHILE (val MOD 2) = 1
DO level ← level+1; size ← size*2 ENDLOOP;
topln ← IF size/2 > longThres THEN lng ELSE srt;
botln ← IF size  > longThres THEN lng ELSE srt;
nameIn       ← AddIndices["In.", section, index];
SELECT size FROM
1    => {
nameA[top][topln][lt] ← AddIndices["In.", section, index];
nameA[top][topln][rt] ← AddIndices["In.", section, index+1];
nameA[bot][botln][rt] ← AddIndices["Xx.", section, index]};
secLength/2 =>{
nameA[top][topln][lt] ← AddIndices["Xx.", section, index - size/2];
nameA[top][topln][rt] ← AddIndices["Xx.", section, index + size/2];
nameA[bot][botln][rt] ← Convert.RopeFromInt[section,36,FALSE]};
secLength => NULL;
ENDCASE => {
nameA[top][topln][lt] ← AddIndices["Xx.", section, index - size/2];
nameA[top][topln][rt] ← AddIndices["Xx.", section, index + size/2];
nameA[bot][botln][rt] ← AddIndices["Xx.", section, index]};
IF (level MOD 2 =1) = insOnTop THEN
FOR ls: LngSrt IN LngSrt DO FOR lr: LtRt IN LtRt DO
temp: ROPE ← nameA[bot][ls][lr];
nameA[bot][ls][lr] ← nameA[top][ls][lr];
nameA[top][ls][lr] ← temp; ENDLOOP ENDLOOP;
byteIn ← CONS[nameIn, byteIn];
FOR tb: TopBot IN TopBot DO FOR ls: LngSrt IN LngSrt DO FOR lr: LtRt IN LtRt DO
byteA[tb][ls][lr] ← CONS[nameA[tb][ls][lr], byteA[tb][ls][lr]];
ENDLOOP ENDLOOP ENDLOOP;
ENDLOOP;
wdIn  ← CONS[byteIn,  wdIn];
FOR tb: TopBot IN TopBot DO FOR ls: LngSrt IN LngSrt DO FOR lr: LtRt IN LtRt DO
wdA[tb][ls][lr] ← CONS[byteA[tb][ls][lr], wdA[tb][ls][lr]]
ENDLOOP ENDLOOP ENDLOOP;
ENDLOOP };
ConsGPCCopyOnLIST: PROC
[rp: IFUPW.RowParams, list: LIST OF REF, ref: LIST OF List, gout, cout, pout: BOOLFALSE]
RETURNS[new: LIST OF REF] = {
new ← CONS[CopyModifiedLIST[ref: ref, rope: "C", shortRopes: cout, rp: rp], list];
new ← CONS[CopyModifiedLIST[ref: ref, rope: "P", shortRopes: pout, rp: rp], new];
new ← CONS[CopyModifiedLIST[ref: ref, rope: "G", shortRopes: gout, rp: rp], new]};
CopyModifiedLIST: PROC
[ref: LIST OF List, rope: Rope.ROPE, shortRopes: BOOL, rp: IFUPW.RowParams]
RETURNS[new: LIST OF List] = {
LISTIndexItem: PROC [list: LIST OF List, index: INT] RETURNS[item: List] = {
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]};
new ← NIL;
FOR i1: INT DECREASING IN [0..rp.rngByte) DO
rlist: List ← LISTIndexItem[ref, i1];
nlist: List ← NIL;
FOR i2: INT DECREASING IN [0..8) DO
rrope: Rope.ROPEIFUPW.ListIndexItem[rlist, i2];
rrope ← IF rrope = NIL OR rrope.Length[]=0 OR (rrope.Length[]<3 AND ~shortRopes)
THENNIL
ELSE rope.Cat[rrope];
nlist ← CONS[rrope, nlist];
ENDLOOP;
new ← CONS[nlist, new];
ENDLOOP};
ConsNILsOnLIST: PROC[count: INT, list: LIST OF REF]
RETURNS[new: LIST OF REF] = {
new ← list;
FOR count ← count, count-1 WHILE count#0 DO new ← CONS[NIL, new] ENDLOOP};
ShiftMergeFill: PROC
[design: CD.Design, lrgObj, smlObj: CD.Object, name: ROPE]
RETURNS[cell: CD.Object] = {
lrgRect:  IFUPW.Size ← CD.InterestSize[lrgObj];
smlRect:  IFUPW.Size ← CD.InterestSize[smlObj];
diff:   INT    ← lrgRect.y - smlRect.y;
fillerTop:  CD.Object   ← NIL;
fillerBot:  CD.Object   ← NIL;
cell  ← CDCells.CreateEmptyCell[];
IF diff<9
THEN {
IF diff#0 THEN ERROR;
fillerTop  ← IFUPW.FillerCell[design, lrgObj, top, 3*9, FALSE];
fillerBot  ← IFUPW.FillerCell[design, smlObj, bottom, 3*9, FALSE];
smlObj  ← PW.AbutListY[design, LIST [fillerBot, smlObj]];
lrgObj  ← PW.AbutListY[design, LIST [lrgObj, fillerTop]]}
ELSE {
fillerTop  ← IFUPW.FillerCell[design, smlObj, top,   9, FALSE];
fillerBot  ← IFUPW.FillerCell[design, smlObj, bottom, diff - 9, FALSE];
smlObj  ← PW.AbutListY[design, LIST [fillerBot, smlObj, fillerTop]]};
[]←PW.IncludeInCell[cell, smlObj];
[]←PW.IncludeInCell[cell, lrgObj];
PW.IncludeInDirectory[design, cell, name];
RETURN[cell] };
Adder32x1x1:  IFUPW.UserProc = {RETURN[ IFUAdderRow[
design:   design,
name:    "AdderTest",
ctl:    NIL,
top:    LIST["XBus.", "SumLt.", "SumRt."],
in:     LIST["SumLt.", "SumRt."],
out:    LIST["Sum."],
bot:    LIST["XBus.", "Sum."],
sums:    1,
rp:     IFUDataColNSeq ]]};
Adder32x1x1Seq:  IFUPW.UserProc = {RETURN[ IFUAdderRow[
design:   design,
name:    "AdderTest",
ctl:    NIL,
top:    LIST["XBus.", "SumLt.", "SumRt."],
in:     LIST["SumLt.", "SumRt."],
out:    LIST["Sum."],
bot:    LIST["XBus.", "Sum."],
sums:    1,
rp:     IFUDataColSeq ]]};
Adder32x4x4:  IFUPW.UserProc = {RETURN[ IFUAdderRow[
design:   design,
name:    "AdderTest",
ctl:    NIL,
top:    LIST["XBus.", "SumLt.", "SumRt."],
in:     LIST["SumLt.", "SumRt."],
out:    LIST["Sum."],
bot:    LIST["XBus.", "Sum."],
sums:    4,
rp:     IFUDataColNSeq ]]};
IFUPW.Register[Adder32x1x1,   "Adder32x1x1"];
IFUPW.Register[Adder32x1x1Seq,  "Adder32x1x1Seq"];
IFUPW.Register[Adder32x4x4,   "Adder32x4x4"];
END.