EU2RamImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Louis Monier May 29, 1986 3:36:59 pm PDT
Barth, April 22, 1986 4:30:34 pm PST
Bertrand Serlet May 11, 1986 7:45:06 pm PDT
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.