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
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;
Signal Type decls
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.STREAMIO.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: BOOLFALSE, -- hack to improve simulation performance
cache: CacheOps.Cache,
randomStream: Random.RandomStream,
cycleNo: INT ← 0,
skipRejects: BOOLFALSE,
rejectCycles: NAT ← 0,
cmdAB: PBusCommands ← NoOp,
address, fetchData, storeDataBA: Dragon.HexWord ← 0,
cmdType: {noOp, reset, fetch, store} ← noOp,
pageFault, writeFault, firstBOfCmdBA: BOOLFALSE
];
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;
explicitly requested CEDAR:
CacheTester: TYPE = PROC[i: CacheIORef, d: REF CacheDrive, h: CellTestHandle];
cacheTester: CacheTester;
RegisterCacheTester: PUBLIC PROC[ct: CacheTester]={
cacheTester ← ct};
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.