From 950f7008b1ec12cc7b0cbdee5ae91543f28b29ed Mon Sep 17 00:00:00 2001 From: Oystein Knauserud Date: Wed, 20 Sep 2023 15:10:22 +0200 Subject: [PATCH] Flushing pipeline on writes to mstateen0. Not a real requirement, as the hazard is resolved as a byproduct og other stalls but it is much easier to understand. Signed-off-by: Oystein Knauserud --- bhv/cv32e40s_wrapper.sv | 8 ++++++++ rtl/cv32e40s_cs_registers.sv | 8 +++++++- sva/cv32e40s_sequencer_sva.sv | 21 ++++++++++++++++++++- 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/bhv/cv32e40s_wrapper.sv b/bhv/cv32e40s_wrapper.sv index 57e49e81a..43fbe943e 100644 --- a/bhv/cv32e40s_wrapper.sv +++ b/bhv/cv32e40s_wrapper.sv @@ -556,6 +556,14 @@ endgenerate .wb_valid_i (core_i.wb_stage_i.wb_valid_o ), .exception_in_wb_i (core_i.controller_i.controller_fsm_i.exception_in_wb ), .pending_sync_debug_i (core_i.controller_i.controller_fsm_i.pending_sync_debug), + .csr_addr_id_i (core_i.id_stage_i.operand_b[11:0]), + .csr_en_id_i (core_i.id_stage_i.csr_en), + .instr_valid_id_i (core_i.id_stage_i.instr_valid), + .csr_raddr_ex_i (core_i.cs_registers_i.csr_raddr), + .csr_waddr_wb_i (core_i.cs_registers_i.csr_waddr), + .csr_we_wb_i (core_i.cs_registers_i.csr_we_int), + .priv_lvl_id_i (core_i.if_id_pipe.priv_lvl), + .csr_illegal_i (core_i.cs_registers_i.csr_illegal_o), .*); bind cv32e40s_instr_obi_interface : diff --git a/rtl/cv32e40s_cs_registers.sv b/rtl/cv32e40s_cs_registers.sv index afee8fbe6..7c3b65462 100644 --- a/rtl/cv32e40s_cs_registers.sv +++ b/rtl/cv32e40s_cs_registers.sv @@ -373,6 +373,9 @@ module cv32e40s_cs_registers import cv32e40s_pkg::*; // Detect JVT writes (requires pipeline flush) logic jvt_wr_in_wb; + // Detect mstateen0 writes (requires pipeline flush) + logic mstateen0_wr_in_wb; + logic mscratch_rd_error; logic mstatus_rd_error; logic mtvec_rd_error; @@ -2216,7 +2219,10 @@ module cv32e40s_cs_registers import cv32e40s_pkg::*; // Detect when a JVT write is in WB assign jvt_wr_in_wb = csr_wr_in_wb && (csr_waddr == CSR_JVT); - assign csr_wr_in_wb_flush_o = xsecure_csr_wr_in_wb || pmp_csr_wr_in_wb || jvt_wr_in_wb; + // Detect when a mstateen0 write is in WB + assign mstateen0_wr_in_wb = csr_wr_in_wb && (csr_waddr == CSR_MSTATEEN0); + + assign csr_wr_in_wb_flush_o = xsecure_csr_wr_in_wb || pmp_csr_wr_in_wb || jvt_wr_in_wb || mstateen0_wr_in_wb; if (USER) begin : privlvl_user // Privilege level register diff --git a/sva/cv32e40s_sequencer_sva.sv b/sva/cv32e40s_sequencer_sva.sv index 9a81e8f13..d217f8080 100644 --- a/sva/cv32e40s_sequencer_sva.sv +++ b/sva/cv32e40s_sequencer_sva.sv @@ -53,7 +53,16 @@ module cv32e40s_sequencer_sva input ex_wb_pipe_t ex_wb_pipe_i, input logic wb_valid_i, input logic exception_in_wb_i, - input logic pending_sync_debug_i + input logic pending_sync_debug_i, + input logic [11:0] csr_addr_id_i, + input logic csr_en_id_i, + input logic instr_valid_id_i, + input csr_num_e csr_raddr_ex_i, // EX stage instr valid included, raddr is zero if not CSR instruction is valid in EX + input csr_num_e csr_waddr_wb_i, + input logic csr_we_wb_i, + input privlvl_t priv_lvl_i, + input privlvl_t priv_lvl_id_i, + input logic csr_illegal_i ); // After kill, all state must be reset. @@ -182,6 +191,16 @@ module cv32e40s_sequencer_sva else `uvm_error("sequencer", "Should not count when handling table jumps") + a_tbljmp_mstateen: + assert property (@(posedge clk) disable iff (!rst_n) + (valid_o && ready_i && seq_tbljmp_o) && // tablejump instruction decoded + (priv_lvl_i == PRIV_LVL_U) // in USER mode + |-> + !(instr_valid_id_i && csr_en_id_i && (csr_num_e'(csr_addr_id_i) == CSR_MSTATEEN0) && (priv_lvl_id_i == PRIV_LVL_M)) && // No access to mstateen0 in ID + !((csr_raddr_ex_i == CSR_MSTATEEN0) && !csr_illegal_i) && // or EX + !((csr_waddr_wb_i == CSR_MSTATEEN0) && csr_we_wb_i)) // or WB + else `uvm_error("sequencer", "Sequencer emitting tablejump while mstateen0 is written") + // Support logic. Sticky bit indicating synchronous exception or syncronous debug during a push or pop sequence logic pushpop_sync_exc_or_dbg_q;