<> <> <> <> <> <<>> <<>> DIRECTORY CD, CDIO, CDViewer, CommandTool, Convert, Core, CoreCreate, CoreGeometry, CoreOps, GList, IO, PWCore, Rope, RopeList, SCParms, Sinix, Sisyph, SmallCacheUtils, TerminalIO, TilingClass; SmallCacheUtilsImpl: CEDAR PROGRAM IMPORTS CDViewer, CommandTool, CDIO, Convert, CoreCreate, CoreGeometry, CoreOps, GList, IO, PWCore, Rope, RopeList, SCParms, Sinix, Sisyph, TerminalIO, TilingClass EXPORTS SmallCacheUtils ~ BEGIN OPEN SmallCacheUtils; workingDirectory: PUBLIC ROPE _ CommandTool.CurrentWorkingDirectory[]; layoutDesign: CD.Design _ NIL; <> 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 _ RopeList.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"]; f0: Wire _ CoreCreate.Seq[size: SCParms.numBitsPerLine, name: "F0"]; -- feedthrough f1: Wire _ CoreCreate.Seq[size: SCParms.numBitsPerLine, name: "F1"]; -- feedthrough 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: "F0", actual: f0[selIndex]], [public: "F1", actual: f1[selIndex]], [public: "WS", actual: wS[selIndex]], [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: "F0", actual: f0[selIndex]], [public: "F1", actual: f1[selIndex]], [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, f0, f1], 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]; }; FuseGroups: PUBLIC PROC [numGroups, groupSize: NAT] RETURNS [public: Core.Wires] = { wire: Wire _ CoreCreate.Seq["Wire", numGroups*groupSize]; fusedWire: Wire _ CoreCreate.Seq["FusedWire", numGroups]; IF numGroups <= 0 OR groupSize <= 0 THEN ERROR; FOR i: NAT IN [0..numGroups*groupSize) DO wire[i] _ fusedWire[i/groupSize]; ENDLOOP; public _ LIST [wire, fusedWire]; }; Flatten: PUBLIC PROC [numGroups, groupSize: NAT] RETURNS [public: Core.Wires] = { flatWire, wire: Wire; IF numGroups <= 0 OR groupSize <= 0 THEN ERROR; flatWire _ CoreCreate.Seq["FlatWire", numGroups*groupSize]; wire _ CoreCreate.Seq["Wire", numGroups, CoreCreate.Seq[size: groupSize]]; FOR i: NAT IN [0..numGroups) DO FOR j: NAT IN [0..groupSize) DO flatWire[i*groupSize+j] _ wire[i][j]; ENDLOOP; ENDLOOP; public _ LIST [wire, flatWire]; }; HexToBin: PUBLIC PROC [h: ROPE] RETURNS [b: ROPE _ NIL] = { FOR i: INT IN [0..Rope.Length[h]) DO SELECT Rope.Fetch[h, i] FROM '0 => b _ Rope.Cat[b, "0000"]; '1 => b _ Rope.Cat[b, "0001"]; '2 => b _ Rope.Cat[b, "0010"]; '3 => b _ Rope.Cat[b, "0011"]; '4 => b _ Rope.Cat[b, "0100"]; '5 => b _ Rope.Cat[b, "0101"]; '6 => b _ Rope.Cat[b, "0110"]; '7 => b _ Rope.Cat[b, "0111"]; '8 => b _ Rope.Cat[b, "1000"]; '9 => b _ Rope.Cat[b, "1001"]; 'a, 'A => b _ Rope.Cat[b, "1010"]; 'b, 'B => b _ Rope.Cat[b, "1011"]; 'c, 'C => b _ Rope.Cat[b, "1100"]; 'd, 'D => b _ Rope.Cat[b, "1101"]; 'e, 'E => b _ Rope.Cat[b, "1110"]; 'f, 'F => b _ Rope.Cat[b, "1111"]; 'x, 'X => b _ Rope.Cat[b, "xxxx"]; ENDCASE => ERROR; ENDLOOP; }; BinToHex: PUBLIC PROC [b: ROPE] RETURNS [h: ROPE _ NIL] = { IF Rope.Length[b] MOD 4 # 0 THEN ERROR; FOR i: INT IN [0..Rope.Length[b]/4) DO digit: ROPE _ Rope.Substr[b, 0, 4]; b _ Rope.Substr[b, 4]; SELECT TRUE FROM Rope.Equal[digit, "0000", FALSE] => h _ Rope.Cat[h, "0"]; Rope.Equal[digit, "0001", FALSE] => h _ Rope.Cat[h, "1"]; Rope.Equal[digit, "0010", FALSE] => h _ Rope.Cat[h, "2"]; Rope.Equal[digit, "0011", FALSE] => h _ Rope.Cat[h, "3"]; Rope.Equal[digit, "0100", FALSE] => h _ Rope.Cat[h, "4"]; Rope.Equal[digit, "0101", FALSE] => h _ Rope.Cat[h, "5"]; Rope.Equal[digit, "0110", FALSE] => h _ Rope.Cat[h, "6"]; Rope.Equal[digit, "0111", FALSE] => h _ Rope.Cat[h, "7"]; Rope.Equal[digit, "1000", FALSE] => h _ Rope.Cat[h, "8"]; Rope.Equal[digit, "1001", FALSE] => h _ Rope.Cat[h, "9"]; Rope.Equal[digit, "1010", FALSE] => h _ Rope.Cat[h, "a"]; Rope.Equal[digit, "1011", FALSE] => h _ Rope.Cat[h, "b"]; Rope.Equal[digit, "1100", FALSE] => h _ Rope.Cat[h, "c"]; Rope.Equal[digit, "1101", FALSE] => h _ Rope.Cat[h, "d"]; Rope.Equal[digit, "1110", FALSE] => h _ Rope.Cat[h, "e"]; Rope.Equal[digit, "1111", FALSE] => h _ Rope.Cat[h, "f"]; Rope.Equal[digit, "xxxx", FALSE] => h _ Rope.Cat[h, "x"]; ENDCASE => ERROR; ENDLOOP; }; BlockToInterleavedBlock: PUBLIC PROC [b: ROPE] RETURNS [ib: ROPE _ NIL] = { b _ HexToBin[b]; IF Rope.Length[b]#SCParms.numBitsPerLine THEN ERROR; FOR i: NAT IN [0..SCParms.numBitsPerWord) DO FOR c: NAT IN [0..SCParms.numCyclesPerLine) DO FOR w: NAT IN [0..SCParms.numWordsPerCycle) DO ib _ Rope.Cat[ib, Rope.FromChar[Rope.Fetch[b, w*SCParms.numBitsPerWord+c*SCParms.numBitsPerCycle+i]]] ENDLOOP; ENDLOOP; ENDLOOP; ib _ BinToHex[ib]; }; InterleavedBlockToBlock: PUBLIC PROC [ib: ROPE] RETURNS [b: ROPE _ NIL] = { ib _ HexToBin[ib]; IF Rope.Length[ib]#SCParms.numBitsPerLine THEN ERROR; FOR c: NAT IN [0..SCParms.numCyclesPerLine) DO FOR w: NAT IN [0..SCParms.numWordsPerCycle) DO FOR i: NAT IN [0..SCParms.numBitsPerWord) DO b _ Rope.Cat[b, Rope.FromChar[Rope.Fetch[ib, i*SCParms.numWordsPerLine+SCParms.numWordsPerCycle*c+w]]] ENDLOOP; ENDLOOP; ENDLOOP; b _ BinToHex[b]; }; GetDesign: PUBLIC PROC [name: ROPE] RETURNS [design: CD.Design] = { design _ CDViewer.FindDesign[name]; IF design=NIL THEN design _ CDIO.ReadDesign[name, NIL, workingDirectory]; }; LayoutDesign: PUBLIC PROC [] RETURNS [design: CD.Design] = { name: ROPE _ "SmallCacheArrayLayout"; -- must declare it as a rope! IF layoutDesign=NIL THEN layoutDesign _ GetDesign[name]; design _ layoutDesign; }; <> 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.