mirror of
https://github.com/openhwgroup/cve2.git
synced 2025-04-24 22:17:39 -04:00
[rtl,dv,doc] Flip priority of fast interrupts
This matches the priority used in Spike. This also fixes an issue in the DV where the priority of external/software/timer interrupts wasn't calculated correctly.
This commit is contained in:
parent
ff6797b26f
commit
f4e3eefcfb
3 changed files with 38 additions and 24 deletions
|
@ -50,7 +50,8 @@ To enable interrupts, both the global interrupt enable (MIE) bit in the ``mstatu
|
|||
For more information, see the :ref:`cs-registers` documentation.
|
||||
|
||||
If multiple interrupts are pending, they are handled in the priority order defined by the RISC-V Privileged Specification, version 1.11 (see Machine Interrupt Registers, Section 3.1.9).
|
||||
The highest priority is given to the interrupt with the highest ID, except for timer interrupts, which have the lowest priority.
|
||||
The fast interrupts have a platform defined priority.
|
||||
In Ibex they take priority over all other interrupts and between fast interrupts the highest priority is given to the interrupt with the lowest ID.
|
||||
|
||||
The NMI is enabled independent of the values in the ``mstatus`` and ``mie`` CSRs, and it is not visible through the ``mip`` CSR.
|
||||
It has interrupt ID 31, i.e., it has the highest priority of all interrupts and the core jumps to the trap-handler base address (in ``mtvec``) plus 0x7C to handle the NMI.
|
||||
|
|
|
@ -202,7 +202,7 @@ class core_ibex_debug_intr_basic_test extends core_ibex_base_test;
|
|||
irq_txn.irq_timer, 3'b0, irq_txn.irq_software, 3'b0};
|
||||
`uvm_info(`gfn, $sformatf("irq: 0x%0x", irq), UVM_LOW)
|
||||
|
||||
irq_valid = get_max_valid_irq_id(irq);
|
||||
irq_valid = get_valid_irq_id(irq);
|
||||
`uvm_info(`gfn, $sformatf("irq_id: 0x%0x", irq_id), UVM_LOW)
|
||||
|
||||
return irq_valid;
|
||||
|
@ -305,22 +305,43 @@ class core_ibex_debug_intr_basic_test extends core_ibex_base_test;
|
|||
if (ret_val) send_irq_stimulus_end();
|
||||
endtask
|
||||
|
||||
function int get_max_valid_irq_id(bit [irq_agent_pkg::DATA_WIDTH-1:0] irq);
|
||||
function int get_valid_irq_id(bit [irq_agent_pkg::DATA_WIDTH-1:0] irq);
|
||||
int i;
|
||||
bit have_irq = 1'b0;
|
||||
// Ibex implementation of MIE does not mask NM interrupts, so need to check this separately
|
||||
if (irq[irq_agent_pkg::DATA_WIDTH - 1]) begin
|
||||
irq_id = irq_agent_pkg::DATA_WIDTH - 1;
|
||||
return 1;
|
||||
end
|
||||
for (i = irq_agent_pkg::DATA_WIDTH - 2; i >= 0; i = i - 1) begin
|
||||
// Ensure that irq is active and unmasked by the core
|
||||
for (i = irq_agent_pkg::DATA_WIDTH - 2; i >= 16; i = i - 1) begin
|
||||
// Fast interrupts (IDs 30-16) are prioritised with the lowest ID first, but any fast
|
||||
// interrupt has priority over other interrupts.
|
||||
if (irq[i] == 1'b1 && core_init_mie[i] == 1'b1) begin
|
||||
irq_id = i;
|
||||
return 1;
|
||||
break;
|
||||
have_irq = 1'b1;
|
||||
end
|
||||
end
|
||||
return 0;
|
||||
|
||||
if (!have_irq) begin
|
||||
// If there was no enabled fast interrupt, check the other interrupts
|
||||
if (irq[11] && core_init_mie[11]) begin
|
||||
// External interrupt
|
||||
irq_id = 11;
|
||||
have_irq = 1'b1;
|
||||
end else if (irq[3] && core_init_mie[3]) begin
|
||||
// Software interrupt
|
||||
irq_id = 3;
|
||||
have_irq = 1'b1;
|
||||
end else if (irq[7] && core_init_mie[7]) begin
|
||||
// Timer interrupt
|
||||
irq_id = 7;
|
||||
have_irq = 1'b1;
|
||||
end
|
||||
|
||||
// Other interrupt IDs aren't implemented in Ibex
|
||||
end
|
||||
|
||||
return have_irq;
|
||||
endfunction
|
||||
|
||||
virtual task check_mcause(bit irq_or_exc, bit[ibex_mem_intf_agent_pkg::DATA_WIDTH-2:0] cause);
|
||||
|
|
|
@ -349,23 +349,15 @@ module ibex_controller #(
|
|||
assign handle_irq = ~debug_mode_q & ~nmi_mode_q &
|
||||
(irq_nm_i | (irq_pending_i & csr_mstatus_mie_i));
|
||||
|
||||
// generate ID of fast interrupts, highest priority to highest ID
|
||||
// generate ID of fast interrupts, highest priority to lowest ID
|
||||
always_comb begin : gen_mfip_id
|
||||
if (irqs_i.irq_fast[14]) mfip_id = 4'd14;
|
||||
else if (irqs_i.irq_fast[13]) mfip_id = 4'd13;
|
||||
else if (irqs_i.irq_fast[12]) mfip_id = 4'd12;
|
||||
else if (irqs_i.irq_fast[11]) mfip_id = 4'd11;
|
||||
else if (irqs_i.irq_fast[10]) mfip_id = 4'd10;
|
||||
else if (irqs_i.irq_fast[ 9]) mfip_id = 4'd9;
|
||||
else if (irqs_i.irq_fast[ 8]) mfip_id = 4'd8;
|
||||
else if (irqs_i.irq_fast[ 7]) mfip_id = 4'd7;
|
||||
else if (irqs_i.irq_fast[ 6]) mfip_id = 4'd6;
|
||||
else if (irqs_i.irq_fast[ 5]) mfip_id = 4'd5;
|
||||
else if (irqs_i.irq_fast[ 4]) mfip_id = 4'd4;
|
||||
else if (irqs_i.irq_fast[ 3]) mfip_id = 4'd3;
|
||||
else if (irqs_i.irq_fast[ 2]) mfip_id = 4'd2;
|
||||
else if (irqs_i.irq_fast[ 1]) mfip_id = 4'd1;
|
||||
else mfip_id = 4'd0;
|
||||
mfip_id = 4'd0;
|
||||
|
||||
for (int i = 14;i >= 0; i--) begin
|
||||
if (irqs_i.irq_fast[i]) begin
|
||||
mfip_id = i[3:0];
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
assign unused_irq_timer = irqs_i.irq_timer;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue