<> <> <> <<>> DIRECTORY Basics, CD, CDCells, CDDirectory, CDPinObjects, Convert, CMos, IFUPW, PW, PWBasics, Rope; IFUPWAdder: CEDAR PROGRAM IMPORTS CD, CDCells, CDDirectory, CDPinObjects, Convert, IFUPW, PW, PWBasics, Rope EXPORTS IFUPW = 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: BOOL _ PW.ODD[PW.Log2[IFUPW.rngByte*IFUPW.rngBit/sums]]; wdA: InterfaceWdLIST; wdIn: LIST OF List; list1, list2: LIST OF REF _ NIL; 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: INT _ IFUPW.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=NIL THEN 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 OF LIST 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 ROPE _ ALL[ALL[ALL[NIL]]]; GenInterleavedSplitTreeNames: PROC[ nofResults: INT _ IFUPW.rngByte, longThres: INT _ IFUPW.rngByte, -- differences <= to this are short wires interleaveDepth: INT _ IFUPW.rngByte, -- implies partitioning of result lists firstPartitionSize: INT _ IFUPW.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: BOOL _ FALSE; 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: BOOL _ TRUE; nameA: InterfaceNameLIST; nameIn: ROPE _ NIL; 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: BOOL_FALSE] 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.ROPE _ IFUPW.ListIndexItem[rlist, i2]; rrope _ IF rrope = NIL OR rrope.Length[]=0 OR (rrope.Length[]<3 AND ~shortRopes) THEN NIL 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]] }; <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <<>> <> <> <> <<>> END.