Skip to content

Commit 7240216

Browse files
Merge pull request #456 from silabs-halfdan/rvfi_bugfix
RVFI bugfixes
2 parents 3575f67 + a18191e commit 7240216

File tree

3 files changed

+21
-7
lines changed

3 files changed

+21
-7
lines changed

bhv/cv32e40x_rvfi.sv

+18-6
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ module cv32e40x_rvfi
5252

5353
//// EX probes ////
5454
input logic branch_in_ex_i,
55+
input logic branch_decision_ex_i,
56+
input logic dret_in_ex_i,
5557
// LSU
5658
input logic lsu_en_ex_i,
5759
input logic lsu_pmp_err_ex_i,
@@ -465,6 +467,8 @@ module cv32e40x_rvfi
465467
logic [31:0] ex_mem_wdata;
466468
mem_err_t [3:0] mem_err;
467469

470+
logic branch_taken_ex;
471+
468472
logic [ 3:0] rvfi_mem_mask_int;
469473
logic [31:0] rvfi_mem_rdata_d;
470474
logic [31:0] rvfi_mem_wdata_d;
@@ -517,6 +521,7 @@ module cv32e40x_rvfi
517521
logic pc_mux_debug;
518522
logic pc_mux_dret;
519523
logic pc_mux_exception;
524+
logic pc_mux_debug_exception;
520525
logic pc_mux_interrupt;
521526
logic pc_mux_nmi;
522527

@@ -543,11 +548,18 @@ module cv32e40x_rvfi
543548
// The pc_mux signals probe the MUX in the IF stage to extract information about events in the WB stage.
544549
// These signals are therefore used both in the WB stage to see effects of the executed instruction (e.g. rvfi_trap), and
545550
// in the IF stage to see the reason for executing the instruction (e.g. rvfi_intr).
546-
assign pc_mux_interrupt = (ctrl_fsm_i.pc_mux == PC_TRAP_IRQ);
547-
assign pc_mux_nmi = (ctrl_fsm_i.pc_mux == PC_TRAP_NMI);
548-
assign pc_mux_debug = (ctrl_fsm_i.pc_mux == PC_TRAP_DBD);
549-
assign pc_mux_exception = (ctrl_fsm_i.pc_mux == PC_TRAP_EXC) || (ctrl_fsm_i.pc_mux == PC_TRAP_DBE);
550-
assign pc_mux_dret = (ctrl_fsm_i.pc_mux == PC_DRET);
551+
assign pc_mux_interrupt = (ctrl_fsm_i.pc_mux == PC_TRAP_IRQ);
552+
assign pc_mux_nmi = (ctrl_fsm_i.pc_mux == PC_TRAP_NMI);
553+
assign pc_mux_debug = (ctrl_fsm_i.pc_mux == PC_TRAP_DBD);
554+
assign pc_mux_exception = (ctrl_fsm_i.pc_mux == PC_TRAP_EXC) || pc_mux_debug_exception ;
555+
// The debug exception for mret is taken in ID (contrary to all other exceptions). In the case where we have a dret in the EX stage at the same time,
556+
// this can lead to a situation we take the exception for the mret even though it never reaches the WB stage.
557+
// This works in rtl because the exception handler instructions will get killed.
558+
// In rvfi this exception needs to be ignored as it comes from an instruction that does not retire.
559+
assign pc_mux_debug_exception = (ctrl_fsm_i.pc_mux == PC_TRAP_DBE) && !dret_in_ex_i;
560+
assign pc_mux_dret = (ctrl_fsm_i.pc_mux == PC_DRET);
561+
562+
assign branch_taken_ex = branch_in_ex_i && branch_decision_ex_i;
551563

552564
// Assign rvfi channels
553565
assign rvfi_halt = 1'b0; // No intruction causing halt in cv32e40x
@@ -733,7 +745,7 @@ module cv32e40x_rvfi
733745
//// EX Stage ////
734746
if (ex_valid_i && wb_ready_i) begin
735747
// Predicting branch target explicitly to avoid predicting asynchronous events
736-
pc_wdata [STAGE_WB] <= branch_in_ex_i ? branch_target_ex_i : pc_wdata[STAGE_EX];
748+
pc_wdata [STAGE_WB] <= branch_taken_ex ? branch_target_ex_i : pc_wdata[STAGE_EX];
737749
debug_mode [STAGE_WB] <= debug_mode [STAGE_EX];
738750
debug_cause[STAGE_WB] <= debug_cause [STAGE_EX];
739751
instr_pmp_err[STAGE_WB] <= instr_pmp_err [STAGE_EX];

bhv/cv32e40x_wrapper.sv

+2
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,8 @@ module cv32e40x_wrapper
386386
.lsu_we_id_i ( core_i.id_stage_i.lsu_we ),
387387

388388
.branch_in_ex_i ( core_i.controller_i.controller_fsm_i.branch_in_ex ),
389+
.branch_decision_ex_i ( core_i.ex_stage_i.branch_decision_o ),
390+
.dret_in_ex_i ( core_i.ex_stage_i.id_ex_pipe_i.sys_dret_insn ),
389391
.lsu_en_ex_i ( core_i.ex_stage_i.id_ex_pipe_i.lsu_en ),
390392

391393
.instr_pmp_err_if_i ( 1'b0 /* PMP not implemented in cv32e40x */ ),

rtl/cv32e40x_load_store_unit.sv

+1-1
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ module cv32e40x_load_store_unit import cv32e40x_pkg::*;
267267

268268
logic [31:0] rdata_ext;
269269
logic [63:0] rdata_full;
270-
logic [31:0] rdata_aligned;
270+
logic [63:0] rdata_aligned; // [63:32] unsused
271271
logic rdata_is_split;
272272

273273
// Check if rdata is split over two accesses

0 commit comments

Comments
 (0)