DIRECTORY
Convert, Core, CoreClasses, CoreCreate, CoreFlat, CoreOps, IO, Ports, Rosemary, RosemaryUser, Rope, PWCoreHack, SmallCacheLogic, SCParms, Sisyph, TerminalIO;
SmallCacheArrayImpl: CEDAR PROGRAM
IMPORTS Convert, CoreClasses, CoreCreate, CoreFlat, CoreOps, Ports, PWCoreHack, Rosemary, Rope, SCParms, Sisyph, TerminalIO
EXPORTS SmallCacheLogic
~ BEGIN OPEN SmallCacheLogic;
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"];

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

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
];

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;
Array: PUBLIC PROC [cts: CellTypeSpec, cx: Context] RETURNS [ct: CellType] = BEGIN
public: Wire _ CoreCreate.WireList[LIST["Vdd", "Gnd", "Reset", "xCVCamPr", "xCRCamPr", "LdVML", "ClrVPV", "PCtlClrAllVPV", "PCtlResetVictim", CoreCreate.Seq["Spare", SCParms.numBitsPerCycle], "RamClock", "xLdUse", "PCtlDrABusVB", "PCtlDrABusVP", "nPartVMch", "xLdVCamRL", "xLdVCamWR", "xDrVCamBL", CoreCreate.Seq["VAdrsInOut", numAddressBits], "VPValidIn", "PCtlDrABusRB", "PCtlDrABusRP", "xLdRCamRL", "nxPartRMch", "xDrRCamBL", "xLdRCamWR", "xEnCamSelExt", "RBCycle2", 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", SCParms.numBytesPerWord], CoreCreate.Seq["nxWdSel", SCParms.numWordsPerLine], CoreCreate.Seq["WdWtData", SCParms.numBitsPerWord], CoreCreate.Seq["CycleIn", SCParms.numBitsPerCycle], CoreCreate.Seq["BAREn", SCParms.numCyclesPerLine], CoreCreate.Seq["Modes", SCParms.numBitsPerWord], CoreCreate.Seq["RAdrsOut", numAddressBits], CoreCreate.Seq["FlagsOut", NumFlagsBits], CoreCreate.Seq["BlkRdData", SCParms.numBitsPerLine], CoreCreate.Seq["WdRdData", SCParms.numBitsPerWord], "SetReschedule", "ASh", "AOw", "ARM3", "AVM", "Clock"]];

SELECT cts FROM
Schematic	=> ct _ Sisyph.ES["SCacheArray.sch", cx];
Procedure	=> {
ct _ CoreClasses.CreateUnspecified[public: public]; 
[] _ Rosemary.BindCellType[cellType: ct, roseClassName: MySmallCacheName];
[] _ 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, "CycleIn"];
Ports.InitPorts[ct, ls, none, "BAREn"];
[] _ 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, "Vdd", "Gnd", "Reset", "xCVCamPr", "xCRCamPr", "LdVML", "ClrVPV", "PCtlClrAllVPV"]; 
Ports.InitPorts[ct, l, none, "PCtlResetVictim", "Spare", "xLdUse", "PCtlDrABusVB", "PCtlDrABusVP", "nPartVMch", "xLdVCamRL", "xLdVCamWR", "xDrVCamBL"];
Ports.InitPorts[ct, l, none, "Clock", "VPValidIn", "PCtlDrABusRB", "PCtlDrABusRP", "xLdRCamRL", "nxPartRMch", "xDrRCamBL", "xLdRCamWR", "xEnCamSelExt", "RBCycle2"];
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", "ARM3", "AVM"]
};
CoreFile	=> ct _ PWCoreHack.Retrieve["SCacheArray"];
ENDCASE	=> ERROR;
END;
ArrayGetState: PUBLIC PROC[] RETURNS[csv: ROPE] = BEGIN
DumpState[];
csv _ cacheStateValueOut
END;
ArrayPutState: PUBLIC PROC[csv: ROPE] = BEGIN
cacheStateValueIn _ csv;
END;
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; 

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;

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]
};


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; 

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;
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;
IF ClockHToL[p, cs, clockEval] THEN cs.csMuxSR _ cs.tmpxEnCamSel;

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;

IF p[nEnRS].l=H THEN {
FOR i IN [0..1] DO 
cs.rsCmdLatch[i] _ p[xRSCmd].ls[i]; 
ENDLOOP; 
};

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
IF ClockLToH[p, cs, clockEval] THEN {
cs.rBCycle[5] _ cs.rBCycle[4]; 
cs.rBCycle[4] _ cs.rBCycle[3]; 
cs.rBCycle[3] _ cs.tmpRBCycle2;  
};

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;

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]
}
};

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;
};

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;

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;

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;
};


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;

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;


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;

IF (numH > 1 OR numX > 0) AND cs.resetDone THEN ERROR;


IF ClockLToH[p, cs, clockEval] THEN {
cs.ramWtSR[0] _ cs.tmpxWtRam;
cs.ramRdSR[0] _ cs.tmpxRdRam;
};

IF ClockHToL[p, cs, clockEval] THEN {
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];
};
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
};

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
};

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;

IF p[nEnRS].l = L THEN BEGIN 
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;

FOR i: NAT IN [0..SCParms.numBitsPerWord) DO p[Modes].ls[i] _ cs.ioRam.modes[i] ENDLOOP;
p[ASh].l _ cs.shBit; p[AOw].l _ cs.owBit;

prech _ Ports.AndL[cs.ramRdorWt, Ports.OrL[p[xRdRam].l, p[xWtRam].l]];
p[RamClock].l _ Ports.AndL[p[nEnRS].l, prech];

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;
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;
};
};
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)

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;

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;


IF ClockHToL[p, cs, clockEval] THEN { 
cs.enCamSelExtFF _ cs.tmpxEnCamSelExt;
cs.vCamLdFF _ cs.tmpxLdVCamRL;
cs.rCamLdFF _ cs.tmpxLdRCamRL;
};

cs.vCamSel _  IF cs.enCamSelExtFF = H THEN cs.csOut ELSE GND;

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;

IF cs.vCamLdFF = H THEN cs.vCamCSCmd1 _ p[xCSCmd].ls[1];
IF cs.rCamLdFF = H THEN cs.rCamCSCmd1 _ p[xCSCmd].ls[1];

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 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;
};

IF ClockLToH[p, cs, clockEval] THEN { 
cs.vCamDrBLFF _ cs.tmpxDrVCamBL; 
cs.rCamDrBLFF _ cs.tmpxDrRCamBL;

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;
};


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];
};
};

p[AVM].l _ cs.avm; p[ARM3].l _ cs.arm;

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 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;
 
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; 
};
IF p[PCtlClrAllVPV].l = H THEN {
FOR i IN [0..numMemLines) DO
cs.vCam[i][numAddressBits-1] _ L;
ENDLOOP;
};

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;
END.
���<��SmallCacheArrayImpl.mesa
Created: Paraminder Sahai September 1, 1987 6:55:41 am PDT
Paraminder Sahai September 27, 1987 0:53:06 am PDT
Pradeep Sindhu May 15, 1988 10:32:16 pm PDT


Constants and Type Defs
Two-D array containing Victim, RamSel, RML1, LVM, RML2, RML3, RML4, and GND
The following are used to capture input signals that go to flops
Signal Defs
Public Procs

Retrieves cacheStateValueOut

Sets cacheStateValueIn
Internal Procs
Copies cache state from cacheStateValueIn to simulation
Copies cache state from simulation to cacheStateValueOut
Create the state if it doesn't already exist
For signals going to flops triggered by Clock
For signals going to flops triggered by nClock
Keep loading state 3 cycles after Reset L to prevent PCtlClrAllVPV from screwing us
First the state changes
Then the combinatorial part
First the state change to the latch
Then the combinatorial part
On clock rising edge change the state for flops in the interface
Note that the array latches are enabled only during half cycles where Clock is low
On ClockLow, capture use and victim in tmp variables
On Rising edge of clock change the state of the flops
On Reset we set victim to point to some location
Do the computation for the PWtInProg path in SOInterface
Load BAR if necessary
Compute the values of Sh and Ow bits in array (Ow computation is completed below)
Compute RamSelectOut, numH, numX and complete computation of Ow
Compute outputs of IOSharedOwnerCell's, and complete computation of numH and numX
Sanity check on numH and numX
Change the state of flops in RamInterfaceCtl triggered by Clock
Do a Ram Read/Write and change the state of flops in RamInterfaceCtl triggered by nClock
Handle reads
Handle writes
Assert the block and word values onto the ports from the RamRdLatch
Compute SetReschedule
Compute composite values on lines going in to SOInterface from array and load SORdlatch
In numShAB, A is the value of the enable on the tristates, and B the value in storage
Assert Modes onto its port

Assert shared and owner onto their ports
Assert RamClock onto its port
Clear shared and owner latches in interface

Handle Read

Handle Write
Check if either set of tristates on VCamInterface are on
Check if either set of tristates on RCamInterface are on
Change the state of flops clocked by nClock in CamInterfaceCtl's
Handle the effect of xEnCamSelExt
Compute vCamIndex, rCamIndex, numX, and numH
Handle latch that holds CSCmd1
If vcam load latch signal is high and exactly one select line is high then read else precharge
If rcam load latch signal is high and exactly one select line is high then read else precharge
On rising edge of clock:
Change state of write flops in CamInterfaceCtl's
First load the write registers for vcam and rcam; note that valid bits are always enabled
Drive the bit lines and do a write or match, as appropriate
Assert avm and arm values onto port
If either block or page part VCamInterface tristates are on then output the appropriate one(s)
If either block or page RCamInterface part tristates are on then output the appropriate one(s)
Handle ClrVPV

Handle PCtlClrAllVPV
Handle Reset

