|
3 | 3 | This is WIP, for now just a scratchpad with notes. |
4 | 4 |
|
5 | 5 | Goals: |
| 6 | +====== |
6 | 7 |
|
7 | 8 | - create a step-by-step gentle introduction, morphing the processor |
8 | 9 | obtained at the end of Episode I into something that can run FreeRTOS |
@@ -66,6 +67,7 @@ could be something like (first draft): |
66 | 67 | particular about simulation / verilator etc...) |
67 | 68 |
|
68 | 69 | List of questions: |
| 70 | +================== |
69 | 71 |
|
70 | 72 | - what is the minimal list of CSRs and instructions needed to run FreeRTOS ? First guess: |
71 | 73 | - mepc: saved PC |
@@ -106,10 +108,88 @@ List of questions: |
106 | 108 | - [(A)CLINT](https://github.com/riscv/riscv-aclint/blob/main/riscv-aclint.adoc) |
107 | 109 | - [CLIC](https://github.com/riscv/riscv-fast-interrupt/blob/master/clic.adoc) |
108 | 110 |
|
109 | | -Links: |
| 111 | +Interrupts, Exception, Traps |
| 112 | +============================ |
| 113 | + |
| 114 | +Definitions |
| 115 | +----------- |
| 116 | + |
| 117 | +- Exception: unusual condition of run-time associated with an instruction |
| 118 | +- Trap: synchronous transfer to a trap handler caused by exceptional condition |
| 119 | +- Interrupt: external event that occurs asynchronously |
| 120 | +(if I understand well, a trap is what you return from using Xret. An exception is |
| 121 | + what triggers a trap from the current instruction, and an interrupt is what triggers |
| 122 | + a trap asynchronously, from the timer, or from a special wire). |
| 123 | + |
| 124 | + |
| 125 | +Interrupts in existing FemtoRV cores |
| 126 | +------------------------------------ |
| 127 | + |
| 128 | +Matthias has developed three FemtoRVs with interrupt support: |
| 129 | +- intermissum (RV32-IM) |
| 130 | +- gracilis (RV32-IMC) |
| 131 | +- individua (RV32-IMAC) |
| 132 | + |
| 133 | +The interrupt logic is common to the three of them. They |
| 134 | +have an additional wire `interrupt_request` that triggers an interrupt |
| 135 | + |
| 136 | +They implement the following CSRs: |
| 137 | +- `mepc`: saved program counter |
| 138 | +- `mtvec`: address of the interrupt handler |
| 139 | +- `mstatus` bit x: interrupt enable |
| 140 | +- `mcause` bit x: interrupt cause (and lock: already in interrupt handler) |
| 141 | +- there is also an `interrupt_request_sticky` flipflop |
| 142 | + |
| 143 | +Besides writing/reading the new CSRs (easy), we need to make three modifications in |
| 144 | +our core: |
| 145 | +- 1 how the `interrupt_request` discusses with the rest of the chip |
| 146 | +- 2 how (and when) do we jump to a trap handler |
| 147 | +- 3 how do we return from a trap handler (that is, what `mret` does) |
| 148 | + |
| 149 | +**1: how `interrupt_request` discusses with `interrupt_sticky`:** |
| 150 | + |
| 151 | +`interrupt_request` only talks to `interrupt_sticky`, and the rest of the chip only sees `interrupt_sticky`. |
| 152 | +- if `interrupt_request` goes high, `interrupt_sticky` goes high |
| 153 | +- if `interrupt_sticky` is high, it stays high until the interrupt has been processed (that is, until we go through |
| 154 | + the `execute` state that does what should be done with the interrupt). |
110 | 155 |
|
| 156 | +**2: how (and when) do we jump to a trap handler ?** |
| 157 | + |
| 158 | +we just need to do three things: |
| 159 | +- jump to the trap handler, that is, set `PC` to `mtvec` |
| 160 | +- save return address, that is, set `mepc` to `PC+4` (or `PC+2` if it is a RV32C instruction) |
| 161 | +- indicate that we are in a trap handler, by setting bit 31 of `mcause` (indicates that we are in an interrupt) |
| 162 | + |
| 163 | +It is done in the `EXECUTE` stage under three conditions: |
| 164 | +- there is an interrupt pending (`interrupt_request_sticky` is asserted) and |
| 165 | +- interrupts are enabled (`MIE`, that is `mstatus`[3] is set) and |
| 166 | +- we are not in an interrupt handler already (`mcause`[31]) is not asserted |
| 167 | + |
| 168 | +**3: how do we return from a trap handler ?** |
| 169 | +- reset `mcause[31]` to 0 |
| 170 | +- jump to the return address in `mepc` |
| 171 | + |
| 172 | +It is done in the `EXECUTE` state. `mepc` is selected by the `PC_next` mux when the current instruction is `mret` |
| 173 | + |
| 174 | +**Another view of what happens when an interrupt is triggered** |
| 175 | +- 1 `interrupt_request` is asserted by the external interrupt source |
| 176 | +- 2 `interrupt_sticky` goes high (and remains high until we are in `EXECUTE` |
| 177 | +- 3 `EXECUTE` sets `mcause[31]`, saves the return address to `mepc` and jumps to the trap handler. |
| 178 | + `interrupt_sticky` goes low |
| 179 | +- 4 the instructions in the trap handler are executed until current instruction is `mret` |
| 180 | +- 5 `EXECUTE` processes `mret` (resets `mcause[31]` and jumps to `mepc`) |
| 181 | + |
| 182 | +Question: in the Risc-V norm, `mstatus` has a `mip` bit (machine interrupt pending). Is it |
| 183 | +different or is it the same thing as our `interrupt_sticky` ? |
| 184 | + |
| 185 | +Links: |
| 186 | +====== |
111 | 187 | - @cnlohr's [minirv32](https://github.com/cnlohr/mini-rv32ima) |
112 | 188 |
|
113 | | -- Linux-capable @ultraembedded's [exact-step](https://github.com/ultraembedded/exactstep/blob/master/cpu-rv32/rv32.cpp) |
| 189 | +- Linux-capable @ultraembedded's simulator [exact-step](https://github.com/ultraembedded/exactstep/blob/master/cpu-rv32/rv32.cpp) |
114 | 190 |
|
115 | 191 | - @regymm [quasi-soc](https://github.com/regymm/quasiSoC) |
| 192 | + |
| 193 | +- @MrBossman [kisc-v](https://github.com/Mr-Bossman/KISC-V) |
| 194 | + |
| 195 | +- @splinedrive [Kian risc-V](https://github.com/splinedrive/kianRiscV) |
0 commit comments