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

Merge from CV32E40X #372

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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 6 additions & 1 deletion bhv/cv32e40s_wrapper.sv
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,8 @@ module cv32e40s_wrapper
.lsu_trans_valid_i (core_i.load_store_unit_i.trans_valid),
.csr_en_id_i (core_i.id_stage_i.csr_en),
.ptr_in_if_i (core_i.if_stage_i.ptr_in_if_o),
.instr_req_o (core_i.instr_req_o),
.instr_dbg_o (core_i.instr_dbg_o),
.*);
bind cv32e40s_cs_registers:
core_i.cs_registers_i
Expand Down Expand Up @@ -317,7 +319,10 @@ module cv32e40s_wrapper
core_i.if_stage_i.prefetch_unit_i
cv32e40s_prefetch_unit_sva
#(.SMCLIC(SMCLIC))
prefetch_unit_sva (.*);
prefetch_unit_sva (
.ctrl_fsm_cs (core_i.controller_i.controller_fsm_i.ctrl_fsm_cs),
.debug_req_i (core_i.debug_req_i),
.*);

generate
if(M_EXT == M) begin: div_sva
Expand Down
23 changes: 13 additions & 10 deletions rtl/cv32e40s_controller_fsm.sv
Original file line number Diff line number Diff line change
Expand Up @@ -714,17 +714,20 @@ module cv32e40s_controller_fsm import cv32e40s_pkg::*;
RESET: begin
ctrl_fsm_o.instr_req = 1'b0;
if (fetch_enable_i) begin
ctrl_fsm_ns = BOOT_SET;
if (debug_req_i) begin
// Not raising instr_req to prevent fetching until we are in debug mode
ctrl_fsm_o.instr_req = 1'b0;
ctrl_fsm_o.pc_mux = PC_BOOT;
ctrl_fsm_o.pc_set = 1'b1; // pc_set is required for propagating boot address to dpc (from IF stage)
ctrl_fsm_ns = DEBUG_TAKEN;
end else begin
ctrl_fsm_o.instr_req = 1'b1;
ctrl_fsm_o.pc_mux = PC_BOOT;
ctrl_fsm_o.pc_set = 1'b1;
ctrl_fsm_ns = FUNCTIONAL;
end
end
end
// BOOT_SET state required to prevent (timing) path from
// fetch_enable_i via pc_set to instruction interface outputs
BOOT_SET: begin
ctrl_fsm_o.instr_req = 1'b1;
ctrl_fsm_o.pc_mux = PC_BOOT;
ctrl_fsm_o.pc_set = 1'b1;
ctrl_fsm_ns = FUNCTIONAL;
end
FUNCTIONAL: begin
// NMI
if (pending_nmi && nmi_allowed) begin
Expand Down Expand Up @@ -1432,7 +1435,7 @@ module cv32e40s_controller_fsm import cv32e40s_pkg::*;

case (debug_fsm_cs)
HAVERESET: begin
if (debug_mode_n || (ctrl_fsm_ns == BOOT_SET)) begin
if (debug_mode_n || (ctrl_fsm_ns == FUNCTIONAL)) begin
if (debug_mode_n) begin
debug_fsm_ns = HALTED;
end else begin
Expand Down
2 changes: 1 addition & 1 deletion rtl/include/cv32e40s_pkg.sv
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ typedef enum logic [DIV_OP_WIDTH-1:0]
} div_opcode_e;

// FSM state encoding
typedef enum logic [2:0] { RESET, BOOT_SET, FUNCTIONAL, SLEEP, DEBUG_TAKEN} ctrl_state_e;
typedef enum logic [1:0] { RESET, FUNCTIONAL, SLEEP, DEBUG_TAKEN} ctrl_state_e;

// Debug FSM state encoding
// State encoding done one-hot to ensure that debug_havereset_o, debug_running_o, debug_halted_o
Expand Down
10 changes: 0 additions & 10 deletions sva/cv32e40s_alignment_buffer_sva.sv
Original file line number Diff line number Diff line change
Expand Up @@ -186,16 +186,6 @@ module cv32e40s_alignment_buffer_sva
`uvm_error("Alignment buffer SVA",
$sformatf("Wrong PC after branch"))

// Check that a taken branch can only occur if fetching is requested
property p_branch_implies_req;
@(posedge clk) disable iff (!rst_n) (ctrl_fsm_i.pc_set) |-> (ctrl_fsm_i.instr_req);
endproperty

a_branch_implies_req:
assert property(p_branch_implies_req)
else
`uvm_error("Alignment buffer SVA",
$sformatf("Taken branch occurs while fetching is not requested"))

// Check that we never exceed two outstanding transactions
property p_max_outstanding;
Expand Down
16 changes: 12 additions & 4 deletions sva/cv32e40s_controller_fsm_sva.sv
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,11 @@ module cv32e40s_controller_fsm_sva
input pipe_pc_mux_e pipe_pc_mux_ctrl,
input logic ptr_in_if_i,
input logic etrigger_in_wb,
input logic lsu_wpt_match_wb_i
input logic lsu_wpt_match_wb_i,
input logic debug_req_i,
input logic fetch_enable_i,
input logic instr_req_o,
input logic instr_dbg_o
);


