Update documentation of interrupt framework

This commit is contained in:
Pirmin Vogel 2019-07-17 14:34:03 +01:00
parent be975eaa9d
commit 09aad340b1
5 changed files with 100 additions and 75 deletions

View file

@ -12,6 +12,8 @@ Ibex implements all the Control and Status Registers (CSRs) listed in the follow
+---------+--------------------+--------+-----------------------------------------------+
| 0x301 | ``misa`` | WARL | Machine ISA and Extensions |
+---------+--------------------+--------+-----------------------------------------------+
| 0x304 | ``mie`` | WARL | Machine Interrupt Enable Register |
+---------+--------------------+--------+-----------------------------------------------+
| 0x305 | ``mtvec`` | WARL | Machine Trap-Vector Base Address |
+---------+--------------------+--------+-----------------------------------------------+
| 0x320 | ``mcountinhibit`` | RW | Machine Counter-Inhibit Register |
@ -20,7 +22,7 @@ Ibex implements all the Control and Status Registers (CSRs) listed in the follow
+---------+--------------------+--------+-----------------------------------------------+
| . . . . |
+---------+--------------------+--------+-----------------------------------------------+
| 0x33F | ``mhpmevent31`` | WARL | Machine performance-monitoring event selector |
| 0x33F | ``mhpmevent31`` | WARL | Machine Performance-Monitoring Event Selector |
+---------+--------------------+--------+-----------------------------------------------+
| 0x340 | ``mscratch`` | RW | Machine Scratch Register |
+---------+--------------------+--------+-----------------------------------------------+
@ -30,6 +32,8 @@ Ibex implements all the Control and Status Registers (CSRs) listed in the follow
+---------+--------------------+--------+-----------------------------------------------+
| 0x343 | ``mtval`` | WARL | Machine Trap Value Register |
+---------+--------------------+--------+-----------------------------------------------+
| 0x344 | ``mip`` | R | Machine Interrupt Pending Register |
+---------+--------------------+--------+-----------------------------------------------+
| 0x7B0 | ``dcsr`` | RW | Debug Control and Status Register |
+---------+--------------------+--------+-----------------------------------------------+
| 0x7B1 | ``dpc`` | RW | Debug PC |
@ -96,6 +100,30 @@ CSR Address: ``0x301``
On Ibex, ``misa`` is hard-wired, i.e. it will remain unchanged after any write.
Machine Interrupt Enable Register (mie)
---------------------------------------
CSR Address: ``0x304``
Reset Value: ``0x0000_0000``
``mie`` is a WARL register which allows to individually enable/disable local interrupts.
After reset, all interrupts are disabled.
+-------+--------------------------------------------------------------------------------------+
| Bit# | Interrupt |
+-------+--------------------------------------------------------------------------------------+
| 30:16 | Machine Fast Interrupt Enables: Set bit x+16 to enable |
| | fast interrupt ``irq_fast_i[x]``. |
+-------+--------------------------------------------------------------------------------------+
| 11 | **Machine External Interrupt Enable (MEIE):** If set, ``irq_external_i`` is enabled. |
+-------+--------------------------------------------------------------------------------------+
| 7 | **Machine Timer Interrupt Enable (MTIE):** If set, ``irq_timer_i`` is enabled. |
+-------+--------------------------------------------------------------------------------------+
| 3 | **Machine Software Interrupt Enable (MSIE):** if set, ``irq_software_i`` is enabled. |
+-------+--------------------------------------------------------------------------------------+
Machine Trap-Vector Base Address (mtvec)
----------------------------------------
@ -153,6 +181,30 @@ When an exception is encountered, this register can hold exception-specific info
For all other exceptions, ``mtval`` is 0.
Machine Interrupt Pending Register (mip)
----------------------------------------
CSR Address: ``0x344``
Reset Value: ``0x0000_0000``
``mip`` is a read-only register indicating pending interrupt requests.
A particular bit in the register reads as one if the corresponding interrupt input signal is high and if the interrupt is enabled in the ``mie`` CSR.
+-------+---------------------------------------------------------------------------------------+
| Bit# | Interrupt |
+-------+---------------------------------------------------------------------------------------+
| 30:16 | Machine Fast Interrupts Pending: If bit x+16 is set, |
| | fast interrupt ``irq_fast_i[x]`` is pending. |
+-------+---------------------------------------------------------------------------------------+
| 11 | **Machine External Interrupt Pending (MEIP):** If set, ``irq_external_i`` is pending. |
+-------+---------------------------------------------------------------------------------------+
| 7 | **Machine Timer Interrupt Pending (MTIP):** If set, ``irq_timer_i`` is pending. |
+-------+---------------------------------------------------------------------------------------+
| 3 | **Machine Software Interrupt Pending (MSIP):** if set, ``irq_software_i`` is pending. |
+-------+---------------------------------------------------------------------------------------+
.. _csr-mhartid:
Hardware Thread ID (mhartid)

View file

@ -6,7 +6,7 @@ Exceptions and Interrupts
Ibex implements trap handling for interrupts and exceptions according to the RISC-V Privileged Specification, version 1.11.
All exceptions cause the core to jump to the base address of the vector table in the ``mtvec`` CSR.
Interrupts are handled in vectored mode, i.e., the core jumps to the base address plus four times the interrupt cause number.
Interrupts are handled in vectored mode, i.e., the core jumps to the base address plus four times the interrupt ID.
The base address of the vector table is given by the boot address (must be aligned to 256 bytes, i.e., its least significant byte must be 0x00).
The most significant 3 bytes of the boot address given to the core are used for the first instruction fetch of the core and as the basis of the interrupt vector table.
@ -18,12 +18,47 @@ It is assumed that the boot address is supplied via a register to avoid long pat
Interrupts
----------
Interrupts can only be enabled/disabled on a global basis and not individually.
The global interrupt enable is done via the ``mstatus`` CSR.
Ibex supports the following interrupts.
It is assumed that there is a separate event/interrupt controller outside of the core that performs masking and buffering of multiple interrupt requests.
When an interrupt is taken, the core gives an acknowledge signal to the external event/interrupt controller as well as the interrupt ID taken.
Check :ref:`interrupts` for more details.
+-------------------------+-------+--------------------------------------------------+
| Interrupt Input Signal | ID | Description |
+=========================+=======+==================================================+
| ``irq_nm_i`` | 31 | Non-maskable interrupt (NMI) |
+-------------------------+-------+--------------------------------------------------+
| ``irq_fast_i[14:0]`` | 30:16 | 15 fast, local interrupts |
+-------------------------+-------+--------------------------------------------------+
| ``irq_external_i`` | 11 | Connected to platform-level interrupt controller |
+-------------------------+-------+--------------------------------------------------+
| ``irq_timer_i`` | 7 | Connected to timer module |
+-------------------------+-------+--------------------------------------------------+
| ``irq_software_i`` | 3 | Connected to memory-mapped (inter-processor) |
| | | interrupt register |
+-------------------------+-------+--------------------------------------------------+
All interrupts except for the non-maskable interrupt (NMI) are controlled via the ``mstatus``, ``mie`` and ``mip`` CSRs.
After reset, all interrupts are disabled.
To enable interrupts, both the global interrupt enable (MIE) bit in the ``mstatus`` CSR and the corresponding individual interrupt enable bit in the ``mie`` CSR need to be set.
For more information, see the :ref:`cs-registers` documentation.
If multiple interrupts are pending, the highest priority is given to the interrupt with the highest 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.
All interrupt lines are level-sensitive.
It is assumed that the interrupt handler signals completion of the handling routine to the interrupt source, e.g., through a memory-mapped register, which then deasserts the corresponding interrupt line.
In debug mode, all interrupts including the NMI are ignored independent of ``mstatus``.MIE and the content of the ``mie`` CSR.
Recoverable Non-Maskable Interrupt
----------------------------------
To support recovering from an NMI happening during a trap handling routine, Ibex features additional CSRs for backing up ``mstatus``.MPP, ``mstatus``.MPIE, ``mepc`` and ``mcause``.
These CSRs are not accessible by software running on the core.
These CSRs are nonstandard.
For more information, see `the corresponding proposal <https://github.com/riscv/riscv-isa-manual/issues/261>`_.
Exceptions

