Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduced type for lsu_err_wb #958

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions bhv/cv32e40x_rvfi.sv
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ module cv32e40x_rvfi
input logic [31:0] rf_wdata_wb_i,
input logic [31:0] lsu_rdata_wb_i,
input logic lsu_exokay_wb_i,
input logic [1:0] lsu_err_wb_i,
input lsu_err_wb_t lsu_err_wb_i,
input logic mret_ptr_wb_i,
input logic clic_ptr_wb_i,
input logic csr_mscratchcsw_in_wb_i,
Expand Down Expand Up @@ -1314,16 +1314,16 @@ module cv32e40x_rvfi
// The err response for bufferable write transactions can lead to an NMI. The exokay response for bufferable write transactions is ignored by the CPU (in fact it is also
// ignored for most other transactions as it is only used for SC.W instructions).

rvfi_mem_exokay [ (1*(memop_cnt+1))-1 -: 1] <= !mem_access_blocked_wb && (|mem_rmask [STAGE_WB] || (|mem_wmask [STAGE_WB] && !ex_mem_trans.memtype[0])) ? lsu_exokay_wb_i : '0;
rvfi_mem_err [ (1*(memop_cnt+1))-1 -: 1] <= !mem_access_blocked_wb && (|mem_rmask [STAGE_WB] || (|mem_wmask [STAGE_WB] && !ex_mem_trans.memtype[0])) ? lsu_err_wb_i[0] : '0;
rvfi_mem_exokay [ (1*(memop_cnt+1))-1 -: 1] <= !mem_access_blocked_wb && (|mem_rmask [STAGE_WB] || (|mem_wmask [STAGE_WB] && !ex_mem_trans.memtype[0])) ? lsu_exokay_wb_i : '0;
rvfi_mem_err [ (1*(memop_cnt+1))-1 -: 1] <= !mem_access_blocked_wb && (|mem_rmask [STAGE_WB] || (|mem_wmask [STAGE_WB] && !ex_mem_trans.memtype[0])) ? lsu_err_wb_i.bus_err : '0;
end

else if (lsu_split_2nd_xfer_wb && !mem_access_blocked_wb) begin
// For split access, rvfi_mem_err and rvfi_mem_exokay are based on both misaligned accesses.
// But, as mentioned above, we disregard the reported OBI err and exokay signals from bufferable write transactions.

rvfi_mem_exokay [ (1*(memop_cnt+1))-1 -: 1] <= rvfi_mem_exokay[ (1'b1*(memop_cnt+1'b1))-1'b1 -: 1] && ((|mem_rmask [STAGE_WB] || (|mem_wmask [STAGE_WB] && !ex_mem_trans_2.memtype[0])) ? lsu_exokay_wb_i : '0);
rvfi_mem_err [ (1*(memop_cnt+1))-1 -: 1] <= rvfi_mem_err [ (1'b1*(memop_cnt+1'b1))-1'b1 -: 1] || ((|mem_rmask [STAGE_WB] || (|mem_wmask [STAGE_WB] && !ex_mem_trans_2.memtype[0])) ? lsu_err_wb_i[0] : '0);
rvfi_mem_exokay [ (1*(memop_cnt+1))-1 -: 1] <= rvfi_mem_exokay[ (1'b1*(memop_cnt+1'b1))-1'b1 -: 1] && ((|mem_rmask [STAGE_WB] || (|mem_wmask [STAGE_WB] && !ex_mem_trans_2.memtype[0])) ? lsu_exokay_wb_i : '0);
rvfi_mem_err [ (1*(memop_cnt+1))-1 -: 1] <= rvfi_mem_err [ (1'b1*(memop_cnt+1'b1))-1'b1 -: 1] || ((|mem_rmask [STAGE_WB] || (|mem_wmask [STAGE_WB] && !ex_mem_trans_2.memtype[0])) ? lsu_err_wb_i.bus_err : '0);
end

else if (lsu_split_2nd_xfer_wb && mem_access_blocked_wb) begin
Expand Down
2 changes: 1 addition & 1 deletion rtl/cv32e40x_controller.sv
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ module cv32e40x_controller import cv32e40x_pkg::*;