�Ê=1��˜�šœ™IcodešÏnœ3™:K™2K™+K™�—šÏk	˜	Kšœ˜—J™�KšÑblnœžœž˜"Kšžœt˜{Kšžœ˜Kšœžœžœ˜headšÏl™Kšœžœžœ˜Kšœžœ~˜”K˜�Kšœžœ˜Kšœžœ˜K˜�Kšœ
žœ˜)KšœžœÏc˜IKšœ
žœ¡˜CKšœžœ$˜<šœžœžœžœ˜2Kšœ7˜7Kšœ7˜7Kšœ7˜7Kšœ7˜7Kšœ7˜7Kšœ6˜6Kšœ˜—šœžœžœžœ˜1Kšœ7˜7Kšœ7˜7Kšœ7˜7Kšœ7˜7Kšœ7˜7Kšœ6˜6Kšœ˜—Kšœ
žœžœžœ4˜bK˜�Kšœ'žœžœžœžœžœž™KKšœžœžœ
˜šœ
žœžœ˜Kšžœžœ˜K˜—K˜�Kšœ	žœžœ˜šœžœžœ˜Kšžœžœžœžœ˜'K˜—K˜�Kšœžœžœ˜#šœžœžœ˜Kšžœžœžœ˜#K˜—K˜�Kšœ
žœ˜$Kšœžœžœžœžœžœžœžœ˜BKšœžœžœ˜%šœžœžœ˜Kšœ˜Kšœžœ¡(˜>Kš
œ	žœžœžœžœžœžœ˜BKšœ¡˜+Kšœ
žœžœ	¡˜>Kšœ¡%˜DKšœ	žœžœ
¡˜;Kšœ¡˜6Kšœ
žœ¡˜0Kšœžœ¡˜3Kšœžœ¡˜/Kšœžœ¡˜7Kšœžœžœ	¡˜<Kšœžœ¡˜5Kšœ¡˜5Kšœ¡˜-Kšœžœžœ¡"˜KKšœ¡˜-Kšœžœ¡˜?Kšœžœ¡˜5Kšœžœ¡˜#Kšœžœqžœ¡
˜‘Kšœ ¡&˜FKšœžœ¡˜3Kšœ¡˜+Kšœžœžœ¡˜QKšœžœ¡˜(Kš
œ	žœžœžœžœ¡˜TKšœ>˜>Kšœžœžœ	˜=Kšœ!¡˜5Kšœžœ	¡a˜}Kšœ¡'˜9Kšœ¡˜Kšœžœ¡?˜UK˜�Kšœ@™@Kšœ+žœ˜/Kšœžœ˜ Kšœžœ˜Kšœžœžœ˜-Kšœ
˜
Kšœ˜Kšœ˜Kšœ
˜
Kšœ
˜
Kšœ
˜
Kšœ
˜
Kšœ
˜
Kšœ
˜
Kšœ
˜
Kšœ
˜
Kšœ
˜
Kšœ
˜
Kšœ
˜
Kšœ
˜
Kšœ˜Kšœž˜Kšœ˜—K˜�—š ™Kšœžœžœ˜Kšœžœ˜ Kšœ'žœžœ˜2Kšœêžœ˜ï—š ™š	Ÿœžœžœ"žœž˜RKšœ#žœ¶
˜Ý
K˜�šžœž˜Kšœžœ˜3˜Kšœ4˜4KšœJ˜JKšœ-˜-K˜�Kšœ\žœ,˜‹Kšœ)˜)KšœZžœ,˜‰Kšœ'˜'Kšœ)˜)Kšœ*˜*Kšœ(˜(Kšœ(˜(Kšœ+˜+Kšœ)˜)Kšœ*˜*Kšœ)˜)Kšœ'˜'KšœZžœ*˜‡Kšœ(˜(Kšœ,˜,Kšœ+˜+K˜�Kšœq˜qKšœ—˜—Kšœ¤˜¤KšœW˜WKšœ†˜†Kšœ*˜*KšœK˜KK˜—Kšœ4˜4Kšžœžœ˜—Kšžœ˜—K™�K™šŸ
œžœžœžœžœž˜7K˜K˜Kšžœ˜—K™�K™š	Ÿ
œžœžœžœž˜-K˜Kšžœ˜——š ™K™7šŸ	œžœž˜Kšœ˜Kšœžœ˜Kšœžœ˜š	œžœžœžœ
ž˜4Kšžœžœžœ˜%šžœž˜ Kšœžœ˜Kšœžœ˜Kšœžœ˜Kšžœžœ˜—Kšžœ˜—K˜�šœžœžœž˜4Kšœžœ˜šžœžœžœž˜Kšœ9˜9šžœž˜%Kšœ˜Kšœ˜Kšœ˜Kšžœ˜—K˜Kšžœ˜—Kšžœ˜—K˜�š	œžœžœž˜:Jšœžœ˜šžœžœžœž˜0šžœžœžœž˜0Jšœ9˜9šžœž˜%Kšœ4˜4Kšœ4˜4Kšœ4˜4Kšžœ˜—K˜Jšžœ˜—Jšžœ˜—Kšžœ˜—K˜�š	œžœžœžœž˜&JšœT˜TJšœJ˜JJšœZ˜ZJšœ˜Jšžœ˜J˜�—š	œžœžœžœž˜(JšœM˜MJšœJ˜JJšžœA˜EJšœ˜Jšžœ˜—J˜�Jšžœžœžœžœ˜%Jšœ.˜.šžœžœžœž˜!J˜Jšžœ˜—Jšœ%˜%J˜�šžœž˜Jšœ	žœ˜Kšœ$˜$Kšœ$˜$Kšœ%˜%Kšœ$˜$Kšœ$˜$Kšœ%˜%Kšœ&˜&Kšžœ˜—Kšžœ˜—K˜�K™8šŸ	œžœž˜Kšœ˜K˜�š	œžœžœžœž˜.šžœž˜
Kšœžœ˜Kšœžœ˜Kšœžœ˜Kšžœžœ˜—Kšžœ˜—K˜�šœžœžœžœžœž˜CKš
žœžœžœžœ%žœ˜JKšžœ˜—K˜�š	
œžœžœžœž˜@Jšœ%˜%Jš
žœžœžœžœ%žœ˜NJšœ˜Jš
žœžœžœ$žœ%žœ˜`Jšœ˜Jš
žœžœžœ'žœ%žœ˜cKšžœ˜—K˜�šœžœžœžœžœž˜Gšžœžœžœž˜0šžœžœžœž˜0JšœF˜FJšžœ˜—Jšžœ žœ˜>Jšžœ˜—Kšžœ˜—K˜�Kšžœžœžœžœ˜KšœW˜Wšžœžœžœž˜!KšœV˜VKšœV˜VKšœV˜VKšœV˜VKšœO˜OKšœO˜OKšœQ˜QKšœU˜UK˜8Kšžœ˜—K˜8Kšžœ˜—K˜�šŸœž˜Kšœžœ˜
Kšœ˜K˜�K™,šžœ
ž˜šžœ˜Kšœžœ˜Kšœžœ˜šžœ
žœž˜Kšœžœ ˜1Kšžœ˜—Kšœ	žœ!˜-Kšœžœ!˜0Kšœžœ!˜,Kšœžœ!˜,Kšœžœ,˜?Kšœ	žœ,˜8Kšœ	žœ˜)šžœžœžœž˜!Kšœžœ,˜;Kšžœ˜—Kšœžœ,˜AKšœžœ,˜AKšœžœ,˜>Kšœžœ,˜DKšœžœ,˜DKšœžœ,˜BKšœžœ,˜@Kšœžœ,˜BKšœžœ,˜BKšœžœ,˜BKšœžœ,˜BKšœ
žœ˜*šžœžœžœž˜!Kšœ
žœ$˜4Kšžœ˜—Kšœ
žœ˜*šžœžœžœž˜!Kšœ
žœ$˜4Kšžœ˜—K˜šžœžœžœž˜ Kšœžœ$˜6Kšžœ˜—šžœžœžœž˜ Kšœžœ$˜6Kšžœ˜—Kšœžœ˜+šžœžœžœž˜!Kšœžœ"˜3Kšžœ˜—Kšœžœ$˜8Kšœžœ$˜6Kšœžœ$˜8Kšœžœ$˜6K˜�Kšœžœ$˜7Kšœžœ-˜@Kšœžœ.˜?Kšœžœ$˜:K˜—Kšžœžœ˜*—K˜�Kšœg˜gK˜�šžœžœžœ˜ K˜WKšžœ˜—šžœžœžœ˜Kšœ-˜-Kšžœ˜—šžœžœžœ˜(Kšœ˜Kšœ˜Kšžœ˜—šžœžœž˜Kšœ4˜4Kšœ4˜4šžœžœIž˜SKšœ%˜%Kšžœ˜—šžœžœžœ˜%K˜%Kšžœ˜—šžœžœž˜K˜Kšžœ˜—šžœžœžœ˜(Kšœ˜Kšžœ˜—K˜<šžœ
žœ
žœžœ˜"K˜Kšžœ˜—Kšœ	žœ	˜Kšžœ˜—K˜Kšœ˜šžœžœžœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšžœ˜—šžœžœžœ˜K˜Kšžœ˜—Kšœ%˜%Kšœ"˜"Kšœ,˜,šžœžœžœ˜ Kšœ/˜/Kšžœ˜	—šžœžœžœ˜)Kšœ˜Kšžœ˜	—šžœžœžœ˜*Kšœ˜Kšžœ˜	—šžœžœžœ˜Kšœ˜Kšžœ˜
—KšœÅžœžœ˜Ïšžœžœžœ˜šžœžœIž˜SK˜+Kšžœ˜—Kšœ$˜$Kšœ#˜#Kšžœ˜—šžœžœž˜šžœžœžœ˜Kšœžœ$žœžœ˜HKšžœ˜—šžœžœž˜$Kšœžœ#žœžœ˜FKšœžœ#žœžœ˜FKšžœ˜—Kšžœ˜—šžœžœžœ˜)Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšžœ˜—šžœžœž˜š	žœ
žœžœžœž˜K˜Kšžœ˜—Kšœžœ	˜Kšžœ˜—Kšœžœ˜K˜�Kšœ¼˜¼KšœÐ˜ÐKšœ¸˜¸K˜�Kšœ”˜”K˜�Kšœ’˜’K˜�Kšœ¢˜¢K˜�KšœP˜PK˜�K˜Kšžœ˜K˜�—K˜�šŸœž˜!Kšœžœ˜"K˜Kšžœžœžœ˜+Kšžœžœ˜1Kšžœžœ˜1Kšœ˜Kšœ
˜
Kšžœ˜Kšœ˜Kšœ#˜#Kšœ˜Kšœ˜Kš
žœžœžœžœžœ˜JKšžœ˜—K˜�š
	œžœ+žœžœžœ˜Qšžœ˜Kš
žœžœžœžœžœ˜<Kšžœžœžœ˜*—K˜—K˜�š
	œžœ+žœžœžœ˜Qšžœ˜Kš
žœžœžœžœžœ˜<Kšžœžœžœ˜*—K˜—K˜�š
œžœ+žœžœžœ˜Nšžœ˜Kšžœžœžœžœ˜+Kšžœžœ˜—K˜—K˜�š
œžœ+žœžœžœ˜Nšžœ˜Kšžœžœžœžœ˜+Kšžœžœ˜—K˜—K˜�K˜�K™-šœžœ"ž˜5šžœžœžœžœ˜%KšœP˜PKšžœ˜	—šžœžœžœžœ˜.Kšœ%˜%Kšžœ˜	—šžœžœžœžœ˜/Kšœ!˜!Kšžœ˜	—šžœžœžœžœ˜$Kšœ%˜%Kšžœ˜
—Kšœ ˜ Kšœ˜Kšœ˜Kšœ!˜!Kšœ!˜!Kšœ!˜!Kšœ!˜!Kšœ!˜!Kšœ!˜!Kšœ!˜!Kšœ˜Kšžœ˜—K˜�K™.šœžœ"ž˜5Kšœ!˜!Kšœ'˜'Kšœ!˜!Kšœ!˜!Kšœ7˜7Kšžœ˜—K˜�šœžœ+žœž˜IKšžœžœžœžœ˜/šžœ
ž˜Kšœ ˜ Kšœ6˜6Kšžœ˜—K™Sšžœžœžœ˜BKšžœ˜Kšžœžœžœ6˜R—Kšžœ˜—K˜�šœžœ+žœž˜CKšœžœ˜K™Kšžœžœ˜AK˜�K™Kšžœžœžœ˜&šžœžœ˜Kšžœžœžœ˜-Kšžœžœ˜&šžœžœ˜Kšœž˜—šžœ˜šžœžœ˜Kšœž˜—šžœ˜šžœžœ˜Kšœž˜—šžœžœžœ˜Kšœ˜———Kšœ˜—Kšœžœ˜—K˜�K˜�šœžœ"ž˜2Kšœžœ˜K˜�K™#šžœžœ˜šžœžœžœ˜Kšœ$˜$—Kšžœ˜	Kšœ˜—K˜�K™Kšžœžœžœ˜.Kšžœžœ˜(šžœžœ˜Kšœžœ˜Kšœ
žœ˜K˜—šžœ˜šžœžœ˜Kšœžœ˜Kšœ
žœ˜—K˜—šžœ˜šžœžœ˜Kšœžœ˜Kšœ
žœ˜—Kšœ˜—šžœ˜šžœžœ˜Kšœ˜Kšœ
žœ˜—Kšœ˜—Kšžœ˜—K˜�šÐbkœžœ+žœž˜DK™@šžœžœ˜%Kšœ˜Kšœ˜Kšœ!˜!Kšœ˜—K˜�J™Ršžœžœ˜"šžœžœžœž˜!šžœžœ˜Kšœ	žœžœ˜'K˜—šžœžœ˜Kšœ	žœžœ˜'K˜—šžœžœ˜Kšœ	žœžœ˜'K˜—Kšžœ˜—K˜�šžœžœžœž˜ šžœžœ˜Kšœžœžœ˜*K˜—šžœžœ˜Kšœžœžœ˜+K˜—šžœžœ˜Kšœžœžœ˜*K˜—Kšžœ˜—Kšœ˜—Kšžœ˜—K˜�K˜�šœžœ+žœž˜Dšœžœžœžœžœž˜*Kšžœžœžœžœ˜*Kšžœ˜—K˜�K™4šžœžœ˜"šžœžœžœž˜!šœ˜Kšœ[˜[šœ
˜
Kšœžœ˜*Kšœ6˜6—K˜—Kšžœ˜—šžœžœ˜ Jšžœžœ+˜MJ˜—K˜—K˜�K™5šžœžœ˜%K˜#šžœžœžœž˜!K˜Kšžœžœžœ˜PKšžœ˜—Kšœ˜—K˜�K™0šžœžœžœ˜5šžœžœžœžœ˜"Kšœ˜Kšžœ˜	—Kšœ%˜%Kšœ4˜4Kšœ˜Kšœ˜—Kšžœ˜—K˜�K˜�šœžœ+žœž˜FKšœ˜Kšœ¡=˜HKšœ¡?˜KKšœ¡=˜DKšœžœ¡C˜OKšœ
˜
K˜�K™8Kšžœžœ˜AKšžœžœ˜<Kšžœžœžœžœ˜RK˜�K™šžœžœ˜%Kšœžœ˜šžœžœžœž˜.šžœžœ˜Kšžœ)žœžœ˜6šžœžœžœž˜,KšœP˜PKšœi˜iKšžœ˜—K˜—Kšžœ˜—Kšœ˜—K˜�K˜�K™Qšžœžœžœ˜šžœ˜šžœ˜šžœžœ˜(Kšžœ˜šžœ˜šžœ˜Kšžœ˜Kšžœžœžœ˜+—K˜——šžœžœ
˜ Kšžœ˜—šžœ˜šžœ
˜Kšžœ˜Kšžœžœžœ˜)—K˜—Kšœ˜—šžœ˜šžœžœ˜"šžœžœ
žœžœ
žœžœ˜tKšžœ˜—šžœžœ
žœžœ
žœžœ˜dKšžœ˜—Kšœ˜—K˜——Kšžœ˜—K˜�Kšœ?™?Kšœ˜K˜šžœžœž˜šžœžœžœžœ˜LKšžœ,˜1šžœ˜šžœžœžœžœ
žœžœ
žœžœ
˜ªKšžœ˜Kšžœ˜———šžœ˜Kšžœ!˜%Kšžœžœžœ˜7—šžœžœžœ˜?šžœ˜šžœ˜
Kšžœ
žœžœžœ˜3šž˜šžœžœ˜"Kšžœ
˜Kšžœžœžœžœžœžœ
˜]———Kšœ˜—šžœ˜šžœžœžœžœ˜Fšžœžœ˜"Kšžœ
˜Kšžœžœžœžœžœžœ˜^—Kšœ˜—K˜——Kšžœ˜—K˜�K˜�K™Qšžœ
˜Kšžœžœ˜šžœžœžœžœ˜!šžœ˜ Kšžœ"˜&Kšžœžœžœ˜>—Kšžœ˜——K˜�K™Kš
žœžœžœžœžœ˜6K˜�K˜�K™?šžœžœ˜%Kšœ˜Kšœ˜Kšœ˜—K˜�K™Xšžœžœ˜%K™šžœžœ˜šžœ˜šžœžœžœžœ˜-Kšœ(˜(Kšžœ˜—Kšžœ˜—Kšœ˜—K™
šžœžœ˜šžœ˜šžœ˜šžœ˜šžœžœžœžœ˜-Kšœ!˜!Kšžœ˜—šžœ˜Kšœ˜šžœžœž˜'Kšœ˜Kšžœžœ)˜GKšœ˜Kšžœ˜—Kšœ˜——Kšœ˜—Kšžœ˜—Kšœ˜—Kšœ˜Kšœ˜Kšœ˜Kšœ˜K˜�—K™CKšœ-˜-šžœžœ˜Kšœžœ˜$šžœžœžœž˜,Kšœ)˜)Kšœ%˜%Kšž˜—K˜—K˜�K™K˜K˜	šžœžœž˜'šžœžœ˜4Kšžœ˜šžœžœžœž˜>K˜——Kšžœ˜—šžœžœ
žœ˜CK˜�—K™Wšžœžœž¡˜K™UKšœ	žœ˜Kšœ	žœ˜Kšœ	žœ˜Kšœ	žœ˜Kšœ	žœ˜Kšœ	žœ˜Kšœ	žœ˜Kšœ	žœ˜Kšœ	žœ˜Kšœ	žœ˜Kšœ	žœ˜Kšœ	žœ˜šžœžœžœ˜šžœ˜šžœ˜šžœ˜
Kšžœ˜šžœžœ
˜Kšžœ˜Kšžœ˜——šžœ˜
Kšžœ˜šžœžœ
˜Kšžœ˜Kšžœ˜——K˜—šžœ˜šžœ˜šžœ˜šžœ
˜Kšžœ˜šžœžœ˜Kšžœ˜Kšžœ˜——šžœ
˜Kšžœ˜šžœžœ
˜Kšžœ˜Kšžœ˜——K˜——K˜——Kšžœ˜	—K˜�šžœžœž˜šžœ˜ Kšžœ˜Kšžœžœžœ˜A—Kšžœ˜—K˜�šžœ4˜6Kšžœ˜šžœžœžœ$˜9Kšžœ˜šžœžœ$˜9Kšžœ˜Kšžœ˜—K˜�——šžœ4˜6Kšžœ˜šžœžœžœ$˜9Kšžœ˜šžœžœ$˜9Kšžœ˜Kšžœ˜———Kšžœ˜—K˜�K™Jš
žœžœžœžœ$žœ˜XK™�K™(K˜)K˜�K™KšœF˜FKšœ.˜.K˜�K™+Kšžœžœ˜4K˜�Kšžœ˜—˜�K˜�—šœžœ+žœž˜Cšœ	žœ˜
Kšœ"˜"K™�K™šžœžœ˜šžœžœžœ˜(Kšœ¡œ¡˜*Kšžœ˜	—šžœžœ˜šžœžœžœ˜!šžœžœžœ˜(KšœF˜FKšžœ˜——šž˜šžœžœžœ˜!šžœžœžœ˜(KšœF˜FKšžœ˜——šž˜šžœžœžœ˜"šžœžœžœ˜(KšœC˜CKšžœ˜——šž˜šžœžœžœ˜!šžœžœžœ˜(KšœI˜IKšžœ˜——šž˜šžœžœžœ˜!šžœžœžœ˜(KšœI˜IKšžœ˜——šž˜šžœžœžœ˜!šžœžœžœ˜(KšœF˜FKšž˜——šž˜šžœžœžœ˜!šžœžœžœ˜(KšœD˜DKšžœ˜——šž˜šžœžœžœ˜!šžœžœžœ˜(KšœF˜FKšžœ˜——šž˜šžœžœžœ˜!šžœžœžœ˜(KšœF˜FKšžœ˜——šž˜šžœžœžœ˜!šžœžœžœ˜(KšœF˜FKšžœ˜——šž˜šžœžœžœžœžœž˜HKšœF˜FKšžœ˜———————————Kšœ˜—Kšœ˜—K™�K™šžœžœ˜šžœžœ˜šžœžœžœ˜!šžœžœžœ˜(Kšœ˜šžœžœ˜Kšœ)˜)——Kšžœ˜—šž˜šžœžœžœ˜!šžœžœžœ˜(Kšœ˜šžœžœ˜Kšœ(˜(——Kšžœ˜—Kšž˜šžœžœžœ˜"šžœžœžœ˜(Kšœ˜šžœžœ˜Kšœ%˜%——Kšžœ˜—šž˜šžœžœžœ˜!šžœžœžœ˜(Kšœ˜šžœžœ˜Kšœ+˜+——Kšžœ˜—šž˜šžœžœžœ˜!šžœžœžœ˜(Kšœ˜šžœžœ˜Kšœ+˜+——Kšžœ˜—šž˜šžœžœžœ˜!šžœžœžœ˜(Kšœ˜šžœžœ˜Kšœ)˜)——Kšžœ˜—šž˜šžœžœžœ˜!šžœžœžœ˜(Kšœ˜šžœžœ˜Kšœ'˜'——Kšžœ˜—šž˜šžœžœžœ˜!šžœžœžœ˜'šžœžœ˜Kšœ˜—šž˜šžœžœž˜;Kšœ˜K˜�———Kšžœ˜—šž˜šžœžœžœ˜!šžœžœžœ˜(šžœžœ˜Kšœ˜—šžœ˜šžœžœž˜<Kšœ˜—K˜�——Kšžœ˜————————Kšœ˜—Kšœ˜——Kšžœ˜—K˜�š	œžœžœžœž˜=šžœžœžœž˜-Kšžœžœžœ˜'Kšžœ˜—Kšžœ˜
Kšžœ˜—K˜�K˜�šœžœ+žœž˜NKšœ˜Kšœ¡6˜BKšœ¡6˜BKšœžœ¡,˜=K˜�K™8š
œžœ!žœžœžœ˜Lšžœžœžœžœžœžœžœ˜‰Kšœžœžœž˜—Kšžœ˜—K˜�K™8š
œžœ!žœžœžœ˜Lšžœžœžœžœžœžœžœ˜‰Kšœžœžœžœ˜—Kšžœ˜—K˜�K˜�K™@šžœžœ˜&Kšœ&˜&Kšœ˜Kšœ˜Kšœ˜—K˜�Kšœ!™!Kš	œžœžœ
žœžœ˜=K˜�K™,K˜K˜šžœžœž˜šžœ˜Kšžœ!˜%Kšžœžœ˜5—Kšžœžœ˜2Kšžœ˜—Kšžœ
žœžœžœ˜(š
žœ
žœžœžœžœ˜AK˜�—K™Kšžœžœ!˜8Kšžœžœ!˜8K˜�K™^š	žœžœžœžœž˜7Kšœžœžœžœ˜HKšžœ˜—K˜�K™^šžœžœ˜šžœžœžœ˜ Kšœžœžœžœ˜IKšžœ˜	—šžœžœžœ˜Kšœžœžœžœ˜KKšžœ˜—Kšœ˜—K˜�K™šžœžœ˜&K™0Kšœ!˜!Kšœ ˜ K˜�K™Yšžœžœ˜šžœžœžœ˜%Kšœ&˜&Kšžœ˜—šžœžœž˜Kšœ$˜$Kšžœ˜—Kšœ˜—Kšœ1˜1K˜�šžœžœ˜šžœžœžœ˜%Kšœ$˜$—Kšžœ˜	Kšœ˜—Kšœ1˜1Kšœ˜—K˜�K˜�Kšœ;™;šžœžœ˜šžœžœ˜šžœžœžœ˜%Kšœ%˜%Kšžœ˜	—KšœC˜CKšœ˜—šžœ˜Kšžœ)˜-šžœ˜šžœžœžœ˜%Kšœ)˜)Kšžœ˜	—šœG˜Gšžœžœžœ˜šžœ˜Kšžœ+˜/Kšžœ¡+˜M—Kšžœ˜——Kšœ˜——Kšœ˜—šžœžœ˜šžœžœ˜šžœžœžœ˜%Kšœ%˜%Kšžœ˜	—KšœB˜BKšœ˜—šžœ˜Kšžœ&˜*šžœ˜šžœžœžœ˜%Kšœ)˜)Kšžœ˜	—KšœF˜FKšœ˜——Kšœ˜—K˜�K™#Kšœ&˜&K˜�K™^šžœ˜šžœ˜šžœ˜šžœ˜šžœžœž˜Kšœ˜Kšœ)˜)Kšžœ˜
—šžœžœ)žœ˜5Kšœ˜Kšœ˜Kšžœ˜—Kšœ,˜,KšœG˜GKšœ˜—šžœ˜šžœžœž˜Kšœ˜Kšžœ˜
—šžœžœ'žœ˜3Kšœ˜Kšžœ˜—Kšœ˜——šžœ˜šžœžœžœ$žœ˜4Kšœ˜Kšœ*˜*Kšž˜—šžœžœžœ$žœ˜4Kšœ˜Kšžœ˜——Kšœ˜—š	žœžœžœžœž˜)Kšœ˜Kšžœ˜——K˜�K™^šžœ˜šžœ˜šžœ˜šžœ˜šžœžœžœžœ˜"Kšœ˜Kšœ'˜'Kšžœ˜—šžœžœžœž˜"Kšœ˜Kšœ'˜'Kšžœ˜—Kšœ˜—šžœ˜Kš
žœžœžœžœžœ˜DKš
žœžœžœžœžœ˜EKšœ˜——šžœ˜šžœ˜šžœžœžœžœ˜/Kšœ˜Kšœ'˜'Kšžœ˜	—šžœžœžœ)žœ˜9Kšœ˜Kšœ˜Kšžœ˜—Kšœ˜—šžœ˜šžœžœžœž˜.Kšœ˜Kšžœ˜—K˜—K˜——š	žœžœžœžœž˜)Kšœ˜Kšžœ˜——K˜Kšœ
™
šžœžœ˜šžœžœžœ˜Kšžœ
žœ	žœ%˜BKšžœ˜	—K˜—K™�K™šžœžœ˜ šžœžœž˜Kšœ!˜!Kšžœ˜—K˜—K˜�K™šžœžœ˜šžœžœž˜Kšœ!˜!Kšœ	žœ	˜Kšœ	žœ	˜Kšžœ˜—šžœžœž˜Kšœžœ	˜Kšœžœ	˜Kšžœ˜—K˜K˜—Kšžœ˜—K˜šœžœCžœž˜bKšœ˜Kšœ¡P˜XKšœžœ¡O˜\Kšœ*žœ˜2K˜�š
œžœžœžœžœ˜6Kšžœžœžœžœžœžœžœžœ˜GKšžœ˜K˜�—š
œžœžœžœžœ˜8Kšžœžœžœžœžœžœžœžœ˜GKšžœ˜—K˜�Kšœžœžœžœ˜Ašžœžœžœ˜-Kšœ˜šžœ˜Kšžœ˜Kšžœ ˜$—šœžœžœžœ˜Kšœ	žœ	˜Kšœ˜Kšœ˜šžœ
žœ
žœ	žœ˜/Kšžœ)žœ
žœ
˜FKšžœžœžœ˜FKšœ˜Kšžœ˜—šžœEž˜KKšœ	žœ
˜—šžœ$žœ"ž˜NKšœ˜—šžœ
žœ	žœ˜šžœžœžœ˜šžœžœ+ž˜KKšœ	žœ
˜—šžœžœžœ˜3Kšœ˜—Kšžœ˜—Kšœ˜—Kš
žœ
žœ	žœžœ
žœ˜Cšžœ
žœ˜Kšžœžœ˜šžœžœ
žœ˜Kšžœžœ˜Kšžœžœ˜——Kšžœ˜—šžœ
˜Kšžœ˜Kšžœžœžœ
˜&—šžœ˜
šžœžœžœžœ˜!Kšœžœ
˜Kšžœ˜—šžœ˜šžœžœžœ˜Kšœžœ
˜Kšœ˜Kšœ˜šžœ
žœžœ	žœ˜1Kšžœ+žœžœ
˜JKšžœžœžœ ˜RKšžœ˜	—šžœGž˜MKšœžœ
˜—šžœ$žœ$ž˜PKšœ˜—šžœžœ	žœ˜ šžœžœžœ˜šžœžœ-ž˜MKšœžœ
˜—Kšžœžœžœ˜J—Kšžœ˜—Kšœ˜Kš
žœžœ	žœžœžœ˜Gšžœžœ˜Kšžœžœ˜šžœžœžœ˜Kšžœžœ˜Kšžœžœ˜——Kšžœ˜
—šžœ
˜Kšžœ˜Kšžœžœžœ˜%—Kšœ˜——Kšœ˜—Kšœ˜šžœžœžœžœ˜JKšœ˜šžœ˜Kšžœ˜Kšžœ ˜$—šœžœžœžœ˜Kšœ	žœ
˜Kšœ˜Kšœ˜šžœ
žœ
žœ	žœ˜0Kšžœ)žœ
žœ	˜FKšœžœžœžœ!˜RKšžœ˜—šžœEž˜KKšœ	žœ
˜—šžœ$žœ"ž˜NKšœ˜—Kš
žœ
žœ	žœžœ
žœ
˜Dšžœ
žœ˜Kšžœžœ˜šžœžœ
žœ˜Kšžœžœ˜Kšžœžœ˜——Kšžœ˜	—šžœ
˜Kšžœ˜Kšžœžœžœ
˜&—šžœ˜
šžœžœžœžœ˜!Kšœžœ
˜Kšžœ˜—šžœ˜šžœžœžœ˜Kšœžœ
˜Kšœ˜Kšœ˜šžœ)žœžœ	žœ˜NKšžœ+žœžœ
˜Kšžœžœžœ˜3Kšœ˜Kšœ˜—Kšžœ˜—šžœžœ˜K˜šžœžœžœ	žœ˜Ašžœ+žœžœ
˜Kšžœžœžœ˜3Kšœ˜Kšœ˜——Kšžœ˜—K˜—Kšœ˜šžœGž˜MKšœžœ
˜—Kšžœ$žœ$žœ˜fKš
žœžœ	žœžœžœ˜Išžœžœ˜Kšžœžœ˜šžœžœžœ˜Kšžœžœ˜Kšžœžœ˜——Kšžœ˜
—šžœ
˜Kšžœ˜Kšžœžœžœ˜%—Kšœ˜——Kšœ˜—Kšœ˜Kšžœ˜——Kšžœ˜J™�—�…—����ºZ��Ç