From f101ad129ec68a2efc39868c5261891c85b566bf Mon Sep 17 00:00:00 2001 From: Jonathan Woodruff Date: Wed, 18 Dec 2019 15:49:42 +0000 Subject: [PATCH] Full RVFI flow-control integration with Toooba's flow control. This enables us to run all test classes successfully. --- src_Core/CPU/Core.bsv | 12 +- .../RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv | 36 ++++- .../RISCY_OOO/procs/RV64G_OOO/FetchStage.bsv | 128 ++++++++++++------ .../RISCY_OOO/procs/RV64G_OOO/RenameStage.bsv | 21 +++ src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv | 6 + .../RISCY_OOO/procs/lib/ReorderBuffer.bsv | 15 ++ 6 files changed, 170 insertions(+), 48 deletions(-) diff --git a/src_Core/CPU/Core.bsv b/src_Core/CPU/Core.bsv index 248d4d4..521497d 100644 --- a/src_Core/CPU/Core.bsv +++ b/src_Core/CPU/Core.bsv @@ -316,7 +316,11 @@ module mkCore#(CoreId coreId)(Core); "; ", fshow(spec_tag), "; ", fshow(inst_tag)); end epochManager.incrementEpoch; - fetchStage.redirect(new_pc); + fetchStage.redirect(new_pc +`ifdef RVFI_DII + , inst_tag.diid + 1 +`endif + ); globalSpecUpdate.incorrectSpec(False, spec_tag, inst_tag); endmethod method correctSpec = globalSpecUpdate.correctSpec[finishAluCorrectSpecPort(i)].put; @@ -931,7 +935,11 @@ module mkCore#(CoreId coreId)(Core); Bit#(64) startpc, Addr toHostAddr, Addr fromHostAddr ); - fetchStage.start(startpc); + fetchStage.start(startpc +`ifdef RVFI_DII + , 0 +`endif + ); started <= True; mmio.setHtifAddrs(toHostAddr, fromHostAddr); // start rename debug diff --git a/src_Core/RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv b/src_Core/RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv index f781671..3c39cf8 100644 --- a/src_Core/RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv +++ b/src_Core/RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv @@ -88,7 +88,11 @@ interface CommitInput; method Action setReconcileD; // recocile D$ // redirect method Action killAll; - method Action redirectPc(Addr trap_pc); + method Action redirectPc(Addr trap_pc +`ifdef RVFI_DII + , Dii_Id diid +`endif + ); method Action setFetchWaitRedirect; method Action incrementEpoch; // record if we commit a CSR inst or interrupt @@ -128,6 +132,9 @@ typedef struct { Addr pc; Addr addr; Trap trap; +`ifdef RVFI_DII + Dii_Id diid; +`endif } CommitTrap deriving(Bits, Eq, FShow); `ifdef RVFI @@ -140,7 +147,10 @@ function Maybe#(RVFI_DII_Execution#(DataSz,DataSz)) genRVFI(ToReorderBuffer rot, ByteEn wmask = replicate(False); if (!isValid(rot.trap)) begin next_pc = rot.pc + 4; - data = rot.traceBundle.regWriteData; // Default for register-to-register operations. + data = case (rot.iType) + St, Br: return 0; + default: return rot.traceBundle.regWriteData; // Default for register-to-register operations. + endcase; case (rot.ppc_vaddr_csrData) matches tagged VAddr .vaddr: begin addr = vaddr; @@ -148,7 +158,6 @@ function Maybe#(RVFI_DII_Execution#(DataSz,DataSz)) genRVFI(ToReorderBuffer rot, tagged Ld .l: rmask = rot.traceBundle.memByteEn; tagged St .s: begin wmask = rot.traceBundle.memByteEn; - data = 0; wdata = rot.traceBundle.regWriteData; end endcase @@ -428,6 +437,9 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage); trap: trap, pc: x.pc, addr: vaddr +`ifdef RVFI_DII + , diid: x.diid +`endif }); commitTrap <= commitTrap_val; @@ -486,7 +498,11 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage); // trap handling & redirect let new_pc <- csrf.trap(trap.trap, trap.pc, trap.addr); - inIfc.redirectPc(new_pc); + inIfc.redirectPc(new_pc +`ifdef RVFI_DII + , trap.diid + 1 +`endif + ); // system consistency // TODO spike flushes TLB here, but perhaps it is because spike's TLB @@ -508,7 +524,11 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage); // kill everything, redirect, and increment epoch inIfc.killAll; - inIfc.redirectPc(x.pc); + inIfc.redirectPc(x.pc +`ifdef RVFI_DII + , x.diid +`endif + ); inIfc.incrementEpoch; // the killed Ld should have claimed phy reg, we should not commit it; @@ -587,7 +607,11 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage); else if(x.iType == Mret) begin next_pc <- csrf.mret; end - inIfc.redirectPc(next_pc); + inIfc.redirectPc(next_pc +`ifdef RVFI_DII + , x.diid + 1 +`endif + ); // rename stage only sends out system inst when ROB is empty, so no // need to flush ROB again diff --git a/src_Core/RISCY_OOO/procs/RV64G_OOO/FetchStage.bsv b/src_Core/RISCY_OOO/procs/RV64G_OOO/FetchStage.bsv index 4d46a18..dbdc87e 100644 --- a/src_Core/RISCY_OOO/procs/RV64G_OOO/FetchStage.bsv +++ b/src_Core/RISCY_OOO/procs/RV64G_OOO/FetchStage.bsv @@ -72,12 +72,20 @@ interface FetchStage; interface MMIOInstToCore mmioIfc; // starting and stopping - method Action start(Addr pc); + method Action start(Addr pc +`ifdef RVFI_DII + , Dii_Id id +`endif + ); method Action stop(); // redirection methods method Action setWaitRedirect; - method Action redirect(Addr pc); + method Action redirect(Addr pc +`ifdef RVFI_DII + , Dii_Id id +`endif + ); method Action done_flushing(); method Action train_predictors( Addr pc, Addr next_pc, IType iType, Bool taken, @@ -149,6 +157,9 @@ typedef struct { ArchRegs regs; Maybe#(Exception) cause; Addr tval; // in case of exception +`ifdef RVFI_DII + Dii_Id diid; +`endif } FromFetchStage deriving (Bits, Eq, FShow); // train next addr pred (BTB) @@ -244,6 +255,9 @@ function ActionValue #(Vector #(SupSize, Inst_Item)) orig_inst: 0, inst: 0}); SupCntX2 j = ((pc_start [1:0] == 2'b00) ? 0 : 1); // Start parse at parcel 0/1 depending on pc lsbs +`ifdef RVFI_DII + j = 0; +`endif Addr pc = pc_start; for (Integer i = 0; i < valueOf (SupSize); i = i + 1) begin Inst_Kind inst_kind = Inst_None; @@ -395,30 +409,31 @@ module mkFetchStage(FetchStage); `endif `ifdef RVFI_DII + Ehr#(3, Dii_Id) dii_id_next <- mkEhr(0); Fifo#(2, Dii_Ids) dii_instIds <- mkCFFifo; Fifo#(2, InstsAndIDs) dii_insts <- mkCFFifo; - FIFOF#(Dii_Id) flush_id <- mkUGFIFOF1; // Next sequence number to request when trapping - Reg#(Dii_Id) dii_id_next <- mkReg(0); + Fifo#(2, Dii_Ids) dii_fetched_ids <- mkCFFifo; + Reg#(Dii_Id) last_trace_id <- mkRegU; - rule feed_dii(!waitForFlush); - Dii_Id next_id = dii_id_next; - if (flush_id.notEmpty) begin - next_id = flush_id.first; - if (verbosity > 0) $display("DII flushed!"); - flush_id.deq; - end - Dii_Ids reqs = replicate(tagged Invalid); - for (Integer i = 0; i < `sizeSup; i = i + 1) - reqs[i] = tagged Valid (next_id + fromInteger(i)); - if (verbosity > 0) $display("Requested from DII", fshow(reqs)); - dii_instIds.enq(reqs); - dii_id_next <= next_id + `sizeSup; - endrule + //rule feed_dii(!waitForFlush); + //Dii_Id next_id = dii_id_next; + //if (flush_id.notEmpty) begin + // next_id = flush_id.first; + // if (verbosity > 0) $display("DII flushed!"); + // flush_id.deq; + //end + //Dii_Ids reqs = replicate(tagged Invalid); + //for (Integer i = 0; i < `sizeSup; i = i + 1) + // reqs[i] = tagged Valid (next_id + fromInteger(i)); + //if (verbosity > 0) $display("Requested from DII", fshow(reqs)); + //dii_instIds.enq(reqs); + //dii_id_next <= next_id + `sizeSup; + //endrule Reg#(Bit#(4)) ticker <- mkReg(0); rule tick; - ticker <= ticker + 4; + ticker <= ticker + 1; if (ticker == 0) $display("%t : tick", $time); endrule `endif @@ -485,6 +500,16 @@ module mkFetchStage(FetchStage); match { .posLastSup, .pred_next_pc } <- fav_pred_next_pc (pc); pc_reg[pc_fetch1_port] <= pred_next_pc; + +`ifdef RVFI_DII + Dii_Id next_id = dii_id_next[pc_fetch1_port]; + Dii_Ids reqs = replicate(tagged Invalid); + for (Integer i = 0; i <= posLastSup; i = i + 1) + reqs[i] = tagged Valid (next_id + fromInteger(i)); + if (verbosity > 0) $display("Requested from DII", fshow(reqs)); + dii_instIds.enq(reqs); + dii_id_next[pc_fetch1_port] <= next_id + fromInteger(posLastSup) + 1; +`endif // Send TLB request. // Mask to 32-bit alignment, even if 'C' is supported (where we may discard first 2 bytes) @@ -495,7 +520,8 @@ module mkFetchStage(FetchStage); pc: pc, pred_next_pc: pred_next_pc, decode_epoch: decode_epoch[0], - main_epoch: f_main_epoch}; + main_epoch: f_main_epoch + }; f12f2.enq(tuple2(fromInteger(posLastSup),out)); if (verbose) $display("Fetch1: ", fshow(out)); endrule @@ -565,11 +591,9 @@ module mkFetchStage(FetchStage); `ifdef RVFI_DII Vector#(SupSize,Maybe#(Instruction)) inst_d = replicate(tagged Valid dii_nop); - if (fetch3In.main_epoch == f_main_epoch) begin - InstsAndIDs ii <- toGet(dii_insts).get(); - inst_d = ii.insts; - if (verbosity > 0) $display("Got from DII: ", fshow (inst_d)); - end + InstsAndIDs ii <- toGet(dii_insts).get(); + inst_d = ii.insts; + if (verbosity > 0) $display("Got from DII: ", fshow (ii)); `else // Get ICache/MMIO response if no exception // In case of exception, we still need to process at least inst_data[0] @@ -636,6 +660,9 @@ module mkFetchStage(FetchStage); instdata.enq (v_items); f32d.enq(f22f3.first); +`ifdef RVFI_DII + dii_fetched_ids.enq(ii.ids); +`endif if (verbosity > 0) begin $display ("----------------"); @@ -652,6 +679,11 @@ module mkFetchStage(FetchStage); f32d.deq(); let inst_data = instdata.first(); instdata.deq(); +`ifdef RVFI_DII + let ids = dii_fetched_ids.first(); + dii_fetched_ids.deq(); + Dii_Id nextId = dii_id_next[pc_decode_port]; +`endif // The main_epoch check is required to make sure this stage doesn't // redirect the PC if a later stage already redirected the PC. if (fetch3In.main_epoch == f_main_epoch) begin @@ -793,6 +825,9 @@ module mkFetchStage(FetchStage); in.ppc = decode_pred_next_pc; // train next addr pred when mispredict trainNAP = Valid (TrainNAP {pc: in.pc, nextPc: decode_pred_next_pc}); +`ifdef RVFI_DII + nextId = fromMaybe(nextId,ids[i]) + 1; +`endif `ifdef PERF_COUNT // performance stats: record decode redirect doAssert(redirectInst == Invalid, "at most 1 decode redirect per cycle"); @@ -809,6 +844,9 @@ module mkFetchStage(FetchStage); orig_inst: inst_data[i].orig_inst, regs: decode_result.regs, cause: cause, +`ifdef RVFI_DII + diid: fromMaybe(?,ids[i]), +`endif tval: tval}; out_fifo.enqS[i].enq(out); if (verbosity > 0) @@ -830,6 +868,9 @@ module mkFetchStage(FetchStage); // update PC and epoch if(redirectPc matches tagged Valid .nextPc) begin pc_reg[pc_decode_port] <= nextPc; +`ifdef RVFI_DII + dii_id_next[pc_decode_port] <= nextId; +`endif end decode_epoch[0] <= decode_epoch_local; // send training data for next addr pred @@ -884,8 +925,16 @@ module mkFetchStage(FetchStage); interface iMemIfc = iMem; interface mmioIfc = mmio.toCore; - method Action start(Addr start_pc); + method Action start( + Addr start_pc +`ifdef RVFI_DII + , Dii_Id id +`endif + ); pc_reg[0] <= start_pc; +`ifdef RVFI_DII + dii_id_next[0] <= id; +`endif started <= True; waitForRedirect <= False; waitForFlush <= False; @@ -898,9 +947,18 @@ module mkFetchStage(FetchStage); waitForRedirect <= True; setWaitRedirect_redirect_conflict.wset(?); // conflict with redirect endmethod - method Action redirect(Addr new_pc); + method Action redirect( + Addr new_pc +`ifdef RVFI_DII + , Dii_Id id +`endif + ); if (verbose) $display("Redirect: newpc %h, old f_main_epoch %d, new f_main_epoch %d",new_pc,f_main_epoch,f_main_epoch+1); pc_reg[pc_redirect_port] <= new_pc; +`ifdef RVFI_DII + dii_id_next[pc_redirect_port] <= id; + if (verbose) $display("%t Redirect: dii_id_next %d", $time(), id); +`endif f_main_epoch <= (f_main_epoch == fromInteger(valueOf(NumEpochs)-1)) ? 0 : f_main_epoch + 1; ehr_pending_straddle[2] <= False; // redirect comes, stop stalling for redirect @@ -912,19 +970,9 @@ module mkFetchStage(FetchStage); endmethod method Action done_flushing() if (waitForFlush); // signal that the pipeline can resume fetching -`ifdef RVFI_DII - if (dii_insts.notEmpty) begin - dii_insts.deq; - if (verbose) $display("%t : Flushing; dequing dii_insts",$time()); - end else begin - flush_id.enq(last_trace_id + 1); -`endif - waitForFlush <= False; - if (verbose) $display("%t : Done Flushing",$time()); -`ifdef RVFI_DII - end -`endif - + waitForFlush <= False; + if (verbose) $display("%t : Done Flushing",$time()); + // XXX The guard prevents the readyToFetch rule in Core.bsv from firing every cycle // The guard also makes this method sequence before (restricted) redirect method // So the effect of setting waitForFlush in redirect method will not be overwritten diff --git a/src_Core/RISCY_OOO/procs/RV64G_OOO/RenameStage.bsv b/src_Core/RISCY_OOO/procs/RV64G_OOO/RenameStage.bsv index 960edde..58dafd5 100644 --- a/src_Core/RISCY_OOO/procs/RV64G_OOO/RenameStage.bsv +++ b/src_Core/RISCY_OOO/procs/RV64G_OOO/RenameStage.bsv @@ -313,6 +313,9 @@ module mkRenameStage#(RenameInput inIfc)(RenameStage); nonMMIOStDone: False, epochIncremented: True, // we have incremented epoch spec_bits: specTagManager.currentSpecBits +`ifdef RVFI_DII + , diid: x.diid +`endif }; rob.enqPort[0].enq(y); // record if we issue an interrupt @@ -418,6 +421,9 @@ module mkRenameStage#(RenameInput inIfc)(RenameStage); // get ROB tag let inst_tag = rob.enqPort[0].getEnqInstTag; +`ifdef RVFI_DII + inst_tag.diid = x.diid; +`endif // CSR inst will be sent to ALU exe pipeline Bool to_exec = False; @@ -474,6 +480,9 @@ module mkRenameStage#(RenameInput inIfc)(RenameStage); nonMMIOStDone: False, epochIncremented: True, // system inst has incremented epoch spec_bits: spec_bits +`ifdef RVFI_DII + , diid: x.diid +`endif }; rob.enqPort[0].enq(y); @@ -561,6 +570,9 @@ module mkRenameStage#(RenameInput inIfc)(RenameStage); // get ROB tag let inst_tag = rob.enqPort[0].getEnqInstTag; +`ifdef RVFI_DII + inst_tag.diid = x.diid; +`endif // LSQ tag LdStQTag lsq_tag = ?; @@ -632,6 +644,9 @@ module mkRenameStage#(RenameInput inIfc)(RenameStage); nonMMIOStDone: False, epochIncremented: False, spec_bits: spec_bits +`ifdef RVFI_DII + , diid: x.diid +`endif }; rob.enqPort[0].enq(y); @@ -805,6 +820,9 @@ module mkRenameStage#(RenameInput inIfc)(RenameStage); // get ROB tag let inst_tag = rob.enqPort[i].getEnqInstTag; +`ifdef RVFI_DII + inst_tag.diid = x.diid; +`endif // LSQ tag LdStQTag lsq_tag = ?; @@ -970,6 +988,9 @@ module mkRenameStage#(RenameInput inIfc)(RenameStage); nonMMIOStDone: False, epochIncremented: False, spec_bits: spec_bits +`ifdef RVFI_DII + , diid: x.diid +`endif }; rob.enqPort[i].enq(y); diff --git a/src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv b/src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv index b1c6bc7..c1588cb 100644 --- a/src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv +++ b/src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv @@ -27,6 +27,9 @@ import Types::*; import FShow::*; import DefaultValue::*; import MemoryTypes::*; +`ifdef RVFI_DII +import RVFI_DII_Types::*; +`endif typedef `NUM_CORES CoreNum; typedef Bit#(TLog#(CoreNum)) CoreId; @@ -56,6 +59,9 @@ typedef struct { SupWaySel way; // which way in superscalar SingleScalarPtr ptr; // pointer within a way InstTime t; // inst time in ROB (for dispatch in reservation station) +`ifdef RVFI_DII + Dii_Id diid; +`endif } InstTag deriving(Bits, Eq, FShow); typedef `SB_SIZE SBSize; diff --git a/src_Core/RISCY_OOO/procs/lib/ReorderBuffer.bsv b/src_Core/RISCY_OOO/procs/lib/ReorderBuffer.bsv index c657a6b..66217cd 100644 --- a/src_Core/RISCY_OOO/procs/lib/ReorderBuffer.bsv +++ b/src_Core/RISCY_OOO/procs/lib/ReorderBuffer.bsv @@ -30,6 +30,9 @@ import Vector::*; import Assert::*; import Ehr::*; import RevertingVirtualReg::*; +`ifdef RVFI_DII +import RVFI_DII_Types::*; +`endif // right after execution, full_result has more up-to-date data (e.g. ppc of mispredicted branch) // some parts of full_result are for verification @@ -82,6 +85,9 @@ typedef struct { // speculation SpecBits spec_bits; +`ifdef RVFI_DII + Dii_Id diid; +`endif `ifdef RVFI ExtraTraceBundle traceBundle; `endif @@ -210,6 +216,9 @@ module mkReorderBufferRowEhr(ReorderBufferRowEhr#(aluExeNum, fpuMulDivExeNum)) p Ehr#(2, Bool) nonMMIOStDone <- mkEhr(?); Reg#(Bool) epochIncremented <- mkRegU; Ehr#(3, SpecBits) spec_bits <- mkEhr(?); +`ifdef RVFI_DII + Reg#(Dii_Id) diid <- mkRegU; +`endif `ifdef RVFI Ehr#(TAdd#(2, aluExeNum), (ExtraTraceBundle)) traceBundle <- mkEhr(?); Reg#(ExtraTraceBundle) traceBundleMem <- mkRegU; @@ -327,6 +336,9 @@ module mkReorderBufferRowEhr(ReorderBufferRowEhr#(aluExeNum, fpuMulDivExeNum)) p ldKilled[ldKill_enq_port] <= Invalid; lsqAtCommitNotified[lsqNotified_enq_port] <= False; nonMMIOStDone[nonMMIOSt_enq_port] <= False; +`ifdef RVFI_DII + diid <= x.diid; +`endif `ifdef RVFI $display("%t : traceBundle = ", $time(), fshow(x.traceBundle), " in write_enq for %x", pc); traceBundle[pvc_enq_port] <= x.traceBundle; @@ -357,6 +369,9 @@ module mkReorderBufferRowEhr(ReorderBufferRowEhr#(aluExeNum, fpuMulDivExeNum)) p lsqAtCommitNotified: lsqAtCommitNotified[lsqNotified_deq_port], nonMMIOStDone: nonMMIOStDone[nonMMIOSt_deq_port], epochIncremented: epochIncremented, +`ifdef RVFI_DII + diid: diid, +`endif `ifdef RVFI traceBundle: case (ppc_vaddr_csrData[pvc_deq_port]) matches tagged VAddr .v: begin