Constants and Type Defs
ClockEvalEnabled: BOOL = TRUE;
MySmallCacheName: ROPE = Rosemary.Register[roseClassName: "SmallCacheArray", init: Init, evalSimple: Simple, scheduleIfClockEval: ClockEvalEnabled];
NumFlagsBits: NAT = 4;
NumIOLines: NAT = 2*3;
numMemLines: NAT ← 2*SCParms.numMemLines;
numAddressBits: NAT ← SCParms.numBitsPerWord+1; --Includes IO/Mem Bit--
numPageBits: NAT ← SCParms.numPageBits+1; --Includes IO/Mem Bit--
numPageAndBlockBits: NAT ← numPageBits+SCParms.numBlockBits;
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, RML1, 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[RML1..GND] OF LevelSequence
];
TwoDArray: TYPE = REF TwoDArrayRec;
TwoDArrayRec:
TYPE =
RECORD [
SEQUENCE size: NAT OF LevelSequence
];
KindOfMatch: TYPE = {Virtual, Real};
Index: TYPE = {Victim, RamSel, RML1, 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[RML1..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
rBCycle: ARRAY [3..5] OF Level, -- delay stages in RML234
enCamSelExtFF: Level, -- delay stage for EnCamSelExt
victimIndex: INT, -- line pointed to by victim
tmpVictimIndex: INT, -- to implement victim Flops
use: LevelSequence ← NIL, -- use bits in array
tmpUse: LevelSequence ← NIL, -- to implement use Flops
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
ramWtSR, ramRdSR: ARRAY [0..1] OF Level, -- 2 flops each in RamInterfaceCtl
ramRdorWt: Level, -- flop to generate Prech
ramRdLatch: LevelSequence ← NIL, -- ramRdLatch in RamInterface
bar: LevelSequence ← NIL, -- block assembly register
ram: TwoDArray ← 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: TwoDArray ← 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: TwoDArray ← 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,
vCamDrBLFF, rCamDrBLFF: Level, -- flops for CamDrBL
vCamLdFF, rCamLdFF: Level, -- flop for LdCamRL; note there is no flop for CCamPr because precharge is not modeled explicitly
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,
tmpCycleIn: LevelSequence ← NIL,
tmpBAREn: LevelSequence ← NIL,
tmpFlagsIn: ARRAY [0..NumFlagsBits) OF Level,
tmpxEnCamSel,
tmpxEnCamSelExt,
tmpRBCycle2,
tmpxWtRam,
tmpxRdRam,
tmpramRdorWt,
tmpxLdVCamWR,
tmpxDrVCamBL,
tmpxLdVCamRL,
tmpxLdRCamRL,
tmpVPValidIn,
tmpRPValidIn,
tmpPWtInProg,
tmpxDrRCamBL,
tmpxLdRCamWR,
tmpReset: Level,
numCyclesAfterReset: NAT
];
Signal Defs
enableDumpState: BOOL ← FALSE;
cacheStateRef: CacheState ← NIL;
cacheStateValueIn, cacheStateValueOut: ROPE ← NIL;
Vdd, Gnd, Reset, xCVCamPr, xCRCamPr, LdVML, ClrVPV, PCtlClrAllVPV, PCtlResetVictim, Spare, RamClock, xLdUse, PCtlDrABusVB, PCtlDrABusVP, nPartVMch, xLdVCamRL, xLdVCamWR, xDrVCamBL, VAdrsInOut, VPValidIn, PCtlDrABusRB, PCtlDrABusRP, xLdRCamRL, nxPartRMch, xDrRCamBL, xLdRCamWR, xEnCamSelExt, RBCycle2, RAdrsIn, RPValidIn, FlagsIn, nPMFlags, xEnCamSel, PCtlShftVictim4, PCtlFrzVictim, xCSCmd, nEnRS, xRSCmd, PWtInProg, BCtlSetOw, BCtlClrOw, SetSh, ClrSh, xRdRam, xWtRam, nxSelWdData, nxByteSel, nxWdSel, WdWtData, CycleIn, BAREn, Modes, RAdrsOut, FlagsOut, BlkRdData, WdRdData, SetReschedule, ASh, AOw, ARM3, AVM, Clock: NAT;
Internal Procs
Copies cache state from cacheStateValueIn to simulation
LoadState:
PROC [] =
BEGIN
cs: CacheState ← cacheStateRef;
fieldStart: NAT ← 0;
fieldStop: NAT ← 0;
RopeToL:
PROC[value:
ROPE]
RETURNS[l: Level] =
BEGIN
IF Rope.Length[value] # 1 THEN ERROR;
SELECT Rope.Fetch[value, 0]
FROM
'1 => RETURN[H];
'0 => RETURN[L];
'X => RETURN[X];
ENDCASE => ERROR;
END;
LoadLS:
PROC[ls: LevelSequence, value:
ROPE] =
BEGIN
ropeIx: NAT ← 0;
FOR i:
NAT
IN [0..ls.size)
DO
ropeIx ← Rope.SkipTo[s: value, pos: ropeIx, skip: "01X"];
SELECT Rope.Fetch[value, ropeIx]
FROM
'1 => ls[i] ← H;
'0 => ls[i] ← L;
'X => ls[i] ← X;
ENDCASE;
ropeIx ← ropeIx+1
ENDLOOP;
END;
LoadBlock:
PROC[block: LevelSequence, value:
ROPE] =
BEGIN
ropeIx: NAT ← 0;
FOR wdIx:
NAT
IN [0..SCParms.numWordsPerLine)
DO
FOR bitIx:
NAT
IN [0..SCParms.numBitsPerWord)
DO
ropeIx ← Rope.SkipTo[s: value, pos: ropeIx, skip: "01X"];
SELECT Rope.Fetch[value, ropeIx]
FROM
'1 => block[bitIx*SCParms.numWordsPerLine+wdIx] ← H;
'0 => block[bitIx*SCParms.numWordsPerLine+wdIx] ← L;
'X => block[bitIx*SCParms.numWordsPerLine+wdIx] ← X;
ENDCASE;
ropeIx ← ropeIx+1;
ENDLOOP;
ENDLOOP;
END;
GetInt:
PROC[]
RETURNS[i:
INT] =
BEGIN
fieldStart ← Rope.SkipTo[s: cacheStateValueIn, pos: fieldStart, skip: "0123456789"];
fieldStop ← Rope.SkipTo[s: cacheStateValueIn, pos: fieldStart, skip: ","];
i ← Convert.IntFromRope[Rope.Substr[cacheStateValueIn, fieldStart, fieldStop-fieldStart]];
fieldStart ← fieldStop+1;
END;
GetRope:
PROC[]
RETURNS[r:
ROPE] =
BEGIN
fieldStart ← Rope.SkipTo[s: cacheStateValueIn, pos: fieldStart, skip: "01X"];
fieldStop ← Rope.SkipTo[s: cacheStateValueIn, pos: fieldStart, skip: ","];
r ← Rope.Substr[cacheStateValueIn, fieldStart, fieldStop-fieldStart];
fieldStart ← fieldStop+1;
END;
IF cacheStateValueIn=NIL THEN RETURN;
cs.victimIndex ← cs.tmpVictimIndex ← GetInt[];
FOR i:
NAT
IN [0..numMemLines)
DO
cs.match[Victim][i] ← L
ENDLOOP;
cs.match[Victim][cs.victimIndex] ← H;
THROUGH [0..numMemLines)
DO
lineNum: NAT ← GetInt[];
LoadLS[cs.vCam[lineNum], GetRope[]];
LoadLS[cs.rCam[lineNum], GetRope[]];
LoadLS[cs.flags[lineNum], GetRope[]];
cs.sh[lineNum] ← RopeToL[GetRope[]];
cs.ow[lineNum] ← RopeToL[GetRope[]];
cs.use[lineNum] ← RopeToL[GetRope[]];
LoadBlock[cs.ram[lineNum], GetRope[]];
ENDLOOP;
END;
Copies cache state from simulation to cacheStateValueOut
DumpState:
PROC[] =
BEGIN
cs: CacheState ← cacheStateRef;
LToRope:
PROC[l: Level]
RETURNS [
ROPE] =
BEGIN
SELECT l
FROM
L => RETURN["0"];
H => RETURN["1"];
X => RETURN["x"];
ENDCASE => ERROR;
END;
LSToRope:
PROC[ls: LevelSequence]
RETURNS [lsr:
ROPE ←
NIL] =
BEGIN
FOR i: NAT IN [0..ls.size) DO lsr ← Rope.Cat[lsr, LToRope[ls[i]]] ENDLOOP;
END;
AdrsToRope:
PROC[adrs: LevelSequence]
RETURNS [ar:
ROPE] =
BEGIN
ar ← Rope.Cat[LToRope[adrs[0]], " "];
FOR i: NAT IN [1..numPageBits) DO ar ← Rope.Cat[ar, LToRope[adrs[i]]] ENDLOOP;
ar ← Rope.Cat[ar, " "];
FOR i: NAT IN [numPageBits..numPageAndBlockBits) DO ar ← Rope.Cat[ar, LToRope[adrs[i]]] ENDLOOP;
ar ← Rope.Cat[ar, " "];
FOR i: NAT IN [numPageAndBlockBits..numAddressBits) DO ar ← Rope.Cat[ar, LToRope[adrs[i]]] ENDLOOP;
END;
BlockToRope:
PROC[block: LevelSequence]
RETURNS[br:
ROPE ←
NIL] =
BEGIN
FOR wdIx:
NAT
IN [0..SCParms.numWordsPerLine)
DO
FOR bitIx:
NAT
IN [0..SCParms.numBitsPerWord)
DO
br ← Rope.Cat[br, LToRope[block[bitIx*SCParms.numWordsPerLine+wdIx]]];
ENDLOOP;
IF wdIx<SCParms.numWordsPerLine-1 THEN br ← Rope.Cat[br, " "];
ENDLOOP;
END;
IF cs=NIL THEN RETURN;
cacheStateValueOut ← Rope.Cat["\n Victim: ", Convert.RopeFromInt[cs.victimIndex], ","];
FOR i:
NAT
IN [0..numMemLines)
DO
cacheStateValueOut ← Rope.Cat[cacheStateValueOut, "\nLine: ", Convert.RopeFromInt[i]];
cacheStateValueOut ← Rope.Cat[cacheStateValueOut, ", VCam: ", AdrsToRope[cs.vCam[i]]];
cacheStateValueOut ← Rope.Cat[cacheStateValueOut, ", RCam: ", AdrsToRope[cs.rCam[i]]];
cacheStateValueOut ← Rope.Cat[cacheStateValueOut, ", Flags: ", LSToRope[cs.flags[i]]];
cacheStateValueOut ← Rope.Cat[cacheStateValueOut, ", Sh: ", LToRope[cs.sh[i]]];
cacheStateValueOut ← Rope.Cat[cacheStateValueOut, ", Ow: ", LToRope[cs.ow[i]]];
cacheStateValueOut ← Rope.Cat[cacheStateValueOut, ", Use: ", LToRope[cs.use[i]]];
cacheStateValueOut ← Rope.Cat[cacheStateValueOut, ", Ram: ", BlockToRope[cs.ram[i]]];
cacheStateValueOut ← Rope.Cat[cacheStateValueOut, ", "];
ENDLOOP;
cacheStateValueOut ← Rope.Cat[cacheStateValueOut, "\n"];
END;
Init: Rosemary.InitProc =
BEGIN
i, j: INT;
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.tmpUse ← NEW [LevelSequenceRec[numMemLines]];
cs.sh ← NEW [LevelSequenceRec[numMemLines]];
cs.ow ← NEW [LevelSequenceRec[numMemLines]];
cs.ramRdLatch ← NEW [LevelSequenceRec[SCParms.numBitsPerLine]];
cs.bar ← NEW [LevelSequenceRec[SCParms.numBitsPerLine]];
cs.ram ← NEW [TwoDArrayRec[numMemLines]];
FOR i:
NAT
IN [0..numMemLines)
DO
cs.ram[i] ← NEW [LevelSequenceRec[SCParms.numBitsPerLine]];
ENDLOOP;
cs.ioRam.cWSOld ← NEW [LevelSequenceRec[SCParms.numBitsPerWord]];
cs.ioRam.cWSNew ← NEW [LevelSequenceRec[SCParms.numBitsPerWord]];
cs.ioRam.aID ← NEW [LevelSequenceRec[SCParms.numBitsPerWord]];
cs.ioRam.faultCode ← NEW [LevelSequenceRec[SCParms.numBitsPerWord]];
cs.ioRam.intStatus ← NEW [LevelSequenceRec[SCParms.numBitsPerWord]];
cs.ioRam.intMask ← NEW [LevelSequenceRec[SCParms.numBitsPerWord]];
cs.ioRam.modes ← NEW [LevelSequenceRec[SCParms.numBitsPerWord]];
cs.ioRam.lFCode1 ← NEW [LevelSequenceRec[SCParms.numBitsPerWord]];
cs.ioRam.lFCode3 ← NEW [LevelSequenceRec[SCParms.numBitsPerWord]];
cs.ioRam.lFCode5 ← NEW [LevelSequenceRec[SCParms.numBitsPerWord]];
cs.ioRam.lFCode7 ← NEW [LevelSequenceRec[SCParms.numBitsPerWord]];
cs.rCam ← NEW [TwoDArrayRec[numMemLines]];
FOR i:
NAT
IN [0..numMemLines)
DO
cs.rCam[i] ← NEW [LevelSequenceRec[numAddressBits]];
ENDLOOP;
cs.vCam ← NEW [TwoDArrayRec[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 [TwoDArrayRec[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.tmpCycleIn ← NEW [LevelSequenceRec[SCParms.numBitsPerCycle]];
cs.tmpBAREn ← NEW [LevelSequenceRec[SCParms.numCyclesPerLine]];
cs.tmpVAdrsInOut ← NEW [LevelSequenceRec[numAddressBits]];
}
ELSE cs ← NARROW[oldStateAny, CacheState];
cs.prevClk ← X; cs.vCamCSCmd1 ← X; cs.rCamCSCmd1 ← X; cs.aVct ← X; cs.ramRdorWt ← X; cs.pWtInProgB ← 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..SCParms.numBitsPerLine)
DO
cs.ramRdLatch[i] ← X;
cs.bar[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+SCParms.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..SCParms.numBitsPerLine)
DO
cs.ram[i][j] ← X;
ENDLOOP;
cs.use[i] ← X; cs.tmpUse[i] ← X; cs.sh[i] ← X; cs.ow[i] ← X;
FOR k: Index
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.rBCycle[i] ← X;
ENDLOOP;
cs.vCamDrBLFF ← X; cs.rCamDrBLFF ← X;
cs.vCamLdFF ← X; cs.rCamLdFF ← X;
cs.tmpxEnCamSel ← X; cs.tmpxEnCamSelExt ← X;
FOR i
IN [0..numAddressBits)
DO
cs.tmpRAdrsIn[i] ← X; cs.tmpVAdrsInOut[i] ← X;
ENDLOOP;
FOR i
IN [0..SCParms.numBitsPerCycle)
DO
cs.tmpCycleIn[i] ← X;
ENDLOOP;
FOR i
IN [0..SCParms.numCyclesPerLine)
DO
cs.tmpBAREn[i] ← X;
ENDLOOP;
FOR i
IN [0..NumFlagsBits)
DO
cs.tmpFlagsIn[i] ← X;
ENDLOOP;
cs.tmpRBCycle2 ← X; cs.tmpxWtRam ← X; cs.tmpxRdRam ← X; cs.tmpramRdorWt ← X; cs.tmpxLdVCamWR ← X; cs.tmpxLdVCamRL ← p[xLdVCamRL].l; cs.tmpxLdRCamRL ← X; cs.tmpVPValidIn ← X; cs.tmpRPValidIn ← X; cs.tmpPWtInProg ← X; cs.tmpxDrRCamBL ← X; cs.tmpxLdRCamWR ← X; cs.tmpxDrVCamBL ← X; cs.tmpReset ← X; cs.numCyclesAfterReset ← LAST[NAT];
FOR i
IN [0..NumIOLines)
DO
FOR j
IN [numPageAndBlockBits..numPageAndBlockBits+SCParms.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..SCParms.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: Index
IN [
RML1..
RML4]
DO
cs.iomatch[k][i] ← X;
ENDLOOP;
cs.iomatch[GND][i] ← L;
ENDLOOP;
cs.resetDone ← FALSE;
[Vdd, Gnd, Reset, xCVCamPr, xCRCamPr, LdVML, ClrVPV, PCtlClrAllVPV] ← Ports.PortIndexes[cellType.public, "Vdd", "Gnd", "Reset", "xCVCamPr", "xCRCamPr", "LdVML", "ClrVPV", "PCtlClrAllVPV"];
[PCtlResetVictim, Spare, RamClock, xLdUse, PCtlDrABusVB, PCtlDrABusVP, nPartVMch, xLdVCamRL, xLdVCamWR, xDrVCamBL, VAdrsInOut, VPValidIn] ← Ports.PortIndexes[cellType.public, "PCtlResetVictim", "Spare", "RamClock", "xLdUse", "PCtlDrABusVB", "PCtlDrABusVP", "nPartVMch", "xLdVCamRL", "xLdVCamWR", "xDrVCamBL", "VAdrsInOut", "VPValidIn"];
[PCtlDrABusRB, PCtlDrABusRP, xLdRCamRL, nxPartRMch, xDrRCamBL, xLdRCamWR, xEnCamSelExt, RBCycle2, RAdrsIn, RPValidIn, FlagsIn] ← Ports.PortIndexes[cellType.public, "PCtlDrABusRB", "PCtlDrABusRP", "xLdRCamRL", "nxPartRMch", "xDrRCamBL", "xLdRCamWR", "xEnCamSelExt", "RBCycle2", "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, CycleIn, BAREn, Modes, RAdrsOut] ← Ports.PortIndexes[cellType.public, "SetSh", "ClrSh", "xRdRam", "xWtRam", "nxSelWdData", "nxByteSel", "nxWdSel", "WdWtData", "CycleIn", "BAREn", "Modes", "RAdrsOut"];
[FlagsOut, BlkRdData, WdRdData, SetReschedule, ASh, AOw] ← Ports.PortIndexes[cellType.public, "FlagsOut", "BlkRdData", "WdRdData", "SetReschedule", "ASh", "AOw"];
[ARM3, AVM, Clock] ← Ports.PortIndexes[cellType.public, "ARM3", "AVM", "Clock"];
stateAny ← cs;
END;
Simple: Rosemary.EvalProc =
BEGIN
cs: CacheState ← NARROW[stateAny];
cacheStateRef ← cs;
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];
HandleState[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]
};
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..SCParms.numBitsPerCycle)
DO
cs.tmpCycleIn[i] ← p[CycleIn].ls[i];
ENDLOOP;
FOR i:
INT
IN [0..SCParms.numCyclesPerLine)
DO
cs.tmpBAREn[i] ← p[BAREn].ls[i];
ENDLOOP;
FOR i:
INT
IN [0..NumFlagsBits)
DO
cs.tmpFlagsIn[i] ← p[FlagsIn].ls[i];
ENDLOOP;
cs.tmpRBCycle2 ← p[RBCycle2].l;
cs.tmpxWtRam ← p[xWtRam].l;
cs.tmpxRdRam ← p[xRdRam].l;
cs.tmpxLdVCamWR ← p[xLdVCamWR].l;
cs.tmpVPValidIn ← p[VPValidIn].l;
cs.tmpRPValidIn ← p[RPValidIn].l;
cs.tmpPWtInProg ← p[PWtInProg].l;
cs.tmpxDrRCamBL ← p[xDrRCamBL].l;
cs.tmpxLdRCamWR ← p[xLdRCamWR].l;
cs.tmpxDrVCamBL ← p[xDrVCamBL].l;
cs.tmpReset ← p[Reset].l
END;
For signals going to flops triggered by nClock
CaptureH:
PROC[p: Ports.Port, cs: CacheState] =
BEGIN
cs.tmpxEnCamSel ← p[xEnCamSel].l;
cs.tmpxEnCamSelExt ← p[xEnCamSelExt].l;
cs.tmpxLdVCamRL ← p[xLdVCamRL].l;
cs.tmpxLdRCamRL ← p[xLdRCamRL].l;
cs.tmpramRdorWt ← Ports.OrL[p[xRdRam].l, p[xWtRam].l];
END;
HandleState:
PROC[p: Ports.Port, cs: CacheState, clockEval:
BOOL] =
BEGIN
IF NOT ClockLToH[p, cs, clockEval] THEN RETURN;
SELECT cs.tmpReset
FROM
H => cs.numCyclesAfterReset ← 0;
L => cs.numCyclesAfterReset ← cs.numCyclesAfterReset+1
ENDCASE;
Keep loading state 3 cycles after Reset L to prevent PCtlClrAllVPV from screwing us
IF cs.tmpReset=H
OR (cs.tmpReset=L
AND cs.numCyclesAfterReset <=3)
THEN LoadState[]
ELSE IF enableDumpState THEN {DumpState[]; TerminalIO.PutRope[cacheStateValueOut]}
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.rBCycle[5] ← cs.rBCycle[4];
cs.rBCycle[4] ← cs.rBCycle[3];
cs.rBCycle[3] ← cs.tmpRBCycle2;
};
Note that the array latches are enabled only during half cycles where Clock is low
IF ClockL[p, cs, clockEval]
THEN {
FOR i:
NAT
IN [0..numMemLines)
DO
IF cs.rBCycle[5] = H
THEN {
cs.match[RML4][i] ← cs.match[RML3][i];
};
IF cs.rBCycle[4] = H
THEN {
cs.match[RML3][i] ← cs.match[RML2][i];
};
IF cs.rBCycle[3] = H
THEN {
cs.match[RML2][i] ← cs.match[RML1][i];
};
ENDLOOP;
FOR i:
NAT
IN [0..NumIOLines)
DO
IF cs.rBCycle[5] = H
THEN {
cs.iomatch[RML4][i] ← cs.iomatch[RML3][i];
};
IF cs.rBCycle[4] = H
THEN {
cs.iomatch[RML3][i] ← cs.iomatch[RML2][i];
};
IF cs.rBCycle[3] = H
THEN {
cs.iomatch[RML2][i] ← cs.iomatch[RML1][i];
};
ENDLOOP;
};
END;
Victim:
PROC[p: Ports.Port, cs: CacheState, clockEval:
BOOL] =
BEGIN
DecMod:
PROC[n:
INT]
RETURNS [
INT] =
BEGIN
RETURN[IF n=0 THEN numMemLines-1 ELSE n-1]
END;
On ClockLow, capture use and victim in tmp variables
IF ClockL[p, cs, clockEval]
THEN {
FOR i:
NAT
IN [0..numMemLines)
DO
cs.tmpUse[i] ← Ports.OrL[
Ports.AndL[Ports.AndL[Ports.NotL[cs.match[Victim][i]], cs.use[i]], Ports.NotL[p[Reset].l]],
Ports.OrL[
Ports.AndL[cs.match[LVM][i], p[xLdUse].l],
Ports.AndL[cs.match[Victim][i], p[PCtlShftVictim4].l]]
]
ENDLOOP;
IF p[PCtlFrzVictim].l = L
THEN {
IF cs.use[cs.victimIndex] = H THEN cs.tmpVictimIndex ← DecMod[cs.victimIndex]
}
};
On Rising edge of clock change the state of the flops
IF ClockLToH[p, cs, clockEval]
THEN {
cs.victimIndex ← cs.tmpVictimIndex;
FOR i:
NAT
IN [0..numMemLines)
DO
cs.use[i] ← cs.tmpUse[i];
IF cs.tmpVictimIndex=i THEN cs.match[Victim][i] ← H ELSE cs.match[Victim][i] ← L
ENDLOOP;
};
On Reset we set victim to point to some location
IF p[Reset].l = H
OR p[PCtlResetVictim].l = H
THEN {
FOR i:
NAT
IN [0..numMemLines)
DO
cs.match[Victim][i] ← L;
ENDLOOP;
cs.match[Victim][numMemLines-1] ← H;
cs.victimIndex ← cs.tmpVictimIndex ← 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;
Load BAR if necessary
IF ClockLToH[p, cs, clockEval]
THEN {
numEnablesHigh: NAT ← 0;
FOR c:
NAT
IN [0..SCParms.numCyclesPerLine)
DO
IF cs.tmpBAREn[c] = H
THEN {
IF (numEnablesHigh ← numEnablesHigh+1) > 1 THEN ERROR;
FOR i:
NAT
IN [0..SCParms.numBitsPerWord)
DO
cs.bar[i*SCParms.numWordsPerLine+SCParms.numWordsPerCycle*c] ← cs.tmpCycleIn[i];
cs.bar[i*SCParms.numWordsPerLine+SCParms.numWordsPerCycle*c+1] ← cs.tmpCycleIn[SCParms.numBitsPerWord+i];
ENDLOOP;
}
ENDLOOP;
};
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..SCParms.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..SCParms.numBitsPerLine)
DO
cs.ram[RamIndex][i] ← cs.bar[i];
ENDLOOP
ELSE {
j ← IndexOfSelectedWord[p];
FOR i
IN [0..SCParms.numBitsPerWord)
DO
k ← i/SCParms.numBitsPerByte;
IF p[nxByteSel].ls[k] = L THEN cs.ram[RamIndex][j] ← p[WdWtData].ls[i];
j← j+SCParms.numWordsPerLine;
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..SCParms.numBitsPerWord)
DO
p[WdRdData].ls[i] ← cs.ramRdLatch[adrs];
adrs ← adrs+SCParms.numWordsPerLine;
ENDLOOP
};
Compute SetReschedule
p[SetReschedule].l ← L;
numX ← 0;
FOR i
IN [0..SCParms.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 composite values on lines going in to SOInterface from array and load SORdlatch
IF p[nEnRS].l = L
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..SCParms.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..SCParms.numBitsPerLine)
DO
cs.ramRdLatch[k] ← L; -- precharge value
ENDLOOP;
IF p[nxSelWdData].l = L
THEN {
IF ioRamIndex = 0
AND j = 1
THEN
FOR k
IN [0..SCParms.numBitsPerWord)
DO
cs.ramRdLatch[j] ← cs.ioRam.cWSOld[k]; j ← j+SCParms.numWordsPerLine;
ENDLOOP
ELSE
IF ioRamIndex = 0
AND j = 3
THEN
FOR k
IN [0..SCParms.numBitsPerWord)
DO
cs.ramRdLatch[j] ← cs.ioRam.cWSNew[k]; j ← j+SCParms.numWordsPerLine;
ENDLOOP
ELSE
IF ioRamIndex = 1
AND j = 1
THEN
FOR k
IN [0..SCParms.numBitsPerWord)
DO
cs.ramRdLatch[j] ← cs.ioRam.aID[k]; j ← j+SCParms.numWordsPerLine;
ENDLOOP
ELSE
IF ioRamIndex = 1
AND j = 3
THEN
FOR k
IN [0..SCParms.numBitsPerWord)
DO
cs.ramRdLatch[j] ← cs.ioRam.faultCode[k]; j ← j+SCParms.numWordsPerLine;
ENDLOOP
ELSE
IF ioRamIndex = 1
AND j = 5
THEN
FOR k
IN [0..SCParms.numBitsPerWord)
DO
cs.ramRdLatch[j] ← cs.ioRam.intStatus[k]; j ← j+SCParms.numWordsPerLine;
ENDLOOP
ELSE
IF ioRamIndex = 1
AND j = 7
THEN
FOR k
IN [0..SCParms.numBitsPerWord)
DO
cs.ramRdLatch[j] ← cs.ioRam.intMask[k]; j ← j+SCParms.numWordsPerLine;
ENDLOOP
ELSE
IF ioRamIndex = 4
AND j = 5
THEN
FOR k
IN [0..SCParms.numBitsPerWord)
DO
cs.ramRdLatch[j] ← cs.ioRam.modes[k]; j ← j+SCParms.numWordsPerLine;
ENDLOOP
ELSE
IF ioRamIndex = 5
AND j = 1
THEN
FOR k
IN [0..SCParms.numBitsPerWord)
DO
cs.ramRdLatch[j] ← cs.ioRam.lFCode1[k]; j ← j+SCParms.numWordsPerLine;
ENDLOOP
ELSE
IF ioRamIndex = 5
AND j = 3
THEN
FOR k
IN [0..SCParms.numBitsPerWord)
DO
cs.ramRdLatch[j] ← cs.ioRam.lFCode3[k]; j ← j+SCParms.numWordsPerLine;
ENDLOOP
ELSE
IF ioRamIndex = 5
AND j = 5
THEN
FOR k
IN [0..SCParms.numBitsPerWord)
DO
cs.ramRdLatch[j] ← cs.ioRam.lFCode5[k]; j ← j+SCParms.numWordsPerLine;
ENDLOOP
ELSE
IF ioRamIndex = 5
AND j = 7
THEN
FOR k
IN [0..SCParms.numBitsPerWord)
DO
cs.ramRdLatch[j] ← cs.ioRam.lFCode7[k]; j ← j+SCParms.numWordsPerLine;
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..SCParms.numBitsPerWord)
DO
l ← k/SCParms.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..SCParms.numBitsPerWord)
DO
l ← k/SCParms.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..SCParms.numBitsPerWord)
DO
l ← k/SCParms.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..SCParms.numBitsPerWord)
DO
l ← k/SCParms.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..SCParms.numBitsPerWord)
DO
l ← k/SCParms.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..SCParms.numBitsPerWord)
DO
l ← k/SCParms.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..SCParms.numBitsPerWord)
DO
l ← k/SCParms.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..SCParms.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..SCParms.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] =
BEGIN
FOR i:
INT
IN [0..SCParms.numWordsPerLine)
DO
IF p[nxWdSel].ls[i] = L THEN RETURN [i]
ENDLOOP;
RETURN [0]
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;
Change the state of flops clocked by nClock in CamInterfaceCtl's
IF ClockHToL[p, cs, clockEval]
THEN {
cs.enCamSelExtFF ← cs.tmpxEnCamSelExt;
cs.vCamLdFF ← cs.tmpxLdVCamRL;
cs.rCamLdFF ← cs.tmpxLdRCamRL;
};
Handle the effect of xEnCamSelExt
cs.vCamSel ← IF cs.enCamSelExtFF = 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 cs.enCamSelExtFF = H
AND cs.resetDone
THEN
ERROR;
Handle latch that holds CSCmd1
IF cs.vCamLdFF = H THEN cs.vCamCSCmd1 ← p[xCSCmd].ls[1];
IF cs.rCamLdFF = H THEN cs.rCamCSCmd1 ← p[xCSCmd].ls[1];
If vcam load latch signal is high and exactly one select line is high then read else precharge
IF cs.vCamLdFF = H
THEN
FOR j
IN [0..numAddressBits)
DO
cs.vCamRdLatch[j] ← IF vCamIndex >= 0 THEN cs.vCam[vCamIndex][j] ELSE H;
ENDLOOP;
If rcam load latch signal is high and exactly one select line is high then read else precharge
IF cs.rCamLdFF = 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;
};
On rising edge of clock:
IF ClockLToH[p, cs, clockEval]
THEN {
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;
};
Drive the bit lines and do a write or match, as appropriate
IF cs.vCamDrBLFF = H
THEN {
IF cs.vCamLdFF = 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, clockEval]
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] ← X; -- both lines are driven low so result is X
ENDLOOP;
};
};
IF cs.rCamDrBLFF = H
THEN {
IF cs.rCamLdFF = 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, clockEval]
ELSE {
FOR j
IN [1..numPageAndBlockBits)
DO
cs.rCam[rCamIndex][j] ← cs.rCamWtReg[j];
ENDLOOP;
cs.rCam[rCamIndex][numAddressBits-1] ← cs.rCamWtReg[numAddressBits-1];
};
};
Assert avm and arm values onto port
p[AVM].l ← cs.avm; p[ARM3].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[RML1][i] = H THEN cs.vCam[i][numAddressBits - 1] ← L;
ENDLOOP;
};
Handle PCtlClrAllVPV
IF p[PCtlClrAllVPV].l = H
THEN {
FOR i
IN [0..numMemLines)
DO
cs.vCam[i][numAddressBits-1] ← L;
ENDLOOP;
};
Handle Reset
IF p[Reset].l = H
THEN {
FOR i
IN [0..numMemLines)
DO
cs.rCam[i][numAddressBits-1] ← L;
cs.match[LVM][i] ← L;
cs.match[RML1][i] ← L;
ENDLOOP;
FOR i
IN [0..NumIOLines)
DO
cs.iomatch[LVM][i] ← L;
cs.iomatch[RML1][i] ← L;
ENDLOOP;
cs.avm ← L; cs.arm ← L;
};
END;
ComputeMatch:
PROC[p: Ports.Port, cs: CacheState, matchType: KindOfMatch, clockEval:
BOOL] =
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
AND p[LdVML].l=H
THEN {
cs.avm ← L;
IF p[nPartVMch].l = L
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.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.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 p[RBCycle2].l=H
AND ClockL[p, cs, clockEval]
THEN {
cs.arm ← L;
IF p[nxPartRMch].l = L
THEN finish ← numPageBits-1
ELSE finish ← numPageAndBlockBits-1;
{
FOR i
IN [0..numMemLines)
DO
cs.match[RML1][i] ← H;
XCount ← 0;
j ← 0;
WHILE j <= finish
AND cs.match[
RML1][i] = H
DO
IF UnEqual[cs.rCamWtReg[j], cs.rCam[i][j]] THEN cs.match[RML1][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[RML1][i] ← L;
IF cs.rCamWtReg[numAddressBits-1] = X
OR cs.rCam[i][numAddressBits-1] = X
THEN
XCount ← XCount + 1;
IF cs.match[RML1][i] = H AND XCount > 0 THEN cs.match[RML1][i] ← X;
IF cs.match[
RML1][i] = H
THEN existsMatchH ← TRUE
ELSE
IF cs.match[
RML1][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[RML1][i] ← L;
ENDLOOP
ELSE {
FOR i
IN [0..NumIOLines)
DO
cs.iomatch[RML1][i] ← H;
XCount ← 0;
j ← 0;
WHILE j <= numPageBits-SCParms.numDevIdBits-1
AND cs.iomatch[
RML1][i] = H
DO
IF UnEqual[cs.rCamWtReg[j], cs.ioRCam[i][j]] THEN cs.iomatch[RML1][i] ← L;
IF cs.rCamWtReg[j] = X
OR cs.ioRCam[i][j] = X
THEN
XCount ← XCount + 1;
j ← j + 1;
ENDLOOP;
IF p[nxPartRMch].l = H
THEN {
j ← numPageBits;
WHILE j <= numPageAndBlockBits-1
AND cs.iomatch[
RML1][i] = H
DO
IF UnEqual[cs.rCamWtReg[j], cs.ioRCam[i][j]]
THEN cs.iomatch[
RML1][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[RML1][i] ← L;
IF cs.rCamWtReg[numAddressBits-1] = X OR cs.ioRCam[i][numAddressBits-1] = X THEN XCount ← XCount + 1;
IF cs.iomatch[RML1][i] = H AND XCount > 0 THEN cs.iomatch[RML1][i] ← X;
IF cs.iomatch[
RML1][i] = H
THEN existsMatchH ← TRUE
ELSE
IF cs.iomatch[
RML1][i] = L
THEN existsMatchL ← TRUE
ELSE existsMatchX ← TRUE;
ENDLOOP;
IF existsMatchH
THEN cs.arm ← H
ELSE IF existsMatchX THEN cs.arm ← X;
};
};
};
END;