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