diff --git a/src_Core/RISCY_OOO/coherence/src/LLBank.bsv b/src_Core/RISCY_OOO/coherence/src/LLBank.bsv index b1db9ff..ca59dc3 100644 --- a/src_Core/RISCY_OOO/coherence/src/LLBank.bsv +++ b/src_Core/RISCY_OOO/coherence/src/LLBank.bsv @@ -415,8 +415,9 @@ endfunction ); endrule - // insert new cRq from child to MSHR and send to pipeline - rule createDataPrefetchRq(newCRqSrc == Valid (Child)); + // 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; cRqT cRq = LLRq { addr: addr, @@ -444,8 +445,9 @@ endfunction ); endrule - // insert new cRq from child to MSHR and send to pipeline - rule createInstrPrefetchRq(newCRqSrc == Valid (Child)); + // 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; cRqT cRq = LLRq { addr: addr, @@ -609,7 +611,9 @@ endfunction ); // performance counter: normal miss lat and cnt // Check lowest bit of child ID to determine if this was an ICache access - incrMissCnt(n, False, cRq.child[0] == 1); + if (!cRqIsPrefetch[n]) begin + incrMissCnt(n, False, cRq.child[0] == 1); + end endrule // this mem resp is just for a DMA req, won't go into pipeline to refill cache diff --git a/src_Core/RISCY_OOO/coherence/src/Prefetcher.bsv b/src_Core/RISCY_OOO/coherence/src/Prefetcher.bsv index 6529ed6..e5cfdf7 100644 --- a/src_Core/RISCY_OOO/coherence/src/Prefetcher.bsv +++ b/src_Core/RISCY_OOO/coherence/src/Prefetcher.bsv @@ -129,7 +129,7 @@ module mkNextLinePrefetcherBackwards(Prefetcher) endmodule module mkSingleWindowPrefetcher(Prefetcher); - Integer cacheLinesInRange = 3; + Integer cacheLinesInRange = 2; Reg#(LineAddr) rangeEnd <- mkReg(0); //Points to one CLine after end of range Reg#(LineAddr) nextToAsk <- mkReg(0); method Action reportHit(Addr hitAddr); @@ -195,8 +195,7 @@ provisos( function ActionValue#(Maybe#(windowIdxT)) getMatchingWindow(Addr addr) = actionvalue - //Finds the first window that contains addr, - //and moves it to the front of the LRU shift reg + //Finds the first window that contains addr let cl = getLineAddr(addr); function Bool pred(StreamEntry se); //TODO < gives 100 cycles less?????? @@ -268,6 +267,89 @@ provisos( endmodule +typedef 64 TargetTableSize; +typedef struct { + Bit#(targetTableTagBits) tag; + LineAddr target; +} TargetEntry#(numeric type targetTableTagBits) deriving (Bits, Eq, FShow); + +module mkSingleWindowTargetPrefetcher(Prefetcher) provisos +( + NumAlias#(targetTableIdxBits, TLog#(TargetTableSize)), + NumAlias#(targetTableTagBits, TSub#(32, targetTableIdxBits)), + Alias#(targetEntryT, TargetEntry#(targetTableTagBits)) +); + Integer cacheLinesInRange = 2; + Reg#(LineAddr) rangeEnd <- mkReg(0); //Points to one CLine after end of range + Reg#(LineAddr) nextToAsk <- mkReg(0); + Reg#(LineAddr) lastChildRequest <- mkReg(0); + Vector#(TargetTableSize, Reg#(Maybe#(targetEntryT))) targetTable <- replicateM(mkReg(Invalid)); + method Action reportHit(Addr hitAddr); + let cl = getLineAddr(hitAddr); + if (rangeEnd - fromInteger(cacheLinesInRange) - 1 < cl && cl < rangeEnd) begin + let nextEnd = cl + fromInteger(cacheLinesInRange) + 1; + rangeEnd <= nextEnd; + if (nextToAsk <= cl) nextToAsk <= cl + 1; + $display("%t Prefetcher reportHit %h, moving window end to %h", $time, hitAddr, Addr'{nextEnd, '0}); + end + /* + else if (rangeEnd - fromInteger(cacheLinesInRange) - 1 != cl) begin + //If hit outside window, reallocate window (test!) + nextToAsk <= cl + 1; + rangeEnd <= cl + fromInteger(cacheLinesInRange) + 1; + $display("%t Prefetcher reportHit %h, allocate new window", $time, hitAddr); + end + */ + if (cl != lastChildRequest + 1 && cl != lastChildRequest && cl != lastChildRequest - 1) begin + //Add entry to target table + targetEntryT entry; + entry.tag = lastChildRequest[31:valueOf(targetTableIdxBits)]; + entry.target = cl; + Bit#(targetTableIdxBits) idx = truncate(lastChildRequest); + targetTable[idx] <= tagged Valid entry; + $display("%t Prefetcher reportHit %h, add target entry from %h", $time, hitAddr, Addr'{lastChildRequest, '0}); + end + lastChildRequest <= cl; + endmethod + method Action reportMiss(Addr missAddr); + $display("%t Prefetcher reportMiss %h", $time, missAddr); + let cl = getLineAddr(missAddr); + nextToAsk <= cl + 1; + rangeEnd <= cl + fromInteger(cacheLinesInRange) + 1; + if (cl != lastChildRequest + 1 && cl != lastChildRequest && cl != lastChildRequest - 1) begin + //Add entry to target table + $display("%t Prefetcher reportMiss %h, add target entry from %h", $time, missAddr, Addr'{lastChildRequest, '0}); + targetEntryT entry; + entry.tag = lastChildRequest[31:valueOf(targetTableIdxBits)]; + entry.target = cl; + Bit#(targetTableIdxBits) idx = truncate(lastChildRequest); + targetTable[idx] <= tagged Valid entry; + end + lastChildRequest <= cl; + endmethod + method ActionValue#(Addr) getNextPrefetchAddr if (nextToAsk != rangeEnd); + Addr retAddr; + let lastAsked = nextToAsk-1; + Bit#(targetTableIdxBits) idx = truncate(lastAsked); + if (targetTable[idx] matches tagged Valid .entry + &&& entry.tag == (lastAsked)[31:valueOf(targetTableIdxBits)]) begin + //If have valid entry for the last requested cline, prefetch the stored target first + //Reset table entry, so on further calls we prefetch the next successive clines + //If we actually take the jump, the table entry will be restored + targetTable[idx] <= Invalid; + retAddr = {entry.target, '0}; + $display("%t Prefetcher getNextPrefetchAddr requesting target entry %h", $time, retAddr); + end + else begin + //If no table entry, prefetch further in window + nextToAsk <= nextToAsk + 1; + retAddr = {nextToAsk, '0}; //extend cache line address to regular address + $display("%t Prefetcher getNextPrefetchAddr requesting next-line %h", $time, retAddr); + end + return retAddr; + endmethod +endmodule + interface PCPrefetcher; method Action reportAccess(Addr addr, Bit#(16) pcHash, HitOrMiss hitMiss); method ActionValue#(Addr) getNextPrefetchAddr(); @@ -514,7 +596,8 @@ module mkL1IPrefetcher(Prefetcher); //let m <- mkNextLinePrefetcher; //let m <- mkMultiWindowPrefetcher; //let m <- mkNextLineOnAllPrefetcher; - let m <- mkDoNothingPrefetcher; + //let m <- mkDoNothingPrefetcher; + let m <- mkSingleWindowTargetPrefetcher; return m; endmodule @@ -527,16 +610,18 @@ endmodule module mkLLIPrefetcher(Prefetcher); //let m <- mkNextLineOnMissPrefetcher; - let m <- mkMultiWindowPrefetcher; + //let m <- mkMultiWindowPrefetcher; + //let m <- mkSingleWindowPrefetcher; + //let m <- mkSingleWindowTargetPrefetcher; //let m <- mkStridePCPrefetcher2; //let m <- mkPrintPrefetcher; - //let m <- mkDoNothingPrefetcher; + let m <- mkDoNothingPrefetcher; return m; endmodule module mkLLDPrefetcher(Prefetcher); //let m <- mkNextLineOnAllPrefetcher; - let m <- mkPrintPrefetcher; - //let m <- mkDoNothingPrefetcher; + //let m <- mkPrintPrefetcher; + let m <- mkDoNothingPrefetcher; return m; endmodule \ No newline at end of file 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 5b4c012..f3ebf86 100644 --- a/src_Core/RISCY_OOO/coherence/src/test/Prefetcher_test.bsv +++ b/src_Core/RISCY_OOO/coherence/src/test/Prefetcher_test.bsv @@ -104,6 +104,70 @@ module mkMultiWindowPrefetcherTest(Empty); ); endmodule +module mkSingleWindowTargetPrefetcherTest(Empty); + //let p <- mkMultipleWindowPrefetcher; + //TODO pass in value of cachelinesinrange + let p <- mkSingleWindowTargetPrefetcher; + mkAutoFSM( + seq + // ----- Send misses and stuff to one window ----- + action + p.reportMiss('h80000040); + endaction + action + let x <- p.getNextPrefetchAddr; + doAssert(x == 'h80000080, "test fail!"); + endaction + action + let x <- p.getNextPrefetchAddr; + doAssert(x == 'h800000c0, "test fail!"); + endaction + action + p.reportHit('h800000c0); //Report hit inside window + endaction + action + let x <- p.getNextPrefetchAddr; + doAssert(x == 'h80000100, "test fail!"); + endaction + action + p.reportHit('h80004000); //Report hit outside window + endaction + action + let x <- p.getNextPrefetchAddr; //Previous window still recommended + doAssert(x == 'h80000140, "test fail!"); + endaction + action + p.reportMiss('h80000140); //Report miss inside window + endaction + action + let x <- p.getNextPrefetchAddr; //Previous window still recommended + doAssert(x == 'h80000180, "test fail!"); + endaction + action + p.reportMiss('h81000000); //Report miss somewhere far away + endaction + action + let x <- p.getNextPrefetchAddr; //New window allocated and recommended + doAssert(x == 'h81000040, "test fail!"); + endaction + action + p.reportMiss('h80000100); //Report miss back home + endaction + action + let x <- p.getNextPrefetchAddr; + doAssert(x == 'h80000140, "test fail!"); + endaction + action + let x <- p.getNextPrefetchAddr; //target address recommended + doAssert(x == 'h81000000, "test fail!"); + endaction + action + let x <- p.getNextPrefetchAddr; + doAssert(x == 'h80000180, "test fail!"); // window addresss recommended + endaction + endseq + ); +endmodule module mkStridePCPrefetcher2Test(Empty); //let p <- mkMultipleWindowPrefetcher; @@ -246,4 +310,4 @@ module mkStridePCPrefetcherTest(Empty); endaction endseq ); -endmodule \ No newline at end of file +endmodule