LLC prefetcher fixes and single window target prefetcher implementation
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user