Implemented BRAM versions of stride, target, markov prefetchers

This commit is contained in:
Karlis Susters
2023-02-06 20:51:48 +00:00
parent 31ae938e78
commit 9d027a3f4b
2 changed files with 641 additions and 0 deletions

View File

@@ -301,6 +301,7 @@ provisos(
streams[idx].rangeEnd <= newRangeEnd;
end
else if (hitMiss == MISS) begin
//A miss in L1 is not necessarily a miss in L2, so this might create a window for lines already in L2
$display("%t Prefetcher report MISS %h, allocating new window, idx %h", $time, addr, shiftReg[3]);
streams[shiftReg[3]] <=
StreamEntry {nextToAsk: getLineAddr(addr) + 1,
@@ -395,6 +396,153 @@ module mkTargetTable(TargetTable#(narrowTableSize, wideTableSize)) provisos
endmethod
endmodule
interface TargetTableBRAM#(numeric type narrowTableSize, numeric type wideTableSize);
method Action writeReq(LineAddr prevAddr, LineAddr currAddr);
method Action readReq(LineAddr addr);
method ActionValue#(Maybe#(LineAddr)) readRespAndClear();
endinterface
module mkTargetTableBRAM(TargetTableBRAM#(narrowTableSize, wideTableSize)) provisos
(
NumAlias#(narrowTableIdxBits, TLog#(narrowTableSize)),
NumAlias#(wideTableIdxBits, TLog#(wideTableSize)),
NumAlias#(narrowTableTagBits, TSub#(32, narrowTableIdxBits)),
NumAlias#(wideTableTagBits, TSub#(32, wideTableIdxBits)),
NumAlias#(narrowDistanceBits, 10),
NumAlias#(narrowMaxDistanceAbs, TExp#(TSub#(narrowDistanceBits, 1))),
Alias#(narrowTargetEntryT, NarrowTargetEntry#(narrowTableTagBits, narrowDistanceBits)),
Alias#(wideTargetEntryT, WideTargetEntry#(wideTableTagBits)),
Add#(a__, TLog#(narrowTableSize), 32),
Add#(b__, TLog#(narrowTableSize), 58),
Add#(c__, TLog#(wideTableSize), 32),
Add#(d__, TLog#(wideTableSize), 58)
);
RWBramCore#(Bit#(narrowTableIdxBits), Maybe#(narrowTargetEntryT)) narrowTable <- mkRWBramCoreForwarded;
RWBramCore#(Bit#(wideTableIdxBits), Maybe#(wideTargetEntryT)) wideTable <- mkRWBramCoreForwarded;
Reg#(LineAddr) readReqLineAddr <- mkReg(?);
method Action writeReq(LineAddr prevAddr, LineAddr currAddr);
let distance = currAddr - prevAddr;
Bit#(32) prevAddrHash = hash(prevAddr);
if (abs(distance) < fromInteger(valueOf(narrowMaxDistanceAbs))) begin
//Store in narrow table
narrowTargetEntryT entry;
entry.tag = prevAddrHash[31:valueOf(narrowTableIdxBits)];
entry.distance = truncate(distance);
Bit#(narrowTableIdxBits) idx = truncate(prevAddrHash);
narrowTable.wrReq(idx, tagged Valid entry);
end
else begin
//Store in wide table
wideTargetEntryT entry;
entry.tag = prevAddrHash[31:valueOf(wideTableIdxBits)];
entry.target = currAddr;
Bit#(wideTableIdxBits) idx = truncate(prevAddrHash);
wideTable.wrReq(idx, tagged Valid entry);
end
endmethod
method Action readReq(LineAddr addr);
Bit#(narrowTableIdxBits) narrowIdx = truncate(addr);
narrowTable.rdReq(narrowIdx);
Bit#(wideTableIdxBits) wideIdx = truncate(addr);
wideTable.rdReq(wideIdx);
readReqLineAddr <= addr;
endmethod
method ActionValue#(Maybe#(LineAddr)) readRespAndClear();
// Returns the read response and if a table had a hit,
// sends a write request to clear the entry in that table
narrowTable.deqRdResp;
wideTable.deqRdResp;
let addr = readReqLineAddr;
Bit#(narrowTableIdxBits) narrowIdx = truncate(addr);
Bit#(wideTableIdxBits) wideIdx = truncate(addr);
if (narrowTable.rdResp matches tagged Valid .entry
&&& entry.tag == addr[31:valueOf(narrowTableIdxBits)]) begin
narrowTable.wrReq(narrowIdx, Invalid);
$display("%t found narrow table entry %h", $time, addr + signExtend(pack(entry.distance)));
return Valid(addr + signExtend(pack(entry.distance)));
end
else if (wideTable.rdResp matches tagged Valid .entry
&&& entry.tag == addr[31:valueOf(wideTableIdxBits)]) begin
wideTable.wrReq(wideIdx, Invalid);
$display("%t found wide table entry %h", $time, entry.target);
return Valid(entry.target);
end
else begin
return Invalid;
end
endmethod
endmodule
module mkBRAMSingleWindowTargetPrefetcher(Prefetcher) provisos
();
Integer cacheLinesInRange = 2;
Reg#(LineAddr) rangeEnd <- mkReg(0); //Points to one CLine after end of range
Reg#(LineAddr) nextToAsk <- mkReg(0);
Reg#(LineAddr) lastChildRequest <- mkReg(0);
TargetTableBRAM#(64, 8) targetTable <- mkTargetTableBRAM;
FIFOF#(LineAddr) targetTableReadResp <- mkBypassFIFOF;
rule sendReadReq;
let lastAsked = nextToAsk-1;
targetTable.readReq(lastAsked);
endrule
rule getReadResp;
let res <- targetTable.readRespAndClear();
if (res matches tagged Valid .cline) begin
//Reset table entry, so on further calls we prefetch the next successive clines
//If we actually take the jump, the table entry will be restored
targetTableReadResp.enq(cline);
end
endrule
method Action reportAccess(Addr addr, HitOrMiss hitMiss);
let cl = getLineAddr(addr);
if (hitMiss == HIT &&
rangeEnd - fromInteger(cacheLinesInRange) - 1 < cl &&
cl < rangeEnd) begin
let nextEnd = cl + fromInteger(cacheLinesInRange) + 1;
$display("%t Prefetcher report HIT %h, moving window end to %h", $time, addr, Addr'{nextEnd, '0});
rangeEnd <= nextEnd;
end
else if (hitMiss == MISS) begin
$display("%t Prefetcher report MISS %h", $time, addr);
//Reset window
nextToAsk <= cl + 1;
rangeEnd <= cl + fromInteger(cacheLinesInRange) + 1;
end
if (cl != lastChildRequest + 1 && cl != lastChildRequest && cl != lastChildRequest - 1) begin
$display("%t Prefetcher add target entry from addr %h to addr %h", $time, Addr'{lastChildRequest, '0}, addr);
targetTable.writeReq(lastChildRequest, cl);
end
lastChildRequest <= cl;
endmethod
method ActionValue#(Addr) getNextPrefetchAddr if (targetTableReadResp.notEmpty || nextToAsk != rangeEnd);
Addr retAddr;
if (targetTableReadResp.notEmpty) begin
//If have valid table entry for some of the last requested clines,
// prefetch the stored target first
retAddr = {targetTableReadResp.first, '0};
targetTableReadResp.deq();
$display("%t Prefetcher getNextPrefetchAddr requesting target entry %h", $time, retAddr);
end
else begin
//If no table entry, prefetch further in window
nextToAsk <= nextToAsk + 1;
retAddr = {nextToAsk, '0};
$display("%t Prefetcher getNextPrefetchAddr requesting next-line %h", $time, retAddr);
end
return retAddr;
endmethod
endmodule
module mkSingleWindowTargetPrefetcher(Prefetcher) provisos
();
Integer cacheLinesInRange = 2;
@@ -448,6 +596,138 @@ module mkSingleWindowTargetPrefetcher(Prefetcher) provisos
endmethod
endmodule
module mkBRAMMultiWindowTargetPrefetcher(Prefetcher)
provisos(
NumAlias#(numWindows, 4),
Alias#(windowIdxT, Bit#(TLog#(numWindows)))
);
Integer cacheLinesInRange = 2;
Vector#(numWindows, Reg#(StreamEntry)) streams
<- replicateM(mkReg(StreamEntry {rangeEnd: '0, nextToAsk: '0}));
Vector#(numWindows, Reg#(windowIdxT)) shiftReg <- genWithM(compose(mkReg, fromInteger));
Reg#(LineAddr) lastChildRequest <- mkReg(0);
TargetTableBRAM#(64, 8) targetTable <- mkTargetTableBRAM;
FIFOF#(LineAddr) targetTableReadResp <- mkBypassFIFOF;
rule sendReadReq;
let lastAsked = streams[shiftReg[0]].nextToAsk-1;
targetTable.readReq(lastAsked);
endrule
rule getReadResp;
let res <- targetTable.readRespAndClear();
if (res matches tagged Valid .cline) begin
//Reset table entry, so on further calls we prefetch the next successive clines
//If we actually take the jump, the table entry will be restored
targetTableReadResp.enq(cline);
end
endrule
function Action moveWindowToFront(windowIdxT window) =
action
if (shiftReg[0] == window) begin
end
else if (shiftReg[1] == window) begin
shiftReg[0] <= window;
shiftReg[1] <= shiftReg[0];
end
else if (shiftReg[2] == window) begin
shiftReg[0] <= window;
shiftReg[1] <= shiftReg[0];
shiftReg[2] <= shiftReg[1];
end
else if (shiftReg[3] == window) begin
shiftReg[0] <= window;
shiftReg[1] <= shiftReg[0];
shiftReg[2] <= shiftReg[1];
shiftReg[3] <= shiftReg[2];
end
endaction;
function ActionValue#(Maybe#(windowIdxT)) getMatchingWindow(LineAddr cl) =
actionvalue
//Finds the first window that contains cache line
function Bool pred(StreamEntry se);
//TODO < gives 100 cycles less??????
return (se.rangeEnd - fromInteger(cacheLinesInRange) - 1 <= cl
&& cl < se.rangeEnd);
endfunction
//Find first window that contains cache line cl
if (findIndex(pred, readVReg(streams)) matches tagged Valid .idx) begin
return Valid(pack(idx));
end
else begin
return Invalid;
end
endactionvalue;
// test: allocate new window on hit too (mostly for target prefetching)
method Action reportAccess(Addr addr, HitOrMiss hitMiss);
//Check if any stream line matches request
//If so, advance that stream line and advance LRU shift reg
//Otherwise if miss, allocate new stream line, and shift LRU reg completely,
let cl = getLineAddr(addr);
// Update window prefetcher
let idxMaybe <- getMatchingWindow(cl);
if (idxMaybe matches tagged Valid .idx) begin
moveWindowToFront(pack(idx)); //Update window as just used
let newRangeEnd = getLineAddr(addr) + fromInteger(cacheLinesInRange) + 1;
if (hitMiss == HIT) begin
$display("%t Prefetcher report HIT %h, moving window end to %h for window idx %h",
$time, addr, Addr'{newRangeEnd, '0}, idx);
streams[idx].rangeEnd <= newRangeEnd;
end
else if (hitMiss == MISS) begin
//Also reset nextToAsk on miss
$display("%t Prefetcher report MISS %h, moving window end to %h for window idx %h",
$time, addr, Addr'{newRangeEnd, '0}, idx);
streams[idx] <=
StreamEntry {nextToAsk: getLineAddr(addr) + 1,
rangeEnd: newRangeEnd};
end
end
else if (hitMiss == MISS) begin
$display("%t Prefetcher report MISS %h, allocating new window, idx %h", $time, addr, shiftReg[3]);
streams[shiftReg[3]] <=
StreamEntry {nextToAsk: getLineAddr(addr) + 1,
rangeEnd: getLineAddr(addr) + fromInteger(cacheLinesInRange) + 1};
shiftReg[0] <= shiftReg[3];
shiftReg[1] <= shiftReg[0];
shiftReg[2] <= shiftReg[1];
shiftReg[3] <= shiftReg[2];
end
// Update target prefetcher
if (cl != lastChildRequest + 1 && cl != lastChildRequest && cl != lastChildRequest - 1) begin
$display("%t Prefetcher add target entry from addr %h to addr %h", $time, Addr'{lastChildRequest, '0}, addr);
targetTable.writeReq(lastChildRequest, cl);
end
lastChildRequest <= cl;
endmethod
method ActionValue#(Addr) getNextPrefetchAddr
if (targetTableReadResp.notEmpty || streams[shiftReg[0]].nextToAsk != streams[shiftReg[0]].rangeEnd);
Addr retAddr;
let lastAsked = streams[shiftReg[0]].nextToAsk-1;
if (targetTableReadResp.notEmpty) begin
//If have valid table entry for some of the last requested clines,
// prefetch the stored target first
retAddr = {targetTableReadResp.first, '0};
targetTableReadResp.deq();
$display("%t Prefetcher getNextPrefetchAddr requesting target entry %h", $time, retAddr);
end
else begin
streams[shiftReg[0]].nextToAsk <= streams[shiftReg[0]].nextToAsk + 1;
retAddr = Addr'{streams[shiftReg[0]].nextToAsk, '0}; //extend cache line address to regular address
$display("%t Prefetcher getNextPrefetchAddr requesting %h from window idx %h", $time, retAddr, shiftReg[0]);
end
return retAddr;
endmethod
endmodule
module mkMultiWindowTargetPrefetcher(Prefetcher)
provisos(
NumAlias#(numWindows, 4),
@@ -459,6 +739,7 @@ provisos(
Vector#(numWindows, Reg#(windowIdxT)) shiftReg <- genWithM(compose(mkReg, fromInteger));
Reg#(LineAddr) lastChildRequest <- mkReg(0);
TargetTable#(64, 8) targetTable <- mkTargetTable;
function Action moveWindowToFront(windowIdxT window) =
action
if (shiftReg[0] == window) begin
@@ -564,6 +845,66 @@ provisos(
endmodule
module mkBRAMMarkovPrefetcher(Prefetcher) provisos
(
NumAlias#(maxChainLength, 2),
Alias#(chainLengthT, Bit#(TLog#(TAdd#(maxChainLength,1))))
);
Reg#(LineAddr) lastLastChildRequest <- mkReg(0);
Reg#(LineAddr) lastChildRequest <- mkReg(0);
TargetTableBRAM#(64, 8) targetTable <- mkTargetTableBRAM;
FIFOF#(LineAddr) targetTableReadResp <- mkBypassFIFOF;
// Stores how many prefetches we can still do in the current chain
Reg#(chainLengthT) chainNumberToPrefetch <- mkReg(0);
Reg#(LineAddr) chainNextToLookup <- mkReg(?);
rule sendReadReq (chainNumberToPrefetch != 0);
targetTable.readReq(chainNextToLookup);
endrule
(* descending_urgency = "getReadResp, sendReadReq" *)
(* execution_order = "getReadResp, sendReadReq" *)
rule getReadResp;
let res <- targetTable.readRespAndClear();
if (res matches tagged Valid .cline) begin
targetTableReadResp.enq(cline);
chainNextToLookup <= cline;
chainNumberToPrefetch <= chainNumberToPrefetch - 1;
end
else begin
chainNumberToPrefetch <= 0;
end
endrule
method ActionValue#(Addr) getNextPrefetchAddr;
targetTableReadResp.deq();
let cline = targetTableReadResp.first;
Addr retAddr = {cline, '0};
$display("%t Prefetcher getNextPrefetchAddr requesting chain entry %h", $time, retAddr);
return retAddr;
endmethod
method Action reportAccess(Addr addr, HitOrMiss hitMiss);
let cl = getLineAddr(addr);
if (cl != lastChildRequest + 1 && cl != lastChildRequest && cl != lastChildRequest - 1) begin
$display("%t Prefetcher report %s add target entry from addr %h to addr %h",
$time, hitMiss == HIT ? "HIT" : "MISS", Addr'{lastChildRequest, '0}, addr);
targetTable.writeReq(lastChildRequest, cl);
end
lastChildRequest <= cl;
lastLastChildRequest <= lastChildRequest;
if (lastLastChildRequest != cl) begin
//Don't start markov chain if its very recent
//$display("%t Prefetcher start new chain with %h", $time, addr);
chainNextToLookup <= cl;
chainNumberToPrefetch <= fromInteger(valueOf(maxChainLength));
end
endmethod
endmodule
module mkMarkovPrefetcher(Prefetcher) provisos
(
NumAlias#(maxChainLength, 2),

View File

@@ -43,6 +43,62 @@ module mkTargetTableTest(Empty);
);
endmodule
module mkTargetTableBRAMTest(Empty);
TargetTableBRAM#(64, 16) t <- mkTargetTableBRAM;
mkAutoFSM(
seq
// ----- Send misses and stuff to one window -----
action
t.writeReq('h8000, 'h800a); // goes in short table
endaction
action
t.writeReq('h8000, 'h80008000); // goes in long table
endaction
action
t.readReq('h8000); // comes from short table
endaction
action
let x <- t.readRespAndClear(); // comes from short table
doAssert(x == Valid('h800a), "test fail!");
endaction
action
t.readReq('h8000); // comes from long table
endaction
action
let x <- t.readRespAndClear(); // comes from long table
doAssert(x == Valid('h80008000), "test fail!");
endaction
action
t.writeReq('h80000000, 'h21230000); // goes in long table
endaction
action
t.readReq('h80000000); // comes from long table
endaction
action
let x <- t.readRespAndClear(); // comes from long table
doAssert(x == Valid('h21230000), "test fail!");
endaction
action
t.writeReq('h7000, 'h6fde); // goes in short table backwards
endaction
action
t.readReq('h7000); // get from short table
endaction
action
let x <- t.readRespAndClear(); // get from short table
doAssert(x == Valid('h6fde), "test fail!");
endaction
action
t.readReq('h7000); // get from short table
endaction
action
let x <- t.readRespAndClear(); // get from short table
doAssert(x == Invalid, "test fail!"); //entry was removed!
endaction
endseq
);
endmodule
module mkMultiWindowPrefetcherTest(Empty);
//let p <- mkMultipleWindowPrefetcher;
//TODO pass in value of cachelinesinrange
@@ -271,6 +327,130 @@ module mkMultiWindowTargetPrefetcherTest(Empty);
);
endmodule
module mkBRAMMultiWindowTargetPrefetcherTest(Empty);
let p <- mkBRAMMultiWindowTargetPrefetcher;
mkAutoFSM(
seq
// ----- Send misses and stuff to one window -----
action
p.reportAccess('h80000040, MISS);
endaction
action
let x <- p.getNextPrefetchAddr;
doAssert(x == 'h80000080, "test fail!");
endaction
action
let x <- p.getNextPrefetchAddr;
doAssert(x == 'h800000c0, "test fail!");
endaction
action
p.reportAccess('h800000c0, HIT); //Report hit inside window
endaction
action
let x <- p.getNextPrefetchAddr;
doAssert(x == 'h80000100, "test fail!");
endaction
action
p.reportAccess('h80004000, HIT); //Report hit outside window
endaction
action
let x <- p.getNextPrefetchAddr; //Previous window still recommended
doAssert(x == 'h80000140, "test fail!");
endaction
action
p.reportAccess('h80000140, MISS); //Report miss inside window
endaction
action
let x <- p.getNextPrefetchAddr; //Previous window still recommended
doAssert(x == 'h80000180, "test fail!");
endaction
// ----- Allocate other windows -----
action
p.reportAccess('h70000000, MISS); //Report miss outside window
endaction
action
let x <- p.getNextPrefetchAddr; //new window recommended
doAssert(x == 'h70000040, "test fail!");
endaction
action
p.reportAccess('h90000000, MISS); //Report miss outside window
endaction
action
let x <- p.getNextPrefetchAddr; //new window recommended
doAssert(x == 'h90000040, "test fail!");
endaction
action
p.reportAccess('h60000000, MISS); //Report miss outside window
endaction
action
let x <- p.getNextPrefetchAddr; //new window recommended
doAssert(x == 'h60000040, "test fail!");
endaction
action
p.reportAccess('h80000180, HIT); //Report hit inside oldest window
endaction
action
let x <- p.getNextPrefetchAddr; //oldest window recommended
doAssert(x == 'h800001c0, "test fail!");
endaction
// ----- Trigger window deletion -----
action
p.reportAccess('h50000000, MISS); //Report miss outside window,
//discard window with 'h70..
endaction
action
let x <- p.getNextPrefetchAddr; //new window recommended
doAssert(x == 'h50000040, "test fail!");
endaction
action
p.reportAccess('h70000040, HIT); //Report hit inside now deleted window
endaction
action
let x <- p.getNextPrefetchAddr; //most recent window still recommended
doAssert(x == 'h50000080, "test fail!");
endaction
// ----- Reorder some more windows around
action
p.reportAccess('h800001c0, MISS); //Report hit inside now deleted window
endaction
action
let x <- p.getNextPrefetchAddr;
doAssert(x == 'h80000200, "test fail!");
endaction
// ------ Test saving and prefetching target clines
action
p.reportAccess('h81000000, MISS); //Report miss somewhere far away
endaction
action
let x <- p.getNextPrefetchAddr; //New window allocated and recommended
doAssert(x == 'h81000040, "test fail!");
endaction
action
p.reportAccess('h80000180, MISS); //Report miss back home
endaction
action
let x <- p.getNextPrefetchAddr;
doAssert(x == 'h800001c0, "test fail!");
endaction
action
let x <- p.getNextPrefetchAddr; //target address recommended
doAssert(x == 'h50000000, "test fail!");
endaction
action
let x <- p.getNextPrefetchAddr; //target address recommended
doAssert(x == 'h81000000, "test fail!");
endaction
action
let x <- p.getNextPrefetchAddr;
doAssert(x == 'h80000200, "test fail!"); // window addresss recommended
endaction
endseq
);
endmodule
module mkSingleWindowTargetPrefetcherTest(Empty);
//let p <- mkMultipleWindowPrefetcher;
//TODO pass in value of cachelinesinrange
@@ -336,6 +516,79 @@ module mkSingleWindowTargetPrefetcherTest(Empty);
);
endmodule
module mkBRAMSingleWindowTargetPrefetcherTest(Empty);
let p <- mkBRAMSingleWindowTargetPrefetcher;
mkAutoFSM(
seq
// ----- Send misses and stuff to one window -----
action
p.reportAccess('h80000040, MISS);
endaction
action
let x <- p.getNextPrefetchAddr;
doAssert(x == 'h80000080, "test fail!");
endaction
action
let x <- p.getNextPrefetchAddr;
doAssert(x == 'h800000c0, "test fail!");
endaction
action
p.reportAccess('h800000c0, HIT); //Report hit inside window
endaction
action
let x <- p.getNextPrefetchAddr;
doAssert(x == 'h80000100, "test fail!");
endaction
action
p.reportAccess('h80004000, HIT); //Report hit outside window
endaction
action
let x <- p.getNextPrefetchAddr; //Previous window still recommended
doAssert(x == 'h80000140, "test fail!");
endaction
action
p.reportAccess('h80000140, MISS); //Report miss inside window
endaction
action
let x <- p.getNextPrefetchAddr; //Previous window still recommended
doAssert(x == 'h80000180, "test fail!");
endaction
action
p.reportAccess('h81000000, MISS); //Report miss somewhere far away
endaction
action
let x <- p.getNextPrefetchAddr; //New window allocated and recommended
doAssert(x == 'h81000040, "test fail!");
endaction
action
p.reportAccess('h80000180, MISS); //Report miss back home
endaction
action
p.reportAccess('h82000000, MISS); //Report miss far away 2
endaction
action
p.reportAccess('h80000100, MISS); //Report miss back home
endaction
action
let x <- p.getNextPrefetchAddr;
doAssert(x == 'h80000140, "test fail!");
endaction
action
let x <- p.getNextPrefetchAddr;
doAssert(x == 'h80000180, "test fail!"); // window addresss recommended
endaction
action
let x <- p.getNextPrefetchAddr; //target address recommended
doAssert(x == 'h81000000, "test fail!");
endaction
action
let x <- p.getNextPrefetchAddr; //target address recommended
doAssert(x == 'h82000000, "test fail!");
endaction
endseq
);
endmodule
module mkStridePCPrefetcherTest(Empty);
//let p <- mkMultipleWindowPrefetcher;
//TODO pass in value of cachelinesinrange
@@ -481,6 +734,53 @@ module mkBRAMStridePCPrefetcherTest(Empty);
);
endmodule
module mkBRAMMarkovPrefetcherTest(Empty);
//let p <- mkMultipleWindowPrefetcher;
//TODO pass in value of cachelinesinrange
let p <- mkBRAMMarkovPrefetcher;
mkAutoFSM(
seq
// ----- Send misses and stuff to one window -----
action
p.reportAccess('h80000000, MISS);
endaction
action
p.reportAccess('h80000700, MISS);
endaction
action
p.reportAccess('h90000000, MISS);
endaction
action
p.reportAccess('ha0000000, MISS);
endaction
action
p.reportAccess('h80000000, HIT); //back to start
endaction
action
let x <- p.getNextPrefetchAddr;
doAssert(x == 'h80000700, "test fail!");
endaction
action
let x <- p.getNextPrefetchAddr;
doAssert(x == 'h90000000, "test fail!");
endaction
action
p.reportAccess('h80000700, HIT);
endaction
action
p.reportAccess('ha0000000, HIT);
endaction
action
let x <- p.getNextPrefetchAddr;
doAssert(x == 'h80000000, "test fail!");
endaction
action
let x <- p.getNextPrefetchAddr;
doAssert(x == 'h80000700, "test fail!");
endaction
endseq
);
endmodule
module mkMarkovPrefetcherTest(Empty);
//let p <- mkMultipleWindowPrefetcher;
//TODO pass in value of cachelinesinrange