Co-Simulation Plugins
LabWired owns deterministic firmware execution, board topology, traces, and fault orchestration. Physical plant models can be declared as co-simulation models and stepped through an adapter.
The first supported manifest shape is:
cosim_models:
- id: "plant_model"
adapter: "external_process" # external_process | fmi | mock
model: "./models/mock-plant.py"
step_ns: 10000
inputs:
controller_enable: "control.enable"
load_torque_nm: "plant.load.torque_nm"
outputs:
shaft_speed_rpm: "observables.shaft_speed_rpm"
plant_ready: "observables.plant_ready"
config:
protocol: "jsonl"
external_process and fmi adapters require model. step_ns must be
greater than zero. The mock adapter is intended for deterministic tests and
dry-runs; its static outputs are declared under config.outputs so the top-level
outputs map can stay dedicated to LabWired signal routing.
The core runtime now exposes a small co-sim registry and runner:
build_cosim_adapter(config)constructsmockandexternal_processadapters from aCosimModelConfig.adapter: fmiintentionally returns a clear unsupported error until the FMI import path is selected.CosimRunner::step_until(time_ns, inputs)steps models only at their configuredstep_nsboundaries. It is deliberately independent from the bus for now; the next integration layer should map real firmware/topology signals into the runner inputs and route returned outputs into traces/UI observables.CosimRunner::step_until_with_signals(time_ns, signals)applies the manifestinputsandoutputsmaps against a signal store. For example,controller_enable: control.enablefeeds the model-localcontroller_enableinput from thecontrol.enablestore path, andshaft_speed_rpm: observables.shaft_speed_rpmwrites the model output back toobservables.shaft_speed_rpm.CosimRunner::from_configs_with_base(configs, base_dir)resolves relative external model paths against the manifest directory, so example manifests can keep local./models/...references.
This contract is intentionally domain-neutral. A model can represent a motor, thermal plant, hydraulic system, sensor array, battery pack, power stage, or any other external process as long as it consumes named inputs and returns named outputs.
The examples/cosim-plant-demo manifest exercises this generic contract with a
reduced-order discrete plant: per-channel enabled/disabled states, a
scenario-driven disabled_channels list, and voltage/current/active-channel
observables. Higher-fidelity behavior (loss, thermal, semiconductor stress,
grid-compliance validation) belongs in a later adapter-backed model.
Drive any manifest-declared model from the command line with
labwired cosim-step <system.yaml> --set <path>=<value>, which builds the
runner from the manifest and prints the routed outputs after stepping.