IFUCoreDataAdderImpl.mesa,
Copyright c 1986 by Xerox Corporation. All rights reserved.
Last Edited by Curry, August 22, 1986 7:53:38 am PDT
DIRECTORY CCDUtils, CD, Core, CoreFrame, CoreGlue, CoreLibrary, CoreOps, CoreName, CoreWire, CoreXform, HashTable, IFUCoreCells, IFUCoreData, CoreInstCell, IO, PWC, Rope;
IFUCoreDataAdderImpl: CEDAR PROGRAM
IMPORTS CCDUtils, CoreFrame, CoreGlue, CoreLibrary, CoreOps, CoreName, CoreWire, CoreXform, HashTable, IFUCoreCells, IFUCoreData, CoreInstCell, IO, Rope =
BEGIN
Either left or right must contain the carries (also specifies # of sums)
ROPE:   TYPE = Core.ROPE;
GND:   ROPE = CoreName.RopeNm["GND"];
VDD:   ROPE = CoreName.RopeNm["VDD"];
NWMML: TYPE = PWC.NWMML;
Side:   TYPE = CoreFrame.Side;
CWire:   TYPE = CoreWire.CWire;
Signal: SIGNAL = CODE;
CryLists: TYPE = ARRAY Side OF ARRAY Side OF LIST OF ROPE; -- [left/right][top/bottom]
ExpandDataAdderFrame: CoreFrame.ExpandProc = { -- frameCT
crys: CryLists ← ALL[ALL[NIL]];
EdgeCell: PROC[lr: Side, tb: Side] RETURNS[edge: Core.CellType] = {
obj: CD.Object;
nsList: LIST OF NWMML;
list: LIST OF ROPE ← crys[lr][tb];
IF list=NIL THEN RETURN[NIL];
FOR list ← list, list.rest WHILE list#NIL DO
nsList ← CONS[NWMML[name: list.first, max: CCDUtils.met2W], nsList] ENDLOOP;
obj ← CoreGlue.SideObject[side: lr, list: nsList, layer: CCDUtils.met2W, length: 0, sameLayerOnly: FALSE];
edge ← CoreLibrary.ObjCell[obj, CoreName.ID["EdgeDummy"]]};
name: ROPE ← CoreName.CellNm[frameCT].n;
frame: CoreFrame.Frame ← NEW[CoreFrame.FrameRec ← [first: top] ];
data: IFUCoreData.DpCellData ← NARROW[frameCT.data];
in0:    CWire ← CWire[frameCT.public].f["in"].i[0];
in1:    CWire ← CWire[frameCT.public].f["in"].i[1];
domain:   NAT ← CoreXform.XformSize[CoreXform.GetXform[data.type]];
topDegree:  NAT ← 0;
cwire: CWire ← [frameCT.public];
gwire: CWire ← [CoreOps.CreateWire[elements: LIST[
CoreOps.CreateWires[cwire.f["top"].w.size, "bot"], -- must be wire 0 for use below
cwire.f["top"],           -- must be wire 1 for use below
cwire.f["pwr"],
CoreOps.CreateWires[0, "in"],
CoreOps.CreateWires[0, "out"],
cwire.f["right"],
cwire.f["left"] ] ] ];
frame.seq  ← NEW[CoreFrame.FrameSeq[4]];
frame.seq[1] ← CoreFrame.NewFrameCell[2*domain, "GPC", [first: left]];
frame.seq[3] ← CoreFrame.NewFrameCell[2*domain, "Base", [first: left]];
frameCT.class ← CoreFrame.frameCellClass;
frameCT.data  ← frame;
FOR val: INT ← Carrys[cwire].w.size/2, val/2 WHILE val#0
DO topDegree ← topDegree + 1 ENDLOOP;
FOR phyIndex: INT DECREASING IN [0..domain) DO
renameGPCProc: CoreInstCell.RenameProc ~
{[new, crys]←TranslateGenericName[FALSE, old, gwire, phyIndex, topDegree, crys]};
renameBaseProc: CoreInstCell.RenameProc ~
{[new, crys]←TranslateGenericName[TRUE, old, cwire, phyIndex, topDegree, crys]};
blank:  BOOL ← in0.x[phyIndex].n[]=NIL AND in1.x[phyIndex].n[]=NIL;
gpcCtx: CoreName.Context ← CoreName.NewContext[];
baseCtx: CoreName.Context ← CoreName.NewContext[];
genGPCCell: Core.CellType ← GetGPCGeneric[cwire, phyIndex];
genBaseCell: Core.CellType ← IF blank
THEN CoreLibrary.Get[IFUCoreCells.library, "DpAdderSumBlank"]
ELSE IFUCoreData.ConstantInputVariant
["DpAdderSum", in0.x[phyIndex].n, in1.x[phyIndex].n];
specificGPC: Core.CellType ← CoreInstCell.SpecificGeneric[genGPCCell, renameGPCProc];
specificBase: Core.CellType ← CoreInstCell.SpecificGeneric[genBaseCell, renameBaseProc];
FOR ii: INT IN [0..gwire.w[0].size) DO
gwire.w[0][ii] ← gwire.w[1][ii] ENDLOOP; -- See above, 0=> bot, 1=> top
CoreFrame.FCT[frame.seq[1]].seq[2*phyIndex+0] ←
IFUCoreData.DpBitRoute[specificGPC, genGPCCell, gwire, phyIndex, data.channels];
CoreFrame.FCT[frame.seq[1]].seq[2*phyIndex+1] ←
CoreFrame.NewFrameCell[0, NIL, [first: left, cell: specificGPC]];
CoreFrame.FCT[frame.seq[3]].seq[2*phyIndex+0] ←
IFUCoreData.DpBitRoute[specificBase, genBaseCell, cwire, phyIndex, data.channels];
CoreFrame.FCT[frame.seq[3]].seq[2*phyIndex+1] ←
CoreFrame.NewFrameCell[0, NIL, [first: left, cell: specificBase]];
gpcCtx ← CoreName.KillContext[gpcCtx];
baseCtx ← CoreName.KillContext[baseCtx];
ENDLOOP;
frame.seq[0] ← CoreGlue.CellProc[subClass: "ThreeLevel", t: conn, b: conn,
lCell: EdgeCell[left, top], rCell: EdgeCell[right, top], data: NEW[INT ← data.channels]];
frame.seq[2] ← CoreGlue.CellProc [subClass: "ThreeLevel", t: conn, b: conn,
lCell: EdgeCell[left, bottom], rCell: EdgeCell[right, bottom], data: NEW[INT ← data.channels]];
AdderID ← AdderID + 1;
frameCT.class ← CoreFrame.frameCellClass;
frameCT.data  ← frame;
CoreFrame.FCT[frame.seq[1]].cell ← CoreFrame.RecastFrameHard[frame.seq[1]];
CoreFrame.FCT[frame.seq[3]].cell ← CoreFrame.RecastFrameHard[frame.seq[3]];
obj ← PWC.Layout[CoreFrame.FCT[frame.seq[1]].cell]; -- Make sure PWC is happy
obj ← PWC.Layout[CoreFrame.FCT[frame.seq[3]].cell]; -- Make sure PWC is happy
CoreFrame.FCT[frame.seq[1]].seq ← NEW[CoreFrame.FrameSeq[0]]; -- free the children
CoreFrame.FCT[frame.seq[3]].seq ← NEW[CoreFrame.FrameSeq[0]]; -- free the children
CoreFrame.SetFrameExpandProc[soft, frameCT, NIL];
CoreFrame.SetFrameExpandProc[hard, frameCT, NIL] };
cry:   ROPE ← CoreName.RopeNm["Cry"];
cryNone:  ROPE ← CoreName.RopeNm["none"];
cryVDD:  ROPE ← CoreName.RopeNm["CryVDD"];
cryGND:  ROPE ← CoreName.RopeNm["CryGND"];
gpcblank:  ROPE ← CoreName.RopeNm["DpAdderGPCBlank"];
gpc0:   ROPE ← CoreName.RopeNm["DpAdderGPC0"];
gpc1:   ROPE ← CoreName.RopeNm["DpAdderGPC1"];
GetGPCGeneric: PROC[cwire: CWire, phyIndex: INT]
RETURNS[genGPCCell: Core.CellType] = {
genGPCCellRope: ROPE;
carryRope: ROPE;
carry:   BOOL;
blank:   BOOL ←
cwire.f["in"].i[0].x[phyIndex].n[]=NIL AND
cwire.f["in"].i[1].x[phyIndex].n[]=NIL;
xform:   CoreXform.Xform ← CoreXform.GetXform[cwire.f["in"].i[0].w];
domain:  NAT ← CoreXform.XformSize[xform];
logicalIndex: INT ← CoreXform.XformIndex[xform, rl, phyIndex].i;
tc:    CoreXform.Coord ← CoreXform.FlatTreeIndex[domain, logicalIndex];
middleUp: BOOL ← (tc.degree MOD 2)#(tc.degrees MOD 2);
topDegree: NAT ← 0;
FOR val: INT ← Carrys[cwire].w.size/2, val/2 WHILE val#0
DO topDegree ← topDegree + 1 ENDLOOP;
carry   ← tc.degree = topDegree+1;
genGPCCellRope ← IF blank OR topDegree >= tc.degree
THEN gpcblank ELSE IF middleUp THEN gpc0 ELSE gpc1;
carryRope ← IF carry
THEN SELECT Carrys[cwire].i[tc.index].n FROM
VDD  => IF middleUp THEN cryGND ELSE cryVDD, -- carry is positive below
GND  => IF middleUp THEN cryVDD ELSE cryGND, -- carry is positive below
ENDCASE => cry
ELSE IF blank THEN cryNone ELSE cry;
genGPCCell ← CoreLibrary.Get[
lib:    IFUCoreCells.library,
name:    genGPCCellRope,
removeNamed: FALSE,
conds:    LIST[ carryRope ]] };
Carrys: PROC[rowPublic: CWire] RETURNS[carry: CWire] = {
left: CWire ← rowPublic.f["left"];
right: CWire ← rowPublic.f["right"];
carry ← IF left.w.size#0 THEN left ELSE right};
TranslateGenericName: PROC
[base: BOOL, name: ROPE, public: CWire, pIndex, topDegree: INT, oldCrys: CryLists]
RETURNS[new: ROPE, crys: CryLists] = {
keyIndex: KeyIndex ←NARROW[HashTable.Fetch[xlateTable, CoreName.RopeNm[name]].value];
xform:  CoreXform.Xform ← CoreXform.GetXform[public.f["top"].i[0]];
domain:  NAT   ← CoreXform.XformSize[xform];
logicalIndex: NAT   ← CoreXform.XformIndex[xform, rl, pIndex].i;
tc:   CoreXform.Coord ← CoreXform.FlatTreeIndex[domain, logicalIndex];
pos:  {left, right, middle};
crys ← oldCrys;
IF keyIndex#NIL THEN
RETURN[public.f[keyIndex.key].i[keyIndex.index].x[pIndex].n[], crys];
IF name=NIL THEN Signal[];
pos ←
IF name.Find["L"]#-1 THEN left ELSE
IF name.Find["R"]#-1 THEN right ELSE
IF name.Find["M"]#-1 THEN middle ELSE ERROR;
IF base
THEN {tc.degree ← tc.degrees; tc.index ← logicalIndex; IF pos#middle THEN Signal[]};
IF pos=middle AND tc.degree = topDegree+1 -- carry in
for sums=1, degree 1 is center, (0 is on right and not present)
THEN SELECT TRUE FROM
name.Find["G"]#-1 => RETURN[CoreName.ID["DeadEnd"], crys];
name.Find["P"]#-1 => RETURN[CoreName.ID["DeadEnd"], crys];
name.Find["G"]#-1 => RETURN[NIL, crys];
name.Find["P"]#-1 => RETURN[NIL, crys];
ENDCASE    => {
middleUp: BOOL ← (tc.degree MOD 2) # (tc.degrees MOD 2);
left:   ROPE ← public.f["left"].i[ tc.index].n;
right:   ROPE ← public.f["right"].i[ tc.index].n;
carry:   ROPEIF left#NIL THEN left ELSE right;
IF (left=NIL)=(right=NIL) THEN Signal[];
SELECT carry FROM GND, VDD => RETURN[NIL, crys]; ENDCASE;
IF middleUp THEN { -- top channel carrys are inverted
sigRec: CoreName.SigRec ← CoreName.NameSig[carry];
sigRec.not ← NOT sigRec.not;
carry ← CoreName.SigName[sigRec]};
SELECT TRUE FROM
left #NIL => IF middleUp
THEN crys[left][top]  ← CONS[carry, crys[left][top]]
ELSE crys[left][bottom] ← CONS[carry, crys[left][bottom]];
right #NIL => IF middleUp
THEN crys[right][top]  ← CONS[carry, crys[right][top]]
ELSE crys[right][bottom] ← CONS[carry, crys[right][bottom]];
ENDCASE  => ERROR;
RETURN[carry, crys]}
ELSE {
new ← IO.PutFR[ "%g%g%g%gi%02g",
IO.rope[IF name.Fetch[0]='n THEN "nA" ELSE "A"],
IO.int[AdderID],
IO.rope[SELECT TRUE FROM
name.Find["G"]#-1=>"G", name.Find["P"]#-1=>"P", ENDCASE=>"C"],
IO.int[IF pos=middle THEN tc.degree ELSE tc.degree+1 ],
IO.int[SELECT pos FROM
middle => tc.index,
left  => (tc.index)*2,
right  => (tc.index)*2 + 1, ENDCASE => ERROR ] ] } };
AdderID:   INT ← 0;
KeyIndex:  TYPE = REF KeyIndexRec;
KeyIndexRec: TYPE = RECORD[key: ROPE, index: INT];
xlateTable:  HashTable.Table;
InitXlateTable: PROC = {
Store: PROC[refName, key: ROPE, index: INT] = {
refName ← CoreName.RopeNm[refName];
key  ← CoreName.RopeNm[key];
[] ← HashTable.Store[xlateTable, refName, NEW[KeyIndexRec ← [key, index]]]};
xlateTable ← HashTable.Create[equal: HashTable.RopeEqual, hash: HashTable.HashRope];
Store[ "in0",  "in",  0];
Store[ "in1",  "in",  1];
Store[ "out0",  "out",  0];
Store[ "out1",  "out",  1];
Store[ "0",  "left",  0];
Store[ "1",  "left",  1];
Store[ "rt0",  "right", 0];
Store[ "rt1",  "right", 1];
Store[ "GND", "pwr", 0];
Store[ "VDD", "pwr", 1] };
InitXlateTable[];
IFUCoreData.RegisterSubClassExpand [hard, "Adder", ExpandDataAdderFrame];
IFUCoreData.RegisterSubClassExpand [soft, "Adder", ExpandDataAdderFrame];
END.