MCU A Fixed RV32I — innovate on microarchitecture
Ship an RV32I core that drops into the locked user_project_wrapper, boots a
binary we provide from QSPI flash, and runs a fixed deterministic CRC32 kernel. The ISA is frozen so
every submission retires the same instruction stream — the entire optimization space is
microarchitecture, and the score is correctness, IPC, and energy per instruction.
user_project_wrapper with the same locked pinout — Wishbone control, QSPI flash, UART, and the
GPIO map are identical for everyone — so results are directly comparable and the design is manufacturable on
the chipignite shuttle.Overview
MCU A is the simplest contract on PPABench, and the most direct test of core design.
The deliverable is one line: prompt → an RV32I core in the chassis. Your core replaces the
reference picorv32 inside the fixed OpenFrame / chipignite user_project_wrapper — same
pinout, same QSPI flash model, same UART, same Wishbone control registers. We hand you a compiled
RV32I binary; your job is to fetch it from flash, execute it correctly, and finish quickly and
efficiently.
Grading runs both halves of a real chip. The harden path (yosys → OpenROAD P&R + STA → Magic DRC → netgen LVS) produces the PPA: area, power, fmax, DRC-clean, LVS-match. The hidden testbench (cocotb / Verilator) boots your firmware, drives the start strobe, decodes the UART result against a software golden, and — critically — counts clock edges externally at the wrapper boundary. Because the kernel is deterministic given its inputs, the golden retired-instruction count is known exactly, so IPC, CPI, MIPS, and energy/instruction are all well-defined.
Why the ISA is fixed
IPC and CPI are only meaningful within a fixed ISA. Comparing "instructions per cycle" across two different instruction sets is meaningless — one design's single fused instruction is another's five. By locking the ISA to RV32I we get three things for free:
- A real, off-the-shelf toolchain compiles the kernel, so the binary is reproducible and auditable.
- A reference instruction-set simulator (ISS) gives the golden retired-instruction count directly — no need to trust anything the DUT reports.
- The retired count is held constant across every submission, so two cores running this benchmark differ only in how many cycles they take and how much energy they burn to retire the identical 17,229-instruction stream.
That turns the whole problem into microarchitecture: instruction cache, prefetch, pipeline depth and forwarding, branch prediction, and — for the ambitious — superscalar issue. None of those change the program; all of them change IPC and energy.
The workload
The kernel is a reflected CRC32 (polynomial 0xEDB88320, the standard zlib/PNG
reflected form) computed over a 256-byte table. To stop anyone hardcoding a single answer, a host
scalar delivered through Wishbone register CFG0 (offset 0x08)
perturbs the table before the CRC is taken. The core emits its result on UART as:
The computation is fully deterministic given the pair (binary, CFG0): the same firmware and the same CFG0 always produce the same retired-instruction count and the same CRC string. The testbench picks CFG0 at runtime, so the correct output is not knowable ahead of the run, but the golden is trivially computable in software once CFG0 is fixed.
Interface & protocol
The chassis is the locked OpenFrame / chipignite user_project_wrapper. Your core talks
to the outside world only through the fixed pins and registers below — nothing else is connected:
The run sequence is: the testbench loads the flash image and CFG0, strobes CTRL.start,
and begins counting wb_clk_i edges. Your core boots from flash, runs the CRC kernel, and
writes the magic value 0x600DF00D to MMIO 0x04000000 to signal completion;
the SoC reflects that into STATUS.done / io[35], at which point the external
counter stops. The UART line is decoded and compared to the golden.
Grading
Functional is binary: the decoded UART string must match the software golden CRC32 for the CFG0 used in that run. No partial credit.
Performance is derived from the externally-counted cycles and the golden retired count:
- IPC = retired / cycles, and CPI = cycles / retired.
- MIPS = IPC × f (operating clock 50 MHz).
- Figure of merit = energy per instruction (pJ/instr), with EDP (energy × wall-time) as the efficiency tiebreaker.
wb_clk_i edges between CTRL.start and STATUS.done, measured at
the wrapper boundary by the testbench. It is never read from a DUT-internal performance counter —
a register you increment yourself does not count and cannot be trusted.Pass/fail is a gate, not a curve: a submission passes only if it clears the PPA caps,
functional_ok, timing_met (WNS ≥ 0), DRC-clean, and LVS-match. Everyone who
passes is a real chip; passers are then ranked by efficiency (EDP / energy / area / perf KPIs),
so the leaderboard sorts on energy-per-instruction with EDP as the ranking key.
Anti-cheat
The defenses are structural rather than policy-based:
- You run our binary — you don't get to choose or shrink the instruction stream.
- Cycles are externally timed at the wrapper boundary, so a self-reported counter is worthless.
- The output is checked against a software golden, so a fast-but-wrong core fails functional.
- The CFG0 perturbation makes the correct CRC depend on a runtime value, so the answer cannot be precomputed or baked into the design.
The net effect: there is no way to win except to actually execute the program faster and more efficiently in real silicon.
Reference baseline — picosoc
The reference is picosoc (picorv32 RV32IMC + spimemio QSPI XIP + simpleuart), hardened on sky130 HD. These are the real measured numbers: functional and cycles come from the live Verilator/cocotb run (cycles counted externally, start→done); energy is the reference routed PPA applied to the real sim cycles at 50 MHz.
MCU A picosoc reference baseline
picorv32 · sky130 HD · 50 MHz · CRC32 kernel| Metric | Value | Note |
|---|---|---|
| Functional | ✓ | UART matches software golden |
| Cycles (external) | 1,433,997 | wb_clk_i edges, start→done |
| Retired instr | 17,229 | golden, from ISS |
| IPC | 0.0120 | retired / cycles |
| CPI | 83.23 | cycles / retired |
| MIPS | 0.60 | IPC × 50 MHz |
| Energy / cycle | 3.54 | pJ/cycle (P/f) |
| Total energy | 5,076 | nJ (P × cycles / f) |
| Energy / instr | 295 | pJ/instr — figure of merit |
| Area | 3,810 | µm² (routed sky130) |
| fmax | 88.5 | MHz (8.7 ns slack @ 50 MHz) |
| EDP | 1.46e8 | nJ·µs (energy × wall-time) |
Note: the PPA figures (area, power, fmax) are the reference routed sky130 numbers, and the energy figures are that PPA applied to the real measured cycle count at 50 MHz. They are a reference route, not yet a per-submission picosoc harden; your submission is hardened and measured as its own single design.
What a strong submission looks like
Every microarchitectural lever here attacks the same fixed instruction stream. The big wins, roughly in order of impact on this XIP-bound workload:
- Instruction cache. The single largest lever. The CRC kernel is small and loop-heavy, so even a modest I-cache turns repeated flash fetches into hits and collapses CPI from ~83 toward single digits — raising IPC by an order of magnitude with little area cost.
- Prefetch / burst fetch. Streaming sequential words from QSPI ahead of demand hides SPI latency on cold instructions and on the first pass through the loop body.
- Pipelining + forwarding. A deeper pipeline with proper bypass raises steady-state IPC once fetch is no longer the bottleneck; without forwarding the data hazards in the CRC inner loop would cap you.
- Branch prediction. The CRC loop is dominated by one tight backward branch; even a simple predictor removes the misprediction bubbles that otherwise eat the IPC you bought with caching.
- Superscalar issue. For the most aggressive designs, dual-issue of the independent XOR/shift/load operations in the inner loop pushes IPC above 1 — but watch area and fmax, since both feed the PPA caps and EDP ranking.
The design tension is real: caching and superscalar issue raise IPC and cut total energy by finishing sooner, but add area and can hurt fmax. Because the score is energy/instruction with EDP as the tiebreaker, the winning design is the one that retires 17,229 instructions in the fewest joules and the least time — not simply the biggest core.
Tracked metrics
The full KPI set recorded for every MCU A submission:
- Functional: functional_ok (UART vs golden), DRC-clean, LVS-match, timing_met (WNS ≥ 0).
- Throughput / latency: cycles (external), wall_time_us = cycles/f, IPC, CPI, MIPS.
- Energy: energy_per_cycle_pj = P/f×1000, total_energy_nj = P×cycles/f, energy_per_instruction_pj, leakage_fraction = leakage/total.
- Area / power: area_um2, area_per_kgate_um2, total_power_mw, dynamic and leakage power, fmax_mhz.
- Efficiency (ranking): edp_nj_us = energy × wall_time, edap_nj_us_um2 = edp × area.
PPABench v0.1 · MCU A reference baseline picosoc/picorv32 on sky130 HD · grading: harden (OpenROAD/Magic/netgen) + hidden cocotb TB · cycles counted externally, CFG0 randomized per run · github.com/balbekov