DIRECTORY RoseTypes, Cache, RoseCreate, IO, BitOps, CacheOps, Cucumber, Dragon, Random, PrintTV, AMBridge, SwitchTypes; CacheImpl: CEDAR PROGRAM IMPORTS RoseCreate, BitOps, CacheOps, Cucumber, Dragon, Random, PrintTV, AMBridge, IO EXPORTS Cache = BEGIN OPEN RoseTypes, Cache; PBusCommands: TYPE = Dragon.PBusCommands; PBusFaults: TYPE = Dragon.PBusFaults; MBusCommands: TYPE = Dragon.MBusCommands; RegisterCells: PROC = BEGIN END; otherss: SymbolTable _ RoseCreate.GetOtherss["Cache.partsAssertions"]; OldCache: TYPE = RECORD [args: CacheArgs, ct: CellType]; oldCache: LIST OF OldCache _ NIL; Cache: PUBLIC PROC [args: CacheArgs] RETURNS [ct: CellType] = BEGIN FOR old: LIST OF OldCache _ oldCache, old.rest WHILE old # NIL DO IF old.first.args = args THEN RETURN [old.first.ct] ENDLOOP; ct _ RoseCreate.RegisterCellType[name: CacheName[args], expandProc: NIL, ioCreator: CreateCacheIO, driveCreator: CreateCacheDrive, initializer: InitializeCache, evals: [EvalSimple: CacheEvalSimple], tests: LIST[], ports: CreateCachePorts[args] , typeData: NEW [CacheArgs _ args]]; oldCache _ CONS[[args, ct], oldCache]; END; CacheName: PROC [args: CacheArgs] RETURNS [name: ROPE] = { to: IO.STREAM _ IO.ROS[]; to.PutRope["Cache"]; TRUSTED {PrintTV.Print[tv: AMBridge.TVForReferent[NEW [CacheArgs _ args]], put: to, depth: 2]}; name _ IO.RopeFromROS[to]}; CreateCachePorts: PROC [args: CacheArgs] RETURNS [ports: Ports] = {ports _ RoseCreate.PortsFromFile["Cache.Cache.rosePorts"]}; CacheSwitchIORef: TYPE = REF CacheSwitchIORec; CacheSwitchIORec: TYPE = RECORD [ PhA: SwitchTypes.SwitchVal ,PhB: SwitchTypes.SwitchVal ,PData: PACKED ARRAY [0 .. 32) OF SwitchTypes.SwitchVal ,PCmdA: PACKED ARRAY [0 .. 6) OF SwitchTypes.SwitchVal ,PRejectB: SwitchTypes.SwitchVal ,PFaultB: PACKED ARRAY [0 .. 4) OF SwitchTypes.SwitchVal ,MCmdAB: PACKED ARRAY [0 .. 4) OF SwitchTypes.SwitchVal ,MDataAB: PACKED ARRAY [0 .. 32) OF SwitchTypes.SwitchVal ,MParityAB: SwitchTypes.SwitchVal ,MNShared: SwitchTypes.SwitchVal ,MNError: SwitchTypes.SwitchVal ,MRq: SwitchTypes.SwitchVal ,MNewRq: SwitchTypes.SwitchVal ,MGnt: SwitchTypes.SwitchVal ,ResetAB: SwitchTypes.SwitchVal ,DHoldAB: SwitchTypes.SwitchVal ,DShiftAB: SwitchTypes.SwitchVal ,DExecuteAB: SwitchTypes.SwitchVal ,DNSelectAB: SwitchTypes.SwitchVal ,DDataInAB: SwitchTypes.SwitchVal ,DDataOutAB: SwitchTypes.SwitchVal ]; CacheSimpleIORef: TYPE = REF CacheSimpleIORec; CacheSimpleIORec: TYPE = RECORD [ fill0: [0 .. 32767], PhA: BOOLEAN ,fill1: [0 .. 32767], PhB: BOOLEAN ,PData: ARRAY [0..2) OF CARDINAL ,fill3: [0 .. 1023], PCmdA: PBusCommands ,fill4: [0 .. 32767], PRejectB: BOOLEAN ,fill5: [0 .. 4095], PFaultB: PBusFaults ,fill6: [0 .. 4095], MCmdAB: MBusCommands ,MDataAB: ARRAY [0..2) OF CARDINAL ,fill8: [0 .. 32767], MParityAB: BOOLEAN ,fill9: [0 .. 32767], MNShared: BOOLEAN ,fill10: [0 .. 32767], MNError: BOOLEAN ,fill11: [0 .. 32767], MRq: BOOLEAN ,fill12: [0 .. 32767], MNewRq: BOOLEAN ,fill13: [0 .. 32767], MGnt: BOOLEAN ,fill14: [0 .. 32767], ResetAB: BOOLEAN ,fill15: [0 .. 32767], DHoldAB: BOOLEAN ,fill16: [0 .. 32767], DShiftAB: BOOLEAN ,fill17: [0 .. 32767], DExecuteAB: BOOLEAN ,fill18: [0 .. 32767], DNSelectAB: BOOLEAN ,fill19: [0 .. 32767], DDataInAB: BOOLEAN ,fill20: [0 .. 32767], DDataOutAB: BOOLEAN ]; CacheDriveRef: TYPE = REF CacheDriveRec; CacheDriveRec: TYPE = RECORD [driveRecordInitialPadding: DriveTagType, drive: PACKED ARRAY CachePort OF DriveLevel]; CachePort: TYPE = { PhA, PhB, PData, PCmdA, PRejectB, PFaultB, MCmdAB, MDataAB, MParityAB, MNShared, MNError, MRq, MNewRq, MGnt, ResetAB, DHoldAB, DShiftAB, DExecuteAB, DNSelectAB, DDataInAB, DDataOutAB, CachePortTypePad21, CachePortTypePad22, CachePortTypePad23}; CreateCacheIO: PROC [ct: CellType, switch: BOOL] RETURNS [ioAsAny: REF ANY] --IOCreator-- = { args: REF CacheArgs _ NARROW[ct.typeData]; {OPEN args; ioAsAny _ IF switch THEN NEW[CacheSwitchIORec] ELSE NEW[CacheSimpleIORec]; }; }; CreateCacheDrive: PROC [ct: CellType] RETURNS [driveAsAny: REF ANY] --DriveCreator-- = { args: REF CacheArgs _ NARROW[ct.typeData]; {OPEN args; driveAsAny _ NEW[CacheDriveRec]; }; }; CacheStateRef: TYPE = REF CacheStateRec; CacheStateRec: TYPE = RECORD [ 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 ]; InitializeCache: Initializer = { args: REF CacheArgs _ NARROW [cell.type.typeData]; {OPEN args; drive: CacheDriveRef _ NARROW[cell.realCellStuff.newDriveAsAny]; sw: CacheSwitchIORef _ NARROW[cell.realCellStuff.switchIO]; newIO: CacheSimpleIORef _ NARROW[cell.realCellStuff.newIO]; state: CacheStateRef _ NEW[CacheStateRec]; cell.realCellStuff.state _ state; BEGIN OPEN drive, newIO, state; cache _ cacheParm; skipRejects _ skipRejectsParm; END; }; }; CacheEvalSimple: SimpleEval = BEGIN args: REF CacheArgs _ NARROW[cell.type.typeData]; drive: CacheDriveRef _ NARROW[cell.realCellStuff.newDriveAsAny]; sw: CacheSwitchIORef _ NARROW[cell.realCellStuff.switchIO]; newIO: CacheSimpleIORef _ NARROW[cell.realCellStuff.newIO]; state: CacheStateRef _ NARROW[cell.realCellStuff.state]; BEGIN OPEN drive, newIO, args, state; 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; END; END; 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]]; RegisterCells[]; END. ΊCacheImpl.Mesa created by RoseTranslate 3.1.3 of September 5, 1985 12:14:34 pm PDT created from Cache.Rose of September 9, 1985 4:18:38 pm PDT created for McCreight.pa created at September 23, 1985 3:29:37 pm PDT Signal Type decls explicitly requested CEDAR: CacheTester: TYPE = PROC[i: CacheIORef, d: REF CacheDrive, h: CellTestHandle]; cacheTester: CacheTester; RegisterCacheTester: PUBLIC PROC[ct: CacheTester]={ cacheTester _ ct}; Κ ˜Icodešœ™KšœC™CKšœ;™;Kšœ™Kšœ,™,K˜K˜šΟk ˜ KšœœM˜m—K˜šΠbl œœ˜KšœL˜UKšœ˜ —K˜šœœ˜ K˜—K˜šœ™Kšœœ˜)Kšœ œ˜%Kšœœ˜)K˜—K˜šΟn œœ˜Kš˜Kšœ˜—K˜FK˜Kšœ œœ!˜8Kšœ œœ œ˜!šŸœœœœ˜;Kšœ˜š œœœœœ˜AKšœœœ˜3Kšœ˜—˜7Kšœ œ˜K˜WK˜%Kšœœ˜K˜K˜Kšœ œ˜"—Kšœ œ˜&Kšœ˜—K˜šŸ œœœœ˜:Kš œœœœœ˜.Kšœ+œ*˜_Kšœœ˜—K˜KšŸœœœN˜~K˜Kšœœœ˜.šœœœ˜!K˜K˜Kšœœœ œ˜7Kšœœœ œ˜6K˜ Kšœ œœ œ˜8Kšœ œœ œ˜7Kšœ œœ œ˜9K˜!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˜Kšœ ˜K˜Kšœ ˜K˜Kšœ ˜K˜Kšœ ˜K˜Kšœ ˜K˜Kšœ ˜K˜—K˜Kšœœœ˜(Kš œœœ2œœ œ ˜tšœ œ˜K˜τ—K˜šŸ œœœœ œœΟc œ˜]šœœ œ˜*Kšœœ˜ Kš œ œœœœœ˜JK˜—K˜—K˜š Ÿœœœœœ œ˜Xšœœ œ˜*Kšœœ˜ Kšœ œ˜ K˜—K˜—K˜Kšœœœ˜(šœœœ˜J˜Jšœ œœ )˜@J˜J˜"Jšœ œ˜Jšœ œœ˜Jšœœ˜J˜J˜4J˜,Jšœ&œ˜2J˜K˜—K˜˜ šœœ œ˜2Kšœœ˜ Kšœœ#˜@Kšœœ˜;Kšœœ˜;Kšœœ˜*K˜!šœœ˜J˜J˜J˜J˜Kšœ˜—K˜—K˜—K˜˜Kš˜Kšœœ œ˜1Kšœœ#˜@Kšœœ˜;Kšœœ˜;šœœ˜8šœœ˜%J˜šœ˜ Jš˜J˜šœœ ˜Jš˜š œœœœ œ ˜JJ˜,—Jšœ œ˜Jšœ˜J˜—šœ˜JšœœI˜^—J˜Jšœ œ˜J˜Jšœ˜J˜—šœ˜ Jš˜J˜šœ ˜Jš˜šœ ˜Jš˜J˜/J˜,J˜J˜ J˜!Jšœœ˜Jš˜—Jšœ˜šœ˜Jš˜Jšœœ˜šœ˜˜Jš˜J˜J˜uJšœ˜—˜Jš˜J˜J˜Jšœ˜—˜-Jš˜Jšœœ2  ˜PJ˜Jšœ˜—Jšœ˜J˜—šœœœ˜ Jšœœ˜J˜