View file

@ -14,7 +14,6 @@ Ibex User Manual
cs_registers
performance_counters
exception_interrupts
interrupts
debug
tracer
rvfi

View file

@ -48,10 +48,11 @@ Instantiation Template
.data_err_i (),
// Interrupt inputs
.irq_i (),
.irq_id_i (),
.irq_ack_o (),
.irq_id_o (),
.irq_software_i (),
.irq_timer_i (),
.irq_external_i (),
.irq_fast_i (),
.irq_nm_i (),
// Debug interface
.debug_req_i (),
@ -103,7 +104,7 @@ Interfaces
+-------------------------+------------------------------------------------------------------------+
| ``data_*`` | Load-store unit interface, see :ref:`load-store-unit` |
+-------------------------+------------------------------------------------------------------------+
| ``irq_*`` | Interrupt interface, see :ref:`interrupts` |
| ``irq_*`` | Interrupt inputs, see :ref:`exceptions-interrupts` |
+-------------------------+------------------------------------------------------------------------+
| ``debug_*`` | Debug interface, see :ref:`debug-support` |
+-------------------------+-------------------------+-----+----------------------------------------+

View file

@ -1,62 +0,0 @@
.. _interrupts:
Interrupts
==========
Ibex requires a separate event/interrupt controller outside of the core that performs masking and buffering of multiple interrupt requests.
Communication with this event/interrupt controller is established through the following external core interface:
+-------------------------+-----------+-----------------------------------------------+
| Signal | Direction | Description |
+=========================+===========+===============================================+
| ``irq_i`` | in | Interrupt event, level sensitive |
+-------------------------+-----------+-----------------------------------------------+
| ``irq_id_i[4:0]`` | in | Interrupt ID |
+-------------------------+-----------+-----------------------------------------------+
| ``irq_ack_o`` | out | Interrupt acknowledgment |
+-------------------------+-----------+-----------------------------------------------+
| ``irq_id_o[4:0]`` | out | Interrupt acknowledgment ID |
+-------------------------+-----------+-----------------------------------------------+
When external interrupts are enabled, the core will serve interrupt requests.
An interrupt request is signaled with ``irq_i`` being high.
The interrupt ID is signaled by ``irq_id_i`` and determines the address offset in the interrupt vector table of the core (see :ref:`exceptions-interrupts`).
Once the interrupt processing is completed, the core asserts ``irq_ack_o`` for one clock cycle and signals the identifier that has been completed in ``irq_id_o``.
.. important::
The core may not start interrupt processing in the same cycle the level changes.
:numref:`irq-processing` shows the signal timing during a standard interrupt cycle.
.. wavedrom::
:name: irq-processing
:caption: Interrupt processing
{ "signal": [
{ "name": "clk_i", "wave": "p...", "period": 2 },
{ "name": "irq_i", "wave": "01..|.0." },
{ "name": "irq_id_i", "wave": "x=..|.x.", "data": ["ID0"] },
{ "name": "irq_ack_o", "wave": "0...|10." },
{ "name": "irq_id_id", "wave": "x...|=x.", "data": ["ID0"] }
]
}
As the interrupt identifier is registered once it is handled, it is allowed that the interrupt identifier at the input changes.
This behavior can be used to handle interrupt priorities.
But as the core may already have started interrupt processing, it is necessary to check the acknowledged ID.
An example cycle is shown in :numref:`irq-processing-prio`.
.. wavedrom::
:name: irq-processing-prio
:caption: Interrupt processing with prioritization. The processing of ``ID0`` has already started.
{ "signal": [
{ "name": "clk_i", "wave": "p...", "period": 2 },
{ "name": "irq_i", "wave": "01..|.1." },
{ "name": "irq_id_i", "wave": "x=.=|...", "data": ["ID0", "ID1"] },
{ "name": "irq_ack_o", "wave": "0...|10." },
{ "name": "irq_id_id", "wave": "x...|=x.", "data": ["ID0"] }
]
}