This example requires external dependencies and cannot be run in the browser.

C Code Generation

Turning a block diagram into standalone C99, and proving the C still solves the same problem.

What comes out

to_c lowers the assembled model to self-contained C99 — libm and nothing else. All state lives in one instance struct, so the code is reentrant and several generated models can link into the same binary. That is what makes it usable on a microcontroller, in a HIL rig, or inside an FMU.

The generated code is not a transcription of the Python. The model first becomes the typed IR, where every block is reduced to scalar operations; the C is emitted from that.

Simulation.to_c() returns the sources as a dict, and Simulation.verify_c() compiles them, integrates both the C and the engine over the same trajectory, and compares state by state.

The Model

A DC motor under PI speed control — a small system with a controller, an integrator and feedback, which is the shape most embedded models have:

MATHDISPLAY0ENDMATH

Python
Loading...
Python
Loading...

The Reference Run

Python
Loading...

Generating the C

to_c returns the sources keyed by file name.

Python
Loading...

The interface

The header is the whole contract: one struct holding the state, an enum naming every addressable signal, and a handful of functions.

Python
Loading...
Python
Loading...

Nothing is global, so two instances of the model can run side by side in one process — the property that makes the code safe to drop into an RTOS task or an FMU.

Signals are reached by name through the enum rather than by digging into the struct layout: motor_get_signal(&m, MOTOR_SIG_ODE_y) is the motor's output wherever the code generator decided to put it.

Verification: Software in the Loop

Reading the C is not evidence. verify_c compiles it with a local C compiler, integrates the binary and the engine over the same trajectory, and compares the state vector at every step.

The figure it reports is a scaled error, MATHINLINE0ENDMATH, so a value below 1 means the C stayed inside the tolerance at every step of every state.

Python
Loading...

Compiling and Running It Ourselves

The same C, driven the way an application would: write the files out, add a main that steps the model, compile, and run it.

Python
Loading...
Python
Loading...
Python
Loading...

Code Generation Options

The same model lowers several ways. The axes are independent, and every combination is checked by the test suite against the engine.

Python
Loading...

numeric="float" is the one that changes the answer rather than just the shape: single precision costs about seven digits, which matters on a target without a double-precision FPU. The verification above is what tells you whether that is affordable for a given model.