diff --git a/src_Core/CPU/Core.bsv b/src_Core/CPU/Core.bsv index 3a4a004..ffe7360 100644 --- a/src_Core/CPU/Core.bsv +++ b/src_Core/CPU/Core.bsv @@ -175,8 +175,7 @@ module mkCore#(CoreId coreId)(Core); // ================================================================ // If using Direct Instruction Injection then make a - // bridge that can insert instructions as if it were - // an instruction cache. + // bridge that can insert instructions. `ifdef RVFI_DII Toooba_RVFI_DII_Bridge_IFC rvfi_bridge <- mkTooobaRVFIDIIBridge; mkConnection(rvfi_bridge.dii, fetchStage.dii); diff --git a/src_Core/RISCY_OOO/procs/RV64G_OOO/AluExePipeline.bsv b/src_Core/RISCY_OOO/procs/RV64G_OOO/AluExePipeline.bsv index 9d57edf..5a19f4a 100644 --- a/src_Core/RISCY_OOO/procs/RV64G_OOO/AluExePipeline.bsv +++ b/src_Core/RISCY_OOO/procs/RV64G_OOO/AluExePipeline.bsv @@ -84,6 +84,9 @@ typedef struct { ControlFlow controlFlow; // speculation Maybe#(SpecTag) spec_tag; +`ifdef RVFI + ExtraTraceBundle traceBundle; +`endif } AluExeToFinish deriving(Bits, Eq, FShow); // XXX currently ALU/Br should not have any exception, so we don't have cause feild above @@ -137,7 +140,14 @@ interface AluExeInput; method Addr rob_getPC(InstTag t); method Addr rob_getPredPC(InstTag t); method Bit #(32) rob_getOrig_Inst (InstTag t); - method Action rob_setExecuted(InstTag t, Maybe#(Data) csrData, ControlFlow cf); + method Action rob_setExecuted( + InstTag t, + Maybe#(Data) csrData, + ControlFlow cf +`ifdef RVFI + , ExtraTraceBundle tb +`endif + ); // Fetch stage method Action fetch_train_predictors(FetchTrainBP train); @@ -292,7 +302,13 @@ module mkAluExePipeline#(AluExeInput inIfc)(AluExePipeline); tag: x.tag, dpTrain: x.dpTrain, data: exec_result.data, - csrData: isValid(x.dInst.csr) ? Valid (exec_result.csrData) : Invalid, + csrData: isValid(x.dInst.csr) ? Valid (exec_result.csrData) : tagged Invalid, +`ifdef RVFI + traceBundle: ExtraTraceBundle{ + regWriteData: exec_result.data, + memByteEn: replicate(False) + }, +`endif controlFlow: exec_result.controlFlow, spec_tag: x.spec_tag }, @@ -317,6 +333,9 @@ module mkAluExePipeline#(AluExeInput inIfc)(AluExePipeline); x.tag, x.csrData, x.controlFlow +`ifdef RVFI + , x.traceBundle +`endif ); // handle spec tags for branch predictions diff --git a/src_Core/RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv b/src_Core/RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv index b4638df..40a6da9 100644 --- a/src_Core/RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv +++ b/src_Core/RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv @@ -132,6 +132,20 @@ typedef struct { `ifdef RVFI function RVFI_DII_Execution#(DataSz,DataSz) genRVFI(ToReorderBuffer rot); + Addr addr = 0; + Addr next_pc = rot.pc + 4; + Data data = rot.traceBundle.regWriteData; + case (rot.ppc_vaddr_csrData) matches + tagged VAddr .vaddr: addr = vaddr; + tagged PPC .ppc: next_pc = ppc; + tagged CSRData .csrdata: data = csrdata; + endcase + ByteEn rmask = replicate(False); + ByteEn wmask = replicate(False); + case (rot.lsqTag) matches + tagged Ld .l: rmask = rot.traceBundle.memByteEn; + tagged St .s: wmask = rot.traceBundle.memByteEn; + endcase return RVFI_DII_Execution { rvfi_order: 0, // Instruction number? InstID maybe? rvfi_trap: isValid(rot.trap), @@ -143,14 +157,14 @@ function RVFI_DII_Execution#(DataSz,DataSz) genRVFI(ToReorderBuffer rot); rvfi_rs1_data: ?, rvfi_rs2_data: ?, rvfi_pc_rdata: rot.pc, - rvfi_pc_wdata: rot.pc + 4, + rvfi_pc_wdata: next_pc, rvfi_mem_wdata: 0, rvfi_rd_addr: rot.orig_inst[11:7], - rvfi_rd_wdata: ?, - rvfi_mem_addr: 0, - rvfi_mem_rmask: 0, - rvfi_mem_wmask: 0, - rvfi_mem_rdata: 0 + rvfi_rd_wdata: ((rot.orig_inst[11:7]==0) ? 0:data), + rvfi_mem_addr: addr, + rvfi_mem_rmask: pack(rmask), + rvfi_mem_wmask: pack(wmask), + rvfi_mem_rdata: data }; endfunction `endif diff --git a/src_Core/RISCY_OOO/procs/RV64G_OOO/MemExePipeline.bsv b/src_Core/RISCY_OOO/procs/RV64G_OOO/MemExePipeline.bsv index 44b7086..e145f80 100644 --- a/src_Core/RISCY_OOO/procs/RV64G_OOO/MemExePipeline.bsv +++ b/src_Core/RISCY_OOO/procs/RV64G_OOO/MemExePipeline.bsv @@ -461,6 +461,20 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline); let x = dTlbResp.inst; let {paddr, cause} = dTlbResp.resp; +`ifdef RVFI_DII + // TestRIG expects us throw an access fault for any memory access outside of a 64-KiB memory at 0x8000000. + if (!isValid(cause) && (paddr < 'h80000000 || paddr >= 'h80010000)) begin + case(x.mem_func) + Ld, Lr: begin + cause = Valid (LoadAccessFault); + end + default: begin + cause = Valid (StoreAccessFault); + end + endcase + end +`endif + if(verbose) $display("[doFinishMem] ", fshow(dTlbResp)); if(isValid(cause) && verbose) $display(" [doFinishMem - dTlb response] PAGEFAULT!"); diff --git a/src_Core/RISCY_OOO/procs/lib/ReorderBuffer.bsv b/src_Core/RISCY_OOO/procs/lib/ReorderBuffer.bsv index c985e09..40deef4 100644 --- a/src_Core/RISCY_OOO/procs/lib/ReorderBuffer.bsv +++ b/src_Core/RISCY_OOO/procs/lib/ReorderBuffer.bsv @@ -44,6 +44,13 @@ typedef union tagged { Data CSRData; // for Csr inst, store csr_data } PPCVAddrCSRData deriving(Bits, Eq, FShow); +`ifdef RVFI +typedef struct { + Data regWriteData; + ByteEn memByteEn; +} ExtraTraceBundle deriving(Bits, Eq, FShow); +`endif + typedef struct { Addr pc; Bit #(32) orig_inst; // original 16b or 32b instruction ([1:0] will distinguish 16b or 32b) @@ -75,6 +82,9 @@ typedef struct { // speculation SpecBits spec_bits; +`ifdef RVFI + ExtraTraceBundle traceBundle; +`endif } ToReorderBuffer deriving(Bits, Eq, FShow); typedef enum { @@ -83,7 +93,13 @@ typedef enum { } RobInstState deriving (Bits, Eq, FShow); interface Row_setExecuted_doFinishAlu; - method Action set(Maybe#(Data) csrData, ControlFlow cf); + method Action set( + Maybe#(Data) csrData, + ControlFlow cf +`ifdef RVFI + , ExtraTraceBundle tb +`endif + ); endinterface interface Row_setExecuted_doFinishFpuMulDiv; @@ -186,6 +202,9 @@ module mkReorderBufferRowEhr(ReorderBufferRowEhr#(aluExeNum, fpuMulDivExeNum)) p Ehr#(2, Bool) nonMMIOStDone <- mkEhr(?); Reg#(Bool) epochIncremented <- mkRegU; Ehr#(3, SpecBits) spec_bits <- mkEhr(?); +`ifdef RVFI + Ehr#(TAdd#(2, aluExeNum), (ExtraTraceBundle)) traceBundle <- mkEhr(?); +`endif // wires to get stale (EHR port 0) values of PPC Wire#(Addr) predPcWire <- mkBypassWire; @@ -197,7 +216,13 @@ module mkReorderBufferRowEhr(ReorderBufferRowEhr#(aluExeNum, fpuMulDivExeNum)) p Vector#(aluExeNum, Row_setExecuted_doFinishAlu) aluSetExe; for(Integer i = 0; i < valueof(aluExeNum); i = i+1) begin aluSetExe[i] = (interface Row_setExecuted_doFinishAlu; - method Action set(Maybe#(Data) csrData, ControlFlow cf); + method Action set( + Maybe#(Data) csrData, + ControlFlow cf +`ifdef RVFI + , ExtraTraceBundle tb +`endif + ); // inst is done rob_inst_state[state_finishAlu_port(i)] <= Executed; // update PPC or csrData (vaddr is always useless for ALU results) @@ -207,6 +232,9 @@ module mkReorderBufferRowEhr(ReorderBufferRowEhr#(aluExeNum, fpuMulDivExeNum)) p else begin ppc_vaddr_csrData[pvc_finishAlu_port(i)] <= PPC (cf.nextPc); end +`ifdef RVFI + traceBundle[pvc_finishAlu_port(i)] <= tb; +`endif doAssert(isValid(csr) == isValid(csrData), "csr valid should match"); endmethod endinterface); @@ -281,6 +309,9 @@ module mkReorderBufferRowEhr(ReorderBufferRowEhr#(aluExeNum, fpuMulDivExeNum)) p ldKilled[ldKill_enq_port] <= Invalid; lsqAtCommitNotified[lsqNotified_enq_port] <= False; nonMMIOStDone[nonMMIOSt_enq_port] <= False; +`ifdef RVFI + traceBundle[pvc_enq_port] <= x.traceBundle; +`endif // check doAssert(!isValid(x.ldKilled), "ld killed must be false"); doAssert(x.memAccessAtCommit == False, "mem access at commit must be false"); @@ -307,6 +338,9 @@ module mkReorderBufferRowEhr(ReorderBufferRowEhr#(aluExeNum, fpuMulDivExeNum)) p lsqAtCommitNotified: lsqAtCommitNotified[lsqNotified_deq_port], nonMMIOStDone: nonMMIOStDone[nonMMIOSt_deq_port], epochIncremented: epochIncremented, +`ifdef RVFI + traceBundle: traceBundle[pvc_deq_port], +`endif spec_bits: spec_bits[sb_deq_port] }; endmethod @@ -379,7 +413,13 @@ endinterface // not raise false conflicts between the superscalar enq/deq actions interface ROB_setExecuted_doFinishAlu; - method Action set(InstTag x, Maybe#(Data) csrData, ControlFlow cf); + method Action set(InstTag x, + Maybe#(Data) csrData, + ControlFlow cf +`ifdef RVFI + , ExtraTraceBundle tb +`endif + ); endinterface interface ROB_setExecuted_doFinishFpuMulDiv; @@ -891,11 +931,22 @@ module mkSupReorderBuffer#( for(Integer i = 0; i < valueof(aluExeNum); i = i+1) begin aluSetExeIfc[i] = (interface ROB_setExecuted_doFinishAlu; method Action set( - InstTag x, Maybe#(Data) csrData, ControlFlow cf + InstTag x, + Maybe#(Data) csrData, + ControlFlow cf +`ifdef RVFI + , ExtraTraceBundle tb +`endif ) if( all(id, readVReg(setExeAlu_SB_enq)) // ordering: < enq ); - row[x.way][x.ptr].setExecuted_doFinishAlu[i].set(csrData, cf); + row[x.way][x.ptr].setExecuted_doFinishAlu[i].set( + csrData, + cf +`ifdef RVFI + , tb +`endif + ); endmethod endinterface); end diff --git a/src_Verifier/BSV-RVFI-DII b/src_Verifier/BSV-RVFI-DII index 2383117..380f77d 160000 --- a/src_Verifier/BSV-RVFI-DII +++ b/src_Verifier/BSV-RVFI-DII @@ -1 +1 @@ -Subproject commit 2383117b4be81fdae4734d7b7d42d090dfa9fbe1 +Subproject commit 380f77da5bbed8ce2b34fd177f4f4dee3cecfa67 diff --git a/src_Verifier/Toooba_RVFI_DII_Bridge.bsv b/src_Verifier/Toooba_RVFI_DII_Bridge.bsv index 378ff38..0f7e654 100644 --- a/src_Verifier/Toooba_RVFI_DII_Bridge.bsv +++ b/src_Verifier/Toooba_RVFI_DII_Bridge.bsv @@ -61,10 +61,11 @@ module mkTooobaRVFIDIIBridge(Toooba_RVFI_DII_Bridge_IFC); // DII state FIFOF#(Tuple2#(Bit#(32), Dii_Id)) dii_in <- mkUGFIFOF; Reg#(InstsAndIDs) buff <- mkConfigRegU; - FIFOF#(InstsAndIDs) instrs <- mkSizedFIFOF(128); + FIFOF#(InstsAndIDs) instrs <- mkSizedFIFOF(2048); + PulseWire putFromBridge <- mkPulseWire; // RVFI state - FIFO#(Rvfi_Traces) report_vectors <- mkSizedFIFO(128); - FIFO#(RVFI_DII_Execution#(DataSz,DataSz)) reports <- mkSizedFIFO(256); + FIFO#(Rvfi_Traces) report_vectors <- mkSizedFIFO(2048); + FIFO#(RVFI_DII_Execution#(DataSz,DataSz)) reports <- mkFIFO; // Request ID FIFO#(Dii_Id) seq_req <- mkFIFO; @@ -93,7 +94,7 @@ module mkTooobaRVFIDIIBridge(Toooba_RVFI_DII_Bridge_IFC); InstsAndIDs cb = buff; Bit#(32) ins = nop; Dii_Id id = ?; - if (dii_in.notEmpty) {ins, id} = dii_in.first; + if (dii_in.notEmpty) {ins, id} <- toGet(dii_in).get; cb.insts[buffLvl] = tagged Valid ins; cb.ids[buffLvl] = id; if (buffLvl == -1) begin @@ -106,14 +107,19 @@ module mkTooobaRVFIDIIBridge(Toooba_RVFI_DII_Bridge_IFC); interface Toooba_RVFI_DII_Server rvfi_dii_server; interface Get seqReq = toGet(seq_req); - interface Put inst = toPut(dii_in); + interface Put inst; + method Action put(Tuple2#(Bit#(32), Dii_Id) in) if (dii_in.notFull); + dii_in.enq(in); + putFromBridge.send(); + endmethod + endinterface interface Get trace_report = toGet(reports); endinterface interface Server dii; interface Put request = toPut(seq_req); interface Get response; - method ActionValue#(InstsAndIDs) get; + method ActionValue#(InstsAndIDs) get if (!putFromBridge); InstsAndIDs insts = instrs.first(); instrs.deq(); if (verbose)