LLC prefetcher fixes and single window target prefetcher implementation

This commit is contained in:
Karlis Susters
2023-01-16 23:43:53 +00:00
parent 347107b733
commit e602d4780e
3 changed files with 167 additions and 14 deletions

View File

@@ -415,8 +415,9 @@ endfunction
);
endrule
// insert new cRq from child to MSHR and send to pipeline
rule createDataPrefetchRq(newCRqSrc == Valid (Child));
// create new request from data prefetcher and send to pipeline
// Rule only fires when no work from child and DMA
rule createDataPrefetchRq(newCRqSrc == Invalid);
Addr addr <- dataPrefetcher.getNextPrefetchAddr;
cRqT cRq = LLRq {
addr: addr,
@@ -444,8 +445,9 @@ endfunction
);
endrule
// insert new cRq from child to MSHR and send to pipeline
rule createInstrPrefetchRq(newCRqSrc == Valid (Child));
// create new request from instruction prefetcher and send to pipeline
// Rule only fires when no work from child and DMA
rule createInstrPrefetchRq(newCRqSrc == Invalid);
Addr addr <- instrPrefetcher.getNextPrefetchAddr;
cRqT cRq = LLRq {
addr: addr,
@@ -609,7 +611,9 @@ endfunction
);
// performance counter: normal miss lat and cnt
// Check lowest bit of child ID to determine if this was an ICache access
incrMissCnt(n, False, cRq.child[0] == 1);
if (!cRqIsPrefetch[n]) begin
incrMissCnt(n, False, cRq.child[0] == 1);
end
endrule
// this mem resp is just for a DMA req, won't go into pipeline to refill cache

View File

@@ -129,7 +129,7 @@ module mkNextLinePrefetcherBackwards(Prefetcher)
endmodule
module mkSingleWindowPrefetcher(Prefetcher);
Integer cacheLinesInRange = 3;
Integer cacheLinesInRange = 2;
Reg#(LineAddr) rangeEnd <- mkReg(0); //Points to one CLine after end of range
Reg#(LineAddr) nextToAsk <- mkReg(0);
method Action reportHit(Addr hitAddr);
@@ -195,8 +195,7 @@ provisos(
function ActionValue#(Maybe#(windowIdxT)) getMatchingWindow(Addr addr) =
actionvalue
//Finds the first window that contains addr,
//and moves it to the front of the LRU shift reg
//Finds the first window that contains addr
let cl = getLineAddr(addr);
function Bool pred(StreamEntry se);
//TODO < gives 100 cycles less??????
@@ -268,6 +267,89 @@ provisos(
endmodule
typedef 64 TargetTableSize;
typedef struct {
Bit#(targetTableTagBits) tag;
LineAddr target;
} TargetEntry#(numeric type targetTableTagBits) deriving (Bits, Eq, FShow);
module mkSingleWindowTargetPrefetcher(Prefetcher) provisos
(
NumAlias#(targetTableIdxBits, TLog#(TargetTableSize)),
NumAlias#(targetTableTagBits, TSub#(32, targetTableIdxBits)),
Alias#(targetEntryT, TargetEntry#(targetTableTagBits))
);
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);
Vector#(TargetTableSize, Reg#(Maybe#(targetEntryT))) targetTable <- replicateM(mkReg(Invalid));
method Action reportHit(Addr hitAddr);
let cl = getLineAddr(hitAddr);
if (rangeEnd - fromInteger(cacheLinesInRange) - 1 < cl && cl < rangeEnd) begin
let nextEnd = cl + fromInteger(cacheLinesInRange) + 1;
rangeEnd <= nextEnd;
if (nextToAsk <= cl) nextToAsk <= cl + 1;
$display("%t Prefetcher reportHit %h, moving window end to %h", $time, hitAddr, Addr'{nextEnd, '0});
end
/*
else if (rangeEnd - fromInteger(cacheLinesInRange) - 1 != cl) begin
//If hit outside window, reallocate window (test!)
nextToAsk <= cl + 1;
rangeEnd <= cl + fromInteger(cacheLinesInRange) + 1;
$display("%t Prefetcher reportHit %h, allocate new window", $time, hitAddr);
end
*/
if (cl != lastChildRequest + 1 && cl != lastChildRequest && cl != lastChildRequest - 1) begin
//Add entry to target table
targetEntryT entry;
entry.tag = lastChildRequest[31:valueOf(targetTableIdxBits)];
entry.target = cl;
Bit#(targetTableIdxBits) idx = truncate(lastChildRequest);
targetTable[idx] <= tagged Valid entry;
$display("%t Prefetcher reportHit %h, add target entry from %h", $time, hitAddr, Addr'{lastChildRequest, '0});
end
lastChildRequest <= cl;
endmethod
method Action reportMiss(Addr missAddr);
$display("%t Prefetcher reportMiss %h", $time, missAddr);
let cl = getLineAddr(missAddr);
nextToAsk <= cl + 1;
rangeEnd <= cl + fromInteger(cacheLinesInRange) + 1;
if (cl != lastChildRequest + 1 && cl != lastChildRequest && cl != lastChildRequest - 1) begin
//Add entry to target table
$display("%t Prefetcher reportMiss %h, add target entry from %h", $time, missAddr, Addr'{lastChildRequest, '0});
targetEntryT entry;
entry.tag = lastChildRequest[31:valueOf(targetTableIdxBits)];
entry.target = cl;
Bit#(targetTableIdxBits) idx = truncate(lastChildRequest);
targetTable[idx] <= tagged Valid entry;
end
lastChildRequest <= cl;
endmethod
method ActionValue#(Addr) getNextPrefetchAddr if (nextToAsk != rangeEnd);
Addr retAddr;
let lastAsked = nextToAsk-1;
Bit#(targetTableIdxBits) idx = truncate(lastAsked);
if (targetTable[idx] matches tagged Valid .entry
&&& entry.tag == (lastAsked)[31:valueOf(targetTableIdxBits)]) begin
//If have valid entry for the last requested cline, prefetch the stored target first
//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
targetTable[idx] <= Invalid;
retAddr = {entry.target, '0};
$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}; //extend cache line address to regular address
$display("%t Prefetcher getNextPrefetchAddr requesting next-line %h", $time, retAddr);
end
return retAddr;
endmethod
endmodule
interface PCPrefetcher;
method Action reportAccess(Addr addr, Bit#(16) pcHash, HitOrMiss hitMiss);
method ActionValue#(Addr) getNextPrefetchAddr();
@@ -514,7 +596,8 @@ module mkL1IPrefetcher(Prefetcher);
//let m <- mkNextLinePrefetcher;
//let m <- mkMultiWindowPrefetcher;
//let m <- mkNextLineOnAllPrefetcher;
let m <- mkDoNothingPrefetcher;
//let m <- mkDoNothingPrefetcher;
let m <- mkSingleWindowTargetPrefetcher;
return m;
endmodule
@@ -527,16 +610,18 @@ endmodule
module mkLLIPrefetcher(Prefetcher);
//let m <- mkNextLineOnMissPrefetcher;
let m <- mkMultiWindowPrefetcher;
//let m <- mkMultiWindowPrefetcher;
//let m <- mkSingleWindowPrefetcher;
//let m <- mkSingleWindowTargetPrefetcher;
//let m <- mkStridePCPrefetcher2;
//let m <- mkPrintPrefetcher;
//let m <- mkDoNothingPrefetcher;
let m <- mkDoNothingPrefetcher;
return m;
endmodule
module mkLLDPrefetcher(Prefetcher);
//let m <- mkNextLineOnAllPrefetcher;
let m <- mkPrintPrefetcher;
//let m <- mkDoNothingPrefetcher;
//let m <- mkPrintPrefetcher;
let m <- mkDoNothingPrefetcher;
return m;
endmodule

View File

@@ -104,6 +104,70 @@ module mkMultiWindowPrefetcherTest(Empty);
);
endmodule
module mkSingleWindowTargetPrefetcherTest(Empty);
//let p <- mkMultipleWindowPrefetcher;
//TODO pass in value of cachelinesinrange
let p <- mkSingleWindowTargetPrefetcher;
mkAutoFSM(
seq
// ----- Send misses and stuff to one window -----
action
p.reportMiss('h80000040);
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.reportHit('h800000c0); //Report hit inside window
endaction
action
let x <- p.getNextPrefetchAddr;
doAssert(x == 'h80000100, "test fail!");
endaction
action
p.reportHit('h80004000); //Report hit outside window
endaction
action
let x <- p.getNextPrefetchAddr; //Previous window still recommended
doAssert(x == 'h80000140, "test fail!");
endaction
action
p.reportMiss('h80000140); //Report miss inside window
endaction
action
let x <- p.getNextPrefetchAddr; //Previous window still recommended
doAssert(x == 'h80000180, "test fail!");
endaction
action
p.reportMiss('h81000000); //Report miss somewhere far away
endaction
action
let x <- p.getNextPrefetchAddr; //New window allocated and recommended
doAssert(x == 'h81000040, "test fail!");
endaction
action
p.reportMiss('h80000100); //Report miss back home
endaction
action
let x <- p.getNextPrefetchAddr;
doAssert(x == 'h80000140, "test fail!");
endaction
action
let x <- p.getNextPrefetchAddr; //target address recommended
doAssert(x == 'h81000000, "test fail!");
endaction
action
let x <- p.getNextPrefetchAddr;
doAssert(x == 'h80000180, "test fail!"); // window addresss recommended
endaction
endseq
);
endmodule
module mkStridePCPrefetcher2Test(Empty);
//let p <- mkMultipleWindowPrefetcher;
@@ -246,4 +310,4 @@ module mkStridePCPrefetcherTest(Empty);
endaction
endseq
);
endmodule
endmodule