Cleanup: remove non-BRAM prefetchers
This commit is contained in:
@@ -576,59 +576,6 @@ module mkBRAMSingleWindowTargetPrefetcher(Prefetcher) provisos
|
||||
endmethod
|
||||
endmodule
|
||||
|
||||
module mkSingleWindowTargetPrefetcher(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);
|
||||
TargetTable#(64, 8) targetTable <- mkTargetTable;
|
||||
//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;
|
||||
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.set(lastChildRequest, cl);
|
||||
end
|
||||
lastChildRequest <= cl;
|
||||
endmethod
|
||||
|
||||
method ActionValue#(Addr) getNextPrefetchAddr if (nextToAsk != rangeEnd);
|
||||
Addr retAddr;
|
||||
let lastAsked = nextToAsk-1;
|
||||
let entryMaybe <- targetTable.getAndRemove(lastAsked);
|
||||
if (entryMaybe matches tagged Valid .cl) 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
|
||||
retAddr = {cl, '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};
|
||||
$display("%t Prefetcher getNextPrefetchAddr requesting next-line %h", $time, retAddr);
|
||||
end
|
||||
return retAddr;
|
||||
endmethod
|
||||
endmodule
|
||||
|
||||
module mkBRAMMultiWindowTargetPrefetcher(Prefetcher)
|
||||
provisos(
|
||||
NumAlias#(numWindows, 4),
|
||||
@@ -761,123 +708,6 @@ provisos(
|
||||
|
||||
endmodule
|
||||
|
||||
module mkMultiWindowTargetPrefetcher(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);
|
||||
TargetTable#(64, 8) targetTable <- mkTargetTable;
|
||||
|
||||
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.set(lastChildRequest, cl);
|
||||
end
|
||||
lastChildRequest <= cl;
|
||||
endmethod
|
||||
|
||||
method ActionValue#(Addr) getNextPrefetchAddr
|
||||
if (streams[shiftReg[0]].nextToAsk != streams[shiftReg[0]].rangeEnd);
|
||||
|
||||
Addr retAddr;
|
||||
let lastAsked = streams[shiftReg[0]].nextToAsk-1;
|
||||
let clMaybe <- targetTable.getAndRemove(lastAsked);
|
||||
if (clMaybe matches tagged Valid .cl) 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
|
||||
retAddr = {cl, '0};
|
||||
$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 mkBRAMMarkovPrefetcher(Prefetcher) provisos
|
||||
(
|
||||
NumAlias#(maxChainLength, 2),
|
||||
@@ -942,59 +772,6 @@ module mkBRAMMarkovPrefetcher(Prefetcher) provisos
|
||||
|
||||
endmodule
|
||||
|
||||
module mkMarkovPrefetcher(Prefetcher) provisos
|
||||
(
|
||||
NumAlias#(maxChainLength, 2),
|
||||
Alias#(chainLengthT, Bit#(TLog#(TAdd#(maxChainLength,1))))
|
||||
);
|
||||
Reg#(LineAddr) lastLastChildRequest <- mkReg(0);
|
||||
Reg#(LineAddr) lastChildRequest <- mkReg(0);
|
||||
TargetTable#(64, 8) targetTable <- mkTargetTable;
|
||||
|
||||
// Stores how many prefetches we can still do in the current chain
|
||||
Reg#(chainLengthT) chainNumberToPrefetch <- mkReg(0);
|
||||
Reg#(LineAddr) chainNextToPrefetch <- mkReg(?);
|
||||
|
||||
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.set(lastChildRequest, cl);
|
||||
end
|
||||
lastChildRequest <= cl;
|
||||
lastLastChildRequest <= lastChildRequest;
|
||||
|
||||
if (lastLastChildRequest != cl) begin
|
||||
//Don't start markov chain if its very recent
|
||||
let x <- targetTable.getAndRemove(cl);
|
||||
if (x matches tagged Valid .nextCl) begin
|
||||
//Start new prefetch chain
|
||||
$display("%t Prefetcher start new chain with %h", $time, addr);
|
||||
chainNextToPrefetch <= nextCl;
|
||||
chainNumberToPrefetch <= fromInteger(valueOf(maxChainLength));
|
||||
end
|
||||
end
|
||||
endmethod
|
||||
|
||||
method ActionValue#(Addr) getNextPrefetchAddr if
|
||||
(chainNumberToPrefetch != 0);
|
||||
|
||||
let x <- targetTable.getAndRemove(chainNextToPrefetch);
|
||||
if (x matches tagged Valid .nextCl) begin
|
||||
chainNumberToPrefetch <= chainNumberToPrefetch - 1;
|
||||
chainNextToPrefetch <= nextCl;
|
||||
end
|
||||
else begin
|
||||
//End chain here
|
||||
chainNumberToPrefetch <= 0;
|
||||
end
|
||||
Addr retAddr = {chainNextToPrefetch, '0};
|
||||
$display("%t Prefetcher getNextPrefetchAddr requesting chain entry %h", $time, retAddr);
|
||||
return retAddr;
|
||||
endmethod
|
||||
endmodule
|
||||
|
||||
module mkBlockPrefetcher(Prefetcher) provisos (
|
||||
NumAlias#(numLinesEachWay, 1),
|
||||
Alias#(lineCountT, Bit#(TLog#(TAdd#(numLinesEachWay, 1))))
|
||||
@@ -1077,120 +854,6 @@ typedef struct {
|
||||
Bit#(4) cLinesPrefetched; //Stores how many cache lines have been prefetched for this instruction
|
||||
} StrideEntry deriving (Bits, Eq, FShow);
|
||||
|
||||
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#(StrideEntry)) strideTable <- replicateM(mkReg(unpack(0)));
|
||||
|
||||
function Maybe#(historyVecIndexT) getNextPrefetchHistoryIndex;
|
||||
function Bool canPrefetch(Tuple2#(strideTableIndexT, Addr) entry);
|
||||
strideTableIndexT idx = tpl_1(entry);
|
||||
return (strideTable[idx].state == STEADY &&
|
||||
strideTable[idx].cLinesPrefetched !=
|
||||
fromInteger(valueof(cLinesAheadToPrefetch)));
|
||||
endfunction
|
||||
|
||||
//Find first entry that allows more prefetches
|
||||
case (findIndex(canPrefetch, historyVec)) matches
|
||||
tagged Valid .historyIdx: return Valid(pack(historyIdx));
|
||||
Invalid: return Invalid;
|
||||
endcase
|
||||
endfunction
|
||||
|
||||
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;
|
||||
Bit#(13) observedStride = {1'b0, addr[11:0]} - {1'b0, se.lastAddr};
|
||||
$writeh("%t Stride Prefetcher reportAccess ", $time,
|
||||
fshow(hitMiss), " ", addr,
|
||||
". Entry ", index, " state is ", fshow(se.state));
|
||||
if (se.state == EMPTY) begin
|
||||
if (hitMiss == MISS) begin
|
||||
seNext.lastAddr = truncate(addr);
|
||||
seNext.state = INIT;
|
||||
$display(", allocate entry");
|
||||
end
|
||||
else begin
|
||||
$display(", ignore");
|
||||
end
|
||||
end
|
||||
else if (se.state == INIT && observedStride != 0) begin
|
||||
seNext.stride = observedStride;
|
||||
seNext.state = TRANSIENT;
|
||||
seNext.lastAddr = truncate(addr);
|
||||
$display(", set stride to %h", seNext.stride);
|
||||
end
|
||||
else if ((se.state == TRANSIENT || se.state == STEADY) && observedStride != 0) begin
|
||||
if (observedStride == se.stride) begin
|
||||
if (se.state == TRANSIENT) begin
|
||||
//Here we transition from TRANSIENT to STEADY, so init this field
|
||||
seNext.cLinesPrefetched = 0;
|
||||
end
|
||||
else begin
|
||||
//state == STEADY
|
||||
if (se.lastAddr[11:6] != addr[11:6]) begin
|
||||
//This means we have crossed a cache line since last access
|
||||
seNext.cLinesPrefetched =
|
||||
(se.cLinesPrefetched == 0) ? 0 : se.cLinesPrefetched - 1;
|
||||
end
|
||||
end
|
||||
seNext.state = STEADY;
|
||||
seNext.lastAddr = truncate(addr);
|
||||
historyVec <= shiftInAt0(historyVec, tuple2(index, addr));
|
||||
$display(", stride %h is confirmed!", seNext.stride);
|
||||
end
|
||||
else begin
|
||||
seNext.state = TRANSIENT;
|
||||
seNext.stride = observedStride;
|
||||
seNext.lastAddr = truncate(addr);
|
||||
$display(", old stride is broken! New stride: %h", seNext.stride);
|
||||
end
|
||||
end
|
||||
else
|
||||
$display("");
|
||||
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
|
||||
|
||||
module mkBRAMStridePCPrefetcher(PCPrefetcher)
|
||||
provisos(
|
||||
NumAlias#(strideTableSize, 512),
|
||||
|
||||
Reference in New Issue
Block a user