Cache2Impl.mesa
Copyright © 1986 by Xerox Corporation. All rights reserved.
McCreight, April 10, 1986 11:40:24 am PST
Cache2Impl:
CEDAR
PROGRAM
IMPORTS CacheOps, Commander, CoreClasses, CoreCreate, CoreOps, CoreProperties, DragonRosemary, Ports, Random, Rosemary
EXPORTS Cache2
= BEGIN OPEN Cache2, Core;
randomSeed: INT ← -1;
CacheName: ROPE = Rosemary.Register[roseClassName: "Cache", init: CacheInit, evalSimple: CacheSimple];
PortData: TYPE = RECORD [ name: Core.ROPE, width: NAT ← 1 ];
pITypes:
ARRAY
PI
OF PortData ← [
PhA: ["PhA"],
PhB: ["PhB"],
PData: ["PData", 32],
PCmdA: ["PCmdA", 8],
PRejectB: ["PRejectB"],
PFaultB: ["PFaultB", 5],
ResetAB: ["ResetAB"]
];
CacheParm:
TYPE =
RECORD [
vm: CacheOps.VirtualMemory,
nLines: NAT,
skipRejects: BOOL ← FALSE
];
CacheInit:
PROC [ cellType: Core.CellType, p: Ports.Port ]
RETURNS [ stateAny:
REF
ANY ←
NIL ]
-- Rosemary.InitProc -- =
BEGIN
cp: REF CacheParm = NARROW[CoreProperties.GetCellTypeProp[cellType, $ClusterInfo]];
stateAny ←
NEW[CacheState ← [
cache: CacheOps.NewCache[cp.vm, cp.nLines],
skipRejects: cp.skipRejects
]];
END;
CacheSimple:
PROC [ p: Ports.Port, stateAny:
REF
ANY ]
-- Rosemary.EvalProc -- =
BEGIN
state: REF CacheState = NARROW[stateAny];
PhA: BOOL = p[PI[PhA].ORD].b;
PhB: BOOL = p[PI[PhB].ORD].b;
IF PhA
THEN
BEGIN
IF
NOT state.phALast
THEN
BEGIN
IF state.cmdType=store
AND state.rejectCycles=0
AND
NOT (state.pageFault
OR state.writeFault)
THEN
CacheOps.Write[state.cache, state.address, state.storeDataBA];
state.phALast ← TRUE;
END;
IF state.rejectCycles=0 THEN state.address ← p[PI[PData].ORD].lc;
state.cmdAB ← VAL[p[PI[PCmdA].ORD].c];
END;
IF PhB
THEN
BEGIN
IF state.phALast
THEN
BEGIN
IF p[
PI[ResetAB].
ORD].b
THEN
BEGIN
state.randomStream ← Random.Create[seed: randomSeed];
state.rejectCycles ← state.randomStream.ChooseInt[1, 5];
state.cmdType ← reset;
state.cycleNo ← 0;
state.cache ← CacheOps.NewCache[state.cache];
state.pageFault ← state.writeFault ← FALSE;
END
ELSE state.cycleNo ← state.cycleNo+1;
IF state.rejectCycles=0
THEN
BEGIN
state.pageFault ← state.writeFault ← FALSE;
SELECT state.cmdAB
FROM
Fetch, FetchHold =>
BEGIN
state.cmdType ← fetch;
[data: state.fetchData, rejectCycles: state.rejectCycles, pageFault: state.pageFault] ← CacheOps.Access[state.cache, state.address, read, state.cycleNo];
END;
Store, StoreHold =>
BEGIN
state.cmdType ← store;
[rejectCycles: state.rejectCycles, pageFault: state.pageFault, writeProtect: state.writeFault] ← CacheOps.Access[state.cache, state.address, write, state.cycleNo];
END;
IOFetch, IOStore, IOFetchHold, IOStoreHold =>
BEGIN
DragonRosemary.Assert[ FALSE, "Cache doesn't yet implement IO operations" ]; -- for now
state.cmdType ← noOp;
END;
ENDCASE => state.cmdType ← noOp;
state.rejectCycles ← (
SELECT
TRUE
FROM
state.skipRejects => INT[0],
state.rejectCycles>0 => state.rejectCycles+state.randomStream.ChooseInt[0, 1],
ENDCASE => state.rejectCycles);
IF state.pageFault OR state.writeFault THEN state.rejectCycles ← MAX[1, state.rejectCycles];
state.firstBOfCmdBA ← TRUE;
END
ELSE
BEGIN -- rejected on previous PhB
DragonRosemary.Assert[ (state.cmdAB = NoOp) ];
state.rejectCycles ← state.rejectCycles-1;
state.firstBOfCmdBA ← FALSE;
END;
state.phALast ← FALSE;
END;
SELECT
TRUE
FROM
state.cmdType=store
AND state.firstBOfCmdBA =>
state.storeDataBA ← p[PI[PData].ORD].lc;
state.cmdType=fetch
AND state.rejectCycles=0
AND
NOT state.pageFault =>
p[PI[PData].ORD].lc ← state.fetchData;
ENDCASE => NULL; -- neither write nor read PData
END;
p[
PI[PData].
ORD].d ←
IF (PhB AND state.cmdType=fetch AND state.rejectCycles=0 AND NOT state.pageFault) THEN drive ELSE none;
p[
PI[PFaultB].
ORD].c ← Dragon.PBusFaults[(
SELECT
TRUE
FROM
NOT PhB => none,
state.rejectCycles=1 AND state.pageFault => page,
state.rejectCycles=1 AND state.writeFault => write,
ENDCASE => none)].ORD;
p[PI[PRejectB].ORD].b ← PhB AND state.rejectCycles>0;
p[
PI[PFaultB].
ORD].d ← p[
PI[PRejectB].
ORD].d ←
IF PhA OR (PhB AND state.cmdType#noOp) THEN drive ELSE none;
END;
Cache:
PUBLIC
PROC [ vm: CacheOps.VirtualMemory, nLines:
NAT ← CacheOps.StdLinesPerCache, skipRejects:
BOOL ←
FALSE ]
RETURNS [ ct: CellType ] =
BEGIN
PIGet:
PROC [ wireId:
PI ]
RETURNS [ w: Core.Wire ] = {
w ← ct.public[wireId.ORD];
};
wireList: LIST OF CoreCreate.WR ← NIL;
FOR wireId:
PI
DECREASING
IN
PI
DO
wr: CoreCreate.
WR ← (
SELECT pITypes[wireId].width
FROM
1 => pITypes[wireId].name,
ENDCASE => CoreCreate.Seq[name: pITypes[wireId].name, size: pITypes[wireId].width]
);
wireList ← CONS[wr, wireList];
ENDLOOP;
ct ← CoreOps.CreateCellType[
class: CoreClasses.unspecifiedCellClass,
public: CoreCreate.WireList[wireList],
props: CoreProperties.Props[[$ClusterInfo,
NEW[CacheParm ← [
vm: vm,
nLines: nLines,
skipRejects: skipRejects
]]]],
name: "Cache"
];
[] ← Rosemary.BindCellType[cellType: ct, roseClassName: CacheName];
FOR wireId:
PI
IN
PI
DO
[] ← Ports.InitPort[wire: ct.public[wireId.
ORD],
initType: (
SELECT pITypes[wireId].width
FROM
1 => b,
<=16 => c,
<=32 => lc,
ENDCASE => ERROR)
];
ENDLOOP;
END;
Cache2CmdProc:
PROC [cmd: Commander.Handle]
RETURNS [result:
REF ←
NIL, msg: Core.
ROPE ←
NIL]
-- Commander.CommandProc -- =
{NULL};
Commander.Register["Cache2", Cache2CmdProc];
END.