Implemented double target table and the corresponding markov prefetcher
This commit is contained in:
@@ -77,7 +77,7 @@ endif
|
||||
ifeq (,$(filter $(DATA_PREFETCHER_LOCATION),NONE L1 L1LL LL))
|
||||
$(error unsupported DATA_PREFETCHER_LOCATION)
|
||||
endif
|
||||
ifeq (,$(filter $(DATA_PREFETCHER_TYPE),MARKOV MARKOV_ON_HIT BLOCK STRIDE STRIDE_ADAPTIVE))
|
||||
ifeq (,$(filter $(DATA_PREFETCHER_TYPE),MARKOV MARKOV_ON_HIT MARKOV_ON_HIT_2 BLOCK STRIDE STRIDE_ADAPTIVE))
|
||||
$(error unsupported DATA_PREFETCHER_TYPE)
|
||||
endif
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import ISA_Decls :: *;
|
||||
import CrossBar::*;
|
||||
import GetPut::*;
|
||||
import RWBramCore::*;
|
||||
import FIFO::*;
|
||||
import Fifos::*;
|
||||
@@ -9,6 +11,7 @@ import CacheUtils::*;
|
||||
import CCTypes::*;
|
||||
import Types::*;
|
||||
import Vector::*;
|
||||
import BuildVector::*;
|
||||
import ProcTypes::*;
|
||||
|
||||
typedef enum {
|
||||
@@ -512,6 +515,221 @@ module mkTargetTableBRAM(TargetTableBRAM#(narrowTableSize, wideTableSize)) provi
|
||||
endmethod
|
||||
endmodule
|
||||
|
||||
interface TargetTableDouble#(numeric type narrowTableSize, numeric type wideTableSize);
|
||||
method Action sendReadWriteReq(LineAddr addr, HitOrMiss hitMiss);
|
||||
method ActionValue#(Tuple2#(Maybe#(LineAddr), Maybe#(LineAddr))) readResp();
|
||||
endinterface
|
||||
|
||||
module mkTargetTableDouble(TargetTableDouble#(narrowTableSize, wideTableSize)) provisos
|
||||
(
|
||||
NumAlias#(narrowTableIdxBits, TLog#(narrowTableSize)),
|
||||
NumAlias#(wideTableIdxBits, TLog#(wideTableSize)),
|
||||
NumAlias#(narrowTableTagBits, TSub#(24, narrowTableIdxBits)),
|
||||
NumAlias#(wideTableTagBits, TSub#(24, wideTableIdxBits)),
|
||||
NumAlias#(narrowDistanceBits, 10),
|
||||
NumAlias#(narrowMaxDistanceAbs, TExp#(TSub#(narrowDistanceBits, 1))),
|
||||
Alias#(narrowTargetEntryT, NarrowTargetEntry#(narrowTableTagBits, narrowDistanceBits)),
|
||||
Alias#(wideTargetEntryT, WideTargetEntry#(wideTableTagBits)),
|
||||
Add#(a__, TLog#(narrowTableSize), 32),
|
||||
Add#(b__, TLog#(narrowTableSize), 58),
|
||||
Add#(c__, TLog#(wideTableSize), 32),
|
||||
Add#(d__, TLog#(wideTableSize), 58)
|
||||
);
|
||||
|
||||
//on any request, read all 4 tables. get prefetches. if it's a miss save both MRU entries.
|
||||
//on a miss, perform a regular table write to the MRU table. if it's a narrow write, write the old MRU narrow entry to the LRU narrow table.
|
||||
//one method, readReq, with parameter isMiss. sends read requests to all 4 tables.
|
||||
//also saves read address
|
||||
//one method setMRU.
|
||||
// sends a write request with the previous miss address to the current miss address.
|
||||
// if narrow table write, then also write the old MRU narrow entry to the LRU narrow table.
|
||||
//one method, getPrefetches, which also saves all results if isMiss true.
|
||||
RWBramCore#(Bit#(narrowTableIdxBits), Maybe#(narrowTargetEntryT)) narrowTableMRU <- mkRWBramCoreForwarded;
|
||||
RWBramCore#(Bit#(wideTableIdxBits), Maybe#(wideTargetEntryT)) wideTableMRU <- mkRWBramCoreForwarded;
|
||||
RWBramCore#(Bit#(narrowTableIdxBits), Maybe#(narrowTargetEntryT)) narrowTableLRU <- mkRWBramCoreForwarded;
|
||||
RWBramCore#(Bit#(wideTableIdxBits), Maybe#(wideTargetEntryT)) wideTableLRU <- mkRWBramCoreForwarded;
|
||||
Reg#(LineAddr) readReqLineAddr <- mkReg(0);
|
||||
Reg#(HitOrMiss) readReqHitMiss <- mkReg(HIT);
|
||||
|
||||
Reg#(LineAddr) lastMissAddr <- mkReg(0);
|
||||
Reg#(Maybe#(wideTargetEntryT)) lastMissWideMRUEntry <- mkReg(unpack(0));
|
||||
Reg#(Maybe#(narrowTargetEntryT)) lastMissNarrowMRUEntry <- mkReg(unpack(0));
|
||||
Reg#(Maybe#(wideTargetEntryT)) lastMissWideLRUEntry <- mkReg(unpack(0));
|
||||
Reg#(Maybe#(narrowTargetEntryT)) lastMissNarrowLRUEntry <- mkReg(unpack(0));
|
||||
|
||||
function Bool narrowTagMatch(Bit#(32) addrHash, narrowTargetEntryT narrow);
|
||||
return narrow.tag == addrHash[23:valueOf(narrowTableIdxBits)];
|
||||
endfunction
|
||||
|
||||
function Bool narrowTagMatchMaybe(Bit#(32) addrHash, Maybe#(narrowTargetEntryT) narrowMaybe);
|
||||
if (narrowMaybe matches tagged Valid .narrow &&& narrowTagMatch(addrHash, narrow))
|
||||
return True;
|
||||
else
|
||||
return False;
|
||||
endfunction
|
||||
|
||||
function Bool wideTagMatch(Bit#(32) addrHash, wideTargetEntryT wide);
|
||||
return wide.tag == addrHash[23:valueOf(wideTableIdxBits)];
|
||||
endfunction
|
||||
|
||||
function Bool wideTagMatchMaybe(Bit#(32) addrHash, Maybe#(wideTargetEntryT) wideMaybe);
|
||||
if (wideMaybe matches tagged Valid .wide &&& wideTagMatch(addrHash, wide))
|
||||
return True;
|
||||
else
|
||||
return False;
|
||||
endfunction
|
||||
|
||||
|
||||
function ActionValue#(Maybe#(LineAddr))
|
||||
checkReadResp(LineAddr addr, Bit#(32) addrHash, Maybe#(narrowTargetEntryT) narrowWrapped, Maybe#(wideTargetEntryT) wideWrapped);
|
||||
actionvalue
|
||||
if (narrowWrapped matches tagged Valid .narrow
|
||||
&&& narrowTagMatch(addrHash, narrow)) begin
|
||||
//$display("%t found narrow table entry %h", $time, addr + signExtend(pack(narrow.distance)));
|
||||
return Valid(addr + signExtend(pack(narrow.distance)));
|
||||
end
|
||||
else if (wideWrapped matches tagged Valid .wide
|
||||
&&& wideTagMatch(addrHash, wide)) begin
|
||||
//$display("%t found wide table entry %h", $time, wide.target);
|
||||
return Valid(wide.target);
|
||||
end
|
||||
else
|
||||
return Invalid;
|
||||
endactionvalue
|
||||
endfunction
|
||||
|
||||
function Action updateTables(
|
||||
Bit#(32) lastMissAddrHash,
|
||||
Bit#(idxBits) idx,
|
||||
RWBramCore#(Bit#(idxBits), Maybe#(otherEntryT)) otherMRU,
|
||||
RWBramCore#(Bit#(idxBits), Maybe#(otherEntryT)) otherLRU,
|
||||
function Bool otherTagMatch(Bit#(32) addrHash, Maybe#(otherEntryT) entry),
|
||||
function Bool myTagMatch(Bit#(32) addrHash, Maybe#(myEntryT) entry),
|
||||
Maybe#(otherEntryT) otherMRUEntry,
|
||||
Maybe#(otherEntryT) otherLRUEntry,
|
||||
Maybe#(myEntryT) myMRUEntry
|
||||
);
|
||||
action
|
||||
//Am inserting a new table entry into "my" table.
|
||||
//So need to re-order the entries in the "other" table.
|
||||
//To maintain the property that can't have both a narrow and wide entry in the same recency table.
|
||||
if (otherTagMatch(lastMissAddrHash, otherMRUEntry)) begin
|
||||
//If MRU other entry matches
|
||||
if (otherTagMatch(lastMissAddrHash, otherLRUEntry)) begin
|
||||
//If LRU other entry matches
|
||||
// Shift other down
|
||||
otherMRU.wrReq(idx, Invalid);
|
||||
otherLRU.wrReq(idx, otherMRUEntry);
|
||||
end
|
||||
else begin
|
||||
//If LRU other entry doesnt match
|
||||
// Switch other entries around
|
||||
otherMRU.wrReq(idx, otherLRUEntry);
|
||||
otherLRU.wrReq(idx, otherMRUEntry);
|
||||
end
|
||||
end
|
||||
else begin
|
||||
//If other MRU entry doesn't match
|
||||
if (otherTagMatch(lastMissAddrHash, otherLRUEntry) &&
|
||||
myTagMatch(lastMissAddrHash, myMRUEntry)) begin
|
||||
|
||||
//will shift my MRU entry down, so
|
||||
// invalidate other LRU entry
|
||||
otherLRU.wrReq(idx, Invalid);
|
||||
end
|
||||
end
|
||||
endaction
|
||||
endfunction
|
||||
|
||||
function Action writeMissEntry(LineAddr currAddr);
|
||||
action
|
||||
let distance = currAddr - lastMissAddr;
|
||||
Bit#(32) lastMissAddrHash = hash(lastMissAddr);
|
||||
$display("%t Recording miss from %x to %x", $time, lastMissAddr, currAddr);
|
||||
if (abs(distance) < fromInteger(valueOf(narrowMaxDistanceAbs))) begin
|
||||
//Store lastMissAddr -> currAddr in narrow MRU table
|
||||
|
||||
Bit#(narrowTableIdxBits) idx = truncate(lastMissAddrHash);
|
||||
narrowTargetEntryT entry;
|
||||
entry.tag = lastMissAddrHash[23:valueOf(narrowTableIdxBits)];
|
||||
entry.distance = truncate(distance);
|
||||
|
||||
if (Valid(entry) != lastMissNarrowMRUEntry) begin
|
||||
//$display("%t Recording miss -- modifying narrow table", $time);
|
||||
//Maintain the property that one address can only have
|
||||
// at most 2 of 4 table entries for it.
|
||||
//Shift narrow table entries down, storing in MRU.
|
||||
//But only if the entry was not already the MRU entry.
|
||||
narrowTableMRU.wrReq(idx, Valid(entry));
|
||||
narrowTableLRU.wrReq(idx, lastMissNarrowMRUEntry);
|
||||
Bit#(wideTableIdxBits) wideIdx = truncate(lastMissAddrHash);
|
||||
updateTables(lastMissAddrHash, wideIdx, wideTableMRU, wideTableLRU, wideTagMatchMaybe, narrowTagMatchMaybe,
|
||||
lastMissWideMRUEntry, lastMissWideLRUEntry, lastMissNarrowMRUEntry);
|
||||
end
|
||||
end
|
||||
else begin
|
||||
//Store lastMissAddr -> currAddr in wide MRU table
|
||||
wideTargetEntryT entry;
|
||||
Bit#(wideTableIdxBits) idx = truncate(lastMissAddrHash);
|
||||
entry.tag = lastMissAddrHash[23:valueOf(wideTableIdxBits)];
|
||||
entry.target = currAddr;
|
||||
|
||||
if (Valid(entry) != lastMissWideMRUEntry) begin
|
||||
//$display("%t Recording miss -- modifying wide table", $time);
|
||||
wideTableMRU.wrReq(idx, Valid(entry));
|
||||
wideTableLRU.wrReq(idx, lastMissWideMRUEntry);
|
||||
Bit#(narrowTableIdxBits) narrowIdx = truncate(lastMissAddrHash);
|
||||
updateTables(lastMissAddrHash, narrowIdx, narrowTableMRU, narrowTableLRU, narrowTagMatchMaybe, wideTagMatchMaybe,
|
||||
lastMissNarrowMRUEntry, lastMissNarrowLRUEntry, lastMissWideMRUEntry);
|
||||
end
|
||||
end
|
||||
endaction
|
||||
endfunction
|
||||
|
||||
method Action sendReadWriteReq(LineAddr addr, HitOrMiss hitMiss);
|
||||
$display("%t send read write req for %x", $time, addr);
|
||||
Bit#(32) addrHash = hash(addr);
|
||||
Bit#(narrowTableIdxBits) narrowIdx = truncate(addrHash);
|
||||
narrowTableMRU.rdReq(narrowIdx);
|
||||
narrowTableLRU.rdReq(narrowIdx);
|
||||
Bit#(wideTableIdxBits) wideIdx = truncate(addrHash);
|
||||
wideTableMRU.rdReq(wideIdx);
|
||||
wideTableLRU.rdReq(wideIdx);
|
||||
readReqLineAddr <= addr;
|
||||
readReqHitMiss <= hitMiss;
|
||||
endmethod
|
||||
|
||||
|
||||
method ActionValue#(Tuple2#(Maybe#(LineAddr), Maybe#(LineAddr))) readResp();
|
||||
// Returns the read response and if a table had a hit,
|
||||
// sends a write request to clear the entry in that table
|
||||
narrowTableMRU.deqRdResp;
|
||||
narrowTableLRU.deqRdResp;
|
||||
wideTableMRU.deqRdResp;
|
||||
wideTableLRU.deqRdResp;
|
||||
let addr = readReqLineAddr;
|
||||
Bit#(32) addrHash = hash(addr);
|
||||
if (readReqHitMiss == MISS) begin
|
||||
//Update the entries for the last miss to point to this one
|
||||
writeMissEntry(addr);
|
||||
//Save the raw table entries
|
||||
//$display("idx: %x", addrHash);
|
||||
//$display("%t Read resp: nMRU: ", fshow(narrowTableMRU.rdResp), "wMRU: ", fshow(wideTableMRU.rdResp));
|
||||
//$display("%t Read resp: nLRU: ", fshow(narrowTableLRU.rdResp), "wLRU: ", fshow(wideTableLRU.rdResp));
|
||||
lastMissWideMRUEntry <= wideTableMRU.rdResp;
|
||||
lastMissNarrowMRUEntry <= narrowTableMRU.rdResp;
|
||||
lastMissWideLRUEntry <= wideTableLRU.rdResp;
|
||||
lastMissNarrowLRUEntry <= narrowTableLRU.rdResp;
|
||||
lastMissAddr <= addr; // save for future use
|
||||
end
|
||||
let entryMRU <- checkReadResp(addr, addrHash, narrowTableMRU.rdResp, wideTableMRU.rdResp);
|
||||
let entryLRU <- checkReadResp(addr, addrHash, narrowTableLRU.rdResp, wideTableLRU.rdResp);
|
||||
Tuple2#(Maybe#(LineAddr), Maybe#(LineAddr)) retval = tuple2(entryMRU, entryLRU);
|
||||
$display("%t read resp for %x returning ", $time, addr, fshow(retval));
|
||||
return retval;
|
||||
endmethod
|
||||
endmodule
|
||||
|
||||
module mkBRAMSingleWindowTargetPrefetcher(Prefetcher) provisos
|
||||
(
|
||||
NumAlias#(numLastRequests, 16)
|
||||
@@ -852,6 +1070,62 @@ module mkBRAMMarkovOnHitPrefetcher(Prefetcher) provisos
|
||||
|
||||
endmodule
|
||||
|
||||
module mkMarkovOnHit2Prefetcher(Prefetcher) provisos
|
||||
(
|
||||
NumAlias#(maxChainLength, 1),
|
||||
NumAlias#(numLastRequests, 32),
|
||||
Alias#(chainLengthT, Bit#(TLog#(TAdd#(maxChainLength,1))))
|
||||
);
|
||||
Reg#(LineAddr) lastChildRequest <- mkReg(0);
|
||||
Reg#(Vector#(numLastRequests, Bit#(32))) lastAddrRequests <- mkReg(replicate(0));
|
||||
TargetTableDouble#(2048, 256) targetTable <- mkTargetTableDouble;
|
||||
Fifo#(8, LineAddr) highPriorityPrefetches <- mkOverflowBypassFifo;
|
||||
Fifo#(8, LineAddr) lowPriorityPrefetches <- mkOverflowBypassFifo;
|
||||
|
||||
//on reportAccess, read the current address in both tables, and save it
|
||||
// Next cycle, add any found next lines to prefetch queues. Have 2 prefetch queues, High and low priority.
|
||||
// If this was a miss, save as lastMissEntry
|
||||
// And issue a write of table[lastMissEntry] = thisMiss.
|
||||
// but checking for LRU and everything.
|
||||
|
||||
rule addPrefetchesToQueues;
|
||||
match { .highPrio, .lowPrio } <- targetTable.readResp();
|
||||
if (highPrio matches tagged Valid .cl)
|
||||
highPriorityPrefetches.enq(cl);
|
||||
if (lowPrio matches tagged Valid .cl)
|
||||
lowPriorityPrefetches.enq(cl);
|
||||
endrule
|
||||
|
||||
method ActionValue#(Addr) getNextPrefetchAddr
|
||||
if (highPriorityPrefetches.notEmpty || lowPriorityPrefetches.notEmpty);
|
||||
//if (false);
|
||||
Addr retAddr = unpack(0);
|
||||
if (highPriorityPrefetches.notEmpty) begin
|
||||
retAddr = {highPriorityPrefetches.first, '0};
|
||||
highPriorityPrefetches.deq;
|
||||
end
|
||||
else if (lowPriorityPrefetches.notEmpty) begin
|
||||
retAddr = {lowPriorityPrefetches.first, '0};
|
||||
lowPriorityPrefetches.deq;
|
||||
end
|
||||
$display("%t Prefetcher getNextPrefetchAddr requesting chain entry %h", $time, retAddr);
|
||||
return retAddr;
|
||||
endmethod
|
||||
|
||||
method Action reportAccess(Addr addr, HitOrMiss hitMiss);
|
||||
let cl = getLineAddr(addr);
|
||||
if (hitMiss == MISS)
|
||||
$display("%t Prefetcher report MISS %h", $time, addr);
|
||||
|
||||
if (hitMiss == MISS || !elem(hash(cl), lastAddrRequests)) begin
|
||||
//Don't start a markov chain if we started a markov chain with that address recently
|
||||
$display("%t Prefetcher start new chain with %h", $time, addr);
|
||||
targetTable.sendReadWriteReq(cl, hitMiss);
|
||||
lastAddrRequests <= shiftInAt0(lastAddrRequests, hash(cl));
|
||||
end
|
||||
endmethod
|
||||
|
||||
endmodule
|
||||
module mkBlockPrefetcher(Prefetcher) provisos (
|
||||
NumAlias#(numLinesEachWay, 1),
|
||||
Alias#(lineCountT, Bit#(TLog#(TAdd#(numLinesEachWay, 1))))
|
||||
@@ -1582,6 +1856,8 @@ module mkL1DPrefetcher(PCPrefetcher);
|
||||
let m <- mkPCPrefetcherAdapter(mkBRAMMarkovPrefetcher);
|
||||
`elsif DATA_PREFETCHER_MARKOV_ON_HIT
|
||||
let m <- mkPCPrefetcherAdapter(mkBRAMMarkovOnHitPrefetcher);
|
||||
`elsif DATA_PREFETCHER_MARKOV_ON_HIT_2
|
||||
let m <- mkPCPrefetcherAdapter(mkMarkovOnHit2Prefetcher);
|
||||
`endif
|
||||
//let m <- mkPCPrefetcherAdapter(mkAlwaysRequestPrefetcher);
|
||||
`else
|
||||
@@ -1602,6 +1878,8 @@ module mkLLDPrefetcherInL1D(PCPrefetcher);
|
||||
let m <- mkPCPrefetcherAdapter(mkBRAMMarkovPrefetcher);
|
||||
`elsif DATA_PREFETCHER_MARKOV_ON_HIT
|
||||
let m <- mkPCPrefetcherAdapter(mkBRAMMarkovOnHitPrefetcher);
|
||||
`elsif DATA_PREFETCHER_MARKOV_ON_HIT_2
|
||||
let m <- mkPCPrefetcherAdapter(mkMarkovOnHit2Prefetcher);
|
||||
`endif
|
||||
//let m <- mkPCPrefetcherAdapter(mkAlwaysRequestPrefetcher);
|
||||
`else
|
||||
@@ -1622,6 +1900,8 @@ module mkLLDPrefetcher(Prefetcher);
|
||||
let m <- mkBRAMMarkovPrefetcher;
|
||||
`elsif DATA_PREFETCHER_MARKOV_ON_HIT
|
||||
let m <- mkBRAMMarkovOnHitPrefetcher;
|
||||
`elsif DATA_PREFETCHER_MARKOV_ON_HIT_2
|
||||
let m <- mkMarkovOnHit2Prefetcher;
|
||||
`endif
|
||||
//let m <- mkPCPrefetcherAdapter(mkAlwaysRequestPrefetcher);
|
||||
`else
|
||||
|
||||
Reference in New Issue
Block a user