No. 30 / project of 147 on the ladder

RV32I tiny runtime

introduces — Linker script, startup assembly, trap handler, and compiled UART-loaded runtime image

harden statelast run2026-05-01

P30 keeps the P29 MMIO platform, but changes how we feed it software. The directed program is now compiled and linked with the RISC-V toolchain, converted to a byte image, loaded over the UART loader, and executed from external RAM.

Status: RTL pass. The compiled tiny runtime test passes, and the scoped ACT4/Sail rv32i/I batch still passes with PASS=39 FAIL=0 NOT RUN=0. Hardening and official privileged tests are NOT RUN for this rung.

The Result

Run it:

make -C projects/30_rv32i_tiny_runtime/test

Result: PASS

checkresult
Build linked runtime ELFPASS
UART-load compiled imagePASS
Clear .bss from startup codePASS
External RAM read/writePASS
MMIO UART writes R, T, EPASS
MMIO timer interrupt and mretPASS
External interrupt and mretPASS
Halt with x5 = 1PASS

ACT4/Sail rv32i/I: PASS=39 FAIL=0 NOT RUN=0

Harden status: NOT RUN

Runtime Shape

piecebehavior
runtime/link.ldplaces code/data/BSS in low external RAM
runtime/start.Sreset entry, .bss clear, MMIO checks, trap handler
runtime/build/tiny_runtime.elfgenerated linked ELF
runtime/build/tiny_runtime.memhgenerated byte image for the UART loader

The runtime is assembly-only and targets rv32i_zicsr: base integer plus CSR instructions. That is the honest minimum for a machine-mode trap handler.

What Changed

Before P30, directed RISC-V programs were mostly instruction words emitted by SystemVerilog helpers. That was useful for focused core work, but it is the wrong shape for runtime software.

P30 adds:

  • a linker script with real symbols like __stack_top, __bss_start, and __bss_end;
  • a reset entry that sets sp and clears .bss;
  • a direct-mode mtvec handler;
  • a compiled program that uses the P29 MMIO map;
  • Makefile targets that generate ELF, binary, memh, and disassembly artifacts.

Generated runtime outputs are ignored. The source of truth is the assembly, linker script, and Makefile.

What This Proves

The compiled runtime:

  1. boots from address zero after the UART loader releases the CPU;
  2. proves external RAM;
  3. writes R to the MMIO UART;
  4. programs the MMIO timer;
  5. takes a machine timer interrupt and returns through mret;
  6. writes T, receives a testbench external IRQ, handles it, and writes E;
  7. sets x5 = 1 and halts.

The scoped ACT4/Sail run still matters because the P30 RTL shell is the P29 platform with a new project wrapper and build flow. The base integer batch still passes: PASS=39 FAIL=0 NOT RUN=0.

Scope

Still unsupported: a C runtime, ABI-heavy function calls, supervisor mode, vectored mtvec, delegation CSRs, satp, an MMU, and official privileged architecture tests.

So the honest label is narrow: PASS for the compiled tiny-runtime RTL test, PASS for scoped ACT4/Sail rv32i/I, NOT RUN for hardening, and NOT RUN for privileged compliance.