diff --git a/src_Core/CPU/Core.bsv b/src_Core/CPU/Core.bsv index 0783e1e..7ce2467 100644 --- a/src_Core/CPU/Core.bsv +++ b/src_Core/CPU/Core.bsv @@ -650,6 +650,7 @@ module mkCore#(CoreId coreId)(Core); method stbEmpty = stb.isEmpty; method stqEmpty = lsq.stqEmpty; method lsqSetAtCommit = lsq.setAtCommit; + method lookupPAddr = lsq.lookupPAddr; method pauseCommit = coreFix.pendingIncorrectSpec; method tlbNoPendingReq = iTlb.noPendingReq && dTlb.noPendingReq; diff --git a/src_Core/RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv b/src_Core/RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv index cdc1fd1..8e14907 100644 --- a/src_Core/RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv +++ b/src_Core/RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv @@ -60,6 +60,7 @@ import RenameDebugIF::*; import CHERICap::*; import CHERICC_Fat::*; import ISA_Decls_CHERI::*; +import RegFile::*; // Just for the interface `ifdef PERFORMANCE_MONITORING import StatCounters::*; `endif @@ -106,6 +107,8 @@ interface CommitInput; method Bool stqEmpty; // notify LSQ that inst has reached commit interface Vector#(SupSize, Put#(LdStQTag)) lsqSetAtCommit; + // method for getting translated addresses for tracing. + interface Vector#(SupSize, RegFile#(LdStQTag, Addr)) lookupPAddr; // TLB has stopped processing now method Bool tlbNoPendingReq; // Pause committing, probably for buffered wrongSpec @@ -213,7 +216,7 @@ typedef struct { Data mtvec; } TraceStateBundle deriving(Bits, FShow); -function Maybe#(RVFI_DII_Execution#(DataSz,DataSz)) genRVFI(ToReorderBuffer rot, Dii_Id traceCnt, TraceStateBundle tsb, Data next_pc); +function Maybe#(RVFI_DII_Execution#(DataSz,DataSz)) genRVFI(ToReorderBuffer rot, Dii_Id traceCnt, TraceStateBundle tsb, Data next_pc, Addr paddr); Addr addr = 0; Data data = 0; Data wdata = 0; @@ -230,6 +233,9 @@ function Maybe#(RVFI_DII_Execution#(DataSz,DataSz)) genRVFI(ToReorderBuffer rot, case (rot.ppc_vaddr_csrData) matches tagged VAddr .vaddr: begin addr = vaddr; +`ifdef PADDR_RVFI + addr = paddr; +`endif case (rot.lsqTag) matches tagged Ld .l: rmask = rot.traceBundle.memByteEn; tagged St .s: begin @@ -800,7 +806,7 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage); }); `ifdef RVFI Rvfi_Traces rvfis = replicate(tagged Invalid); - rvfis[0] = genRVFI(trap.x, traceCnt, getTSB(), getAddr(new_pc)); + rvfis[0] = genRVFI(trap.x, traceCnt, getTSB(), getAddr(new_pc), inIfc.lookupPAddr[0].sub(trap.x.lsqTag)); rvfiQ.enq(rvfis); traceCnt <= traceCnt + 1; `endif @@ -969,7 +975,7 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage); Rvfi_Traces rvfis = replicate(tagged Invalid); x.ppc_vaddr_csrData = tagged PPC next_pc; CapPipe cp = cast(next_pc); - rvfis[0] = genRVFI(x, traceCnt, getTSB(), getOffset(cp)); + rvfis[0] = genRVFI(x, traceCnt, getTSB(), getOffset(cp), inIfc.lookupPAddr[0].sub(x.lsqTag)); rvfiQ.enq(rvfis); traceCnt <= traceCnt + 1; `endif @@ -1147,7 +1153,7 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage); if (verbose) $display("%t : [doCommitNormalInst - %d] ", $time(), i, fshow(inst_tag), " ; ", fshow(x)); `ifdef RVFI CapPipe pipePc = cast(x.pc); - rvfis[i] = genRVFI(x, traceCnt + zeroExtend(whichTrace), getTSB(), getOffset(pipePc) + (is_16b_inst(x.orig_inst) ? 2:4)); + rvfis[i] = genRVFI(x, traceCnt + zeroExtend(whichTrace), getTSB(), getOffset(pipePc) + (is_16b_inst(x.orig_inst) ? 2:4), inIfc.lookupPAddr[i].sub(x.lsqTag)); whichTrace = whichTrace + 1; `endif diff --git a/src_Core/RISCY_OOO/procs/lib/SplitLSQ.bsv b/src_Core/RISCY_OOO/procs/lib/SplitLSQ.bsv index 6513a8c..e7d8cba 100644 --- a/src_Core/RISCY_OOO/procs/lib/SplitLSQ.bsv +++ b/src_Core/RISCY_OOO/procs/lib/SplitLSQ.bsv @@ -51,6 +51,7 @@ import StoreBuffer::*; import Exec::*; import FP_Utils::*; import CacheUtils::*; // For CLoadTags alignment +import RegFile::*; // Just for the interface // I don't want to export auxiliary functions, so manually export all types export LdQMemFunc(..); @@ -439,6 +440,8 @@ interface SplitLSQ; // Sc/Amo/Fence, and flush L1 cache. method StQDeqEntry firstSt; method Action deqSt; + // method for reporting the physical address of an entry used for tracing. + interface Vector#(SupSize, RegFile#(LdStQTag, Addr)) lookupPAddr; `ifdef TSO_MM // Kill loads when a cache line is evicted (TSO only) method Action cacheEvict(LineAddr a); @@ -949,7 +952,17 @@ module mkSplitLSQ(SplitLSQ); // make wrongSpec conflict with all others (but not correctSpec method and // findIssue) - PulseWire wrongSpec_conflict <- mkPulseWire; + RWire#(void) wrongSpec_hit_conflict <- mkRWire; + RWire#(void) wrongSpec_enqIss_conflict <- mkRWire; + RWire#(void) wrongSpec_enq_conflict <- mkRWire; + RWire#(void) wrongSpec_cacheEvict_conflict <- mkRWire; + RWire#(void) wrongSpec_update_conflict <- mkRWire; + RWire#(void) wrongSpec_issue_conflict <- mkRWire; + RWire#(void) wrongSpec_respLd_conflict <- mkRWire; + RWire#(void) wrongSpec_deqLd_conflict <- mkRWire; + RWire#(void) wrongSpec_deqSt_conflict <- mkRWire; + RWire#(void) wrongSpec_verify_conflict <- mkRWire; + RWire#(void) wrongSpec_wakeBySB_conflict <- mkRWire; // make wrongSpec more urgent than firstSt (resolve bsc error) Wire#(Bool) wrongSpec_urgent_firstSt <- mkDWire(True); Map#(Bit#(10),Bit#(6),Int#(3),2) ldKillMap <- mkMapLossy(minBound); @@ -1135,7 +1148,7 @@ module mkSplitLSQ(SplitLSQ); end endrule - rule enqIssueQ(issueLdInfo.wget matches tagged Valid .info &&& !wrongSpec_conflict); + rule enqIssueQ(issueLdInfo.wget matches tagged Valid .info); if(verbose) begin $display("[LSQ - enqIss] ", fshow(info)); end @@ -1177,6 +1190,8 @@ module mkSplitLSQ(SplitLSQ); spec_bits: ld_specBits_enqIss[info.tag] }); ld_inIssueQ_enqIss[info.tag] <= True; + // make conflict with incorrect spec + wrongSpec_enqIss_conflict.wset(?); endrule // Verify SQ entry one by one @@ -1199,8 +1214,7 @@ module mkSplitLSQ(SplitLSQ); // NOTE that when SQ is full and all verified, verifyP will point to a // valid and verified entry rule verifySt(st_valid_verify[st_verifyP_verify] && - !st_verified_verify[st_verifyP_verify] && - !wrongSpec_conflict); + !st_verified_verify[st_verifyP_verify]); StQTag verP = st_verifyP_verify; // check if the entry can be verified. We should not fire this rule if @@ -1250,6 +1264,9 @@ module mkSplitLSQ(SplitLSQ); joinActions(map(setVerified, idxVec)); if(verbose) $display("[LSQ - verifySt] st_verifyP %d", verP); + + // make conflict with incorrect spec + wrongSpec_verify_conflict.wset(?); endrule `ifdef BSIM @@ -1415,6 +1432,16 @@ module mkSplitLSQ(SplitLSQ); endinterface); end + RegFile#(LdStQTag, Addr) lookupAPAddr = (interface RegFile; + method Addr sub(LdStQTag t); + case (t) matches + tagged Ld .l: return ld_paddr_deqLd[l]; + tagged St .s: return st_paddr_deqSt[s]; + endcase + endmethod + method upd = ?; + endinterface); + method ByteOrTagEn getOrigBE(LdStQTag t); return (case(t) matches tagged Ld .tag: (ld_byteOrTagEn[tag]); @@ -1423,7 +1450,10 @@ module mkSplitLSQ(SplitLSQ); endcase); endmethod - method ActionValue#(LSQHitInfo) getHit(LdStQTag t) if (!wrongSpec_conflict); + method ActionValue#(LSQHitInfo) getHit(LdStQTag t); + // Conflict with wrong spec. This makes cache pipelineResp rule + // conflict with wrong spec, and can help avoid scheduling cycle. + wrongSpec_hit_conflict.wset(?); return (case(t) matches tagged Ld .tag: (LSQHitInfo { waitWPResp: ld_waitWPResp_hit[tag], @@ -1448,7 +1478,7 @@ module mkSplitLSQ(SplitLSQ); MemInst mem_inst, Maybe#(PhyDst) dst, SpecBits spec_bits, - Bit#(16) pc_hash) if(ld_can_enq_wire && !wrongSpec_conflict); + Bit#(16) pc_hash) if(ld_can_enq_wire); if(verbose) begin $display("[LSQ - enqLd] enqP %d; ", ld_enqP, "; ", fshow(inst_tag), @@ -1501,12 +1531,14 @@ module mkSplitLSQ(SplitLSQ); ld_olderSt_enq[ld_enqP] <= Invalid; ld_olderStVerified_enq[ld_enqP] <= False; end + // make conflict with incorrect spec + wrongSpec_enq_conflict.wset(?); endmethod method Action enqSt(InstTag inst_tag, MemInst mem_inst, Maybe#(PhyDst) dst, - SpecBits spec_bits) if(st_can_enq_wire && !wrongSpec_conflict); + SpecBits spec_bits) if(st_can_enq_wire); if(verbose) begin $display("[LSQ - enqSt] enqP %d; ", st_enqP, "; ", fshow(inst_tag), @@ -1535,6 +1567,8 @@ module mkSplitLSQ(SplitLSQ); st_verified_enq[st_enqP] <= False; st_specBits_enq[st_enqP] <= spec_bits; st_atCommit_enq[st_enqP] <= False; + // make conflict with incorrect spec + wrongSpec_enq_conflict.wset(?); endmethod method Action updateData(StQTag t, MemTaggedData d); @@ -1549,7 +1583,7 @@ module mkSplitLSQ(SplitLSQ); method ActionValue#(LSQUpdateAddrResult) updateAddr( LdStQTag lsqTag, Maybe#(Trap) fault, Bool allowCap, Addr pa, Bool mmio, ByteOrTagEn shift_be - ) if (!wrongSpec_conflict); + ); // index vec for vector functions Vector#(LdQSize, LdQTag) idxVec = genWith(fromInteger); @@ -1715,6 +1749,9 @@ module mkSplitLSQ(SplitLSQ); end end + // make conflict with incorrect spec + wrongSpec_update_conflict.wset(?); + // return waiting for wp resp bit: for deciding whether the updating Ld // can be issued return LSQUpdateAddrResult { @@ -1729,7 +1766,7 @@ module mkSplitLSQ(SplitLSQ); method ActionValue#(LSQIssueLdResult) issueLd(LdQTag tag, Addr pa, ByteOrTagEn shift_be, - SBSearchRes sbRes) if (!wrongSpec_conflict); + SBSearchRes sbRes); if(verbose) begin $display("[LSQ - issueLd] ", fshow(tag), "; ", fshow(pa), "; ", fshow(shift_be), "; ", fshow(sbRes)); @@ -1998,6 +2035,9 @@ module mkSplitLSQ(SplitLSQ); end `endif + // make conflict with incorrect spec + wrongSpec_issue_conflict.wset(?); + return issRes; endmethod @@ -2014,7 +2054,7 @@ module mkSplitLSQ(SplitLSQ); return issueLdQ.first.data; endmethod - method ActionValue#(LSQRespLdResult) respLd(LdQTag t, MemTaggedData alignedData) if (!wrongSpec_conflict); + method ActionValue#(LSQRespLdResult) respLd(LdQTag t, MemTaggedData alignedData); let res = LSQRespLdResult { wrongPath: False, dst: Invalid, @@ -2063,6 +2103,8 @@ module mkSplitLSQ(SplitLSQ); $display("[LSQ - respLd] ", fshow(t), "; ", fshow(alignedData), "; ", fshow(res)); end + // make conflict with incorrect spec + wrongSpec_respLd_conflict.wset(?); // return return res; endmethod @@ -2087,7 +2129,7 @@ module mkSplitLSQ(SplitLSQ); }; endmethod - method Action deqLd if(deqLdGuard && !wrongSpec_conflict); + method Action deqLd if(deqLdGuard); LdQTag deqP = ld_deqP_deqLd; if(verbose) $display("[LSQ - deqLd] deqP %d", deqP); @@ -2134,6 +2176,9 @@ module mkSplitLSQ(SplitLSQ); endfunction Vector#(LdQSize, LdQTag) idxVec = genWith(fromInteger); joinActions(map(setReady, idxVec)); + + // make conflict with incorrect spec + wrongSpec_deqLd_conflict.wset(?); endmethod method StQDeqEntry firstSt if(deqStGuard && wrongSpec_urgent_firstSt); @@ -2154,7 +2199,7 @@ module mkSplitLSQ(SplitLSQ); }; endmethod - method Action deqSt if(deqStGuard && !wrongSpec_conflict); + method Action deqSt if(deqStGuard); StQTag deqP = st_deqP; if(verbose) $display("[LSQ - deqSt] deqP %d", deqP); @@ -2202,10 +2247,15 @@ module mkSplitLSQ(SplitLSQ); endfunction Vector#(LdQSize, LdQTag) idxVec = genWith(fromInteger); joinActions(map(resetSt, idxVec)); + + // make conflict with incorrect spec + wrongSpec_deqSt_conflict.wset(?); endmethod + interface lookupPAddr = replicate(lookupAPAddr); + `ifdef TSO_MM - method Action cacheEvict(LineAddr lineAddr) if (!wrongSpec_conflict); + method Action cacheEvict(LineAddr lineAddr); if(verbose) $display("[LSQ - cacheEvict] ", fshow(lineAddr)); // kill a load if it satisfies the following conditions: // (1) valid @@ -2235,11 +2285,14 @@ module mkSplitLSQ(SplitLSQ); doAssert(!ld_isMMIO_evict[killTag], "cannot kill MMIO"); doAssert(ld_memFunc[killTag] == Ld, "can only kill Ld"); end + + // make conflict with incorrect spec + wrongSpec_cacheEvict_conflict.wset(?); endmethod `else - method Action wakeupLdStalledBySB(SBIndex sbIdx) if (!wrongSpec_conflict); + method Action wakeupLdStalledBySB(SBIndex sbIdx); if(verbose) begin $display("[LSQ - wakeupBySB] ", fshow(sbIdx)); end @@ -2254,6 +2307,8 @@ module mkSplitLSQ(SplitLSQ); endfunction Vector#(LdQSize, LdQTag) idxVec = genWith(fromInteger); joinActions(map(setReady, idxVec)); + // make conflict with incorrect spec + wrongSpec_wakeBySB_conflict.wset(?); endmethod `endif @@ -2398,7 +2453,17 @@ module mkSplitLSQ(SplitLSQ); end // make conflict with others - wrongSpec_conflict.send(); + wrongSpec_hit_conflict.wset(?); + wrongSpec_enqIss_conflict.wset(?); + wrongSpec_enq_conflict.wset(?); + wrongSpec_update_conflict.wset(?); + wrongSpec_issue_conflict.wset(?); + wrongSpec_respLd_conflict.wset(?); + wrongSpec_deqLd_conflict.wset(?); + wrongSpec_deqSt_conflict.wset(?); + wrongSpec_verify_conflict.wset(?); + wrongSpec_cacheEvict_conflict.wset(?); + wrongSpec_wakeBySB_conflict.wset(?); // more urgent than firstSt wrongSpec_urgent_firstSt <= True; endmethod