<> <> <> <> <> <<>> <<>> DIRECTORY CD, CDIO, CDViewer, CommandTool, Convert, Core, CoreCreate, CoreGeometry, CoreOps, GList, IO, PWCore, Rope, SCParms, Sinix, Sisyph, SCUtils, TerminalIO, TilingClass; SCUtilsImpl: CEDAR PROGRAM IMPORTS CDViewer, CommandTool, CDIO, Convert, CoreCreate, CoreGeometry, CoreOps, GList, IO, PWCore, Rope, SCParms, Sinix, Sisyph, TerminalIO, TilingClass EXPORTS SCUtils ~ BEGIN OPEN SCUtils; myLogicDesign: CD.Design _ NIL; myLayoutDesign: CD.Design _ NIL; workingDirectory: ROPE _ CommandTool.CurrentWorkingDirectory[]; <> Log2: PUBLIC PROC [n: INT] RETURNS [log: INT _ 0] ~ { WHILE n > 1 DO n _ n/2; log _ log+1 ENDLOOP }; ComRecord: PUBLIC PROC [pattern: ROPE, cx: Sisyph.Context, ctName: ROPE] RETURNS [ct: CellType] ~ { n: Names _ NIL; FOR i: INT DECREASING IN [0..Rope.Length[pattern]) DO SELECT Rope.Fetch[pattern, i] FROM '0 => n _ CONS["ComCell0.icon", n]; '1 => n _ CONS["ComCell1.icon", n]; 'X => n _ CONS["ComCellX.icon", n]; 'N => n _ CONS["ComCellN.icon", n]; 'E => n _ CONS["ComCellE.icon", n]; ENDCASE => ERROR; ENDLOOP; ct _ RecordX[n, cx, Rope.Cat[ctName, pattern]]; }; <> RecordX: PUBLIC PROC [obNames: Names, cx: Sisyph.Context, ctName: ROPE] RETURNS [ct: CellType] ~ { count: NAT _ GList.Length[obNames]; Index: TYPE = {ComCell0, ComCell1, ComCellX, ComCellN, ComCellE}; baseCTs: CellTypes _ NIL; public: Wire; -- public of cellType to be returned tileRow: TilingClass.TileRow _ NEW [TilingClass.TileRowRec[count]]; tileArray: TilingClass.TileArray _ NEW [TilingClass.TileArrayRec[1]]; publicElements, arrayedWires, leftSideOnlyWires, rightSideOnlyWires, globalWires: Wires _ NIL; EachWire: CoreOps.EachWireProc = { sides: CoreGeometry.Sides = WireSide[wire, baseCTs.first]; vertical: BOOL = sides[top] OR sides[bottom]; IF vertical AND (sides[right] OR sides[left]) THEN WireSideProblem[wire, "touches adjacent sides", baseCTs.first]; IF vertical THEN { newPublic: Wire _ CoreOps.CreateWires[count, CoreOps.GetShortWireName[wire]]; arrayedWires _ CONS[wire, arrayedWires]; FOR i: INT IN [0..count) DO newPublic[i] _ CoreOps.SetShortWireName[CoreOps.CopyWire[wire], NIL]; ENDLOOP; publicElements _ CONS[newPublic, publicElements]; } ELSE { IF sides=CoreGeometry.noSide THEN { IF IsGlobal[wire, cx] THEN { globalWires _ CONS [wire, globalWires]; publicElements _ CONS [wire, publicElements] } } ELSE { IF sides[left] THEN leftSideOnlyWires _ CONS[wire, leftSideOnlyWires]; IF sides[right] THEN rightSideOnlyWires _ CONS[wire, rightSideOnlyWires]; publicElements _ CONS [wire, publicElements] } } }; <> FOR l: Names _ obNames, l.rest WHILE l#NIL DO baseCTs _ CONS[Sisyph.ExtractSchematicByName[l.first, cx], baseCTs]; ENDLOOP; baseCTs _ NARROW[GList.Reverse[baseCTs]]; <> [] _ CoreOps.VisitWireSeq[baseCTs.first.public, EachWire]; public _ CoreOps.CreateWire[publicElements]; <> FOR i: INT IN [0..count) DO tileRow[i] _ NEW [TilingClass.TileRec _ [type: baseCTs.first]]; baseCTs _ baseCTs.rest; ENDLOOP; <> FOR wl: Wires _ leftSideOnlyWires, wl.rest WHILE wl#NIL DO wireName: ROPE _ CoreOps.GetShortWireName[wl.first]; tileRow[0].renaming _ CONS[[wireName, wireName], tileRow[0].renaming]; ENDLOOP; <> FOR wl: Wires _ rightSideOnlyWires, wl.rest WHILE wl#NIL DO wireName: ROPE _ CoreOps.GetShortWireName[wl.first]; tileRow[count-1].renaming _ CONS[[wireName, wireName], tileRow[count-1].renaming]; ENDLOOP; <> FOR wl: Wires _ globalWires, wl.rest WHILE wl#NIL DO wireName: ROPE _ CoreOps.GetShortWireName[wl.first]; FOR i: NAT IN [0..count) DO tileRow[i].renaming _ CONS[[wireName, wireName], tileRow[i].renaming]; ENDLOOP; ENDLOOP; <> FOR wl: Wires _ arrayedWires, wl.rest WHILE wl#NIL DO wireName: ROPE _ CoreOps.GetShortWireName[wl.first]; FOR i: NAT IN [0..count) DO tileRow[i].renaming _ CONS[[wireName, Rope.Cat[wireName, "[", Convert.RopeFromInt[i], "]"]], tileRow[i].renaming]; ENDLOOP; ENDLOOP; tileArray[0] _ tileRow; <> ct _ TilingClass.CreateTiling[CoreOps.CopyWire[public], tileArray, TilingClass.SchematicsNeighborX, TilingClass.SchematicsNeighborY, Rope.Cat[ctName, ".RecordX"]]; }; RamInterfaceRout: PUBLIC PROC [cx: Sisyph.Context] RETURNS [ct: CellType] ~ { Flip: TYPE ~ {normal, flipped}; BaseCells: TYPE ~ REF BaseCellsRep; BaseCellsRep: TYPE ~ RECORD [v: SEQUENCE size: NAT OF ARRAY Flip OF RECORD [ct: CellType, w: Wire]]; index, selIndex, spareIndex: INT; baseB: BaseCells _ NEW [BaseCellsRep[SCParms.numBytesPerWord]]; baseW: BaseCells _ NEW [BaseCellsRep[SCParms.numWordsPerLine]]; spacerB, spacerW: CellType; spare: Wire _ CoreCreate.Seq[size: SCParms.numBitsPerCycle, name: "Spare"]; byteSel: Wire _ CoreCreate.Seq[size: SCParms.numBytesPerWord, name: "ByteSel"]; bS: Wire _ CoreCreate.Seq[size: SCParms.numBitsPerLine, name: "BS"]; wordSel: Wire _ CoreCreate.Seq[size: SCParms.numWordsPerLine, name: "WdSel"]; wS: Wire _ CoreCreate.Seq[size: SCParms.numBitsPerLine, name: "WS"]; count: INT ~ SCParms.numBitsPerLine+SCParms.numBitsPerCycle; -- Including the spare lines tileRowB: TilingClass.TileRow _ NEW [TilingClass.TileRowRec[count]]; tileRowW: TilingClass.TileRow _ NEW [TilingClass.TileRowRec[count]]; tileArray: TilingClass.TileArray _ NEW [TilingClass.TileArrayRec[2]]; <> FOR i: NAT IN [0..SCParms.numBytesPerWord) DO name: ROPE = IO.PutFR["RamInterfaceBitRout2%g.sch", IO.int[i]]; bSName: ROPE = IO.PutFR["ByteSel[%g]", IO.int[i]]; baseB[i][normal].ct _ Sisyph.ExtractSchematicByName[name, Sisyph.Copy[cx]]; baseB[i][flipped].ct _ PWCore.RotateCellType[baseB[i][normal].ct, $FlipX]; FOR m: Flip IN Flip DO baseB[i][m].w _ CoreOps.FindWire[baseB[i][m].ct.public, bSName]; ENDLOOP; ENDLOOP; FOR word: NAT IN [0..SCParms.numWordsPerLine) DO name: ROPE = IO.PutFR["RamInterfaceBitRout1%g.sch", IO.int[word]]; wSName: ROPE = IO.PutFR["WdSel[%g]", IO.int[word]]; baseW[word][normal].ct _ Sisyph.ExtractSchematicByName[name, Sisyph.Copy[cx]]; baseW[word][flipped].ct _ PWCore.RotateCellType[baseW[word][normal].ct, $FlipX]; FOR m: Flip IN Flip DO baseW[word][m].w _ CoreOps.FindWire[baseW[word][m].ct.public, wSName]; ENDLOOP; ENDLOOP; spacerB _ Sisyph.ExtractSchematicByName["RamInterfaceSpacerRout2.sch", cx]; spacerW _ Sisyph.ExtractSchematicByName["RamInterfaceSpacerRout1.sch", cx]; <> <> index _ 0; -- index in the tilling class selIndex _ 0; -- index in the BS wire spareIndex _ 0; -- index in the Spare wire FOR i: INT IN [0..SCParms.numBytesPerWord) DO FOR j: INT IN [0..SCParms.numBitsPerByte) DO word: INT _ 0; FOR k: INT IN [0..SCParms.numWordsPerCycle) DO FOR l: INT IN [0..SCParms.numCyclesPerLine/2) DO FOR m: Flip IN Flip DO bS[selIndex] _ byteSel[i]; wS[selIndex] _ wordSel[word]; tileRowB[index] _ NEW [TilingClass.TileRec _ [ type: baseB[i][m].ct, renaming: LIST[ [public: "ByteSel", actual: byteSel], [public: baseB[i][m].w, actual: bS[selIndex]] ]]]; tileRowW[index] _ NEW [TilingClass.TileRec _ [ type: baseW[word][m].ct, renaming: LIST[ [public: "WdSel", actual: wordSel], [public: baseW[word][m].w, actual: wS[selIndex]] ]]]; selIndex _ selIndex+1; index _ index+1; word _ word+1; ENDLOOP; ENDLOOP; tileRowB[index] _ NEW [TilingClass.TileRec _ [ type: spacerB, renaming: LIST[ [public: "ByteSel", actual: byteSel], [public: "Spare", actual: spare[spareIndex]] ]]]; tileRowW[index] _ NEW [TilingClass.TileRec _ [ type: spacerW, renaming: LIST[ [public: "WdSel", actual: wordSel], [public: "Spare", actual: spare[spareIndex]] ]]]; spareIndex _ spareIndex +1; index _ index+1; ENDLOOP; IF word # SCParms.numWordsPerLine THEN ERROR; ENDLOOP; ENDLOOP; IF index # count THEN ERROR; IF selIndex # SCParms.numBitsPerLine THEN ERROR; IF spareIndex # SCParms.numBitsPerCycle THEN ERROR; tileArray[1] _ tileRowW; tileArray[0] _ tileRowB; <> ct _ TilingClass.CreateTiling[ public: CoreCreate.Wires[spare, byteSel, bS, wordSel, wS], tileArray: tileArray, neighborX: TilingClass.LayoutNeighborX, neighborY: TilingClass.LayoutNeighborY, name: "RamInterfaceRout"]; }; Interleave: PUBLIC PROC [b: NAT] RETURNS [public: Core.Wires] = { wire: Wire _ CoreCreate.Seq["Wire", b]; interleavedWire: Wire _ CoreCreate.Seq["InterleavedWire", b]; IF b MOD 2 = 1 THEN ERROR; IF b=0 THEN ERROR; FOR i: NAT IN [0..b/2) DO interleavedWire[2*i] _ wire[i]; interleavedWire[2*i+1] _ wire[b/2+i]; ENDLOOP; public _ LIST [wire, interleavedWire]; }; Interleave2: PUBLIC PROC [b: NAT] RETURNS [public: Core.Wires] = { wire0: Wire _ CoreCreate.Seq["Wire0", b/2]; wire1: Wire _ CoreCreate.Seq["Wire1", b/2]; interleavedWire: Wire _ CoreCreate.Seq["InterleavedWire", b]; IF b MOD 2 = 1 THEN ERROR; IF b=0 THEN ERROR; FOR i: NAT IN [0..b/2) DO interleavedWire[2*i] _ wire0[i]; interleavedWire[2*i+1] _ wire1[i]; ENDLOOP; public _ LIST [wire0, wire1, interleavedWire]; }; LogicDesign: PUBLIC PROC [] RETURNS [design: CD.Design] = { name: ROPE _ "SCLogic"; -- must declare it as a rope! IF myLogicDesign=NIL THEN { myLogicDesign _ CDViewer.FindDesign[name]; IF myLogicDesign=NIL THEN myLogicDesign _ CDIO.ReadDesign[name, NIL, workingDirectory]; IF myLogicDesign = NIL THEN ERROR; }; design _ myLogicDesign }; LayoutDesign: PUBLIC PROC [] RETURNS [design: CD.Design] = { name: ROPE _ "CacheCells"; -- must declare it as a rope! IF myLayoutDesign=NIL THEN { myLayoutDesign _ CDViewer.FindDesign[name]; IF myLayoutDesign=NIL THEN myLayoutDesign _ CDIO.ReadDesign[name, NIL, workingDirectory]; IF myLayoutDesign = NIL THEN ERROR; }; design _ myLayoutDesign }; <> IsGlobal: PROC [w: Wire, cx: Sisyph.Context] RETURNS [BOOL _ FALSE] = { name: ROPE _ CoreOps.GetShortWireName[w]; FOR lr: LIST OF ROPE _ Sisyph.GetGlobalNames[cx], lr.rest WHILE lr#NIL DO IF Rope.Equal[name, lr.first] THEN RETURN [TRUE] ENDLOOP; }; WireSide: PROC [wire: Wire, baseCT: CellType] RETURNS [sides: CoreGeometry.Sides _ CoreGeometry.noSide] ~ { <> EachPin: CoreGeometry.EachPinProc = { sides[side] _ TRUE; }; [] _ CoreGeometry.EnumerateSides[Sisyph.mode.decoration, baseCT, wire, EachPin]; }; WireSideProblem: PROC [wire: Wire, msg: ROPE, baseCT: CellType] ~ { TerminalIO.PutF["\n*** Wire %g %g in cell %g\n", IO.rope[CoreOps.GetFullWireName[baseCT.public, wire]], IO.rope[msg], IO.rope[CoreOps.GetCellTypeName[baseCT]]]; SIGNAL Sinix.CallerBug[]; }; CatIndex: PROC[name: ROPE, index: INT] RETURNS [ROPE] ~ { RETURN [Rope.Cat[name, "[", Convert.RopeFromInt[index], "]"]] }; END.