// LSU
input logic data_stall_wb_i, // WB stalled by LSU
input logic [1:0] lsu_err_wb_i, // LSU bus error in WB stage
input lsu_err_wb_t lsu_err_wb_i, // LSU bus error in WB stage
input logic lsu_busy_i, // LSU is busy with outstanding transfers or is initiating a new transfer
input logic lsu_bus_busy_i, // LSU is busy with outstanding transfers
input logic lsu_interruptible_i, // LSU may be interrupted
Expand Down
10 changes: 5 additions & 5 deletions rtl/cv32e40x_controller_fsm.sv
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ module cv32e40x_controller_fsm import cv32e40x_pkg::*;

// From WB stage
input ex_wb_pipe_t ex_wb_pipe_i,
input logic [1:0] lsu_err_wb_i, // LSU caused bus_error in WB stage, gated with data_rvalid_i inside load_store_unit
input lsu_err_wb_t lsu_err_wb_i, // LSU caused bus_error in WB stage, gated with data_rvalid_i inside load_store_unit
input logic last_op_wb_i, // WB stage contains the last operation of an instruction
input logic abort_op_wb_i, // WB stage contains an (to be) aborted instruction or sequence
input mpu_status_e mpu_status_wb_i, // MPU status (WB timing)
Expand Down Expand Up @@ -414,12 +414,12 @@ module cv32e40x_controller_fsm import cv32e40x_pkg::*;
// Using flopped version to avoid paths from data_err_i/data_rvalid_i to instr_* outputs
assign pending_nmi = nmi_pending_q;

// Early version of the pending_nmi signal, using the unflopped lsu_err_wb_i[0]
// Early version of the pending_nmi signal, using the unflopped lsu_err_wb_i.bus_err
// This signal is used for halting the ID stage in the same cycle as the bus error arrives.
// This ensures that any instruction in the ID stage that may depend on the result of the faulted load
// will not propagate to the EX stage. For cycles after lsu_err_wb_i[0] is
// high, ID stage will be halted due to pending_nmi and !nmi_allowed.
assign pending_nmi_early = lsu_err_wb_i[0];
assign pending_nmi_early = lsu_err_wb_i.bus_err;

// 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
Expand Down Expand Up @@ -1222,11 +1222,11 @@ module cv32e40x_controller_fsm import cv32e40x_pkg::*;
nmi_pending_q <= 1'b0;
nmi_is_store_q <= 1'b0;
end else begin
if (lsu_err_wb_i[0] && !nmi_pending_q) begin
if (lsu_err_wb_i.bus_err && !nmi_pending_q) begin
// Set whenever an error occurs in WB for the LSU, unless we already have an NMI pending.
// Later errors could overwrite the bit for load/store type, and with mtval the address would be overwritten.
nmi_pending_q <= 1'b1;
nmi_is_store_q <= lsu_err_wb_i[1];
nmi_is_store_q <= lsu_err_wb_i.store;
// Clear when the controller takes the NMI
end else if (ctrl_fsm_o.pc_set && (ctrl_fsm_o.pc_mux == PC_TRAP_NMI)) begin
nmi_pending_q <= 1'b0;
Expand Down
2 changes: 1 addition & 1 deletion rtl/cv32e40x_core.sv
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ module cv32e40x_core import cv32e40x_pkg::*;
logic [31:0] lsu_wpt_match_wb;
align_status_e lsu_align_status_wb;
logic [31:0] lsu_rdata_wb;
logic [1:0] lsu_err_wb;
lsu_err_wb_t lsu_err_wb;
lsu_atomic_e lsu_atomic_wb;

logic lsu_valid_0; // Handshake with EX
Expand Down
5 changes: 3 additions & 2 deletions rtl/cv32e40x_load_store_unit.sv
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ module cv32e40x_load_store_unit import cv32e40x_pkg::*;
output logic [3:0] lsu_be_o,

