IFUPWAdder.mesa
Copyright c 1985 by Xerox Corporation. All rights reserved.
Last Edited by Curry, June 16, 1985 1:07:37 pm PDT
DIRECTORY
Basics,
CD,
CDCells,
CDDirectory,
CDPinObjects,
Convert,
CMos,
IFUPW,
PW,
PWBasics,
Rope;
IFUPWAdder: CEDAR PROGRAM
IMPORTSCD, CDCells, CDDirectory, CDPinObjects, Convert, IFUPW, PW, PWBasics, Rope
EXPORTSIFUPW =
BEGIN
List: TYPE = IFUPW.List;
ROPE: TYPE = Rope.ROPE;
IFUAdderRow: PUBLIC PROC[
design:   CD.Design,
name:    Rope.ROPE,
ctl:    LIST OF REF  ← NIL,
top:    LIST OF REF  ← NIL,
in:     LIST OF REF  ← NIL,
out:    LIST OF REF  ← NIL,
bot:    LIST OF REF  ← NIL,
sums:    INT    ← 1,
seq:    BOOL    ← FALSE ]
RETURNS[cellName: IFUPW.ObjName]= { -- positive bus on top
controlOnTop: BOOLPW.ODD[PW.Log2[IFUPW.rngByte*IFUPW.rngBit/sums]];
wdA: InterfaceWdLIST;
wdIn: LIST OF List;
list1, list2: LIST OF REFNIL;
cellList, mainList, ctls: IFUPW.List ← NIL;
size: IFUPW.Size;
in1Y, in2Y, outY: INT;
refCell, obj: CD.ObPtr;
met2Box, polyBox, switchbox: IFUPW.ObjName;
gpcRow, sumRow: IFUPW.ObjName;
[wdA, wdIn] ← GenInterleavedSplitTreeNames[sums, (IF seq THEN 4 ELSE 1)];
FOR ii: INT DECREASING IN [0..sums) DO
ctls ← CONS[Rope.Cat["C", Convert.RopeFromInt[ii]], ctls] ENDLOOP;
list1 ← list2 ← NIL;
list2 ← ConsGPCCopyOnLIST [list2, wdA[top][lng][rt], FALSE, TRUE, FALSE];
list2 ← ConsGPCCopyOnLIST [list2, wdA[top][lng][lt], FALSE, TRUE, FALSE];
list2 ← ConsNILsOnLIST  [list2, 8];
met2Box ← IFUPW.SwitchBoxRow[
design: design,
name:  name.Cat["TopMet2"],
rowType: IFUPW.cmosMet2,
topSeq: seq,
top:  list1,
left:  NIL,
right:  IF controlOnTop THEN ctls ELSE NIL,
bot:  list2,
botSeq: seq,
fixGV: TRUE ];
list1 ← list2 ← NIL;
list2 ← ConsGPCCopyOnLIST [list2, wdA[top][srt][rt], FALSE, TRUE, FALSE];
list2 ← ConsGPCCopyOnLIST [list2, wdA[top][srt][lt], FALSE, TRUE, FALSE];
list2 ← ConsNILsOnLIST  [list2, 8];
polyBox ← IFUPW.SwitchBoxRow[
design: design,
name:  name.Cat["TopPoly"],
rowType: IFUPW.cmosPoly,
topSeq: seq,
top:  list1,
left:  NIL,
right:  NIL,
bot:  list2,
botSeq: seq,
fixGV: TRUE,
m2Pitch: TRUE ];
switchbox ← ShiftMergeFill[design, polyBox, met2Box, name.Cat["SwitchTop"]];
mainList ← CONS[switchbox, mainList];
cellList ← NIL;
FOR index: INT DECREASING IN [0..IFUPW.rngByte*IFUPW.rngBit) DO
byte, bit, numIndex, level: INT ← 0;
[byte, bit] ← IFUPW.ByteBitFromIndex[index, seq];
numIndex ← (byte*8+bit) MOD (IFUPW.rngByte*IFUPW.rngBit/sums);
FOR val: INT ← numIndex, val/2 WHILE (val MOD 2) = 1 DO level ← level+1 ENDLOOP;
cellList ← CONS[
(IF numIndex+1 = (IFUPW.rngByte*IFUPW.rngBit/sums)
THEN "GPAdderGPCBlank"
ELSE IF (level MOD 2)=0
THEN "GPAdderGPC0"
ELSE "GPAdderGPC1"),
cellList];
ENDLOOP;
gpcRow ← IFUPW.AbutListX[design, cellList];
obj ← CDDirectory.Fetch[design, gpcRow].object;
[ ] ← CDDirectory.Rename[design, obj, name.Cat["GPC"]];
mainList ← CONS[CDDirectory.Name[obj], mainList];
list1 ← list2 ← NIL;
list1 ← ConsGPCCopyOnLIST [list1, wdA[bot][lng][rt]];
list1 ← ConsGPCCopyOnLIST [list1, wdA[bot][lng][lt]];
list1 ← ConsNILsOnLIST   [list1, 8];
met2Box ← IFUPW.SwitchBoxRow[
design: design,
name:  name.Cat["BotMet2"],
rowType: IFUPW.cmosMet2,
topSeq: seq,
top:  list1,
left:  NIL,
right:  IF ~controlOnTop THEN ctls ELSE NIL,
bot:  list2,
botSeq: seq,
fixGV: TRUE ];
list1 ← list2 ← NIL;
list1 ← ConsGPCCopyOnLIST [list1, wdA[bot][srt][rt]];
list1 ← ConsGPCCopyOnLIST [list1, wdA[bot][srt][lt]];
list1 ← ConsNILsOnLIST  [list1, 8];
list2 ← ConsGPCCopyOnLIST [list2, wdIn];
list2 ← ConsNILsOnLIST  [list2, 8];
polyBox ← IFUPW.SwitchBoxRow[
design: design,
name:  name.Cat["BotPoly"],
rowType: IFUPW.cmosPoly,
topSeq: seq,
top:  list1,
left:  NIL,
right:  NIL,
bot:  list2,
botSeq: seq,
fixGV: TRUE,
m2Pitch: TRUE ];
switchbox ← ShiftMergeFill[design, polyBox, met2Box, name.Cat["SwitchBot"]];
mainList ← CONS[switchbox, mainList];
cellList ← NIL;
FOR index: INT DECREASING IN [0..IFUPW.rngByte*IFUPW.rngBit) DO
cellList ← CONS["GPAdderSum", cellList] ENDLOOP;
sumRow ← IFUPW.AbutListX[design, cellList];
obj ← CDDirectory.Fetch[design, sumRow].object;
[ ] ← CDDirectory.Rename[design, obj, name.Cat["XOR"]];
mainList ← CONS[CDDirectory.Name[obj], mainList];
cellName ← IFUPW.AbutListY[design, mainList];
size ← PWBasics.GetISize[CDDirectory.Fetch[design, cellName].object];
obj ← CDCells.CreateEmptyCell[];
[]←PWBasics.IncludeApplication[obj, CDDirectory.Fetch[design, cellName].object];
refCell ← CDDirectory.Fetch[design, "GPAdderSum"].object;
in1Y ← CDPinObjects.FindPins[refCell, "In1"].first.location.y;
in2Y ← CDPinObjects.FindPins[refCell, "In2"].first.location.y;
outY ← CDPinObjects.FindPins[refCell, "Out"].first.location.y;
FOR index: INT IN [0..IFUPW.rngBit) DO
FOR byte: INT IN [0..IFUPW.rngByte) DO
refX: INTIFUPW.cellWidth*IFUPW.ByteBitToIndex[byte, index, seq];
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];
IFUPW.IOConnect[
design: design,
cell:  obj,
refX:  refX,
top:  topl,
topY:  size.y,
in1:  IF inl=NIL THEN NIL ELSE inl.first,
in2:  IF inl=NIL THEN NIL ELSE IF inl.rest=NILTHEN NIL ELSE inl.rest.first,
out:  IF outl=NIL THEN NIL ELSE outl.first,
in1Y:  in1Y,
in2Y:  in2Y,
outY:  outY,
botY:  0,
bot:  botl ];
IFUPW.AddMetalPins[obj, topl, botl, refX, size.y, 0, TRUE];
ENDLOOP;
ENDLOOP;
PWBasics.RepositionCell[design, obj];
[ ] ← CDDirectory.Rename[design, obj, name];
cellName ← CDDirectory.Name[obj]};
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:   INTIFUPW.rngByte,
longThres:   INTIFUPW.rngByte, -- differences <= to this are short wires
interleaveDepth:  INTIFUPW.rngByte, -- implies partitioning of result lists
firstPartitionSize: INTIFUPW.rngBit] -- 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 ← (IFUPW.rngByte * IFUPW.rngBit) / nofResults;
FOR byte: INT DECREASING IN [0..IFUPW.rngByte) DO
byteA: InterfaceByteLIST; byteIn: List ← NIL;
FOR bit: INT DECREASING IN [0..IFUPW.rngBit) DO
longWire: BOOLTRUE;
nameA: InterfaceNameLIST; nameIn: ROPENIL;
size: INT ← 1; -- will be length of output
level: INT ← 0;
section: INT ← ((byte * IFUPW.rngBit) + bit) / secLength;
index:  INT ← ((byte * IFUPW.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
[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], list];
new ← CONS[CopyModifiedLIST[ref: ref, rope: "P", shortRopes: pout], new];
new ← CONS[CopyModifiedLIST[ref: ref, rope: "G", shortRopes: gout], new]};
CopyModifiedLIST: PROC[ref: LIST OF List, rope: Rope.ROPE, shortRopes: BOOL]
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..IFUPW.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[list: LIST OF REF, count: INT]
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, lrgBox, smlBox: IFUPW.ObjName, name: ROPE]
RETURNS[cellName: IFUPW.ObjName] = {
lrgObj:  CD.ObPtr   ← CDDirectory.Fetch[design, lrgBox].object;
smlObj:  CD.ObPtr   ← CDDirectory.Fetch[design, smlBox].object;
lrgRect:  CD.DesignRect ← CD.InterestRect[lrgObj];
smlRect:  CD.DesignRect ← CD.InterestRect[smlObj];
diff:   INT    ← (lrgRect.y2 - lrgRect.y1) - (smlRect.y2 - smlRect.y1);
fillerTop:  CD.ObPtr   ← NIL;
fillerBot:  CD.ObPtr   ← NIL;
cell:   CD.ObPtr   ← CDCells.CreateEmptyCell[];
fTopName: IFUPW.ObjName ← NIL;
fBotName: IFUPW.ObjName ← NIL;
IF diff<9
THEN {
IF diff#0 THEN ERROR;
fillerTop  ← IFUPW.FillerCell[design, lrgObj, IFUPW.TopSide, 3*9, FALSE];
fillerBot  ← IFUPW.FillerCell[design, smlObj, IFUPW.BotSide, 3*9, FALSE];
fTopName ← CDDirectory.Name[fillerTop];
fBotName  ← CDDirectory.Name[fillerBot];
smlBox  ← IFUPW.AbutListY[design, LIST [fBotName, smlBox]];
lrgBox  ← IFUPW.AbutListY[design, LIST [lrgBox, fTopName]];
smlObj  ← CDDirectory.Fetch[design, smlBox].object;
lrgObj  ← CDDirectory.Fetch[design, lrgBox].object}
ELSE {
fillerTop  ← IFUPW.FillerCell[design, smlObj, IFUPW.TopSide,   9, FALSE];
fillerBot  ← IFUPW.FillerCell[design, smlObj, IFUPW.BotSide, diff - 9, FALSE];
fTopName ← CDDirectory.Name[fillerTop];
fBotName  ← CDDirectory.Name[fillerBot];
smlBox  ← IFUPW.AbutListY[design, LIST [fBotName, smlBox, fTopName]];
smlObj  ← CDDirectory.Fetch[design, smlBox].object};
[]←PWBasics.IncludeApplication[cell, smlObj];
[]←PWBasics.IncludeApplication[cell, lrgObj];
PWBasics.RepositionCell[design, cell, name];
RETURN[CDDirectory.Name[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,
seq:    FALSE ]]};
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,
seq:    TRUE ]]};
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,
seq:    FALSE ]]};
IFUPW.Register[Adder32x1x1,   "Adder32x1x1"];
IFUPW.Register[Adder32x1x1Seq,  "Adder32x1x1Seq"];
IFUPW.Register[Adder32x4x4,   "Adder32x4x4"];
END.