Expand Down Expand Up @@ -208,11 +212,11 @@ module cv32e40s_controller_fsm_sva
(ctrl_fsm_o.kill_wb) |-> (!csr_we_i) )
else `uvm_error("controller", "csr written while kill_wb is asserted")

// Check that no stages have valid instructions using RESET or BOOT_SET
// Check that no stages have valid instructions using RESET
a_reset_if_csr :
assert property (@(posedge clk) disable iff (!rst_n)
((ctrl_fsm_cs == RESET) || (ctrl_fsm_cs == BOOT_SET)) |-> (!if_valid_i && !if_id_pipe_i.instr_valid && !id_ex_pipe_i.instr_valid && !ex_wb_pipe_i.instr_valid) )
else `uvm_error("controller", "Instruction valid during RESET or BOOT_SET")
((ctrl_fsm_cs == RESET)) |-> (!if_valid_i && !if_id_pipe_i.instr_valid && !id_ex_pipe_i.instr_valid && !ex_wb_pipe_i.instr_valid) )
else `uvm_error("controller", "Instruction valid during RESET")

// Check that no LSU insn can be in EX when there is a WFI or WFE in WB
a_wfi_wfe_lsu_csr :
Expand Down Expand Up @@ -975,5 +979,9 @@ end
|->
(abort_op_wb_i && (ctrl_fsm_ns == DEBUG_TAKEN)))
else `uvm_error("controller", "Debug not entered on a WPT match")




endmodule

31 changes: 30 additions & 1 deletion sva/cv32e40s_core_sva.sv
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ module cv32e40s_core_sva
)
(
input logic clk,
input logic clk_i,
input logic rst_ni,

input ctrl_fsm_t ctrl_fsm,
Expand Down Expand Up @@ -94,6 +95,9 @@ module cv32e40s_core_sva
input logic [31:0] data_rdata_i,
input logic [4:0] data_rchk_i,
input logic data_err_i,
input logic fetch_enable_i,
input logic debug_req_i,

input alu_op_a_mux_e alu_op_a_mux_sel_id_i,
input alu_op_b_mux_e alu_op_b_mux_sel_id_i,
input logic [31:0] operand_a_id_i,
Expand Down Expand Up @@ -803,5 +807,30 @@ endproperty;

a_hint_id_wb: assert property(p_dummy_id_wb)
else `uvm_error("core", "X0 not stable for hint instruction in ID")
endmodule


// If debug_req_i is asserted when fetch_enable_i gets asserted we should not execute any
// instruction until the core is in debug mode.
a_reset_into_debug:
assert property (@(posedge clk_i) disable iff (!rst_ni)
(ctrl_fsm_cs == RESET) &&
fetch_enable_i &&
debug_req_i
##1
debug_req_i // Controller gets a one cycle delayed fetch enable, must keep debug_req_i asserted for two cycles
|->
!wb_valid until (wb_valid && ctrl_fsm.debug_mode))
else `uvm_error("controller", "Debug out of reset but executed instruction outside debug mode")

// When entering debug out of reset, the first fetch must also flag debug on the instruction OBI interface
a_first_fetch_debug:
assert property (@(posedge clk_i) disable iff (!rst_ni)
(ctrl_fsm_cs == RESET) &&
fetch_enable_i &&
debug_req_i
##1
debug_req_i // Controller gets a one cycle delayed fetch enable, must keep debug_req_i asserted for two cycles
|->
!instr_req_o until (instr_req_o && instr_dbg_o))
else `uvm_error("controller", "Debug out of reset but fetched without setting instr_dbg_o")
endmodule
9 changes: 7 additions & 2 deletions sva/cv32e40s_prefetch_unit_sva.sv
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@ module cv32e40s_prefetch_unit_sva import cv32e40s_pkg::*;
input logic prefetch_ready_i,
input logic trans_valid_o,
input logic trans_ready_i,
input logic fetch_ptr_resp
input logic fetch_ptr_resp,
input ctrl_state_e ctrl_fsm_cs,
input logic debug_req_i

);

Expand All @@ -46,8 +48,11 @@ module cv32e40s_prefetch_unit_sva import cv32e40s_pkg::*;
else `uvm_error("prefetch_buffer", "Assertion a_branch_halfword_aligned failed")

// Check that a taken branch can only occur if fetching is requested
// Exception while in RESET state and debug_request_i is high - in that case we want to
// do a pc_set to update the IF stage PC without actually fetching anything. This is to ensure
// that dpc gets the correct (boot) address when going from reset to debug.
property p_branch_implies_req;
@(posedge clk) (ctrl_fsm_i.pc_set) |-> (ctrl_fsm_i.instr_req);
@(posedge clk) (ctrl_fsm_i.pc_set) && !((ctrl_fsm_cs == RESET) && debug_req_i) |-> (ctrl_fsm_i.instr_req);
endproperty

a_branch_implies_req : assert property(p_branch_implies_req)
Expand Down