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:

  1. Cross-builds the firmware ELF with zig build -Dboard=....
  2. Writes a temporary .resc script that loads our vendored .repl descriptions.
  3. Starts Renode in console mode and captures UART output to build/renode/<board>-uart.log.

Vendored Platform Files

  • renode/platforms/cpus/*.repl describe 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/*.repl assemble 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=1 before mise run sim-bluepill-display; Renode will open the framebuffer analyzer window.
  • You can still override RENODE_OPTS to tweak Renode flags (e.g. "" to allow windows while keeping the analyzer).
  • Need more time to poke around? Set RENODE_NO_QUIT=1 so the .resc script skips issuing quit and 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:

  1. Vendor (or author) the CPU and board .repl files under renode/platforms/.
  2. Update .mise.toml with build-<board> and sim-<board> tasks.
  3. Extend build.zig with the new linker script, CPU model, and board banner.
  4. Add the board to the GitHub Actions matrix so cross builds run on every commit.