Skip to content

OMJLIR: the backend on its own IR, DAE removed (0.7.0) - #88

Merged
JKRT merged 32 commits into
masterfrom
omjlir
Oct 18, 2026
Merged

JKRT merged 32 commits into
masterfrom
omjlir

Conversation

@JKRT

@JKRT JKRT commented Oct 16, 2026 •

Copy link
Copy Markdown
Member

OMBackend lowers the flat model to its own IR, OMJLIR (src/IR), runs its passes there (src/Backend/passes), and generates the simulation code (src/SimCode) and from it the target code. BDAE, SimulationCode, FrontendUtil and the DAE dependency are removed. translate takes the flat model only; BackendMode without DAE_MODE/ODE_MODE; unused dependencies dropped (CSV, GR, ImmutableList, ListUtil, OMParser, REPL, Tables); license headers on the new sources.

Fixes found by coverage after the switch: semiLinear chains, inlined derivatives through record arguments, fixed starts of equation-defined discretes, dead states, aliases of eliminated representatives, the observed filter and the initialization equations, t0 values from initial algorithm sections only. With arrays kept (Buildings): scalarized elements' types, self-referencing record types, iterator selection on record arrays, scalars subscripted by ones; asserts keep call-bound parameters.

Checked locally: tests 405/405; OM.jl tests pass (6 broken); OMLibraryTesting tests and smoke pass. MSL validate 3.2.3 346-347/425, 4.1.0 436-437/534 (old pipeline 347, 435), backend time about 0.8x. Buildings 13 sample of 93 models: 74 simulate (old 71).

Version 0.7.0. Same branch: OpenModelica/OMLibraryTesting.jl#9, JKRT/OM.jl#68 (merge OM.jl last).

🤖 Generated with Claude Code

JKRT added 26 commits October 16, 2026 14:09
Writes each generated module to <dir>/<model>-<n>.jl: a reference corpus
for comparing code generation before and after a backend change.

Assisted-by: Claude Opus 5.5
src/IR/OMJLIR.jl: an IR modelled on NBackendDAE (variables with kinds, derivative
variables, mutable equations, partitions with slots for adjacency, matching and
strong components), independent of the frontend packages.
src/Backend/lowerFlatModel.jl: NF FlatModel -> OMJLIR.Model, in the previous
backend's equation order. Not used by the pipeline yet.

Assisted-by: Claude Opus 5.5
OMJLIR: a when-branch holds its triggers and whether it is also active at the
initialization and at the end (MLS 8.6), classified once by the lowering;
variables record their origin (the model, or the pass that introduced them).
src/SimCode: the SimCode types, closed and without DAE (not used yet).

Assisted-by: Claude Opus 5.5
A reference keeps its parts (each name with its subscripts) and its flat name;
equality by name. The lowering builds every reference from the frontend's parts
and needs no scope.

Assisted-by: Claude Opus 5.5
src/Backend/passes: smooth removal, record decomposition, algorithm lifting,
deduplication, binding equations, when-condition booleans, discrete lifting,
assert hoisting, clock partitioning, clocked lowering, derivative variables,
ported from the BDAE versions. On 672 of 675 test models the result has the
previous backend's equations and variables (names and order); the others are
the name collisions the SimCode lowering resolves and a solver clock (refused).

OMJLIR: variables carry their reference; WhenKind INITIAL_WHEN for the initial
whens the passes make; foreachRootExp, mapChildren, mapExpTopDown.

Assisted-by: Claude Opus 5.5
Integer variables bound to literals, der() subscripts, higher derivatives, run-time
indices, binding references, if-expressions, record field arrays, record and array
equations, constant reductions. T_CLASS for model and connector parts; array
equations in the previous backend's orientation. 671/675 test models as BDAE after
Causalize (name collisions: SimCode lowering; NestedDerUnsupported: der_x a state).

Assisted-by: Claude Opus 5.5
fromOMJLIR: names (collisions, t, enum subscripts), variable categories and
indices, residuals, when-equations (initial arms, sample triggers, vector
triggers), initial equations, asserts, irreducibles, graph, matching, if-equation
branches. flattenRecordCallSites on the new SimCode. Fixes in the passes: binding
lhs crefs, initial() in lifted algorithm whens, record fields by index, record
assignment of a call. SimCode equal to the old (canonical dump) on 657/664 test
models and 48/49 MSL test models; the rest are intended differences.

Assisted-by: Claude Opus 5.5
Functions lowered from the frontend's list (FunctionVariable with field bindings,
structured external clauses, derivative annotations); SimCode functions with the
records of inputs and outputs flattened (on OMJLIR), smooth() removed, inline
derivatives. Equal to the old SimCode functions on the test and MSL models.

