Types and Constants
wdsPerBlk: CARDINAL = 8;
blksPerSLn: CARDINAL = 4;
sLnsPerBLn: CARDINAL = 8;
blksPerBLn: CARDINAL = blksPerSLn*sLnsPerBLn;
sLnsPerSCache: CARDINAL = 64;
SCPerBC: CARDINAL = 8;
bLnsPerBC: CARDINAL = sLnsPerSCache * SCPerBC;
AddrPageIdx: TYPE = [0..4194304); -- 22 bits
PageWdIdx: TYPE = [0..1024); -- 10 bits
BCLineIdx: TYPE = [0..bLnsPerBC);
BlkWdIdx: TYPE = [0..wdsPerBlk);
DeviceID: TYPE = [0..1024);
DynaBusCmd:
TYPE = {
RBRqst, RBRply,
WSRqst, WSRply,
CWSRqst, CWSRply,
WBRqst, WBRply, -- WBRply not used
FBRqst, FBRply,
IORRqst, IORRply,
IOWRqst, IOWRply,
BIORqst, BIORply,
MapRqst, MapRply,
DMRqst, DMRply};
Word: TYPE = LONG CARDINAL;
AddressRec: TYPE = RECORD[page: AddrPageIdx𡤀, wd: PageWdIdx𡤀];
Data: TYPE = REF DataAry;
DataAry: TYPE = ARRAY WdIndex OF Word ← ALL[0];
BlockAry:
TYPE =
RECORD[
victim: BlkIndex ← 0,
victimLock: BOOL ← FALSE,
blks: ARRAY BlkIndex OF BlockRec];
BlockRec:
TYPE =
RECORD[
owner: BOOL ← FALSE, -- Owner
shared: BOOL ← FALSE, -- Shared
rpValid: BOOL ← FALSE, -- Real page valid
vpValid: BOOL ← FALSE, -- Virtual page valid
rAddr: AddressRec ← [ ], -- Real address
vAddr: AddressRec ← [ ], -- Virtual address
data: Data ← NIL ];
SnoopRec:
TYPE =
RECORD[
enabled: BOOL ← FALSE, -- Enable snooping of the outstanding address
shared: BOOL ← FALSE, -- Shared Accumulator
rplyStale: BOOL ← FALSE, -- RplyStale
addr: AddressRec ← [ ] ]; -- Outstanding address
PacketRec:
TYPE =
RECORD[
valid: BOOL ← FALSE,
head: HeaderRec ← [],
data: Data ← NIL ];
HeaderRec:
TYPE =
RECORD[
id: DeviceID ← 0,
cmd: DynaBusCmd ← RBRqst,
shared: BOOL ← FALSE,
rAddr: AddressRec ← [ ] ];
FifoRec:
TYPE =
RECORD[
count: INT ← 0,
ary: SEQUENCE size: CARDINAL OF PacketRec ];
CacheRec:
TYPE =
RECORD[
id: DeviceID ← 0, -- this caches id
p: PacketRec ← [], -- received packet
snoop: SnoopRec ← [], -- state of the snooper
array: CacheAry ← [], -- main cache arrary
fifoHi5: REF FifoRec ← NEW[FifoRec[4]], -- Hi priority port for 5 cycle requests
fifoLo2: REF FifoRec ← NEW[FifoRec[1]], -- Lo priority port for 2 cycle requests
tipFB: BOOL ← FALSE, -- a flush block request is outstanding
tipNFB: BOOL ← FALSE, -- non flush block request is outstanding
pAddr: AddressRec ← [ ], -- processor side address
pWord: Word ← 0, -- processor side data
];
c: Cache ← NewCache[];
Cache processor side
PFetch:
PROC[c: Cache] = {
aMatch: BOOL;
blk: BlkIndex;
[aMatch, blk] ← VirtualMatch[c];
IF ~aMatch
THEN {
HandleMiss[c];
[aMatch, blk] ← VirtualMatch[c]};
c.pWord ← ExtractWd[ c.array[blk].data[c.pAddr MOD wdsPerBlk] ] };
PStore:
PROC[c: Cache] = {
aMatch: BOOL;
blk: BlkIndex;
[aMatch, blk] ← VirtualMatch[c];
IF ~aMatch
THEN {
HandleMiss[];
[aMatch, blk] ← VirtualMatch[c];
IF ~array[blk].shared
THEN {
InsertWd[array[blk].data, vAddr, c.pWord];
array[blk].owner ← T}
ELSE {
EnQOut[fifo: bufLo2, cmd: WSRqst, shared: F, addr: rAddr, wd: c.pWord];
tipNonFB ← T; WHILE tipNonFB DO NoOp[] ENDLOOP}}};
HandleMiss:
PROC[c: Cache] = {
aMatch: BOOL;
blk: BlkIndex;
rAddr: AddressRec;
WHILE tipFB DO NoOp[] ENDLOOP; -- tipFB must be cleared on Reset
[aMatch, blk] ← VirtualPageMatch[c];
Multiple Matches Possible
IF aMatch
THEN rAddr ← array[blk].rAddr
ELSE {
EnQOut[fifo: bufLo2, cmd: MapRqst, shared: F, addr: vAddr];
tipNonFB ← T; WHILE tipNonFB DO NoOp[] ENDLOOP};
Somthing funny to make rAddr from vAddr and rPage
FreezeVictim[];
victimAddr ← array[array.victim].rAddr;
IF array[array.victim].owner
THEN {
InitSnooper[snoop, array[array.victim].raddr]; -- do this before owner can change
EnQOut[fifo: fifoHi5, cmd: FBRqst, addr: rAddr, data: array[array.victim].data];
tipFB ← 1}; -- Snooper must abort FB if stale data (WSRply, CWSRply, WB)
EnQOut[fifo: bufLo2, cmd: RBRqst, shared: F, addr: rAddr, data: victimAddr];
tipNonFB ← T;
WHILE tipNonFB
DO NoOp[]
ENDLOOP};
Note that we don't wait for the FBRply. Its checked for before the next processor reference!