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 #377

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
15 changes: 9 additions & 6 deletions bhv/cv32e40s_rvfi.sv
Expand Up @@ -941,7 +941,8 @@ module cv32e40s_rvfi
instr_prot[STAGE_ID] <= obi_instr_if.req_payload.prot;

end else begin
if (in_trap_clr) begin
// Clear in trap if trap reached rvfi outputs or we insert a bubble into the ID stage
if (in_trap_clr || id_ready_i) begin
// Clear interrupt pipeline when it reaches rvfi_intr
in_trap [STAGE_ID] <= '0;
end
Expand All @@ -956,10 +957,12 @@ module cv32e40s_rvfi

// If there is a trap in the pipeline when debug is taken, the trap will be supressed but the side-effects will not.
// The succeeding instruction therefore needs to re-trigger the intr signals if it it did not reach the rvfi output.
// When in_trap_clr is set, the in_trap[STAGE_WB] reached the RVFI outputs and we must not propagate it back to the in_trap[STAGE_IF]
in_trap[STAGE_IF] <= in_trap[STAGE_IF].intr ? in_trap[STAGE_IF] :
in_trap[STAGE_ID].intr ? in_trap[STAGE_ID] :
in_trap[STAGE_EX].intr ? in_trap[STAGE_EX] :
in_trap[STAGE_WB];
!in_trap_clr ? in_trap[STAGE_WB] :
'0;
// In case the first instruction during debug mode gets an exception, if_stage will be killed and the clearing
// of debug_cause due to last_op_if_i during (if_valid && id_ready) may never happen. This will lead to a wrong
// value of debug_cause on RVFI outputs. To avoid this, debug_cause is cleared if IF stage is killed due to an exception.
Expand Down Expand Up @@ -1019,8 +1022,8 @@ module cv32e40s_rvfi
rs1_re_subop [STAGE_EX] <= rf_re_id_i[0];
rs2_re_subop [STAGE_EX] <= rf_re_id_i[1];
end else begin
if (in_trap_clr) begin
// Clear interrupt pipeline when it reaches rvfi_intr
if (in_trap_clr || ex_ready_i) begin
// Clear in trap if trap reached rvfi outputs or we insert a bubble into the EX stage
in_trap [STAGE_EX] <= '0;
end
end
Expand Down Expand Up @@ -1064,8 +1067,8 @@ module cv32e40s_rvfi
ex_csr_rdata <= ex_csr_rdata_d;

end else begin
if (in_trap_clr) begin
// Clear interrupt pipeline when it reaches rvfi_intr
if (in_trap_clr || wb_ready_i) begin
// Clear in trap if trap reached rvfi outputs or we insert a bubble into the WB stage
in_trap [STAGE_WB] <= '0;
end
end
Expand Down
6 changes: 4 additions & 2 deletions rtl/cv32e40s_controller_fsm.sv
Expand Up @@ -1434,8 +1434,10 @@ module cv32e40s_controller_fsm import cv32e40s_pkg::*;
woke_to_debug_q <= 1'b0;
woke_to_interrupt_q <= 1'b0;
end else begin
woke_to_debug_q <= (ctrl_fsm_cs == SLEEP) && debug_req_i;
woke_to_interrupt_q <= (ctrl_fsm_cs == SLEEP) && irq_wu_ctrl_i;
// Woke up to debug if no nmi was pending
woke_to_debug_q <= (ctrl_fsm_cs == SLEEP) && debug_req_i && !(pending_nmi);
// Woke up to interrupts if no NMI or debug was pending
woke_to_interrupt_q <= (ctrl_fsm_cs == SLEEP) && irq_wu_ctrl_i && !(pending_nmi || debug_req_i);
end
end

Expand Down
11 changes: 5 additions & 6 deletions sva/cv32e40s_controller_fsm_sva.sv
Expand Up @@ -985,24 +985,24 @@ end
(abort_op_wb_i && (ctrl_fsm_ns == DEBUG_TAKEN)))
else `uvm_error("controller", "Debug not entered on a WPT match")

// Ensure debug mode is entered if woken up by a debug request
// Ensure debug mode is entered if woken up by a debug request (unless a higher priority NMI woke up the core)
a_sleep_to_debug:
assert property (@(posedge clk) disable iff (!rst_n)
(ctrl_fsm_cs == SLEEP) &&
(ctrl_fsm_ns == FUNCTIONAL) &&
debug_req_i &&
!(pending_nmi || irq_wu_ctrl_i || (wfe_in_wb && wu_wfe_i))
!pending_nmi
|=>
(ctrl_fsm_ns == DEBUG_TAKEN))
else `uvm_error("controller", "Woke from sleep due to debug_req but debug mode not entered")

// Ensure interrupt is taken if woken up by an interrupt
// Ensure interrupt is taken if woken up by an interrupt (unless a higher priority NMI or debug request woke up the core)
a_sleep_to_irq:
assert property (@(posedge clk) disable iff (!rst_n)
(ctrl_fsm_cs == SLEEP) &&
(ctrl_fsm_ns == FUNCTIONAL) &&
irq_wu_ctrl_i &&
!(pending_nmi || debug_req_i || (wfe_in_wb && wu_wfe_i)) &&
!(pending_nmi || debug_req_i) &&
mstatus_i.mie
|=>
(ctrl_fsm_o.pc_mux == PC_TRAP_IRQ) || (ctrl_fsm_o.pc_mux == PC_TRAP_CLICV))
Expand All @@ -1013,8 +1013,7 @@ end
assert property (@(posedge clk) disable iff (!rst_n)
(ctrl_fsm_cs == SLEEP) &&
(ctrl_fsm_ns == FUNCTIONAL) &&
pending_nmi &&
!(debug_req_i || irq_wu_ctrl_i || (wfe_in_wb && wu_wfe_i))
pending_nmi
|=>
(ctrl_fsm_o.pc_mux == PC_TRAP_NMI))
else `uvm_error("controller", "Woke from sleep due to NMI but NMI not taken")
Expand Down