Add BIOS and tiny kernel roadmap phases
This commit is contained in:
@@ -29,8 +29,8 @@ See ROADMAP.md for the full phased plan.
|
||||
- Firmware source: `fw/` directory. Built with `riscv64-unknown-elf-gcc`
|
||||
(multilib build required). March string evolves with the implemented ISA:
|
||||
- Phase 8 (pre-CSR bare-metal): `-march=rv32im -mabi=ilp32`
|
||||
- Phase 9+ (CSRs/Zifencei decoded): `-march=rv32im_zicsr_zifencei -mabi=ilp32`
|
||||
- Phase 12+ (atomics): `-march=rv32ima_zicsr_zifencei -mabi=ilp32`
|
||||
- Phase 12+ (CSRs/Zifencei decoded): `-march=rv32im_zicsr_zifencei -mabi=ilp32`
|
||||
- Phase 15+ (atomics): `-march=rv32ima_zicsr_zifencei -mabi=ilp32`
|
||||
Don't advertise an extension before its ops are decoded — the compiler is
|
||||
free to emit them, and "trap as illegal" early is much better than NOPing.
|
||||
|
||||
@@ -55,14 +55,14 @@ End target: **RV32IMA + Zicsr + Zifencei + M/S/U privilege + Sv32** (Linux-capab
|
||||
|
||||
Extensions land incrementally:
|
||||
- RV32IM base — Phases 1-8
|
||||
- Zicsr (CSR instructions) + M-mode trap handling — Phase 9
|
||||
- Zifencei (`fence.i`) — decoded but NOP until caches exist (Phase 14+)
|
||||
- A (atomics: LR/SC + AMO) — Phase 12 (required for mainline Linux)
|
||||
- S-mode + U-mode + Sv32 — Phase 15
|
||||
- Zicsr (CSR instructions) + M-mode trap handling — Phase 12
|
||||
- Zifencei (`fence.i`) — decoded but NOP until caches exist (Phase 17+)
|
||||
- A (atomics: LR/SC + AMO) — Phase 15 (required for mainline Linux)
|
||||
- S-mode + U-mode + Sv32 — Phase 18
|
||||
|
||||
## Key Design Decisions
|
||||
|
||||
- Single-cycle first, pipeline later (Phase 13, optional). Stages are separated
|
||||
- Single-cycle first, pipeline later (Phase 16, optional). Stages are separated
|
||||
in the code even without pipeline registers between them.
|
||||
- "Single-cycle" is a logical model, not a literal one cycle per instruction.
|
||||
BRAM has a 1-cycle read latency, so fetch is registered and loads take 2
|
||||
@@ -82,10 +82,10 @@ Extensions land incrementally:
|
||||
```
|
||||
0x0000_0000 – 0x0FFF_FFFF reserved boot aperture (256 MB decode region)
|
||||
actual SPI flash device is 16 MB (Arty A7),
|
||||
mapped at 0x0000_0000–0x00FF_FFFF in Phase 14
|
||||
mapped at 0x0000_0000–0x00FF_FFFF in Phase 17
|
||||
0x1000_0000 – 0x1000_0FFF MMIO (UART; later: timer, PLIC)
|
||||
0x2000_0000 – 0x2000_FFFF instruction BRAM (64 KB)
|
||||
0x8000_0000 – 0x8000_FFFF data BRAM (64 KB) → grows to DRAM 0x8000_0000–0x8FFF_FFFF in Phase 14
|
||||
0x8000_0000 – 0x8000_FFFF data BRAM (64 KB) → grows to DRAM 0x8000_0000–0x8FFF_FFFF in Phase 17
|
||||
```
|
||||
|
||||
Reset PC = `0x2000_0000`. Linker script anchors text/rodata at `0x2000_0000`
|
||||
@@ -99,7 +99,7 @@ UART register layout (split, not 16550-style):
|
||||
```
|
||||
|
||||
This is fine for bare-metal firmware but is *not* directly Linux-compatible:
|
||||
the in-tree `8250/16550` driver expects a different register layout. Phase 16
|
||||
the in-tree `8250/16550` driver expects a different register layout. Phase 19
|
||||
(Linux Boot Contract) revisits this — either add a 16550-compatible wrapper
|
||||
or write a custom Linux serial driver + device-tree binding.
|
||||
|
||||
@@ -123,7 +123,7 @@ typedef struct packed {
|
||||
logic [1:0] size; // 00=byte, 01=halfword, 10=word
|
||||
logic [31:0] wdata; // lane-aligned per wstrb
|
||||
logic [3:0] wstrb; // byte enables (writes only)
|
||||
logic [3:0] amo; // AMO op encoding (D-bus only, Phase 12+)
|
||||
logic [3:0] amo; // AMO op encoding (D-bus only, Phase 15+)
|
||||
} mem_req_t;
|
||||
|
||||
// Payload — slave → master
|
||||
@@ -153,7 +153,7 @@ Handshake notes:
|
||||
producing a response (BRAM = 1 cycle, DRAM = many).
|
||||
- `wstrb` is mandatory from Phase 6.2 onward (sub-word stores). For
|
||||
Phase 6.1 (word-only), tie strobes to `4'b1111` on stores.
|
||||
- `amo` is unused (drive `4'h0`) until Phase 12; on the I-bus it is always
|
||||
- `amo` is unused (drive `4'h0`) until Phase 15; on the I-bus it is always
|
||||
unused.
|
||||
- `err` is **only** raised by a slave to report access faults it owns:
|
||||
unmapped address, peripheral-access violation, eventually DRAM ECC fault.
|
||||
@@ -173,8 +173,8 @@ separately. Per-phase progression:
|
||||
| 4 | CPU fetch ↔ instruction BRAM | (none yet) |
|
||||
| 6 | unchanged | LSU ↔ data BRAM (single slave) |
|
||||
| 7 | unchanged | LSU ↔ decoder → {data BRAM, UART MMIO} |
|
||||
| 9-12 | unchanged | + timer (Phase 10), PLIC (Phase 11) |
|
||||
| 14 | I-bus → arbiter → DRAM | D-bus → arbiter → DRAM (or MIG dual-port) |
|
||||
| 12-15 | unchanged | + timer (Phase 13), PLIC (Phase 14) |
|
||||
| 17 | I-bus → arbiter → DRAM | D-bus → arbiter → DRAM (or MIG dual-port) |
|
||||
|
||||
Both buses can fault independently; classification happens in the masters
|
||||
(see below).
|
||||
@@ -195,17 +195,17 @@ transaction adds context to produce the precise architectural cause:
|
||||
| Store/AMO address misaligned | 6 | LSU (size + addr LSBs, pre-issue) |
|
||||
| Store/AMO access fault | 7 | LSU (D-bus `rsp.err` on write) |
|
||||
| Ecall from M-mode | 11 | decoder |
|
||||
| Instruction page fault | 12 | I-side MMU (Phase 15) |
|
||||
| Load page fault | 13 | D-side MMU (Phase 15) |
|
||||
| Store/AMO page fault | 15 | D-side MMU (Phase 15) |
|
||||
| Instruction page fault | 12 | I-side MMU (Phase 18) |
|
||||
| Load page fault | 13 | D-side MMU (Phase 18) |
|
||||
| Store/AMO page fault | 15 | D-side MMU (Phase 18) |
|
||||
|
||||
Two consequences:
|
||||
- The LSU detects misalignment **before** issuing a bus request — never
|
||||
send a request you already know will trap.
|
||||
- Page faults (Phase 15) are raised by the MMU during translation,
|
||||
- Page faults (Phase 18) are raised by the MMU during translation,
|
||||
before the (translated) request hits the bus.
|
||||
|
||||
### Atomics (Phase 12)
|
||||
### Atomics (Phase 15)
|
||||
|
||||
LR/SC and AMO use the `amo` field of `mem_req_t` (D-bus only) rather than
|
||||
a separate bus. Single-hart reservation tracking lives in the LSU.
|
||||
|
||||
Reference in New Issue
Block a user