Assisted-by: Claude Opus 5.5
…stant propagation

SIMVAR carries its element type; one substitution for eliminated variables.

Assisted-by: Claude Opus 5.5
…valent equations

Assisted-by: Claude Opus 5.5
Assisted-by: Claude Opus 5.5
translate lowers the flat model to OMJLIR, runs its passes and the SimCode
passes; every code generator (MTK, DE, algorithmic, callbacks, runtime)
reads SimCode expressions, statements and types. SimCode gets a printer,
a pre-codegen check, TYPE_NORETCALL and the initial-section flag.

Assisted-by: Claude Opus 5.5
Modes lowered with the top level's variables and equations, shared and
top variables, explicit transitions. A call returning a record is one
argument (spread by the code generation, evaluated once). Arrays of
record locals by field; the balance check counts states under der();
an assert halfway at its boundary is no failure; runPasses! through.

Assisted-by: Claude Opus 5.5
SimulationCode, FrontendUtil and the BDAE backend deleted; DAE out of
Project.toml. Tests on Modelica examples and OMJLIR/SimCode values; a
test that src reads no DAE. Lowering arguments typed.

Assisted-by: Claude Opus 5.5
Assisted-by: Claude Opus 5.5
CSV, GR, ImmutableList, ListUtil, OMParser, REPL, Tables; the build
script builds OMFrontend (and through it OMParser).

Assisted-by: Claude Opus 5.5
semiLinear chain tuple typing; inlined derivatives by declared inputs;
fixed starts of equation-defined discretes; dead states demoted; scalar
operators for scalarized array operands; aliases re-pointed when a later
pass eliminates their representative; the observed filter keeps what
the initialization equations read.

Assisted-by: Claude Opus 5.5
The initial() arms of when-equations and discrete clusters set lifted
discretes the DAE initialization starts at their start values; seeded,
the if-equations' initial branches disagreed with that start (MSL 4.1.0
IMC_YD).

Assisted-by: Claude Opus 5.5
translate takes the flat model only; BackendMode without DAE_MODE and
ODE_MODE; DAE and unused dependencies dropped.

Assisted-by: Claude Opus 5.5
Connection equalities and references of scalarized kept arrays typed by
the subscripted reference; arithmetic of scalars scalar; a record its
own field's dimension reads lowered once; an iterator on an earlier part
selects among the element variables; a scalar subscripted by ones is the
scalar. Buildings 13 sample.

Assisted-by: Claude Opus 5.5
A parameter bound to a call of a function stays a reference in the
asserts, computed once: inlined, a time-varying assert's crossing called
it at every evaluation (Buildings' weather data read the file, 40 ms).

Assisted-by: Claude Opus 5.5
JKRT added 3 commits October 17, 2026 12:19
MTK path: tuple equations (no unused matching/SCC data), Complex
operations only of Complex's functions, Boolean bindings that latched,
the redundant-equation count, EliminationOptions, world-age reads,
objectid memos. Delay histories per solving task; algorithm ifs lifted
only when assigned once, sample() events of the body; no *THETA rule;
folded variables observed. Refusals for silent drops, typed helpers,
isequal for IR nodes, MTK 11 names.

Assisted-by: Claude Opus 5.5
Calls like Modelica_SIunits_ComplexVoltage_'*'_multiply returning a re/im record
are Complex operations (MSL QuasiStatic machines).

Assisted-by: Claude Opus 5.5
In a square init system, rows that read one unknown and are affine in it are
solved first (MSL Fluid MeasuringTemperature: d, V, m = V*d, pressures; the
simultaneous Newton from the media's start values converged on rounding).

Assisted-by: Claude Opus 5.5
Comment thread src/SimCode/traverse.jl Outdated
traverseChildren(e::Union{ICONST, RCONST, BCONST, SCONST, ENUM_LITERAL, EXP_CREF, DER, PRE, WILD, WHOLE_DIMENSION}, recur::R, arg) where {R} = (e, arg)
function traverseChildren(e::Union{UNARY, LUNARY}, recur::R, arg) where {R}
local (x, a) = recur(e.exp, arg)
return (x === e.exp ? e : typeof(e)(e.op, x), a)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This pattern should be generalized

A node is traversed by its fields in declaration order (IR/Traversal.jl,
traverseFields); each IR declares which field values are children, containers
or leaves. children, mapChildren, foreachExp, anyExp, mapStatementExps,
mapStatement, mapEquation!, foreachRootExp and the statement/equation
substitute are thin wrappers over it instead of per-type methods.

Assisted-by: Claude Opus 5.5
@JKRT
JKRT merged commit 8ae10b2 into master Oct 18, 2026
9 checks passed
@JKRT
JKRT deleted the omjlir branch October 23, 2026 18:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant