diff --git a/bhv/cv32e40s_rvfi.sv b/bhv/cv32e40s_rvfi.sv index 23be802f4..9a729e091 100644 --- a/bhv/cv32e40s_rvfi.sv +++ b/bhv/cv32e40s_rvfi.sv @@ -30,7 +30,7 @@ module cv32e40s_rvfi input logic rst_ni, // Non-pipeline Probes - if_c_obi.monitor m_c_obi_instr_if, + cv32e40s_if_c_obi.monitor m_c_obi_instr_if, //// IF Probes //// input logic if_valid_i, @@ -1289,11 +1289,12 @@ module cv32e40s_rvfi // If the 2nd transfer in a split misaligned is blocked (by debug watchpoint, mpu or alignment check), the corresponding bits in rmask/wmaks will be cleared if (!lsu_split_2nd_xfer_wb) begin // 1st transfer of a split misaligned, or the only transfer in case of a single transfer - rvfi_mem_rmask[ (4*(memop_cnt+1))-1 -: 4] <= mem_access_blocked_wb ? '0 : mem_rmask [STAGE_WB]; - rvfi_mem_wmask[ (4*(memop_cnt+1))-1 -: 4] <= mem_access_blocked_wb ? '0 : mem_wmask [STAGE_WB]; - rvfi_mem_addr [(32*(memop_cnt+1))-1 -: 32] <= ex_mem_trans.addr; - rvfi_mem_wdata[(32*(memop_cnt+1))-1 -: 32] <= ex_mem_trans.wdata; - rvfi_mem_prot [ (3*(memop_cnt+1))-1 -: 3] <= ex_mem_trans.prot; + rvfi_mem_rmask[ (4*(memop_cnt+1))-1 -: 4] <= mem_access_blocked_wb ? '0 : mem_rmask [STAGE_WB]; + rvfi_mem_wmask[ (4*(memop_cnt+1))-1 -: 4] <= mem_access_blocked_wb ? '0 : mem_wmask [STAGE_WB]; + rvfi_mem_addr [(32*(memop_cnt+1))-1 -: 32] <= ex_mem_trans.addr; + rvfi_mem_wdata[(32*(memop_cnt+1))-1 -: 32] <= ex_mem_trans.wdata; + // Using (2*memop_cnt+memop_cnt) rather than 3*memop_cnt. This is a workaround to avoid blackboxed multiplier in the slice boundary calculations + rvfi_mem_prot [(2*memop_cnt + memop_cnt) +: 3] <= ex_mem_trans.prot; end else if (lsu_split_2nd_xfer_wb && mem_access_blocked_wb) begin // 2nd transfer of a split misaligned is blocked. Clear related bits in rmask/wmask diff --git a/bhv/cv32e40s_rvfi_instr_obi.sv b/bhv/cv32e40s_rvfi_instr_obi.sv index 206315b8a..438c6752c 100644 --- a/bhv/cv32e40s_rvfi_instr_obi.sv +++ b/bhv/cv32e40s_rvfi_instr_obi.sv @@ -39,7 +39,7 @@ module cv32e40s_rvfi_instr_obi import cv32e40s_pkg::*; import cv32e40s_rvfi_pkg: input logic prefetch_trans_ready_i, input logic prefetch_resp_valid_i, - if_c_obi.monitor m_c_obi_instr_if, + cv32e40s_if_c_obi.monitor m_c_obi_instr_if, output rvfi_obi_instr_t obi_instr // OBI address and response phase packet aligned to IF timing ); @@ -111,14 +111,14 @@ module cv32e40s_rvfi_instr_obi import cv32e40s_pkg::*; import cv32e40s_rvfi_pkg: // trans_accepted is based on the core side control signals from the MPU. // When there is no MPU fault, trans_accepted will have the same timing as // m_c_obi_instr_if.s_req.req, since the control signals are passed directly through the MPU, - // and cv32e40x_instr_obi_interface will be in TRANSPARENT mode (trans_ready_o == 1'b1). + // and cv32e40s_instr_obi_interface will be in TRANSPARENT mode (trans_ready_o == 1'b1). // Upon MPU fault, req_payload will be undefined. assign fifo_req_push = trans_accepted; // Push OBI response phase signals into FIFO when response is valid. // response_valid is based on the core side control signal from the MPU. // When there is no MPU fault, response_valid will have the same timing as - // m_c_obi_instr_if.s_rvalid.rvalid, since this signal is passed directly through cv32e40x_instr_obi_interface and the MPU. + // m_c_obi_instr_if.s_rvalid.rvalid, since this signal is passed directly through cv32e40s_instr_obi_interface and the MPU. // Upon MPU fault, resp_payload will be undefined, with the exception of resp_payload.mpu_status assign fifo_resp_push = response_valid; diff --git a/bhv/rvfi_sim_trace.sv b/bhv/cv32e40s_rvfi_sim_trace.sv similarity index 99% rename from bhv/rvfi_sim_trace.sv rename to bhv/cv32e40s_rvfi_sim_trace.sv index 4eaa0fb27..e588c4e39 100644 --- a/bhv/rvfi_sim_trace.sv +++ b/bhv/cv32e40s_rvfi_sim_trace.sv @@ -27,7 +27,7 @@ // // //////////////////////////////////////////////////////////////////////////////// -module rvfi_sim_trace +module cv32e40s_rvfi_sim_trace import cv32e40s_rvfi_pkg::*; #(parameter string ITB_PLUSARG = "itb_file", parameter string LOGFILE_PATH_PLUSARG = "log_file", diff --git a/bhv/cv32e40s_wrapper.sv b/bhv/cv32e40s_wrapper.sv index dbad10b4c..93caa90a4 100644 --- a/bhv/cv32e40s_wrapper.sv +++ b/bhv/cv32e40s_wrapper.sv @@ -532,7 +532,7 @@ endgenerate `ifndef FORMAL bind cv32e40s_rvfi: rvfi_i - rvfi_sim_trace + cv32e40s_rvfi_sim_trace tracer_i(.*); `endif @@ -549,6 +549,7 @@ endgenerate .obi_instr_rptr_q_inc(rvfi_i.rvfi_instr_obi_i.rptr_q_inc), .obi_instr_rptr_q(rvfi_i.rvfi_instr_obi_i.rptr_q), .pc_ex_i (core_i.id_ex_pipe.pc), + .m_c_obi_data_if (core_i.m_c_obi_data_if), .*); `endif // `ifndef COREV_ASSERT_OFF diff --git a/cv32e40s_manifest.flist b/cv32e40s_manifest.flist index 4bbea5134..35bfc4594 100644 --- a/cv32e40s_manifest.flist +++ b/cv32e40s_manifest.flist @@ -29,7 +29,7 @@ +incdir+${DESIGN_RTL_DIR}/../sva ${DESIGN_RTL_DIR}/include/cv32e40s_pkg.sv -${DESIGN_RTL_DIR}/if_c_obi.sv +${DESIGN_RTL_DIR}/cv32e40s_if_c_obi.sv ${DESIGN_RTL_DIR}/../bhv/include/cv32e40s_rvfi_pkg.sv ${DESIGN_RTL_DIR}/../bhv/cv32e40s_wrapper.sv ${DESIGN_RTL_DIR}/cv32e40s_align_check.sv @@ -88,4 +88,4 @@ ${DESIGN_RTL_DIR}/../bhv/cv32e40s_sim_clock_gate.sv ${DESIGN_RTL_DIR}/../bhv/cv32e40s_rvfi_instr_obi.sv ${DESIGN_RTL_DIR}/../bhv/cv32e40s_rvfi_data_obi.sv ${DESIGN_RTL_DIR}/../bhv/cv32e40s_rvfi.sv -${DESIGN_RTL_DIR}/../bhv/rvfi_sim_trace.sv +${DESIGN_RTL_DIR}/../bhv/cv32e40s_rvfi_sim_trace.sv diff --git a/docs/user_manual/source/exceptions_interrupts.rst b/docs/user_manual/source/exceptions_interrupts.rst index acd7b0843..779d3c68e 100644 --- a/docs/user_manual/source/exceptions_interrupts.rst +++ b/docs/user_manual/source/exceptions_interrupts.rst @@ -72,7 +72,7 @@ Non Maskable Interrupts Non Maskable Interrupts (NMIs) update ``mepc``, ``mcause`` and ``mstatus`` similar to regular interrupts. However, as the faults that result in NMIs are imprecise, the contents of ``mepc`` is not guaranteed to point to the instruction after the faulted load or store. -The ``minsttatus`` CSR (which exists only if ``CLIC`` == 1) is not impacted by NMIs. +The ``mintstatus`` CSR (which exists only if ``CLIC`` == 1) is not impacted by NMIs. .. note:: diff --git a/rtl/cv32e40s_alu.sv b/rtl/cv32e40s_alu.sv index 6365a6b4c..b06891f98 100644 --- a/rtl/cv32e40s_alu.sv +++ b/rtl/cv32e40s_alu.sv @@ -71,6 +71,8 @@ module cv32e40s_alu import cv32e40s_pkg::*; output logic [31:0] div_op_b_shifted_o ); + localparam RV32B_ZBS = (B_EXT == ZBA_ZBB_ZBS) || (B_EXT == ZBA_ZBB_ZBC_ZBS); + logic [31:0] operand_a_rev; logic [31:0] operand_b_rev; @@ -159,7 +161,9 @@ module cv32e40s_alu import cv32e40s_pkg::*; ALU_B_BSET, ALU_B_BCLR, ALU_B_BINV : begin - shifter_aa = 32'h1; + if (RV32B_ZBS) begin + shifter_aa = 32'h1; + end end default: ; endcase @@ -175,17 +179,23 @@ module cv32e40s_alu import cv32e40s_pkg::*; shifter_tmp = shifter_shamt[0] ? {shifter_tmp[62:0], shifter_tmp[63:63]} : shifter_tmp; end - always_comb begin - shifter_result = shifter_tmp[31:0]; - - unique case (operator_i) - ALU_B_BEXT : shifter_result = 32'h1 & shifter_tmp[31:0]; - ALU_B_BSET : shifter_result = operand_a_i | shifter_tmp[31:0]; - ALU_B_BCLR : shifter_result = operand_a_i & ~shifter_tmp[31:0]; - ALU_B_BINV : shifter_result = operand_a_i ^ shifter_tmp[31:0]; - default: ; - endcase - end + generate + if (RV32B_ZBS) begin : gen_shift_zbs + always_comb begin + shifter_result = shifter_tmp[31:0]; + + unique case (operator_i) + ALU_B_BEXT : shifter_result = 32'h1 & shifter_tmp[31:0]; + ALU_B_BSET : shifter_result = operand_a_i | shifter_tmp[31:0]; + ALU_B_BCLR : shifter_result = operand_a_i & ~shifter_tmp[31:0]; + ALU_B_BINV : shifter_result = operand_a_i ^ shifter_tmp[31:0]; + default: ; + endcase + end + end else begin : gen_shift_nozbs + assign shifter_result = shifter_tmp[31:0]; + end + endgenerate assign div_op_b_shifted_o = shifter_tmp[31:0]; diff --git a/rtl/cv32e40s_controller.sv b/rtl/cv32e40s_controller.sv index eff1ef061..39237b17b 100644 --- a/rtl/cv32e40s_controller.sv +++ b/rtl/cv32e40s_controller.sv @@ -132,7 +132,7 @@ module cv32e40s_controller import cv32e40s_pkg::*; input logic wb_valid_i, // WB stage is done // Data OBI interface monitor - if_c_obi.monitor m_c_obi_data_if, + cv32e40s_if_c_obi.monitor m_c_obi_data_if, // Outputs output ctrl_byp_t ctrl_byp_o, diff --git a/rtl/cv32e40s_controller_bypass.sv b/rtl/cv32e40s_controller_bypass.sv index 2453d2cad..d525bfade 100644 --- a/rtl/cv32e40s_controller_bypass.sv +++ b/rtl/cv32e40s_controller_bypass.sv @@ -203,9 +203,9 @@ module cv32e40s_controller_bypass import cv32e40s_pkg::*; ((id_ex_pipe_i.alu_jmp && id_ex_pipe_i.alu_en && !id_ex_pipe_i.last_sec_op && id_ex_pipe_i.instr_valid)); - // Stall ID when WFI or WFE is active in EX. - // Prevent load/store following a WFI or WFE in the pipeline - assign ctrl_byp_o.wfi_wfe_stall = (id_ex_pipe_i.sys_en && (id_ex_pipe_i.sys_wfi_insn || id_ex_pipe_i.sys_wfe_insn) && id_ex_pipe_i.instr_valid); + // Stall ID when instruction that can trigger sleep (e.g. WFI or WFE) is active in EX. + // Prevent load/store following a sleep instruction in the pipeline + assign ctrl_byp_o.sleep_stall = (id_ex_pipe_i.sys_en && (id_ex_pipe_i.sys_wfi_insn || id_ex_pipe_i.sys_wfe_insn) && id_ex_pipe_i.instr_valid); // Stall ID when mnxti CSR is accessed in EX // This is needed because the data bypass from EX uses csr_rdata, and for mnxti this is actually mstatus and not the result diff --git a/rtl/cv32e40s_controller_fsm.sv b/rtl/cv32e40s_controller_fsm.sv index 9ada881a2..cc417ca0f 100644 --- a/rtl/cv32e40s_controller_fsm.sv +++ b/rtl/cv32e40s_controller_fsm.sv @@ -130,7 +130,7 @@ module cv32e40s_controller_fsm import cv32e40s_pkg::*; input logic fencei_flush_ack_i, // Data OBI interface monitor - if_c_obi.monitor m_c_obi_data_if + cv32e40s_if_c_obi.monitor m_c_obi_data_if ); // FSM state encoding @@ -684,7 +684,7 @@ module cv32e40s_controller_fsm import cv32e40s_pkg::*; // - If not checking for id_stage_haltable for interrupts and debug, the core could end up in a situation where it tries to create a bubble // by halting ID, but the condition disallowing interrupt or debug will not disappear until the sequence currently handled by the ID stage // is done. This would create an unrecoverable deadlock. - ctrl_fsm_o.halt_id = (ctrl_byp_i.jalr_stall || ctrl_byp_i.load_stall || ctrl_byp_i.csr_stall || ctrl_byp_i.wfi_wfe_stall || ctrl_byp_i.mnxti_id_stall) || + ctrl_fsm_o.halt_id = (ctrl_byp_i.jalr_stall || ctrl_byp_i.load_stall || ctrl_byp_i.csr_stall || ctrl_byp_i.sleep_stall || ctrl_byp_i.mnxti_id_stall) || ((pending_interrupt || pending_nmi || pending_nmi_early) && debug_interruptible && id_stage_haltable) || ((pending_async_debug || pending_sync_debug) && id_stage_haltable); @@ -1272,8 +1272,8 @@ module cv32e40s_controller_fsm import cv32e40s_pkg::*; end // Wakeup from sleep - assign ctrl_fsm_o.wake_from_sleep = pending_nmi || irq_wu_ctrl_i || pending_async_debug || debug_mode_q || (wfe_in_wb && wu_wfe_i); // Only WFE wakes up for wfe_wu_i - assign ctrl_fsm_o.debug_wfi_wfe_no_sleep = debug_mode_q || dcsr_i.step; + assign ctrl_fsm_o.wake_from_sleep = pending_nmi || irq_wu_ctrl_i || pending_async_debug || debug_mode_q || (wfe_in_wb && wu_wfe_i); // Only WFE wakes up for wfe_wu_i + assign ctrl_fsm_o.debug_no_sleep = debug_mode_q || dcsr_i.step; //////////////////// // Flops // diff --git a/rtl/cv32e40s_core.sv b/rtl/cv32e40s_core.sv index d70942528..41429080c 100644 --- a/rtl/cv32e40s_core.sv +++ b/rtl/cv32e40s_core.sv @@ -382,8 +382,8 @@ module cv32e40s_core import cv32e40s_pkg::*; logic lfsr_shift_id; // Internal OBI interfaces - if_c_obi #(.REQ_TYPE(obi_inst_req_t), .RESP_TYPE(obi_inst_resp_t)) m_c_obi_instr_if(); - if_c_obi #(.REQ_TYPE(obi_data_req_t), .RESP_TYPE(obi_data_resp_t)) m_c_obi_data_if(); + cv32e40s_if_c_obi #(.REQ_TYPE(obi_inst_req_t), .RESP_TYPE(obi_inst_resp_t)) m_c_obi_instr_if(); + cv32e40s_if_c_obi #(.REQ_TYPE(obi_data_req_t), .RESP_TYPE(obi_data_resp_t)) m_c_obi_data_if(); // Connect toplevel OBI signals to internal interfaces assign instr_req_o = m_c_obi_instr_if.s_req.req; diff --git a/rtl/cv32e40s_cs_registers.sv b/rtl/cv32e40s_cs_registers.sv index 946639b7a..4cc4ad1de 100644 --- a/rtl/cv32e40s_cs_registers.sv +++ b/rtl/cv32e40s_cs_registers.sv @@ -1313,12 +1313,6 @@ module cv32e40s_cs_registers import cv32e40s_pkg::*; end end - CSR_MINTSTATUS: begin - if (CLIC) begin - mintstatus_we = 1'b1; - end - end - CSR_MINTTHRESH: begin if (CLIC) begin mintthresh_we = 1'b1; diff --git a/rtl/cv32e40s_data_obi_interface.sv b/rtl/cv32e40s_data_obi_interface.sv index b19a6e84c..64c7c3c71 100644 --- a/rtl/cv32e40s_data_obi_interface.sv +++ b/rtl/cv32e40s_data_obi_interface.sv @@ -58,7 +58,7 @@ module cv32e40s_data_obi_interface import cv32e40s_pkg::*; input xsecure_ctrl_t xsecure_ctrl_i, // OBI interface - if_c_obi.master m_c_obi_data_if + cv32e40s_if_c_obi.master m_c_obi_data_if ); diff --git a/rtl/cv32e40s_i_decoder.sv b/rtl/cv32e40s_i_decoder.sv index 7526ea3c3..7a8609fd5 100644 --- a/rtl/cv32e40s_i_decoder.sv +++ b/rtl/cv32e40s_i_decoder.sv @@ -30,8 +30,8 @@ module cv32e40s_i_decoder import cv32e40s_pkg::*; #( parameter bit CLIC = 1 - ) - ( +) +( // from IF/ID pipeline input logic [31:0] instr_rdata_i, @@ -40,9 +40,9 @@ module cv32e40s_i_decoder import cv32e40s_pkg::*; input privlvl_t priv_lvl_i, // Priviledge level for ID stage input mstatus_t mstatus_i, output decoder_ctrl_t decoder_ctrl_o - ); +); - localparam CUSTOM_EXT = 1; + localparam CUSTOM_EXT = 1; always_comb begin @@ -335,8 +335,8 @@ module cv32e40s_i_decoder import cv32e40s_pkg::*; if((priv_lvl_i == PRIV_LVL_U) && mstatus_i.tw) begin decoder_ctrl_o = DECODER_CTRL_ILLEGAL_INSN; end else begin - // Suppressing WFI in case of ctrl_fsm_i.debug_wfi_wfe_no_sleep to prevent sleeping when not allowed. - decoder_ctrl_o.sys_wfi_insn = ctrl_fsm_i.debug_wfi_wfe_no_sleep ? 1'b0 : 1'b1; + // Suppressing WFI in case of ctrl_fsm_i.debug_no_sleep to prevent sleeping when not allowed. + decoder_ctrl_o.sys_wfi_insn = ctrl_fsm_i.debug_no_sleep ? 1'b0 : 1'b1; end end @@ -345,8 +345,8 @@ module cv32e40s_i_decoder import cv32e40s_pkg::*; if((priv_lvl_i == PRIV_LVL_U) && mstatus_i.tw) begin decoder_ctrl_o = DECODER_CTRL_ILLEGAL_INSN; end else begin - // Suppressing WFI in case of ctrl_fsm_i.debug_wfi_wfe_no_sleep to prevent sleeping when not allowed. - decoder_ctrl_o.sys_wfe_insn = ctrl_fsm_i.debug_wfi_wfe_no_sleep ? 1'b0 : 1'b1; + // Suppressing WFE in case of ctrl_fsm_i.debug_no_sleep to prevent sleeping when not allowed. + decoder_ctrl_o.sys_wfe_insn = ctrl_fsm_i.debug_no_sleep ? 1'b0 : 1'b1; end end else begin decoder_ctrl_o = DECODER_CTRL_ILLEGAL_INSN; diff --git a/rtl/cv32e40s_id_stage.sv b/rtl/cv32e40s_id_stage.sv index 34ea225f6..4b1da0051 100644 --- a/rtl/cv32e40s_id_stage.sv +++ b/rtl/cv32e40s_id_stage.sv @@ -115,7 +115,6 @@ module cv32e40s_id_stage import cv32e40s_pkg::*; localparam REG_D_LSB = 7; logic [31:0] instr; - logic [15:0] c_instr; // Compressed instruction // Register Read/Write Control logic [1:0] rf_re; // Decoder only supports rs1, rs2 @@ -185,8 +184,6 @@ module cv32e40s_id_stage import cv32e40s_pkg::*; logic [31:0] imm_u_type; logic [31:0] imm_uj_type; logic [31:0] imm_z_type; - logic [31:0] imm_ciw_type; - logic [31:0] imm_cl_type; // Branch target address logic [31:0] bch_target; @@ -229,7 +226,6 @@ module cv32e40s_id_stage import cv32e40s_pkg::*; assign lfsr_shift_o = (id_valid_o && ex_ready_i) && (if_id_pipe_i.instr_meta.dummy || if_id_pipe_i.instr_meta.hint) && last_sec_op; assign instr = if_id_pipe_i.instr.bus_resp.rdata; - assign c_instr = if_id_pipe_i.compressed_instr; // Immediate extraction and sign extension assign imm_i_type = { {20 {instr[31]}}, instr[31:20] }; @@ -238,27 +234,6 @@ module cv32e40s_id_stage import cv32e40s_pkg::*; assign imm_u_type = { instr[31:12], 12'b0 }; assign imm_uj_type = { {12 {instr[31]}}, instr[19:12], instr[20], instr[30:21], 1'b0 }; - // Immediate extraction and sign extension (compressed instructions) - assign imm_ciw_type = { 22'b0, c_instr[10:7], c_instr[12:11], c_instr[5], c_instr[6], 2'b0 }; - assign imm_cl_type = { 25'b0, c_instr[5], c_instr[12:10], c_instr[6], 2'b0 }; - -/* - assign imm_cfldsp_type = {22'b0, c_instr[4:2], c_instr[12], c_instr[6:5], 3'b0}; - assign imm_caddi_type = {{22{c_instr[12]}}, c_instr[12:12], c_instr[4:3], c_instr[5:5], c_instr[2:2], c_instr[6:6], 4'b0}; - assign imm_clwsp_type = {24'b0, c_instr[3:2], c_instr[12:12], c_instr[6:4], 2'b0}; - assign imm_cld_type = {24'b0, c_instr[6:5], c_instr[12:10], 3'b0}; - assign imm_cswsp_type = {24'b0, c_instr[8:7], c_instr[12:9], 2'b0}; - assign imm_fsdp_type = {24'b0, c_instr[9:7], c_instr[12:10], 2'b0}; - assign imm_csrli_type = {26'b0, c_instr[12:12], c_instr[6:2]}; - assign imm_candi_type = {{26{c_instr[12]}}, c_instr[12:12], c_instr[6:2]}; - assign imm_cbeq_type = {{23{c_instr[12]}}, c_instr[12:12], c_instr[6:5], c_instr[2:2], c_instr[11:10], c_instr[4:3], 1'b0}; - assign imm_clui_type = {{14{c_instr[12]}}, c_instr[12:12], c_instr[6:2], 12'b0}; - assign imm_clsb_type = {28'd0, c_instr[10], c_instr[6:5], c_instr[11]}; - assign imm_clsh_type = {27'd0, c_instr[11:10], c_instr[6:5], 1'b0}; -*/ - - - // Immediate for CSR manipulation (zero extended) assign imm_z_type = { 27'b0, instr[REG_S1_MSB:REG_S1_LSB] }; @@ -366,8 +341,6 @@ module cv32e40s_id_stage import cv32e40s_pkg::*; IMMB_S: imm_b = imm_s_type; IMMB_U: imm_b = imm_u_type; IMMB_PCINCR: imm_b = if_id_pipe_i.instr_meta.compressed ? 32'h2 : 32'h4; - IMMB_CIW: imm_b = imm_ciw_type; - IMMB_CL: imm_b = imm_cl_type; default: imm_b = imm_i_type; endcase end diff --git a/rtl/if_c_obi.sv b/rtl/cv32e40s_if_c_obi.sv similarity index 94% rename from rtl/if_c_obi.sv rename to rtl/cv32e40s_if_c_obi.sv index 5906f4dba..5dd22fd18 100644 --- a/rtl/if_c_obi.sv +++ b/rtl/cv32e40s_if_c_obi.sv @@ -24,7 +24,7 @@ // // The 'c' in the interface names means 'Compressed' // since this interface is a subset of the full OBI spec. -interface if_c_obi import cv32e40s_pkg::*; +interface cv32e40s_if_c_obi import cv32e40s_pkg::*; #( parameter type REQ_TYPE = obi_inst_req_t, parameter type RESP_TYPE = obi_inst_resp_t @@ -49,4 +49,4 @@ interface if_c_obi import cv32e40s_pkg::*; s_gnt, s_rvalid, resp_payload ); -endinterface : if_c_obi +endinterface : cv32e40s_if_c_obi diff --git a/rtl/cv32e40s_if_stage.sv b/rtl/cv32e40s_if_stage.sv index c52a7af36..7bfd1de8a 100644 --- a/rtl/cv32e40s_if_stage.sv +++ b/rtl/cv32e40s_if_stage.sv @@ -70,7 +70,7 @@ module cv32e40s_if_stage import cv32e40s_pkg::*; // Instruction bus interface - if_c_obi.master m_c_obi_instr_if, + cv32e40s_if_c_obi.master m_c_obi_instr_if, output if_id_pipe_t if_id_pipe_o, // IF/ID pipeline stage output logic [31:0] pc_if_o, // Program counter diff --git a/rtl/cv32e40s_instr_obi_interface.sv b/rtl/cv32e40s_instr_obi_interface.sv index 22bf65ba0..79446bdc8 100644 --- a/rtl/cv32e40s_instr_obi_interface.sv +++ b/rtl/cv32e40s_instr_obi_interface.sv @@ -57,7 +57,7 @@ module cv32e40s_instr_obi_interface import cv32e40s_pkg::*; input xsecure_ctrl_t xsecure_ctrl_i, // OBI interface - if_c_obi.master m_c_obi_instr_if + cv32e40s_if_c_obi.master m_c_obi_instr_if ); diff --git a/rtl/cv32e40s_load_store_unit.sv b/rtl/cv32e40s_load_store_unit.sv index 93588c293..8fc726cea 100644 --- a/rtl/cv32e40s_load_store_unit.sv +++ b/rtl/cv32e40s_load_store_unit.sv @@ -43,7 +43,7 @@ module cv32e40s_load_store_unit import cv32e40s_pkg::*; input ctrl_fsm_t ctrl_fsm_i, // output to data memory - if_c_obi.master m_c_obi_data_if, + cv32e40s_if_c_obi.master m_c_obi_data_if, // ID/EX pipeline input id_ex_pipe_t id_ex_pipe_i, @@ -116,7 +116,7 @@ module cv32e40s_load_store_unit import cv32e40s_pkg::*; logic alcheck_trans_pushpop; obi_data_req_t alcheck_trans; - // Transaction request to cv32e40x_mpu + // Transaction request to cv32e40s_mpu logic mpu_trans_valid; logic mpu_trans_ready; logic mpu_trans_pushpop; @@ -137,7 +137,7 @@ module cv32e40s_load_store_unit import cv32e40s_pkg::*; logic [31:0] alcheck_resp_rdata; data_resp_t alcheck_resp; - // Transaction response interface (from cv32e40x_mpu) + // Transaction response interface (from cv32e40s_mpu) logic mpu_resp_valid; data_resp_t mpu_resp; diff --git a/rtl/cv32e40s_prefetcher.sv b/rtl/cv32e40s_prefetcher.sv index 80d31d77e..b1aa2e36c 100644 --- a/rtl/cv32e40s_prefetcher.sv +++ b/rtl/cv32e40s_prefetcher.sv @@ -140,9 +140,10 @@ module cv32e40s_prefetcher import cv32e40s_pkg::*; begin if(rst_n == 1'b0) begin - state_q <= IDLE; - trans_addr_q <= '0; + state_q <= IDLE; + trans_addr_q <= '0; trans_ptr_access_q <= 1'b0; + trans_priv_lvl_q <= PRIV_LVL_M; end else begin diff --git a/rtl/cv32e40s_sleep_unit.sv b/rtl/cv32e40s_sleep_unit.sv index 27810cb8a..718cf7de2 100644 --- a/rtl/cv32e40s_sleep_unit.sv +++ b/rtl/cv32e40s_sleep_unit.sv @@ -86,7 +86,7 @@ module cv32e40s_sleep_unit import cv32e40s_pkg::*; // Sleep only in response to WFI which leads to clock disable. The controller determines the // scenarios for which WFI can(not) cause sleep. WFI suppression is performed in the i_decoder - // based on the debug_wfi_no_sleep signal from the controller. + // based on the debug_no_sleep signal from the controller. assign core_sleep_o = fetch_enable_q && !clock_en; always_ff @(posedge clk_ungated_i, negedge rst_n) diff --git a/rtl/cv32e40s_write_buffer.sv b/rtl/cv32e40s_write_buffer.sv index defb1b794..2ddaf7c14 100644 --- a/rtl/cv32e40s_write_buffer.sv +++ b/rtl/cv32e40s_write_buffer.sv @@ -100,7 +100,7 @@ module cv32e40s_write_buffer import cv32e40s_pkg::*; /////////////////////////////////////////// always_ff @(posedge clk, negedge rst_n) begin if(!rst_n) begin - trans_q <= '0; + trans_q <= obi_data_req_t'{we: 1'b1, default: '0}; end else if (push) begin trans_q <= trans_i; end diff --git a/rtl/include/cv32e40s_pkg.sv b/rtl/include/cv32e40s_pkg.sv index a46f83995..eeb86f2df 100644 --- a/rtl/include/cv32e40s_pkg.sv +++ b/rtl/include/cv32e40s_pkg.sv @@ -870,13 +870,11 @@ typedef enum logic[1:0] { } alu_op_b_mux_e; // Immediate b selection -typedef enum logic[2:0] { - IMMB_I = 3'b000, - IMMB_S = 3'b001, - IMMB_U = 3'b010, - IMMB_PCINCR = 3'b011, - IMMB_CIW = 3'b100, - IMMB_CL = 3'b101 +typedef enum logic[1:0] { + IMMB_I = 2'b00, + IMMB_S = 2'b01, + IMMB_U = 2'b10, + IMMB_PCINCR = 2'b11 } imm_b_mux_e; // Operand c selection @@ -1430,7 +1428,7 @@ typedef struct packed { logic jalr_stall; // Stall due to JALR hazard (JALR used result from EX or LSU result in WB) logic load_stall; // Stall due to load operation logic csr_stall; - logic wfi_wfe_stall; + logic sleep_stall; // Stall ID due to sleep (e.g. WFI, WFE) instruction in EX logic mnxti_id_stall; // Stall ID due to mnxti CSR access in EX logic mnxti_ex_stall; // Stall EX due to LSU instruction in WB logic minstret_stall; // Stall due to minstret/h read in EX @@ -1471,7 +1469,7 @@ typedef struct packed { logic debug_mode; // Flag signalling we are in debug mode, valid for ID, EX and WB logic [2:0] debug_cause; // cause of debug entry logic debug_csr_save; // Update debug CSRs - logic debug_wfi_wfe_no_sleep; // Debug prevents core from sleeping after WFI + logic debug_no_sleep; // Debug prevents core from sleeping after WFI, etc. logic debug_havereset; // Signal to external debugger that we have reset logic debug_running; // Signal to external debugger that we are running (not in debug) logic debug_halted; // Signal to external debugger that we are halted (in debug mode) diff --git a/sva/cv32e40s_clic_int_controller_sva.sv b/sva/cv32e40s_clic_int_controller_sva.sv index f56c9f98c..ac8582748 100644 --- a/sva/cv32e40s_clic_int_controller_sva.sv +++ b/sva/cv32e40s_clic_int_controller_sva.sv @@ -32,7 +32,7 @@ module cv32e40s_clic_int_controller_sva import uvm_pkg::*; import cv32e40s_pkg::*; - ( +( input logic clk, input logic rst_n, @@ -48,9 +48,7 @@ module cv32e40s_clic_int_controller_sva input ctrl_fsm_t ctrl_fsm, input dcsr_t dcsr - - ); - +); // Check that a pending interrupt is taken as soon as possible after being enabled property p_clic_enable; @@ -91,5 +89,6 @@ module cv32e40s_clic_int_controller_sva a_clic_disable: assert property(p_clic_disable) else `uvm_error("core", "Interrupt taken after disabling"); + endmodule diff --git a/sva/cv32e40s_controller_fsm_sva.sv b/sva/cv32e40s_controller_fsm_sva.sv index 2f9a7daaf..305cb227e 100644 --- a/sva/cv32e40s_controller_fsm_sva.sv +++ b/sva/cv32e40s_controller_fsm_sva.sv @@ -245,7 +245,7 @@ module cv32e40s_controller_fsm_sva // lsu_err_wb_i.bus_err || lsu_err_wb_i.integrity_err |-> ex_wb_pipe_i.instr_valid && ex_wb_pipe_i.lsu_en) // else `uvm_error("controller", "lsu_error in WB with no valid LSU instruction") - // Check that fencei handshake is only exersiced when there's a fencei in the writeback stage + // Check that fencei handshake is only exercised when there is a fencei in the writeback stage a_fencei_hndshk_fencei_wb : assert property (@(posedge clk) disable iff (!rst_n) fencei_flush_req_o |-> fencei_in_wb) @@ -369,7 +369,7 @@ module cv32e40s_controller_fsm_sva assert property (@(posedge clk) disable iff (!rst_n) // Disregard higher priority exceptions and trigger match, and debug as WFI masked during debug !(((ex_wb_pipe_i.instr.mpu_status != MPU_OK) || ex_wb_pipe_i.instr.bus_resp.err || trigger_match_in_wb) && ex_wb_pipe_i.instr_valid) && - !ctrl_fsm_o.debug_wfi_wfe_no_sleep && + !ctrl_fsm_o.debug_no_sleep && // Check for wfi in instruction word and user mode ((ex_wb_pipe_i.instr.bus_resp.rdata == 32'h10500073) && ex_wb_pipe_i.instr_valid && (priv_lvl_i == PRIV_LVL_U) && !mstatus_i.tw) |-> (!exception_in_wb && (ex_wb_pipe_i.sys_en && ex_wb_pipe_i.sys_wfi_insn))) diff --git a/sva/cv32e40s_data_obi_interface_sva.sv b/sva/cv32e40s_data_obi_interface_sva.sv index d5f97b88a..0e293cba7 100644 --- a/sva/cv32e40s_data_obi_interface_sva.sv +++ b/sva/cv32e40s_data_obi_interface_sva.sv @@ -29,7 +29,7 @@ module cv32e40s_data_obi_interface_sva ( input logic clk, input logic rst_n, - if_c_obi.monitor m_c_obi_data_if, + cv32e40s_if_c_obi.monitor m_c_obi_data_if, input logic gntpar_err, input logic gntpar_err_q, input obi_data_resp_t resp_o, diff --git a/sva/cv32e40s_decoder_sva.sv b/sva/cv32e40s_decoder_sva.sv index be4893c2c..11cb91c2b 100644 --- a/sva/cv32e40s_decoder_sva.sv +++ b/sva/cv32e40s_decoder_sva.sv @@ -155,6 +155,7 @@ module cv32e40s_decoder_sva (decoder_i_ctrl.sys_ecall_insn == decoder_ctrl_mux.sys_ecall_insn) && (decoder_i_ctrl.sys_wfi_insn == decoder_ctrl_mux.sys_wfi_insn) && (decoder_i_ctrl.sys_wfe_insn == decoder_ctrl_mux.sys_wfe_insn) && + (decoder_i_ctrl.sys_fence_insn == decoder_ctrl_mux.sys_fence_insn) && (decoder_i_ctrl.sys_fencei_insn == decoder_ctrl_mux.sys_fencei_insn))) else `uvm_error("decoder", "SYS related signals driven from unexpected decoder") diff --git a/sva/cv32e40s_id_stage_sva.sv b/sva/cv32e40s_id_stage_sva.sv index bd18ec4bd..7628fc9f9 100644 --- a/sva/cv32e40s_id_stage_sva.sv +++ b/sva/cv32e40s_id_stage_sva.sv @@ -32,8 +32,6 @@ module cv32e40s_id_stage_sva ( input logic clk, input logic rst_n, - - input logic [31:0] instr, input logic [1:0] rf_re, input logic rf_we, input logic rf_we_dec, @@ -46,14 +44,8 @@ module cv32e40s_id_stage_sva input logic lsu_en, input alu_op_a_mux_e alu_op_a_mux_sel, input alu_op_b_mux_e alu_op_b_mux_sel, - input logic lsu_we, input op_c_mux_e op_c_mux_sel, - input logic sys_dret_insn, - input logic sys_ebrk_insn, - input logic sys_ecall_insn, - input logic sys_fencei_insn, input logic sys_mret_insn, - input logic sys_wfi_insn, input logic ex_ready_i, input logic illegal_insn, input logic [31:0] operand_a_fw, @@ -76,9 +68,6 @@ module cv32e40s_id_stage_sva input logic alu_jmpr, input logic [31:0] jmp_target_o, input logic jmp_taken_id_ctrl_i - - - ); /* todo: check and fix/remove diff --git a/sva/cv32e40s_if_stage_sva.sv b/sva/cv32e40s_if_stage_sva.sv index b02fe4549..96dcea049 100644 --- a/sva/cv32e40s_if_stage_sva.sv +++ b/sva/cv32e40s_if_stage_sva.sv @@ -39,7 +39,7 @@ module cv32e40s_if_stage_sva input privlvl_t prefetch_priv_lvl, input logic dummy_insert, input if_id_pipe_t if_id_pipe_o, - if_c_obi.monitor m_c_obi_instr_if, + cv32e40s_if_c_obi.monitor m_c_obi_instr_if, input logic [31:0] mstateen0_i, input logic seq_tbljmp, input logic seq_valid, diff --git a/sva/cv32e40s_instr_obi_interface_sva.sv b/sva/cv32e40s_instr_obi_interface_sva.sv index 5450811d9..7cb0f4d84 100644 --- a/sva/cv32e40s_instr_obi_interface_sva.sv +++ b/sva/cv32e40s_instr_obi_interface_sva.sv @@ -29,7 +29,7 @@ module cv32e40s_instr_obi_interface_sva ( input logic clk, input logic rst_n, - if_c_obi.monitor m_c_obi_instr_if, + cv32e40s_if_c_obi.monitor m_c_obi_instr_if, input logic gntpar_err, input logic gntpar_err_q, input obi_inst_resp_t resp_o, diff --git a/sva/cv32e40s_load_store_unit_sva.sv b/sva/cv32e40s_load_store_unit_sva.sv index 6f314399f..ebab34798 100644 --- a/sva/cv32e40s_load_store_unit_sva.sv +++ b/sva/cv32e40s_load_store_unit_sva.sv @@ -41,7 +41,7 @@ module cv32e40s_load_store_unit_sva input mpu_status_e lsu_mpu_status_1_o, // WB mpu status input align_status_e lsu_align_status_1_o, input ex_wb_pipe_t ex_wb_pipe_i, - if_c_obi.monitor m_c_obi_data_if, + cv32e40s_if_c_obi.monitor m_c_obi_data_if, input logic id_valid, input logic ex_ready, input logic lsu_en_id, diff --git a/sva/cv32e40s_rvfi_sva.sv b/sva/cv32e40s_rvfi_sva.sv index 8fa2c70d1..997df3375 100644 --- a/sva/cv32e40s_rvfi_sva.sv +++ b/sva/cv32e40s_rvfi_sva.sv @@ -74,8 +74,15 @@ module cv32e40s_rvfi_sva input logic pc_mux_debug, input logic in_trap_clr, input logic wb_valid_lastop, - input logic etrigger_in_wb_i - + input logic etrigger_in_wb_i, + + cv32e40s_if_c_obi.monitor m_c_obi_data_if, + input logic [32*NMEM-1:0] rvfi_mem_addr, + input logic [ 4*NMEM-1:0] rvfi_mem_rmask, + input logic [ 4*NMEM-1:0] rvfi_mem_wmask, + input logic [32*NMEM-1:0] rvfi_mem_rdata, + input logic [32*NMEM-1:0] rvfi_mem_wdata, + input logic [ 3*NMEM-1:0] rvfi_mem_prot ); rvfi_trap_t rvfi_trap_q; // RVFI trap value of the previous valid rvfi instruction @@ -353,6 +360,320 @@ end else `uvm_error("rvfi", "rvfi_instr_obi prot not the same for split transfers") */ -endmodule + localparam int unsigned OBI_FIFO_SIZE = 32; // FIFO needs to be able to hold at least 2*13 memory transfers (because Zc can cause 13 transfers, and these can be split misaligned) + localparam int unsigned MAX_NUM_MEMOP = 13; // This must be set to the maximum number of memory operations per retired instruction. If set too high it will result in unreachable covers + + typedef struct packed { + bit valid; + bit ld_str_blocked; + bit [32*NMEM-1:0] addr; + bit [ 4*NMEM-1:0] rmask; + bit [ 4*NMEM-1:0] wmask; + bit [32*NMEM-1:0] rdata; + bit [32*NMEM-1:0] wdata; + bit [ 3*NMEM-1:0] prot; + } rvfi_mem_t; + + // Return number of memory operations based on rvfi_mem_rmaks/wmask + function automatic int unsigned get_num_memop(bit [4*NMEM-1:0] rvfi_mem_mask); + + int unsigned num_memop = 0; + + for (int i=0; i 4) begin + return 1'b1; + end + else begin + return 1'b0; + end + endfunction : split_xfer + + // Helper signals to identify reads and writes on RVFI + bit [MAX_NUM_MEMOP-1:0] rvfi_mem_xfer; + bit [MAX_NUM_MEMOP-1:0] rvfi_mem_read; + bit [MAX_NUM_MEMOP-1:0] rvfi_mem_write; + bit split_transfer; + + // OBI FIFOs and pointers + obi_data_req_t [OBI_FIFO_SIZE-1:0] data_obi_req_fifo; + obi_data_resp_t [OBI_FIFO_SIZE-1:0] data_obi_resp_fifo; + bit [$clog2(OBI_FIFO_SIZE)-1:0] rd_ptr, rd_ptr_inc, rd_ptr_n; + bit [$clog2(OBI_FIFO_SIZE)-1:0] wr_req_ptr, wr_resp_ptr; + + // Indicate number of memory operations per instruction + int unsigned num_memop; + + rvfi_mem_t rvfi_mem, rvfi_mem_dly, rvfi_mem_exp; + + assign rvfi_mem.valid = rvfi_valid; + assign rvfi_mem.ld_str_blocked = rvfi_trap.trap && ( + (rvfi_trap.exception && + ((rvfi_trap.exception_cause == 6'h4) || // Load Address Misaligned + (rvfi_trap.exception_cause == 6'h5) || // Load Access Fault + (rvfi_trap.exception_cause == 6'h6) || // Store/AMO Address Misaligned + (rvfi_trap.exception_cause == 6'h7))) || // Store/AMO Access Fault + (rvfi_trap.debug && + ((rvfi_trap.debug_cause == 3'h1) || // Debug Breakpoint + (rvfi_trap.debug_cause == 3'h2)))); // Debug trigger match + + assign rvfi_mem.addr = rvfi_mem_addr; + assign rvfi_mem.rmask = rvfi_mem_rmask; + assign rvfi_mem.wmask = rvfi_mem_wmask; + assign rvfi_mem.rdata = rvfi_mem_rdata; + assign rvfi_mem.wdata = rvfi_mem_wdata; + assign rvfi_mem.prot = rvfi_mem_prot; + + localparam MAX_GNT_DLY = 2; + + bit [$clog2(MAX_GNT_DLY+1):0] obi_gnt_dly_cnt; + bit obi_gnt_delay_ok; + + // Keep track of cycles with obi request but no grant + always_ff @(posedge clk_i, negedge rst_ni) begin + if(!rst_ni) begin + obi_gnt_dly_cnt <= '0; + end else begin + if(m_c_obi_data_if.s_req.req && !m_c_obi_data_if.s_gnt.gnt) begin + if (obi_gnt_dly_cnt <= MAX_GNT_DLY) begin + obi_gnt_dly_cnt <= obi_gnt_dly_cnt + 1; + end + end + else begin + obi_gnt_dly_cnt <= '0; + end + end + end + + // Indicate that the OBI grant delay is small enough to allow the OBI FIFO to be populated + // before rvfi_mem_dly.valid is set + assign obi_gnt_delay_ok = obi_gnt_dly_cnt <= MAX_GNT_DLY; + + // Generate delayed version of rvfi_mem + // Needed because write buffer can cause OBI tranfers to be accepted after it's signaled on RVFI + always_ff @(posedge clk_i, negedge rst_ni) begin + if(!rst_ni) begin + rvfi_mem_dly <= '0; + end + else begin + rvfi_mem_dly <= $past(rvfi_mem, MAX_GNT_DLY-1); + end + end + + // FIFOs for OBI transfers + always_ff @(posedge clk_i, negedge rst_ni) begin + if(!rst_ni) begin + data_obi_req_fifo <= '0; + data_obi_resp_fifo <= '0; + wr_req_ptr <= '0; + wr_resp_ptr <= '0; + rd_ptr <= '0; + end + else begin + + // Update read pointer + rd_ptr <= rd_ptr_n; + + // Populate OBI req FIFO + if (m_c_obi_data_if.s_req.req && m_c_obi_data_if.s_gnt.gnt) begin + data_obi_req_fifo[wr_req_ptr] <= m_c_obi_data_if.req_payload; + wr_req_ptr <= wr_req_ptr + 1; + end + + // Populate OBI resp FIFO + if (m_c_obi_data_if.s_rvalid.rvalid) begin + data_obi_resp_fifo[wr_resp_ptr] <= m_c_obi_data_if.resp_payload; + wr_resp_ptr <= wr_resp_ptr + 1; + end + end + end + + // Pointer to next OBI transfer. Used for split misaligned + assign rd_ptr_inc = rd_ptr + 1; + + // Extract number of memory operation in retired instruction + assign num_memop = get_num_memop(rvfi_mem_dly.wmask) + get_num_memop(rvfi_mem_dly.rmask); + + // Assumption here is that if the first transfer is a split, the following ones will be as well. + // The reasoning is that Zc push/pop will always do word read/writes, meaning that if the first is split, so will the rest + assign split_transfer = split_xfer(rvfi_mem_dly.addr[31:0], rvfi_mem_dly.wmask[3:0] | rvfi_mem_dly.rmask[3:0]); + + // Increment read pointer based on memory operations in the retired instruction + always_comb begin + rd_ptr_n = rd_ptr; + + if (|rvfi_mem_xfer) begin + if(split_transfer) begin + // For split transferse, we'll consume 2 OBI tranfers per memory operation + rd_ptr_n = rd_ptr + 2*num_memop; + end + else begin + rd_ptr_n = rd_ptr + 1*num_memop; + end + end + end + + genvar i_memop; + generate + + for(i_memop = 0; i_memop < MAX_NUM_MEMOP; i_memop++) begin: rvfi_mem_asrt + + assign rvfi_mem_read[i_memop] = rvfi_mem_dly.valid && (|rvfi_mem_dly.rmask[(4*i_memop) +: 4]); + assign rvfi_mem_write[i_memop] = rvfi_mem_dly.valid && (|rvfi_mem_dly.wmask[(4*i_memop) +: 4]); + assign rvfi_mem_xfer[i_memop] = rvfi_mem_read[i_memop] || rvfi_mem_write[i_memop]; + + // Helper signals + bit [3:0] exp_rvfi_mem_mask; + bit [31:0] split_1st_wdata; + bit [31:0] split_2nd_wdata; + bit [31:0] split_1st_rdata; + bit [31:0] split_2nd_rdata; + bit [1:0] split_2nd_shift; + + bit [$clog2(OBI_FIFO_SIZE)-1:0] rd_ptr_memop, rd_ptr_memop_inc; + + // Assemble expected transaction on RVFI, based on OBI FIFO + always_comb begin + rvfi_mem_exp.addr [32*i_memop +: 32] = '0; + rvfi_mem_exp.rmask[ 4*i_memop +: 4] = '0; + rvfi_mem_exp.wmask[ 4*i_memop +: 4] = '0; + rvfi_mem_exp.rdata[32*i_memop +: 32] = '0; + rvfi_mem_exp.wdata[32*i_memop +: 32] = '0; + rvfi_mem_exp.prot [ 3*i_memop +: 3] = '0; + + exp_rvfi_mem_mask = '0; + split_2nd_shift = '0; + split_1st_wdata = '0; + split_2nd_wdata = '0; + split_1st_rdata = '0; + split_2nd_rdata = '0; + + rd_ptr_memop = '0; + rd_ptr_memop_inc = '0; + + if (rvfi_mem_xfer[i_memop]) begin + + if(split_transfer) begin + // Split misaligned transfer(s) + + rd_ptr_memop = rd_ptr + 2*i_memop; // Split transfers are reported in one memory operation on rvfi_mem, but results in 2 OBI transfers. + rd_ptr_memop_inc = rd_ptr_memop + 1; + + split_2nd_shift = 4 - data_obi_req_fifo[rd_ptr_memop].addr[1:0]; + + exp_rvfi_mem_mask = (data_obi_req_fifo[rd_ptr_memop].be >> data_obi_req_fifo[rd_ptr_memop].addr[1:0]) | + (data_obi_req_fifo[rd_ptr_memop_inc].be << split_2nd_shift); + + // Extract data from the two OBI transfers + split_1st_wdata = data_obi_req_fifo[rd_ptr_memop].wdata & get_bitmask(data_obi_req_fifo[rd_ptr_memop].be); + split_2nd_wdata = data_obi_req_fifo[rd_ptr_memop_inc].wdata & get_bitmask(data_obi_req_fifo[rd_ptr_memop_inc].be); + + split_1st_rdata = data_obi_resp_fifo[rd_ptr_memop].rdata & get_bitmask(data_obi_req_fifo[rd_ptr_memop].be); + split_2nd_rdata = data_obi_resp_fifo[rd_ptr_memop_inc].rdata & get_bitmask(data_obi_req_fifo[rd_ptr_memop_inc].be); + + // Align rdata/wdata to correspond to expected rdata/wdata on RVFI + rvfi_mem_exp.wdata[(32*i_memop) +: 32] = split_1st_wdata >> (8 * data_obi_req_fifo[rd_ptr_memop].addr[1:0]) | + split_2nd_wdata << (8 * split_2nd_shift); + + rvfi_mem_exp.rdata[(32*i_memop) +: 32] = split_1st_rdata >> (8 * data_obi_req_fifo[rd_ptr_memop].addr[1:0]) | + split_2nd_rdata << (8 * split_2nd_shift); + end + else begin + + rd_ptr_memop = rd_ptr + i_memop; + + exp_rvfi_mem_mask = data_obi_req_fifo[rd_ptr_memop].be >> data_obi_req_fifo[rd_ptr_memop].addr[1:0]; + + // Align rdata/wdata to correspond to expected rdata/wdata on RVFI + rvfi_mem_exp.wdata[(32*i_memop) +: 32] = data_obi_req_fifo[rd_ptr_memop].wdata >> (8 * data_obi_req_fifo[rd_ptr_memop].addr[1:0]); + + rvfi_mem_exp.rdata[(32*i_memop) +: 32] = data_obi_resp_fifo[rd_ptr_memop].rdata >> (8 * data_obi_req_fifo[rd_ptr_memop].addr[1:0]); + + end + + // Addr and prot are equal for both transfers in a split transfer + rvfi_mem_exp.addr[(32*i_memop) +: 32] = data_obi_req_fifo[rd_ptr_memop].addr; + rvfi_mem_exp.prot[(3*i_memop) +: 3] = data_obi_req_fifo[rd_ptr_memop].prot; + + if(rvfi_mem_read[i_memop]) begin + rvfi_mem_exp.rmask[(4*i_memop) +: 4] = exp_rvfi_mem_mask; + end + else begin + rvfi_mem_exp.wmask[(4*i_memop) +: 4] = exp_rvfi_mem_mask; + end + + end // if (rvfi_mem_xfer[i_memop]) + + end + + // Assert that rvfi_mem is consistent with OBI transfers + a_rvfi_mem_consistency_read_addr: + assert property (@(posedge clk_i) disable iff (!rst_ni) + rvfi_mem_read[i_memop] |-> rvfi_mem_exp.addr[(32*i_memop) +: 32] == rvfi_mem_dly.addr[(32*i_memop) +: 32]) + else `uvm_error("rvfi", "rvfi_mem_addr not consistent with OBI transfers for reads") + + a_rvfi_mem_consistency_read_rmask: + assert property (@(posedge clk_i) disable iff (!rst_ni) + rvfi_mem_read[i_memop] |-> rvfi_mem_exp.rmask[(4*i_memop) +: 4] == rvfi_mem_dly.rmask[(4*i_memop) +: 4]) + else `uvm_error("rvfi", "rvfi_mem_rmask not consistent with OBI transfers") + + a_rvfi_mem_consistency_rdata: + assert property (@(posedge clk_i) disable iff (!rst_ni) + rvfi_mem_read[i_memop] && !rvfi_mem_dly.ld_str_blocked |-> + (rvfi_mem_exp.rdata[(32*i_memop) +: 32] & get_bitmask(rvfi_mem_exp.rmask[(4*i_memop) +: 4])) == + (rvfi_mem_dly.rdata[(32*i_memop) +: 32] & get_bitmask(rvfi_mem_dly.rmask[(4*i_memop) +: 4]))) + else `uvm_error("rvfi", "rvfi_mem_rdata not consistent with OBI transfers") + + a_rvfi_mem_consistency_read_prot: + assert property (@(posedge clk_i) disable iff (!rst_ni) + rvfi_mem_read[i_memop] |-> rvfi_mem_exp.prot[(3*i_memop) +: 3] == rvfi_mem_dly.prot[(3*i_memop) +: 3]) + else `uvm_error("rvfi", "rvfi_mem_prot not consistent with OBI transfers for reads") + + a_rvfi_mem_consistency_write_addr: + assert property (@(posedge clk_i) disable iff (!rst_ni) + obi_gnt_delay_ok && rvfi_mem_write[i_memop] |-> rvfi_mem_exp.addr[(32*i_memop) +: 32] == rvfi_mem_dly.addr[(32*i_memop) +: 32]) + else `uvm_error("rvfi", "rvfi_mem_addr not consistent with OBI transfers for writes") + + a_rvfi_mem_consistency_write_wmask: + assert property (@(posedge clk_i) disable iff (!rst_ni) + obi_gnt_delay_ok && rvfi_mem_write[i_memop] |-> rvfi_mem_exp.wmask[(4*i_memop) +: 4] == rvfi_mem_dly.wmask[(4*i_memop) +: 4]) + else `uvm_error("rvfi", "rvfi_mem_wdata not consistent with OBI transfers") + + a_rvfi_mem_consistency_wdata: + assert property (@(posedge clk_i) disable iff (!rst_ni) + obi_gnt_delay_ok && rvfi_mem_write[i_memop] |-> + (rvfi_mem_exp.wdata[(32*i_memop) +: 32] & get_bitmask(rvfi_mem_exp.wmask[(4*i_memop) +: 4])) == + (rvfi_mem_dly.wdata[(32*i_memop) +: 32] & get_bitmask(rvfi_mem_dly.wmask[(4*i_memop) +: 4]))) + else `uvm_error("rvfi", "rvfi_mem_wdata not consistent with OBI transfers") + + a_rvfi_mem_consistency_write_prot: + assert property (@(posedge clk_i) disable iff (!rst_ni) + obi_gnt_delay_ok && rvfi_mem_write[i_memop] |-> rvfi_mem_exp.prot[(3*i_memop) +: 3] == rvfi_mem_dly.prot[(3*i_memop) +: 3]) + else `uvm_error("rvfi", "rvfi_mem_prot not consistent with OBI transfers for writes") + + end + + endgenerate + +endmodule diff --git a/yaml/csr.yaml.m4 b/yaml/csr.yaml.m4 index f789bdc7d..1f5858318 100644 --- a/yaml/csr.yaml.m4 +++ b/yaml/csr.yaml.m4 @@ -4654,22 +4654,13 @@ ifelse(eval(ZC != 0), 1, [[[ address: 0x017 privilege_mode: U rv32: - - field_name: Base_31_10 + - field_name: Base_31_6 description: > - Upper bits of vector table base address, 1024 byte aligned + Table Jump Base Address, 64 byte aligned type: WARL reset_val: 0 msb: 31 - lsb: 10 - - field_name: Base_9_6 - description: > - Lower bits of vector table base address, 1024 byte aligned always 0 - type: WARL - reset_val: 0 - msb: 9 lsb: 6 - warl_legalize: | - val_out = val_in if val_in == 0 else val_orig - field_name: Mode description: > Jump table mode