Merged reportHit & reportMiss, changed compile time parameter passing

This commit is contained in:
Karlis Susters
2023-01-19 11:59:31 +00:00
parent 06e648df6a
commit 9f733eddf1
4 changed files with 214 additions and 449 deletions

View File

@@ -513,7 +513,7 @@ module mkIBank#(
line: ram.line
}, True); // hit, so update rep info
if (!cRqIsPrefetch[n]) begin
prefetcher.reportHit(req.addr);
prefetcher.reportAccess(req.addr, HIT);
end
prefetchRqDone[n] <= True;
// process req to get superscalar inst read results
@@ -576,7 +576,7 @@ module mkIBank#(
line: ram.line
}, False);
if (!cRqIsPrefetch[n]) begin
prefetcher.reportMiss(procRq.addr);
prefetcher.reportAccess(procRq.addr, MISS);
end
endaction
endfunction
@@ -606,7 +606,7 @@ module mkIBank#(
waitP: True
});
if (!cRqIsPrefetch[n]) begin
prefetcher.reportMiss(procRq.addr);
prefetcher.reportAccess(procRq.addr, MISS);
end
// send replacement resp to parent
rsToPIndexQ.enq(CRq (n));

View File

@@ -1002,10 +1002,10 @@ endfunction
}, True); // hit, so update rep info
if (!cRqIsPrefetch[n]) begin
if (cRq.child[0] == 1) begin
instrPrefetcher.reportHit(cRq.addr);
instrPrefetcher.reportAccess(cRq.addr, HIT);
end
else begin
dataPrefetcher.reportHit(cRq.addr);
dataPrefetcher.reportAccess(cRq.addr, HIT);
end
end
endaction
@@ -1203,10 +1203,10 @@ endfunction
}, False);
if (!cRqIsPrefetch[n]) begin
if (cRq.child[0] == 1) begin
instrPrefetcher.reportMiss(cRq.addr);
instrPrefetcher.reportAccess(cRq.addr, MISS);
end
else begin
dataPrefetcher.reportMiss(cRq.addr);
dataPrefetcher.reportAccess(cRq.addr, MISS);
end
end
endaction
@@ -1279,10 +1279,10 @@ endfunction
end
if (!cRqIsPrefetch[n]) begin
if (cRq.child[0] == 1) begin
instrPrefetcher.reportMiss(cRq.addr);
instrPrefetcher.reportAccess(cRq.addr, MISS);
end
else begin
dataPrefetcher.reportMiss(cRq.addr);
dataPrefetcher.reportAccess(cRq.addr, MISS);
end
end
endaction

View File

