-- TamRegFileCells.mesa
Copyright Ó 1987 by Xerox Corporation. All rights reserved.
September 29, 1987 10:01:20 pm PDT
Last Edited by: Krivacic April June 26, 1987 3:09:37 pm PDT
Last Edited by: Alan Bell September 28, 1987 5:28:42 pm PDT
DIRECTORY
Basics, BitOps, Core, CoreCreate, CoreFlat, CoreClasses, Logic, CoreProperties, Ports, Rosemary, RosemaryUser, TamPorts, Rope, TamDefs, TerminalIO, IO;
TamRegFileCells: CEDAR PROGRAM
IMPORTS Ports, Rosemary, TamPorts, TerminalIO, IO
= BEGIN OPEN TamDefs, TamPorts;
-- Register File Implementation
banks: NAT = 6;
bankSize: NAT = 40;
nextRegAddr: NAT ← 0;
curRegAddr: ARRAY BOOL OF NAT;
registerArray: ARRAY [0..576) OF Rope.ROPE;
debug: BOOL ← FALSE;
RegisterFile: PUBLIC PROC[r: Rope.ROPE, uWriteOctal, uDSwap: BOOL, regAddr: NAT, nClock, nClock2, writeOk, writeBack: BOOL] RETURNS [d1, d2: Rope.ROPE]= {
IF nClock2 THEN nextRegAddr ← regAddr ELSE {curRegAddr[~nClock] ← nextRegAddr; IF debug THEN TerminalIO.PutF["Set RegAddr[%g] ← %g \n", IO.bool[~nClock], IO.int[nextRegAddr]];
};
d1 ← registerArray[curRegAddr[TRUE]];
d2 ← (IF (curRegAddr[TRUE]-1) >= 0 THEN registerArray[curRegAddr[TRUE]-1] ELSE "0000000000000000000000000000000000");
IF d1 = NIL THEN d1 ← "0000000000000000000000000000000000";
IF d2 = NIL THEN d2 ← "0000000000000000000000000000000000";
IF uDSwap THEN {temp: Rope.ROPE ← d1; d1 ← d2; d2 ← temp;};
IF nClock2 AND nClock AND writeOk AND writeBack THEN {
registerArray[curRegAddr[FALSE]] ← r;
IF debug THEN TerminalIO.PutF["Write RegAddr[%g] ← %g \n", IO.int[curRegAddr[FALSE]], IO.rope[r]];
IF uWriteOctal THEN
FOR i: NAT ← curRegAddr[FALSE] + 1, i + 1 WHILE (i MOD 8) # 0 DO
registerArray[i] ← r;
ENDLOOP;
};
};
-------------------- Create RegFile Cell ---------------------
RegisterFileState: TYPE = REF RegisterFileStateRec;
RegisterFileStateRec: TYPE = RECORD [
d1, d2, r, writeBack, writeOk, nextRegAddr, nClock2, nClock, writeOctal, dSwap, rd1addr, rd2addr, state, vdd, gnd: NATLAST[NAT]];
-- Rosemary Register File Initialization
RegisterFileInit: Rosemary.InitProc = {
--PROC [cellType: Core.CellType, p: Ports.Port] RETURNS [stateAny: REF ANY ← NIL]--
state: RegisterFileState ← NEW[RegisterFileStateRec];
[state.vdd, state.gnd] ← Ports.PortIndexes[cellType.public, "Vdd", "Gnd"];
[state.r, state.nextRegAddr, state.writeOctal, state.dSwap, state.rd1addr, state.rd2addr, state.writeBack, state.writeOk, state.nClock2, state.nClock ] ← Ports.PortIndexes[cellType.public, "R", "NextRegAddr", "WriteOctal", "DSwap", "RD1addr", "RD2addr", "WriteBack", "WriteOk", "nClock2", "nClock"];
[state.d1, state.d2] ← Ports.PortIndexes[cellType.public, "D1", "D2"];
[] ← Rosemary.SetFixedWire[cellType.public[state.vdd], H];
[] ← Rosemary.SetFixedWire[cellType.public[state.gnd], L];
stateAny ← state;
};
-- Rosemary Register File Eval Proc
RegisterFileEvalSimple: Rosemary.EvalProc = {
PROC [p: Ports.Port, stateAny: REF ANY]--
XSet: PROC [p: Ports.Port, index: NAT, val: CARD, name: ATOMNIL] =
{
IF HasXs[p, index] THEN {
SetPVal[p, index, val];
p[index].d ← none;
IF clockset THEN TerminalIO.PutF["X Input in Reg File: %g index: %g \n", IO.atom[name], IO.int[index]];
};
};
state: RegisterFileState   ← NARROW[stateAny];
d1, d2: Rope.ROPE;
clockset: BOOLTRUE;
anyXs: BOOLFALSE;
-- Clear any inputs with X'x
XSet[p, state.nClock, 0, $nClock];
XSet[p, state.nClock2, 0, $nClock2];
clockset ← PortToBool[p,state.nClock2];
XSet[p, state.r, 0, $r];
XSet[p, state.writeBack, 0, $writeBack];
XSet[p, state.writeOk, 0, $writeOk];
XSet[p, state.dSwap, 0, $dSwap];
XSet[p, state.rd1addr, 0, $rd1addr];
XSet[p, state.rd2addr, 0, $rd2addr];
XSet[p, state.nextRegAddr, 0, $nextRegAddr];
IF ~anyXs THEN {
[d1, d2] ←
RegisterFile[Ports.LSToRope[p[state.r].ls, 34, 2], PortToBool[p,state.writeOctal], PortToBool[p,state.dSwap], PortToNat[p,state.nextRegAddr], PortToBool[p,state.nClock], PortToBool[p,state.nClock2], PortToBool[p,state.writeOk], PortToBool[p,state.writeBack] ];
TamPorts.RopeToLS[d1, p[state.d1].ls];
TamPorts.RopeToLS[d2, p[state.d2].ls];
p[state.d1].d ← (IF PortToNat[p,state.rd1addr] = 0 THEN drive ELSE none);
p[state.d2].d ← (IF PortToNat[p,state.rd2addr] = 0 THEN drive ELSE none);
}
ELSE {
p[state.d1].d ← none;
p[state.d2].d ← none;
};
};
regFileName: Rope.ROPE ← Rosemary.Register[roseClassName: "RegisterFileTile", init: RegisterFileInit, evalSimple: RegisterFileEvalSimple];
END.