Software-in-the-Loop (SIL) & Hardware-in-the-Loop (HIL) with ModelScript
This guide documents ModelScript's unified SIL and HIL architecture based on eFMI-style deterministic code generation, WebAssembly, FMI Layered Standards (FMI-LS-BUS), and browser-native Soft HIL.
Architecture Overview
Modelica Plant Model (.mo)
│
▼
DAEBuilder Linear Memory Arena
├── Fixed-step RK4 solver
└── Neural ROM Surrogates (rom-trainer)
│
┌─────────────────────────┴─────────────────────────┐
▼ ▼
1. BROWSER SOFT HIL 2. HARD REAL-TIME HIL
(Chrome / Edge Web APIs) (Linux RT-PREEMPT / WAMR)
- AudioWorklet real-time clock - SCHED_FIFO Priority 99
- WebSerial (SLCAN / COBS / JSON) - mlockall (Zero page faults)
- Dedicated Web Worker sandbox - Linux SocketCAN (can0)
- 10 Hz – 200 Hz control loops - > 1 kHz, < 50 µs jitter
- Testing: Arduino, STM32, ESP32, USB-CAN - Testing: Production ECUs, Inverters1. FMI-LS-BUS (Layered Standard for Network Communication)
ModelScript implements the Modelica Association FMI-LS-BUS standard:
FmiLsBusManifest: Describes CAN, CAN-FD, LIN, and Ethernet buses and frames.generateFmiLsBusXml: Generates standardfmi-ls-bus.xmlbundled inside the FMU archive.FmiLsBusCodec: High-performance bit-level encoder and decoder supporting Intel (little-endian) and Motorola (big-endian) bit alignments, linear scaling (physical = raw * factor + offset), signed/unsigned integers, and float32 data types.
Example: Defining CAN Frames in TypeScript
import { FmiLsBusFrame, FmiLsBusCodec, generateFmiLsBusXml } from "@modelscript/exchange";
const engineFrame: FmiLsBusFrame = {
name: "EngineStatus",
id: 0x120, // CAN ID 288
length: 8,
cycleTime: 0.01, // 10 ms (100 Hz)
signals: [
{
name: "engineSpeed",
valueReference: 1,
startBit: 0,
bitLength: 16,
byteOrder: "littleEndian",
factor: 0.25, // 1 LSB = 0.25 rpm
offset: 0,
unit: "rpm",
},
{
name: "throttlePosition",
valueReference: 2,
startBit: 16,
bitLength: 8,
byteOrder: "littleEndian",
factor: 0.392, // 0-100%
offset: 0,
unit: "%",
},
],
};2. In-Browser "Soft HIL" (WebSerial, WebUSB, WebHID)
For desktop and browser-based testing, ModelScript provides the WebSerialParticipant (packages/exchange/src/cosim/participants/web-hardware.ts):
Supported Hardware Adapters & Microcontrollers
- USB-to-CAN Adapters (SLCAN): CANable, candleLight, USBtin, Zubax Babel.
- Microcontrollers (USB-UART / CDC): STM32 Nucleo, ESP32, Arduino, Teensy, Raspberry Pi Pico.
- Framing Protocols:
slcan: Standard ASCII CAN protocol (t12080102030405060708\r).cobs: Consistent Overhead Byte Stuffing for binary frames.json: Line-delimited JSON objects ({"rpm": 3200, "throttle": 45}\n).
Using WebSerialParticipant in Co-Simulation
import { CoSimOrchestrator, CoSimSession, WebSerialParticipant } from "@modelscript/exchange";
// Create hardware participant
const hwParticipant = new WebSerialParticipant({
id: "ecu_serial",
baudRate: 115200,
protocol: "slcan",
busFrames: [engineFrame],
});
// Add to co-simulation session
session.addParticipant(hwParticipant);Unthrottled Browser Pacing via AudioWorkletClock
Browsers throttle setInterval to 1 Hz when tabs are backgrounded. ModelScript's AudioWorkletClock (packages/exchange/src/cosim/audio-worklet-clock.ts) leverages the high-priority OS audio thread (44.1 kHz) to drive the simulation loop, so it is not subject to background-tab timer throttling.
3. Hard Real-Time HIL on Linux RT-PREEMPT
For hard real-time execution with physical ECUs over CAN:
- Compile Model to Standalone C / WASM: ModelScript's C generator produces a static memory model with an embedded zero-allocation
integrate_rk4solver. - Compile Neural ROM Surrogates to C: Use
exportROMToC(trainedRom)from@modelscript/simulateto generate zero-dependency static C arrays for surrogate evaluation in < 20 µs. - Deploy with Standalone Runner: Use
hil-runner-template.c(packages/exchange/src/fmu/hil-runner-template.c):- Compiles with
gcc -O3 hil-runner-template.c model.c -lm -o model_hil. - Runs with
sudo ./model_hil can0underSCHED_FIFOpriority 80 withmlockall.
- Compiles with
4. Shared-Memory IPC & Zero-Overhead Local Agent Proxy
For multi-rate co-simulation between compiled FMUs, ModelScript provides a high-throughput Shared-Memory IPC Protocol (packages/exchange/src/cosim/ipc/fmu-shm-protocol.ts):
- Zero-Copy Memory-Mapped Ring Buffers: Uses POSIX shared memory (
/dev/shmon Linux) and named shared memory segments on Windows with cache-line-aligned (64-byte) atomic variables. - Spinlock & Futex Synchronization: State exchanges achieve > 500,000 steps/sec with sub-2µs latency, bypassing TCP/loopback network stack overheads.
- Local Agent Proxy (
local-agent-proxy.ts): Couples proprietary or legacy simulation executables into ModelScript'sCoSimOrchestratorvia shared-memory participants with dead-reckoning extrapolation and interface Jacobian negotiation.