// Stage 1 outputs (WB)
output logic [1:0] lsu_err_1_o,
output lsu_err_wb_t lsu_err_1_o,
output logic [31:0] lsu_rdata_1_o, // LSU read data
output mpu_status_e lsu_mpu_status_1_o, // MPU (PMA) status, response/WB timing. To controller and wb_stage
output logic [31:0] lsu_wpt_match_1_o, // Address match trigger, WB timing.
Expand Down Expand Up @@ -704,7 +704,8 @@ module cv32e40x_load_store_unit import cv32e40x_pkg::*;

// Validate bus_error on rvalid from the bus (WB stage)
// For bufferable transfers, this can happen many cycles after the pipeline control logic has seen the filtered resp_valid
assign lsu_err_1_o = xif_res_q ? '0 : resp.bus_resp.err;
assign lsu_err_1_o.bus_err = xif_res_q ? 1'b0 : resp.bus_resp.err[0];
assign lsu_err_1_o.store = xif_res_q ? 1'b0 : resp.bus_resp.err[1];

//////////////////////////////////////////////////////////////////////////////
// WPT
Expand Down
6 changes: 6 additions & 0 deletions rtl/include/cv32e40x_pkg.sv
Original file line number Diff line number Diff line change
Expand Up @@ -1123,6 +1123,12 @@ typedef struct packed
logic pushpop; // Operation is part of a push/pop sequence.
} instr_meta_t;

typedef struct packed
{
logic bus_err;
logic store;
} lsu_err_wb_t;

// Struct for carrying eXtension interface information
typedef struct packed
{
Expand Down
10 changes: 5 additions & 5 deletions sva/cv32e40x_controller_fsm_sva.sv
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ module cv32e40x_controller_fsm_sva
input logic csr_illegal_i,
input logic pending_single_step,
input logic trigger_match_in_wb,
input logic [1:0] lsu_err_wb_i,
input lsu_err_wb_t lsu_err_wb_i,
input logic wb_valid_i,
input logic fencei_in_wb,
input logic fencei_flush_req_o,
Expand Down Expand Up @@ -267,19 +267,19 @@ module cv32e40x_controller_fsm_sva
(ex_wb_pipe_i.sys_en && (ex_wb_pipe_i.sys_wfi_insn || ex_wb_pipe_i.sys_wfe_insn) && ex_wb_pipe_i.instr_valid) |-> !(id_ex_pipe_i.lsu_en) )
else `uvm_error("controller", "LSU instruction follows WFI or WFE")

// Check that lsu_err_wb_i==2'b01 (load error) can only be true when an LSU instruction is valid in WB
// Check that a load error can only be true when an LSU instruction is valid in WB
// Not using wb_valid, as that is only active for the second half of misaligned.
// bus error may also be active on the first half, thus checking only for active LSU in WB.
a_lsu_load_err_wb :
assert property (@(posedge clk) disable iff (!rst_n)
lsu_err_wb_i == 2'b01 // Upon LSU error on load
(lsu_err_wb_i.bus_err && !lsu_err_wb_i.store) // Upon LSU error on load
|-> ex_wb_pipe_i.instr_valid && ex_wb_pipe_i.lsu_en) // There must be a valid LSU instruction in WB
else `uvm_error("controller", "LSU load error in WB with no valid LSU instruction")

// Check that lsu_err_wb_i==2'b11 (store error) can only be true when an LSU instruction is valid in WB, or there's an outstanding OBI transfer
// Check that a store error can only be true when an LSU instruction is valid in WB, or there's an outstanding OBI transfer
a_lsu_store_err_wb :
assert property (@(posedge clk) disable iff (!rst_n)
lsu_err_wb_i == 2'b11 // Upon LSU error on store
(lsu_err_wb_i.bus_err && lsu_err_wb_i.store) // Upon LSU error on store
|-> (ex_wb_pipe_i.instr_valid && ex_wb_pipe_i.lsu_en) // There must be a valid LSU instruction in WB
|| (response_filter_bus_cnt_q_i != '0)) // Or an outstanding transfer on the bus (taking buffered writes into account)
else `uvm_error("controller", "LSU store error in WB with no valid LSU instruction or outstanding transfers on the bus")
Expand Down