<> <> <> <> <<>> <> <> <> <> Directory IO; Imports BitOps, CacheOps, Cucumber, Dragon, Random; <> Cache: LAMBDA [cacheParm: |CacheOps.Cache|, skipRejectsParm: |BOOL|] RETURN CELLTYPE AutoName PORTS [ <> <<>> <> PhA, PhB < BOOL, <> PData = INT[32], PCmdA < EnumType["Dragon.PBusCommands"], PRejectB = BOOL, PFaultB = EnumType["Dragon.PBusFaults"], <
> MCmdAB = EnumType["Dragon.MBusCommands"], MDataAB = INT[32], MParityAB = BOOL, MNShared = BOOL, MNError > BOOL, MRq > BOOL, MNewRq > BOOL, MGnt < BOOL, <> <> ResetAB < BOOL, DHoldAB < BOOL, -- must be high before testing DShiftAB < BOOL, -- shift the shift register by 1 bit if ~DNSelect DExecuteAB < BOOL, -- interpret the content of the shift register if ~DNSelect DNSelectAB < BOOL, -- if high, hold but don't Execute or Shift DDataInAB < BOOL, -- sampled during each PhB following a PhB that DShift is asserted DDataOutAB > BOOL -- changes during each PhA following a PhB that DShift is asserted, continues to be driven through the PhB following the PhA it changes ] State phALast: BOOL _ FALSE, -- hack to improve simulation performance cache: CacheOps.Cache, randomStream: Random.RandomStream, cycleNo: INT _ 0, skipRejects: BOOL _ FALSE, rejectCycles: NAT _ 0, cmdAB: PBusCommands _ NoOp, address, fetchData, storeDataBA: Dragon.HexWord _ 0, cmdType: {noOp, reset, fetch, store} _ noOp, pageFault, writeFault, firstBOfCmdBA: BOOL _ FALSE EvalSimple IF PhA THEN BEGIN IF NOT phALast THEN BEGIN IF cmdType=store AND rejectCycles=0 AND NOT (pageFault OR writeFault) THEN CacheOps.Write[cache, address, storeDataBA]; phALast _ TRUE; END; IF rejectCycles=0 THEN address _ BitOps.ELFD[container: PData, containerWidth: 32, fieldPosition: 0, fieldWidth: 32]; cmdAB _ PCmdA; PRejectB _ FALSE; PFaultB _ none; END; IF PhB THEN BEGIN IF phALast THEN BEGIN IF ResetAB THEN BEGIN randomStream _ Random.Create[seed: randomSeed]; rejectCycles _ randomStream.ChooseInt[1, 5]; cmdType _ reset; cycleNo _ 0; cache _ CacheOps.NewCache[cache]; pageFault _ writeFault _ FALSE; END ELSE cycleNo _ cycleNo+1; IF rejectCycles=0 THEN BEGIN pageFault _ writeFault _ FALSE; SELECT cmdAB FROM Fetch, FetchHold => BEGIN cmdType _ fetch; [data: fetchData, rejectCycles: rejectCycles, pageFault: pageFault] _ CacheOps.Access[cache, address, read, cycleNo]; END; Store, StoreHold => BEGIN cmdType _ store; [rejectCycles: rejectCycles, pageFault: pageFault, writeProtect: writeFault] _ CacheOps.Access[cache, address, write, cycleNo]; END; IOFetch, IOStore, IOFetchHold, IOStoreHold => BEGIN Dragon.Assert[ FALSE, "Cache doesn't yet implement IO operations" ]; -- for now cmdType _ noOp; END; ENDCASE => cmdType _ noOp; rejectCycles _ (SELECT TRUE FROM skipRejects => INT[0], rejectCycles>0 => rejectCycles+randomStream.ChooseInt[0, 1], ENDCASE => rejectCycles); IF pageFault OR writeFault THEN rejectCycles _ MAX[1, rejectCycles]; firstBOfCmdBA _ TRUE; END ELSE BEGIN -- rejected on previous PhB Dragon.Assert[ (cmdAB = NoOp) ]; rejectCycles _ rejectCycles-1; firstBOfCmdBA _ FALSE; END; phALast _ FALSE; END; SELECT TRUE FROM cmdType=store AND firstBOfCmdBA => storeDataBA _ BitOps.ELFD[container: PData, containerWidth: 32, fieldPosition: 0, fieldWidth: 32]; cmdType=fetch AND rejectCycles=0 AND NOT pageFault => PData _ BitOps.ILID[source: fetchData, container: PData, containerWidth: 32, fieldPosition: 0, fieldWidth: 32]; ENDCASE => NULL; -- neither write nor read PData END; drive[PData] _ IF (PhB AND cmdType=fetch AND rejectCycles=0 AND NOT pageFault) THEN drive ELSE ignore; PFaultB _ (SELECT TRUE FROM NOT PhB => none, rejectCycles=1 AND pageFault => page, rejectCycles=1 AND writeFault => write, ENDCASE => none); PRejectB _ PhB AND rejectCycles>0; drive[PFaultB] _ drive[PRejectB] _ IF PhA OR (PhB AND cmdType#noOp) THEN drive ELSE ignore; Initializer cache _ cacheParm; skipRejects _ skipRejectsParm; <> <<>> <> <> <> <<>> <> <> <> <<>> <> <> <> <<>> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <<>> <

M control, all change during PhA>> <> <> <> <> <> <> <<>> <> <> <> <<>> <> <> ENDCELLTYPE; CEDAR <> <> <<>> <> <> CacheStateHandler: Cucumber.Handler = NEW[Cucumber.HandlerRep _ [ PrepareWhole: CacheStatePrepareProc, PartTransfer: CacheTransferProc ]]; CacheStatePrepareProc: PROC [ whole: REF ANY, where: IO.STREAM, direction: Cucumber.Direction, data: REF ANY ] RETURNS [ leaveTheseToMe: Cucumber.SelectorList ] -- Cucumber.Bracket -- = {leaveTheseToMe _ LIST[$cache]}; CacheTransferProc: PROC [ whole: REF ANY, part: Cucumber.Path, where: IO.STREAM, direction: Cucumber.Direction, data: REF ANY ] -- Cucumber.PartTransferProc -- = TRUSTED {Cucumber.Transfer[ what: NARROW[whole, REF CacheStateRec].cache, where: where, direction: direction ]}; randomSeed: INT _ -1; Cucumber.Register[CacheStateHandler, CODE[CacheStateRec]];