From a0fd5a8f3799e5091f995ee5118c74f55fc8a86f Mon Sep 17 00:00:00 2001 From: James Clarke Date: Sat, 2 Nov 2019 20:37:34 +0000 Subject: [PATCH 1/5] Print cycle counter like Piccolo/Flute on write to to_host --- src_Core/CPU/Proc.bsv | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src_Core/CPU/Proc.bsv b/src_Core/CPU/Proc.bsv index 70be811..f485003 100644 --- a/src_Core/CPU/Proc.bsv +++ b/src_Core/CPU/Proc.bsv @@ -38,6 +38,7 @@ import ConfigReg :: *; // ---------------- // BSV additional libs +import Cur_Cycle :: *; import GetPut_Aux :: *; // ================================================================ @@ -272,7 +273,7 @@ module mkProc (Proc_IFC); // Print out values written 'tohost' rule rl_tohost; let x <- mmioPlatform.to_host; - $display ("mmioPlatform.rl_tohost: 0x%0x (= %0d)", x, x); + $display ("%0d: mmioPlatform.rl_tohost: 0x%0x (= %0d)", cur_cycle, x, x); if (x != 0) begin // Standard RISC-V ISA tests finish by writing a value tohost with x[0]==1. // Further when x[63:1]==0, all tests within the program pass, From 78cad5bbcc87f39d4aef6e9171a8cc6ebf32c197 Mon Sep 17 00:00:00 2001 From: James Clarke Date: Sat, 2 Nov 2019 20:38:35 +0000 Subject: [PATCH 2/5] Fix BTB entry aliasing with C extension --- src_Core/RISCY_OOO/procs/lib/Btb.bsv | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src_Core/RISCY_OOO/procs/lib/Btb.bsv b/src_Core/RISCY_OOO/procs/lib/Btb.bsv index bd035a7..713013f 100644 --- a/src_Core/RISCY_OOO/procs/lib/Btb.bsv +++ b/src_Core/RISCY_OOO/procs/lib/Btb.bsv @@ -39,9 +39,10 @@ interface NextAddrPred; endinterface // Local BTB Typedefs +typedef 1 PcLsbsIgnore; typedef 256 BtbEntries; // 4KB BTB typedef Bit#(TLog#(BtbEntries)) BtbIndex; -typedef Bit#(TSub#(TSub#(AddrSz, TLog#(BtbEntries)), 2)) BtbTag; +typedef Bit#(TSub#(TSub#(AddrSz, TLog#(BtbEntries)), PcLsbsIgnore)) BtbTag; typedef struct { Addr pc; @@ -65,7 +66,7 @@ module mkBtb(NextAddrPred); Bool flushDone = True; `endif - function BtbIndex getIndex(Addr pc) = truncate(pc >> 2); + function BtbIndex getIndex(Addr pc) = truncate(pc >> valueof(PcLsbsIgnore)); function BtbTag getTag(Addr pc) = truncateLSB(pc); // no flush, accept update From 87daa8e319cbe8f7ba9eff52cc3be09eea7e9b8b Mon Sep 17 00:00:00 2001 From: James Clarke Date: Sun, 3 Nov 2019 03:47:25 +0000 Subject: [PATCH 3/5] Revert unwanted MMIOInst diff in e7fbf32b38 This stopped unmapped addresses from faulting, instead giving back a list of all Invalid entries, triggering the "Fetched insts not enough" assertion in FetchStage's doDecode. Fixes rv64mi-p-access. --- src_Core/RISCY_OOO/procs/lib/MMIOInst.bsv | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src_Core/RISCY_OOO/procs/lib/MMIOInst.bsv b/src_Core/RISCY_OOO/procs/lib/MMIOInst.bsv index 368a0af..c4b4884 100644 --- a/src_Core/RISCY_OOO/procs/lib/MMIOInst.bsv +++ b/src_Core/RISCY_OOO/procs/lib/MMIOInst.bsv @@ -77,13 +77,15 @@ module mkMMIOInst(MMIOInst); method InstFetchTarget getFetchTarget(Addr phyPc); let addr = getDataAlignedAddr(phyPc); - if(addr >= mainMemBaseAddr && (addr < mainMemBoundAddr) && - addr != toHostAddr && addr != fromHostAddr) - begin - return MainMem; - end + if (soc_map.m_is_IO_addr (phyPc)) begin + return IODevice; + end + else if(addr >= mainMemBaseAddr && (addr < mainMemBoundAddr) && + addr != toHostAddr && addr != fromHostAddr) begin + return MainMem; + end else begin - return IODevice; + return Fault; end endmethod From 67be950d3a8e858d29bb1f363930af2517e2e0ee Mon Sep 17 00:00:00 2001 From: James Clarke Date: Sun, 3 Nov 2019 04:12:34 +0000 Subject: [PATCH 4/5] FetchStage: Use EHRs to remove conflicts between doDecode and doFetch3 This conflict was introduced by 53aacff7c when compressed support was added. Previously, doDecode could be scheduled in the same cycle as doFetch3 (and only in that order), but the Reg reads added to doDecode prevented this. Instead, use EHRs to allow a bypass path from doDecode to doFetch3. This means we can issue every cycle again, rather than only every other cycle. --- .../RISCY_OOO/procs/RV64G_OOO/FetchStage.bsv | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/src_Core/RISCY_OOO/procs/RV64G_OOO/FetchStage.bsv b/src_Core/RISCY_OOO/procs/RV64G_OOO/FetchStage.bsv index 7424031..e91e389 100644 --- a/src_Core/RISCY_OOO/procs/RV64G_OOO/FetchStage.bsv +++ b/src_Core/RISCY_OOO/procs/RV64G_OOO/FetchStage.bsv @@ -321,13 +321,13 @@ module mkFetchStage(FetchStage); Integer pc_redirect_port = 2; // Epochs - Reg#(Bool) decode_epoch <- mkReg(False); + Ehr#(2, Bool) decode_epoch <- mkEhr(False); Reg#(Epoch) f_main_epoch <- mkReg(0); // fetch estimate of main epoch - // Regs to hold the first half of an instruction that straddles a cache line boundary - Reg #(Bool) rg_pending_straddle <- mkReg (False); - Reg #(Addr) rg_half_inst_pc <- mkRegU; // The PC of the straddling instruction - Reg #(Bit #(16)) rg_half_inst_lsbs <- mkRegU; // The 16 lsbs of the straddling instruction + // Regs/wires to hold the first half of an instruction that straddles a cache line boundary + Ehr #(2, Bool) ehr_pending_straddle <- mkEhr (False); + Ehr #(2, Addr) ehr_half_inst_pc <- mkEhr (?); // The PC of the straddling instruction + Ehr #(2, Bit #(16)) ehr_half_inst_lsbs <- mkEhr (?); // The 16 lsbs of the straddling instruction // Pipeline Stage FIFOs Fifo#(2, Tuple2#(Bit#(TLog#(SupSize)),Fetch1ToFetch2)) f12f2 <- mkCFFifo; @@ -456,7 +456,7 @@ module mkFetchStage(FetchStage); let out = Fetch1ToFetch2 { pc: pc, pred_next_pc: pred_next_pc, - decode_epoch: decode_epoch, + decode_epoch: decode_epoch[0], main_epoch: f_main_epoch}; f12f2.enq(tuple2(fromInteger(posLastSup),out)); if (verbose) $display("Fetch1: ", fshow(out)); @@ -539,11 +539,11 @@ module mkFetchStage(FetchStage); end end - if (fetch3In.decode_epoch != decode_epoch) begin + if (fetch3In.decode_epoch != decode_epoch[1]) begin // Just drop it. if (verbosity > 0) begin $display ("----------------"); - $display ("Fetch3: Drop: decode epoch: %d", decode_epoch); + $display ("Fetch3: Drop: decode epoch: %d", decode_epoch[1]); $display ("Fetch3: f22f3.first: ", fshow (f22f3.first)); $display ("Fetch3: inst_d: ", fshow (inst_d)); end @@ -554,8 +554,8 @@ module mkFetchStage(FetchStage); Addr start_PC = fetch3In.pc; // Handle cache-line boundary straddling instruction, if one is pending - if (rg_pending_straddle) begin - if (fetch3In.pc != rg_half_inst_pc + 4) begin + if (ehr_pending_straddle[1]) begin + if (fetch3In.pc != ehr_half_inst_pc[1] + 4) begin $display ("----------------"); $display ("Fetch3: straddle: pc mismatch"); $display ("Fetch3: f22f3.first: ", fshow (f22f3.first)); @@ -564,17 +564,17 @@ module mkFetchStage(FetchStage); end else begin // Prepend onto the sequence: { first-half of the instruction , 0 } - v_x16 = shiftInAt0 (shiftInAt0 (v_x16, rg_half_inst_lsbs), 0); + v_x16 = shiftInAt0 (shiftInAt0 (v_x16, ehr_half_inst_lsbs[1]), 0); let bound = valueOf (SupSizeX2) - 1; if (n_x16s < (fromInteger (bound) - 1)) n_x16s = n_x16s + 2; else if (n_x16s < fromInteger (bound)) n_x16s = n_x16s + 1; - start_PC = rg_half_inst_pc; - rg_pending_straddle <= False; + start_PC = ehr_half_inst_pc[1]; + ehr_pending_straddle[1] <= False; if (verbosity > 0) begin $display ("----------------"); - $display ("Fetch3: straddle: prepend x16 %0h", rg_half_inst_lsbs); + $display ("Fetch3: straddle: prepend x16 %0h", ehr_half_inst_lsbs[1]); $display ("Fetch3: f22f3.first: ", fshow (f22f3.first)); $display ("Fetch3: inst_d: ", fshow (inst_d)); $display ("Fetch3: v_x16: ", fshow (v_x16)); @@ -606,7 +606,7 @@ module mkFetchStage(FetchStage); // 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 - Bool decode_epoch_local = decode_epoch; // next value for decode epoch + Bool decode_epoch_local = decode_epoch[0]; // next value for decode epoch Maybe#(Addr) redirectPc = Invalid; // next pc redirect by branch predictor Maybe#(TrainNAP) trainNAP = Invalid; // training data sent to next addr pred `ifdef PERF_COUNT @@ -619,9 +619,9 @@ module mkFetchStage(FetchStage); if ((inst_data[i].inst_kind == Inst_32b_Lsbs) && (fromInteger(i) <= nbSup)) begin if (fetch3In.decode_epoch == decode_epoch_local) begin // Save the half-instruction and redirect doFetch1 to get the next cache line - rg_pending_straddle <= True; - rg_half_inst_pc <= inst_data[i].pc; - rg_half_inst_lsbs <= inst_data[i].orig_inst [15:0]; + ehr_pending_straddle[0] <= True; + ehr_half_inst_pc[0] <= inst_data[i].pc; + ehr_half_inst_lsbs[0] <= inst_data[i].orig_inst [15:0]; decode_epoch_local = ! decode_epoch_local; let next_PC = inst_data[i].pc + 4; redirectPc = tagged Valid (next_PC); @@ -782,7 +782,7 @@ module mkFetchStage(FetchStage); if(redirectPc matches tagged Valid .nextPc) begin pc_reg[pc_decode_port] <= nextPc; end - decode_epoch <= decode_epoch_local; + decode_epoch[0] <= decode_epoch_local; // send training data for next addr pred if (trainNAP matches tagged Valid .x) begin napTrainByDecQ.enq(x); From 3b5443e284f2568246ab42c8fda50a80c8289a09 Mon Sep 17 00:00:00 2001 From: James Clarke Date: Sun, 3 Nov 2019 04:59:52 +0000 Subject: [PATCH 5/5] FetchStage: Clear straddle state on redirect Otherwise, if the last instruction we tried to decode was the first half of a 32-bit instruction, we will think the first 16-bit parcel from the new PC is the second half of the previous instruction and take an assertion failure because the PC does not match what was expected. This fixes rv64uc-p-rvc, which broke after the previous commit as the scheduling changes exposed this bug. --- src_Core/RISCY_OOO/procs/RV64G_OOO/FetchStage.bsv | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src_Core/RISCY_OOO/procs/RV64G_OOO/FetchStage.bsv b/src_Core/RISCY_OOO/procs/RV64G_OOO/FetchStage.bsv index e91e389..56c20c1 100644 --- a/src_Core/RISCY_OOO/procs/RV64G_OOO/FetchStage.bsv +++ b/src_Core/RISCY_OOO/procs/RV64G_OOO/FetchStage.bsv @@ -325,7 +325,7 @@ module mkFetchStage(FetchStage); Reg#(Epoch) f_main_epoch <- mkReg(0); // fetch estimate of main epoch // Regs/wires to hold the first half of an instruction that straddles a cache line boundary - Ehr #(2, Bool) ehr_pending_straddle <- mkEhr (False); + Ehr #(3, Bool) ehr_pending_straddle <- mkEhr (False); Ehr #(2, Addr) ehr_half_inst_pc <- mkEhr (?); // The PC of the straddling instruction Ehr #(2, Bit #(16)) ehr_half_inst_lsbs <- mkEhr (?); // The 16 lsbs of the straddling instruction @@ -853,6 +853,7 @@ module mkFetchStage(FetchStage); 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; 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 waitForRedirect <= False; setWaitRedirect_redirect_conflict.wset(?); // conflict with setWaitForRedirect