diff --git a/bhv/cv32e40x_rvfi.sv b/bhv/cv32e40x_rvfi.sv index d8bcff7f..97b816dc 100644 --- a/bhv/cv32e40x_rvfi.sv +++ b/bhv/cv32e40x_rvfi.sv @@ -98,8 +98,6 @@ module cv32e40x_rvfi input logic single_step_allowed_i, input logic nmi_pending_i, // regular NMI pending input logic nmi_is_store_i, // regular NMI type - input logic clic_nmi_pending_i, // NMI due to CLIC vector load is pending - input logic clic_nmi_is_store_i, // NMI type due to CLIC vector load input logic pending_debug_i, input logic debug_mode_q_i, @@ -639,7 +637,7 @@ module cv32e40x_rvfi rvfi_trap_next.trap = rvfi_trap_next.exception || rvfi_trap_next.debug; end - // WFI instructions retire when their wake-up condition is present. + // WFI instructions retire when their wake-up condition is present. // The wake-up condition is only checked in the SLEEP state of the controller FSM. assign wb_valid_adjusted = (sys_en_wb_i && sys_wfi_insn_wb_i) ? (ctrl_fsm_cs_i == SLEEP) && (ctrl_fsm_ns_i == FUNCTIONAL) : wb_valid_i; @@ -846,7 +844,7 @@ module cv32e40x_rvfi end end // always_ff @ - assign rvfi_nmip = {(nmi_is_store_i || clic_nmi_is_store_i), (nmi_pending_i || clic_nmi_pending_i)}; + assign rvfi_nmip = {nmi_is_store_i, nmi_pending_i}; // Capture possible performance counter writes during WB, before wb_valid // If counter write happens before wb_valid (e.g. LSU stalled waiting for rvalid or WFI that is in WB multiple cycles), diff --git a/bhv/cv32e40x_wrapper.sv b/bhv/cv32e40x_wrapper.sv index 72113cd9..9e189dab 100644 --- a/bhv/cv32e40x_wrapper.sv +++ b/bhv/cv32e40x_wrapper.sv @@ -433,8 +433,6 @@ module cv32e40x_wrapper .single_step_allowed_i ( core_i.controller_i.controller_fsm_i.single_step_allowed ), .nmi_pending_i ( core_i.controller_i.controller_fsm_i.nmi_pending_q ), .nmi_is_store_i ( core_i.controller_i.controller_fsm_i.nmi_is_store_q ), - .clic_nmi_pending_i ( core_i.controller_i.controller_fsm_i.pending_clic_nmi ), - .clic_nmi_is_store_i ( 1'b0 /* CLIC NMI can only be due to a load*/ ), .pending_debug_i ( core_i.controller_i.controller_fsm_i.pending_debug ), .debug_mode_q_i ( core_i.controller_i.controller_fsm_i.debug_mode_q ), .irq_i ( core_i.irq_i & IRQ_MASK ), diff --git a/rtl/cv32e40x_controller.sv b/rtl/cv32e40x_controller.sv index 70007946..82ac9926 100644 --- a/rtl/cv32e40x_controller.sv +++ b/rtl/cv32e40x_controller.sv @@ -68,7 +68,6 @@ module cv32e40x_controller import cv32e40x_pkg::*; input logic [1:0] lsu_err_wb_i, // LSU bus error in WB stage input logic lsu_busy_i, // LSU is busy with outstanding transfers input logic lsu_interruptible_i, // LSU may be interrupted - input logic lsu_write_buffer_empty_i, // LSU write buffer state // jump/branch signals input logic branch_decision_ex_i, // branch decision signal from EX ALU @@ -162,7 +161,6 @@ module cv32e40x_controller import cv32e40x_pkg::*; .wb_valid_i ( wb_valid_i ), .lsu_interruptible_i ( lsu_interruptible_i ), - .lsu_write_buffer_empty_i ( lsu_write_buffer_empty_i ), // Interrupt Controller Signals .irq_req_ctrl_i ( irq_req_ctrl_i ), .irq_id_ctrl_i ( irq_id_ctrl_i ), diff --git a/rtl/cv32e40x_controller_fsm.sv b/rtl/cv32e40x_controller_fsm.sv index ec460fca..59323f41 100644 --- a/rtl/cv32e40x_controller_fsm.sv +++ b/rtl/cv32e40x_controller_fsm.sv @@ -72,7 +72,6 @@ module cv32e40x_controller_fsm import cv32e40x_pkg::*; input logic lsu_busy_i, // LSU is busy with outstanding transfers input logic lsu_interruptible_i, // LSU can be interrupted - input logic lsu_write_buffer_empty_i, // LSU write buffer state // Interrupt Controller Signals input logic irq_req_ctrl_i, // irq requst input logic [9:0] irq_id_ctrl_i, // irq id @@ -159,7 +158,6 @@ module cv32e40x_controller_fsm import cv32e40x_pkg::*; logic pending_nmi; logic pending_nmi_early; - logic pending_clic_nmi; logic pending_debug; logic pending_single_step; logic pending_single_step_ptr; @@ -176,9 +174,6 @@ module cv32e40x_controller_fsm import cv32e40x_pkg::*; // Used to block debug until pointer logic pointer_in_pipeline; - // Flag for checking if we can to a CLIC pointer fetch - logic wbuf_irq_ok; - // Internal irq_ack for use when a (clic) pointer reaches ID stage and // we have single stepping enabled. logic non_shv_irq_ack; @@ -249,24 +244,20 @@ module cv32e40x_controller_fsm import cv32e40x_pkg::*; assign branch_taken_ex = branch_in_ex && !branch_taken_q; // Exception in WB if the following evaluates to 1 - // CLIC: bus errors for pointer fetches are treated as NMI, not exceptions. assign exception_in_wb = ((ex_wb_pipe_i.instr.mpu_status != MPU_OK) || - (!ex_wb_pipe_i.instr_meta.clic_ptr && ex_wb_pipe_i.instr.bus_resp.err) || + ex_wb_pipe_i.instr.bus_resp.err || ex_wb_pipe_i.illegal_insn || (ex_wb_pipe_i.sys_en && ex_wb_pipe_i.sys_ecall_insn) || (ex_wb_pipe_i.sys_en && ex_wb_pipe_i.sys_ebrk_insn) || (lsu_mpu_status_wb_i != MPU_OK)) && ex_wb_pipe_i.instr_valid; // Set exception cause - // For CLIC: Pointer fetches with PMA/PMP errors will get the exception code converted to LOAD_FAULT - // Bus errors will be converted to NMI as for regular loads. - assign exception_cause_wb = (!ex_wb_pipe_i.instr_meta.clic_ptr && (ex_wb_pipe_i.instr.mpu_status != MPU_OK)) ? EXC_CAUSE_INSTR_FAULT : - (!ex_wb_pipe_i.instr_meta.clic_ptr && ex_wb_pipe_i.instr.bus_resp.err) ? EXC_CAUSE_INSTR_BUS_FAULT : - (ex_wb_pipe_i.instr_meta.clic_ptr && (ex_wb_pipe_i.instr.mpu_status != MPU_OK)) ? EXC_CAUSE_LOAD_FAULT : - ex_wb_pipe_i.illegal_insn ? EXC_CAUSE_ILLEGAL_INSN : - (ex_wb_pipe_i.sys_en && ex_wb_pipe_i.sys_ecall_insn) ? EXC_CAUSE_ECALL_MMODE : - (ex_wb_pipe_i.sys_en && ex_wb_pipe_i.sys_ebrk_insn) ? EXC_CAUSE_BREAKPOINT : - (lsu_mpu_status_wb_i == MPU_WR_FAULT) ? EXC_CAUSE_STORE_FAULT : + assign exception_cause_wb = (ex_wb_pipe_i.instr.mpu_status != MPU_OK) ? EXC_CAUSE_INSTR_FAULT : + ex_wb_pipe_i.instr.bus_resp.err ? EXC_CAUSE_INSTR_BUS_FAULT : + ex_wb_pipe_i.illegal_insn ? EXC_CAUSE_ILLEGAL_INSN : + (ex_wb_pipe_i.sys_en && ex_wb_pipe_i.sys_ecall_insn) ? EXC_CAUSE_ECALL_MMODE : + (ex_wb_pipe_i.sys_en && ex_wb_pipe_i.sys_ebrk_insn) ? EXC_CAUSE_BREAKPOINT : + (lsu_mpu_status_wb_i == MPU_WR_FAULT) ? EXC_CAUSE_STORE_FAULT : EXC_CAUSE_LOAD_FAULT; // (lsu_mpu_status_wb_i == MPU_RE_FAULT) // For now we are always allowed to take exceptions once they arrive in WB. @@ -303,11 +294,7 @@ module cv32e40x_controller_fsm import cv32e40x_pkg::*; // Using flopped version to avoid paths from data_err_i/data_rvalid_i to instr_* outputs // Gating the pending signal instead of the allowed signal for debug related conditions, otherwise a pending NMI during debug mode // or single stepping with dcsr.stepie==0 would stall ID stage and we would never get out of debug, resulting in a deadlock. - // CLIC pointer fetches with associated bus errors are treated as NMI. The error bit is taken from ex_wb_pipe and not flopped further. - // This preserves the address of the pointer (ex_wb_pipe.pc) that must be stored to mepc. - assign pending_clic_nmi = (ex_wb_pipe_i.instr_valid && ex_wb_pipe_i.instr_meta.clic_ptr && ex_wb_pipe_i.instr.bus_resp.err); - assign pending_nmi = (nmi_pending_q || pending_clic_nmi) && - !debug_mode_q && !(dcsr_i.step && !dcsr_i.stepie); + assign pending_nmi = nmi_pending_q && !debug_mode_q && !(dcsr_i.step && !dcsr_i.stepie); // Early version of the pending_nmi signal, using the unflopped lsu_err_wb_i[0] // This signal is used for halting the ID stage in the same cycle as the bus error arrives. @@ -320,9 +307,6 @@ module cv32e40x_controller_fsm import cv32e40x_pkg::*; // dcsr.nmip will always see a pending nmi if nmi_pending_q is set. // This CSR bit shall not be gated by debug mode or step without stepie - // NMI's related to clic pointer load bus errors are not signaled through dcsr.nmip - // This can only happen during machine mode as interrupts are blocked during debug, - // and the dcsr is not readable from machine mode. No need to expose this bit as it will never be visible. assign ctrl_fsm_o.pending_nmi = nmi_pending_q; // Debug // @@ -407,17 +391,7 @@ module cv32e40x_controller_fsm import cv32e40x_pkg::*; // The cycle after fencei enters WB, the fencei handshake will be initiated. This must complete and the fencei instruction must retire before allowing interrupts. // TODO:OK:low May allow interuption of Zce to idempotent memories - // todo: generate CLIC, check shv and write buffer status - generate - if (SMCLIC) begin : gen_clic_wbuf_check - // If an interrupt is SHV, the write buffer must be empty before we allow to take the interrupt - // The content in the write buffer could be a pointer update. - assign wbuf_irq_ok = irq_clic_shv_i ? lsu_write_buffer_empty_i : 1'b1; - end else begin : gen_basic_wbuf_check - assign wbuf_irq_ok = 1'b1; - end - endgenerate - assign interrupt_allowed = lsu_interruptible_i && !fencei_ongoing && !xif_in_wb && wbuf_irq_ok; + assign interrupt_allowed = lsu_interruptible_i && !fencei_ongoing && !xif_in_wb; // Allowing NMI's follow the same rule as regular interrupts. assign nmi_allowed = interrupt_allowed; diff --git a/rtl/cv32e40x_core.sv b/rtl/cv32e40x_core.sv index c0c4b980..b1aa6446 100644 --- a/rtl/cv32e40x_core.sv +++ b/rtl/cv32e40x_core.sv @@ -151,7 +151,6 @@ module cv32e40x_core import cv32e40x_pkg::*; logic if_busy; logic lsu_busy; logic lsu_interruptible; - logic lsu_write_buffer_empty; // ID/EX pipeline id_ex_pipe_t id_ex_pipe; @@ -575,7 +574,6 @@ module cv32e40x_core import cv32e40x_pkg::*; // Control signals .busy_o ( lsu_busy ), .interruptible_o ( lsu_interruptible ), - .write_buffer_empty_o ( lsu_write_buffer_empty ), // Stage 0 outputs (EX) .lsu_split_0_o ( lsu_split_ex ), @@ -784,7 +782,6 @@ module cv32e40x_core import cv32e40x_pkg::*; .lsu_err_wb_i ( lsu_err_wb ), .lsu_busy_i ( lsu_busy ), .lsu_interruptible_i ( lsu_interruptible ), - .lsu_write_buffer_empty_i ( lsu_write_buffer_empty ), // jump/branch control .branch_decision_ex_i ( branch_decision_ex ), diff --git a/rtl/cv32e40x_load_store_unit.sv b/rtl/cv32e40x_load_store_unit.sv index 0ef7d61a..fb6b74ac 100644 --- a/rtl/cv32e40x_load_store_unit.sv +++ b/rtl/cv32e40x_load_store_unit.sv @@ -49,7 +49,6 @@ module cv32e40x_load_store_unit import cv32e40x_pkg::*; // Control outputs output logic busy_o, output logic interruptible_o, - output logic write_buffer_empty_o, // Stage 0 outputs (EX) output logic lsu_split_0_o, // Misaligned access is split in two transactions (to controller) @@ -95,8 +94,6 @@ module cv32e40x_load_store_unit import cv32e40x_pkg::*; logic buffer_trans_ready; obi_data_req_t buffer_trans; - logic buffer_empty; - logic filter_trans_valid; logic filter_trans_ready; obi_data_req_t filter_trans; @@ -665,11 +662,9 @@ module cv32e40x_load_store_unit import cv32e40x_pkg::*; .valid_o ( bus_trans_valid ), .ready_i ( bus_trans_ready ), - .trans_o ( bus_trans ), - .empty_o ( buffer_empty ) + .trans_o ( bus_trans ) ); - assign write_buffer_empty_o = buffer_empty; ////////////////////////////////////////////////////////////////////////////// // OBI interface ////////////////////////////////////////////////////////////////////////////// diff --git a/rtl/cv32e40x_write_buffer.sv b/rtl/cv32e40x_write_buffer.sv index f11a4c90..e0e15802 100644 --- a/rtl/cv32e40x_write_buffer.sv +++ b/rtl/cv32e40x_write_buffer.sv @@ -47,10 +47,8 @@ module cv32e40x_write_buffer import cv32e40x_pkg::*; // outputs output logic valid_o, output obi_data_req_t trans_o, - output logic ready_o, - - output logic empty_o - ); + output logic ready_o + ); // local signals write_buffer_state_e state, next_state; @@ -115,6 +113,4 @@ module cv32e40x_write_buffer import cv32e40x_pkg::*; assign valid_o = (state == WBUF_FULL) || valid_i; assign trans_o = (state == WBUF_FULL) ? trans_q : trans_i; - assign empty_o = (state == WBUF_EMPTY); - endmodule diff --git a/sva/cv32e40x_controller_fsm_sva.sv b/sva/cv32e40x_controller_fsm_sva.sv index ef81bdd0..36f88d45 100644 --- a/sva/cv32e40x_controller_fsm_sva.sv +++ b/sva/cv32e40x_controller_fsm_sva.sv @@ -73,7 +73,6 @@ module cv32e40x_controller_fsm_sva input logic nmi_is_store_q, input logic nmi_pending_q, input dcsr_t dcsr_i, - input logic lsu_write_buffer_empty_i, input logic irq_clic_shv_i ); @@ -514,11 +513,6 @@ endgenerate else `uvm_error("controller", "NMI handler not taken within two instruction retirements") if (SMCLIC) begin - // When a CLIC SHV interrupt is taken, the write buffer must be empty - a_clic_shv_wbuf_empty: - assert property (@(posedge clk) disable iff (!rst_n) - (irq_clic_shv_i && ctrl_fsm_o.irq_ack) |-> lsu_write_buffer_empty_i) - else `uvm_error("controller", "LSU write buffer not empty when fetching CLIC pointer") // After a pc_set to PC_TRAP_CLICV, only the following jump targets are allowed: // PC_POINTER : Normal execution, the pointer target is being fetched diff --git a/sva/cv32e40x_core_sva.sv b/sva/cv32e40x_core_sva.sv index 3fccb3fa..86c02573 100644 --- a/sva/cv32e40x_core_sva.sv +++ b/sva/cv32e40x_core_sva.sv @@ -185,10 +185,8 @@ always_ff @(posedge clk , negedge rst_ni) expected_instr_err_mepc <= ex_wb_pipe.pc; end - // CLIC pointers generate data errors, exluding to avoid cause mismatch. todo: make separate asserts for clicptr exceptions. - // todo: if CLIC spec changes from data to instruction fetch for pointer, this must change again. if (!first_instr_mpuerr_found && ex_wb_pipe.instr_valid && !irq_ack && !(ctrl_pending_debug && ctrl_debug_allowed) && - !(ctrl_fsm.pc_mux == PC_TRAP_NMI) && !(ex_wb_pipe.instr_meta.clic_ptr) && + !(ctrl_fsm.pc_mux == PC_TRAP_NMI) && (ex_wb_pipe.instr.mpu_status != MPU_OK) && !ctrl_debug_mode_n) begin first_instr_mpuerr_found <= 1'b1; expected_instr_mpuerr_mepc <= ex_wb_pipe.pc;