<> <> <> <> <<>> 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> 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. <<>>