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