No. 32 / project of 147 on the ladder

RV32IM runtime probe

introduces — RV32M multiply/divide, ACT4 rv32i/M tests, and C arithmetic without avoiding hardware division

harden statelast run2026-05-01
cells39,172non-filler
slack-7.80ns setup
area900 x 900 die, 314163 stdcell areaμm²
signoff
  • DRCPASS
  • LVSPASS
  • antennaPASS

P32 adds the RV32M multiply/divide extension. The core still has the same external-memory platform, UART loader, MMIO timer, and machine interrupt path, but OP instructions with funct7=0000001 are now real instructions instead of illegal traps.

Status: hardened with timing cleanup left. The compiled RV32IM runtime passes, ACT4/Sail rv32i/I passes with PASS=39 FAIL=0 NOT RUN=0, and ACT4/Sail rv32i/M passes with PASS=8 FAIL=0 NOT RUN=0. LibreLane run RUN_2026-05-01_12-10-27 produced final GDS and passed DRC, LVS, and antenna checks. Slow-corner setup timing, max slew, and max cap still need cleanup.

The Result

Run it:

make -C projects/32_rv32im_runtime_probe/test

Result: PASS

checkresult
Build linked rv32im_zicsr runtime ELFPASS
UART-load compiled imagePASS
Execute C *, /, and % through RV32MPASS
Execute mulh, mulhsu, and mulhuPASS
Check divide-by-zero and overflow edge casesPASS
MMIO UART writes M, T, EPASS
MMIO timer interrupt visible to CPASS
External interrupt visible to CPASS
Halt with x5 = 1PASS

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

ACT4/Sail rv32i/M: PASS=8 FAIL=0 NOT RUN=0

Harden status: PASS with timing cleanup left

harden checkresult
Run directoryprojects/32_rv32im_runtime_probe/librelane/runs/RUN_2026-05-01_12-10-27
Final GDSprojects/32_rv32im_runtime_probe/librelane/runs/RUN_2026-05-01_12-10-27/final/gds/top.gds
Metricsprojects/32_rv32im_runtime_probe/librelane/runs/RUN_2026-05-01_12-10-27/final/metrics.json
Magic DRCPASS (0 errors)
KLayout DRCPASS (0 errors)
LVSPASS (0 errors)
AntennaPASS (0 violations)
Hold timingPASS (0 violations)
Setup timingFAIL at slow corners; worst setup slack -7.798 ns
Max slew / max capFAIL; 8158 max-slew and 127 max-cap violations

What Changed

The core now implements:

instructionbehavior
MULlow 32 bits of signed/unsigned product
MULHhigh 32 bits of signed x signed product
MULHSUhigh 32 bits of signed x unsigned product
MULHUhigh 32 bits of unsigned x unsigned product
DIV, DIVUsigned and unsigned quotient
REM, REMUsigned and unsigned remainder

RISC-V edge cases are included: divide by zero, signed overflow on 0x80000000 / -1, and the corresponding remainder behavior.

misa now reports IM: 0x40001100.

Runtime Shape

The runtime still uses the P31 reset/trap shape, but main.c now includes an RV32M probe. Ordinary C operators force mul, div, divu, rem, and remu to appear in the compiler output. Inline assembly covers mulh, mulhsu, and mulhu, because C has no direct 32-bit high-product operator.

The generated runtime binary is 888 bytes in the current build.

Scope

This is no longer simulation-only: the backend completed and emitted final GDS. The worst part is no longer a single-cycle divider. Multiply and high-half multiply use combinational product logic; divide and remainder use a 32-cycle restoring divider. That gets P32 through physical signoff checks, but the remaining timing reports say the arithmetic datapath is too slow in the slow corners at this clock target.

Still unsupported: atomics, compressed instructions, supervisor mode, vectored mtvec, delegation CSRs, satp, an MMU, and official full compliance packaging.