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 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]]; 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 THEN SELECT TRUE FROM 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: ROPE _ IF 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[ "GND", "pwr", 0]; Store[ "VDD", "pwr", 1] }; InitXlateTable[]; IFUCoreData.RegisterSubClassExpand [hard, "Adder", ExpandDataAdderFrame]; IFUCoreData.RegisterSubClassExpand [soft, "Adder", ExpandDataAdderFrame]; END. ΌIFUCoreDataAdderImpl.mesa, Copyright c 1986 by Xerox Corporation. All rights reserved. Last Edited by Curry, August 22, 1986 7:53:38 am PDT Either left or right must contain the carries (also specifies # of sums) 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 for sums=1, degree 1 is center, (0 is on right and not present) name.Find["G"]#-1 => RETURN[CoreName.ID["DeadEnd"], crys]; name.Find["P"]#-1 => RETURN[CoreName.ID["DeadEnd"], crys]; Store[ "out1", "out", 1]; Store[ "0", "left", 0]; Store[ "1", "left", 1]; Store[ "rt0", "right", 0]; Store[ "rt1", "right", 1]; Κ M˜šœ™Jšœ<™—Jšœœ œ œ˜7šœœ˜Jšœ˜Jšœ˜Jšœœœ ˜5—————J˜J˜Jšœ œœ ˜"Jš œ œœœ œ˜2Jšœ˜J˜šŸœœ˜šŸœœœ œ˜/Jšœ#˜#Jšœ˜Jšœ*œ˜L—JšœT˜TJšœ˜Jšœ˜Jšœ˜Jšœ™Jšœ™Jšœ™Jšœ™Jšœ™Jšœ˜Jšœ˜—J™Icodešœ˜J˜JšœI˜IJšœI˜IJ˜Jšœ˜——…—$€1‰