@@ -5,77 +5,61 @@ import Types::*;
import Vector::*;
import ProcTypes::*;
typedef enum {
HIT = 1'b0, MISS = 1'b1
} HitOrMiss deriving (Bits, Eq, FShow);
interface Prefetcher;
method Action reportHit(Addr hitAddr);
method Action reportMiss(Addr missAddr);
(* always_ready *)
method Action reportAccess(Addr addr, HitOrMiss hitMiss);
method ActionValue#(Addr) getNextPrefetchAddr();
//method Action flush;
//method Bool flush_done;
endinterface
module mkTestPrefetcher(Prefetcher);
Reg#(Addr) lastMissAddr <- mkReg(0);
Reg#(Bit#(2)) reqSent <- mkReg(0);
method Action reportHit(Addr hitAddr);
$display("%t I Prefetcher reportHit %h", $time, hitAddr);
endmethod
method Action reportMiss(Addr missAddr);
$display("%t I Prefetcher reportMiss %h", $time, missAddr);
if (missAddr == 'h0000000080000040)
lastMissAddr <= missAddr;
endmethod
method ActionValue#(Addr) getNextPrefetchAddr if (reqSent < 2 && lastMissAddr == 'h0000000080000040);
$display("%t I Prefetcher getNextPrefetchAddr", $time);
reqSent <= reqSent + 1;
if (reqSent == 0) begin
return 64'h0000000080000080;
end
else begin
return 64'h00000000800000c0;
end
endmethod
endmodule
module mkDoNothingPrefetcher(Prefetcher);
method Action reportHit(Addr hitAddr);
endmethod
method Action reportMiss(Addr missAddr);
method Action reportAccess(Addr addr, HitOrMiss hitMiss);
endmethod
method ActionValue#(Addr) getNextPrefetchAddr if (False);
return 64'h0000000080000080;
return 64'h0;
endmethod
endmodule
module mkPrintPrefetcher(Prefetcher);
method Action reportHit(Addr hitAddr);
$display("%t PrintPrefetcher reportHit %h", $time, hitAddr);
endmethod
method Action reportMiss(Addr missAddr);
$display("%t PrintPrefetcher reportMiss %h", $time, missAddr);
method Action reportAccess(Addr addr, HitOrMiss hitMiss);
if (hitMiss == HIT) begin
$display("%t PrintPrefetcher report HIT %h", $time, addr);
end
else begin
$display("%t PrintPrefetcher report MISS %h", $time, addr);
end
endmethod
method ActionValue#(Addr) getNextPrefetchAddr if (False);
return 64'h0000000080000080;
return 64'h0;
endmethod
endmodule
typedef 3 INextLinesOnMiss;
typedef 0 DNextLinesOnMiss;
module mkNextLineOnMissPrefetcher(Prefetcher)
provisos (
Alias#(rqCntT, Bit#(TLog#(TAdd#(INextLinesOnMiss, 1))))
NumAlias#(nextLinesOnMiss, 3),
Alias#(rqCntT, Bit#(TLog#(TAdd#(nextLinesOnMiss, 1))))
);
Reg#(Addr) lastMissAddr <- mkReg(0);
Reg#(rqCntT) sentRequestCounter <- mkReg(fromInteger(valueOf(INextLinesOnMiss)));
method Action reportHit(Addr hitAddr);
$display("%t Prefetcher reportHit %h", $time, hitAddr);
Reg#(rqCntT) sentRequestCounter <- mkReg(fromInteger(valueOf(nextLinesOnMiss)));
method Action reportAccess(Addr addr, HitOrMiss hitMiss);
if (hitMiss == HIT) begin
$display("%t Prefetcher report HIT %h", $time, addr);
end
else begin
$display("%t Prefetcher report MISS %h", $time, addr);
lastMissAddr <= addr;
sentRequestCounter <= 0;
end
endmethod
method Action reportMiss(Addr missAddr);
$display("%t Prefetcher reportMiss %h", $time, missAddr);
lastMissAddr <= missAddr;
sentRequestCounter <= 0;
endmethod
method ActionValue#(Addr) getNextPrefetchAddr if (sentRequestCounter < fromInteger(valueOf(INextLinesOnMiss)));
method ActionValue#(Addr) getNextPrefetchAddr if
(sentRequestCounter < fromInteger(valueOf(nextLinesOnMiss)));
sentRequestCounter <= sentRequestCounter + 1;
let addrToRequest = lastMissAddr + (zeroExtend(sentRequestCounter) + 1)*fromInteger(valueOf(DataSz));
$display("%t Prefetcher getNextPrefetchAddr requesting %h", $time, addrToRequest);
@@ -85,45 +69,29 @@ endmodule
module mkNextLineOnAllPrefetcher(Prefetcher)
provisos (
Alias#(rqCntT, Bit#(TLog#(TAdd#(INextLinesOnMiss, 1))))
NumAlias#(nextLinesOnAccess, 3),
Alias#(rqCntT, Bit#(TLog#(TAdd#(nextLinesOnAccess, 1))))
);
Reg#(Addr) lastMissAddr <- mkReg(0);
Reg#(rqCntT) sentRequestCounter <- mkReg(fromInteger(valueOf(INextLinesOnMiss)));
method Action reportHit(Addr hitAddr);
$display("%t Prefetcher reportHit %h", $time, hitAddr);
lastMissAddr <= hitAddr;
sentRequestCounter <= 0;
endmethod
method Action reportMiss(Addr missAddr);
$display("%t Prefetcher reportMiss %h", $time, missAddr);
lastMissAddr <= missAddr;
sentRequestCounter <= 0;
endmethod
method ActionValue#(Addr) getNextPrefetchAddr if (sentRequestCounter < fromInteger(valueOf(INextLinesOnMiss)));
sentRequestCounter <= sentRequestCounter + 1;
let addrToRequest = lastMissAddr + (zeroExtend(sentRequestCounter) + 1)*fromInteger(valueOf(DataSz));
$display("%t Prefetcher getNextPrefetchAddr requesting %h", $time, addrToRequest);
return addrToRequest;
endmethod
endmodule
Reg#(Addr) lastAccessAddr <- mkReg(0);
Reg#(rqCntT) sentRequestCounter <- mkReg(fromInteger(valueOf(nextLinesOnAccess)));
module mkNextLinePrefetcherBackwards(Prefetcher)
provisos (
Alias#(rqCntT, Bit#(TLog#(TAdd#(DNextLinesOnMiss, 1))))
);
Reg#(Addr) lastMissAddr <- mkReg(0);
Reg#(rqCntT) sentRequestCounter <- mkReg(fromInteger(valueOf(DNextLinesOnMiss)));
method Action reportHit(Addr hitAddr);
$display("%t Prefetcher reportHit %h", $time, hitAddr);
method Action reportAccess(Addr addr, HitOrMiss hitMiss);
if (hitMiss == HIT) begin
$display("%t Prefetcher report HIT %h", $time, addr);
lastAccessAddr <= addr;
sentRequestCounter <= 0;
end
else begin
$display("%t Prefetcher report MISS %h", $time, addr);
lastAccessAddr <= addr;
sentRequestCounter <= 0;
end
endmethod
method Action reportMiss(Addr missAddr);
$display("%t Prefetcher reportMiss %h", $time, missAddr);
lastMissAddr <= missAddr;
sentRequestCounter <= 0;
endmethod
method ActionValue#(Addr) getNextPrefetchAddr if (sentRequestCounter < fromInteger(valueOf(DNextLinesOnMiss)));
method ActionValue#(Addr) getNextPrefetchAddr if
(sentRequestCounter < fromInteger(valueOf(nextLinesOnAccess)));
sentRequestCounter <= sentRequestCounter + 1;
let addrToRequest = lastMissAddr - (zeroExtend(sentRequestCounter) + 1)*fromInteger(valueOf(DataSz));
let addrToRequest = lastAccessAddr + (zeroExtend(sentRequestCounter) + 1)*fromInteger(valueOf(DataSz));
$display("%t Prefetcher getNextPrefetchAddr requesting %h", $time, addrToRequest);
return addrToRequest;
endmethod
@@ -133,19 +101,22 @@ module mkSingleWindowPrefetcher(Prefetcher);
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);
let cl = getLineAddr(hitAddr);
if (rangeEnd - fromInteger(cacheLinesInRange) - 1 < cl && cl < rangeEnd) begin
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 reportHit %h, moving window end to %h", $time, hitAddr, Addr'{nextEnd, '0});
$display("%t Prefetcher report HIT %h, moving window end to %h", $time, addr, Addr'{nextEnd, '0});
rangeEnd <= nextEnd;
end
endmethod
method Action reportMiss(Addr missAddr);
$display("%t Prefetcher reportMiss %h", $time, missAddr);
nextToAsk <= getLineAddr(missAddr) + 1;
rangeEnd <= getLineAddr(missAddr) + fromInteger(cacheLinesInRange) + 1;
//LgLineSzBytes
else begin
$display("%t Prefetcher report MISS %h", $time, addr);
//Reset window
nextToAsk <= getLineAddr(addr) + 1;
rangeEnd <= getLineAddr(addr) + fromInteger(cacheLinesInRange) + 1;
end
endmethod
method ActionValue#(Addr) getNextPrefetchAddr if (nextToAsk != rangeEnd);
nextToAsk <= nextToAsk + 1;
@@ -161,18 +132,16 @@ typedef struct {
LineAddr nextToAsk;
} StreamEntry deriving (Bits);
typedef 4 NumWindows;
module mkMultiWindowPrefetcher(Prefetcher)
provisos(
Alias#(windowIdxT, Bit#(TLog#(NumWindows)))
NumAlias#(numWindows, 4),
Alias#(windowIdxT, Bit#(TLog#(numWindows)))
);
Integer cacheLinesInRange = 2;
Vector#(NumWindows, Reg#(StreamEntry)) streams
Vector#(numWindows, Reg#(StreamEntry)) streams
<- replicateM(mkReg(StreamEntry {rangeEnd: '0, nextToAsk: '0}));
Vector#(NumWindows, Reg#(windowIdxT)) shiftReg <- genWithM(compose(mkReg, fromInteger));
Vector#(numWindows, Reg#(windowIdxT)) shiftReg <- genWithM(compose(mkReg, fromInteger));
//function
function Action moveWindowToFront(windowIdxT window) =
action
if (shiftReg[0] == window) begin
@@ -212,44 +181,33 @@ provisos(
end
endactionvalue;
method Action reportHit(Addr hitAddr);
//Check if any stream line matches request
//if so, advance that stream line
//also advance LRU shift reg
let idxMaybe <- getMatchingWindow(hitAddr);
if (idxMaybe matches tagged Valid .idx) begin
moveWindowToFront(pack(idx)); //Update window as just used
let newRangeEnd = getLineAddr(hitAddr) + fromInteger(cacheLinesInRange) + 1;
streams[idx].rangeEnd <= newRangeEnd;
$display("%t Prefetcher reportHit %h, moving window end to %h for window idx %h",
$time, hitAddr, Addr'{newRangeEnd, '0}, idx);
end
else begin
$display("%t Prefetcher reportHit %h, no matching window found.",
$time, hitAddr);
end
endmethod
method Action reportMiss(Addr missAddr);
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, allocate new stream line, and shift LRU reg completely,
let idxMaybe <- getMatchingWindow(missAddr);
//Otherwise if miss, allocate new stream line, and shift LRU reg completely,
let idxMaybe <- getMatchingWindow(addr);
if (idxMaybe matches tagged Valid .idx) begin
moveWindowToFront(pack(idx)); //Update window as just used
let newRangeEnd = getLineAddr(missAddr) + fromInteger(cacheLinesInRange) + 1;
//Also refresh nextToAsk on miss
streams[idx] <=
StreamEntry {nextToAsk: getLineAddr(missAddr) + 1,
rangeEnd: newRangeEnd};
$display("%t Prefetcher reportMiss %h, moving window end to %h for window idx %h",
$time, missAddr, Addr'{newRangeEnd, '0}, idx);
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 begin
$display("%t Prefetcher reportMiss %h, allocating new stream, idx %h", $time, missAddr, shiftReg[3]);
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(missAddr) + 1,
rangeEnd: getLineAddr(missAddr) + fromInteger(cacheLinesInRange) + 1};
StreamEntry {nextToAsk: getLineAddr(addr) + 1,
rangeEnd: getLineAddr(addr) + fromInteger(cacheLinesInRange) + 1};
shiftReg[0] <= shiftReg[3];
shiftReg[1] <= shiftReg[0];
shiftReg[2] <= shiftReg[1];
@@ -340,7 +298,6 @@ module mkTargetTable(TargetTable#(narrowTableSize, wideTableSize)) provisos
endmethod
endmodule
module mkSingleWindowTargetPrefetcher(Prefetcher) provisos
();
Integer cacheLinesInRange = 2;
@@ -348,39 +305,31 @@ module mkSingleWindowTargetPrefetcher(Prefetcher) provisos
Reg#(LineAddr) nextToAsk <- mkReg(0);
Reg#(LineAddr) lastChildRequest <- mkReg(0);
TargetTable#(64, 8) targetTable <- mkTargetTable;
method Action reportHit(Addr hitAddr);
let cl = getLineAddr(hitAddr);
if (rangeEnd - fromInteger(cacheLinesInRange) - 1 < cl && cl < rangeEnd) begin
//If hit outside window, reallocate window (test!)
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;
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!)
else if (hitMiss == MISS) begin
$display("%t Prefetcher report MISS %h", $time, addr);
//Reset window
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
$display("%t Prefetcher reportHit %h, add target entry from addr %h", $time, hitAddr, Addr'{lastChildRequest, '0});
targetTable.set(lastChildRequest, cl);
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
$display("%t Prefetcher add target entry from %h", $time, Addr'{lastChildRequest, '0});
$display("%t Prefetcher add target entry from addr %h to addr %h", $time, Addr'{lastChildRequest, '0}, addr);
targetTable.set(lastChildRequest, cl);
end
lastChildRequest <= cl;
endmethod
method ActionValue#(Addr) getNextPrefetchAddr if (nextToAsk != rangeEnd);
Addr retAddr;
let lastAsked = nextToAsk-1;
@@ -404,12 +353,13 @@ endmodule
module mkMultiWindowTargetPrefetcher(Prefetcher)
provisos(
Alias#(windowIdxT, Bit#(TLog#(NumWindows)))
NumAlias#(numWindows, 4),
Alias#(windowIdxT, Bit#(TLog#(numWindows)))
);
Integer cacheLinesInRange = 2;
Vector#(NumWindows, Reg#(StreamEntry)) streams
Vector#(numWindows, Reg#(StreamEntry)) streams
<- replicateM(mkReg(StreamEntry {rangeEnd: '0, nextToAsk: '0}));
Vector#(NumWindows, Reg#(windowIdxT)) shiftReg <- genWithM(compose(mkReg, fromInteger));
Vector#(numWindows, Reg#(windowIdxT)) shiftReg <- genWithM(compose(mkReg, fromInteger));
Reg#(LineAddr) lastChildRequest <- mkReg(0);
TargetTable#(64, 8) targetTable <- mkTargetTable;
function Action moveWindowToFront(windowIdxT window) =
@@ -449,71 +399,46 @@ provisos(
return Invalid;
end
endactionvalue;
// test: allocate new window on hit too (mostly for target prefetching)
method Action reportHit(Addr hitAddr);
//Check if any stream line matches request
//if so, advance that stream line
//also advance LRU shift reg
let cl = getLineAddr(hitAddr);
let idxMaybe <- getMatchingWindow(cl);
if (idxMaybe matches tagged Valid .idx) begin
moveWindowToFront(pack(idx)); //Update window as just used
let newRangeEnd = getLineAddr(hitAddr) + fromInteger(cacheLinesInRange) + 1;
streams[idx].rangeEnd <= newRangeEnd;
$display("%t Prefetcher reportHit %h, moving window end to %h for window idx %h",
$time, hitAddr, Addr'{newRangeEnd, '0}, idx);
end
else begin
$display("%t Prefetcher reportHit %h, no matching window found.",
$time, hitAddr);
/*
test: allocate new window on hit too (mostly for target prefetching)
streams[shiftReg[3]] <=
StreamEntry {nextToAsk: getLineAddr(missAddr) + 1,
rangeEnd: getLineAddr(missAddr) + fromInteger(cacheLinesInRange) + 1};
shiftReg[0] <= shiftReg[3];
shiftReg[1] <= shiftReg[0];
shiftReg[2] <= shiftReg[1];
shiftReg[3] <= shiftReg[2];
*/
end
if (cl != lastChildRequest + 1 && cl != lastChildRequest && cl != lastChildRequest - 1) begin
//Add entry to target table
$display("%t Prefetcher reportHit %h, add target entry from %h", $time, hitAddr, Addr'{lastChildRequest, '0});
targetTable.set(lastChildRequest, cl);
end
lastChildRequest <= cl;
endmethod
method Action reportMiss(Addr missAddr);
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, allocate new stream line, and shift LRU reg completely,
let cl = getLineAddr(missAddr);
//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(missAddr) + fromInteger(cacheLinesInRange) + 1;
//Also refresh nextToAsk on miss
streams[idx] <=
StreamEntry {nextToAsk: getLineAddr(missAddr) + 1,
rangeEnd: newRangeEnd};
$display("%t Prefetcher reportMiss %h, moving window end to %h for window idx %h",
$time, missAddr, Addr'{newRangeEnd, '0}, idx);
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 begin
$display("%t Prefetcher reportMiss %h, allocating new stream, idx %h", $time, missAddr, shiftReg[3]);
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(missAddr) + 1,
rangeEnd: getLineAddr(missAddr) + fromInteger(cacheLinesInRange) + 1};
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
//Add entry to target table
$display("%t Prefetcher reportMiss %h, add target entry from %h", $time, missAddr, Addr'{lastChildRequest, '0});
$display("%t Prefetcher add target entry from addr %h to addr %h", $time, Addr'{lastChildRequest, '0}, addr);
targetTable.set(lastChildRequest, cl);
end
lastChildRequest <= cl;
@@ -543,6 +468,7 @@ provisos(
endmodule
interface PCPrefetcher;
(* always_ready *)
method Action reportAccess(Addr addr, Bit#(16) pcHash, HitOrMiss hitMiss);
method ActionValue#(Addr) getNextPrefetchAddr();
endinterface
@@ -558,9 +484,9 @@ endmodule
module mkPrintPCPrefetcher(PCPrefetcher);
method Action reportAccess(Addr addr, Bit#(16) pcHash, HitOrMiss hitMiss);
if (hitMiss == HIT)
$display("%t PCPrefetcher reportHit %h", $time, addr);
$display("%t PCPrefetcher report HIT %h", $time, addr);
else
$display("%t PCPrefetcher reportMiss %h", $time, addr);
$display("%t PCPrefetcher report MISS %h", $time, addr);
endmethod
method ActionValue#(Addr) getNextPrefetchAddr if (False);
return 64'h0000000080000080;
@@ -571,115 +497,23 @@ typedef enum {
EMPTY = 2'b00, INIT = 2'b01, TRANSIENT = 2'b10, STEADY = 2'b11
} StrideState deriving (Bits, Eq, FShow);
typedef enum {
HIT = 1'b0, MISS = 1'b1
} HitOrMiss deriving (Bits, Eq, FShow);
typedef struct {
Addr lastAddr; //TODO maybe store less bits here?
Bit#(13) stride;
StrideState state;
Bit#(4) lastPrefetch; //Stores how many strides ahead of lastAddr was the last prefetch done
} StrideEntry deriving (Bits, Eq, FShow);
typedef 8 HistoryLen;
typedef 64 StrideTableSize;
typedef 4 StridesAheadToPrefetch;
module mkStridePCPrefetcher(PCPrefetcher)
provisos(
Alias#(strideTableIndexT, Bit#(TLog#(StrideTableSize)))
);
Reg#(Vector#(HistoryLen, strideTableIndexT)) historyVec <- mkReg(replicate(?));
Vector#(StrideTableSize, Reg#(StrideEntry)) strideTable <- replicateM(mkReg(unpack(0)));
function Maybe#(strideTableIndexT) getNextPrefetchIndex;
function Bool canPrefetch(strideTableIndexT idx);
return (strideTable[idx].state == STEADY &&
strideTable[idx].lastPrefetch != fromInteger(valueof(StridesAheadToPrefetch)));
endfunction
//Find first entry that allows more prefetches
case (find(canPrefetch, historyVec)) matches
tagged Valid .idx: return Valid(pack(idx));
Invalid: return Invalid;
endcase
endfunction
method ActionValue#(Addr) getNextPrefetchAddr if
(getNextPrefetchIndex() matches tagged Valid .idx);
//could store some most recent table entries,
//then check if any of those entries can be prefetched more
//could just store the recent table entries in a circular buffer with duplication
// since shouldn't have duplicates within one loop iteration
// but we need to access all entries (or have rule that discards first entry, it we can't prefetch for it)
Reg#(StrideEntry) se = strideTable[idx];
se.lastPrefetch <= se.lastPrefetch + 1;
return se.lastAddr + (signExtend(se.stride) * zeroExtend(se.lastPrefetch + 1));
endmethod
method Action reportAccess(Addr addr, Bit#(16) pcHash, HitOrMiss hitMiss);
//Find slot in vector
//if miss and slot empty
//if slot init, put address, stride and move to transit
//if slot transit or steady, verify stride, and move to steady
// also put last_prefetched
//if stride wrong, move to transit
strideTableIndexT index = truncate(pcHash);
Reg#(StrideEntry) se = strideTable[index];
StrideEntry seNext = se;
$writeh("Prefetcher: ",
fshow(hitMiss), " ", addr,
". Entry state is ", fshow(se.state));
if (hitMiss == MISS && se.state == EMPTY) begin
seNext.lastAddr = addr;
seNext.state = INIT;
$display(", allocate entry");
end
else if (se.state == INIT) begin
seNext.stride = truncate(addr - se.lastAddr);
seNext.state = TRANSIENT;
seNext.lastAddr = addr;
$display(", set stride to %h", seNext.stride);
end
else if (se.state == TRANSIENT || se.state == STEADY) begin
if (truncate(addr - se.lastAddr) == se.stride) begin
case (se.state)
TRANSIENT: seNext.lastPrefetch = 0;
STEADY: seNext.lastPrefetch = (seNext.lastPrefetch == 0) ? 0 : se.lastPrefetch - 1;
endcase
seNext.state = STEADY;
seNext.lastAddr = addr;
historyVec <= shiftInAt0(historyVec, index);
$display(", stride %h is confirmed!", seNext.stride);
end
else begin
seNext.state = TRANSIENT;
seNext.stride = truncate(addr - se.lastAddr);
seNext.lastAddr = addr;
$display(", old stride is broken! New stride: %h", seNext.stride);
end
end
se <= seNext;
endmethod
endmodule
typedef struct {
Bit#(12) lastAddr;
Bit#(13) stride;
StrideState state;
Bit#(4) cLinesPrefetched; //Stores how many cache lines have been prefetched for this instruction
} StrideEntry2 deriving (Bits, Eq, FShow);
} StrideEntry deriving (Bits, Eq, FShow);
typedef 3 CLinesAheadToPrefetch;
module mkStridePCPrefetcher2(PCPrefetcher)
module mkStridePCPrefetcher(PCPrefetcher)
provisos(
NumAlias#(historyLen, 8),
NumAlias#(strideTableSize, 64),
NumAlias#(cLinesAheadToPrefetch, 3), // TODO fetch more if have repeatedly hit an entry, and if stride big
Alias#(strideTableIndexT, Bit#(TLog#(StrideTableSize))),
Alias#(historyVecIndexT, Bit#(TLog#(HistoryLen)))
);
Reg#(Vector#(HistoryLen, Tuple2#(strideTableIndexT, Addr))) historyVec <- mkReg(replicate(?));
Vector#(StrideTableSize, Reg#(StrideEntry2)) strideTable <- replicateM(mkReg(unpack(0)));
Vector#(StrideTableSize, Reg#(StrideEntry)) strideTable <- replicateM(mkReg(unpack(0)));
function Maybe#(historyVecIndexT) getNextPrefetchHistoryIndex;
function Bool canPrefetch(Tuple2#(strideTableIndexT, Addr) entry);
@@ -696,29 +530,6 @@ provisos(
endcase
endfunction
method ActionValue#(Addr) getNextPrefetchAddr if
(getNextPrefetchHistoryIndex() matches tagged Valid .historyIdx);
match {.strideIdx, .fullAddr} = historyVec[historyIdx];
Reg#(StrideEntry2) se = strideTable[strideIdx];
se.cLinesPrefetched <= se.cLinesPrefetched + 1;
Bit#(13) strideToUse;
Bit#(13) cLineSize = fromInteger(valueof(DataSz));
if (se.stride[12] == 1 && se.stride > -cLineSize) begin
//stride is negative and jumps less than one cline
strideToUse = -cLineSize;
end
else if (se.stride[12] == 0 && se.stride < cLineSize) begin
//stride is positive and jumps less than one cline
strideToUse = cLineSize;
end
else
strideToUse = se.stride;
let reqAddr = fullAddr +
(signExtend(strideToUse) * zeroExtend(se.cLinesPrefetched + 1));
$display("%t Stride Prefetcher getNextPrefetchAddr requesting %h for entry %h", $time, reqAddr, strideIdx);
return reqAddr;
endmethod
method Action reportAccess(Addr addr, Bit#(16) pcHash, HitOrMiss hitMiss);
//Find slot in vector
//if miss and slot empty
@@ -727,8 +538,8 @@ provisos(
// also put last_prefetched
//if stride wrong, move to transit
strideTableIndexT index = truncate(pcHash);
Reg#(StrideEntry2) se = strideTable[index];
StrideEntry2 seNext = se;
Reg#(StrideEntry) se = strideTable[index];
StrideEntry seNext = se;
Bit#(13) observedStride = {1'b0, addr[11:0]} - {1'b0, se.lastAddr};
$writeh("%t Stride Prefetcher reportAccess ", $time,
fshow(hitMiss), " ", addr,
@@ -780,7 +591,30 @@ provisos(
se <= seNext;
endmethod
method ActionValue#(Addr) getNextPrefetchAddr if
(getNextPrefetchHistoryIndex() matches tagged Valid .historyIdx);
match {.strideIdx, .fullAddr} = historyVec[historyIdx];
Reg#(StrideEntry) se = strideTable[strideIdx];
se.cLinesPrefetched <= se.cLinesPrefetched + 1;
Bit#(13) strideToUse;
Bit#(13) cLineSize = fromInteger(valueof(DataSz));
if (se.stride[12] == 1 && se.stride > -cLineSize) begin
//stride is negative and jumps less than one cline
strideToUse = -cLineSize;
end
else if (se.stride[12] == 0 && se.stride < cLineSize) begin
//stride is positive and jumps less than one cline
strideToUse = cLineSize;
end
else begin
strideToUse = se.stride;
end
let reqAddr = fullAddr +
(signExtend(strideToUse) * zeroExtend(se.cLinesPrefetched + 1));
$display("%t Stride Prefetcher getNextPrefetchAddr requesting %h for entry %h", $time, reqAddr, strideIdx);
return reqAddr;
endmethod
endmodule
@@ -788,8 +622,10 @@ module mkL1IPrefetcher(Prefetcher);
//let m <- mkNextLinePrefetcher;
//let m <- mkMultiWindowPrefetcher;
//let m <- mkNextLineOnAllPrefetcher;
//let m <- mkDoNothingPrefetcher;
let m <- mkSingleWindowTargetPrefetcher;
let m <- mkDoNothingPrefetcher;
//let m <- mkSingleWindowTargetPrefetcher;
//let m <- mkMultiWindowTargetPrefetcher;
//module mkMultiWindowPrefetcher(Integer cacheLinesInRange)(Prefetcher)
return m;
endmodule
@@ -803,11 +639,12 @@ endmodule
module mkLLIPrefetcher(Prefetcher);
//let m <- mkNextLineOnMissPrefetcher;
//let m <- mkMultiWindowPrefetcher;
let m <- mkMultiWindowTargetPrefetcher;
//let m <- mkSingleWindowPrefetcher;
//let m <- mkSingleWindowTargetPrefetcher;
//let m <- mkStridePCPrefetcher2;
//let m <- mkPrintPrefetcher;
let m <- mkDoNothingPrefetcher;
//let m <- mkDoNothingPrefetcher;
return m;
endmodule

View File

@@ -51,7 +51,7 @@ module mkMultiWindowPrefetcherTest(Empty);
seq
// ----- Send misses and stuff to one window -----
action
p.reportMiss('h80000040);
p.reportAccess('h80000040, MISS);
endaction
action
let x <- p.getNextPrefetchAddr;
@@ -62,21 +62,21 @@ module mkMultiWindowPrefetcherTest(Empty);
doAssert(x == 'h800000c0, "test fail!");
endaction
action
p.reportHit('h800000c0); //Report hit inside window
p.reportAccess('h800000c0, HIT); //Report hit inside window
endaction
action
let x <- p.getNextPrefetchAddr;
doAssert(x == 'h80000100, "test fail!");
endaction
action
p.reportHit('h80004000); //Report hit outside window
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.reportMiss('h80000140); //Report miss inside window
p.reportAccess('h80000140, MISS); //Report miss inside window
endaction
action
let x <- p.getNextPrefetchAddr; //Previous window still recommended
@@ -85,28 +85,28 @@ module mkMultiWindowPrefetcherTest(Empty);
// ----- Allocate other windows -----
action
p.reportMiss('h70000000); //Report miss outside window
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.reportMiss('h90000000); //Report miss outside window
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.reportMiss('h60000000); //Report miss outside window
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.reportHit('h80000180); //Report hit inside oldest window
p.reportAccess('h80000180, HIT); //Report hit inside oldest window
endaction
action
let x <- p.getNextPrefetchAddr; //oldest window recommended
@@ -115,7 +115,7 @@ module mkMultiWindowPrefetcherTest(Empty);
// ----- Trigger window deletion -----
action
p.reportMiss('h50000000); //Report miss outside window,
p.reportAccess('h50000000, MISS); //Report miss outside window,
//discard window with 'h70..
endaction
action
@@ -123,7 +123,7 @@ module mkMultiWindowPrefetcherTest(Empty);
doAssert(x == 'h50000040, "test fail!");
endaction
action
p.reportHit('h70000040); //Report hit inside now deleted window
p.reportAccess('h70000040, HIT); //Report hit inside now deleted window
endaction
action
let x <- p.getNextPrefetchAddr; //most recent window still recommended
@@ -132,7 +132,7 @@ module mkMultiWindowPrefetcherTest(Empty);
// ----- Reorder some more windows around
action
p.reportMiss('h800001c0); //Report hit inside now deleted window
p.reportAccess('h800001c0, MISS); //Report hit inside now deleted window
endaction
action
let x <- p.getNextPrefetchAddr; //most recent window still recommended
@@ -152,7 +152,7 @@ module mkMultiWindowTargetPrefetcherTest(Empty);
seq
// ----- Send misses and stuff to one window -----
action
p.reportMiss('h80000040);
p.reportAccess('h80000040, MISS);
endaction
action
let x <- p.getNextPrefetchAddr;
@@ -163,21 +163,21 @@ module mkMultiWindowTargetPrefetcherTest(Empty);
doAssert(x == 'h800000c0, "test fail!");
endaction
action
p.reportHit('h800000c0); //Report hit inside window
p.reportAccess('h800000c0, HIT); //Report hit inside window
endaction
action
let x <- p.getNextPrefetchAddr;
doAssert(x == 'h80000100, "test fail!");
endaction
action
p.reportHit('h80004000); //Report hit outside window
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.reportMiss('h80000140); //Report miss inside window
p.reportAccess('h80000140, MISS); //Report miss inside window
endaction
action
let x <- p.getNextPrefetchAddr; //Previous window still recommended
@@ -186,28 +186,28 @@ module mkMultiWindowTargetPrefetcherTest(Empty);
// ----- Allocate other windows -----
action
p.reportMiss('h70000000); //Report miss outside window
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.reportMiss('h90000000); //Report miss outside window
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.reportMiss('h60000000); //Report miss outside window
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.reportHit('h80000180); //Report hit inside oldest window
p.reportAccess('h80000180, HIT); //Report hit inside oldest window
endaction
action
let x <- p.getNextPrefetchAddr; //oldest window recommended
@@ -216,7 +216,7 @@ module mkMultiWindowTargetPrefetcherTest(Empty);
// ----- Trigger window deletion -----
action
p.reportMiss('h50000000); //Report miss outside window,
p.reportAccess('h50000000, MISS); //Report miss outside window,
//discard window with 'h70..
endaction
action
@@ -224,7 +224,7 @@ module mkMultiWindowTargetPrefetcherTest(Empty);
doAssert(x == 'h50000040, "test fail!");
endaction
action
p.reportHit('h70000040); //Report hit inside now deleted window
p.reportAccess('h70000040, HIT); //Report hit inside now deleted window
endaction
action
let x <- p.getNextPrefetchAddr; //most recent window still recommended
@@ -233,7 +233,7 @@ module mkMultiWindowTargetPrefetcherTest(Empty);
// ----- Reorder some more windows around
action
p.reportMiss('h800001c0); //Report hit inside now deleted window
p.reportAccess('h800001c0, MISS); //Report hit inside now deleted window
endaction
action
let x <- p.getNextPrefetchAddr;
@@ -242,14 +242,14 @@ module mkMultiWindowTargetPrefetcherTest(Empty);
// ------ Test saving and prefetching target clines
action
p.reportMiss('h81000000); //Report miss somewhere far away
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.reportMiss('h80000180); //Report miss back home
p.reportAccess('h80000180, MISS); //Report miss back home
endaction
action
let x <- p.getNextPrefetchAddr; //new window recommended
@@ -279,7 +279,7 @@ module mkSingleWindowTargetPrefetcherTest(Empty);
seq
// ----- Send misses and stuff to one window -----
action
p.reportMiss('h80000040);
p.reportAccess('h80000040, MISS);
endaction
action
let x <- p.getNextPrefetchAddr;
@@ -290,35 +290,35 @@ module mkSingleWindowTargetPrefetcherTest(Empty);
doAssert(x == 'h800000c0, "test fail!");
endaction
action
p.reportHit('h800000c0); //Report hit inside window
p.reportAccess('h800000c0, HIT); //Report hit inside window
endaction
action
let x <- p.getNextPrefetchAddr;
doAssert(x == 'h80000100, "test fail!");
endaction
action
p.reportHit('h80004000); //Report hit outside window
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.reportMiss('h80000140); //Report miss inside window
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.reportMiss('h81000000); //Report miss somewhere far away
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.reportMiss('h80000100); //Report miss back home
p.reportAccess('h80000100, MISS); //Report miss back home
endaction
action
let x <- p.getNextPrefetchAddr;
@@ -336,10 +336,10 @@ module mkSingleWindowTargetPrefetcherTest(Empty);
);
endmodule
module mkStridePCPrefetcher2Test(Empty);
module mkStridePCPrefetcherTest(Empty);
//let p <- mkMultipleWindowPrefetcher;
//TODO pass in value of cachelinesinrange
let p <- mkStridePCPrefetcher2;
let p <- mkStridePCPrefetcher;
mkAutoFSM(
seq
// ----- Send misses and stuff to one window -----
@@ -406,75 +406,3 @@ module mkStridePCPrefetcher2Test(Empty);
endseq
);
endmodule
module mkStridePCPrefetcherTest(Empty);
//let p <- mkMultipleWindowPrefetcher;
//TODO pass in value of cachelinesinrange
let p <- mkStridePCPrefetcher;
mkAutoFSM(
seq
// ----- Send misses and stuff to one window -----
action
p.reportAccess('h80000040, 'h0069, MISS);
endaction
action
p.reportAccess('h80000080, 'h0069, HIT);
endaction
action
p.reportAccess('h800000a0, 'h0069, HIT);
endaction
action
p.reportAccess('h800000c0, 'h0069, MISS);
endaction
action
let x <- p.getNextPrefetchAddr;
doAssert(x == 'h80000100, "test fail!");
endaction
action
let x <- p.getNextPrefetchAddr;
doAssert(x == 'h80000140, "test fail!");
endaction
action
p.reportAccess('h800000e0, 'h0069, MISS);
endaction
action
let x <- p.getNextPrefetchAddr;
doAssert(x == 'h80000180, "test fail!");
endaction
action
p.reportAccess('h80000100, 'h0069, MISS);
endaction
action
p.reportAccess('h80000120, 'h0069, MISS);
endaction
action
p.reportAccess('h80000140, 'h0069, MISS);
endaction
action
let x <- p.getNextPrefetchAddr;
doAssert(x == 'h80000160, "test fail!");
endaction
action
p.reportAccess('h90000040, 'h0000, MISS);
endaction
action
p.reportAccess('h90000140, 'h0000, MISS);
endaction
action
p.reportAccess('h90000240, 'h0000, MISS);
endaction
action
let x <- p.getNextPrefetchAddr;
doAssert(x == 'h90000340, "test fail!");
endaction
action
p.reportAccess('h80000160, 'h0069, MISS);
endaction
action
let x <- p.getNextPrefetchAddr;
doAssert(x == 'h80000180, "test fail!");
endaction
endseq
);
endmodule