From 4463679387e5430f976c5fc253faac53edb96b4e Mon Sep 17 00:00:00 2001 From: Oystein Knauserud Date: Wed, 31 May 2023 13:34:07 +0200 Subject: [PATCH] Fixed issue where branch_addr_n would be miscalculated for a CLIC SHV interrupt if CLIC_ID_WIDTH was less than 4. Signed-off-by: Oystein Knauserud --- bhv/cv32e40x_wrapper.sv | 3 ++- rtl/cv32e40x_if_stage.sv | 7 ++++++- sva/cv32e40x_controller_fsm_sva.sv | 15 ++++++++++++--- 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/bhv/cv32e40x_wrapper.sv b/bhv/cv32e40x_wrapper.sv index 440a153c..81bacf7f 100644 --- a/bhv/cv32e40x_wrapper.sv +++ b/bhv/cv32e40x_wrapper.sv @@ -225,7 +225,8 @@ module cv32e40x_wrapper cv32e40x_controller_fsm_sva #(.X_EXT(X_EXT), .DEBUG(DEBUG), - .CLIC(CLIC)) + .CLIC(CLIC), + .CLIC_ID_WIDTH(CLIC_ID_WIDTH)) controller_fsm_sva ( .lsu_outstanding_cnt (core_i.load_store_unit_i.cnt_q), .rf_we_wb_i (core_i.wb_stage_i.rf_we_wb_o ), diff --git a/rtl/cv32e40x_if_stage.sv b/rtl/cv32e40x_if_stage.sv index c0c1c350..0a1d5076 100644 --- a/rtl/cv32e40x_if_stage.sv +++ b/rtl/cv32e40x_if_stage.sv @@ -91,6 +91,11 @@ module cv32e40x_if_stage import cv32e40x_pkg::*; localparam int unsigned ALBUF_DEPTH = 3; localparam int unsigned ALBUF_CNT_WIDTH = $clog2(ALBUF_DEPTH); + // Calculate number of bits of mtvt_pc_mux to use in branch_addr_n for CLIC SHV interrupts. + // Minimum number of bits to use from ctrl_fsm.mtvt_pc_mux is four to keep 32-bit address 64B aligned. + // Otherwise the resulting concatenated address will be less than 32 bits. + localparam int unsigned CLIC_MUX_WIDTH = (CLIC_ID_WIDTH < 4) ? 4 : CLIC_ID_WIDTH; + logic if_ready; // prefetch buffer related signals @@ -169,7 +174,7 @@ module cv32e40x_if_stage import cv32e40x_pkg::*; PC_TRAP_DBD: branch_addr_n = {dm_halt_addr_i[31:2], 2'b0}; PC_TRAP_DBE: branch_addr_n = {dm_exception_addr_i[31:2], 2'b0}; PC_TRAP_NMI: branch_addr_n = {mtvec_addr_i, ctrl_fsm_i.nmi_mtvec_index, 2'b00}; - PC_TRAP_CLICV: branch_addr_n = {mtvt_addr_i, ctrl_fsm_i.mtvt_pc_mux[CLIC_ID_WIDTH-1:0], 2'b00}; + PC_TRAP_CLICV: branch_addr_n = {mtvt_addr_i, ctrl_fsm_i.mtvt_pc_mux[CLIC_MUX_WIDTH-1:0], 2'b00}; // CLIC and Zc* spec requires to clear bit 0. This clearing is done in the alignment buffer. PC_POINTER : branch_addr_n = if_id_pipe_o.ptr; // JVT + (index << 2) diff --git a/sva/cv32e40x_controller_fsm_sva.sv b/sva/cv32e40x_controller_fsm_sva.sv index 8ffc7a5a..20229d4d 100644 --- a/sva/cv32e40x_controller_fsm_sva.sv +++ b/sva/cv32e40x_controller_fsm_sva.sv @@ -28,9 +28,10 @@ module cv32e40x_controller_fsm_sva import uvm_pkg::*; import cv32e40x_pkg::*; - #( parameter bit X_EXT = 1'b0, - parameter bit DEBUG = 1'b0, - parameter bit CLIC = 1'b0 + #( parameter bit X_EXT = 1'b0, + parameter bit DEBUG = 1'b0, + parameter bit CLIC = 1'b0, + parameter int unsigned CLIC_ID_WIDTH = 5 ) ( input logic clk, @@ -639,6 +640,14 @@ if (CLIC) begin $stable(mintstatus_i)) else `uvm_error("controller", "mintstatus changed after taking an NMI") + // Check that unused bits of ctrl_fsm.mtvt_pc_mux is zero + if (CLIC_ID_WIDTH < 10) begin + a_unused_mtvt_bits: + assert property (@(posedge clk) disable iff (!rst_n) + |ctrl_fsm_o.mtvt_pc_mux[9:CLIC_ID_WIDTH] == 1'b0) + else `uvm_error("controller", "Unused bits of ctrl_fsm_o.mtvt_pc_mux is not zero") + end + end else begin // CLIC // Check that CLIC related signals are inactive when CLIC is not configured. a_clic_inactive: