LabWired uses a YAML-based configuration system to define the simulated hardware environment. This separation allows the same firmware binary to be tested against different hardware configurations (e.g., changing memory sizes or remapping peripherals) without recompilation.
A complete simulation requires two descriptor files:
- Chip Descriptor (
chips/<name>.yaml): Defines the internal architecture of the SoC (Flash/RAM size, internal peripheral addresses). - System Manifest (
systems/<name>.yaml): Instantiates a chip and defines board-level wiring (external sensors, UART loopbacks).
Defines the invariant properties of the silicon.
name: "STM32F103"
arch: "arm"
core: "cortex-m3" # Exact CPU core; gates core-specific behavior
# (e.g. bit-band aliasing exists only on M3/M4)
flash:
base: 0x08000000
size: "64KB" # Supports KB/MB suffixes
ram:
base: 0x20000000
size: "20KB"
peripherals:
# Internal Peripheral Definition
- id: "usart1"
type: "uart"
base_address: 0x40013800
irq: 37
config:
profile: "stm32f1" # Loads architecture-specific register map
- id: "gpioa"
type: "gpio"
base_address: 0x40010800
config:
profile: "stm32f1"
# Declarative Peripheral (Custom)
- id: "my_custom_timer"
type: "declarative"
base_address: 0x40004000
config:
path: "../peripherals/custom_timer.yaml"uart,usart: Universal Asynchronous Receiver Transmittergpio: General Purpose I/Orcc: Reset and Clock Controltimer: Basic Timeri2c: Inter-Integrated Circuitspi: Serial Peripheral Interfaceexti: External Interrupt Controllerafio: Alternate Function I/Odma: Direct Memory Access Controllersystick: System Tick Timerdeclarative: Loads a generic peripheral from a YAML register description.
Defines the board-level environment.
name: "BluePill Board"
chip: "../chips/stm32f103.yaml" # Path relative to this file
# External Device Connections (Planned)
connectors:
- type: "uart"
peripheral: "usart1"
endpoint: "host_console" # Pipes UART output to simulator stdoutFor an inputs.env CI world, each nodes[].system value points to this
same System Manifest format used by the Playground. The environment manifest
adds node IDs, firmware paths, and explicit interconnects; it does not create a
second board-configuration dialect. v0.19 world manifests reject
nodes[].config_overrides: the field must be omitted, including {} and null.
Each resolved node chip must resolve to arch: arm and declare
core: cortex-m*; its firmware must be an EM_ARM ELF with a valid Cortex-M
Thumb reset vector at flash.base + reset_vector_offset (SP in RAM and
Thumb-bit reset handler in flash). See the CI Test Runner
for the closed world-interconnect schema.
World completion stays in the inputs.env test script, not the manifest. Set
limits.stop_when_assertions_pass: true to opt into a durable early completion:
all node-qualified assertions must pass at or after the optional
stop_when_assertions_pass_min_steps floor and remain true for the optional
stop_when_assertions_pass_settle_steps window (default 100000). The default
is false; a same-round runtime failure or wall_time_ms, max_cycles, or
max_uart_bytes limit takes precedence over assertions_passed. max_steps
remains the outer execution bound, so an all-pass final world round reports
assertions_passed.
To run a simulation, provide both the firmware and the system manifest:
labwired --firmware firmware.elf --system configs/systems/bluepill.yamlThe simulator loads the system manifest, resolves the chip descriptor, initializes the memory map, and begins execution at the Reset Vector.