SCArrayImpl.mesa
Created: Paraminder Sahai September 1, 1987 6:55:41 am PDT
Paraminder Sahai September 27, 1987 0:53:06 am PDT
Pradeep Sindhu January 21, 1988 3:52:02 pm PST
DIRECTORY
Core, CoreClasses, CoreCreate, CoreFlat, CoreOps, IO, Ports, Rosemary, RosemaryUser, Rope, SCLogic, SCParms, TerminalIO;
SCArrayImpl: CEDAR PROGRAM
IMPORTS CoreClasses, CoreCreate, CoreFlat, CoreOps, IO, Ports, Rosemary, Rope, SCParms, TerminalIO
EXPORTS SCLogic
~ BEGIN OPEN SCLogic;
Constants and Type Defs
ClockEvalEnabled: BOOL = TRUE;
MySCName: ROPE = Rosemary.Register[roseClassName: "SCArray", init: Init, evalSimple: Simple, scheduleIfClockEval: ClockEvalEnabled];
NumFlagsBits: NAT = 4;
NumMemLines: NAT = 2*SCParms.numMemLines;
NumIOLines: NAT = 2*3;
NumBytesPerWord: NAT = SCParms.numBytesPerWord;
NumBitsPerByte: NAT = SCParms.numBitsPerByte;
NumBitsPerWord: NAT = SCParms.numBitsPerWord;
NumWordsPerLine: NAT = SCParms.numWordsPerLine;
NumBitsPerLine: NAT = SCParms.numBitsPerLine;
LogNumWordsPerLine: NAT = SCParms.logNumWordsPerLine;
NumBitsPerCycle: NAT = SCParms.numBitsPerCycle;
NumAddressBits: NAT = NumBitsPerWord+1;   --Includes IO/Mem Bit--
NumPageBits: NAT = SCParms.numPageBits+1;   --Includes IO/Mem Bit--
NumBlockBits: NAT = SCParms.numBlockBits;
NumPageAndBlockBits: NAT = NumPageBits+NumBlockBits;
NumDevIdBits: NAT = SCParms.numDevIdBits;
IOVCamLine: ARRAY [0..NumIOLines) OF Rope.ROPE = [
Rope.Cat[SCParms.vPagePattern, SCParms.vBlock0Pattern],
Rope.Cat[SCParms.vPagePattern, SCParms.vBlock1Pattern],
Rope.Cat[SCParms.vPagePattern, SCParms.vBlock2Pattern],
Rope.Cat[SCParms.vPagePattern, SCParms.vBlock3Pattern],
Rope.Cat[SCParms.vPagePattern, SCParms.vBlock4Pattern],
Rope.Cat[SCParms.vPagePattern, SCParms.vBlock5Pattern]];
IORCamLine: ARRAY[0..NumIOLines) OF Rope.ROPE = [
Rope.Cat[SCParms.rPagePattern, SCParms.rBlock0Pattern],
Rope.Cat[SCParms.rPagePattern, SCParms.rBlock1Pattern],
Rope.Cat[SCParms.rPagePattern, SCParms.rBlock2Pattern],
Rope.Cat[SCParms.rPagePattern, SCParms.rBlock3Pattern],
Rope.Cat[SCParms.rPagePattern, SCParms.rBlock4Pattern],
Rope.Cat[SCParms.rPagePattern, SCParms.rBlock5Pattern]];
IOFlagsLine: ARRAY[0..NumIOLines) OF Rope.ROPE = ["1111", "0011", "0011", "0011", "0011", "0011"];
Two-D array containing Victim, RamSel, LRM, LVM, RML2, RML3, RML4, and GND
Match: TYPE = REF MatchRec;
MatchRec: TYPE = RECORD [
ARRAY Index OF LevelSequence
];
IOMatch: TYPE = REF IOMatchRec;
IOMatchRec: TYPE = RECORD [
ARRAY Index[LRM..GND] OF LevelSequence
];
Array: TYPE = REF ArrayRec;
ArrayRec: TYPE = RECORD [
SEQUENCE size: NAT OF LevelSequence
];
KindOfMatch: TYPE = {Virtual, Real};
Index: TYPE = {Victim, RamSel, LRM, LVM, RML2, RML3, RML4, GND};
CacheState: TYPE = REF CacheStateRec;
CacheStateRec: TYPE = RECORD [
prevClk: Level,
match: Match ← NIL,   -- contains mem array ctl bits (see def)
iomatch: ARRAY Index[LRM..GND] OF ARRAY [0..NumIOLines) OF Level,
csMuxSR: Level,   -- flop in CSMuxInterface
rsCmdLatch : ARRAY[0..1] OF Level,  -- latch in RSMuxInterface
csOut, rsOut, iorsOut: Index,  -- to implement csmux, rsmux, iorsmux
bCycle: ARRAY [3..5] OF Level,   -- delay stages in RML234
victimIndex: INT,   -- line pointed to by victim
use: LevelSequence ← NIL,  -- use bits in array
soSR: ARRAY [0..1] OF Level,  -- delay stages in SOInterface
sh, ow: LevelSequence ← NIL,   -- sh ow bits in array
shBit, owBit: Level,   -- sh and ow bits in SORdLatch
pWtInProgB: Level,   -- output of SOInterface
ldSORdLatch: Level,   -- input to SOInterface
ramWtSR, ramRdSR: ARRAY [0..1] OF Level, -- 2 flops each in RamInterfaceCtl
ramRdorWt: Level,   -- flop to generate Prech
ramRdLatch: LevelSequence ← NIL,  -- ramRdLatch in RamInterface
ram: Array ← NIL,   -- ram bits
ioRam: RECORD [cWSOld, cWSNew, aID, faultCode, intStatus, intMask, modes, lFCode1, lFCode3, lFCode5, lFCode7: LevelSequence ← NIL], -- ioram bits
vCamCSCmd1, rCamCSCmd1: Level,  -- latches in RCam and VCam Interfaces
rCam, vCam: Array ← NIL,  -- rcam and vcam bits
arm, avm: Level,   -- values of arm and avm
ioRCam, ioVCam: ARRAY [0..NumIOLines) OF LevelSequence, -- iorcam and iovcam bits
flags: Array ← NIL,   -- flags array
ioFlags: ARRAY [0..NumIOLines) OF ARRAY [0..NumFlagsBits) OF Level, -- ioflags array
rCamRdLatch, rCamWtReg, vCamRdLatch, vCamWtReg: LevelSequence,
flagsRdLatch, flagsWtReg: ARRAY [0..NumFlagsBits) OF Level,
vCamPartMch, rCamPartMch: Level,  -- flops to delay PartMch
vCamDrBLFF, rCamDrBLFF: Level,   -- flops for CamDrBL
vCamRdSR, rCamRdSR: ARRAY [0..2] OF Level, -- flops for RdCam; odd indeces correspond to flops clocked by nClock, even to those clocked by Clock
vCamSel: Index,   -- source of input for vcam select line
aVct: Level,    -- arrayVictim
resetDone: BOOLEAN,   -- used to suppress error due to X's before Reset has been done
The following are used to capture input signals that go to flops
tmpRAdrsIn, tmpVAdrsInOut: LevelSequence ← NIL,
tmpFlagsIn: ARRAY [0..NumFlagsBits) OF Level,
tmpxEnCamSel,
tmpBCycle2,
tmpxWtRam,
tmpxRdRam,
tmpramRdorWt,
tmpxLdVCamWR,
tmpxDrVCamBL,
tmpxRdVCam,
tmpxRdRCam,
tmpVPValidIn,
tmpRPValidIn,
tmpxPartRMch,
tmpPCtlPartVMch,
tmpPWtInProg,
tmpxDrRCamBL,
tmpxLdRCamWR: Level
];
Signal Defs
debug: BOOLFALSE;
Reset, LdRML1, LdVML, ClrVPV, PCtlResetVictim, Spare, RamClock, xLdUse, PCtlDrABusVB, PCtlDrABusVP, PCtlPartVMch, xRdVCam, xLdVCamWR, xDrVCamBL, VAdrsInOut, VPValidIn, PCtlDrABusRB, PCtlDrABusRP, xRdRCam, xPartRMch, xDrRCamBL, xLdRCamWR, xEnCamSelExt, BCycle2, RAdrsIn, RPValidIn, FlagsIn, nPMFlags, xEnCamSel, PCtlShftVictim4, PCtlFrzVictim, xCSCmd, nEnRS, xRSCmd, PWtInProg, BCtlSetOw, BCtlClrOw, SetSh, ClrSh, xRdRam, xWtRam, nxSelWdData, nxByteSel, nxWdSel, WdWtData, BlkWtData, Modes, RAdrsOut, FlagsOut, BlkRdData, WdRdData, SetReschedule, ASh, AOw, ARM, AVM, Clock, nClock: NAT;
Public Procs
SCArray: PUBLIC PROC [] RETURNS [ct: CellType] = BEGIN
public: Wire ← CoreCreate.WireList[LIST["Reset", "LdRML1", "LdVML", "ClrVPV", "PCtlResetVictim", CoreCreate.Seq["Spare", NumBitsPerCycle], "RamClock", "xLdUse", "PCtlDrABusVB", "PCtlDrABusVP", "PCtlPartVMch", "xRdVCam", "xLdVCamWR", "xDrVCamBL", CoreCreate.Seq["VAdrsInOut", NumAddressBits], "VPValidIn", "PCtlDrABusRB", "PCtlDrABusRP", "xRdRCam", "xPartRMch", "xDrRCamBL", "xLdRCamWR", "xEnCamSelExt", "BCycle2", CoreCreate.Seq["RAdrsIn", NumAddressBits], "RPValidIn", CoreCreate.Seq["FlagsIn", NumFlagsBits], CoreCreate.Seq["nPMFlags", NumFlagsBits], "xEnCamSel", "PCtlShftVictim4", "PCtlFrzVictim", CoreCreate.Seq["xCSCmd", 2], "nEnRS", CoreCreate.Seq["xRSCmd",2], "PWtInProg", "BCtlSetOw", "BCtlClrOw", "SetSh", "ClrSh", "xRdRam", "xWtRam", "nxSelWdData", CoreCreate.Seq["nxByteSel", NumBytesPerWord], CoreCreate.Seq["nxWdSel", NumWordsPerLine], CoreCreate.Seq["WdWtData", NumBitsPerWord], CoreCreate.Seq["BlkWtData", NumBitsPerLine], CoreCreate.Seq["Modes", NumBitsPerWord], CoreCreate.Seq["RAdrsOut", NumAddressBits], CoreCreate.Seq["FlagsOut", NumFlagsBits], CoreCreate.Seq["BlkRdData", NumBitsPerLine], CoreCreate.Seq["WdRdData", NumBitsPerWord], "SetReschedule", "ASh", "AOw", "ARM", "AVM", "Clock", "nClock"]];
ct ← CoreClasses.CreateUnspecified[public: public];
[] ← Rosemary.BindCellType[cellType: ct, roseClassName: MySCName];
[] ← CoreFlat.CellTypeCutLabels[ct, "Logic"];
[] ← Ports.InitPort[public[CoreOps.GetWireIndex[public, "VAdrsInOut"]], ls, separate, none, NEW [Ports.DriveSequenceRec[NumAddressBits]]];
Ports.InitPorts[ct, ls, none, "RAdrsIn"];
[] ← Ports.InitPort[public[CoreOps.GetWireIndex[public, "RAdrsOut"]], ls, separate, none, NEW [Ports.DriveSequenceRec[NumAddressBits]]];
Ports.InitPorts[ct, ls, none, "Spare"];
Ports.InitPorts[ct, ls, none, "FlagsIn"];
Ports.InitPorts[ct, ls, none, "nPMFlags"];
Ports.InitPorts[ct, ls, none, "xCSCmd"];
Ports.InitPorts[ct, ls, none, "xRSCmd"];
Ports.InitPorts[ct, ls, none, "nxByteSel"];
Ports.InitPorts[ct, ls, none, "nxWdSel"];
Ports.InitPorts[ct, ls, none, "WdWtData"];
Ports.InitPorts[ct, ls, none, "BlkWtData"];
[] ← Ports.InitPort[public[CoreOps.GetWireIndex[public, "FlagsOut"]], ls, separate, none, NEW [Ports.DriveSequenceRec[NumFlagsBits]]];
Ports.InitPorts[ct, ls, drive, "Modes"];
Ports.InitPorts[ct, ls, drive, "BlkRdData"];
Ports.InitPorts[ct, ls, drive, "WdRdData"];
Ports.InitPorts[ct, l, none, "Reset", "LdRML1", "LdVML", "ClrVPV"];
Ports.InitPorts[ct, l, none, "PCtlResetVictim", "Spare", "xLdUse", "PCtlDrABusVB", "PCtlDrABusVP", "PCtlPartVMch", "xRdVCam", "xLdVCamWR", "xDrVCamBL"];
Ports.InitPorts[ct, l, none, "Clock", "nClock", "VPValidIn", "PCtlDrABusRB", "PCtlDrABusRP", "xRdRCam", "xPartRMch", "xDrRCamBL", "xLdRCamWR", "xEnCamSelExt", "BCycle2"];
Ports.InitPorts[ct, l, none, "xEnCamSel", "PCtlShftVictim4", "PCtlFrzVictim", "nEnRS"];
Ports.InitPorts[ct, l, none, "PWtInProg", "BCtlSetOw", "BCtlClrOw", "SetSh", "ClrSh", "xRdRam", "xWtRam", "nxSelWdData", "RPValidIn"];
Ports.InitPorts[ct, l, drive, "RamClock"];
Ports.InitPorts[ct, l, drive, "SetReschedule", "ASh", "AOw", "ARM", "AVM"]
END;
Internal Procs
Init: Rosemary.InitProc = BEGIN
i, j: INT;
k: Index;
cs: CacheState;
Create the state if it doesn't already exist
IF oldStateAny=NIL
THEN {
cs ← NEW [CacheStateRec];
cs.match ← NEW[MatchRec];
FOR k: Index IN Index DO
cs.match[k] ← NEW [LevelSequenceRec[NumMemLines]]
ENDLOOP;
cs.use ← NEW [LevelSequenceRec[NumMemLines]];
cs.sh ← NEW [LevelSequenceRec[NumMemLines]];
cs.ow ← NEW [LevelSequenceRec[NumMemLines]];
cs.ramRdLatch ← NEW [LevelSequenceRec[NumBitsPerLine]];
cs.ram ← NEW [ArrayRec[NumMemLines]];
FOR i: NAT IN [0..NumMemLines) DO
cs.ram[i] ← NEW [LevelSequenceRec[NumBitsPerLine]];
ENDLOOP;
cs.ioRam.cWSOld ← NEW [LevelSequenceRec[NumBitsPerWord]];
cs.ioRam.cWSNew ← NEW [LevelSequenceRec[NumBitsPerWord]];
cs.ioRam.aID ← NEW [LevelSequenceRec[NumBitsPerWord]];
cs.ioRam.faultCode ← NEW [LevelSequenceRec[NumBitsPerWord]];
cs.ioRam.intStatus ← NEW [LevelSequenceRec[NumBitsPerWord]];
cs.ioRam.intMask ← NEW [LevelSequenceRec[NumBitsPerWord]];
cs.ioRam.modes ← NEW [LevelSequenceRec[NumBitsPerWord]];
cs.ioRam.lFCode1 ← NEW [LevelSequenceRec[NumBitsPerWord]];
cs.ioRam.lFCode3 ← NEW [LevelSequenceRec[NumBitsPerWord]];
cs.ioRam.lFCode5 ← NEW [LevelSequenceRec[NumBitsPerWord]];
cs.ioRam.lFCode7 ← NEW [LevelSequenceRec[NumBitsPerWord]];
cs.rCam ← NEW [ArrayRec[NumMemLines]];
FOR i: NAT IN [0..NumMemLines) DO
cs.rCam[i] ← NEW [LevelSequenceRec[NumAddressBits]];
ENDLOOP;
cs.vCam ← NEW [ArrayRec[NumMemLines]];
FOR i: NAT IN [0..NumMemLines) DO
cs.vCam[i] ← NEW [LevelSequenceRec[NumAddressBits]];
ENDLOOP;
cs.arm ← X; cs.avm ← X;
FOR i: NAT IN [0..NumIOLines) DO
cs.ioRCam[i] ← NEW [LevelSequenceRec[NumAddressBits]];
ENDLOOP;
FOR i: NAT IN [0..NumIOLines) DO
cs.ioVCam[i] ← NEW [LevelSequenceRec[NumAddressBits]];
ENDLOOP;
cs.flags ← NEW [ArrayRec[NumMemLines]];
FOR i: NAT IN [0..NumMemLines) DO
cs.flags[i] ← NEW [LevelSequenceRec[NumFlagsBits]];
ENDLOOP;
cs.rCamRdLatch ← NEW [LevelSequenceRec[NumAddressBits]];
cs.rCamWtReg ← NEW [LevelSequenceRec[NumAddressBits]];
cs.vCamRdLatch ← NEW [LevelSequenceRec[NumAddressBits]];
cs.vCamWtReg ← NEW [LevelSequenceRec[NumAddressBits]];
cs.tmpRAdrsIn ← NEW [LevelSequenceRec[NumAddressBits]];
cs.tmpVAdrsInOut ← NEW [LevelSequenceRec[NumAddressBits]];
}
ELSE cs ← NARROW[oldStateAny, CacheState];
cs.prevClk ← X; cs.vCamCSCmd1 ← X; cs.rCamCSCmd1 ← X; cs.aVct ← X; cs.vCamPartMch ← X; cs.rCamPartMch ← X; cs.ramRdorWt ← X; cs.pWtInProgB ← X; cs.ldSORdLatch ← X;
FOR i IN [0..NumAddressBits) DO
cs.vCamRdLatch[i] ← X; cs.vCamWtReg[i] ← X; cs.rCamRdLatch[i] ← X; cs.rCamWtReg[i] ← X;
ENDLOOP;
FOR i IN [0..NumFlagsBits) DO
cs.flagsRdLatch[i] ← X; cs.flagsWtReg[i] ← X;
ENDLOOP;
FOR i IN [0..NumBitsPerLine) DO
cs.ramRdLatch[i] ← X;
ENDLOOP;
FOR i IN [0..NumMemLines) DO
cs.vCam[i][0] ← L; cs.vCam[i][NumAddressBits-1] ← X;
cs.rCam[i][0] ← L; cs.rCam[i][NumAddressBits-1] ← X;
FOR j IN [NumPageAndBlockBits..NumPageAndBlockBits+LogNumWordsPerLine-2] DO
cs.vCam[i][j] ← L; cs.rCam[i][j] ← L;
ENDLOOP;
FOR j IN [1..NumPageAndBlockBits) DO
cs.vCam[i][j] ← X; cs.rCam[i][j] ← X;
ENDLOOP;
FOR j IN [0..NumFlagsBits) DO
cs.flags[i][j] ← X;
ENDLOOP;
FOR j IN [0..NumBitsPerLine) DO
cs.ram[i][j] ← X;
ENDLOOP;
cs.use[i] ← X; cs.sh[i] ← X; cs.ow[i] ← X;
FOR k IN [Victim..RML4] DO
cs.match[k][i] ← X;
ENDLOOP;
cs.match[GND][i] ← L;
ENDLOOP;
cs.shBit ← X; cs.owBit ← X;
cs.csMuxSR ← X;
FOR i IN [0..1] DO
cs.rsCmdLatch[i] ← X;
cs.ramWtSR[i] ← X;
cs.ramRdSR[i] ← X;
cs.soSR[i] ← X;
ENDLOOP;
FOR i IN [3..5] DO
cs.bCycle[i] ← X;
ENDLOOP;
cs.vCamDrBLFF ← X; cs.rCamDrBLFF ← X;
FOR i IN [0..2] DO
cs.vCamRdSR[i] ← X; cs.rCamRdSR[i] ← X;
ENDLOOP;
cs.tmpxEnCamSel ← X;
FOR i IN [0..NumAddressBits) DO
cs.tmpRAdrsIn[i] ← X; cs.tmpVAdrsInOut[i] ← X;
ENDLOOP;
FOR i IN [0..NumFlagsBits) DO
cs.tmpFlagsIn[i] ← X;
ENDLOOP;
cs.tmpBCycle2 ← X; cs.tmpxWtRam ← X; cs.tmpxRdRam ← X; cs.tmpramRdorWt ← X; cs.tmpxLdVCamWR ← X; cs.tmpxRdVCam ← p[xRdVCam].l; cs.tmpxRdRCam ← X; cs.tmpVPValidIn ← X; cs.tmpRPValidIn ← X; cs.tmpxPartRMch ← X; cs.tmpPCtlPartVMch ← X; cs.tmpPWtInProg ← X; cs.tmpxDrRCamBL ← X; cs.tmpxLdRCamWR ← X; cs.tmpxDrVCamBL ← X;
FOR i IN [0..NumIOLines) DO
FOR j IN [NumPageAndBlockBits..NumPageAndBlockBits+LogNumWordsPerLine-2] DO
cs.ioVCam[i][j] ← L; cs.ioRCam[i][j] ← L;
ENDLOOP;
cs.ioVCam[i][NumAddressBits-1] ← H;
cs.ioRCam[i][NumAddressBits-1] ← H;
ENDLOOP;
FOR i IN [0..NumIOLines) DO
FOR j IN [0..NumFlagsBits) DO
cs.ioFlags[i][j] ← IF Rope.Fetch[IOFlagsLine[i], j] = '1 THEN H ELSE L;
ENDLOOP;
FOR j IN [0..NumPageAndBlockBits) DO
cs.ioVCam[i][j] ← IF Rope.Fetch[IOVCamLine[i], j] = '1 THEN H ELSE L;
cs.ioRCam[i][j] ← IF Rope.Fetch[IORCamLine[i], j] = '1 THEN H ELSE L;
ENDLOOP;
ENDLOOP;
FOR i IN [0..NumBitsPerWord) DO
cs.ioRam.cWSOld[i] ← X;
cs.ioRam.cWSNew[i] ← X;
cs.ioRam.aID[i] ← X;
cs.ioRam.faultCode[i] ← X;
cs.ioRam.intStatus[i] ← X;
cs.ioRam.intMask[i] ← X;
cs.ioRam.modes[i] ← X;
cs.ioRam.lFCode1[i] ← H;
cs.ioRam.lFCode3[i] ← H;
cs.ioRam.lFCode5[i] ← H;
cs.ioRam.lFCode7[i] ← H;
ENDLOOP;
FOR i IN [0..NumIOLines) DO
FOR k IN [LRM..RML4] DO
cs.iomatch[k][i] ← X;
ENDLOOP;
cs.iomatch[GND][i] ← L;
ENDLOOP;
cs.resetDone ← FALSE;
[Reset, LdRML1, LdVML, ClrVPV] ← Ports.PortIndexes[cellType.public, "Reset", "LdRML1", "LdVML", "ClrVPV"];
[PCtlResetVictim, Spare, RamClock, xLdUse, PCtlDrABusVB, PCtlDrABusVP, PCtlPartVMch, xRdVCam, xLdVCamWR, xDrVCamBL, VAdrsInOut, VPValidIn] ← Ports.PortIndexes[cellType.public, "PCtlResetVictim", "Spare", "RamClock", "xLdUse", "PCtlDrABusVB", "PCtlDrABusVP", "PCtlPartVMch", "xRdVCam", "xLdVCamWR", "xDrVCamBL", "VAdrsInOut", "VPValidIn"];
[PCtlDrABusRB, PCtlDrABusRP, xRdRCam, xPartRMch, xDrRCamBL, xLdRCamWR, xEnCamSelExt, BCycle2, RAdrsIn, RPValidIn, FlagsIn] ← Ports.PortIndexes[cellType.public, "PCtlDrABusRB", "PCtlDrABusRP", "xRdRCam", "xPartRMch", "xDrRCamBL", "xLdRCamWR", "xEnCamSelExt", "BCycle2", "RAdrsIn", "RPValidIn", "FlagsIn"];
[nPMFlags, xEnCamSel, PCtlShftVictim4, PCtlFrzVictim, xCSCmd, nEnRS, xRSCmd, PWtInProg, BCtlSetOw, BCtlClrOw] ← Ports.PortIndexes[cellType.public, "nPMFlags", "xEnCamSel", "PCtlShftVictim4", "PCtlFrzVictim", "xCSCmd", "nEnRS", "xRSCmd", "PWtInProg", "BCtlSetOw", "BCtlClrOw"];
[SetSh, ClrSh, xRdRam, xWtRam, nxSelWdData, nxByteSel, nxWdSel, WdWtData, BlkWtData, Modes, RAdrsOut] ← Ports.PortIndexes[cellType.public, "SetSh", "ClrSh", "xRdRam", "xWtRam", "nxSelWdData", "nxByteSel", "nxWdSel", "WdWtData", "BlkWtData", "Modes", "RAdrsOut"];
[FlagsOut, BlkRdData, WdRdData, SetReschedule, ASh, AOw] ← Ports.PortIndexes[cellType.public, "FlagsOut", "BlkRdData", "WdRdData", "SetReschedule", "ASh", "AOw"];
[ARM, AVM, Clock, nClock] ← Ports.PortIndexes[cellType.public, "ARM", "AVM", "Clock", "nClock"];
stateAny ← cs;
END;
Simple: Rosemary.EvalProc = BEGIN
cs: CacheState ← NARROW[stateAny];
IF p[Reset].l = H THEN cs.resetDone ← TRUE;
IF ClockL[p, cs, clockEval] THEN CaptureL[p, cs];
IF ClockH[p, cs, clockEval] THEN CaptureH[p, cs];
CSMux[p, cs, clockEval];
RSMux[p, cs];
RML234[p, cs, clockEval];
Victim[p, cs, clockEval];
VCamRCamAndFlags[p, cs, clockEval];
SOAndRam[p, cs, clockEval];
IF ClockLToH[p, cs, clockEval] AND debug THEN PrintState[cs];
IF (NOT ClockEvalEnabled) OR (NOT clockEval) THEN cs.prevClk ← p[Clock].l;
END;
ClockLToH: PROC[p: Ports.Port, cs: CacheState, clockEval: BOOL] RETURNS[BOOL] = {
IF ClockEvalEnabled
THEN RETURN[NOT clockEval AND cs.prevClk=L AND p[Clock].l=H]
ELSE RETURN[cs.prevClk=L AND p[Clock].l=H]
};
ClockHToL: PROC[p: Ports.Port, cs: CacheState, clockEval: BOOL] RETURNS[BOOL] = {
IF ClockEvalEnabled
THEN RETURN[NOT clockEval AND cs.prevClk=H AND p[Clock].l=L]
ELSE RETURN[cs.prevClk=H AND p[Clock].l=L]
};
ClockL: PROC[p: Ports.Port, cs: CacheState, clockEval: BOOL] RETURNS[BOOL] = {
IF ClockEvalEnabled
THEN RETURN[NOT clockEval AND p[Clock].l=L]
ELSE RETURN[p[Clock].l=L]
};
ClockH: PROC[p: Ports.Port, cs: CacheState, clockEval: BOOL] RETURNS[BOOL] = {
IF ClockEvalEnabled
THEN RETURN[NOT clockEval AND p[Clock].l=H]
ELSE RETURN[p[Clock].l=H]
};
For signals going to flops triggered by Clock
CaptureL: PROC[p: Ports.Port, cs: CacheState] = BEGIN
FOR i: INT IN [0..NumAddressBits) DO
cs.tmpRAdrsIn[i] ← p[RAdrsIn].ls[i]; cs.tmpVAdrsInOut[i] ← p[VAdrsInOut].ls[i];
ENDLOOP;
FOR i: INT IN [0..NumFlagsBits) DO
cs.tmpFlagsIn[i] ← p[FlagsIn].ls[i];
ENDLOOP;
cs.tmpBCycle2 ← p[BCycle2].l; cs.tmpxWtRam ← p[xWtRam].l; cs.tmpxRdRam ← p[xRdRam].l; cs.tmpxLdVCamWR ← p[xLdVCamWR].l; cs.tmpxRdVCam ← p[xRdVCam].l; cs.tmpxRdRCam ← p[xRdRCam].l; cs.tmpVPValidIn ← p[VPValidIn].l; cs.tmpRPValidIn ← p[RPValidIn].l; cs.tmpxPartRMch ← p[xPartRMch].l; cs.tmpPCtlPartVMch ← p[PCtlPartVMch].l; cs.tmpPWtInProg ← p[PWtInProg].l; cs.tmpxDrRCamBL ← p[xDrRCamBL].l; cs.tmpxLdRCamWR ← p[xLdRCamWR].l; cs.tmpxDrVCamBL ← p[xDrVCamBL].l;
END;
For signals going to flops triggered by nClock
CaptureH: PROC[p: Ports.Port, cs: CacheState] = BEGIN
cs.tmpxEnCamSel ← p[xEnCamSel].l;
cs.tmpramRdorWt ← Ports.OrL[p[xRdRam].l, p[xWtRam].l];
END;
PrintLS: PROC[ls: LevelSequence] = BEGIN
FOR i: NAT IN [0..ls.size) DO
SELECT ls[i] FROM
L => TerminalIO.PutRope["0"];
H => TerminalIO.PutRope["1"];
X => TerminalIO.PutRope["x"];
ENDCASE => ERROR;
ENDLOOP;
END;
PrintState: PROC[cs: CacheState] = BEGIN
FOR i: NAT IN [0..NumMemLines) DO
TerminalIO.PutF["\nLine: %g VCam: ", IO.int[i]]; PrintLS[cs.vCam[i]];
TerminalIO.PutRope[" RCam: "]; PrintLS[cs.rCam[i]];
TerminalIO.PutRope[" Flags: "]; PrintLS[cs.flags[i]];
TerminalIO.PutRope[" Ram: "]; PrintLS[cs.ram[i]];
ENDLOOP;
TerminalIO.PutF[" Victim: %g", IO.int[cs.victimIndex]];
END;
CSMux: PROC[p: Ports.Port, cs: CacheState, clockEval: BOOL] = BEGIN
i: INT;
First the state changes
IF ClockHToL[p, cs, clockEval] THEN cs.csMuxSR ← cs.tmpxEnCamSel;
Then the combinatorial part
IF cs.csMuxSR = L THEN cs.csOut ← GND;
IF cs.csMuxSR = H THEN {
IF p[xCSCmd].ls[0] = H THEN i ← 2 ELSE i ← 0;
IF p[xCSCmd].ls[1] = H THEN i ← i + 1;
IF i = 0 THEN
cs.csOut ← GND
ELSE
IF i = 1 THEN
cs.csOut ← RML3
ELSE
IF i = 2 THEN
cs.csOut ← LVM
ELSE IF i = 3 THEN
cs.csOut ← Victim;
};
END;
RSMux: PROC[p: Ports.Port, cs: CacheState] = BEGIN
i: INT;
First the state change to the latch
IF p[nEnRS].l=H THEN {
FOR i IN [0..1] DO
cs.rsCmdLatch[i] ← p[xRSCmd].ls[i];
ENDLOOP;
};
Then the combinatorial part
IF cs.rsCmdLatch[0] = H THEN i ← 2 ELSE i ← 0;
IF cs.rsCmdLatch[1] = H THEN i ← i + 1;
IF i = 0 THEN {
cs.rsOut ← GND;
cs.iorsOut ← GND;
}
ELSE
IF i = 1 THEN {
cs.rsOut ← RML4;
cs.iorsOut ← RML4;
}
ELSE
IF i = 2 THEN {
cs.rsOut ← LVM;
cs.iorsOut ← LVM;
}
ELSE
IF i = 3 THEN {
cs.rsOut ← Victim;
cs.iorsOut ← GND;
};
END;
RML234: PROC[p: Ports.Port, cs: CacheState, clockEval: BOOL] = BEGIN
On clock rising edge change the state for flops in the interface
IF ClockLToH[p, cs, clockEval] THEN {
cs.bCycle[5] ← cs.bCycle[4];
cs.bCycle[4] ← cs.bCycle[3];
cs.bCycle[3] ← cs.tmpBCycle2;
};
Note that the array latches are enabled only during half cycles where Clock is low
IF ClockL[p, cs, clockEval] THEN {
IF cs.bCycle[3] = H THEN {
cs.match[RML2] ← cs.match[LRM];
cs.iomatch[RML2] ← cs.iomatch[LRM];
};
IF cs.bCycle[4] = H THEN {
cs.match[RML3] ← cs.match[RML2];
cs.iomatch[RML3] ← cs.iomatch[RML2];
};
IF cs.bCycle[5] = H THEN {
cs.match[RML4] ← cs.match[RML3];
cs.iomatch[RML4] ← cs.iomatch[RML3];
};
};
END;
Victim: PROC[p: Ports.Port, cs: CacheState, clockEval: BOOL] = BEGIN
i: INT;
DecMod: PROC[n: INT] RETURNS [INT] = BEGIN
RETURN[IF n=0 THEN NumMemLines-1 ELSE n-1]
END;
Rising edge of clock
IF ClockLToH[p, cs, clockEval] THEN {
IF p[PCtlFrzVictim].l = H THEN cs.use[cs.victimIndex] ← L;
IF p[PCtlShftVictim4].l = H THEN {
IF cs.use[cs.victimIndex] = H THEN {
cs.match[Victim][cs.victimIndex] ← L;
cs.victimIndex ← DecMod[cs.victimIndex];
cs.match[Victim][cs.victimIndex] ← H
}
ELSE
cs.use[cs.victimIndex] ← H;
}
ELSE {
IF cs.use[cs.victimIndex] = H THEN {
cs.use[cs.victimIndex] ← L;
cs.match[Victim][cs.victimIndex] ← L;
cs.victimIndex ← DecMod[cs.victimIndex];
cs.match[Victim][cs.victimIndex] ← H;
};
};
IF p[xLdUse].l = H THEN {
FOR i IN [0..NumMemLines) DO
IF cs.match[LVM][i] = H THEN cs.use[i] ← H ;
ENDLOOP;
};
};
On Reset we set all the use bits to 0, and set victim to point to some location
IF p[Reset].l = H OR p[PCtlResetVictim].l=H THEN {
FOR i IN [0..NumMemLines) DO
cs.use[i] ← L; cs.match[Victim][i] ← L;
ENDLOOP;
cs.match[Victim][NumMemLines-1] ← H;
cs.victimIndex ← NumMemLines-1;
cs.aVct ← H;
};
END;
SOAndRam: PROC[p: Ports.Port, cs: CacheState, clockEval: BOOL] = BEGIN
i, j, k,
RamIndex,  -- index of ramselect line that is high (if only one is high)
IORamIndex, -- index of ioramselect line that is high (if only one is high)
numH,  -- number of ramSelectOut lines high (total of ram and ioram)
numX: INT;  -- number of ramSelectOut lines that are x (total of ram and ioram)
prech: Level;
Do the computation for the PWtInProg path in SOInterface
IF ClockLToH[p, cs, clockEval] THEN cs.soSR[0] ← cs.tmpPWtInProg;
IF ClockHToL[p, cs, clockEval] THEN cs.soSR[1] ← cs.soSR[0];
IF cs.soSR[0] = H OR cs.soSR[1] = H THEN cs.pWtInProgB ← H ELSE cs.pWtInProgB ← L;
Compute the values of Sh and Ow bits in array (Ow computation is completed below)
FOR i IN [0..NumMemLines) DO
IF cs.match[cs.rsOut][i]=H
THEN {
IF p[BCtlClrOw].l=H AND p[BCtlSetOw].l=H
THEN cs.ow[i] ← X
ELSE {
IF p[BCtlSetOw].l=H
THEN cs.ow[i] ← H
ELSE IF p[BCtlClrOw].l=H THEN cs.ow[i] ← L;
};
IF p[ClrSh].l=H AND p[SetSh].l=H
THEN cs.sh[i] ← X
ELSE {
IF p[SetSh].l=H
THEN cs.sh[i] ← H
ELSE IF p[ClrSh].l = H THEN cs.sh[i] ← L;
}
}
ELSE {
IF cs.match[cs.rsOut][i]=X THEN {
IF (p[BCtlSetOw].l=H AND cs.ow[i]#H) OR (p[BCtlClrOw].l=H AND cs.ow[i]#L) OR (p[BCtlClrOw].l=H AND p[BCtlSetOw].l=H)
THEN cs.ow[i] ← X;
IF (p[SetSh].l=H AND cs.sh[i]#H) OR (p[ClrSh].l=H AND cs.sh[i]#L) OR (p[ClrSh].l=H AND p[SetSh].l=H)
THEN cs.sh[i] ← X;
};
};
ENDLOOP;
Compute RamSelectOut, numH, numX and complete computation of Ow
numH ← 0; numX ← 0;
RamIndex ← -1; IORamIndex ← -1;
FOR i IN [0..NumMemLines) DO
IF p[nEnRS].l=L AND ((cs.pWtInProgB=L) OR (cs.pWtInProgB=H AND cs.sh[i]=L))
THEN cs.match[RamSel][i] ← cs.match[cs.rsOut][i]
ELSE
IF p[nEnRS].l=L AND cs.pWtInProgB=H AND ((cs.match[cs.rsOut][i]=H AND cs.sh[i]=X) OR (cs.match[cs.rsOut][i]=X AND cs.sh[i]=X) OR (cs.match[cs.rsOut][i]=X AND cs.sh[i]=L))
THEN cs.match[RamSel][i] ← X
ELSE cs.match[RamSel][i] ← L;
IF cs.match[RamSel][i] = H
THEN {numH ← numH + 1; RamIndex ← i}
ELSE {IF cs.match[RamSel][i] = X THEN numX ← numX + 1};
IF p[nEnRS].l=L AND cs.pWtInProgB=H AND cs.match[cs.rsOut][i]=H
THEN {
IF cs.sh[i]=L
THEN {cs.ow[i] ← IF p[BCtlClrOw].l=L THEN H ELSE X}
ELSE
IF cs.sh[i]=X AND p[BCtlClrOw].l=H
THEN cs.ow[i] ← X
ELSE IF cs.sh[i]=X AND p[BCtlSetOw].l=L AND p[BCtlClrOw].l=L AND cs.ow[i]#H THEN cs.ow[i] ← X
}
ELSE {
IF p[nEnRS].l=L AND cs.pWtInProgB=H AND cs.match[cs.rsOut][i]=X THEN {
IF cs.sh[i]#H AND p[BCtlClrOw].l=H
THEN cs.ow[i] ← X
ELSE IF cs.sh[i]#H AND p[BCtlClrOw].l=L AND p[BCtlSetOw].l=L AND cs.ow[i]#H THEN cs.ow[i] ← X;
}
}
ENDLOOP;
Compute outputs of IOSharedOwnerCell's, and complete computation of numH and numX
IF p[nEnRS].l=H
THEN cs.iorsOut ← GND
ELSE FOR i IN [0..NumIOLines) DO
IF cs.iomatch[cs.iorsOut][i] = H
THEN {numH ← numH + 1; IORamIndex ← i}
ELSE {IF cs.iomatch[cs.iorsOut][i] = X THEN numX ← numX + 1};
ENDLOOP;
Sanity check on numH and numX
IF (numH > 1 OR numX > 0) AND cs.resetDone THEN ERROR;
Change the state of flops in RamInterfaceCtl triggered by Clock
IF ClockLToH[p, cs, clockEval] THEN {
cs.ramWtSR[0] ← cs.tmpxWtRam;
cs.ramRdSR[0] ← cs.tmpxRdRam;
};
Do a Ram Read/Write and change the state of flops in RamInterfaceCtl triggered by nClock
IF ClockHToL[p, cs, clockEval] THEN {
Handle reads
IF cs.ramRdSR[0] = H THEN {
IF RamIndex >= 0
THEN FOR i IN [0..NumBitsPerLine) DO
cs.ramRdLatch[i] ← cs.ram[RamIndex][i];
ENDLOOP
ELSE IORam[p, cs, IORamIndex];
};
Handle writes
IF cs.ramWtSR[0] = H THEN {
IF RamIndex >= 0
THEN {
IF p[nxSelWdData].l = H
THEN FOR i IN [0..NumBitsPerLine) DO
cs.ram[RamIndex][i] ← p[BlkWtData].ls[i];
ENDLOOP
ELSE {
j ← IndexOfSelectedWord[p];
FOR i IN [0..NumBitsPerWord) DO
k ← i/NumBitsPerByte;
IF p[nxByteSel].ls[k] = L THEN cs.ram[RamIndex][j] ← p[WdWtData].ls[i];
j← j+NumBitsPerWord;
ENDLOOP;
};
}
ELSE IORam[p, cs, IORamIndex];
};
cs.ramWtSR[1] ← cs.ramWtSR[0];
cs.ramRdSR[1] ← cs.ramRdSR[0];
cs.ramRdorWt ← cs.tmpramRdorWt
};
Assert the block and word values onto the ports from the RamRdLatch
Ports.CopyLS[cs.ramRdLatch, p[BlkRdData].ls];
IF p[nxSelWdData].l = L THEN {
adrs: NAT ← IndexOfSelectedWord[p];
FOR i: NAT IN [0..NumBitsPerWord) DO
p[WdRdData].ls[i] ← cs.ramRdLatch[adrs];
adrs ← adrs+NumBitsPerWord;
ENDLOOP
};
Compute SetReschedule
p[SetReschedule].l ← L;
numX ← 0;
FOR i IN [0..NumBitsPerWord) DO
IF cs.ioRam.intStatus[i]=H AND cs.ioRam.intMask[i]=H
THEN p[SetReschedule].l ← H
ELSE IF cs.ioRam.intStatus[i]#L AND cs.ioRam.intMask[i]#L THEN
numX ← numX+1;
ENDLOOP;
IF p[SetReschedule].l = L AND numX > 0 THEN p[SetReschedule].l ← X;
Compute ldSORdLatch in RamInterfaceCtl
IF cs.ramWtSR[0] = H OR cs.ramWtSR[1] = H OR cs.ramRdSR[0] = H OR cs.ramRdSR[1] = H
THEN cs.ldSORdLatch ← H
ELSE cs.ldSORdLatch ← L;
Compute composite values on lines going in to SOInterface from array and load SORdlatch
IF cs.ldSORdLatch = H THEN BEGIN
In numShAB, A is the value of the enable on the tristates, and B the value in storage
numShHH: INT ← 0;
numShHL: INT ← 0;
numShHX: INT ← 0;
numShXH: INT ← 0;
numShXL: INT ← 0;
numShXX: INT ← 0;
numOwHH: INT ← 0;
numOwHL: INT ← 0;
numOwHX: INT ← 0;
numOwXH: INT ← 0;
numOwXL: INT ← 0;
numOwXX: INT ← 0;
FOR i IN [0..NumMemLines) DO
IF cs.match[cs.rsOut][i]=H
THEN {
IF cs.sh[i]=H
THEN numShHH ← numShHH+1
ELSE IF cs.sh[i] = L
THEN numShHL ← numShHL+1
ELSE numShHX ← numShHX+1;
IF cs.ow[i]=H
THEN numOwHH ← numOwHH + 1
ELSE IF cs.ow[i] = L
THEN numOwHL ← numOwHL+1
ELSE numOwHX ← numOwHX+1;
}
ELSE {
IF cs.match[cs.rsOut][i]=X
THEN {
IF cs.sh[i] = H
THEN numShXH ← numShXH+1
ELSE IF cs.sh[i]=L
THEN numShXL ← numShXL+1
ELSE numShXX ← numShXX+1;
IF cs.ow[i] = H
THEN numOwXH ← numOwXH+1
ELSE IF cs.ow[i] = L
THEN numOwXL ← numOwXL+1
ELSE numOwXX ← numOwXX+1;
}
}
ENDLOOP;
FOR i IN [0..NumIOLines) DO
IF cs.iomatch[cs.iorsOut][i] = H
THEN numOwHH ← numOwHH + 1
ELSE IF cs.iomatch[cs.iorsOut][i] = X THEN numOwXH ← numOwXH + 1;
ENDLOOP;
IF numShHH+numShHL+numShHX+numShXH+numShXL+numShXX = 0
THEN cs.shBit ← L
ELSE IF numShHH>0 AND numShHL+numShXL+numShXX+numShHX = 0
THEN cs.shBit ← H
ELSE IF numShHL>0 AND numShHH+numShHX+numShXX+numShXH = 0
THEN cs.shBit ← L
ELSE cs.shBit ← X;
IF numOwHH+numOwHL+numOwHX+numOwXH+numOwXL+numOwXX = 0
THEN cs.owBit ← L
ELSE IF numOwHH>0 AND numOwHL+numOwXL+numOwXX+numOwHX = 0
THEN cs.owBit ← H
ELSE IF numOwHL>0 AND numOwHH+numOwHX+numOwXX+numOwXH = 0
THEN cs.owBit ← L
ELSE cs.owBit ← X;
END;
Assert Modes onto its port
FOR i: NAT IN [0..NumBitsPerWord) DO p[Modes].ls[i] ← cs.ioRam.modes[i] ENDLOOP;
Assert shared and owner onto their ports
p[ASh].l ← cs.shBit; p[AOw].l ← cs.owBit;
Assert RamClock onto its port
prech ← Ports.AndL[cs.ramRdorWt, Ports.OrL[p[xRdRam].l, p[xWtRam].l]];
p[RamClock].l ← Ports.AndL[p[nEnRS].l, prech];
Clear shared and owner latches in interface
IF p[Reset].l = H THEN {cs.shBit ← L; cs.owBit ← L};
END;
IORam: PROC[p: Ports.Port, cs: CacheState, ioRamIndex: INT] = BEGIN
j, k, l: INT;
j ← IndexOfSelectedWord[p]; l ← j;
Handle Read
IF cs.ramRdSR[0] = H THEN {
FOR k IN [0..NumBitsPerLine) DO
cs.ramRdLatch[k] ← H;-- Precharge value
ENDLOOP;
IF p[nxSelWdData].l = L THEN {
IF ioRamIndex = 0 AND j = 1 THEN
FOR k IN [0..NumBitsPerWord) DO
cs.ramRdLatch[j] ← cs.ioRam.cWSOld[k]; j ← j+NumBitsPerWord;
ENDLOOP
ELSE
IF ioRamIndex = 0 AND j = 3 THEN
FOR k IN [0..NumBitsPerWord) DO
cs.ramRdLatch[j] ← cs.ioRam.cWSNew[k]; j ← j+NumBitsPerWord;
ENDLOOP
ELSE
IF ioRamIndex = 1 AND j = 1 THEN
FOR k IN [0..NumBitsPerWord) DO
cs.ramRdLatch[j] ← cs.ioRam.aID[k]; j ← j+NumBitsPerWord;
ENDLOOP
ELSE
IF ioRamIndex = 1 AND j = 3 THEN
FOR k IN [0..NumBitsPerWord) DO
cs.ramRdLatch[j] ← cs.ioRam.faultCode[k]; j ← j+NumBitsPerWord;
ENDLOOP
ELSE
IF ioRamIndex = 1 AND j = 5 THEN
FOR k IN [0..NumBitsPerWord) DO
cs.ramRdLatch[j] ← cs.ioRam.intStatus[k]; j ← j+NumBitsPerWord;
ENDLOOP
ELSE
IF ioRamIndex = 1 AND j = 7 THEN
FOR k IN [0..NumBitsPerWord) DO
cs.ramRdLatch[j] ← cs.ioRam.intMask[k]; j ← j+NumBitsPerWord;
ENDLOOP
ELSE
IF ioRamIndex = 4 AND j = 5 THEN
FOR k IN [0..NumBitsPerWord) DO
cs.ramRdLatch[j] ← cs.ioRam.modes[k]; j ← j+NumBitsPerWord;
ENDLOOP
ELSE
IF ioRamIndex = 5 AND j = 1 THEN
FOR k IN [0..NumBitsPerWord) DO
cs.ramRdLatch[j] ← cs.ioRam.lFCode1[k]; j ← j+NumBitsPerWord;
ENDLOOP
ELSE
IF ioRamIndex = 5 AND j = 3 THEN
FOR k IN [0..NumBitsPerWord) DO
cs.ramRdLatch[j] ← cs.ioRam.lFCode3[k]; j ← j+NumBitsPerWord;
ENDLOOP
ELSE
IF ioRamIndex = 5 AND j = 5 THEN
FOR k IN [0..NumBitsPerWord) DO
cs.ramRdLatch[j] ← cs.ioRam.lFCode5[k]; j ← j+NumBitsPerWord;
ENDLOOP
ELSE
IF ioRamIndex = 5 AND j = 7 THEN FOR k IN [0..NumBitsPerWord) DO
cs.ramRdLatch[j] ← cs.ioRam.lFCode7[k]; j ← j+NumBitsPerWord;
ENDLOOP;
};
};
Handle Write
IF cs.ramWtSR[0] = H THEN {
IF p[nxSelWdData].l = L THEN {
IF ioRamIndex = 0 AND j = 1 THEN
FOR k IN [0..NumBitsPerWord) DO
l ← k/NumBitsPerByte;
IF p[nxByteSel].ls[l] = L THEN
cs.ioRam.cWSOld[k] ← p[WdWtData].ls[k];
ENDLOOP
ELSE
IF ioRamIndex = 0 AND j = 3 THEN
FOR k IN [0..NumBitsPerWord) DO
l ← k/NumBitsPerByte;
IF p[nxByteSel].ls[l] = L THEN
cs.ioRam.cWSNew[k] ← p[WdWtData].ls[k];
ENDLOOP
ELSE
IF ioRamIndex = 1 AND j = 1 THEN
FOR k IN [0..NumBitsPerWord) DO
l ← k/NumBitsPerByte;
IF p[nxByteSel].ls[l] = L THEN
cs.ioRam.aID[k] ← p[WdWtData].ls[k];
ENDLOOP
ELSE
IF ioRamIndex = 1 AND j = 3 THEN
FOR k IN [0..NumBitsPerWord) DO
l ← k/NumBitsPerByte;
IF p[nxByteSel].ls[l] = L THEN
cs.ioRam.faultCode[k] ← p[WdWtData].ls[k];
ENDLOOP
ELSE
IF ioRamIndex = 1 AND j = 5 THEN
FOR k IN [0..NumBitsPerWord) DO
l ← k/NumBitsPerByte;
IF p[nxByteSel].ls[l] = L THEN
cs.ioRam.intStatus[k] ← p[WdWtData].ls[k];
ENDLOOP
ELSE
IF ioRamIndex = 1 AND j = 7 THEN
FOR k IN [0..NumBitsPerWord) DO
l ← k/NumBitsPerByte;
IF p[nxByteSel].ls[l] = L THEN
cs.ioRam.intMask[k] ← p[WdWtData].ls[k];
ENDLOOP
ELSE
IF ioRamIndex = 4 AND j = 5 THEN
FOR k IN [0..NumBitsPerWord) DO
l ← k/NumBitsPerByte;
IF p[nxByteSel].ls[l] = L THEN
cs.ioRam.modes[k] ← p[WdWtData].ls[k];
ENDLOOP
ELSE
IF ioRamIndex = 2 AND j = 5 THEN
FOR k IN[0..NumBitsPerWord) DO
IF p[WdWtData].ls[k] = H THEN
cs.ioRam.intStatus[k] ← L
ELSE
IF p[WdWtData].ls[k] = X AND cs.ioRam.intStatus[k] # L THEN
cs.ioRam.intStatus[k] ← X;
ENDLOOP
ELSE
IF ioRamIndex = 3 AND j = 5 THEN
FOR k IN [0..NumBitsPerWord) DO
IF p[WdWtData].ls[k] = H THEN
cs.ioRam.intStatus[k] ← H
ELSE
IF p[WdWtData].ls[k] = X AND cs.ioRam.intStatus[k] # H THEN
cs.ioRam.intStatus[k] ← X;
ENDLOOP;
};
};
END;
IndexOfSelectedWord: PROC[p: Ports.Port] RETURNS[INT ← 0] = BEGIN
FOR i: INT IN [0..NumWordsPerLine) DO
IF p[nxWdSel].ls[i] = L THEN RETURN [i]
ENDLOOP;
END;
VCamRCamAndFlags: PROC[p: Ports.Port, cs: CacheState, clockEval: BOOL] = BEGIN
i, j,
vCamIndex,  -- index of vCamSelect line that is high (if only one)
rCamIndex,  -- index of rCamSelect line that is high (if only one)
numX, numH: INT; -- number of rCamSelect lines that are X (H)
Check if either set of tristates on VCamInterface are on
CRdVCam: PROC[p: Ports.Port, cs: CacheState ] RETURNS [ b: BOOLEAN] = BEGIN
IF (p[PCtlDrABusVB].l = H OR p[PCtlDrABusVP].l = H) AND ((cs.vCamCSCmd1 = H AND cs.aVct = H) OR (cs.vCamCSCmd1 = L AND cs.avm = H)) THEN
b ← TRUE ELSE b ← FALSE
END;
Check if either set of tristates on RCamInterface are on
CRdRCam: PROC[p: Ports.Port, cs: CacheState ] RETURNS [ b: BOOLEAN] = BEGIN
IF (p[PCtlDrABusRB].l = H OR p[PCtlDrABusRP].l = H) AND ((cs.rCamCSCmd1 = H AND cs.aVct = H) OR (cs.rCamCSCmd1 = L AND cs.avm = H)) THEN
b ← TRUE ELSE b ← FALSE;
END;
Handle the effect of xEnCamSelExt
cs.vCamSel ← IF p[xEnCamSelExt].l = H THEN cs.csOut ELSE GND;
Compute vCamIndex, rCamIndex, numX, and numH
vCamIndex ← -1; rCamIndex ← -1;
numX ← 0; numH ← 0;
FOR i IN [0..NumMemLines) DO
IF cs.match[cs.csOut][i] = H
THEN {numH ← numH + 1; rCamIndex ← i}
ELSE IF cs.match[cs.csOut][i] = X THEN numX ← numX+1;
IF cs.match[cs.vCamSel][i] = H THEN vCamIndex ← i;
ENDLOOP;
IF numX > 0 AND cs.resetDone THEN ERROR;
IF numH > 1 AND p[xEnCamSelExt].l = H AND cs.resetDone THEN ERROR;
Change the state of flops clocked by nClock in CamInterfaceCtl's
IF ClockHToL[p, cs, clockEval] THEN {
cs.vCamRdSR[1] ← cs.vCamRdSR[0];
cs.rCamRdSR[1] ← cs.rCamRdSR[0];
};
Handle latch that holds CSCmd1
IF cs.vCamRdSR[1] = H THEN cs.vCamCSCmd1 ← p[xCSCmd].ls[1];
IF cs.rCamRdSR[1] = H THEN cs.rCamCSCmd1 ← p[xCSCmd].ls[1];
On rising edge of clock:
IF ClockLToH[p, cs, clockEval] THEN {
Change state of read flops in CamInterfaceCtl's
cs.vCamRdSR[2] ← cs.vCamRdSR[1];
cs.vCamRdSR[0] ← cs.tmpxRdVCam;
cs.rCamRdSR[2] ← cs.rCamRdSR[1];
cs.rCamRdSR[0] ← cs.tmpxRdRCam;
If read ctl signal has been H for 2 cycles and exactly one select line is high then read
IF cs.vCamRdSR[0] = H AND cs.vCamRdSR[2] = H THEN FOR j IN [0..NumAddressBits) DO
cs.vCamRdLatch[j] ← IF vCamIndex >= 0 THEN cs.vCam[vCamIndex][j] ELSE H;
ENDLOOP;
IF cs.rCamRdSR[0] = H AND cs.rCamRdSR[2] = H THEN {
FOR j IN [0..NumAddressBits) DO
cs.rCamRdLatch[j] ← IF rCamIndex >= 0 THEN cs.rCam[rCamIndex][j] ELSE H;
ENDLOOP;
FOR j IN [0..NumFlagsBits) DO
cs.flagsRdLatch[j] ← IF rCamIndex >= 0 THEN cs.flags[rCamIndex][j] ELSE H;
ENDLOOP;
};
Change state of write flops in CamInterfaceCtl's
cs.vCamDrBLFF ← cs.tmpxDrVCamBL;
cs.rCamDrBLFF ← cs.tmpxDrRCamBL;
First load the write registers for vcam and rcam; note that valid bits are always enabled
IF cs.tmpxLdVCamWR = H THEN {
FOR i IN [0..NumPageAndBlockBits) DO
cs.vCamWtReg[i] ← cs.tmpVAdrsInOut[i];
ENDLOOP;
FOR i IN [0..NumFlagsBits) DO
cs.flagsWtReg[i] ← cs.tmpFlagsIn[i];
ENDLOOP;
};
cs.vCamWtReg[NumAddressBits-1] ← cs.tmpVPValidIn;
IF cs.tmpxLdRCamWR = H THEN {
FOR i IN [0..NumPageAndBlockBits) DO
cs.rCamWtReg[i] ← cs.tmpRAdrsIn[i];
ENDLOOP;
};
cs.rCamWtReg[NumAddressBits-1] ← cs.tmpRPValidIn;
Then drive the bit lines and do a write or match, as appropriate
IF cs.vCamDrBLFF = H THEN {
IF cs.vCamRdSR[2] = H THEN {
FOR j IN [0..NumPageAndBlockBits) DO
cs.vCamRdLatch[j] ← cs.vCamWtReg[j];
ENDLOOP;
cs.vCamRdLatch[NumAddressBits-1] ← cs.vCamWtReg[NumAddressBits-1];
};
IF vCamIndex < 0
THEN ComputeMatch[p, cs, Virtual]
ELSE {
FOR j IN [1..NumPageAndBlockBits) DO
cs.vCam[vCamIndex][j] ← cs.vCamWtReg[j];
ENDLOOP;
cs.vCam[vCamIndex][NumAddressBits-1] ← cs.vCamWtReg[NumAddressBits-1];
FOR j IN [0..NumFlagsBits) DO
IF p[nPMFlags].ls[j] = H
THEN cs.flags[vCamIndex][j] ← cs.flagsWtReg[j]
ELSE cs.flags[vCamIndex][j] ← L;
ENDLOOP;
};
};
IF cs.rCamDrBLFF = H THEN {
IF cs.rCamRdSR[2] = H THEN {
FOR j IN [0..NumPageAndBlockBits) DO
cs.rCamRdLatch[j] ← cs.rCamWtReg[j];
ENDLOOP;
cs.rCamRdLatch[NumAddressBits-1] ← cs.rCamWtReg[NumAddressBits-1];
};
IF rCamIndex < 0
THEN ComputeMatch[p, cs, Real]
ELSE {
FOR j IN [1..NumPageAndBlockBits) DO
cs.rCam[rCamIndex][j] ← cs.rCamWtReg[j];
ENDLOOP;
cs.rCam[rCamIndex][NumAddressBits-1] ← cs.rCamWtReg[NumAddressBits-1];
};
};
cs.vCamPartMch ← cs.tmpPCtlPartVMch; cs.rCamPartMch ← cs.tmpxPartRMch;
};
Assert avm and arm values onto port
p[AVM].l ← cs.avm; p[ARM].l ← cs.arm;
If either block or page part VCamInterface tristates are on then output the appropriate one(s)
IF CRdVCam[p, cs]
THEN {
IF p[PCtlDrABusVP].l = H
THEN {
FOR i IN [0..NumPageBits) DO
p[VAdrsInOut].ds[i] ← drive;
p[VAdrsInOut].ls[i] ← cs.vCamRdLatch[i];
ENDLOOP;
FOR i IN [NumPageAndBlockBits..NumAddressBits-1) DO
p[VAdrsInOut].ds[i] ← drive;
p[VAdrsInOut].ls[i] ← L;
ENDLOOP;
p[VAdrsInOut].ds[NumAddressBits-1] ← drive;
p[VAdrsInOut].ls[NumAddressBits-1] ← cs.vCamRdLatch[NumAddressBits-1];
}
ELSE {
FOR i IN [0..NumPageBits) DO
p[VAdrsInOut].ds[i] ← none;
ENDLOOP;
FOR i IN [NumPageAndBlockBits..NumAddressBits) DO
p[VAdrsInOut].ds[i] ← none;
ENDLOOP;
};
IF p[PCtlDrABusVB].l = H
THEN FOR i IN [NumPageBits..NumPageAndBlockBits) DO
p[VAdrsInOut].ds[i] ← drive;
p[VAdrsInOut].ls[i] ← cs.vCamRdLatch[i] ;
ENDLOOP
ELSE FOR i IN [NumPageBits..NumPageAndBlockBits) DO
p[VAdrsInOut].ds[i] ← none;
ENDLOOP;
}
ELSE FOR i: NAT IN [0..NumAddressBits) DO
p[VAdrsInOut].ds[i] ← none;
ENDLOOP;
If either block or page RCamInterface part tristates are on then output the appropriate one(s)
IF CRdRCam[p, cs]
THEN {
IF p[PCtlDrABusRP].l = H
THEN {
FOR i: NAT IN [0..NumPageBits) DO
p[RAdrsOut].ds[i] ← drive;
p[RAdrsOut].ls[i] ← cs.rCamRdLatch[i];
ENDLOOP;
FOR i: NAT IN [0..NumFlagsBits) DO
p[FlagsOut].ds[i] ← drive;
p[FlagsOut].ls[i] ← cs.flagsRdLatch[i];
ENDLOOP;
}
ELSE {
FOR i: NAT IN [0..NumPageBits) DO p[RAdrsOut].ds[i] ← none; ENDLOOP;
FOR i: NAT IN [0..NumFlagsBits) DO p[FlagsOut].ds[i] ← none; ENDLOOP;
};
IF p[PCtlDrABusRB].l = H
THEN {
FOR i: NAT IN [NumPageBits..NumAddressBits) DO
p[RAdrsOut].ds[i] ← drive;
p[RAdrsOut].ls[i] ← cs.rCamRdLatch[i];
ENDLOOP;
FOR i: NAT IN [NumPageAndBlockBits..NumAddressBits-1) DO
p[RAdrsOut].ds[i] ← drive;
p[RAdrsOut].ls[i] ← L;
ENDLOOP;
}
ELSE {
FOR i: NAT IN [NumPageBits..NumAddressBits) DO
p[RAdrsOut].ds[i] ← none;
ENDLOOP;
};
}
ELSE FOR i: NAT IN [0..NumAddressBits) DO
p[RAdrsOut].ds[i] ← none;
ENDLOOP;
Handle ClrVPV
IF p[ClrVPV].l = H THEN {
FOR i IN [0..NumMemLines) DO
IF cs.match[LRM][i] = H THEN cs.vCam[i][NumAddressBits - 1] ← L;
ENDLOOP;
};
IF p[Reset].l = H THEN {
FOR i IN [0..NumMemLines) DO
cs.vCam[i][NumAddressBits-1] ← L;
cs.rCam[i][NumAddressBits-1] ← L;
cs.match[LVM][i] ← L;
cs.match[LRM][i] ← L;
ENDLOOP;
FOR i IN [0..NumIOLines) DO
cs.iomatch[LVM][i] ← L;
cs.iomatch[LRM][i] ← L;
ENDLOOP;
cs.avm ← L; cs.arm ← L;
};
END;

ComputeMatch: PROC[p: Ports.Port, cs: CacheState, matchType: KindOfMatch] = BEGIN
i, j,
XCount, -- number of bit positions in a line that compute X for their match contribution
finish: INT; -- gives index of bit position up to which a match is done (handles part match)
existsMatchL, existsMatchH, existsMatchX: BOOLEAN;
Equal: PROC[a, b: Level] RETURNS [c: BOOLEAN] = BEGIN
IF (a = H AND b = H) OR (a = L AND b = L) THEN c ← TRUE ELSE c ← FALSE;
END;
UnEqual: PROC[a, b: Level] RETURNS [c: BOOLEAN] = BEGIN
IF (a = H AND b = L) OR (a = L AND b = H) THEN c ← TRUE ELSE c ← FALSE;
END;
existsMatchX ← FALSE; existsMatchL ← FALSE; existsMatchH ← FALSE;
IF matchType = Virtual THEN {
cs.avm ← L;
IF cs.vCamPartMch = H
THEN finish ← NumPageBits-1
ELSE finish ← NumPageAndBlockBits-1;
{FOR i IN [0..NumMemLines) DO
cs.match[LVM][i] ← H;
XCount ← 0;
j ← 0;
WHILE j <= finish AND cs.match[LVM][i] = H DO
IF UnEqual[cs.vCamWtReg[j], cs.vCam[i][j]] THEN cs.match[LVM][i] ← L;
IF cs.vCamWtReg[j] = X OR cs.vCam[i][j] = X THEN XCount ← XCount + 1;
j ← j + 1;
ENDLOOP;
IF Equal[cs.vCamWtReg[NumAddressBits-1], cs.vCam[i][NumAddressBits-1]] THEN
cs.match[LVM][i] ← L;
IF cs.vCamWtReg[NumAddressBits-1] = X OR cs.vCam[i][NumAddressBits-1] = X THEN
XCount ← XCount + 1;
IF cs.vCamPartMch = L AND cs.match[LVM][i] = H THEN {
FOR j IN [0..NumFlagsBits) DO
IF p[nPMFlags].ls[j] = H AND UnEqual[cs.flagsWtReg[j], cs.flags[i][j]] THEN
cs.match[LVM][i] ← L;
IF cs.flags[i][j] = X OR cs.flagsWtReg[j] = X THEN
XCount ← XCount + 1;
ENDLOOP;
};
IF cs.match[LVM][i] = H AND XCount > 0 THEN cs.match[LVM][i] ← X;
IF cs.match[LVM][i] = H
THEN existsMatchH ← TRUE
ELSE IF cs.match[LVM][i] = L
THEN existsMatchL ← TRUE
ELSE existsMatchX ← TRUE;
ENDLOOP;
IF existsMatchH
THEN cs.avm ← H
ELSE IF existsMatchX THEN cs.avm ← X;
IF cs.avm = H
THEN FOR i IN [0..NumIOLines) DO
cs.iomatch[LVM][i] ← L;
ENDLOOP
ELSE {
FOR i IN [0..NumIOLines) DO
cs.iomatch[LVM][i] ← H;
XCount ← 0;
j ← 0;
WHILE j <= finish AND cs.iomatch[LVM][i] = H DO
IF UnEqual[cs.vCamWtReg[j], cs.ioVCam[i][j]] THEN cs.iomatch[LVM][i] ← L;
IF cs.vCamWtReg[j] = X OR cs.ioVCam[i][j] = X THEN XCount ← XCount + 1; j ← j + 1;
ENDLOOP;
IF Equal[cs.vCamWtReg[NumAddressBits-1], cs.ioVCam[i][NumAddressBits-1]] THEN
cs.iomatch[LVM][i] ← L;
IF cs.vCamWtReg[NumAddressBits-1] = X OR cs.ioVCam[i][NumAddressBits-1] = X THEN
XCount ← XCount + 1;
IF cs.vCamPartMch = L AND cs.iomatch[LVM][i] = H THEN {
FOR j IN [0..NumFlagsBits) DO
IF p[nPMFlags].ls[j] = H AND UnEqual[cs.flagsWtReg[j], cs.ioFlags[i][j]] THEN
cs.iomatch[LVM][i] ← L;
IF cs.ioFlags[i][j] = X OR cs.flagsWtReg[j] = X THEN XCount ← XCount + 1;
ENDLOOP;
};
IF cs.iomatch[LVM][i] = H AND XCount > 0 THEN cs.iomatch[LVM][i] ← X;
IF cs.iomatch[LVM][i] = H
THEN existsMatchH ← TRUE
ELSE IF cs.iomatch[LVM][i] = L
THEN existsMatchL ← TRUE
ELSE existsMatchX ← TRUE;
ENDLOOP;
IF existsMatchH
THEN cs.avm ← H
ELSE IF existsMatchX THEN cs.avm ← X;
};
};
};
IF matchType=Real AND cs.bCycle[3]=H THEN {
cs.arm ← L;
IF cs.rCamPartMch = H
THEN finish ← NumPageBits-1
ELSE finish ← NumPageAndBlockBits-1;
{FOR i IN [0..NumMemLines) DO
cs.match[LRM][i] ← H;
XCount ← 0;
j ← 0;
WHILE j <= finish AND cs.match[LRM][i] = H DO
IF UnEqual[cs.rCamWtReg[j], cs.rCam[i][j]] THEN cs.match[LRM][i] ← L;
IF cs.rCamWtReg[j] = X OR cs.rCam[i][j] = X THEN XCount ← XCount + 1; j ← j + 1;
ENDLOOP;
IF Equal[cs.rCamWtReg[NumAddressBits-1], cs.rCam[i][NumAddressBits-1]] THEN
cs.match[LRM][i] ← L;
IF cs.rCamWtReg[NumAddressBits-1] = X OR cs.rCam[i][NumAddressBits-1] = X THEN
XCount ← XCount + 1;
IF cs.match[LRM][i] = H AND XCount > 0 THEN cs.match[LRM][i] ← X;
IF cs.match[LRM][i] = H
THEN existsMatchH ← TRUE
ELSE IF cs.match[LRM][i] = L
THEN existsMatchL ← TRUE
ELSE existsMatchX ← TRUE;
ENDLOOP;
IF existsMatchH
THEN cs.arm ← H
ELSE IF existsMatchX THEN cs.arm ← X;
IF cs.arm = H
THEN FOR i IN [0..NumIOLines) DO
cs.iomatch[LRM][i] ← L;
ENDLOOP
ELSE {
FOR i IN [0..NumIOLines) DO
cs.iomatch[LRM][i] ← H;
XCount ← 0;
j ← 0;
WHILE j <= NumPageBits-NumDevIdBits-1 AND cs.iomatch[LRM][i] = H DO
IF UnEqual[cs.rCamWtReg[j], cs.ioRCam[i][j]] THEN cs.iomatch[LRM][i] ← L;
IF cs.rCamWtReg[j] = X OR cs.ioRCam[i][j] = X THEN
XCount ← XCount + 1;
j ← j + 1;
ENDLOOP;
IF cs.rCamPartMch = L THEN {
j ← NumPageBits;
WHILE j <= NumPageAndBlockBits-1 AND cs.iomatch[LRM][i] = H DO
IF UnEqual[cs.rCamWtReg[j], cs.ioRCam[i][j]] THEN cs.iomatch[LRM][i] ← L;
IF cs.rCamWtReg[j] = X OR cs.ioRCam[i][j] = X THEN
XCount ← XCount + 1;
j ← j + 1;
ENDLOOP;
};
IF Equal[cs.rCamWtReg[NumAddressBits-1], cs.ioRCam[i][NumAddressBits-1]] THEN
cs.iomatch[LRM][i] ← L;
IF cs.rCamWtReg[NumAddressBits-1] = X OR cs.ioRCam[i][NumAddressBits-1] = X THEN XCount ← XCount + 1;
IF cs.iomatch[LRM][i] = H AND XCount > 0 THEN cs.iomatch[LRM][i] ← X;
IF cs.iomatch[LRM][i] = H
THEN existsMatchH ← TRUE
ELSE IF cs.iomatch[LRM][i] = L
THEN existsMatchL ← TRUE
ELSE existsMatchX ← TRUE;
ENDLOOP;
IF existsMatchH
THEN cs.arm ← H
ELSE IF existsMatchX THEN cs.arm ← X;
};
};
};
END;
END.