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 October 23, 1987 7:19:42 pm PDT
DIRECTORY
Core, CoreClasses, CoreCreate, CoreFlat, CoreOps, Ports, Rosemary, RosemaryUser, Rope, SCLogic, SCParms;
SCArrayImpl: CEDAR PROGRAM
IMPORTS CoreClasses, CoreCreate, CoreFlat, CoreOps, Ports, Rosemary, Rope, SCParms
EXPORTS SCLogic
~ BEGIN OPEN SCLogic;
Constants and Type Defs
ClockEvalEnabled: BOOL = TRUE;
MySCName: ROPE = Rosemary.Register[roseClassName: "SCArray", init: Init, evalSimple: Simple, scheduleIfClockEval: ClockEvalEnabled];
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;
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 = ["111", "001", "001", "001", "001", "001"];
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
];
Flags: TYPE = REF FlagsRec;
FlagsRec: TYPE = RECORD [
SEQUENCE size: NAT OF ARRAY [0..2] OF Level
];
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: ARRAY [0..1] OF Level,  -- two flops 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
lduse: Level,   -- ldUse in VictimInterface
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
ramrd, ramwt: Level,   -- 2 flops to generate ramClock
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
pRamClock, ramClock: Level,  -- previous and current ramClocks
wdAdrs: LevelSequence ← NIL,  -- input to RamInterfaceCtl
byteSel: LevelSequence ← NIL,  -- input to RamInterfaceCtl
wdSel: Level,   -- input to RamInterfaceCtl
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: Flags ← NIL,   -- flags array
ioFlags: ARRAY [0..NumIOLines) OF ARRAY [0..2] OF Level, -- ioflags array
rCamRdLatch, rCamWtReg, vCamRdLatch, vCamWtReg: LevelSequence,
flagsRdLatch, flagsWtReg: ARRAY [0..2] OF Level,
vCamPartMch, rCamPartMch: Level,  -- flops to delay PartMch
vCamRdSR, vCamWtSR, rCamRdSR, rCamWtSR: ARRAY [0..2] OF Level, -- flops in CamInterfaceCtl; 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
deMapRply1: Level,   -- flop in VCamInterface
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..2] OF Level,
tmpxEnCamSel,
tmpBCycle2,
tmpxWtRam,
tmpxRdRam,
tmpxWtMchVCam,
tmpxRdVCam,
tmpxRdRCam,
tmpVPValidIn,
tmpRPValidIn,
tmpxPartRMch,
tmpPCtlPartVMch,
tmpPWtInProg,
tmpxDrRCamBL,
tmpDeMapRply1,
tmpxLdRCamWR: Level
];
Signal Defs
Reset, PCtlDrABusVB, PCtlDrABusVP, PCtlPartVMch, xRdVCam, xWtMchVCam, DeMapRply1, 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, xSelWdData, xByteSel, xWdAdrs,WdWtData, BlkWtData, 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", "PCtlDrABusVB", "PCtlDrABusVP", "PCtlPartVMch", "xRdVCam", "xWtMchVCam", "DeMapRply1", CoreCreate.Seq["VAdrsInOut", NumAddressBits], "VPValidIn", "PCtlDrABusRB", "PCtlDrABusRP", "xRdRCam", "xPartRMch", "xDrRCamBL", "xLdRCamWR", "xEnCamSelExt", "BCycle2", CoreCreate.Seq["RAdrsIn", NumAddressBits], "RPValidIn", CoreCreate.Seq["FlagsIn",3], CoreCreate.Seq["nPMFlags", 3], "xEnCamSel", "PCtlShftVictim4", "PCtlFrzVictim", CoreCreate.Seq["xCSCmd", 2], "nEnRS", CoreCreate.Seq["xRSCmd",2], "PWtInProg", "BCtlSetOw", "BCtlClrOw", "SetSh", "ClrSh", "xRdRam", "xWtRam", "xSelWdData", CoreCreate.Seq["xByteSel", NumBytesPerWord], CoreCreate.Seq["xWdAdrs", LogNumWordsPerLine], CoreCreate.Seq["WdWtData", NumBitsPerWord], CoreCreate.Seq["BlkWtData", NumBitsPerLine], CoreCreate.Seq["RAdrsOut", NumAddressBits], CoreCreate.Seq["FlagsOut", 3], 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, "FlagsIn"];
Ports.InitPorts[ct, ls, none, "nPMFlags"];
Ports.InitPorts[ct, ls, none, "xCSCmd"];
Ports.InitPorts[ct, ls, none, "xRSCmd"];
Ports.InitPorts[ct, ls, none, "xByteSel"];
Ports.InitPorts[ct, ls, none, "xWdAdrs"];
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[3]]];
Ports.InitPorts[ct, ls, drive, "BlkRdData"];
Ports.InitPorts[ct, ls, drive, "WdRdData"];
Ports.InitPorts[ct, l, none, "Reset", "PCtlDrABusVB", "PCtlDrABusVP", "PCtlPartVMch", "xRdVCam", "xWtMchVCam", "DeMapRply1"];
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", "xSelWdData", "RPValidIn"];
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.wdAdrs ← NEW [LevelSequenceRec[LogNumWordsPerLine]];
cs.byteSel ← NEW [LevelSequenceRec[NumBytesPerWord]];
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 [FlagsRec[NumMemLines]];
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.lduse ← X; cs.vCamCSCmd1 ← X; cs.rCamCSCmd1 ← X; cs.aVct ← X; cs.vCamPartMch ← X; cs.rCamPartMch ← X; cs.wdSel ← X; cs.pRamClock ← X; cs.ramClock ← X; cs.ramrd ← X; cs.ramwt ← X; cs.pWtInProgB ← X; cs.ldSORdLatch ← X; cs.deMapRply1 ← 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..2] 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..2] 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;
FOR i IN [0..1] DO
cs.csMuxSR[i] ← X;
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;
FOR i IN [0..NumBytesPerWord) DO
cs.byteSel[i] ← X;
ENDLOOP;
FOR i IN [0..LogNumWordsPerLine) DO
cs.wdAdrs[i] ← X;
ENDLOOP;
FOR i IN [0..2] DO
cs.vCamRdSR[i] ← X; cs.vCamWtSR[i] ← X; cs.rCamRdSR[i] ← X; cs.rCamWtSR[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..2] DO
cs.tmpFlagsIn[i] ← X;
ENDLOOP;
cs.tmpBCycle2 ← X; cs.tmpxWtRam ← X; cs.tmpxRdRam ← X; cs.tmpxWtMchVCam ← 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.tmpDeMapRply1 ← 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..2] 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, PCtlDrABusVB, PCtlDrABusVP, PCtlPartVMch, xRdVCam, xWtMchVCam, DeMapRply1, VAdrsInOut, VPValidIn] ← Ports.PortIndexes[cellType.public, "Reset", "PCtlDrABusVB", "PCtlDrABusVP", "PCtlPartVMch", "xRdVCam", "xWtMchVCam", "DeMapRply1", "VAdrsInOut", "VPValidIn"];
[PCtlDrABusRB, PCtlDrABusRP, xRdRCam, xPartRMch, xDrRCamBL, xLdRCamWR, xEnCamSelExt, BCycle2, RAdrsIn, FlagsIn] ← Ports.PortIndexes[cellType.public, "PCtlDrABusRB", "PCtlDrABusRP", "xRdRCam", "xPartRMch", "xDrRCamBL", "xLdRCamWR", "xEnCamSelExt", "BCycle2", "RAdrsIn", "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, xSelWdData, xByteSel, xWdAdrs,WdWtData, BlkWtData, RAdrsOut] ← Ports.PortIndexes[cellType.public, "SetSh", "ClrSh", "xRdRam", "xWtRam", "xSelWdData", "xByteSel", "xWdAdrs", "WdWtData", "BlkWtData", "RAdrsOut"];
[FlagsOut, BlkRdData, WdRdData, SetReschedule, ASh, AOw] ← Ports.PortIndexes[cellType.public, "FlagsOut", "BlkRdData", "WdRdData", "SetReschedule", "ASh", "AOw"];
[ARM, AVM, Clock, nClock, RPValidIn] ← Ports.PortIndexes[cellType.public, "ARM", "AVM", "Clock", "nClock", "RPValidIn"];
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 Capture[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 (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]
};
Capture: PROC[p: Ports.Port, cs: CacheState] = BEGIN
i: INT;
cs.tmpxEnCamSel ← p[xEnCamSel].l;
FOR i IN [0..NumAddressBits) DO
cs.tmpRAdrsIn[i] ← p[RAdrsIn].ls[i]; cs.tmpVAdrsInOut[i] ← p[VAdrsInOut].ls[i];
ENDLOOP;
FOR i IN [0..2] 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.tmpxWtMchVCam ← p[xWtMchVCam].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.tmpDeMapRply1 ← p[DeMapRply1].l;
END;
CSMux: PROC[p: Ports.Port, cs: CacheState, clockEval: BOOL] = BEGIN
i: INT;
First the state changes
IF ClockLToH[p, cs, clockEval] THEN cs.csMuxSR[0] ← cs.tmpxEnCamSel;
IF ClockHToL[p, cs, clockEval] THEN cs.csMuxSR[1] ← cs.csMuxSR[0];
Then the combinatorial part
IF cs.csMuxSR[1] = L THEN cs.csOut ← GND;
IF cs.csMuxSR[1] = 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 cs.lduse = H THEN {
FOR i IN [0..NumMemLines) DO
IF cs.match[LVM][i] = H THEN cs.use[i] ← H ;
ENDLOOP;
};
IF cs.tmpxEnCamSel = L AND cs.tmpxWtMchVCam = H AND cs.tmpPCtlPartVMch = L THEN
cs.lduse ← H
ELSE
cs.lduse ← L;
};
On Reset we set all the use bits to 0, and set victim to point to some location
IF p[Reset].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)
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 cs.wdSel = L
THEN FOR i IN [0..NumBitsPerLine) DO
cs.ram[RamIndex][i] ← p[BlkWtData].ls[i];
ENDLOOP
ELSE {
j ← DecodeAdrs[cs];
FOR i IN [0..NumBitsPerWord) DO
k ← i/NumBitsPerByte;
IF cs.byteSel[k] = H 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.ramrd ← cs.tmpxRdRam; cs.ramwt ← cs.tmpxWtRam;
};
Cycle ram clock
cs.pRamClock ← cs.ramClock;
Compute new value for ramClock
IF ((cs.ramrd=H AND cs.tmpxRdRam=H) OR (cs.ramwt=H AND cs.tmpxWtRam=H)) AND p[nEnRS].l=H
THEN cs.ramClock ← H
ELSE cs.ramClock ← L;
Change state as a result of ramClock positive edge
IF cs.pRamClock = L AND cs.ramClock = H THEN {
FOR i IN [0..NumBytesPerWord) DO
cs.byteSel[i] ← p[xByteSel].ls[i];
ENDLOOP;
FOR i IN [0..LogNumWordsPerLine) DO
cs.wdAdrs[i] ← p[xWdAdrs].ls[i];
ENDLOOP;
cs.wdSel ← p[xSelWdData].l
};
Assert the block and word values onto the ports from the RamRdLatch
Ports.CopyLS[cs.ramRdLatch, p[BlkRdData].ls];
IF cs.wdSel = H THEN {
adrs: NAT ← DecodeAdrs[cs];
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 shared and owner onto their ports
p[ASh].l ← cs.shBit; p[AOw].l ← cs.owBit;
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 ← DecodeAdrs[cs]; l ← j;
Handle Read
IF cs.ramRdSR[0] = H THEN {
FOR k IN [0..NumBitsPerLine) DO
cs.ramRdLatch[k] ← H;-- Precharge value
ENDLOOP;
IF cs.wdSel = H 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 cs.wdSel = H THEN {
IF ioRamIndex = 0 AND j = 1 THEN
FOR k IN [0..NumBitsPerWord) DO
l ← k/NumBitsPerByte;
IF cs.byteSel[l] = H 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 cs.byteSel[l] = H 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 cs.byteSel[l] = H 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 cs.byteSel[l] = H 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 cs.byteSel[l] = H 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 cs.byteSel[l] = H 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 cs.byteSel[l] = H 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;
DecodeAdrs: PROC[cs: CacheState] RETURNS[i: INT] = BEGIN
k: INT ← NumWordsPerLine;
i ← 0;
FOR j: INT IN [0..LogNumWordsPerLine) DO
k ← k/2;
IF cs.wdAdrs[j] = H THEN i ← i + k;
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;
cs.deMapRply1 ← cs.tmpDeMapRply1;
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..2] DO
cs.flagsRdLatch[j] ← IF rCamIndex >= 0 THEN cs.flags[rCamIndex][j] ELSE H;
ENDLOOP;
};
Change state of write flops in CamInterfaceCtl's
cs.vCamWtSR[2] ← cs.vCamWtSR[0];
cs.rCamWtSR[2] ← cs.rCamWtSR[0];
cs.vCamWtSR[0] ← cs.tmpxWtMchVCam;
cs.rCamWtSR[0] ← cs.tmpxDrRCamBL;
First load the write register
IF cs.tmpxWtMchVCam = H THEN {
FOR i IN [0..NumPageAndBlockBits) DO
cs.vCamWtReg[i] ← cs.tmpVAdrsInOut[i];
ENDLOOP;
cs.vCamWtReg[NumAddressBits-1] ← cs.tmpVPValidIn;
FOR i IN [0..2] DO
cs.flagsWtReg[i] ← cs.tmpFlagsIn[i];
ENDLOOP;
};
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.vCamWtSR[2] = 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.tmpVPValidIn;
};
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.tmpVPValidIn;
FOR j IN [0..2] DO
IF p[nPMFlags].ls[j] = H THEN
cs.flags[vCamIndex][j] ← cs.flagsWtReg[j]
ELSE
cs.flags[vCamIndex][j] ← L;
ENDLOOP;
};
};
IF cs.rCamWtSR[2] = 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.tmpRPValidIn;
};
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.tmpRPValidIn;
};
};
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;
}
ELSE {
FOR i IN [0..NumPageBits) DO
p[VAdrsInOut].ds[i] ← none;
ENDLOOP;
FOR i IN [NumPageAndBlockBits..NumAddressBits-1) 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..2] 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..2] 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 DeMapRply
IF cs.deMapRply1 = H OR p[DeMapRply1].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..2] 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..2] 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.