MATLAB Simulink Control Systems
ModelScript provides first-class, polyglot compiler support for MATLAB Simulink (.slx, .mdl) control models and dynamic block diagrams. Engineers can author, inspect, lint, formally lower to differential-algebraic equations (DAEs), and project Simulink systems into standard Modelica blocks without requiring a MATLAB license or desktop installation.
Capabilities & Supported Formats
| Format | Extension | Description |
|---|---|---|
| Simulink Modern Zip Package | .slx | Modern OPC XML archive packaging block hierarchy, solver configuration, and state routing. |
| Simulink Classic ASCII Model | .mdl | Classic structured text block diagram specification with hierarchical System, Block, and Line trees. |
Core Architectural Features
- Native Binary & Text Parser:
- Fast, streaming unpacker and XML reader for
.slxpackages viaparseSlx(). - Recursive descent structured parser and lossless roundtrip serializer for
.mdltext files viaparseMdl().
- Fast, streaming unpacker and XML reader for
- Pre-Flight Control System Linters (
M7201–M7210):- Graph-theoretic algebraic loop detection via Tarjan's Strongly Connected Components (SCC) algorithm across direct-feedthrough blocks (
Gain,Sum,Product). - Unconnected input ports, division-by-zero risks, port index mismatches, and multi-rate sample time conflicts.
- Graph-theoretic algebraic loop detection via Tarjan's Strongly Connected Components (SCC) algorithm across direct-feedthrough blocks (
- Continuous & Discrete DAE Lowering:
- Directly maps standard block types (
Integrator,Gain,Sum,Constant,TransferFcn,UnitDelay,Saturation) intoDAEBuilderSoA linear memory arena. - Automatically transforms high-order continuous transfer functions
into Controllable Canonical Form (state-space realization). - Handles discrete sample-and-hold states for synchronous multirate execution.
- Directly maps standard block types (
- Modelica Projection:
- Synthesizes idiomatic
Modelica.Blockscontinuous and discrete acausal models preserving block hierarchy, signal dimensions, and parameter arithmetic.
- Synthesizes idiomatic
- Language Server Protocol (LSP):
- Real-time diagnostic publication, hierarchical document outline (
DocumentSymbol), contextual hover documentation, and quick-fixes in VS Code and web editors.
- Real-time diagnostic publication, hierarchical document outline (
Command Line Interface (msx simulink)
ModelScript CLI exposes turnkey subcommands for headless CI/CD and automation workflows:
msx simulink <action> [files...] [options]| Action | Description | Key Options |
|---|---|---|
inspect | Dumps block diagram hierarchy, solver settings, block counts, and connection topologies. | — |
lint | Runs pre-flight static analysis, algebraic loop detection, and semantic checks. | — |
to-modelica | Generates standard Modelica.Blocks source code. | --out=<file.mo> |
to-dae | Compiles block diagram into ModelScript linear-memory DAE arena and prints statistics. | — |
Examples
# Inspect model parameters, sample times, and block topology
msx simulink inspect CruiseControl.slx
# Check for unconnected inputs, algebraic loops, or division-by-zero risks
msx simulink lint EngineGovernor.mdl
# Convert a Simulink controller into standard Modelica 3.x blocks
msx simulink to-modelica SuspensionControl.slx --out=SuspensionControl.mo
# Lower continuous and discrete equations into DAEBuilder arena
msx simulink to-dae FlightGuidance.mdlControl-Theoretic Linters & Diagnostic Rules
10 rules7 error2 warning1 info Run with msx simulink lint
| Code | Rule | Severity | Message |
|---|---|---|---|
M7201 | unconnected-input-port | error | Input port <portNumber> on block '<blockName>' (<blockType>) is unconnected. All input ports must be driven or terminated with a Ground block. |
M7202 | direct-feedthrough-algebraic-loop | error | Direct-feedthrough algebraic loop detected across blocks: [<loopNames>]. Control loops with direct algebraic feedthrough must contain at least one state delay (Integrator or UnitDelay) or will require an iterative non-linear solver. |
M7203 | unresolved-subsystem-link | error | SubSystem block '<blockName>' has no defined sub-diagram or unresolved library reference. |
M7204 | port-index-out-of-bounds | error | Block '<blockName>' has invalid port index <portNumber>. Port numbers must be positive integers (1, 2, ...). |
M7205 | multirate-sample-time-conflict | warning | Block '<blockName>' has invalid SampleTime <sampleTime>. SampleTime must be >= 0 (discrete) or -1 (inherited). |
M7206 | non-numeric-parameter | error | Block '<blockName>' parameter '<paramName>' contains non-finite value <value>. Parameters must evaluate to finite Real numbers. |
M7207 | invalid-bus-selector | error | BusSelector block '<blockName>' references signal '<signalName>' absent from the incoming bus schema from '<sourceBlock>'. |
M7208 | duplicate-block-name | error | Duplicate block name '<blockName>' found in subsystem scope '<systemName>'. Block names within a system must be unique. |
M7209 | divide-by-zero-risk | warning | Product/Divide block '<blockName>' performs division operations with inputs '<inputs>'; ensure denominator signal is protected against division by zero. |
M7210 | missing-integrator-initial-condition | info | Integrator block '<blockName>' does not specify an explicit 'InitialCondition'; defaulting to 0.0. |
Generated from languages/simulink/src/lints/rules.ts. All languages →
TIP
Algebraic loops detected by M7202 can often be broken without physical fidelity loss by inserting a UnitDelay (discrete) or by modeling small actuator/sensor inertia via a first-order lag TransferFcn (continuous).
Language Server Protocol & Registry Integration
Simulink is fully integrated with @modelscript/lsp via SimulinkWorkspaceIndex:
import { parseSimulink, lintSimulinkModel, simulinkToModelica, lowerSimulinkToDae } from "@modelscript/simulink";
// Parse .mdl or .slx buffer
const model = parseSimulink(fileContent);
// Run static linting
const diagnostics = lintSimulinkModel(model);
// Project to Modelica standard blocks
const modelicaCode = simulinkToModelica(model);
// Lower directly to linear-memory DAE arena
const dae = lowerSimulinkToDae(model);
console.log(`Variables: ${dae.varCount}, Equations: ${dae.eqCount}`);
