P15 could run the first official RISC-V arch-test smoke from SRAM, but the top-level SRAM test still preloaded the macro models hierarchically. That was fine for checking the adapter and useless as a boot story.
P16 adds the missing boring thing: a byte loader.
The protocol is:
| byte(s) | meaning |
|---|---|
0xa5 | start |
| count low | low 8 count bits |
| count high | high 6 count bits |
| payload | bytes written from SRAM address zero |
The current test sends an 8192-byte image built from upstream
rv32i/I/I-nop-00.S in RVTEST_SELFCHECK mode. The loader writes SRAM,
the testbench drops load_mode, and the CPU runs from address zero.
Result:
riscv-arch-test a7c9930
built official rv32i/I/I-nop-00.S in RVTEST_SELFCHECK mode
PASS: P16 loaded 8192 bytes into SRAM over UART
PASS: P16 UART-loaded official rv32i/I/I-nop-00.S self-check accepted after 1067 clocks
PASS: P16 UART SRAM-loader acceptance smoke complete.
After KLayout DRC passed, we widened the official-source RTL probe:
make -C projects/16_rv32i_sram_loader/test batch
That batch builds all 39 upstream rv32i/I/*.S tests in
RVTEST_SELFCHECK mode. Two images fit in the current 8 KiB SRAM and both
pass through the UART loader:
| test | result |
|---|---|
I-nop-00.S | PASS |
I-fence-00.S | PASS |
The other 37 are NOT RUN, not core failures: their generated self-check
images exceed the 8 KiB SRAM window. I-auipc and I-lui are the smallest
misses at 8968 bytes; the arithmetic and branch tests are much larger because
the official framework reserves signature storage. The full table is in
projects/16_rv32i_sram_loader/compliance/RESULTS.md.
Then we sent it through LibreLane.
The first harden command completed placement, CTS, routing, antenna repair, extraction, and STA, then died at optional KLayout render:
The layout has multiple top cells in Layout.top_cell
That render is useful for the notebook picture, not for signoff, so the run
was resumed from Magic.WriteLEF with KLayout.Render skipped. The resumed
flow completed:
| check | result |
|---|---|
| Run directory | projects/16_rv32i_sram_loader/librelane/runs/RUN_2026-04-30_13-21-47 |
| Final GDS | projects/16_rv32i_sram_loader/librelane/runs/RUN_2026-04-30_13-21-47/final/gds/top.gds |
| Metrics | projects/16_rv32i_sram_loader/librelane/runs/RUN_2026-04-30_13-21-47/final/metrics.json |
| Route DRC | PASS (0) |
| Magic DRC | PASS (0) |
| KLayout XOR | PASS (0) |
| KLayout DRC | PASS (0) |
| LVS | PASS (0) |
| Antenna | PASS (0) |
| Setup timing | PASS (0 setup violations, worst setup slack 13.475 ns) |
| Hold timing | PASS (0 hold violations, worst hold slack 0.0779 ns) |
| Max slew / cap checker | PARTIAL (4719 slew, 153 cap warnings) |
KLayout DRC initially failed before checking rules because the Magic-streamed
GDS had multiple top cells from the SRAM collateral. Switching P16 to
PRIMARY_GDSII_STREAMOUT_TOOL: klayout gave the DRC deck a single-top GDS
input; the follow-up 81-klayout-drc step finished in 17:35 with 0
violations.
Status is now hardened, with the same honest caveat as the recent macro
projects: the layout is routed, connected, and timed, but the electrical
transition/capacitance warnings are still real cleanup work.
This is a much better next chip candidate than another preloaded SRAM demo. The harden answer is yes: the small UART loader fits into the same four-macro floorplan that P15 used.