ICore Blocks / Features / MATLAB bridge

Two grammars.
One dictionary.
Both directions.

MATLAB's syntax and ICore's each have a grammar of their own, and one shared dictionary translates between them. A .m file comes in as an ICore script, and an ICore script goes out as a .m that runs on its own. A diagram crosses to Simulink and back.

.m → .icore .icore → .m Diagram ⇄ Simulink Diagram → MATLAB code
>>> matlabImportScript /tmp/mbimp/example.m MATLAB → ICore
example.mscripts/example.icore
  1. clc; clear all;→clc clear allsplit
  2. A = [4 -2; 1 3];→A = [4, -2; 1, 3];rewritten
  3. b = [1; 2];→b = [1; 2];as itself
  4. x = A \ b;→x = solve(A, b);rewritten
  5. [Q, R] = qr(A);→[Q, R] = qr(A);as itself
  6. s = sum(A); % column sums→s = sum(A); # column sumscomment kept
  7. t = 0:0.25:1;→t = 0:0.25:1;as itself
  8. Z = zeros(2, 3);→Z = zeros(2, 3);as itself
  9. r = A(1, :);→r = A(1, :);as itself
  10. if det(A) > 0, disp(x), end✕# ICORE-NOT-IMPORTED('if' -- …): if det(A) > 0, disp(x), endrefused
Statements11
Translated10
Refused, reason kept1

This is the manual's own worked import, run against a release build. Most lines cross as themselves: where the two languages already mean the same thing, nothing is translated. The dictionary steps in only where they differ. The one line that could not cross stays in the script as a comment with its reason, so the output still accounts for every line of the .m.

Parity with MATLAB
2,932/ 2,935
console cases whose results agree with MATLAB's own
The dictionary
1,000+
rows, each read forwards for export and backwards for import
Matrix functions
990
in the console, across core MATLAB and eight toolboxes
Simulink blocks
447/ 806
blocks with a Simulink counterpart, bridged both ways
Three bridges

The language, the model, the code.

There are three separate crossings, and each one refuses to carry the others' statements: one for MATLAB code, one for Simulink models, and one for generated code.

Language · .m ⇄ .icore

The MATLAB command bridge

Translates the console's maths language to and from MATLAB, one statement or a whole script at a time. fromMatlab, matlabImportScript and the Import MATLAB button bring code in. toMatlab and matlabExportScript send it out.

Model · diagram ⇄ Simulink

The Simulink bridge

Writes any subsystem, or the whole model, as a Simulink model-construction script, and reads such a script back into an equivalent ICore diagram. Nested subsystems, solver settings and data types cross in both directions.

Code · diagram → .m

MATLAB as an export target

MATLAB is one of the ten code-export targets. It writes a deployable classdef and its testbench, which verification runs in MATLAB itself. See the MATLAB target →

Grammar ⇄ grammar

Parsed as MATLAB. Written as ICore. And back.

MATLAB code is not pattern-matched as raw text. It goes through a lexer that follows MATLAB's own rules, then a parser that uses MATLAB's operator precedence, and only the resulting syntax tree is matched against the dictionary. Export runs the same dictionary forwards. Because every export template is also the import pattern, editing one row changes both directions at once, and a self-check (fromMatlab --selfcheck) confirms that every export can be read back in exactly one way.

IMPORT · fromMatlab · matlabImportScript .m Lexer Parser AST Match .icore quote-aware MATLAB precedence syntax tree most specific wins One dictionary 1,000+ rows · templates with %1…%9 slots read backwards, as a pattern read forwards, as a template .m Template .icore + icp_* adapters appended as local functions EXPORT · toMatlab · matlabExportScript
The apostrophe

Transpose, or the start of a string?

.mB = A'; n = norm(A, 'fro')

In MATLAB, ' after a value is a transpose, and anywhere else it opens a string. The lexer applies that rule itself, so it never has to guess which one it is reading.

Whitespace inside brackets

[4 -2] is two elements

.mA = [4 -2; 1 3];
.icoreA = [4, -2; 1, 3];

[4 -2] is two elements and [4 - 2] is one. The parser follows MATLAB's spacing rule, then writes the elements out with explicit commas.

Operators

Left division, in both directions

.mx = A \ b
.icorex = solve(A, b)

toMatlab writes it back as x = ((A) \ (b)), and the importer reads that form too, with or without the parentheses.

Same name, different meaning

The translation follows the meaning, not the spelling

.mn = norm(A, 'fro') s = sum(A, 2) m = max(A, [], 2)
.icoren = normfro(A) s = sumrows(A) m = maxrows(A)

Where one name means two things, the import writes the console function that does what the MATLAB line meant.

Compositions

Whole expressions, matched as trees

.mn = sum(svd(A)) c = min(max(x, lo), hi) m = abs(fft(x))
.icoren = nucnorm(A) c = clamp(x, lo, hi) m = fftmag(x)

The most specific match wins. sum(svd(A)) is recognised as the nuclear norm, even though a plain sum row would also match it.

Going out

An exported .m needs nothing from ICore

.icoreQ = qrq(A)
.mQ = icp_qrq(A)

If a console function has no MATLAB equivalent, the export uses a small icp_* adapter and appends it to the file as a local function. The script runs in MATLAB as it stands. A line that cannot cross is written as % ICORE-UNSUPPORTED(reason).

The console speaks MATLAB

Most of it doesn't need translating.

The console runs core MATLAB itself: operators and precedence, a:s:b ranges, end inside an index, indexed assignment and deletion, [Q, R] = qr(A), @(x) anonymous functions, if / for / while / switch / try, script-local functions, plot and subplot, readmatrix and writematrix, tic and toc. There are 990 matrix functions in all, split between core MATLAB and the eight toolboxes below:

Control SystemSignal Processing Statistics & Machine LearningSymbolic Math OptimizationSystem Identification AerospaceCurve Fitting

help <name> tells you which toolbox a function comes from, so before you export you know which MATLAB licences the script will need.

Checked against MATLAB, case by case

Each case runs the same computation in the console and in MATLAB and compares the two results within a tolerance. In the last full run, 2,932 of the 2,935 cases agreed.

  • Core MATLAB1,075
  • Statistics625
  • Signal Processing471
  • Control System368 / 369
  • Aerospace177
  • System Identification110
  • Curve Fitting52 / 54
  • Optimization54

Cases that belong to two toolboxes are counted once, under the first. The three that do not yet agree are one zero-pole-gain Bode magnitude and two curve-fitting models (exp2 and fourier1).

Simulink

Models cross as models.

Export → Export as Simulink Script… writes any subsystem, or the whole model, as a MATLAB model-construction script (new_system, add_block, set_param, add_line) that rebuilds the diagram in Simulink. Import → Import as Simulink Script… reads a script like that back into an equivalent ICore diagram, in one undo step.

Nested subsystems cross recursively, with their inports and outports. Output data types cross. Goto/From pairs are folded into wires on the way in. Mapping a block isn't guesswork: each block declares its own Simulink counterpart and how each of its parameters translates. A block without one is reported and skipped, never guessed at.

The import reads the construction script, not the .slx file. For a model you only have as .slx, the import dialog suggests asking Simulink Copilot to write that script for you.

  • RK1 … RK4ode1 … ode4
  • BE1ode1be
  • RK23 · RK45ode23 · ode45
  • TRBDF2ode23tb
  • DiscreteFixedStepDiscrete
  • TR2ode14x, the nearest Simulink solver

Solver settings cross in both directions.

What the coverage looks like

447 of the 806 blocks are bridged. Almost all of the classic Simulink families are covered. Discontinuities, matrix operations, model verification, logic and bit operations, and the increment/decrement family are covered in full. So are 137 of the 174 robotics and aerospace blocks: equations of motion, axes transformations, and the atmosphere, gravity and wind models all map across. Curve fitting, optimization, symbolic maths, system identification and nearly all of machine learning stay ICore-only, because Simulink has no single block for them to be equivalent to. Each block's page in the documentation names its Simulink counterpart, and every documentation build checks that entry against the block's code.

Checked block by block, before every release

Every block bridged to Simulink has a testbench. A seeded random stimulus drives the block, and the same samples run through the Simulink counterpart and through the block's own generated MATLAB. The two outputs are compared sample by sample. A block that drifts fails the release.

Algebra
1e-12
Dynamics
1e-9
Iterative · continuous
1e-6
Integer · boolean
0
exact, bit for bit
Honest edges

What does not cross - and says so.

Anything the bridge refuses, it refuses by name and gives the reason. Nothing is silently approximated.

  • Control-flow blocks on importThe console runs if, for, while and switch, but the import reads one statement at a time, and a block spans several. Those lines are kept as comments that give the reason. A file that starts with function is refused as a whole.
  • Data typesCell arrays, general structs, tables, containers.Map, sparse and N-D arrays, and integer and single types.
  • Files and sessionssave and load of .mat files, .mlx, eval, global and persistent, and input.
  • InteropNo live MATLAB Engine connection, and no Java, Python or MEX calls. The bridge works on text, so MATLAB doesn't need to be installed to import or export.
  • Simulink.slx is not read directly. The 332 blocks without a counterpart are reported, not approximated.

Where to find it

See also: Python and MATLAB, both  ·  The MATLAB target  ·  Code export

Get started

Bring your .m files with you.

Download the application from the customer portal, or read the documentation first - the manual, a page for every block, and the full command reference are public.