We wanted one official acceptance test to pass, not another local “looks RISC-V-ish” smoke. P15 is that bridge.
The target was the smallest upstream unprivileged integer test:
rv32i/I/I-nop-00.S from riscv-arch-test revision a7c9930.
The important change from P14 is not a fancy CPU feature. It is making the simulation environment look enough like an architectural-test target:
- 32 integer registers, because the official framework initializes
x16..x31. - 8 KiB byte-addressed unified memory, because text, data, signature, and model sections all have addresses.
- Byte and halfword load/store decode, because the official framework’s failure/reporting paths contain them even before we chase broader coverage.
- A tiny P15
rvmodel_macros.hthat usesRVTEST_SELFCHECK, no UART, and a simple pass tail:x5 = 1; jal x0, 0.
Result:
PASS: P15 official rv32i/I/I-nop-00.S self-check accepted after 761 clocks
PASS: P15 official acceptance smoke complete.
Honesty note: this is one official test, not the full suite. We have
not passed the branch, ALU, load/store, CSR, trap, or privileged tests.
But the repo now has its first official PASS, and the next failures
will be real failures instead of “cannot even load the test.”
Backend memory lesson
We also tried to harden this shape, and the memory choice immediately became the real lesson.
The first version put the full 8 KiB official test memory inside the
design. That made the simulator convenient, but it made synthesis awful:
Yosys expanded the byte RAM into standard-cell flops and muxes, then
spent a long time optimizing a design that was mostly fake memory. That
run, RUN_2026-04-29_15-49-08, is PARTIAL.
The fix is to make memory a bus device. The P15 core now exposes a small
byte-addressed request bus. The official testbench hangs an 8 KiB RAM on
that bus and still passes I-nop-00.S. The LibreLane top hangs only a
16-byte halt-loop memory on the same bus, so the backend probe explores
the CPU and interface without pretending an 8 KiB flop RAM is a sane
chip memory.
That got much farther. RUN_2026-04-29_19-04-58 reached post-PnR STA
and Magic DRC with the 16-byte memory, but post-PnR setup timing failed
at the current 25 ns clock target. Worst reported setup WNS was about
-5.16 ns, so that run was PARTIAL.
The next morning’s compact 40 ns run, RUN_2026-04-30_06-20-57, closed
the practical backend loop with an explicit project SDC. Final GDS
exists, Magic DRC is PASS, KLayout DRC is PASS, LVS is PASS,
antenna is PASS, setup timing is PASS, and hold timing is PASS.
The metrics still carry max slew/cap warnings (5155 slew, 59 cap),
so that remains a cleanup note rather than invisible hand-waving.
Next practical memory step: keep the bus boundary and replace the tiny placeholder with an SRAM-backed memory wrapper when we want a real chip target. For official acceptance testing, keep the big memory in the testbench.