<> <> <> <> <> DIRECTORY CD, CoreCreate, EU2Ram, EU2LeafUtils, EU2Utils, LayoutCheckpoint, Rosemary, Ports, PWCore; EU2RamImpl: CEDAR PROGRAM IMPORTS CoreCreate, EU2LeafUtils, EU2Utils, LayoutCheckpoint, Rosemary, Ports, PWCore EXPORTS EU2Ram = BEGIN OPEN CoreCreate, EU2Ram, EU2LeafUtils, EU2Utils; public: Wire _ Wires[ "Vdd", "Gnd", "dRamRead", "nPrech", Bus["ramA"], Bus["ramB"], Bus["cBus"], -- select lines Seq["selA", nRows], Seq["selB", nRows], Seq["selC", nRows], Seq["selALow", sizeSelLow], Seq["selBLow", sizeSelLow], Seq["selCLow", sizeSelLow] ]; <<>> Vdd: PUBLIC NAT _ PortIndex[public, "Vdd"]; Gnd: PUBLIC NAT _ PortIndex[public, "Gnd"]; dRamRead: PUBLIC NAT _ PortIndex[public, "dRamRead"]; nPrech: PUBLIC NAT _ PortIndex[public, "nPrech"]; selA: PUBLIC NAT _ PortIndex[public, "selA"]; selB: PUBLIC NAT _ PortIndex[public, "selB"]; selC: PUBLIC NAT _ PortIndex[public, "selC"]; selALow: PUBLIC NAT _ PortIndex[public, "selALow"]; selBLow: PUBLIC NAT _ PortIndex[public, "selBLow"]; selCLow: PUBLIC NAT _ PortIndex[public, "selCLow"]; ramA: PUBLIC NAT _ PortIndex[public, "ramA"]; ramB: PUBLIC NAT _ PortIndex[public, "ramB"]; cBus: PUBLIC NAT _ PortIndex[public, "cBus"]; <<>> <<-- (ramA, ramB, cBus)[0..32), (selA, selB, selC)[0..nRows), (selALow, selBLow, selCLow)[0..4), Vdd, Gnd, dRamRead, nPrech>> CreateEU2Ram: PUBLIC PROC RETURNS [cellType: CellType] = { top, array, mux, rw: CellInstance; IF EU2Utils.useRamCheckpoint THEN RETURN [LayoutCheckpoint.Retrieve["EU2Ram"]]; PrintStart["EU2Ram"]; mux _ Instance[type: CreateRamMux[]]; rw _ Instance[type: CreateRamReadWrite[]]; top _ Instance[type: CreateRamTop[]]; array _ Instance[type: CreateRamArray[]]; cellType _ Cell[name: "EU2Ram", public: public, onlyInternal: Wires[ Seq["naBit", wordSize, Seq[size: 4]], Bus["na"], Seq["bBit", wordSize, Seq[size: 4]], Bus["b"], Seq["ncBit", wordSize, Seq[size: 4]], Bus["nc"], Seq["cBit", wordSize, Seq[size: 4]], Bus["c"]], instances: LIST [rw, mux, array, top]]; [] _ Ports.InitPort[cellType.public[dRamRead], l, none]; [] _ Ports.InitPort[cellType.public[nPrech], l, none]; -- not used in simulation [] _ Ports.InitPort[cellType.public[selA], ls, none]; [] _ Ports.InitPort[cellType.public[selB], ls, none]; [] _ Ports.InitPort[cellType.public[selC], ls, none]; [] _ Ports.InitPort[cellType.public[selALow], ls, none]; [] _ Ports.InitPort[cellType.public[selBLow], ls, none]; [] _ Ports.InitPort[cellType.public[selCLow], ls, none]; [] _ Ports.InitPort[cellType.public[ramA], ls, drive]; [] _ Ports.InitPort[cellType.public[ramB], ls, drive]; [] _ Ports.InitPort[cellType.public[cBus], ls, none]; -- actually both ways [] _ Rosemary.BindCellType[cellType: cellType, roseClassName: EU2RamRoseClass]; [] _ Rosemary.AddCutSets[cellType: cellType, cs1: EU2RamRoseClass]; PWCore.SetAbutY[cellType]; PrintStop["EU2Ram"]; }; <<>> EU2RamRoseClass: ROPE = Rosemary.Register[roseClassName: "EU2Ram", evalSimple: EU2RamSimple]; EU2RamInit: Rosemary.InitProc = { state: EU2RamState _ NEW[EU2RamStateRec[EU2Utils.nbWords]]; FOR word: NAT IN [0..EU2Utils.nbWords) DO state.ram[word] _ NEW[Ports.LevelSequenceRec[32]]; ENDLOOP; ResetRam[state, X]; FOR bit: NAT IN [0..32) DO allXes[bit] _ X; ENDLOOP; stateAny _ state; }; allXes: Ports.LevelSequence _ NEW[Ports.LevelSequenceRec[32]]; ResetRam: PROC [state: EU2RamState, l: Ports.Level] ~ { FOR i: NAT IN [0..EU2Utils.nbWords) DO FOR bit: NAT IN [0..32) DO state.ram[i][bit] _ l; ENDLOOP; ENDLOOP; FOR bit: NAT IN [0..32) DO state.ram[constAdr][bit] _ L; ENDLOOP; }; CopyLS: PROC [source, dest: Ports.LevelSequence] ~ { FOR bit: NAT IN [0..source.size) DO dest[bit] _ source[bit]; ENDLOOP; }; <<-- ramA and ramB always output, cBus output during debugging only>> EU2RamSimple: Rosemary.EvalProc = { state: EU2RamState _ NARROW[stateAny]; {OPEN state; max: NAT _ 255; anyX, oneHiA, oneHiB, oneHiC, oneHiAlow, oneHiBlow, oneHiClow: BOOL _ FALSE; aAdr, bAdr, cAdr, aLow, bLow, cLow: NAT; FOR i: NAT IN [0..EU2Utils.nRows) DO <<-- no two select lines high at the same time>> IF p[selA].ls[i]=H THEN {IF oneHiA THEN anyX _ TRUE; aAdr _ i; oneHiA _ TRUE}; IF p[selB].ls[i]=H THEN {IF oneHiB THEN anyX _ TRUE; bAdr _ i; oneHiB _ TRUE}; IF p[selC].ls[i]=H THEN {IF oneHiC THEN anyX _ TRUE; cAdr _ i; oneHiC _ TRUE}; anyX _ anyX OR p[selA].ls[i]=X OR p[selB].ls[i]=X OR p[selC].ls[i]=X; ENDLOOP; FOR i: NAT IN [0..EU2Utils.sizeSelLow) DO <<-- no two select lines high at the same time>> IF p[selALow].ls[i]=H THEN { IF oneHiAlow THEN anyX _ TRUE; aLow _ i; oneHiAlow _ TRUE}; IF p[selBLow].ls[i]=H THEN { IF oneHiBlow THEN anyX _ TRUE; bLow _ i; oneHiBlow _ TRUE}; IF p[selCLow].ls[i]=H THEN { IF oneHiClow THEN anyX _ TRUE; cLow _ i; oneHiClow _ TRUE}; ENDLOOP; IF oneHiC AND oneHiClow THEN CopyLS[p[cBus].ls, ram[4*cAdr+cLow]]; IF anyX THEN ResetRam[state, X]; -- nasty stuff!!! CopyLS[IF oneHiA AND oneHiAlow THEN ram[4*aAdr+aLow] ELSE allXes, p[ramA].ls]; CopyLS[IF oneHiB AND oneHiBlow THEN ram[4*bAdr+bLow] ELSE allXes, p[ramB].ls]; p[cBus].d _ none; IF p[dRamRead].l=H THEN {p[cBus].d _ drive; CopyLS[ram[4*aAdr+aLow], p[cBus].ls]}; IF p[dRamRead].l=X THEN {p[cBus].d _ drive; CopyLS[allXes, p[cBus].ls]}; }}; <<>> <<>> <<-- Pull-up on top>> <<-- (naBit, bBit, cBit, ncBit)[0..32)[0..4), nPrech, Vdd, Gnd>> CreateRamTop: PROC RETURNS [cellType: CellType] = { cellType _ SequenceCell[name: "RamTop", baseCell: CreatePrechQuadSt[], count: wordSize, sequencePorts: Wires["naBit", "bBit", "cBit", "ncBit"]]; PWCore.SetArrayX[cellType]; }; <<>> <<-- (naBit, bBit)[0..4), nPrech, Vdd, Gnd>> CreatePrechQuadSt: PROC RETURNS [cellType: CellType] = { q: CellInstance _ Instance[type: CreatePrechQuad[]]; s: CellInstance _ Instance[type: Extract["RamPrechSt.sch"]]; cellType _ Cell[name: "PrechQuadSt", public: Wires[Seq["naBit", 4], Seq["bBit", 4], Seq["cBit", 4], Seq["ncBit", 4], "nPrech", "Vdd", "Gnd"], instances: LIST [q, s]]; PWCore.SetAbutX[cellType]; }; CreatePrechQuad: PROC RETURNS [cellType: CellType] = { cellType _ SequenceCell[name: "PrechQuad", baseCell: Extract["RamPrech.sch"], count: 4, sequencePorts: Wires["naBit", "bBit", "cBit", "ncBit"]]; PWCore.SetArrayX[cellType]; }; <<>> <<-- The complete array: a mess because of these ROM bits (cf. EMM)>> <<-- The row 33 (= constAdr/4) has one ROM word and three RAM words.>> <<-- The row zero is on top (because of CONS and AbutY)>> <<-- (naBit, bBit, cBit, ncBit)[0..32)[0..4), (selA, selB, selC)[0..nRows), Vdd, Gnd>> CreateRamArray: PROC RETURNS [cellType: CellType] = { insts: CellInstances _ NIL; ramRow: CellType _ CreateRamRow[]; ramPair: CellType _ CreateRowPair[ramRow, ramRow]; ramRomPair: CellType _ CreateRowPair[ramRow, CreateRamRomRow[]]; IF constAdr/4 MOD 2=0 THEN ERROR; -- otherwise change the orientation of the rom row! FOR i: NAT IN [0..nRows/2) DO insts _ CONS[ Instance[IF i=constAdr/8 THEN ramRomPair ELSE ramPair, ["selA0", Index["selA", 2*i]], ["selA1", Index["selA", 2*i+1]], ["selB0", Index["selB", 2*i]], ["selB1", Index["selB", 2*i+1]], ["selC0", Index["selC", 2*i]], ["selC1", Index["selC", 2*i+1]]], insts]; ENDLOOP; cellType _ Cell[name: "RamArray", public: Wires["Vdd", "Gnd", Seq["selA", nRows], Seq["selB", nRows], Seq["selC", nRows], Seq["naBit", wordSize, Seq[size: 4]], Seq["bBit", wordSize, Seq[size: 4]], Seq["cBit", wordSize, Seq[size: 4]], Seq["ncBit", wordSize, Seq[size: 4]] ], instances: insts]; PWCore.SetAbutY[cellType]; }; <<>> <<-- The pairs of rows>> <<-- (naBit, bBit, cBit, ncBit)[0..32)[0..4), (selA, selB, selC)[0..2), Vdd, Gnd>> CreateRowPair: PROC[topCt, botCt: CellType] RETURNS [cellType: CellType] = { top, bot: CellInstance; top _ Instance[topCt, ["selA", "selA0"], ["selB", "selB0"], ["selC", "selC0"]]; bot _ Instance[PWCore.RotateCellType[botCt, $FlipY], ["selA", "selA1"], ["selB", "selB1"], ["selC", "selC1"]]; cellType _ Cell[name: "RowPair", public: Wires["Vdd", "Gnd", "selA0", "selA1", "selB0", "selB1", "selC0", "selC1", Seq["naBit", wordSize, Seq[size: 4]], Seq["bBit", wordSize, Seq[size: 4]], Seq["cBit", wordSize, Seq[size: 4]], Seq["ncBit", wordSize, Seq[size: 4]] ], instances: LIST[bot, top]]; PWCore.SetAbutY[cellType]; }; <<>> <<-- The RAM and ROM row>> <<-- (naBit, bBit, cBit, ncBit)[0..32)[0..4), (selA, selB, selC), Vdd, Gnd>> CreateRamRomRow: PROC RETURNS [cellType: CellType] = { cellType _ SequenceCell[name: "RamRomRow", baseCell: CreateRamRomQuadSt[], count: wordSize, sequencePorts: Wires["naBit", "bBit", "cBit", "ncBit"]]; PWCore.SetArrayX[cellType]; }; <<-- (naBit, bBit, cBit, ncBit)[0..4), selA, selB, selC, Vdd, Gnd>> CreateRamRomQuadSt: PROC RETURNS [cellType: CellType] = { ramCell: CellType _ Extract["RamCell.sch"]; rom0: CellInstance _ Instance[Extract["Rom0Cell.sch"], ["naBit", "naBit[0]"], ["bBit", "bBit[0]"], ["cBit", "cBit[0]"], ["ncBit", "ncBit[0]"]]; ram1: CellInstance _ Instance[ramCell, ["naBit", "naBit[1]"], ["bBit", "bBit[1]"], ["cBit", "cBit[1]"], ["ncBit", "ncBit[1]"]]; ram2: CellInstance _ Instance[ramCell, ["naBit", "naBit[2]"], ["bBit", "bBit[2]"], ["cBit", "cBit[2]"], ["ncBit", "ncBit[2]"]]; ram3: CellInstance _ Instance[ramCell, ["naBit", "naBit[3]"], ["bBit", "bBit[3]"], ["cBit", "cBit[3]"], ["ncBit", "ncBit[3]"]]; s: CellInstance _ Instance[Extract["RamStitch.sch"]]; cellType _ Cell[name: "RamRomQuadSt", public: Wires["Vdd", "Gnd", "selA", "selB", "selC", Seq["naBit", 4], Seq["bBit", 4], Seq["cBit", 4], Seq["ncBit", 4]], instances: LIST [rom0, ram1, ram2, ram3, s]]; PWCore.SetAbutX[cellType]; }; <<>> <<-- The RAM row>> <<-- (naBit, bBit, cBit, ncBit)[0..32)[0..4), (selA, selB, selC)[0..2), Vdd, Gnd>> CreateRamRow: PROC RETURNS [cellType: CellType] = { cellType _ SequenceCell[name: "RamRow", baseCell: CreateRamQuadSt[], count: wordSize, sequencePorts: Wires["naBit", "bBit", "cBit", "ncBit"]]; PWCore.SetArrayX[cellType]; }; <<-- (naBit, bBit, cBit, ncBit)[0..4), selA, selB, selC, Vdd, Gnd>> CreateRamQuadSt: PROC RETURNS [cellType: CellType] = { q: CellInstance _ Instance[type: CreateRamQuad[]]; s: CellInstance _ Instance[type: Extract["RamStitch.sch"]]; cellType _ Cell[name: "RamQuadSt", public: Wires["Vdd", "Gnd", "selA", "selB", "selC", Seq["naBit", 4], Seq["bBit", 4], Seq["cBit", 4], Seq["ncBit", 4]], instances: LIST [q, s]]; PWCore.SetAbutX[cellType]; }; <<-- (naBit, bBit, cBit, ncBit)[0..4), selA, selB, selC, Vdd, Gnd>> CreateRamQuad: PROC RETURNS [cellType: CellType] = { cellType _ SequenceCell[name: "RamQuad", baseCell: Extract["RamCell.sch"], count: 4, sequencePorts: Wires["naBit", "bBit", "cBit", "ncBit"]]; PWCore.SetArrayX[cellType]; }; <<-- Muxes on bottom>> <<-- (naBit, bBit, cBit, ncBit)[0..4)[0..32), (a, b, c, nc)[0..32), (selALow, selBLow, selCLow)[0..4), Gnd>> CreateRamMux: PROC RETURNS [cellType: CellType] = { cellType _ SequenceCell[name: "RamMux", baseCell: Extract["MuxQuadSt.sch"], count: wordSize, sequencePorts: Wires["naBit", "bBit", "cBit", "ncBit", "na", "b", "c", "nc"]]; PWCore.SetArrayX[cellType]; }; <<>> <<-- Read-write on bottom>> <<-- (na, b, c, nc, ramA, ramB, cBus)[0..32), dRamRead, Vdd, Gnd>> CreateRamReadWrite: PROC RETURNS [cellType: CellType] = { cellType _ SequenceCell[name: "RamReadWrite", baseCell: Extract["RamRW.sch"], count: wordSize, sequencePorts: Wires["na", "b", "c", "nc", "ramA", "ramB", "cBus"]]; PWCore.SetArrayX[cellType]; }; <<>> <<>> END.