Autonomous-mode rung. Splits the address-map work for S-mode support away from the actual S-mode behavior. P47 is “the nine S-mode CSR addresses are decoded and round-trip cleanly”; the priv transition itself comes later.
What landed
Nine CSRs added to src/top.sv as M-mode-readable storage:
| addr | name | future role |
|---|---|---|
| 0x100 | sstatus | S-mode status |
| 0x104 | sie | S interrupt enables |
| 0x105 | stvec | S trap vector |
| 0x140 | sscratch | scratch |
| 0x141 | sepc | S exception PC |
| 0x142 | scause | S trap cause |
| 0x143 | stval | S trap value |
| 0x144 | sip | S interrupt pending |
| 0x180 | satp | translation + protection |
Each CSR got a localparam, a 32-bit storage register, an entry
in csr_known/csr_writable/csr_read()/the reset block, and
a write case in S_EXECUTE. Roughly 40 lines of additive RTL.
Probe writes 0xC0DE000X to each (X=1..9), reads back, and a
final cross-check re-reads sstatus to confirm the eight
intervening writes didn’t smear. Error codes 80-89.
PASS at 5,101,601 clocks; FreeRTOS demo continues to halt cleanly afterwards.
Why split the rungs
S-mode is a fairly large architectural addition: priv tracking, mret-to-the-right-priv, real S-mode trap entry, satp-driven paging. Doing all of that in one rung is a big change with many failure modes and a lot of ways to regress the existing M-mode behavior.
Splitting “addresses decode and store” out as its own rung means the next rung can be entirely about behavior. The chip continues to run M-mode-only after P47 (no software change required), so this is a low-risk staging step.
Wart count
Zero new ones. P46’s gcc-zbb-auto-emit hang is still unresolved (march held at zba). Otherwise everything pre-P47 still works.