A fork of wokwi/rp2040js that emulates the RP2350 (Raspberry Pi Pico 2) Hazard3 RISC-V cores — a corrected, test-gated RISC-V core that boots the A2 bootrom and runs real firmware instruction-by-instruction, with no hardware in the loop.
PGA2350 carrier · main |
PGA2350 carrier · mini |
This isn't a demo reel — it's a readout. The light show is the ghostshow firmware's effects.c, and every WS2812 bit that drives it is produced by this engine stepping the Hazard3 core through the RP2350 bootrom, SIO, timers, and PIO. The boards are the GhostLabs PGA2350 carriers this emulator was built to bring up.
Status: early but real. The RISC-V core boots and runs RV32IMAC + Zba/Zbb/Zbs/Zcb code and passes a verified instruction-correctness suite. The RP2350 peripheral layer is now multi-chip parameterized (
tscis clean), and the chip boots its A2 bootrom and runs real RISC-V firmware: all three firmware integration tests pass —blink_simple(GPIO via SIO),hello_timer(a 250M-step run driven by RP2350 timer interrupts), andpio_blink(two PIO blocks driving GPIO3 and GPIO32, the latter through the RP2350 GPIOBASE pin-window). All 348 tests pass, none skipped. Some RP2350 PIO features not yet exercised by firmware remain deferred — see ROADMAP.md.
The point of a digital twin is to fail in software, not silicon. This engine is the brain inside the
PGA2350 carrier's simulation: the firmware boots
here — A2 bootrom → Hazard3 core → the WS2812 chain on GP28 — long before a board is reflowed, so a
wrong MUL, a dropped timer IRQ, or a mis-based PIO pin-window surfaces as a red test, not a dead
pixel on a soldered-down module. A Vite + TypeScript dashboard in the carrier repo drives this engine
headless, reconstructs the GP28 bitstream into 24 live pixels, and plays exactly the show above in a
browser. Same firmware binary, same instruction core — emulated here, reflowed there.
Three links in a chain, all MIT, all credited (see CREDITS.md):
- wokwi/rp2040js (Uri Shaked) — the RP2040 emulator base.
- c1570/rp2040js (
rp2350js/WIP) — added the entire RP2350 / Hazard3 RISC-V core (~50 h). Imported here with authorship preserved. - This fork — re-bases c1570's RP2350 work onto the latest upstream and fixes the RISC-V core.
c1570's core is an honest WIP; an adversarial spec review (7 ISA-area reviewers, each finding independently verified) surfaced 19 confirmed defects. We fixed them, each with a falsifiable test:
- The whole RV32M multiply family.
MULused JavaScript's float64*, silently wrong for any product above 2⁵³ (~95% of random operands);MULH/MULHUlost precision;MULHSUwas undecoded and crashed the core. Now exact viaMath.imul/BigInt. - Synchronous trap entry.
ECALL/EBREAKskipped the handler's first instruction (landed atmtvec + ilen) — would break a FreeRTOSportYIELD. Fixed. - Hazard3 external IRQ 0 (TIMER0_IRQ_0) was never delivered (NOIRQ tested via
irq==0instead of themeinextsign bit). Fixed. SLTIUimmediate sign-extension,JALRLSB masking,CSRRCwrite gating, warm-reset PC, the trap-entrymstatusupdate, and the Zcb compressed instructions the RP2350 bootrom needs.
Two further trap bugs were found by lockstepping this engine against c1570's (which runs the firmware) and bisecting the first divergence — these are what make a full firmware run work, not just the unit suite:
MEINEXTreset value. It must reset to NOIRQ; a zeroedMEINEXTreads as "IRQ 0 pending", so the IRQ-0 gate above took a phantom IRQ 0 the instant firmware enabled interrupts. (This was thehello_timerstall.)- MTVEC mode bits. Trap targets must mask
mtvec[1:0]; a vectored mtvec (RP2350 firmware sets0x20000001) otherwise sends an exception to an odd address and crashes. (This was thepio_blinkcrash.)
Most fixes have a regression test in
src/riscv/test/cpu-fixes.spec.ts, each proven to fail on
the pre-fix engine (negative control); the two trap fixes above are covered by the hello_timer
firmware-integration test. The illegal-instruction throw is kept deliberately as a
debug aid rather than silently trapping mcause=2.
npm install
npm test # 348 pass, 0 skipped. hello_timer takes ~22s (a 250M-step firmware run).The RISC-V correctness suite alone:
npx vitest run src/riscvsrc/riscv/— the Hazard3 RISC-V CPU, assembler, and tests (c1570's, with our fixes).src/rp2350.ts,src/rpchip.ts,src/*_rp2350.ts,src/peripherals/*_rp2350.ts— the RP2350 chip and its peripheral variants (c1570's).- everything else — upstream wokwi/rp2040js (RP2040).
MIT — see LICENSE and CREDITS.md.

