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.
|
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).
|
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.
|
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.
|
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};
|
irq_txn.irq_timer, 3'b0, irq_txn.irq_software, 3'b0};
|
||||||
`uvm_info(`gfn, $sformatf("irq: 0x%0x", irq), UVM_LOW)
|
`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)
|
`uvm_info(`gfn, $sformatf("irq_id: 0x%0x", irq_id), UVM_LOW)
|
||||||
|
|
||||||
return irq_valid;
|
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();
|
if (ret_val) send_irq_stimulus_end();
|
||||||
endtask
|
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;
|
int i;
|
||||||
|
bit have_irq = 1'b0;
|
||||||
// Ibex implementation of MIE does not mask NM interrupts, so need to check this separately
|
// Ibex implementation of MIE does not mask NM interrupts, so need to check this separately
|
||||||
if (irq[irq_agent_pkg::DATA_WIDTH - 1]) begin
|
if (irq[irq_agent_pkg::DATA_WIDTH - 1]) begin
|
||||||
irq_id = irq_agent_pkg::DATA_WIDTH - 1;
|
irq_id = irq_agent_pkg::DATA_WIDTH - 1;
|
||||||
return 1;
|
return 1;
|
||||||
end
|
end
|
||||||
for (i = irq_agent_pkg::DATA_WIDTH - 2; i >= 0; i = i - 1) begin
|
for (i = irq_agent_pkg::DATA_WIDTH - 2; i >= 16; i = i - 1) begin
|
||||||
// Ensure that irq is active and unmasked by the core
|
// 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
|
if (irq[i] == 1'b1 && core_init_mie[i] == 1'b1) begin
|
||||||
irq_id = i;
|
irq_id = i;
|
||||||
return 1;
|
have_irq = 1'b1;
|
||||||
break;
|
|
||||||
end
|
end
|
||||||
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
|
endfunction
|
||||||
|
|
||||||
virtual task check_mcause(bit irq_or_exc, bit[ibex_mem_intf_agent_pkg::DATA_WIDTH-2:0] cause);
|
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 &
|
assign handle_irq = ~debug_mode_q & ~nmi_mode_q &
|
||||||
(irq_nm_i | (irq_pending_i & csr_mstatus_mie_i));
|
(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
|
always_comb begin : gen_mfip_id
|
||||||
if (irqs_i.irq_fast[14]) mfip_id = 4'd14;
|
mfip_id = 4'd0;
|
||||||
else if (irqs_i.irq_fast[13]) mfip_id = 4'd13;
|
|
||||||
else if (irqs_i.irq_fast[12]) mfip_id = 4'd12;
|
for (int i = 14;i >= 0; i--) begin
|
||||||
else if (irqs_i.irq_fast[11]) mfip_id = 4'd11;
|
if (irqs_i.irq_fast[i]) begin
|
||||||
else if (irqs_i.irq_fast[10]) mfip_id = 4'd10;
|
mfip_id = i[3:0];
|
||||||
else if (irqs_i.irq_fast[ 9]) mfip_id = 4'd9;
|
end
|
||||||
else if (irqs_i.irq_fast[ 8]) mfip_id = 4'd8;
|
end
|
||||||
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;
|
|
||||||
end
|
end
|
||||||
|
|
||||||
assign unused_irq_timer = irqs_i.irq_timer;
|
assign unused_irq_timer = irqs_i.irq_timer;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue