@@ -52,6 +52,8 @@ module cv32e40x_rvfi
52
52
53
53
// // EX probes ////
54
54
input logic branch_in_ex_i,
55
+ input logic branch_decision_ex_i,
56
+ input logic dret_in_ex_i,
55
57
// LSU
56
58
input logic lsu_en_ex_i,
57
59
input logic lsu_pmp_err_ex_i,
@@ -465,6 +467,8 @@ module cv32e40x_rvfi
465
467
logic [31 : 0 ] ex_mem_wdata;
466
468
mem_err_t [3 : 0 ] mem_err;
467
469
470
+ logic branch_taken_ex;
471
+
468
472
logic [ 3 : 0 ] rvfi_mem_mask_int;
469
473
logic [31 : 0 ] rvfi_mem_rdata_d;
470
474
logic [31 : 0 ] rvfi_mem_wdata_d;
@@ -517,6 +521,7 @@ module cv32e40x_rvfi
517
521
logic pc_mux_debug;
518
522
logic pc_mux_dret;
519
523
logic pc_mux_exception;
524
+ logic pc_mux_debug_exception;
520
525
logic pc_mux_interrupt;
521
526
logic pc_mux_nmi;
522
527
@@ -543,11 +548,18 @@ module cv32e40x_rvfi
543
548
// The pc_mux signals probe the MUX in the IF stage to extract information about events in the WB stage.
544
549
// These signals are therefore used both in the WB stage to see effects of the executed instruction (e.g. rvfi_trap), and
545
550
// 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;
551
563
552
564
// Assign rvfi channels
553
565
assign rvfi_halt = 1'b0 ; // No intruction causing halt in cv32e40x
@@ -733,7 +745,7 @@ module cv32e40x_rvfi
733
745
// // EX Stage ////
734
746
if (ex_valid_i && wb_ready_i) begin
735
747
// 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 ];
737
749
debug_mode [STAGE_WB ] <= debug_mode [STAGE_EX ];
738
750
debug_cause[STAGE_WB ] <= debug_cause [STAGE_EX ];
739
751
instr_pmp_err[STAGE_WB ] <= instr_pmp_err [STAGE_EX ];
0 commit comments