SIL emulator¶
The software-in-the-loop (SIL) system tests the complete firmware ↔ UI
integration with no physical hardware. It executes the Propeller 2
image on an instruction-set simulator. The machine's pins are nets, and the
physics models sit on those nets. The host on the protocol link is the host's
Chrome, every page and worker held to the board's clock by embsim's
chrome-cdp node; or a PTY, for a serial console. The control app connects to
the virtual serial port exactly as it would to a real board.
One system runs it:
- The machine's project files (
SIL/mad.tomland the others, underembsim run): the Edge carrier and the P2-EC32MB module from their netlists, the ISS as the module's processor booting the firmware image (pio run -e MaD) off the module's flash, the DS2 add-on and the machine on the carrier's connectors, the host on the carrier's control portJ4(or, on the serial-boot files that flash it, the debug headerJ1). The e2e suite runs here (make e2e, onmad-cosim.toml); so do the scenarios that move the carriage, on the same file (make e2e-motion), SERVO-stall, on that file with a hard stop on its carriage,mad-hard-stop-cosim.toml(make e2e-stall, MaD #298), FW-ISS, the app's flasher against the mask ROM, onmad-serial-boot-cosim.toml(make e2e-rom), the playgrounds, on headed copies (make playground,playground-rom), andmad-catalog's tests.
This is not a mock
The firmware under test is the image you flash. The ISS executes its
instructions, including WRPIN / DIR / OUT, so a wrong smart-pin mode
or a wrong clkfreq shows up on the wire. The screenshots in this
documentation were produced by driving the app against this emulator.
embsim — a reusable framework¶
The board is embsim. A part is a node: it publishes a drive and receives a sense. MaD supplies the core (the ISS) and the bench around it. The generic crates carry no MaD protocol and no gantry geometry.
flowchart TB
catalog["<b>mad-catalog</b> / <b>mad-runner</b><br/>MaD's kinds; runs the project files"]
iss["<b>p2iss</b> / <b>p2core</b><br/>the P2 image, instruction by instruction"]
board["<b>embsim-board</b><br/>nets, drives, host PTY"]
models["<b>embsim-models</b><br/>ADC · stepper · encoder · end switch"]
core["<b>embsim-core</b> — virtual clock · serial PTY"]
madmodels["<b>models</b><br/>gantry · sample · strain gauge"]
catalog --> iss --> board
catalog --> models
catalog --> madmodels
board --> core
models --> core
madmodels --> models
The dependency graph is acyclic — no generic crate depends on a project crate.
MaD-specific code lives in mad-catalog/, mad-runner/,
p2iss/, p2core/, models/, and the protocol crate (Protocol/rust/). See the
embsim README.
The simulation chain¶
When the firmware commands the motor, a chain of callbacks turns pulses into forces and feeds them back as sensor readings:
flowchart TB
pulse["step pin, periodic drive"] --> motor["stepper model<br/>(position over time)"]
motor --> enc["encoder (position feedback)"]
motor --> limit["end switches"]
motor --> gantry["gantry"]
gantry --> sample["sample model<br/>force = f(displacement)"]
sample --> gauge["strain gauge"]
gauge --> adc["ADS122U04 ADC"]
adc -->|"serial levels"| fw["firmware reads force"]
limit --> fw
enc --> fw
The ADC, stepper, encoder, and end switch are generic (embsim-models).
The gantry, sample, and strain gauge are MaD-specific (SIL/models/).
Pin numbers are the firmware's (HW_pins.h); the project files reach them
through the carrier's netlist (mad-catalog/netlists/mad_edge.net).
The virtual serial port¶
The host end sits on the protocol nets at 2,000,000 baud 8N1: on the project,
the carrier's control port J4, through the isolator IC2 to P30/P32,
as on the machine (the serial-boot files and the reflash file put it on the
debug header J1, P63/P62, where the Prop Plug sits, to flash). It is
one of two components:
- Chrome on the board's clock (
chrome-cdp:mad-cosim.toml'sHOST,make e2e;mad-playground.toml's, headed,make playground). Every page'snavigator.serialis the node's shim, whose one port is this line (USB0403:6001onJ4,0403:6015onJ1), by Chrome's own rules; every page and dedicated worker lives the board's time, a 1 ms quantum at a time over DevTools, so the app's 2 s response timeout is 2 s of the board's time. Its rail pins are wired to a 3.3 V rail and the board's ground. - A PTY (
host-serial:mad.toml'sHOST,embsim run mad.toml --pty PATH;make playground-pty,embsim run mad.toml --pty /tmp/tty.iss), for a serial console or a program. A browser behind it (the WS↔PTY bridge) runs at host speed while the ISS runs at a few percent of real time, so it measures the host, not the machine.
On real hardware the app uses Web Serial directly. See SIL testing.
One emulator per process¶
The virtual clock and the host PTY are process-global, so there is one
emulator per OS process. To run several, run several processes — which is
why the E2E suite uses workers: 1.