Changes to make Prefetcher more deterministic, and also to report schedules.

This commit is contained in:
Jonathan Woodruff
2025-04-28 17:52:17 +01:00
parent 03b8face1e
commit f964e1dd2c

View File

@@ -36,6 +36,8 @@ import Vector::*;
import BuildVector::*; import BuildVector::*;
import ProcTypes::*; import ProcTypes::*;
Bool verbose = False;
typedef enum { typedef enum {
HIT = 1'b0, MISS = 1'b1 HIT = 1'b0, MISS = 1'b1
} HitOrMiss deriving (Bits, Eq, FShow); } HitOrMiss deriving (Bits, Eq, FShow);
@@ -193,7 +195,7 @@ module mkSingleWindowL1LLPrefetcher(Prefetcher);
method ActionValue#(Addr) getNextPrefetchAddr if (nextToAsk != rangeEnd); method ActionValue#(Addr) getNextPrefetchAddr if (nextToAsk != rangeEnd);
nextToAsk <= nextToAsk + 1; nextToAsk <= nextToAsk + 1;
let retAddr = Addr'{nextToAsk, '0}; //extend cache line address to regular address let retAddr = Addr'{nextToAsk, '0}; //extend cache line address to regular address
if(verbose) $display("%t Prefetcher getNextPrefetchAddr requesting %h", $time, retAddr); if (verbose) $display("%t Prefetcher getNextPrefetchAddr requesting %h", $time, retAddr);
return retAddr; return retAddr;
endmethod endmethod
endmodule endmodule
@@ -446,13 +448,13 @@ module mkTargetTable(TargetTable#(narrowTableSize, wideTableSize)) provisos
if (narrowTable[narrowIdx][0] matches tagged Valid .entry if (narrowTable[narrowIdx][0] matches tagged Valid .entry
&&& entry.tag == addr[31:valueOf(narrowTableIdxBits)]) begin &&& entry.tag == addr[31:valueOf(narrowTableIdxBits)]) begin
narrowTable[narrowIdx][0] <= Invalid; narrowTable[narrowIdx][0] <= Invalid;
//$display("%t found narrow table entry %h", $time, addr + signExtend(pack(entry.distance))); //if (verbose) $display("%t found narrow table entry %h", $time, addr + signExtend(pack(entry.distance)));
return Valid(addr + signExtend(pack(entry.distance))); return Valid(addr + signExtend(pack(entry.distance)));
end end
else if (wideTable[wideIdx][0] matches tagged Valid .entry else if (wideTable[wideIdx][0] matches tagged Valid .entry
&&& entry.tag == addr[31:valueOf(wideTableIdxBits)]) begin &&& entry.tag == addr[31:valueOf(wideTableIdxBits)]) begin
wideTable[wideIdx][0] <= Invalid; wideTable[wideIdx][0] <= Invalid;
//$display("%t found wide table entry %h", $time, entry.target); //if (verbose) $display("%t found wide table entry %h", $time, entry.target);
return Valid(entry.target); return Valid(entry.target);
end end
else else
@@ -620,12 +622,12 @@ module mkTargetTableDouble(TargetTableDouble#(narrowTableSize, wideTableSize)) p
actionvalue actionvalue
if (narrowWrapped matches tagged Valid .narrow if (narrowWrapped matches tagged Valid .narrow
&&& narrowTagMatch(addrHash, narrow)) begin &&& narrowTagMatch(addrHash, narrow)) begin
//$display("%t found narrow table entry %h", $time, addr + signExtend(pack(narrow.distance))); //if (verbose) $display("%t found narrow table entry %h", $time, addr + signExtend(pack(narrow.distance)));
return Valid(addr + signExtend(pack(narrow.distance))); return Valid(addr + signExtend(pack(narrow.distance)));
end end
else if (wideWrapped matches tagged Valid .wide else if (wideWrapped matches tagged Valid .wide
&&& wideTagMatch(addrHash, wide)) begin &&& wideTagMatch(addrHash, wide)) begin
//$display("%t found wide table entry %h", $time, wide.target); //if (verbose) $display("%t found wide table entry %h", $time, wide.target);
return Valid(wide.target); return Valid(wide.target);
end end
else else
@@ -690,7 +692,7 @@ module mkTargetTableDouble(TargetTableDouble#(narrowTableSize, wideTableSize)) p
entry.distance = truncate(distance); entry.distance = truncate(distance);
if (Valid(entry) != lastMissNarrowMRUEntry) begin if (Valid(entry) != lastMissNarrowMRUEntry) begin
//$display("%t Recording miss -- modifying narrow table", $time); //if (verbose) $display("%t Recording miss -- modifying narrow table", $time);
//Maintain the property that one address can only have //Maintain the property that one address can only have
// at most 2 of 4 table entries for it. // at most 2 of 4 table entries for it.
//Shift narrow table entries down, storing in MRU. //Shift narrow table entries down, storing in MRU.
@@ -710,7 +712,7 @@ module mkTargetTableDouble(TargetTableDouble#(narrowTableSize, wideTableSize)) p
entry.target = currAddr; entry.target = currAddr;
if (Valid(entry) != lastMissWideMRUEntry) begin if (Valid(entry) != lastMissWideMRUEntry) begin
//$display("%t Recording miss -- modifying wide table", $time); //if (verbose) $display("%t Recording miss -- modifying wide table", $time);
wideTableMRU.wrReq(idx, Valid(entry)); wideTableMRU.wrReq(idx, Valid(entry));
wideTableLRU.wrReq(idx, lastMissWideMRUEntry); wideTableLRU.wrReq(idx, lastMissWideMRUEntry);
Bit#(narrowTableIdxBits) narrowIdx = truncate(lastMissAddrHash); Bit#(narrowTableIdxBits) narrowIdx = truncate(lastMissAddrHash);
@@ -748,9 +750,9 @@ module mkTargetTableDouble(TargetTableDouble#(narrowTableSize, wideTableSize)) p
//Update the entries for the last miss to point to this one //Update the entries for the last miss to point to this one
writeMissEntry(addr); writeMissEntry(addr);
//Save the raw table entries //Save the raw table entries
//$display("idx: %x", addrHash); //if (verbose) $display("idx: %x", addrHash);
//$display("%t Read resp: nMRU: ", fshow(narrowTableMRU.rdResp), "wMRU: ", fshow(wideTableMRU.rdResp)); //if (verbose) $display("%t Read resp: nMRU: ", fshow(narrowTableMRU.rdResp), "wMRU: ", fshow(wideTableMRU.rdResp));
//$display("%t Read resp: nLRU: ", fshow(narrowTableLRU.rdResp), "wLRU: ", fshow(wideTableLRU.rdResp)); //if (verbose) $display("%t Read resp: nLRU: ", fshow(narrowTableLRU.rdResp), "wLRU: ", fshow(wideTableLRU.rdResp));
lastMissWideMRUEntry <= wideTableMRU.rdResp; lastMissWideMRUEntry <= wideTableMRU.rdResp;
lastMissNarrowMRUEntry <= narrowTableMRU.rdResp; lastMissNarrowMRUEntry <= narrowTableMRU.rdResp;
lastMissWideLRUEntry <= wideTableLRU.rdResp; lastMissWideLRUEntry <= wideTableLRU.rdResp;
@@ -1036,7 +1038,7 @@ module mkBRAMMarkovPrefetcher(Prefetcher) provisos
if (hitMiss == MISS) begin if (hitMiss == MISS) begin
//Don't start markov chain if its very recent //Don't start markov chain if its very recent
//$display("%t Prefetcher start new chain with %h", $time, addr); //if (verbose) $display("%t Prefetcher start new chain with %h", $time, addr);
chainNextToLookup <= cl; chainNextToLookup <= cl;
chainNumberToPrefetch <= fromInteger(valueOf(maxChainLength)); chainNumberToPrefetch <= fromInteger(valueOf(maxChainLength));
end end
@@ -1291,7 +1293,7 @@ provisos(
strideTable.deqRdResp; strideTable.deqRdResp;
StrideEntry seNext = se; StrideEntry seNext = se;
Bit#(13) observedStride = {1'b0, addr[11:0]} - {1'b0, se.lastAddr}; Bit#(13) observedStride = {1'b0, addr[11:0]} - {1'b0, se.lastAddr};
if (verbose) $writeh("%t Stride Prefetcher updateStrideEntry ", $time, if (verbose) $display("%t Stride Prefetcher updateStrideEntry ", $time,
fshow(hitMiss), " ", addr, fshow(hitMiss), " ", addr,
". Entry ", index, " state is ", fshow(se.state)); ". Entry ", index, " state is ", fshow(se.state));
if (se.state == EMPTY) begin if (se.state == EMPTY) begin
@@ -1415,7 +1417,7 @@ provisos(
); );
Bool verbose = False; Bool verbose = False;
RWBramCore#(strideTableIndexT, StrideEntry2) strideTable <- mkRWBramCoreForwarded; RWBramCore#(strideTableIndexT, StrideEntry2) strideTable <- mkRWBramCoreForwarded;
FIFOF#(Tuple3#(Addr, Bit#(16), HitOrMiss)) memAccesses <- mkSizedBypassFIFOF(8); FIFOF#(Tuple3#(Addr, Bit#(16), HitOrMiss)) memAccesses <- mkUGSizedFIFOF(8);
Reg#(Tuple3#(Addr, Bit#(16), HitOrMiss)) rdRespEntry <- mkReg(?); Reg#(Tuple3#(Addr, Bit#(16), HitOrMiss)) rdRespEntry <- mkReg(?);
Fifo#(8, Addr) addrToPrefetch <- mkOverflowPipelineFifo; Fifo#(8, Addr) addrToPrefetch <- mkOverflowPipelineFifo;
@@ -1423,7 +1425,7 @@ provisos(
Reg#(Maybe#(Bit#(2))) cLinesPrefetchedLatest <- mkReg(?); Reg#(Maybe#(Bit#(2))) cLinesPrefetchedLatest <- mkReg(?);
PulseWire holdReadReq <- mkPulseWire; PulseWire holdReadReq <- mkPulseWire;
rule sendReadReq if (!holdReadReq); rule sendReadReq if (!holdReadReq && memAccesses.notEmpty);
match {.addr, .pcHash, .hitMiss} = memAccesses.first; match {.addr, .pcHash, .hitMiss} = memAccesses.first;
if (verbose) $display("%t Sending read req for %h!", $time, pcHash); if (verbose) $display("%t Sending read req for %h!", $time, pcHash);
strideTable.rdReq(truncate(pcHash)); strideTable.rdReq(truncate(pcHash));
@@ -1445,7 +1447,7 @@ provisos(
strideTable.deqRdResp; strideTable.deqRdResp;
StrideEntry2 seNext = se; StrideEntry2 seNext = se;
Int#(12) observedStride = unpack(addr[11:0] - se.lastAddr); Int#(12) observedStride = unpack(addr[11:0] - se.lastAddr);
if (verbose) $writeh("%t Stride Prefetcher updateStrideEntry ", $time, if (verbose) $display("%t Stride Prefetcher updateStrideEntry ", $time,
fshow(hitMiss), " ", addr, fshow(hitMiss), " ", addr,
". Entry ", index, " state is ", fshow(se.state)); ". Entry ", index, " state is ", fshow(se.state));
if (se.state == INIT && observedStride != 0) begin if (se.state == INIT && observedStride != 0) begin
@@ -1548,7 +1550,7 @@ provisos(
endrule endrule
method Action reportAccess(Addr addr, Bit#(16) pcHash, HitOrMiss hitMiss); method Action reportAccess(Addr addr, Bit#(16) pcHash, HitOrMiss hitMiss);
memAccesses.enq(tuple3 (addr, pcHash, hitMiss)); if (memAccesses.notFull) memAccesses.enq(tuple3 (addr, pcHash, hitMiss));
endmethod endmethod
method ActionValue#(Addr) getNextPrefetchAddr; method ActionValue#(Addr) getNextPrefetchAddr;
@@ -1726,7 +1728,7 @@ provisos(
strideTable.deqRdResp; strideTable.deqRdResp;
StrideEntryAdaptive seNext = se; StrideEntryAdaptive seNext = se;
Bit#(13) observedStride = {1'b0, addr[11:0]} - {1'b0, se.lastAddr}; Bit#(13) observedStride = {1'b0, addr[11:0]} - {1'b0, se.lastAddr};
if (verbose) $writeh("%t Stride Prefetcher updateStrideEntry ", $time, if (verbose) $display("%t Stride Prefetcher updateStrideEntry ", $time,
fshow(hitMiss), " ", addr, fshow(hitMiss), " ", addr,
". Entry ", index, " state is ", fshow(se.state)); ". Entry ", index, " state is ", fshow(se.state));
if (se.state == EMPTY) begin if (se.state == EMPTY) begin
@@ -1946,7 +1948,7 @@ module mkLLIPrefetcher(Prefetcher);
`endif `endif
return m; return m;
endmodule endmodule
(* synthesize *)
module mkL1DPrefetcher(PCPrefetcher); module mkL1DPrefetcher(PCPrefetcher);
`ifdef DATA_PREFETCHER_IN_L1 `ifdef DATA_PREFETCHER_IN_L1
`ifdef DATA_PREFETCHER_BLOCK `ifdef DATA_PREFETCHER_BLOCK