Implemented BRAM versions of stride, target, markov prefetchers
This commit is contained in:
@@ -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),
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user