Skip to content

Commit

Permalink
Removed todo in clic_int_controller.
Browse files Browse the repository at this point in the history
Added assertion to check that an interrupt request must be raised the cycle after waking up for an interrupt if interrupts are globally enabled.

Signed-off-by: Oystein Knauserud <Oystein.Knauserud@silabs.com>
  • Loading branch information
silabs-oysteink committed Aug 4, 2023
1 parent 860f809 commit 2406ca9
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 5 deletions.
5 changes: 4 additions & 1 deletion rtl/cv32e40x_clic_int_controller.sv
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,10 @@ module cv32e40x_clic_int_controller import cv32e40x_pkg::*;
// and the incoming irq level is above the core's current effective interrupt level. Machine mode interrupts
// during user mode shall always be taken if their level is > 0

// Cannot use flopped comparator results from the irq_wu_ctrl_o logic, as the effective_irq_level
// may change from one cycle to the next due to CSR updates. However, as the irq_wu_ctrl_o is only used
// when the core is in the SLEEP state (where no CSR updates can happen), an assertion exists to check that the cycle after a core wakes up
// due to an interupt the irq_req_ctrl_o must be asserted if global_irq_enable == 1;
assign irq_req_ctrl_o = clic_irq_q && global_irq_enable &&
((priv_lvl_i == PRIV_LVL_M) ? (clic_irq_level_q > effective_irq_level) : (clic_irq_level_q > '0));

Expand All @@ -135,7 +139,6 @@ module cv32e40x_clic_int_controller import cv32e40x_pkg::*;
// - priv mode == current, irq i is max (done in external CLIC), level > max(mintstatus.mil, mintthresh.th)
// - priv mode > current, irq i is max (done in external CLIC), level != 0

// todo: can we share the comparator below and flop the result for irq_req_ctrl_o?
assign irq_wu_ctrl_o = clic_irq_i &&
((priv_lvl_i == PRIV_LVL_M) ? (clic_irq_level_i > effective_irq_level) : (clic_irq_level_i > '0));

Expand Down
24 changes: 21 additions & 3 deletions sva/cv32e40x_clic_int_controller_sva.sv
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ module cv32e40x_clic_int_controller_sva
input logic clic_irq_q,
input logic [7:0] clic_irq_level_q,

input logic global_irq_enable,
input logic irq_wu_ctrl_o,

input logic ctrl_pending_interrupt,
input logic ctrl_interrupt_allowed,
input logic ctrl_pending_nmi,
Expand All @@ -60,7 +63,7 @@ module cv32e40x_clic_int_controller_sva
endproperty;

a_clic_enable: assert property(p_clic_enable)
else `uvm_error("core", "Interrupt not taken soon enough after enabling");
else `uvm_error("clic_int_controller", "Interrupt not taken soon enough after enabling");

// Check that only NMI and external debug take presedence over interrupts after being enabled by mret or CSR writes
property p_irq_pri;
Expand All @@ -76,7 +79,7 @@ module cv32e40x_clic_int_controller_sva
endproperty;

a_irq_pri: assert property(p_irq_pri)
else `uvm_error("core", "Interrupt not taken soon enough after enabling")
else `uvm_error("clic_int_controller", "Interrupt not taken soon enough after enabling")

// Check a pending interrupt that is disabled is actually not taken
property p_clic_disable;
Expand All @@ -88,7 +91,22 @@ module cv32e40x_clic_int_controller_sva
endproperty;

a_clic_disable: assert property(p_clic_disable)
else `uvm_error("core", "Interrupt taken after disabling");
else `uvm_error("clic_int_controller", "Interrupt taken after disabling");

// If an interrupt wakeup is signalled while the core is in the SLEEP state, an interrupt
// request must be asserted in the next cycle if the signal global_irq_enable is set.
property p_req_after_wake;
@(posedge clk) disable iff (!rst_n)
( (ctrl_fsm_cs == SLEEP) && // Core is in sleep state
irq_wu_ctrl_o // Wakeup requested
|=>
(irq_req_ctrl_o) // interrupts must be requested
or
(!irq_req_ctrl_o && !global_irq_enable)); // unless interrupts are not enabled
endproperty;

a_req_after_wake: assert property(p_req_after_wake)
else `uvm_error("clic_int_controller", "No request after wakeup signal");

endmodule

19 changes: 18 additions & 1 deletion sva/cv32e40x_core_sva.sv
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ module cv32e40x_core_sva
input logic irq_ack, // irq ack output
input logic irq_clic_shv, // ack'ed irq is a CLIC SHV
input logic irq_req_ctrl, // Interrupt controller request an interrupt
input logic irq_wu_ctrl,
input ex_wb_pipe_t ex_wb_pipe,
input logic wb_valid,
input logic branch_taken_in_ex,
Expand Down Expand Up @@ -131,7 +132,8 @@ module cv32e40x_core_sva
input logic [1:0] lsu_cnt_q,
input logic [1:0] resp_filter_bus_cnt_q,
input logic [1:0] resp_filter_core_cnt_q,
input write_buffer_state_e write_buffer_state
input write_buffer_state_e write_buffer_state,
input privlvl_t priv_lvl
);

if (CLIC) begin
Expand Down Expand Up @@ -690,6 +692,21 @@ if (!CLIC) begin

a_mip_mie_write_disable: assert property(p_mip_mie_write_disable)
else `uvm_error("core", "Interrupt taken after disabling");

// If an interrupt wakeup is signalled while the core is in the SLEEP state, an interrupt
// request must be asserted in the next cycle if interrupts are globally enabled.
property p_req_after_wake;
@(posedge clk) disable iff (!rst_ni)
( (ctrl_fsm_cs == SLEEP) && // Core is in sleep state
irq_wu_ctrl // Wakeup requested
|=>
(irq_req_ctrl) // interrupt must be requested
or
(!irq_req_ctrl && !(cs_registers_mstatus_q.mie || (priv_lvl < PRIV_LVL_M)))); // unless interrupts are disabled
endproperty;

a_req_after_wake: assert property(p_req_after_wake)
else `uvm_error("core", "No interrupt request after wakeup signal");
end

// Clearing external interrupts via a store instruction causes irq_i to go low the next cycle.
Expand Down

0 comments on commit 2406ca9

Please sign in to comment.