journal 2026-04-30

P16 loads the official smoke over UART

p16riscvsramuart

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
0xa5start
count lowlow 8 count bits
count highhigh 6 count bits
payloadbytes 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:

testresult
I-nop-00.SPASS
I-fence-00.SPASS

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:

checkresult
Run directoryprojects/16_rv32i_sram_loader/librelane/runs/RUN_2026-04-30_13-21-47
Final GDSprojects/16_rv32i_sram_loader/librelane/runs/RUN_2026-04-30_13-21-47/final/gds/top.gds
Metricsprojects/16_rv32i_sram_loader/librelane/runs/RUN_2026-04-30_13-21-47/final/metrics.json
Route DRCPASS (0)
Magic DRCPASS (0)
KLayout XORPASS (0)
KLayout DRCPASS (0)
LVSPASS (0)
AntennaPASS (0)
Setup timingPASS (0 setup violations, worst setup slack 13.475 ns)
Hold timingPASS (0 hold violations, worst hold slack 0.0779 ns)
Max slew / cap checkerPARTIAL (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.