Simulation Workflow
Renode is a core part of zenbedded's developer loop. Every Pull Request must pass our Renode smoke tests before it is merged, and the logs must be silent—warnings are bugs.
Task Wrappers
.mise.toml defines tasks for each board:
mise run sim-stm32f4
mise run sim-bluepill
mise run sim-nrf52840
mise run sim-bluepill-display # ST7789 SPI analyzer harness
All tasks default to renode --disable-xwt --console …. Set RENODE_OPTS if you need different flags (e.g. RENODE_OPTS="" to pop analyzer windows) or RENODE to point at an alternate binary.
Each task performs the following steps:
- Cross-builds the firmware ELF with
zig build -Dboard=.... - Writes a temporary
.rescscript that loads our vendored.repldescriptions. - Starts Renode in console mode and captures UART output to
build/renode/<board>-uart.log.
Vendored Platform Files
renode/platforms/cpus/*.repldescribe CPU cores, interrupt controllers, and memory maps. We include lightweight stubs (such as a dummy RCC region for STM32F1) to silence Renode warnings.renode/platforms/boards/*.replassemble the CPU description with board-level peripherals (LEDs, buttons) for visibility when debugging.
By committing these files, we guarantee that CI and local developers exercise the same virtual hardware.
Clean logs
A key quality metric is “no warnings in Renode logs.” When warnings do appear, we either stub the missing peripheral or adjust our register writes until Renode can acknowledge them. This makes genuine regressions easy to spot in CI artifacts and keeps the simulation environment predictable.
Display bring-up (Blue Pill + ST7789)
mise run test-display-renode builds the Blue Pill firmware, launches Renode with a logging SPI slave, and verifies the exact initialization sequence emitted by the ST7789 driver. The analyzer writes a detailed trace to build/renode/st7789.log; the Python parser inspects the MOSI stream and fails if any required command is missing or reordered.
The display harness stores the UART and SPI logs as GitHub Actions artifacts so reviewers can audit the byte stream when regressions surface. For visual debugging we ship a tiny C# plugin (renode/plugins/ST7789Visual.cs) that exposes the framebuffer via Renode’s VideoDevice. The helper task mise run build-st7789-visual compiles the plugin with the pinned .NET SDK before each simulation.
- The default console run verifies the SPI byte-stream deterministically.
- Opt-in visualization by exporting
RENODE_VISUAL=1beforemise run sim-bluepill-display; Renode will open the framebuffer analyzer window. - You can still override
RENODE_OPTSto tweak Renode flags (e.g.""to allow windows while keeping the analyzer). - Need more time to poke around? Set
RENODE_NO_QUIT=1so the.rescscript skips issuingquitand leaves Renode running until you close it manually.
Note: Renode's STM32F1 GPIO/SPI models still warn when we tweak CNF bits or enable the SPI master (the emulator doesn't implement those fields yet). We track these warnings and treat them as expected noise until upstream support lands; all other warnings remain blockers.
Extending Simulations
To add a new board:
- Vendor (or author) the CPU and board
.replfiles underrenode/platforms/. - Update
.mise.tomlwithbuild-<board>andsim-<board>tasks. - Extend
build.zigwith the new linker script, CPU model, and board banner. - Add the board to the GitHub Actions matrix so cross builds run on every commit.