<> <> <> <> <<>> DIRECTORY CCDUtils, CD, CDBasics, CDCells, CDDirectory, CDRects, CDSymbolicObjects, Convert, Core, CoreBlock, CoreFrame, CoreLibrary, CoreName, CoreOps, CoreWire, CoreXform, HashTable, IFUCoreCells, IFUCoreData, CoreInstCell, IO, PW, PWC, Rope; IFUCoreDataImpl: CEDAR PROGRAM IMPORTS CCDUtils, CD, CDBasics, CDCells, CDDirectory, CDRects, CDSymbolicObjects, Convert, CoreBlock, CoreFrame, CoreLibrary, CoreName, CoreOps, CoreWire, CoreXform, HashTable, IFUCoreCells, IFUCoreData, CoreInstCell, IO, PW, PWC, Rope EXPORTS IFUCoreData = BEGIN ROPE: TYPE = Core.ROPE; NameLetterCode: TYPE = IFUCoreData.NameLetterCode; NameLetterCodeRec: TYPE = IFUCoreData.NameLetterCodeRec; NWMML: TYPE = PWC.NWMML; GND: ROPE _ CoreName.RopeNm["GND"]; VDD: ROPE _ CoreName.RopeNm["VDD"]; minus: ROPE _ CoreName.RopeNm["-"]; plus: ROPE _ CoreName.RopeNm["+"]; nil: ROPE _ CoreName.RopeNm["nil"]; pwrList: LIST OF REF _ LIST[GND, VDD]; Signal: SIGNAL = CODE; dpCellClass: PUBLIC Core.CellClass _ CoreOps.SetClassPrintProc[ NEW[Core.CellClassRec _ [name: "IFUCoreData", recast: NIL]], ClassPrintProc]; ClassPrintProc: CoreOps.PrintClassProc = { dpData: IFUCoreData.DpCellData _ NARROW[data]; IO.PutF[out, "Data Path Subclass: %g Type: \n", IO.rope[dpData.subClass] ]; CoreOps.PrintWire[dpData.type.w, out, 2] }; RegisterSubClassExpand: PUBLIC PROC [type: CoreFrame.ExpandType, subClass: ROPE, expand: CoreFrame.ExpandProc] = { IF type = soft THEN [ ] _ HashTable.Store[expandSoft, subClass, NEW[CoreFrame.ExpandProc_ expand]] ELSE [ ] _ HashTable.Store[expandHard,subClass, NEW[CoreFrame.ExpandProc_ expand]]}; expandHard: HashTable.Table _ HashTable.Create[equal: HashTable.RopeEqual, hash: HashTable.HashRope]; expandSoft: HashTable.Table _ HashTable.Create[equal: HashTable.RopeEqual, hash: HashTable.HashRope]; Sequencial48: PUBLIC CoreXform.Xform _ CoreXform.GenXform[LIST[ [4, 0], [8, 1] ]]; Interleaved48: PUBLIC CoreXform.Xform _ CoreXform.GenXform[LIST[ [4, 1], [8, 0] ]]; CellProc: PUBLIC PROC [ subClass: ROPE _ NIL, type: ROPE _ NIL, name: ROPE _ NIL, left: REF _ NIL, right: REF _ NIL, top: REF _ NIL, bot: REF _ NIL, in: REF _ NIL, out: REF _ NIL, data: REF _ NIL, channels: INT _ 6, xform: CoreXform.Xform _ IFUCoreData.Interleaved48 ] RETURNS [cellType: Core.CellType] = { ctx: CoreName.Context _ CoreName.NewContext[]; public: CoreWire.CWire; strucType: CoreWire.CWire; expandSoftProc: REF CoreFrame.ExpandProc; expandHardProc: REF CoreFrame.ExpandProc; xforms: CoreXform.Xforms _ CoreXform.GenXforms[xform]; public _ [CoreOps.CreateWire[LIST[ RdListOfXfrmWires[ctx, "top", top, xforms], RdListOfXfrmWires[ctx, "bot", bot, xforms], RdListOfXfrmWires[ctx, "in", in, xforms], RdListOfXfrmWires[ctx, "out", out, xforms], RdListOfXfrmWires[ctx, "right", right, NIL], -- if needed put xform on rope RdListOfXfrmWires[ctx, "left", left, NIL], -- if needed put xform on rope RdListOfXfrmWires[ctx, "pwr", pwrList, NIL] ]]]; ctx _ CoreName.KillContext[ctx]; ctx _ CoreName.NewContext[]; strucType _ [RdListOfXfrmWires[ctx, "type", LIST[type], xforms][0]]; ctx _ CoreName.KillContext[ctx]; DeleteGV[public.f["top"].w]; DeleteGV[public.f["bot"].w]; cellType _ CoreOps.SetCellTypeName[ NEW [ Core.CellTypeRec _ [ class: dpCellClass, public: public.w, data: NEW[IFUCoreData.DpCellDataRec _ [ subClass: subClass, type: strucType, data: data, channels: channels ] ], properties: NIL] ], name]; expandSoftProc _ NARROW[HashTable.Fetch[expandSoft, subClass].value]; expandHardProc _ NARROW[HashTable.Fetch[expandHard, subClass].value]; IF expandSoftProc=NIL THEN Signal[]; IF expandHardProc=NIL THEN Signal[]; CoreFrame.SetFrameExpandProc[soft, cellType, expandSoftProc ]; CoreFrame.SetFrameExpandProc[hard, cellType, expandHardProc ]}; <> <> RdListOfXfrmWires: PROC[ctx: CoreName.Context, name: ROPE, ref: REF, xforms: CoreXform.Xforms] RETURNS[wire: Core.Wire] = { new: CoreXform.Xforms; [ref, new] _ Parse[ref]; IF new#NIL THEN xforms _ new; IF ISTYPE[ref, LIST OF REF] THEN wire _ GenWireFmList[ctx, NARROW[ ref], xforms] ELSE wire _ GenWireFmItem[ctx, ref, xforms]; [ ] _ CoreName.WireNm[wire, name]; FOR jj: INT IN [0..wire.size) DO CoreXform.SetXform[wire[jj], CoreXform.GenXform[xforms]] ENDLOOP }; DeleteGV: PROC[top: Core.Wire] = { -- doesn't work for top node DeleteGVMain: PROC[wire: Core.Wire] RETURNS[new: Core.Wire] = { IF wire.size=0 THEN RETURN[SELECT CoreName.WireNm[wire].n FROM GND, VDD => CoreOps.CreateWires[0] ENDCASE => wire] ELSE FOR i: INT IN [0..wire.size) DO wire[i] _ DeleteGVMain[wire[i]] ENDLOOP; RETURN[wire]}; [] _ DeleteGVMain[top]}; <> <> <> < {>> <> <{Sym.SetName[inst, VDD]; IF conn THEN locs_CONS[vddLoc, locs]};>> <{Sym.SetName[inst, GND]; IF conn THEN locs_CONS[gndLoc, locs]};>> <> <> <> <> <<[ ] _ PW.IncludeInCell[new, cont, locs.first] ENDLOOP;>> <<[ ] _ CDCells.RepositionCell[new, NIL];>> <> <> <<>> ConnSpec: TYPE = REF ConnSeqRec; ConnSeqRec: TYPE = RECORD[SEQUENCE size: CARDINAL OF CnntRec]; CnntRec: TYPE = RECORD[name: ROPE, min, max: INT, layer: CD.Layer]; GenericCellRegistry: HashTable.Table _ HashTable.Create[]; CreateNameLetterCode: PUBLIC PROC [genericID: REF, list: LIST OF CoreWire.CWire, xformBit: INT] RETURNS[code: NameLetterCode] = { code _ InitNameLetterCode[]; IF genericID=NIL THEN code.name _ CoreName.ID["BitRouteRef"] ELSE { code.name _ NARROW[HashTable.Fetch[GenericCellRegistry, genericID].value]; IF code.name = NIL THEN { IF genericID=NIL THEN genericID _ CoreName.ID["BitRouteRef"]; code.name _ WITH genericID SELECT FROM rope: ROPE => genericID _ CoreName.RopeNm[rope], text: REF TEXT => genericID _ CoreName.RopeNm[Rope.FromRefText[text]], ENDCASE => CoreName.ID["BitRouteRef"]; [ ] _ HashTable.Store[GenericCellRegistry, genericID, code.name]} }; FOR list _ list, list.rest WHILE list#NIL DO code.name _ code.name.Cat[ "|" ]; FOR index: INT IN [0..list.first.w.size) DO code.name _ code.name.Cat [UniqueLetter[code, list.first.i[index].x[xformBit].n[] ] ] ENDLOOP; ENDLOOP}; Encode: PUBLIC PROC[code: NameLetterCode, name: ROPE] RETURNS[letter: ROPE] = {letter _ NARROW[HashTable.Fetch[code.letFmNm, name].value]}; Decode: PUBLIC PROC[code: NameLetterCode, letter: ROPE] RETURNS[name: ROPE] = {name _ NARROW[HashTable.Fetch[code.nmFmLet, letter].value]}; InitNameLetterCode: PROC RETURNS[code: NameLetterCode] = { code _ NEW[ NameLetterCodeRec _ [ name: NIL, letFmNm: HashTable.Create[equal: HashTable.RopeEqual, hash: HashTable.HashRope], nmFmLet: HashTable.Create[equal: HashTable.RopeEqual, hash: HashTable.HashRope], char: 'a, none: CoreName.RopeNm["="] ] ]; [ ] _ HashTable.Store[code.letFmNm, VDD, plus]; [ ] _ HashTable.Store[code.nmFmLet, plus, VDD]; [ ] _ HashTable.Store[code.letFmNm, GND, minus]; [ ] _ HashTable.Store[code.nmFmLet, minus, GND] }; UniqueLetter: PROC[code: NameLetterCode, name: ROPE] RETURNS[letter: ROPE] = { name _ CoreName.RopeNm[name]; IF name.Length[]=0 OR name=nil THEN RETURN[code.none]; letter _ NARROW[HashTable.Fetch[code.letFmNm, name].value]; IF letter#NIL THEN RETURN[letter]; letter _ CoreName.RopeNm[Convert.RopeFromChar[code.char, FALSE]]; [ ] _ HashTable.Store[code.letFmNm, name, letter]; [ ] _ HashTable.Store[code.nmFmLet, letter, name]; SELECT code.char FROM IN ['a..'z) => code.char _ code.char + 1; 'z => code.char _ 'A; IN ['A..'Z) => code.char _ code.char + 1; ENDCASE => Signal[]}; DpBitRoute: PUBLIC PROC[ specificCell: Core.CellType, genericCell: Core.CellType, rowWire: CoreWire.CWire, phyBit: INT, channels: INT, specificName: ROPE _ NIL ] RETURNS [glue: Core.CellType] = { renameProc: CoreInstCell.RenameProc ~ {new _ code.Decode[letter: old]; IF new=NIL THEN Signal[]; RETURN[new]}; code: IFUCoreData.NameLetterCode _ CreateNameLetterCode [genericID: genericCell, xformBit: phyBit, list: LIST[ rowWire.f["top" ], rowWire.f["in" ], rowWire.f["out" ], rowWire.f["right" ], rowWire.f["left" ], rowWire.f["bot" ] ]]; genericObj: CD.Object; generic: Core.CellType _ CoreLibrary.Get[IFUCoreCells.library, code.name]; IF generic=NIL THEN { size: INT _ PWC.InterestSize[specificCell].y; list: LIST OF NWMML _ CCDUtils.SidePinList[specificCell, left]; count: INT _ 0; connSpec: ConnSpec; FOR temp: LIST OF NWMML _ list, temp.rest WHILE temp#NIL DO count _ count + 1 ENDLOOP; connSpec _ NEW[ConnSeqRec[count+2]]; connSpec[0] _ [NIL, 0, 0, CCDUtils.cmosMet]; connSpec[connSpec.size-1] _ [NIL, size, size, CCDUtils.cmosMet]; FOR count IN [1..connSpec.size-1) DO connSpec[count] _ [ name: code.Encode[list.first.name], min: list.first.min, max: list.first.max, layer: list.first.layer ]; list _ list.rest ENDLOOP; genericObj _ IncludeBitWiring[code, connSpec, rowWire, phyBit, channels]; generic _ CoreLibrary.ObjCell[genericObj, code.name ]; CoreLibrary.Set[IFUCoreCells.library, code.name, generic]}; IF specificName = NIL THEN specificName _ CoreName.CellNm[specificCell].n; IF specificName = NIL THEN specificName _ CoreName.ID["BitRoute"] ELSE specificName _ Rope.Cat[specificName, "BitRoute"]; glue _ CoreInstCell.SpecificGeneric[generic, renameProc]; glue _ CoreFrame.NewFrameCell[0, specificName, [cell: glue ]] }; IncludeBitWiring: PROC[code: IFUCoreData.NameLetterCode, connSpec: ConnSpec, rowWire: CoreWire.CWire, xBit, channels: INT] RETURNS[cell: CD.Object] = { OPEN CM: CCDUtils; Same: PROC[idx1, idx2: CARDINAL] RETURNS[BOOL] = {RETURN[Rope.Equal[connSpec[idx1].name, connSpec[idx2].name]]}; tIdx: CARDINAL _ connSpec.size-1; bIdx: CARDINAL _ 0; cell _ CDCells.CreateEmptyCell[]; <> FOR col: INT IN [0..channels) DO Add: PROC[idx1, idx2: CARDINAL] RETURNS[BOOL] = { IF ~Same[idx1, idx2] THEN RETURN[FALSE]; loc.y _ connSpec[idx1].min; size.y _ connSpec[idx2].max - connSpec[idx1].min; IF size.y < 0 THEN ERROR; CCDUtils.AddRet[cell:cell, size: size, loc: loc, level: CM.cmosMet]; RETURN[TRUE]}; size: CD.Position _ [CM.metW, 0]; loc: CD.Position _ [CM.leftTail+col*CM.metPitch-CM.metW/2, 0]; connSpec[tIdx].name _ code.Encode[rowWire.f["top"].i[col].x[xBit].n]; connSpec[bIdx].name _ code.Encode[rowWire.f["bot"].i[col].x[xBit].n]; SELECT connSpec[tIdx].name FROM GND, VDD => connSpec[tIdx].name_NIL ENDCASE; SELECT connSpec[bIdx].name FROM GND, VDD => connSpec[bIdx].name_NIL ENDCASE; IF connSpec[tIdx].name#NIL THEN FOR row: INT IN [bIdx..tIdx) DO CM.PutPin[cell, [CM.metW, CM.metW], [loc.x, connSpec[tIdx].max-CM.metW], CM.cmosMet, connSpec[tIdx].name]; IF Add[ row, tIdx] THEN EXIT; REPEAT FINISHED => { log.PutF["Orphan top signal: %g", IO.rope[IFUCoreData.Decode[code, connSpec[tIdx].name]]]; Signal[]} ENDLOOP; IF connSpec[bIdx].name#NIL THEN FOR row: INT DECREASING IN (bIdx..tIdx) DO CM.PutPin[cell, [CM.metW, CM.metW], [loc.x, 0], CM.cmosMet, connSpec[bIdx].name]; IF Add[ bIdx, row] THEN EXIT; REPEAT FINISHED => IF ~Same[bIdx, tIdx] THEN { log.PutF["Orphan bottom signal: %g", IO.rope[IFUCoreData.Decode[code, connSpec[bIdx].name]]]; Signal[]} ENDLOOP; ENDLOOP; <> FOR row: INT IN (bIdx..tIdx) DO ctct: CD.Object _ CM.Contact[connSpec[row].layer]; wire: CD.Object; wWdth: INT _ connSpec[row].max - connSpec[row].min; Pin: PROC[side: {left, right}] = { xLoc: INT _ IF side = right THEN channels*CM.metPitch-CM.cnctSize ELSE 0; CM.PutPin[cell, [CM.cnctSize, wWdth], [xLoc, connSpec[row].min], connSpec[row].layer, connSpec[row].name]}; IF connSpec[row].layer = CM.cmosMet2 THEN { wire _ CDRects.CreateRect[[channels*CM.metPitch, wWdth], connSpec[row].layer]; Pin[left]; Pin[right]; [] _ PW.IncludeInCell[cell, wire, [0, connSpec[row].min]]}; FOR col: INT IN [0..channels) DO wLen: INT _ (channels-1-col)*CM.metPitch + CM.rightTail; wLoc: CD.Position _ [CM.leftTail + col*CM.metPitch, connSpec[row].min]; connSpec[tIdx].name _ code.Encode[rowWire.f["top"].i[col].x[xBit].n]; connSpec[bIdx].name _ code.Encode[rowWire.f["bot"].i[col].x[xBit].n]; IF ~Same[row, tIdx] AND ~Same[row, bIdx] THEN LOOP; wire _ CDRects.CreateRect[[wLen, wWdth], connSpec[row].layer]; Pin[right]; [] _ PW.IncludeInCell[cell, ctct, [wLoc.x-CM.cnctSize/2, wLoc.y-(CM.cnctSize-wWdth)/2]]; [] _ PW.IncludeInCell[cell, wire, wLoc]; ENDLOOP; ENDLOOP; CDCells.SetInterestRect[cell, [0, 0, channels*CM.metPitch, connSpec[tIdx].max]]; [ ] _ CDCells.RepositionCell[cell, NIL] }; BlockSides: PUBLIC PROC[cell: Core.CellType, cwire: CoreWire.CWire] = { BlockSideIfNotUsed: PROC[wire: Core.Wire] = { sides: CoreBlock.Sides _ CoreBlock.GetWireSide[wire]; name: ROPE _ CoreName.WireNm[wire].n; ltrt: BOOL _ cwire.f["left"].f[name].w#NIL OR cwire.f["right"].f[name].w#NIL; IF NOT ltrt THEN RETURN; SELECT name FROM VDD, GND => RETURN ENDCASE; IF cwire.f["left" ].f[name].w=NIL THEN sides _ CoreBlock.DelSide[left, sides]; IF cwire.f["right" ].f[name].w=NIL THEN sides _ CoreBlock.DelSide[right, sides]; CoreBlock.PutWireSide[wire, sides]}; CoreOps.VisitRootAtomics[cell.public, BlockSideIfNotUsed]}; log: IO.STREAM _ CoreFrame.GetLog[]; END. <<>>