From 4ea9b179715db6f312ef4e2471324ef6d3d5d0d0 Mon Sep 17 00:00:00 2001 From: Karlis Susters Date: Wed, 12 Apr 2023 21:31:08 +0300 Subject: [PATCH 01/12] Minor changes to targettable and instruction target prefetchers --- .../RISCY_OOO/coherence/src/Prefetcher.bsv | 63 +++++++++++-------- 1 file changed, 38 insertions(+), 25 deletions(-) diff --git a/src_Core/RISCY_OOO/coherence/src/Prefetcher.bsv b/src_Core/RISCY_OOO/coherence/src/Prefetcher.bsv index 9f2e0c2..d7adc74 100644 --- a/src_Core/RISCY_OOO/coherence/src/Prefetcher.bsv +++ b/src_Core/RISCY_OOO/coherence/src/Prefetcher.bsv @@ -446,8 +446,8 @@ module mkTargetTableBRAM(TargetTableBRAM#(narrowTableSize, wideTableSize)) provi Add#(c__, TLog#(wideTableSize), 32), Add#(d__, TLog#(wideTableSize), 58) ); - RWBramCore#(Bit#(narrowTableIdxBits), Maybe#(narrowTargetEntryT)) narrowTable <- mkRWBramCoreForwarded; - RWBramCore#(Bit#(wideTableIdxBits), Maybe#(wideTargetEntryT)) wideTable <- mkRWBramCoreForwarded; + RWBramCore#(Bit#(narrowTableIdxBits), Maybe#(narrowTargetEntryT)) narrowTable <- mkRWBramCore; + RWBramCore#(Bit#(wideTableIdxBits), Maybe#(wideTargetEntryT)) wideTable <- mkRWBramCore; Reg#(LineAddr) readReqLineAddr <- mkReg(?); method Action writeReq(LineAddr prevAddr, LineAddr currAddr); @@ -472,9 +472,10 @@ module mkTargetTableBRAM(TargetTableBRAM#(narrowTableSize, wideTableSize)) provi endmethod method Action readReq(LineAddr addr); - Bit#(narrowTableIdxBits) narrowIdx = truncate(addr); + Bit#(32) addrHash = hash(addr); + Bit#(narrowTableIdxBits) narrowIdx = truncate(addrHash); narrowTable.rdReq(narrowIdx); - Bit#(wideTableIdxBits) wideIdx = truncate(addr); + Bit#(wideTableIdxBits) wideIdx = truncate(addrHash); wideTable.rdReq(wideIdx); readReqLineAddr <= addr; endmethod @@ -485,20 +486,21 @@ module mkTargetTableBRAM(TargetTableBRAM#(narrowTableSize, wideTableSize)) provi narrowTable.deqRdResp; wideTable.deqRdResp; let addr = readReqLineAddr; - Bit#(narrowTableIdxBits) narrowIdx = truncate(addr); - Bit#(wideTableIdxBits) wideIdx = truncate(addr); + Bit#(32) addrHash = hash(addr); + Bit#(narrowTableIdxBits) narrowIdx = truncate(addrHash); + Bit#(wideTableIdxBits) wideIdx = truncate(addrHash); if (narrowTable.rdResp matches tagged Valid .entry - &&& entry.tag == addr[23:valueOf(narrowTableIdxBits)]) begin + &&& entry.tag == addrHash[23:valueOf(narrowTableIdxBits)]) begin if (clearEntry) begin - narrowTable.wrReq(narrowIdx, Invalid); + //narrowTable.wrReq(narrowIdx, Invalid); end $display("%t found narrow table entry %h", $time, addr + signExtend(pack(entry.distance))); return Valid(addr + signExtend(pack(entry.distance))); end else if (wideTable.rdResp matches tagged Valid .entry - &&& entry.tag == addr[23:valueOf(wideTableIdxBits)]) begin + &&& entry.tag == addrHash[23:valueOf(wideTableIdxBits)]) begin if (clearEntry) begin - wideTable.wrReq(wideIdx, Invalid); + //wideTable.wrReq(wideIdx, Invalid); end $display("%t found wide table entry %h", $time, entry.target); return Valid(entry.target); @@ -511,30 +513,37 @@ module mkTargetTableBRAM(TargetTableBRAM#(narrowTableSize, wideTableSize)) provi endmodule module mkBRAMSingleWindowTargetPrefetcher(Prefetcher) provisos -(); - Integer cacheLinesInRange = 2; +( + NumAlias#(numLastRequests, 16) +); + Integer cacheLinesInRange = 1; Reg#(LineAddr) rangeEnd <- mkReg(0); //Points to one CLine after end of range Reg#(LineAddr) nextToAsk <- mkReg(0); + Reg#(LineAddr) lastChildRequest <- mkReg(0); - TargetTableBRAM#(64, 8) targetTable <- mkTargetTableBRAM; + TargetTableBRAM#(1024, 128) targetTable <- mkTargetTableBRAM; FIFOF#(LineAddr) targetTableReadResp <- mkBypassFIFOF; + Reg#(Vector#(numLastRequests, Bit#(32))) lastTargetRequests <- mkReg(replicate(0)); + rule sendReadReq; - let lastAsked = nextToAsk-1; - targetTable.readReq(lastAsked); + if (!elem(hash(lastChildRequest), lastTargetRequests)) begin + targetTable.readReq(lastChildRequest); + $display("%t Prefetcher sending target read request for %h", $time, lastChildRequest); + lastTargetRequests <= shiftInAt0(lastTargetRequests, hash(lastChildRequest)); + end endrule rule getReadResp; - let res <- targetTable.readResp(True); + let res <- targetTable.readResp(False); if (res matches tagged Valid .cline) begin - //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 targetTableReadResp.enq(cline); end endrule method Action reportAccess(Addr addr, HitOrMiss hitMiss); let cl = getLineAddr(addr); + $display("%t prefecher reportAccess", $time); if (hitMiss == HIT && rangeEnd - fromInteger(cacheLinesInRange) - 1 < cl && cl < rangeEnd) begin @@ -550,7 +559,8 @@ module mkBRAMSingleWindowTargetPrefetcher(Prefetcher) provisos rangeEnd <= cl + fromInteger(cacheLinesInRange) + 1; end - if (cl != lastChildRequest + 1 && cl != lastChildRequest && cl != lastChildRequest - 1) begin + if (hitMiss == MISS && cl != lastChildRequest + 1 && cl != lastChildRequest && cl != lastChildRequest - 1) begin + //Try only recording table entries on a miss! $display("%t Prefetcher add target entry from addr %h to addr %h", $time, Addr'{lastChildRequest, '0}, addr); targetTable.writeReq(lastChildRequest, cl); end @@ -579,6 +589,7 @@ endmodule module mkBRAMMultiWindowTargetPrefetcher(Prefetcher) provisos( NumAlias#(numWindows, 4), + NumAlias#(numLastRequests, 16), Alias#(windowIdxT, Bit#(TLog#(numWindows))) ); Integer cacheLinesInRange = 2; @@ -589,17 +600,19 @@ provisos( TargetTableBRAM#(64, 8) targetTable <- mkTargetTableBRAM; FIFOF#(LineAddr) targetTableReadResp <- mkBypassFIFOF; + Reg#(Vector#(numLastRequests, Bit#(32))) lastTargetRequests <- mkReg(replicate(0)); rule sendReadReq; - let lastAsked = streams[shiftReg[0]].nextToAsk-1; - targetTable.readReq(lastAsked); + if (!elem(hash(lastChildRequest), lastTargetRequests)) begin + targetTable.readReq(lastChildRequest); + $display("%t Prefetcher sending target read request for %h", $time, lastChildRequest); + lastTargetRequests <= shiftInAt0(lastTargetRequests, hash(lastChildRequest)); + end endrule rule getReadResp; - let res <- targetTable.readResp(True); + let res <- targetTable.readResp(False); if (res matches tagged Valid .cline) begin - //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 targetTableReadResp.enq(cline); end endrule @@ -679,7 +692,7 @@ provisos( end // Update target prefetcher - if (cl != lastChildRequest + 1 && cl != lastChildRequest && cl != lastChildRequest - 1) begin + if (hitMiss == MISS && 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.writeReq(lastChildRequest, cl); end From 2d94cba9514cafe3b9db9bf62ae4f613aa660ebc Mon Sep 17 00:00:00 2001 From: Karlis Susters Date: Wed, 12 Apr 2023 21:50:31 +0300 Subject: [PATCH 02/12] Implemented vector prefetcher setup in L2 --- src_Core/RISCY_OOO/coherence/src/LLBank.bsv | 41 +++++++++++++------ .../RISCY_OOO/coherence/src/Prefetcher.bsv | 34 +++++++++++++++ 2 files changed, 62 insertions(+), 13 deletions(-) diff --git a/src_Core/RISCY_OOO/coherence/src/LLBank.bsv b/src_Core/RISCY_OOO/coherence/src/LLBank.bsv index 4a2914c..6ae40d8 100644 --- a/src_Core/RISCY_OOO/coherence/src/LLBank.bsv +++ b/src_Core/RISCY_OOO/coherence/src/LLBank.bsv @@ -52,6 +52,7 @@ import Cntrs::*; import ConfigReg::*; import RandomReplace::*; import Prefetcher::*; +import ProcTypes::*; `ifdef PERFORMANCE_MONITORING import PerformanceMonitor::*; import StatCounters::*; @@ -184,7 +185,8 @@ module mkLLBank#( FShow#(dmaRqIdT), Add#(tagSz, a__, AddrSz), // make sure: cRqNum <= wayNum - Add#(cRqNum, b__, wayNum) + Add#(cRqNum, b__, wayNum), + Add#(TLog#(TDiv#(childNum,2)), c__, TLog#(childNum)) ); Bool verbose = True; @@ -234,8 +236,9 @@ module mkLLBank#( Count#(Bit#(32)) removedCRqs <- mkCount(0); Vector#(cRqNum, Reg#(Bool)) cRqIsPrefetch <- replicateM(mkReg(?)); - Prefetcher dataPrefetcher <- mkLLDPrefetcher; - Prefetcher instrPrefetcher <- mkLLIPrefetcher; + PrefetcherVector#(TDiv#(childNum, 2)) dataPrefetchers <- mkPrefetcherVector(mkLLDPrefetcher); + PrefetcherVector#(TDiv#(childNum, 2)) instrPrefetchers <- mkPrefetcherVector(mkLLIPrefetcher); + `ifdef PERF_COUNT Reg#(Bool) doStats <- mkConfigReg(True); Count#(Data) dmaMemLdCnt <- mkCount(0); @@ -417,13 +420,16 @@ endfunction // 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; + let x <- dataPrefetchers.getNextPrefetchAddr; + match {.addr, .cacheIdx} = x; + //Request from L1D of cacheIdx-th core + childT child = {cacheIdx, '0}; cRqT cRq = LLRq { addr: addr, fromState: I, toState: E, canUpToE: True, - child: 0, + child: child, byteEn: ?, id: Child (?) }; @@ -447,13 +453,16 @@ endfunction // 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; + let x <- instrPrefetchers.getNextPrefetchAddr; + match {.addr, .cacheIdx} = x; + //Request from L1D of cacheIdx-th core + childT child = {cacheIdx, '1}; cRqT cRq = LLRq { addr: addr, fromState: I, toState: S, canUpToE: True, - child: 1, + child: child, byteEn: ?, id: Child (?) }; @@ -1002,10 +1011,12 @@ endfunction }, True); // hit, so update rep info if (!cRqIsPrefetch[n]) begin if (cRq.child[0] == 1) begin - instrPrefetcher.reportAccess(cRq.addr, HIT); + instrPrefetchers.reportAccess( + truncateLSB(cRq.child), cRq.addr, HIT); end else begin - dataPrefetcher.reportAccess(cRq.addr, HIT); + dataPrefetchers.reportAccess( + truncateLSB(cRq.child), cRq.addr, HIT); end end endaction @@ -1205,10 +1216,12 @@ endfunction }, False); if (!cRqIsPrefetch[n]) begin if (cRq.child[0] == 1) begin - instrPrefetcher.reportAccess(cRq.addr, MISS); + instrPrefetchers.reportAccess( + truncateLSB(cRq.child), cRq.addr, MISS); end else begin - dataPrefetcher.reportAccess(cRq.addr, MISS); + dataPrefetchers.reportAccess( + truncateLSB(cRq.child), cRq.addr, MISS); end end endaction @@ -1281,10 +1294,12 @@ endfunction end if (!cRqIsPrefetch[n]) begin if (cRq.child[0] == 1) begin - instrPrefetcher.reportAccess(cRq.addr, MISS); + instrPrefetchers.reportAccess( + truncateLSB(cRq.child), cRq.addr, MISS); end else begin - dataPrefetcher.reportAccess(cRq.addr, MISS); + dataPrefetchers.reportAccess( + truncateLSB(cRq.child), cRq.addr, MISS); end end endaction diff --git a/src_Core/RISCY_OOO/coherence/src/Prefetcher.bsv b/src_Core/RISCY_OOO/coherence/src/Prefetcher.bsv index d7adc74..1556efc 100644 --- a/src_Core/RISCY_OOO/coherence/src/Prefetcher.bsv +++ b/src_Core/RISCY_OOO/coherence/src/Prefetcher.bsv @@ -1466,6 +1466,40 @@ provisos( endmodule + +interface PrefetcherVector#(numeric type size); + method ActionValue#(Tuple2#(Addr, Bit#(TLog#(size)))) getNextPrefetchAddr; + method Action reportAccess(Bit#(TLog#(size)) idx, Addr addr, HitOrMiss hitMiss); +endinterface + +module mkPrefetcherVector#(module#(Prefetcher) mkPrefetcher) +( + PrefetcherVector#(size) +) provisos ( + Alias#(idxT, Bit#(TLog#(size))) +); + Vector#(size, Prefetcher) prefetchers <- replicateM(mkPrefetcher); + Fifo#(1, Tuple2#(Addr, idxT)) prefetchRq <- mkBypassFifo; + + function XBarDstInfo#(Bit#(0),Tuple2#(Addr, idxT)) convertPrefetchRq(idxT item, Addr a); + return XBarDstInfo { + idx: 0, + data: tuple2(a, item) + }; + endfunction + function Get#(Addr) reqGet(Prefetcher p) = toGet(p.getNextPrefetchAddr); + mkXBar(convertPrefetchRq, map(reqGet, prefetchers), vec(toPut(prefetchRq))); + + method ActionValue#(Tuple2#(Addr, idxT)) getNextPrefetchAddr; + prefetchRq.deq; + return prefetchRq.first; + endmethod + + method Action reportAccess(idxT idx, Addr addr, HitOrMiss hitMiss); + prefetchers[idx].reportAccess(addr, hitMiss); + endmethod +endmodule + module mkL1IPrefetcher(Prefetcher); `ifdef INSTR_PREFETCHER_IN_L1 `ifdef INSTR_PREFETCHER_NEXT_LINE_ON_ALL From bf0f26ce561a1014fa75396d8c9c246e6c8b146f Mon Sep 17 00:00:00 2001 From: Karlis Susters Date: Wed, 12 Apr 2023 21:52:56 +0300 Subject: [PATCH 03/12] Implemented double target table and the corresponding markov prefetcher --- builds/Resources/Include_RISCY_Config.mk | 2 +- .../RISCY_OOO/coherence/src/Prefetcher.bsv | 280 ++++++++++++++++++ 2 files changed, 281 insertions(+), 1 deletion(-) diff --git a/builds/Resources/Include_RISCY_Config.mk b/builds/Resources/Include_RISCY_Config.mk index a1a02f9..78005ab 100644 --- a/builds/Resources/Include_RISCY_Config.mk +++ b/builds/Resources/Include_RISCY_Config.mk @@ -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 diff --git a/src_Core/RISCY_OOO/coherence/src/Prefetcher.bsv b/src_Core/RISCY_OOO/coherence/src/Prefetcher.bsv index 1556efc..b8dacc4 100644 --- a/src_Core/RISCY_OOO/coherence/src/Prefetcher.bsv +++ b/src_Core/RISCY_OOO/coherence/src/Prefetcher.bsv @@ -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 From d2b41c852d7ae23bcb152bba55fe3636de58dcf9 Mon Sep 17 00:00:00 2001 From: Karlis Susters Date: Wed, 12 Apr 2023 21:55:13 +0300 Subject: [PATCH 04/12] Added prefetcher port to ICrqmshr and retired prefetchRqDone --- src_Core/RISCY_OOO/coherence/src/IBank.bsv | 8 +--- src_Core/RISCY_OOO/coherence/src/ICRqMshr.bsv | 38 ++++++++++++++++--- 2 files changed, 34 insertions(+), 12 deletions(-) diff --git a/src_Core/RISCY_OOO/coherence/src/IBank.bsv b/src_Core/RISCY_OOO/coherence/src/IBank.bsv index e6728fb..44b60d3 100644 --- a/src_Core/RISCY_OOO/coherence/src/IBank.bsv +++ b/src_Core/RISCY_OOO/coherence/src/IBank.bsv @@ -168,7 +168,6 @@ module mkIBank#( FIFO#(cRqIdxT) cRqIndexQ <- mkSizedFIFO(valueof(cRqNum)); FIFO#(cRqIdxT) prefetchIndexQ <- mkSizedFIFO(valueof(cRqNum)); Vector#(cRqNum, Reg#(Bool)) cRqIsPrefetch <- replicateM(mkReg(?)); - Vector#(cRqNum, Reg#(Bool)) prefetchRqDone <- replicateM(mkReg(?)); let prefetcher <- mkL1IPrefetcher; let llcPrefetcher <- mkLLIPrefetcherInL1I; @@ -323,7 +322,6 @@ module mkIBank#( // enq to indexQ for in order resp prefetchIndexQ.enq(n); cRqIsPrefetch[n] <= True; - prefetchRqDone[n] <= False; addedCRqs.incr(1); // performance counter: cRq type //incrReqCnt; TODO make separate counter for prefetch requests @@ -536,7 +534,6 @@ module mkIBank#( prefetcher.reportAccess(req.addr, HIT); llcPrefetcher.reportAccess(req.addr, HIT); end - prefetchRqDone[n] <= True; // process req to get superscalar inst read results // set MSHR entry as Done & save inst results let instResult = readInst(ram.line, req.addr); @@ -773,11 +770,10 @@ module mkIBank#( endrule rule discardPrefetchRqResult( - //cRqMshr.sendRsToC.getResult(prefetchIndexQ.first) matches tagged Valid .inst); - prefetchRqDone[prefetchIndexQ.first]); + cRqMshr.prefetcher.getResult(prefetchIndexQ.first) matches tagged Valid .inst); prefetchIndexQ.deq; removedCRqs.incr(1); - cRqMshr.sendRsToC.releaseEntry(prefetchIndexQ.first); // release MSHR entry + cRqMshr.prefetcher.releaseEntry(prefetchIndexQ.first); // release MSHR entry if (verbose) $display("%t I %m discardPrefetchRqResult: ", $time, fshow(prefetchIndexQ.first) diff --git a/src_Core/RISCY_OOO/coherence/src/ICRqMshr.bsv b/src_Core/RISCY_OOO/coherence/src/ICRqMshr.bsv index b6c815f..7db5c5a 100644 --- a/src_Core/RISCY_OOO/coherence/src/ICRqMshr.bsv +++ b/src_Core/RISCY_OOO/coherence/src/ICRqMshr.bsv @@ -143,6 +143,14 @@ interface ICRqMshr_sendRsToC#( method Maybe#(resultT) getResult(Bit#(TLog#(cRqNum)) n); endinterface +interface ICRqMshr_prefetcher#( + numeric type cRqNum, + type resultT +); + method Action releaseEntry(Bit#(TLog#(cRqNum)) n); + method Maybe#(resultT) getResult(Bit#(TLog#(cRqNum)) n); +endinterface + interface ICRqMshr#( numeric type cRqNum, type wayT, @@ -156,6 +164,9 @@ interface ICRqMshr#( // port for sendRsToC interface ICRqMshr_sendRsToC#(cRqNum, resultT) sendRsToC; + // port for prefetcher + interface ICRqMshr_prefetcher#(cRqNum, resultT) prefetcher; + // port for sendRsToP_cRq interface ICRqMshr_sendRsToP_cRq#(cRqNum, wayT, tagT, reqT) sendRsToP_cRq; @@ -192,7 +203,8 @@ module mkICRqMshrSafe#( // EHR ports // We put pipelineResp < transfer to cater for deq < enq of cache pipeline - Integer cRqTransfer_port = 2; + Integer cRqTransfer_port = 3; + Integer prefetcher_port = 2; Integer sendRsToC_port = 1; // create a bypass behavior from pipelineResp to sendRsToC (to save a cycle) Integer pipelineResp_port = 0; Integer sendRqToP_port = 0; // sendRqToP is read only @@ -200,15 +212,15 @@ module mkICRqMshrSafe#( Integer flush_port = 0; // flush port is read only // MSHR entry state - Vector#(cRqNum, Ehr#(3, ICRqState)) stateVec <- replicateM(mkEhr(Empty)); + Vector#(cRqNum, Ehr#(4, ICRqState)) stateVec <- replicateM(mkEhr(Empty)); // cRq req contents - Vector#(cRqNum, Ehr#(3, reqT)) reqVec <- replicateM(mkEhr(?)); + Vector#(cRqNum, Ehr#(4, reqT)) reqVec <- replicateM(mkEhr(?)); // cRq mshr slots - Vector#(cRqNum, Ehr#(3, slotT)) slotVec <- replicateM(mkEhr(defaultValue)); + Vector#(cRqNum, Ehr#(4, slotT)) slotVec <- replicateM(mkEhr(defaultValue)); // result - Vector#(cRqNum, Ehr#(3, Maybe#(resultT))) resultVec <- replicateM(mkEhr(Invalid)); + Vector#(cRqNum, Ehr#(4, Maybe#(resultT))) resultVec <- replicateM(mkEhr(Invalid)); // successor valid bit - Vector#(cRqNum, Ehr#(3, Bool)) succValidVec <- replicateM(mkEhr(False)); + Vector#(cRqNum, Ehr#(4, Bool)) succValidVec <- replicateM(mkEhr(False)); // successor MSHR index RegFile#(cRqIndexT, cRqIndexT) succFile <- mkRegFile(0, fromInteger(valueOf(cRqNum) - 1)); // empty entry FIFO @@ -273,6 +285,20 @@ module mkICRqMshrSafe#( endmethod endinterface + interface ICRqMshr_prefetcher prefetcher; + method Action releaseEntry(cRqIndexT n) if(inited); + emptyEntryQ.enq(n); + stateVec[n][prefetcher_port] <= Empty; +`ifdef CHECK_DEADLOCK + checker.releaseEntry(n); +`endif + endmethod + + method Maybe#(resultT) getResult(Bit#(TLog#(cRqNum)) n); + return resultVec[n][prefetcher_port]; + endmethod + endinterface + interface ICRqMshr_sendRsToP_cRq sendRsToP_cRq; method reqT getRq(cRqIndexT n); return reqVec[n][sendRsToP_cRq_port]; From f20e80e5b2fd30e5b354d8bda6ca16cd83174670 Mon Sep 17 00:00:00 2001 From: Karlis Susters Date: Wed, 12 Apr 2023 21:57:03 +0300 Subject: [PATCH 05/12] Tests for prefetchervector, double target table, overflow bypass fifo --- .../coherence/src/test/Prefetcher_test.bsv | 405 +++++++++++++++++- 1 file changed, 391 insertions(+), 14 deletions(-) diff --git a/src_Core/RISCY_OOO/coherence/src/test/Prefetcher_test.bsv b/src_Core/RISCY_OOO/coherence/src/test/Prefetcher_test.bsv index e7b06ff..ddcdcb2 100644 --- a/src_Core/RISCY_OOO/coherence/src/test/Prefetcher_test.bsv +++ b/src_Core/RISCY_OOO/coherence/src/test/Prefetcher_test.bsv @@ -1,4 +1,5 @@ import Prefetcher::*; +import RWBramCore::*; import StmtFSM::*; import Types::*; import Fifos::*; @@ -99,6 +100,182 @@ module mkTargetTableBRAMTest(Empty); ); endmodule +module mkTargetTableDoubleTest(Empty); + TargetTableDouble#(2048, 128) t <- mkTargetTableDouble; + mkAutoFSM( + seq + // ----- Send misses and stuff to one window ----- + action + t.sendReadWriteReq('h8000, MISS); // goes in short table + endaction + action let x <- t.readResp(); endaction + action + t.sendReadWriteReq('h800a, MISS); // goes in short table + endaction + action let x <- t.readResp(); endaction + action + t.sendReadWriteReq('h8080000b, MISS); // goes in long table + endaction + action let x <- t.readResp(); endaction + action + t.sendReadWriteReq('h8000, MISS); // comes from short table + endaction + action + let x <- t.readResp(); + doAssert(x == tuple2(Valid('h800a), Invalid), "test fail!"); + endaction + action + t.sendReadWriteReq('h800a, MISS); // comes from long table + endaction + action + let x <- t.readResp(); + doAssert(x == tuple2(Valid('h8080000b), Invalid), "test fail!"); + endaction + + + action + t.sendReadWriteReq('h8000, MISS); + endaction + action let x <- t.readResp(); endaction + action + t.sendReadWriteReq('h2123000c, MISS); + endaction + action let x <- t.readResp(); endaction + action + t.sendReadWriteReq('h8000, HIT); + endaction + action + let x <- t.readResp(); + doAssert(x == tuple2(Valid('h2123000c), Valid('h800a)), "test fail!"); + endaction + action + t.sendReadWriteReq('h8000, MISS); + endaction + action let x <- t.readResp(); endaction + action + t.sendReadWriteReq('h2123000c, MISS); + endaction + action let x <- t.readResp(); endaction + action + t.sendReadWriteReq('h8000, MISS); + endaction + action + let x <- t.readResp(); + doAssert(x == tuple2(Valid('h2123000c), Valid('h800a)), "test fail!"); + endaction + + + /// ---- Add third entry (narrow) 8003 + action + t.sendReadWriteReq('h8003, MISS); + endaction + action let x <- t.readResp(); endaction + action + t.sendReadWriteReq('h8000, MISS); + endaction + action + //wide entry is moved to LRU + let x <- t.readResp(); + doAssert(x == tuple2(Valid('h8003), Valid('h2123000c)), "test fail!"); + endaction + action + t.sendReadWriteReq('h8003, MISS); + endaction + action let x <- t.readResp(); endaction + action + t.sendReadWriteReq('h8000, MISS); + endaction + action + let x <- t.readResp(); + doAssert(x == tuple2(Valid('h8003), Valid('h2123000c)), "test fail!"); + endaction + //refresh 21230000 + action + t.sendReadWriteReq('h2123000c, MISS); + endaction + action let x <- t.readResp(); endaction + + action + t.sendReadWriteReq('h8000, MISS); + endaction + action + let x <- t.readResp(); + doAssert(x == tuple2(Valid('h2123000c), Valid('h8003)), "test fail!"); + endaction + + /// ---- Add another entry (wide) 2123000d + action + t.sendReadWriteReq('h2123000d, MISS); + endaction + action let x <- t.readResp(); endaction + action + t.sendReadWriteReq('h8000, MISS); + endaction + action + //wide entry is moved to LRU + let x <- t.readResp(); + doAssert(x == tuple2(Valid('h2123000d), Valid('h2123000c)), "test fail!"); + endaction + + + /// ---- Add fifth entry (narrow) 8004 + action + t.sendReadWriteReq('h8004, MISS); + endaction + action let x <- t.readResp(); endaction + action + t.sendReadWriteReq('h8000, MISS); + endaction + action + //wide entry is moved to LRU + let x <- t.readResp(); + doAssert(x == tuple2(Valid('h8004), Valid('h2123000d)), "test fail!"); + endaction + // --- Add a sixth narrow entry 8005 + action + t.sendReadWriteReq('h8005, MISS); + endaction + action let x <- t.readResp(); endaction + action + t.sendReadWriteReq('h8000, MISS); + endaction + action + //wide entry is moved to LRU + let x <- t.readResp(); + doAssert(x == tuple2(Valid('h8005), Valid('h8004)), "test fail!"); + endaction + + + action + t.sendReadWriteReq('h7004, MISS); // get from short table + endaction + + action + let x <- t.readResp(); + doAssert(x == tuple2(Invalid, Invalid), "test fail!"); + endaction + action + t.sendReadWriteReq('h6fde, MISS); // get from short table + endaction + action let x <- t.readResp(); endaction + action + t.sendReadWriteReq('h7004, MISS); // get from short table + endaction + action + let x <- t.readResp(); + doAssert(x == tuple2(Valid('h6fde), Invalid), "test fail!"); + endaction + action + t.sendReadWriteReq('h200, HIT); // get from short table + endaction + action + let x <- t.readResp(); + doAssert(x == tuple2(Invalid, Invalid), "test fail!"); //entry was removed! + endaction + endseq + ); +endmodule + module mkBRAMMultiWindowTargetPrefetcherTest(Empty); let p <- mkBRAMMultiWindowTargetPrefetcher; mkAutoFSM( @@ -212,10 +389,6 @@ module mkBRAMMultiWindowTargetPrefetcherTest(Empty); let x <- p.getNextPrefetchAddr; //target address recommended doAssert(x == 'h50000000, "test fail!"); endaction - action - let x <- p.getNextPrefetchAddr; //target address recommended - doAssert(x == 'h81000000, "test fail!"); - endaction action let x <- p.getNextPrefetchAddr; doAssert(x == 'h80000200, "test fail!"); // window addresss recommended @@ -225,6 +398,8 @@ module mkBRAMMultiWindowTargetPrefetcherTest(Empty); endmodule module mkBRAMSingleWindowTargetPrefetcherTest(Empty); + //2 ahead + //remember last 2 target table requests. let p <- mkBRAMSingleWindowTargetPrefetcher; mkAutoFSM( seq @@ -262,24 +437,21 @@ module mkBRAMSingleWindowTargetPrefetcherTest(Empty); doAssert(x == 'h80000180, "test fail!"); endaction action - p.reportAccess('h81000000, MISS); //Report miss somewhere far away + p.reportAccess('h81000200, MISS); //Report miss somewhere far away endaction action let x <- p.getNextPrefetchAddr; //New window allocated and recommended - doAssert(x == 'h81000040, "test fail!"); + doAssert(x == 'h81000240, "test fail!"); endaction action p.reportAccess('h80000180, MISS); //Report miss back home endaction + action endaction action p.reportAccess('h82000000, MISS); //Report miss far away 2 endaction action - p.reportAccess('h80000100, MISS); //Report miss back home - endaction - action - let x <- p.getNextPrefetchAddr; - doAssert(x == 'h80000140, "test fail!"); + p.reportAccess('h80000140, MISS); //Report miss back home endaction action let x <- p.getNextPrefetchAddr; @@ -287,11 +459,17 @@ module mkBRAMSingleWindowTargetPrefetcherTest(Empty); endaction action let x <- p.getNextPrefetchAddr; //target address recommended - doAssert(x == 'h81000000, "test fail!"); + doAssert(x == 'h81000200, "test fail!"); endaction action - let x <- p.getNextPrefetchAddr; //target address recommended - doAssert(x == 'h82000000, "test fail!"); + p.reportAccess('h80000140, HIT); //Report miss back home + endaction + action + p.reportAccess('h81000200, HIT); + endaction + action + let x <- p.getNextPrefetchAddr; //target addresss recommended + doAssert(x == 'h800001c0, "test fail!"); endaction endseq ); @@ -372,6 +550,7 @@ module mkBRAMStridePCPrefetcherTest(Empty); endmodule module mkBRAMStrideAdaptivePCPrefetcherTest(Empty); + // config is 2 - 3 - 5 let p <- mkBRAMStrideAdaptivePCPrefetcher; mkAutoFSM( seq @@ -474,6 +653,74 @@ module mkBRAMStrideAdaptivePCPrefetcherTest(Empty); ); endmodule +module mkMarkovOnHit2PrefetcherTest(Empty); + //let p <- mkMultipleWindowPrefetcher; + //TODO pass in value of cachelinesinrange + let p <- mkMarkovOnHit2Prefetcher; + mkAutoFSM( + seq + // ----- Send misses and stuff to one window ----- + action + p.reportAccess('h80010000, MISS); + endaction + action + p.reportAccess('h80010700, MISS); + endaction + action + p.reportAccess('h90010000, MISS); + endaction + action + p.reportAccess('ha0010300, MISS); + endaction + action + p.reportAccess('h80010000, MISS); //back to start + endaction + action + let x <- p.getNextPrefetchAddr; + doAssert(x == 'h80010700, "test fail!"); + endaction + + //Add second target + action + p.reportAccess('h80010900, MISS); + endaction + action + p.reportAccess('h80010000, MISS); //back to start + endaction + action + let x <- p.getNextPrefetchAddr; + doAssert(x == 'h80010900, "test fail!"); + endaction + action + let x <- p.getNextPrefetchAddr; + doAssert(x == 'h80010700, "test fail!"); + endaction + + action + p.reportAccess('ha0010300, MISS); + endaction + action + let x <- p.getNextPrefetchAddr; + doAssert(x == 'h80010000, "test fail!"); + endaction + action + p.reportAccess('ha0010200, MISS); + endaction + action + p.reportAccess('ha0010300, MISS); + endaction + action + let x <- p.getNextPrefetchAddr; + doAssert(x == 'ha0010200, "test fail!"); + endaction + action + let x <- p.getNextPrefetchAddr; + doAssert(x == 'h80010000, "test fail!"); + endaction + endseq + ); +endmodule + module mkBRAMMarkovPrefetcherTest(Empty); //let p <- mkMultipleWindowPrefetcher; //TODO pass in value of cachelinesinrange @@ -598,6 +845,77 @@ module mkOverflowPipelineFifoTest(Empty); ); endmodule +module mkOverflowBypassFifoTest(Empty); + Fifo#(4, Bit#(8)) p <- mkOverflowBypassFifo; + mkAutoFSM( + seq + action + p.enq('h01); + endaction + action + p.enq('h02); + endaction + action + p.enq('h03); + endaction + action + p.enq('h04); + endaction + action + let x = p.first; + p.deq; + doAssert(x == 'h01, "test fail!"); + endaction + action + p.enq('h05); + let x = p.first; + p.deq; + doAssert(x == 'h02, "test fail!"); + endaction + action + p.enq('h06); + endaction + action + p.enq('h07); + let x = p.first; + p.deq; + $display("found %x", x); + doAssert(x == 'h04, "test fail!"); + endaction + action + p.enq('h08); + endaction + action + p.enq('h09); + let x = p.first; + p.deq; + doAssert(x == 'h06, "test fail!"); + endaction + action + let x = p.first; + p.deq; + doAssert(x == 'h07, "test fail!"); + endaction + action + let x = p.first; + p.deq; + doAssert(x == 'h08, "test fail!"); + endaction + action + let x = p.first; + p.deq; + doAssert(x == 'h09, "test fail!"); + endaction + action + doAssert(!p.notEmpty, "test fail!"); + endaction + action + $display("test done!"); + endaction + endseq + ); +endmodule + module mkStride2PCPrefetcherTest(Empty); //paremeter - 2 ahead let p <- mkStride2PCPrefetcher; @@ -671,4 +989,63 @@ module mkStride2PCPrefetcherTest(Empty); endaction endseq ); +endmodule + +module mkPrefetcherVectorTest(Empty); + //config - 2 lines + PrefetcherVector#(3) p <- mkPrefetcherVector(mkNextLineOnMissPrefetcher); + mkAutoFSM( + seq + action p.reportAccess(1, 'h90000000, MISS); endaction + action p.reportAccess(0, 'h80000000, MISS); endaction + action + let x <- p.getNextPrefetchAddr; + $display("%t Got %x", $time, x); + doAssert(x == tuple2('h90000040, 1), "test fail!"); + endaction + action + let x <- p.getNextPrefetchAddr; + $display("%t Got %x", $time, x); + doAssert(x == tuple2('h90000080, 1), "test fail!"); + endaction + action p.reportAccess(0, 'h40000000, MISS); endaction + action p.reportAccess(1, 'h50000000, MISS); endaction + action + let x <- p.getNextPrefetchAddr; + $display("%t Got %x", $time, x); + doAssert(x == tuple2('h80000040, 0), "test fail!"); + endaction + action + let x <- p.getNextPrefetchAddr; + $display("%t Got %x", $time, x); + doAssert(x == tuple2('h40000040, 0), "test fail!"); + endaction + action + let x <- p.getNextPrefetchAddr; + $display("%t Got %x", $time, x); + doAssert(x == tuple2('h50000040, 1), "test fail!"); + endaction + action + let x <- p.getNextPrefetchAddr; + $display("%t Got %x", $time, x); + doAssert(x == tuple2('h40000080, 0), "test fail!"); + endaction + action + let x <- p.getNextPrefetchAddr; + $display("%t Got %x", $time, x); + doAssert(x == tuple2('h50000080, 1), "test fail!"); + endaction + action p.reportAccess(2, 'ha0000000, MISS); endaction + action + let x <- p.getNextPrefetchAddr; + $display("%t Got %x", $time, x); + doAssert(x == tuple2('ha0000040, 2), "test fail!"); + endaction + action + let x <- p.getNextPrefetchAddr; + $display("%t Got %x", $time, x); + doAssert(x == tuple2('ha0000080, 2), "test fail!"); + endaction + endseq + ); endmodule \ No newline at end of file From 5733ed9ac0fa84e021a4604815bf55d6b25d9332 Mon Sep 17 00:00:00 2001 From: Karlis Susters Date: Wed, 12 Apr 2023 21:58:35 +0300 Subject: [PATCH 06/12] Implemented overflow bypass fifo, required for double target table --- src_Core/RISCY_OOO/procs/lib/Fifos.bsv | 50 +++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/src_Core/RISCY_OOO/procs/lib/Fifos.bsv b/src_Core/RISCY_OOO/procs/lib/Fifos.bsv index 9ad7714..813592f 100644 --- a/src_Core/RISCY_OOO/procs/lib/Fifos.bsv +++ b/src_Core/RISCY_OOO/procs/lib/Fifos.bsv @@ -740,4 +740,52 @@ module mkOverflowPipelineFifo( Fifo#(n, t) ) provisos (Bits#(t,tSz)); empty[2] <= True; full[2] <= False; endmethod -endmodule \ No newline at end of file +endmodule + +module mkOverflowBypassFifo( Fifo#(n, t) ) provisos (Bits#(t,tSz)); + // n is size of fifo + // t is data type of fifo + Vector#(n, Ehr#(2,t)) data <- replicateM(mkEhr(?)); + Ehr#(2, Bit#(TLog#(n))) enqP <- mkEhr(0); + Ehr#(3, Bit#(TLog#(n))) deqP <- mkEhr(0); + Ehr#(3, Bool) empty <- mkEhr(True); + Ehr#(3, Bool) full <- mkEhr(False); + Bit#(TLog#(n)) max_index = fromInteger(valueOf(n)-1); + + method Bool notFull = !full[0]; + + method Action enq(t x); + data[enqP[0]][0] <= x; + empty[0] <= False; + let next_enqP = (enqP[0] == max_index) ? 0 : enqP[0] + 1; + if (full[0]) begin + deqP[0] <= next_enqP; + end + enqP[0] <= next_enqP; + if( next_enqP == deqP[0] ) begin + full[0] <= True; + end + endmethod + + method Bool notEmpty = !empty[1]; + + method Action deq if( !empty[1] ); + full[1] <= False; + let next_deqP = (deqP[1] == max_index) ? 0 : deqP[1] + 1; + deqP[1] <= next_deqP; + if( next_deqP == enqP[1] ) begin + empty[1] <= True; + end + endmethod + + method t first if( !empty[1] ); + return data[deqP[1]][1]; + endmethod + + method Action clear; + enqP[1] <= 0; + deqP[2] <= 0; + empty[2] <= True; + full[2] <= False; + endmethod +endmodule From 0e4b9a710af56fba58612c0d109dcada1d2a8248 Mon Sep 17 00:00:00 2001 From: Karlis Susters Date: Wed, 12 Apr 2023 23:31:15 +0300 Subject: [PATCH 07/12] Implemented SimpleStride, to compare with Gem5 --- .../RISCY_OOO/coherence/src/Prefetcher.bsv | 75 +++++++++++++++++++ .../coherence/src/test/Prefetcher_test.bsv | 31 ++++++++ 2 files changed, 106 insertions(+) diff --git a/src_Core/RISCY_OOO/coherence/src/Prefetcher.bsv b/src_Core/RISCY_OOO/coherence/src/Prefetcher.bsv index b8dacc4..344cd26 100644 --- a/src_Core/RISCY_OOO/coherence/src/Prefetcher.bsv +++ b/src_Core/RISCY_OOO/coherence/src/Prefetcher.bsv @@ -1529,6 +1529,81 @@ provisos( endmodule +typedef struct { + Addr lastAddr; + Bit#(13) stride; + Bit#(2) confidence; +} SimpleStrideEntry deriving (Bits, Eq, FShow); + +//10 minutes of planning +//25 minutes of implementation +//30 minutes of writing tests and fixing bugs +module mkSimpleStridePCPrefetcher(PCPrefetcher) +provisos( + NumAlias#(strideTableSize, 512), + NumAlias#(cLinesAheadToPrefetch, 2), + NumAlias#(minConfidenceToPrefetch, 2), + Alias#(strideTableIndexT, Bit#(TLog#(strideTableSize))) + ); + Vector#(strideTableSize, Reg#(SimpleStrideEntry)) strideTable <- replicateM(mkReg(unpack(0))); + + Reg#(Addr) addrToPrefetch <- mkReg(0); + Reg#(Bit#(13)) strideToPrefetch <- mkReg(0); + Ehr#(2, Bit#(3)) prefetchesIssued <- mkEhr(fromInteger(valueOf(cLinesAheadToPrefetch))); + + method Action reportAccess(Addr addr, Bit#(16) pcHash, HitOrMiss hitMiss); + $display("%t report access %x %x", $time, addr, pcHash); + strideTableIndexT idx = truncate(pcHash); + SimpleStrideEntry entry = strideTable[idx]; + Bit#(13) calc_stride = truncate(addr - entry.lastAddr); + $display("found stride %x", entry.stride); + entry.lastAddr = addr; + if (calc_stride == entry.stride) begin + if (entry.confidence != 2'd3) begin + entry.confidence = entry.confidence + 1; + end + end + else begin + if (entry.confidence > 0) begin + entry.confidence = entry.confidence - 1; + end + if (entry.confidence < fromInteger(valueOf(minConfidenceToPrefetch))) begin + entry.stride = calc_stride; + entry.confidence = 0; + end + end + + if (entry.confidence >= fromInteger(valueOf(minConfidenceToPrefetch))) begin + prefetchesIssued[1] <= 0; + addrToPrefetch <= addr; + strideToPrefetch <= entry.stride; + end + strideTable[idx] <= entry; + endmethod + + method ActionValue#(Addr) getNextPrefetchAddr + if (prefetchesIssued[0] < fromInteger(valueOf(cLinesAheadToPrefetch))); + + Bit#(13) strideToUse; + Bit#(13) cLineSize = fromInteger(valueof(DataSz)); + if (abs(strideToPrefetch) < cLineSize) begin + strideToUse = (strideToPrefetch[12] == 1) ? -cLineSize : cLineSize; + end + else begin + strideToUse = strideToPrefetch; + end + + prefetchesIssued[0] <= prefetchesIssued[0] + 1; + let reqAddr = addrToPrefetch + + (signExtend(strideToUse) * zeroExtend(prefetchesIssued[0] + 1)); + + check(reqAddr[63:12] == addrToPrefetch[63:12]); + $display("%t getprefetchaddr ret %x", $time, reqAddr); + return reqAddr; + endmethod + +endmodule + typedef enum { EMPTY = 3'd0, INIT = 3'd1, TRANSIENT = 3'd2, STEADY1 = 3'd3, STEADY2 = 3'd4, STEADY3 = 3'd5, STEADY4 = 4'd6, STEADYLAST = 3'd7 diff --git a/src_Core/RISCY_OOO/coherence/src/test/Prefetcher_test.bsv b/src_Core/RISCY_OOO/coherence/src/test/Prefetcher_test.bsv index ddcdcb2..4fd3d1f 100644 --- a/src_Core/RISCY_OOO/coherence/src/test/Prefetcher_test.bsv +++ b/src_Core/RISCY_OOO/coherence/src/test/Prefetcher_test.bsv @@ -1048,4 +1048,35 @@ module mkPrefetcherVectorTest(Empty); endaction endseq ); +endmodule + +module mkSimpleStridePCPrefetcherTest(Empty); + //paremeter - 2 ahead + let p <- mkSimpleStridePCPrefetcher; + mkAutoFSM( + seq + // ----- Send misses and stuff to one window ----- + action $display("%t", $time); 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 p.reportAccess('h800000e0, 'h0069, MISS); endaction + action + let x <- p.getNextPrefetchAddr; + doAssert(x == 'h80000120, "test fail!"); + endaction + action + let x <- p.getNextPrefetchAddr; + doAssert(x == 'h80000160, "test fail!"); + endaction + action p.reportAccess('h80000400, 'h0069, MISS); endaction + action p.reportAccess('h80000300, 'h0069, MISS); endaction + action p.reportAccess('h80000200, 'h0069, MISS); endaction + action p.reportAccess('h80000100, 'h0069, MISS); endaction + action + let x <- p.getNextPrefetchAddr; + doAssert(x == 'h80000000, "test fail!"); + endaction + endseq + ); endmodule \ No newline at end of file From 2ec0f37bbd835aa291418010ecd65e0df1150fe1 Mon Sep 17 00:00:00 2001 From: Karlis Susters Date: Thu, 13 Apr 2023 13:39:22 +0300 Subject: [PATCH 08/12] Remove stride prefetcher empty state --- src_Core/RISCY_OOO/coherence/src/Prefetcher.bsv | 14 ++------------ .../coherence/src/test/Prefetcher_test.bsv | 11 +++++++---- 2 files changed, 9 insertions(+), 16 deletions(-) diff --git a/src_Core/RISCY_OOO/coherence/src/Prefetcher.bsv b/src_Core/RISCY_OOO/coherence/src/Prefetcher.bsv index 344cd26..b436b89 100644 --- a/src_Core/RISCY_OOO/coherence/src/Prefetcher.bsv +++ b/src_Core/RISCY_OOO/coherence/src/Prefetcher.bsv @@ -1352,7 +1352,7 @@ provisos( endmodule typedef enum { - EMPTY = 3'd0, INIT = 3'd1, TRANSIENT = 3'd2, STEADY = 3'd3, NO_PRED = 3'd4 + INIT = 2'd0, TRANSIENT = 2'd1, STEADY = 2'd2, NO_PRED = 2'd3 } StrideState2 deriving (Bits, Eq, FShow); typedef struct { @@ -1402,17 +1402,7 @@ provisos( $writeh("%t Stride Prefetcher updateStrideEntry ", $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 + if (se.state == INIT && observedStride != 0) begin if (se.stride == observedStride) begin //fast track to steady seNext.state = STEADY; diff --git a/src_Core/RISCY_OOO/coherence/src/test/Prefetcher_test.bsv b/src_Core/RISCY_OOO/coherence/src/test/Prefetcher_test.bsv index 4fd3d1f..0570eb4 100644 --- a/src_Core/RISCY_OOO/coherence/src/test/Prefetcher_test.bsv +++ b/src_Core/RISCY_OOO/coherence/src/test/Prefetcher_test.bsv @@ -952,7 +952,11 @@ module mkStride2PCPrefetcherTest(Empty); action p.reportAccess('h90000160, 'h006a, HIT); endaction action let x <- p.getNextPrefetchAddr; - doAssert(x == 'h90000120, "test fail!"); + doAssert(x == 'h90000150, "test fail!"); + endaction + action + let x <- p.getNextPrefetchAddr; + doAssert(x == 'h90000110, "test fail!"); endaction action let x <- p.getNextPrefetchAddr; @@ -961,14 +965,13 @@ module mkStride2PCPrefetcherTest(Empty); action p.reportAccess('h90000100, 'h006b, MISS); endaction action p.reportAccess('h90000200, 'h006b, MISS); endaction action p.reportAccess('h90000300, 'h006b, MISS); endaction - action p.reportAccess('h90000400, 'h006b, MISS); endaction action let x <- p.getNextPrefetchAddr; - doAssert(x == 'h90000500, "test fail!"); + doAssert(x == 'h90000400, "test fail!"); endaction action let x <- p.getNextPrefetchAddr; - doAssert(x == 'h90000600, "test fail!"); + doAssert(x == 'h90000500, "test fail!"); endaction action p.reportAccess('ha0000420, 'h006b, MISS); endaction action p.reportAccess('ha0000520, 'h006b, MISS); endaction From 2f428a974a7bdafa2a19d1c0036bb7a8efa40961 Mon Sep 17 00:00:00 2001 From: Karlis Susters Date: Thu, 13 Apr 2023 18:27:28 +0300 Subject: [PATCH 09/12] Reduce bit storage for stride prefetcher --- src_Core/RISCY_OOO/coherence/src/Prefetcher.bsv | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src_Core/RISCY_OOO/coherence/src/Prefetcher.bsv b/src_Core/RISCY_OOO/coherence/src/Prefetcher.bsv index b436b89..f4d517f 100644 --- a/src_Core/RISCY_OOO/coherence/src/Prefetcher.bsv +++ b/src_Core/RISCY_OOO/coherence/src/Prefetcher.bsv @@ -1358,7 +1358,7 @@ typedef enum { typedef struct { Bit#(12) lastAddr; Bit#(13) stride; - Bit#(4) cLinesPrefetched; //Stores how many cache lines have been prefetched for this instruction + Bit#(2) cLinesPrefetched; //Stores how many cache lines have been prefetched for this instruction StrideState2 state; } StrideEntry2 deriving (Bits, Eq, FShow); @@ -1374,7 +1374,7 @@ provisos( Fifo#(8, Addr) addrToPrefetch <- mkOverflowPipelineFifo; FIFO#(Tuple3#(StrideEntry2, Addr, Bit#(16))) strideEntryForPrefetch <- mkBypassFIFO(); - Reg#(Maybe#(Bit#(4))) cLinesPrefetchedLatest <- mkReg(?); + Reg#(Maybe#(Bit#(2))) cLinesPrefetchedLatest <- mkReg(?); PulseWire holdReadReq <- mkPulseWire; rule sendReadReq if (!holdReadReq); @@ -1467,7 +1467,7 @@ provisos( rule createPrefetchRequests; match {.se, .addr, .pcHash} = strideEntryForPrefetch.first; //If this rule is looping, then we'll have a valid cLinesPrefetchedLatest - Bit#(4) cLinesPrefetched = fromMaybe(se.cLinesPrefetched, cLinesPrefetchedLatest); + Bit#(2) cLinesPrefetched = fromMaybe(se.cLinesPrefetched, cLinesPrefetchedLatest); if (se.state == STEADY && cLinesPrefetched != From 8e3d6409c056b5530c4b0b8f10f1f800d61147ba Mon Sep 17 00:00:00 2001 From: Karlis Susters Date: Sat, 15 Apr 2023 15:37:59 +0300 Subject: [PATCH 10/12] Simplified Stride2 code, using Int type --- .../RISCY_OOO/coherence/src/Prefetcher.bsv | 26 +++++++------------ 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/src_Core/RISCY_OOO/coherence/src/Prefetcher.bsv b/src_Core/RISCY_OOO/coherence/src/Prefetcher.bsv index f4d517f..9c0b239 100644 --- a/src_Core/RISCY_OOO/coherence/src/Prefetcher.bsv +++ b/src_Core/RISCY_OOO/coherence/src/Prefetcher.bsv @@ -1357,7 +1357,7 @@ typedef enum { typedef struct { Bit#(12) lastAddr; - Bit#(13) stride; + Int#(13) stride; Bit#(2) cLinesPrefetched; //Stores how many cache lines have been prefetched for this instruction StrideState2 state; } StrideEntry2 deriving (Bits, Eq, FShow); @@ -1398,7 +1398,7 @@ provisos( StrideEntry2 se = strideTable.rdResp; strideTable.deqRdResp; StrideEntry2 seNext = se; - Bit#(13) observedStride = {1'b0, addr[11:0]} - {1'b0, se.lastAddr}; + Int#(13) observedStride = unpack({1'b0, addr[11:0]} - {1'b0, se.lastAddr}); $writeh("%t Stride Prefetcher updateStrideEntry ", $time, fshow(hitMiss), " ", addr, ". Entry ", index, " state is ", fshow(se.state)); @@ -1473,23 +1473,15 @@ provisos( cLinesPrefetched != fromInteger(valueof(cLinesAheadToPrefetch))) begin //can prefetch - - 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; + + Int#(13) cLineSize = fromInteger(valueof(DataSz)); + Int#(13) strideToUse = se.stride; + if (abs(strideToUse) < cLineSize) begin + strideToUse = (strideToUse < 0) ? -cLineSize : cLineSize; end - let reqAddr = addr + - (signExtend(strideToUse) * zeroExtend(cLinesPrefetched + 1)); + Bit#(13) jumpDist = pack(strideToUse) * zeroExtend(cLinesPrefetched+1); + let reqAddr = addr + signExtend(jumpDist); addrToPrefetch.enq(reqAddr); // We will still be processing this StrideEntry next cycle, From cc65297cf90bc8a3b2faf682615d5ed401b42ab8 Mon Sep 17 00:00:00 2001 From: Karlis Susters Date: Sat, 15 Apr 2023 15:49:34 +0300 Subject: [PATCH 11/12] simplified simple stride slightly --- src_Core/RISCY_OOO/coherence/src/Prefetcher.bsv | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/src_Core/RISCY_OOO/coherence/src/Prefetcher.bsv b/src_Core/RISCY_OOO/coherence/src/Prefetcher.bsv index 9c0b239..8c4cf4d 100644 --- a/src_Core/RISCY_OOO/coherence/src/Prefetcher.bsv +++ b/src_Core/RISCY_OOO/coherence/src/Prefetcher.bsv @@ -1513,7 +1513,7 @@ endmodule typedef struct { Addr lastAddr; - Bit#(13) stride; + Int#(13) stride; Bit#(2) confidence; } SimpleStrideEntry deriving (Bits, Eq, FShow); @@ -1530,14 +1530,14 @@ provisos( Vector#(strideTableSize, Reg#(SimpleStrideEntry)) strideTable <- replicateM(mkReg(unpack(0))); Reg#(Addr) addrToPrefetch <- mkReg(0); - Reg#(Bit#(13)) strideToPrefetch <- mkReg(0); + Reg#(Int#(13)) strideToPrefetch <- mkReg(0); Ehr#(2, Bit#(3)) prefetchesIssued <- mkEhr(fromInteger(valueOf(cLinesAheadToPrefetch))); method Action reportAccess(Addr addr, Bit#(16) pcHash, HitOrMiss hitMiss); $display("%t report access %x %x", $time, addr, pcHash); strideTableIndexT idx = truncate(pcHash); SimpleStrideEntry entry = strideTable[idx]; - Bit#(13) calc_stride = truncate(addr - entry.lastAddr); + Int#(13) calc_stride = unpack(truncate(addr - entry.lastAddr)); $display("found stride %x", entry.stride); entry.lastAddr = addr; if (calc_stride == entry.stride) begin @@ -1566,18 +1566,15 @@ provisos( method ActionValue#(Addr) getNextPrefetchAddr if (prefetchesIssued[0] < fromInteger(valueOf(cLinesAheadToPrefetch))); - Bit#(13) strideToUse; - Bit#(13) cLineSize = fromInteger(valueof(DataSz)); + Int#(13) strideToUse = strideToPrefetch; + Int#(13) cLineSize = fromInteger(valueof(DataSz)); if (abs(strideToPrefetch) < cLineSize) begin - strideToUse = (strideToPrefetch[12] == 1) ? -cLineSize : cLineSize; - end - else begin - strideToUse = strideToPrefetch; + strideToUse = (strideToPrefetch < 0) ? -cLineSize : cLineSize; end prefetchesIssued[0] <= prefetchesIssued[0] + 1; let reqAddr = addrToPrefetch + - (signExtend(strideToUse) * zeroExtend(prefetchesIssued[0] + 1)); + (pack(signExtend(strideToUse)) * zeroExtend(prefetchesIssued[0] + 1)); check(reqAddr[63:12] == addrToPrefetch[63:12]); $display("%t getprefetchaddr ret %x", $time, reqAddr); From 4bc04b581da7db8bff4a38eb742f3260f5a5f7db Mon Sep 17 00:00:00 2001 From: Karlis Susters Date: Wed, 19 Apr 2023 14:22:01 +0300 Subject: [PATCH 12/12] Config for L1I MultiWindowTarget-2 --- builds/Resources/Include_RISCY_Config.mk | 6 +++--- src_Core/RISCY_OOO/coherence/src/Prefetcher.bsv | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/builds/Resources/Include_RISCY_Config.mk b/builds/Resources/Include_RISCY_Config.mk index 78005ab..888b825 100644 --- a/builds/Resources/Include_RISCY_Config.mk +++ b/builds/Resources/Include_RISCY_Config.mk @@ -45,10 +45,10 @@ SIM_LLC_ARBITER_LAT ?= # default check cache deadlock and rename error CHECK_DEADLOCK ?= true RENAME_DEBUG ?= false -INSTR_PREFETCHER_LOCATION ?= NONE -INSTR_PREFETCHER_TYPE ?= MULTI_WINDOW +INSTR_PREFETCHER_LOCATION ?= L1 +INSTR_PREFETCHER_TYPE ?= MULTI_WINDOW_TARGET DATA_PREFETCHER_LOCATION ?= NONE -DATA_PREFETCHER_TYPE ?= STRIDE +DATA_PREFETCHER_TYPE ?= MARKOV_ON_HIT_2 # clk frequency depends on core size ifneq (,$(filter $(CORE_SIZE),TINY SMALL BOOM MEDIUM)) diff --git a/src_Core/RISCY_OOO/coherence/src/Prefetcher.bsv b/src_Core/RISCY_OOO/coherence/src/Prefetcher.bsv index 8c4cf4d..b8a0ab8 100644 --- a/src_Core/RISCY_OOO/coherence/src/Prefetcher.bsv +++ b/src_Core/RISCY_OOO/coherence/src/Prefetcher.bsv @@ -816,14 +816,14 @@ provisos( Vector#(numWindows, Reg#(windowIdxT)) shiftReg <- genWithM(compose(mkReg, fromInteger)); Reg#(LineAddr) lastChildRequest <- mkReg(0); - TargetTableBRAM#(64, 8) targetTable <- mkTargetTableBRAM; + TargetTableBRAM#(8192, 2048) targetTable <- mkTargetTableBRAM; FIFOF#(LineAddr) targetTableReadResp <- mkBypassFIFOF; Reg#(Vector#(numLastRequests, Bit#(32))) lastTargetRequests <- mkReg(replicate(0)); rule sendReadReq; if (!elem(hash(lastChildRequest), lastTargetRequests)) begin targetTable.readReq(lastChildRequest); - $display("%t Prefetcher sending target read request for %h", $time, lastChildRequest); + $display("%t Prefetcher sending target read request for %h", $time, Addr'{lastChildRequest, 'h0}); lastTargetRequests <= shiftInAt0(lastTargetRequests, hash(lastChildRequest)); end endrule