Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 61.9% 301 / 0 / 486
Functions: -% 0 / 1 / 1
Branches: 64.3% 202 / 0 / 314

OMCompiler/Compiler/NBackEnd/Classes/NBackendDAE.mo
Line Branch Exec Source
1 /*
2 * This file is part of OpenModelica.
3 *
4 * Copyright (c) 1998-2026, Open Source Modelica Consortium (OSMC),
5 * c/o Linköpings universitet, Department of Computer and Information Science,
6 * SE-58183 Linköping, Sweden.
7 *
8 * All rights reserved.
9 *
10 * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF AGPL VERSION 3 LICENSE OR
11 * THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.8.
12 * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES
13 * RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GNU AGPL
14 * VERSION 3, ACCORDING TO RECIPIENTS CHOICE.
15 *
16 * The OpenModelica software and the OSMC (Open Source Modelica Consortium)
17 * Public License (OSMC-PL) are obtained from OSMC, either from the above
18 * address, from the URLs:
19 * http://www.openmodelica.org or
20 * https://github.com/OpenModelica/ or
21 * http://www.ida.liu.se/projects/OpenModelica,
22 * and in the OpenModelica distribution.
23 *
24 * GNU AGPL version 3 is obtained from:
25 * https://www.gnu.org/licenses/licenses.html#GPL
26 *
27 * This program is distributed WITHOUT ANY WARRANTY; without
28 * even the implied warranty of MERCHANTABILITY or FITNESS
29 * FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH
30 * IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL.
31 *
32 * See the full OSMC Public License conditions for more details.
33 *
34 */
35
36 encapsulated uniontype NBackendDAE
37 "file: NBackendDAE.mo
38 package: NBackendDAE
39 description: This file contains the main data type for the backend containing
40 all data. It further contains the lower and solve main function.
41 "
42 public
43 import BVariable = NBVariable;
44 import DAE;
45 import BEquation = NBEquation;
46 import NBEquation.{Equation, EquationPointer, EquationPointers, EqData, EquationAttributes, EquationKind, IfEquationBody, Iterator};
47 import NBVariable.{VariablePointer, VariablePointers, VarData};
48 import Evaluation = NBEvaluation;
49 import Events = NBEvents;
50 import Jacobian = NBJacobian;
51 import Partitioning = NBPartitioning;
52 import StrongComponent = NBStrongComponent;
53 import NBStrongComponent.CountCollector;
54 import NBPartition;
55 import NBPartition.Partition;
56
57 protected
58 import PointerWeak;
59 // Old Frontend imports
60 import Absyn.Path;
61
62 // New Frontend imports
63 import Algorithm = NFAlgorithm;
64 import NFBackendExtension.{Annotations, BackendInfo, VariableAttributes, VariableKind};
65 import Binding = NFBinding;
66 import Call = NFCall;
67 import Class = NFClass;
68 import ComplexType = NFComplexType;
69 import ComponentRef = NFComponentRef;
70 import ConvertDAE = NFConvertDAE;
71 import Dimension = NFDimension;
72 import Expression = NFExpression;
73 import FEquation = NFEquation;
74 import FlatModel = NFFlatModel;
75 import NFFunction.Function;
76 import InstNode = NFInstNode.InstNode;
77 import NFInstNode;
78 import MutableWeak;
79 import Prefixes = NFPrefixes;
80 import SimplifyExp = NFSimplifyExp;
81 import Statement = NFStatement;
82 import Subscript = NFSubscript;
83 import Type = NFType;
84 import Variable = NFVariable;
85
86 // New Backend imports
87 import Adjacency = NBAdjacency;
88 import Alias = NBAlias;
89 import BackendDAE = NBackendDAE;
90 import Bindings = NBBindings;
91 import Causalize = NBCausalize;
92 import DAEMode = NBDAEMode;
93 import DetectStates = NBDetectStates;
94 import Differentiate = NBDifferentiate;
95 import FunctionAlias = NBFunctionAlias;
96 import Initialization = NBInitialization;
97 import Inline = NBInline;
98 import NBJacobian.JacobianType;
99 import Module = NBModule;
100 import Resizable = NBResizable;
101 import Solve = NBSolve;
102 import Tearing = NBTearing;
103
104 // Util imports
105 import ClockIndexes;
106 import Error;
107 import ExecStat;
108 import Flags;
109 import StringUtil;
110 import System;
111
112 public
113 record MAIN
114 list<Partition> ode "Partitions for differential-algebraic equations";
115 list<Partition> algebraic "Partitions for algebraic equations";
116 list<Partition> ode_event "Partitions for differential-algebraic event iteration";
117 list<Partition> alg_event "Partitions for algebraic event iteration";
118 list<Partition> clocked "Clocked Partitions";
119 list<Partition> init "Partitions for initialization";
120 Option<list<Partition>> init_0 "Partitions for initialization with lambda = 0 (homotopy)";
121 // add init_1 for lambda = 1? (test for efficency)
122 Option<list<Partition>> dae "Partitions for dae mode";
123 list<StrongComponent> parameters "explicitly solved bindings of the primary parameters in evaluation order, computed before the initialization";
124
125 VarData varData "Variable data";
126 EqData eqData "Equation data";
127
128 Events.EventInfo eventInfo "contains time and state events";
129 Partitioning.ClockedInfo clockedInfo "contains information about clocked partitions";
130 UnorderedMap<Path, Function> funcMap "Function bodies";
131 end MAIN;
132
133 record JACOBIAN
134 String name "unique matrix name";
135 JacobianType jacType "type of jacobian";
136 VarData varData "Variable data";
137 array<StrongComponent> comps "the sorted equations";
138 Adjacency.Matrix sparsity "new sparsity pattern";
139 Boolean isAdjoint "is this an adjoint jacobian?";
140 end JACOBIAN;
141
142 record HESSIAN
143 VarData varData "Variable data";
144 EqData eqData "Equation data";
145 end HESSIAN;
146
147 function toString
148 input BackendDAE bdae;
149 input output String str = "";
150 algorithm
151 str := match bdae
152 local
153 String tmp = "";
154
155 case MAIN()
156 algorithm
157
4/20
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
9 if not Flags.isSet(Flags.BLT_DUMP) or (listEmpty(bdae.ode) and listEmpty(bdae.algebraic) and listEmpty(bdae.ode_event) and listEmpty(bdae.alg_event) and listEmpty(bdae.clocked) and listEmpty(bdae.init) and isNone(bdae.dae)) then
158 ✗ tmp := StringUtil.headline_1("BackendDAE: " + str) + "\n";
159 ✗ tmp := tmp + VarData.toString(bdae.varData, 2) + "\n" +
160 EqData.toString(bdae.eqData, 1);
161 else
162 9 tmp := tmp + Partition.toStringList(bdae.ode, "[ODE] Differential-Algebraic: " + str);
163 9 tmp := tmp + Partition.toStringList(bdae.algebraic, "[ALG] Algebraic: " + str);
164 9 tmp := tmp + Partition.toStringList(bdae.ode_event, "[ODE_EVENT] Event Handling: " + str);
165 9 tmp := tmp + Partition.toStringList(bdae.alg_event, "[ALG_EVENT] Event Handling: " + str);
166 9 tmp := tmp + Partition.toStringList(bdae.clocked, "[CLOCKED] Event Handling: " + str);
167 9 tmp := tmp + Partition.toStringList(bdae.init, "[INI] Initialization: " + str);
168
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 9 times.
9 if isSome(bdae.init_0) then
169 ✗ tmp := tmp + Partition.toStringList(Util.getOption(bdae.init_0), "[INI_0] Initialization Lambda=0: " + str);
170 end if;
171
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 9 times.
9 if isSome(bdae.dae) then
172 ✗ tmp := tmp + Partition.toStringList(Util.getOption(bdae.dae), "[DAE] DAEMode: " + str);
173 end if;
174 end if;
175 9 tmp := tmp + Events.EventInfo.toString(bdae.eventInfo);
176 9 tmp := tmp + Partitioning.ClockedInfo.toString(bdae.clockedInfo);
177 then tmp;
178
179 case JACOBIAN() algorithm
180 4 tmp := StringUtil.headline_1(Jacobian.jacobianTypeString(bdae.jacType) + " Jacobian " + bdae.name + ": " + str) + "\n";
181 4 tmp := tmp + BVariable.VarData.toString(bdae.varData, 1);
182
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 1 time.
✓ Branch 3 taken 3 times.
14 for i in 1:arrayLength(bdae.comps) loop
183 6 tmp := tmp + StrongComponent.toString(bdae.comps[i], i) + "\n";
184 end for;
185 4 tmp := tmp + Adjacency.Matrix.toString(bdae.sparsity);
186 then tmp;
187
188 ✗ case HESSIAN() then StringUtil.headline_1("Hessian: " + str) + "\n" +
189 VarData.toString(bdae.varData, 1) + "\n" +
190 EqData.toString(bdae.eqData, 1);
191 else algorithm
192 ✗ Error.addMessage(Error.INTERNAL_ERROR, {getInstanceName() + " failed."});
193 ✗ then fail();
194 end match;
195 end toString;
196
197 function getVarData
198 input BackendDAE bdae;
199 output VarData varData;
200 algorithm
201 varData := match bdae
202 ✗ case MAIN() then bdae.varData;
203 ✗ case JACOBIAN() then bdae.varData;
204 ✗ case HESSIAN() then bdae.varData;
205 else algorithm
206 ✗ Error.addMessage(Error.INTERNAL_ERROR, {getInstanceName() + " failed."});
207 ✗ then fail();
208 end match;
209 end getVarData;
210
211 function setVarData
212 input output BackendDAE bdae;
213 input VarData varData;
214 algorithm
215 bdae := match bdae
216 188 case MAIN() algorithm bdae.varData := varData; then bdae;
217 ✗ case JACOBIAN() algorithm bdae.varData := varData; then bdae;
218 ✗ case HESSIAN() algorithm bdae.varData := varData; then bdae;
219 else algorithm
220 ✗ Error.addMessage(Error.INTERNAL_ERROR, {getInstanceName() + " failed."});
221 ✗ then fail();
222 end match;
223 end setVarData;
224
225 function getIsAdjoint
226 input BackendDAE bdae;
227 output Boolean isAdjoint;
228 algorithm
229 isAdjoint := match bdae
230 case JACOBIAN(isAdjoint = isAdjoint) then isAdjoint;
231 else algorithm
232 ✗ Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed! Only the record type JACOBIAN() has a jacobian."});
233 ✗ then fail();
234 end match;
235 end getIsAdjoint;
236
237 function getFunctionMap
238 input BackendDAE bdae;
239 output UnorderedMap<Path, Function> funcMap;
240 algorithm
241 funcMap := match bdae
242 188 case MAIN() then bdae.funcMap;
243 else algorithm
244 ✗ Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed! Only the record type MAIN() has a function map."});
245 ✗ then fail();
246 end match;
247 end getFunctionMap;
248
249 function sizes
250 input BackendDAE bdae;
251 output tuple<Integer, Integer> varSizes "scal, arr";
252 output tuple<Integer, Integer> eqnSizes "scal, arr";
253 algorithm
254 (varSizes, eqnSizes) := match bdae
255 ✗ case MAIN() then ((VarData.scalarSize(bdae.varData, true), VarData.size(bdae.varData)), (EqData.scalarSize(bdae.eqData, true), EqData.size(bdae.eqData)));
256 else ((0, 0), (0, 0));
257 end match;
258 end sizes;
259
260 function lower
261 "This function transforms the FlatModel structure to BackendDAE."
262 input FlatModel flatModel;
263 input UnorderedMap<Path, Function> funcMap;
264 output BackendDAE bdae;
265 protected
266 VarData variableData;
267 EqData equationData;
268 Events.EventInfo eventInfo = Events.EventInfo.empty();
269 Partitioning.ClockedInfo clockedInfo = Partitioning.ClockedInfo.new();
270 algorithm
271 193 variableData := lowerVariableData(continuousImplicitDiscretes(flatModel.variables, listAppend(flatModel.equations, flatModel.initialEquations),
272 listAppend(flatModel.algorithms, flatModel.initialAlgorithms)));
273 193 (equationData, variableData) := lowerEquationData(flatModel.equations, flatModel.algorithms, flatModel.initialEquations, flatModel.initialAlgorithms, variableData);
274 193 bdae := MAIN({}, {}, {}, {}, {}, {}, NONE(), NONE(), {}, variableData, equationData, eventInfo, clockedInfo, lowerFunctions(funcMap));
275 end lower;
276
277 function continuousImplicitDiscretes
278 "Real variables assigned in a when-equation are implicitly discrete. The frontend marks them before
279 if-equations with parameter conditions are resolved, so a variable only assigned in a when-equation
280 of an inactive branch would lose its derivative. Those are continuous."
281 input output list<Variable> variables;
282 input list<FEquation> equations;
283 input list<Algorithm> algorithms;
284 protected
285 UnorderedSet<ComponentRef> assigned = UnorderedSet.new(ComponentRef.hash, ComponentRef.isEqual);
286 algorithm
287
2/2
✓ Branch 0 taken 4060 times.
✓ Branch 1 taken 193 times.
4253 for eq in equations loop
288 4060 collectWhenAssigned(eq, false, assigned);
289 end for;
290
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 193 times.
210 for alg in algorithms loop
291 17 collectWhenAssignedStmts(alg.statements, false, assigned);
292 end for;
293
4/4
✓ Branch 0 taken 6373 times.
✓ Branch 1 taken 193 times.
✓ Branch 2 taken 6373 times.
✓ Branch 3 taken 193 times.
6566 variables := list(continuousIfUnassigned(var, assigned) for var in variables);
294 end continuousImplicitDiscretes;
295
296 function continuousIfUnassigned
297 input output Variable var;
298 input UnorderedSet<ComponentRef> assigned;
299 algorithm
300
6/6
✓ Branch 1 taken 6121 times.
✓ Branch 2 taken 252 times.
✓ Branch 5 taken 242 times.
✓ Branch 6 taken 10 times.
✓ Branch 9 taken 9 times.
✓ Branch 10 taken 1 time.
6373 if Variable.variability(var) == NFPrefixes.Variability.IMPLICITLY_DISCRETE and Type.isReal(Type.arrayElementType(var.ty))
301 and not UnorderedSet.contains(ComponentRef.stripSubscriptsAll(var.name), assigned) then
302 1 var := Variable.setVariability(var, NFPrefixes.Variability.CONTINUOUS);
303 end if;
304 end continuousIfUnassigned;
305
306 function collectWhenAssigned
307 input FEquation eq;
308 input Boolean inWhen;
309 input UnorderedSet<ComponentRef> assigned;
310 algorithm
311 () := match eq
312 case FEquation.EQUALITY() guard(inWhen) algorithm
313
2/2
✓ Branch 2 taken 119 times.
✓ Branch 3 taken 118 times.
237 for cref in UnorderedSet.toList(Expression.extractCrefs(eq.lhs)) loop
314 119 UnorderedSet.add(ComponentRef.stripSubscriptsAll(cref), assigned);
315 end for;
316 then ();
317 case FEquation.FOR() algorithm
318
2/2
✓ Branch 1 taken 267 times.
✓ Branch 2 taken 245 times.
512 for e in eq.body loop collectWhenAssigned(e, inWhen, assigned); end for;
319 then ();
320 case FEquation.IF() algorithm
321
2/2
✓ Branch 1 taken 30 times.
✓ Branch 2 taken 22 times.
52 for branch in eq.branches loop collectWhenAssignedBranch(branch, inWhen, assigned); end for;
322 then ();
323 case FEquation.WHEN() algorithm
324
2/2
✓ Branch 1 taken 87 times.
✓ Branch 2 taken 55 times.
142 for branch in eq.branches loop collectWhenAssignedBranch(branch, true, assigned); end for;
325 then ();
326 else ();
327 end match;
328 end collectWhenAssigned;
329
330 function collectWhenAssignedBranch
331 input FEquation.Branch branch;
332 input Boolean inWhen;
333 input UnorderedSet<ComponentRef> assigned;
334 algorithm
335 () := match branch
336 case FEquation.Branch.BRANCH() algorithm
337
2/2
✓ Branch 1 taken 160 times.
✓ Branch 2 taken 117 times.
277 for e in branch.body loop collectWhenAssigned(e, inWhen, assigned); end for;
338 then ();
339 else ();
340 end match;
341 end collectWhenAssignedBranch;
342
343 function collectWhenAssignedStmts
344 input list<Statement> stmts;
345 input Boolean inWhen;
346 input UnorderedSet<ComponentRef> assigned;
347 algorithm
348
2/2
✓ Branch 0 taken 87 times.
✓ Branch 1 taken 50 times.
137 for stmt in stmts loop
349 () := match stmt
350 case Statement.ASSIGNMENT() guard(inWhen) algorithm
351
2/2
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 10 times.
28 for cref in UnorderedSet.toList(Expression.extractCrefs(stmt.lhs)) loop
352 18 UnorderedSet.add(ComponentRef.stripSubscriptsAll(cref), assigned);
353 end for;
354 then ();
355 4 case Statement.FOR() algorithm collectWhenAssignedStmts(stmt.body, inWhen, assigned); then ();
356 ✗ case Statement.WHILE() algorithm collectWhenAssignedStmts(stmt.body, inWhen, assigned); then ();
357 case Statement.IF() algorithm
358
2/2
✓ Branch 2 taken 21 times.
✓ Branch 3 taken 13 times.
34 for branch in stmt.branches loop collectWhenAssignedStmts(Util.tuple22(branch), inWhen, assigned); end for;
359 then ();
360 case Statement.WHEN() algorithm
361
2/2
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 8 times.
16 for branch in stmt.branches loop collectWhenAssignedStmts(Util.tuple22(branch), true, assigned); end for;
362 then ();
363 else ();
364 end match;
365 end for;
366 end collectWhenAssignedStmts;
367
368 function main
369 input output BackendDAE bdae;
370 protected
371 list<tuple<Module.wrapper, String>> preOptModules;
372 list<tuple<Module.wrapper, String>> mainModules;
373 list<tuple<Module.wrapper, String>> postOptModules;
374 list<tuple<String, Real>> preOptClocks;
375 list<tuple<String, Real>> mainClocks;
376 list<tuple<String, Real>> postOptClocks;
377 list<String> followEquations = Flags.getConfigStringList(Flags.DEBUG_FOLLOW_EQUATIONS);
378 Option<UnorderedSet<String>> eq_filter_opt;
379 list<DAE.InlineType> inline_types = {DAE.NORM_INLINE(), DAE.BUILTIN_EARLY_INLINE(), DAE.EARLY_INLINE(), DAE.DEFAULT_INLINE()};
380 NBPartition.Kind kind;
381 algorithm
382 // if we filter dump for equations
383
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 193 times.
193 if listEmpty(followEquations) then
384 eq_filter_opt := NONE();
385 else
386 ✗ print(List.toStringCustom(followEquations, Util.id, "[debugFilterEquations] filtering for equations: ") + "\n\n");
387 ✗ eq_filter_opt := SOME(UnorderedSet.fromList(followEquations, stringHashDjb2, stringEqual));
388 end if;
389
390
2/2
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 192 times.
193 if Flags.getConfigBool(Flags.DAE_MODE) then
391 1 mainModules := {(DAEMode.main, "DAE-Mode")};
392 kind := NBPartition.Kind.DAE;
393 else
394 mainModules := {};
395 kind := NBPartition.Kind.ODE;
396 end if;
397
398 // Pre-Partitioning Modules
399 // (do not change order SIMPLIFY -> ALIAS -> EVENTS -> DETECTSTATES)
400 193 preOptModules := {
401 (Bindings.main, "Bindings"),
402 (function FunctionAlias.main(kind = kind), "FunctionAlias"),
403 (function Inline.main(inline_types = inline_types, init = false), "Early Inline"),
404 (function simplify(init = false), "Simplify 1"),
405 (function Alias.main(kind = kind), "Alias"),
406 (function simplify(init = false), "Simplify 2"), // TODO simplify in Alias only
407 (removeStream, "Remove Stream"),
408 (DetectStates.main, "Detect States"),
409 (Events.main, "Events")
410 };
411
412 // all main modules are always done in ODE mode
413 193 mainModules := listAppend({
414 (function Partitioning.main(kind = NBPartition.Kind.ODE), "Partitioning"),
415 (function Causalize.main(kind = NBPartition.Kind.ODE), "Causalize"),
416 (function Inline.main(inline_types = {DAE.AFTER_INDEX_RED_INLINE()}, init = false), "After Index Reduction Inline"),
417 (Initialization.main, "Initialization")
418 }, mainModules);
419
420 // (do not change order SOLVE -> JACOBIAN)
421 193 postOptModules := {
422 (Evaluation.removeDummies, "Remove Dummies"),
423 (function Tearing.main(kind = kind), "Tearing"),
424 (Partitioning.categorize, "Categorize"),
425 (Solve.main, "Solve"),
426 (function Jacobian.main(kind = kind), "Jacobian"),
427 (Initialization.minimizeHomotopySystem, "Minimize Homotopy System")
428 };
429
430 193 (bdae, preOptClocks) := applyModules(bdae, preOptModules, eq_filter_opt, ClockIndexes.RT_CLOCK_NEW_BACKEND_MODULE);
431 190 (bdae, mainClocks) := applyModules(bdae, mainModules, eq_filter_opt, ClockIndexes.RT_CLOCK_NEW_BACKEND_MODULE);
432 188 (bdae, postOptClocks) := applyModules(bdae, postOptModules, eq_filter_opt, ClockIndexes.RT_CLOCK_NEW_BACKEND_MODULE);
433
434
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 188 times.
188 if Flags.isSet(Flags.DUMP_BACKEND_CLOCKS) then
435 ✗ if not listEmpty(preOptClocks) then
436 ✗ print(StringUtil.headline_4("Pre-Opt Backend Clocks:"));
437 ✗ print(stringDelimitList(list(Module.moduleClockString(clck) for clck in preOptClocks), "\n") + "\n");
438 end if;
439 ✗ if not listEmpty(mainClocks) then
440 ✗ print(StringUtil.headline_4("Main Backend Clocks:"));
441 ✗ print(stringDelimitList(list(Module.moduleClockString(clck) for clck in mainClocks), "\n") + "\n");
442 end if;
443 ✗ if not listEmpty(postOptClocks) then
444 ✗ print(StringUtil.headline_4("Post-Opt Backend Clocks:"));
445 ✗ print(stringDelimitList(list(Module.moduleClockString(clck) for clck in postOptClocks), "\n") + "\n\n");
446 end if;
447 end if;
448
449 188 backenddaeinfo(bdae);
450 end main;
451
452 function applyModules
453 input output BackendDAE bdae;
454 input list<tuple<Module.wrapper, String>> modules;
455 input Option<UnorderedSet<String>> eq_filter_opt;
456 input Integer clock_idx;
457 output list<tuple<String, Real>> module_clocks = {};
458 protected
459 Module.wrapper func;
460 String name, debugStr = "";
461 Real clock_time;
462 tuple<Integer, Integer> varSizes, eqnSizes;
463 algorithm
464 759 System.reportProgress(-1, 4) "PHASE_BACKEND";
465
2/2
✓ Branch 0 taken 4738 times.
✓ Branch 1 taken 754 times.
5492 for module in modules loop
466 4738 Error.checkCancel();
467 4738 (func, name) := module;
468
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4738 times.
4738 if Flags.isSet(Flags.FAILTRACE) then
469 ✗ debugStr := "[failtrace] ........ [" + ClockIndexes.toString(clock_idx) + "] " + name;
470 ✗ debugStr := debugStr + StringUtil.repeat(".", intMax(60 - stringLength(debugStr), 0));
471 end if;
472
1/2
✓ Branch 0 taken 4738 times.
✗ Branch 1 not taken.
4738 if clock_idx <> -1 then
473 4738 System.realtimeClear(clock_idx);
474 4738 System.realtimeTick(clock_idx);
475 try
476
2/2
✓ Branch 0 taken 2846 times.
✓ Branch 1 taken 1892 times.
4738 bdae := func(bdae);
477 else
478
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
5 if Flags.isSet(Flags.FAILTRACE) then
479 ✗ debugStr := debugStr + " failed\n";
480 ✗ print(debugStr);
481 end if;
482 5 fail();
483 end try;
484 4733 clock_time := System.realtimeTock(clock_idx);
485 4733 ExecStat.execStat("[" + ClockIndexes.toString(clock_idx) + "] " + name);
486 4733 module_clocks := (name, clock_time) :: module_clocks;
487
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4733 times.
4733 if Flags.isSet(Flags.FAILTRACE) then
488 ✗ (varSizes, eqnSizes) := sizes(bdae);
489 ✗ debugStr := debugStr + " V(" + intString(Util.tuple21(varSizes)) + "|" + intString(Util.tuple22(varSizes)) +")";
490 ✗ debugStr := debugStr + " E(" + intString(Util.tuple21(eqnSizes)) + "|" + intString(Util.tuple22(eqnSizes)) +") ";
491 ✗ if Util.tuple21(varSizes) <> Util.tuple21(eqnSizes) then
492 ✗ debugStr := debugStr + "XX ";
493 end if;
494 ✗ debugStr := debugStr + StringUtil.repeat(".", intMax(100 - stringLength(debugStr), 0));
495 ✗ debugStr := debugStr + " " + realString(clock_time) + "s\n";
496 ✗ print(debugStr);
497
498 // run lowering diagnostics when failtrace is active
499 ✗ debugLowering(bdae);
500 end if;
501 else
502 ✗ bdae := func(bdae);
503 end if;
504
505
10/12
✓ Branch 1 taken 4733 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 75 times.
✓ Branch 5 taken 4658 times.
✓ Branch 6 taken 6 times.
✓ Branch 7 taken 69 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 6 times.
✓ Branch 11 taken 6 times.
✓ Branch 12 taken 63 times.
✓ Branch 14 taken 3 times.
✓ Branch 15 taken 3 times.
4733 if Flags.isSet(Flags.OPT_DAE_DUMP) or (Flags.isSet(Flags.BLT_DUMP) and (name == "Causalize" or name == "Solve")) then
506 9 print(toString(bdae, "(" + name + ")"));
507 end if;
508
509
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 4733 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4733 times.
4733 if isSome(eq_filter_opt) then
510 ✗ debugFollowEquations(bdae, eq_filter_opt, "(" + name + ")");
511 end if;
512 end for;
513
514 754 module_clocks := listReverse(module_clocks);
515 end applyModules;
516
517 function simplify
518 "ToDo: add simplification for bindings"
519 input output BackendDAE bdae;
520 input Boolean init;
521 protected
522 Pointer<list<Pointer<Variable>>> acc_discrete_states = Pointer.create({});
523 Pointer<list<Pointer<Variable>>> acc_previous = Pointer.create({});
524
525 BEquation.MapFuncEqn func = function Equation.simplify(
526 name = getInstanceName(),
527 indent = "",
528 acc_discrete_states = acc_discrete_states,
529 acc_previous = acc_previous,
530 simplifyExp = function SimplifyExp.simplifyDump(
531 includeScope = true,
532 name = getInstanceName(),
533 indent = ""));
534 algorithm
535 bdae := match bdae
536 local
537 EqData eqData;
538 VarData varData;
539
540 case MAIN(eqData = eqData as BEquation.EQ_DATA_SIM()) algorithm
541
2/2
✓ Branch 0 taken 188 times.
✓ Branch 1 taken 383 times.
571 if init then
542 188 eqData.initials := EquationPointers.map(eqData.initials, func);
543 else
544 383 eqData.equations := EquationPointers.map(eqData.equations, func);
545 end if;
546 571 bdae.eqData := EqData.compress(eqData);
547
548 // update varData with accs obtained from mapping
549 571 bdae.varData := updateDiscreteStates(bdae.varData, acc_discrete_states, acc_previous);
550 then bdae;
551 else bdae;
552 end match;
553 end simplify;
554
555 function removeStream
556 // TODO this does the same as `simplify`
557 // except it calls `SimplifyExp.removeStream`,
558 // maybe we can merge those
559 input output BackendDAE bdae;
560 algorithm
561 bdae := match bdae
562 local
563 EqData eqData;
564 Pointer<list<Pointer<Variable>>> acc_discrete_states = Pointer.create({});
565 Pointer<list<Pointer<Variable>>> acc_previous = Pointer.create({});
566
567 case MAIN(eqData = eqData as BEquation.EQ_DATA_SIM()) algorithm
568 380 eqData.equations := EquationPointers.map(
569 eqData.equations,
570 function Equation.simplify(
571 name = getInstanceName(),
572 indent = "",
573 acc_discrete_states = acc_discrete_states,
574 acc_previous = acc_previous,
575 simplifyExp = SimplifyExp.removeStream));
576 190 bdae.eqData := EqData.compress(eqData);
577
578 // update varData with accs obtained from mapping
579 190 bdae.varData := updateDiscreteStates(bdae.varData, acc_discrete_states, acc_previous);
580 then bdae;
581 else bdae;
582 end match;
583 end removeStream;
584
585 function updateDiscreteStates
586 "update varData with accs obtained from mapping"
587 input output VarData varData;
588 input Pointer<list<Pointer<Variable>>> acc_discrete_states;
589 input Pointer<list<Pointer<Variable>>> acc_previous;
590 algorithm
591 varData := match varData
592 local
593 list<Pointer<Variable>> ads_accessed, ap_accessed;
594
595 case VarData.VAR_DATA_SIM() algorithm
596 761 ads_accessed := Pointer.access(acc_discrete_states);
597 761 ap_accessed := Pointer.access(acc_previous);
598
599
2/4
✓ Branch 0 taken 761 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 761 times.
761 if not (listEmpty(ads_accessed) and listEmpty(ap_accessed)) then
600 ✗ VariablePointers.removeList(ads_accessed, varData.unknowns);
601 ✗ VariablePointers.removeList(ads_accessed, varData.discretes);
602 ✗ VariablePointers.removeList(ads_accessed, varData.discrete_states);
603
604 ✗ VariablePointers.removeList(ap_accessed, varData.previous);
605 ✗ VariablePointers.removeList(ap_accessed, varData.variables);
606
607 ✗ VariablePointers.addList(ads_accessed, varData.parameters);
608 ✗ VariablePointers.addList(ads_accessed, varData.knowns);
609
610 ✗ for v in ads_accessed loop
611 ✗ BVariable.setVarKind(v, VariableKind.PARAMETER(NONE()));
612 ✗ BVariable.removePartner(v, BackendInfo.setVarPre);
613 end for;
614 end if;
615 then varData;
616 else varData;
617 end match;
618 end updateDiscreteStates;
619
620 function getLoopResiduals
621 input BackendDAE bdae;
622 output VariablePointers residuals;
623 algorithm
624 residuals := match bdae
625 local
626 list<Pointer<Variable>> var_lst = {};
627
628 case MAIN() algorithm
629
2/2
✓ Branch 0 taken 66 times.
✓ Branch 1 taken 188 times.
254 for syst in bdae.ode loop
630 66 var_lst := listAppend(Partition.getLoopResiduals(syst), var_lst);
631 end for;
632
2/2
✓ Branch 0 taken 168 times.
✓ Branch 1 taken 188 times.
356 for syst in bdae.algebraic loop
633 168 var_lst := listAppend(Partition.getLoopResiduals(syst), var_lst);
634 end for;
635
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 188 times.
205 for syst in bdae.ode_event loop
636 17 var_lst := listAppend(Partition.getLoopResiduals(syst), var_lst);
637 end for;
638
2/2
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 188 times.
246 for syst in bdae.alg_event loop
639 58 var_lst := listAppend(Partition.getLoopResiduals(syst), var_lst);
640 end for;
641
2/2
✓ Branch 0 taken 174 times.
✓ Branch 1 taken 188 times.
362 for syst in bdae.init loop
642 174 var_lst := listAppend(Partition.getLoopResiduals(syst), var_lst);
643 end for;
644 188 residuals := VariablePointers.fromList(var_lst);
645 then residuals;
646
647 ✗ else VariablePointers.empty();
648 end match;
649 end getLoopResiduals;
650
651 protected
652 function lowerVariableData
653 "Lowers all variables to backend structure.
654 kabdelhak: Splitting up the creation of the variable array and the variable
655 pointer arrays in two steps is slightly less effective, but way more readable
656 and maintainable."
657 input list<Variable> varList;
658 output VarData variableData;
659 protected
660 Variable lowVar;
661 list<Variable> vars;
662 Pointer<Variable> lowVar_ptr, time_ptr, dummy_ptr;
663 list<Pointer<Variable>> unknowns_lst = {}, knowns_lst = {}, initials_lst = {}, auxiliaries_lst = {}, aliasVars_lst = {}, nonTrivialAlias_lst = {};
664 list<Pointer<Variable>> states_lst = {}, derivatives_lst = {}, algebraics_lst = {}, discretes_lst = {}, discrete_states_lst = {}, clocked_states_lst = {}, previous_lst = {}, clocks_lst = {};
665 list<Pointer<Variable>> inputs_lst = {}, resizables_lst = {}, parameters_lst = {}, constants_lst = {}, records_lst = {}, external_objects_lst = {}, artificials_lst = {};
666 VariablePointers variables, unknowns, knowns, initials, auxiliaries, aliasVars, nonTrivialAlias;
667 VariablePointers states, derivatives, algebraics, discretes, discrete_states, clocked_states, previous, clocks;
668 VariablePointers inputs, resizables, parameters, constants, records, external_objects, artificials;
669 UnorderedSet<VariablePointer> binding_iter_set = UnorderedSet.new(BVariable.hash, BVariable.equalName);
670 list<Pointer<Variable>> binding_iter_lst;
671 Boolean scalarized = Flags.isSet(Flags.NF_SCALARIZE);
672 list<Pointer<Variable>> forced_states = {};
673 algorithm
674
4/4
✓ Branch 0 taken 6373 times.
✓ Branch 1 taken 193 times.
✓ Branch 2 taken 6373 times.
✓ Branch 3 taken 193 times.
6566 vars := List.flatten(list(Variable.expandChildren(v) for v in varList));
675
676 // instantiate variable data (with one more space for time variable);
677 193 variables := VariablePointers.empty(listLength(vars) + 1, scalarized);
678
679 // create dummy and time var and add then
680 // needed to make function BVariable.getVarPointer() more universally applicable
681 193 dummy_ptr := Pointer.create(NBVariable.DUMMY_VARIABLE);
682 193 time_ptr := BVariable.createTimeVar();
683 193 variables := VariablePointers.add(dummy_ptr, variables);
684 193 variables := VariablePointers.add(time_ptr, variables);
685 artificials_lst := {dummy_ptr, time_ptr};
686
687 // routine to prepare the lists for pointer arrays
688
2/2
✓ Branch 1 taken 6708 times.
✓ Branch 2 taken 193 times.
6901 for var in listReverse(vars) loop
689 6708 lowVar_ptr := lowerVariable(var);
690 6708 lowVar := Pointer.access(lowVar_ptr);
691 6708 variables := VariablePointers.add(lowVar_ptr, variables);
692 () := match lowVar.backendinfo.varKind
693 local
694 Boolean natural;
695 Pointer<Variable> der_ptr;
696 ComponentRef der_cref;
697
698 // do nothing for size 0 variables, they get removed
699 // Note: record elements need to exist in the full
700 // variable array even if they are of size 0
701 case _ guard(Variable.size(lowVar) == 0) then ();
702
703 case _ guard(Variable.isTopLevelInput(lowVar)) algorithm
704 inputs_lst := lowVar_ptr :: inputs_lst;
705 knowns_lst := lowVar_ptr :: knowns_lst;
706 then ();
707
708 case VariableKind.ALGEBRAIC() algorithm
709 algebraics_lst := lowVar_ptr :: algebraics_lst;
710 unknowns_lst := lowVar_ptr :: unknowns_lst;
711 initials_lst := lowVar_ptr :: initials_lst;
712 then ();
713
714 case VariableKind.STATE(natural = natural) algorithm
715
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if not natural then
716 // Check if a frontend $DER variable already exists in variables.
717 // If so, reuse it (promote to STATE_DER) to avoid a pointer identity
718 // mismatch: equation dep_crefs are lowered to point to the frontend
719 // variable, but makeDerVar would create a separate new pointer.
720 4 (der_cref, der_ptr) := BVariable.makeDerVar(BVariable.getVarName(lowVar_ptr));
721
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
4 if VariablePointers.containsCref(ComponentRef.stripSubscriptsAll(der_cref), variables) then
722 ✗ der_ptr := VariablePointers.getVarSafe(variables, ComponentRef.stripSubscriptsAll(der_cref), NONE());
723 // Promote the existing frontend variable to STATE_DER.
724 // It is already in unknowns_lst/initials_lst from its ALGEBRAIC dispatch;
725 // it will be filtered out of algebraics_lst after the loop.
726 ✗ BVariable.setStateDerKind(der_ptr, lowVar_ptr);
727 else
728 4 variables := VariablePointers.add(der_ptr, variables);
729 4 unknowns_lst := der_ptr :: unknowns_lst;
730 4 initials_lst := der_ptr :: initials_lst;
731 end if;
732 4 BVariable.setStateDerivativeVar(lowVar_ptr, der_ptr);
733 4 derivatives_lst := der_ptr :: derivatives_lst;
734 forced_states := lowVar_ptr :: forced_states;
735 end if;
736
737 states_lst := lowVar_ptr :: states_lst;
738 knowns_lst := lowVar_ptr :: knowns_lst;
739 initials_lst := lowVar_ptr :: initials_lst;
740 then ();
741
742 case VariableKind.STATE_DER() algorithm
743 derivatives_lst := lowVar_ptr :: derivatives_lst;
744 unknowns_lst := lowVar_ptr :: unknowns_lst;
745 initials_lst := lowVar_ptr :: initials_lst;
746 then ();
747
748 case VariableKind.DISCRETE() algorithm
749 discretes_lst := lowVar_ptr :: discretes_lst;
750 unknowns_lst := lowVar_ptr :: unknowns_lst;
751 initials_lst := lowVar_ptr :: initials_lst;
752 then ();
753
754 case VariableKind.PREVIOUS() algorithm
755 previous_lst := lowVar_ptr :: previous_lst;
756 knowns_lst := lowVar_ptr :: knowns_lst;
757 initials_lst := lowVar_ptr :: initials_lst;
758 then ();
759
760 case VariableKind.PARAMETER() algorithm
761
2/2
✓ Branch 1 taken 19 times.
✓ Branch 2 taken 2523 times.
2542 if BVariable.isResizableParameter(lowVar_ptr) then
762 resizables_lst := lowVar_ptr :: resizables_lst;
763 else
764 parameters_lst := lowVar_ptr :: parameters_lst;
765 end if;
766 knowns_lst := lowVar_ptr :: knowns_lst;
767 then ();
768
769 case VariableKind.CONSTANT() algorithm
770 constants_lst := lowVar_ptr :: constants_lst;
771 knowns_lst := lowVar_ptr :: knowns_lst;
772 then ();
773
774 // always consider records known since their attributes are in the unknown section (if they are unknown)
775 case VariableKind.RECORD() algorithm
776 records_lst := lowVar_ptr :: records_lst;
777 knowns_lst := lowVar_ptr :: knowns_lst;
778 then ();
779
780 case VariableKind.CLOCK() algorithm
781 clocks_lst := lowVar_ptr :: clocks_lst;
782 then ();
783
784 // clocked variables are handled just as algebraics, the clocked type is just for partitioning
785 case VariableKind.CLOCKED() algorithm
786 algebraics_lst := lowVar_ptr :: algebraics_lst;
787 unknowns_lst := lowVar_ptr :: unknowns_lst;
788 initials_lst := lowVar_ptr :: initials_lst;
789 then ();
790
791 case VariableKind.EXTOBJ() algorithm
792 3 lowVar_ptr := BVariable.setFixed(lowVar_ptr);
793 external_objects_lst := lowVar_ptr :: external_objects_lst;
794 knowns_lst := lowVar_ptr :: knowns_lst;
795 then ();
796
797 /* other cases should not occur up until now */
798 else algorithm
799 ✗ Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed for " + BVariable.toString(var)});
800 ✗ then fail();
801
802 end match;
803 end for;
804
805 // Remove any variables that were promoted from ALGEBRAIC to STATE_DER during
806 // the dispatch loop (e.g. frontend $DER.x variables for StateSelect.prefer states).
807
5/6
✗ Branch 1 not taken.
✓ Branch 2 taken 3673 times.
✓ Branch 3 taken 3673 times.
✓ Branch 4 taken 193 times.
✓ Branch 5 taken 3673 times.
✓ Branch 6 taken 193 times.
3866 algebraics_lst := list(p for p guard(not BVariable.isStateDerivative(p)) in algebraics_lst);
808
809 // create pointer arrays
810 193 unknowns := VariablePointers.fromList(unknowns_lst, scalarized);
811 193 knowns := VariablePointers.fromList(knowns_lst, scalarized);
812 193 initials := VariablePointers.fromList(initials_lst, scalarized);
813 193 auxiliaries := VariablePointers.fromList(auxiliaries_lst, scalarized);
814 193 aliasVars := VariablePointers.fromList(aliasVars_lst, scalarized);
815 193 nonTrivialAlias := VariablePointers.fromList(nonTrivialAlias_lst, scalarized);
816
817 193 states := VariablePointers.fromList(states_lst, scalarized);
818 193 derivatives := VariablePointers.fromList(derivatives_lst, scalarized);
819 193 algebraics := VariablePointers.fromList(algebraics_lst, scalarized);
820 193 discretes := VariablePointers.fromList(discretes_lst, scalarized);
821 193 discrete_states := VariablePointers.fromList(discrete_states_lst, scalarized);
822 193 clocked_states := VariablePointers.fromList(clocked_states_lst, scalarized);
823 193 previous := VariablePointers.fromList(previous_lst, scalarized);
824 193 clocks := VariablePointers.fromList(clocks_lst, scalarized);
825
826 193 inputs := VariablePointers.fromList(inputs_lst, scalarized);
827 193 resizables := VariablePointers.fromList(resizables_lst, scalarized);
828 193 parameters := VariablePointers.fromList(parameters_lst, scalarized);
829 193 constants := VariablePointers.fromList(constants_lst, scalarized);
830 193 records := VariablePointers.fromList(records_lst, scalarized);
831 193 external_objects:= VariablePointers.fromList(external_objects_lst, scalarized);
832 193 artificials := VariablePointers.fromList(artificials_lst, scalarized);
833
834 /* lower the variable bindings and add binding iterators */
835 193 variables := VariablePointers.map(variables, function collectVariableBindingIterators(variables = variables, set = binding_iter_set));
836 193 binding_iter_lst:= UnorderedSet.toList(binding_iter_set);
837 193 variables := VariablePointers.addList(binding_iter_lst, variables);
838 193 knowns := VariablePointers.addList(binding_iter_lst, knowns);
839 193 artificials := VariablePointers.addList(binding_iter_lst, artificials);
840
841 // lower the component references properly
842 193 variables := VariablePointers.map(variables, function Variable.mapExp(fn = function lowerComponentReferenceExp(variables = variables, complete = true)));
843 193 variables := VariablePointers.map(variables, function Variable.applyToType(func = function Type.applyToDims(func = function lowerDimension(variables = variables, complete = true))));
844
845 /* lower the records to add children */
846 193 records := VariablePointers.mapPtr(records, function lowerRecordChildren(variables = variables));
847
848 /* create variable data */
849 193 variableData := BVariable.VAR_DATA_SIM(Pointer.create(0), variables, unknowns, knowns, initials, auxiliaries, aliasVars, nonTrivialAlias,
850 derivatives, algebraics, discretes, discrete_states, clocked_states, previous, clocks,
851 states, inputs, resizables, parameters, constants, records, external_objects, artificials,
852 UnorderedMap.new<ComponentRef>(ComponentRef.hash, ComponentRef.isEqual));
853
854
2/2
✓ Branch 1 taken 188 times.
✓ Branch 2 taken 5 times.
193 if Flags.isSet(Flags.DUMP_STATESELECTION_INFO) then
855 5 print(StringUtil.headline_4("[stateselection] (" + intString(listLength(forced_states)) + ") Forced states by StateSelect.ALWAYS:"));
856
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 time.
5 if listEmpty(forced_states) then
857 4 print("\t<no states>\n\n");
858 else
859 1 print(List.toString(forced_states, BVariable.pointerToString, List.Style.NEWLINE_TAB) + "\n\n");
860 end if;
861 end if;
862 end lowerVariableData;
863
864 function lowerVariable
865 input Variable var;
866 output Pointer<Variable> var_ptr;
867 protected
868 VariableKind varKind;
869 VariableAttributes attributes;
870 Annotations annotations;
871 algorithm
872 try
873 12387 attributes := VariableAttributes.create(var.typeAttributes, var.ty, var.attributes, var.children, var.comment);
874 12387 annotations := Annotations.create(var.comment, var.attributes);
875
876 // only change varKind if unset (Iterators are set before)
877 var.backendinfo := match var.backendinfo
878 case BackendInfo.BACKEND_INFO(varKind = VariableKind.FRONTEND_DUMMY()) algorithm
879 6834 (varKind, attributes) := lowerVariableKind(var, attributes, var.ty);
880 6834 then BackendInfo.BACKEND_INFO(varKind, attributes, annotations, NONE(), NONE(), NONE(), NONE(), NONE(), NONE());
881 5553 else BackendInfo.setAttributes(var.backendinfo, attributes, annotations);
882 end match;
883
884 // Remove old type attribute information since it has been converted.
885 12387 var.typeAttributes := {};
886
887 // This creates a cyclic dependency, be aware of that!
888 12387 (var_ptr, _) := BVariable.makeVarPtr(var, var.name);
889 else
890 ✗ Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed for " + Variable.toString(var)});
891 ✗ fail();
892 end try;
893 end lowerVariable;
894
895 function lowerVariableKind
896 "ToDo: Merge this part from old backend conversion:
897 /* Consider toplevel inputs as known unless they are protected. Ticket #5591 */
898 false := ConnectUtil.topLevelInput(inComponentRef, inVarDirection, inConnectorType, protection);"
899 input Variable var;
900 output VariableKind varKind;
901 input output VariableAttributes attributes;
902 input Type ty;
903 protected
904 Prefixes.Variability min_var, max_var, variability = Variable.variability(var);
905 function lowerRecordKind
906 input list<Variable> children;
907 output Prefixes.Variability min_var = NFPrefixes.Variability.CONTINUOUS;
908 output Prefixes.Variability max_var = NFPrefixes.Variability.CONSTANT;
909 protected
910 Prefixes.Variability tmp_min_var, tmp_max_var;
911 algorithm
912
2/2
✓ Branch 0 taken 341 times.
✓ Branch 1 taken 156 times.
497 for child in children loop
913 (tmp_min_var, tmp_max_var) := match child.ty
914 2 case Type.COMPLEX() then lowerRecordKind(child.children);
915 1 case Type.ARRAY(elementType = Type.COMPLEX()) then lowerRecordKind(child.children);
916 338 else (Variable.variability(child), Variable.variability(child));
917 end match;
918 341 min_var := if tmp_min_var < min_var then tmp_min_var else min_var;
919 341 max_var := if tmp_max_var > max_var then tmp_max_var else max_var;
920 end for;
921 end lowerRecordKind;
922 algorithm
923 varKind := match(variability, attributes, ty)
924 local
925 Type elemTy;
926 list<Pointer<Variable>> children = {};
927
928 // clocks and clocked signals
929 case (_, _, Type.CLOCK()) then VariableKind.CLOCK();
930 case (_,_ , _) guard(Binding.isClockOrSampleFunction(var.binding)) then VariableKind.CLOCKED();
931
932 // variable -> artificial state if it has stateSelect = StateSelect.always
933 case (NFPrefixes.Variability.CONTINUOUS, VariableAttributes.VAR_ATTR_REAL(stateSelect = SOME(NFBackendExtension.StateSelect.ALWAYS)), _)
934 guard(variability == NFPrefixes.Variability.CONTINUOUS)
935 then VariableKind.STATE(1, NONE(), false);
936
937 // get external object class
938 case (_, _, Type.COMPLEX(complexTy = ComplexType.EXTERNAL_OBJECT()))
939 3 then VariableKind.EXTOBJ(Class.constrainingClassPath(Type.complexNode(ty)));
940 case (_, _, Type.ARRAY(elementType = elemTy as Type.COMPLEX(complexTy = ComplexType.EXTERNAL_OBJECT())))
941 ✗ then VariableKind.EXTOBJ(Class.constrainingClassPath(Type.complexNode(elemTy)));
942
943 // add children pointers for records afterwards, record is considered known if it is of "less" then discrete variability
944 case (_, _, Type.COMPLEX()) algorithm
945 140 (min_var, max_var) := lowerRecordKind(var.children);
946 140 then VariableKind.RECORD({}, min_var, max_var);
947 case (_, _, Type.ARRAY(elementType = Type.COMPLEX())) algorithm
948 13 (min_var, max_var) := lowerRecordKind(var.children);
949 13 then VariableKind.RECORD({}, min_var, max_var);
950
951 case (NFPrefixes.Variability.CONTINUOUS, _, Type.BOOLEAN()) then VariableKind.DISCRETE();
952 case (NFPrefixes.Variability.CONTINUOUS, _, Type.INTEGER()) then VariableKind.DISCRETE();
953 case (NFPrefixes.Variability.CONTINUOUS, _, Type.ENUMERATION()) then VariableKind.DISCRETE();
954 case (NFPrefixes.Variability.CONTINUOUS, _, _) then VariableKind.ALGEBRAIC();
955
956 case (NFPrefixes.Variability.DISCRETE, _, _) then VariableKind.DISCRETE();
957 case (NFPrefixes.Variability.IMPLICITLY_DISCRETE, _, _) then VariableKind.DISCRETE();
958
959 case (NFPrefixes.Variability.PARAMETER, _, _) then VariableKind.PARAMETER(NONE());
960 case (NFPrefixes.Variability.STRUCTURAL_PARAMETER, _, _) then VariableKind.PARAMETER(NONE()); // CONSTANT ?
961 case (NFPrefixes.Variability.NON_STRUCTURAL_PARAMETER, _, _) then VariableKind.PARAMETER(NONE());
962 case (NFPrefixes.Variability.CONSTANT, _, _) then VariableKind.CONSTANT();
963
964 else algorithm
965 ✗ Error.addMessage(Error.INTERNAL_ERROR, {getInstanceName() + " failed."});
966 ✗ then fail();
967 end match;
968
969 // make adjustments to attributes based on variable kind
970 attributes := match varKind
971 2543 case VariableKind.PARAMETER() then VariableAttributes.setFixed(attributes, ty, true, false);
972 else attributes;
973 end match;
974 end lowerVariableKind;
975
976 function collectVariableBindingIterators
977 input output Variable var;
978 input VariablePointers variables;
979 input UnorderedSet<VariablePointer> set;
980 protected
981 Option<Expression> exp_opt;
982 algorithm
983 7098 BackendInfo.map(var.backendinfo, function collectIterators(variables = variables, set = set));
984 7098 exp_opt := Binding.typedExp(var.binding);
985
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 7098 times.
✓ Branch 2 taken 3005 times.
✓ Branch 3 taken 4093 times.
7098 if isSome(exp_opt) then
986 3005 Expression.map(Util.getOption(exp_opt), function collectIterators(variables = variables, set = set));
987 end if;
988 end collectVariableBindingIterators;
989
990 public function lowerRecordChildren
991 input Pointer<Variable> var_ptr;
992 input VariablePointers variables;
993 protected
994 Variable var = Pointer.access(var_ptr);
995 algorithm
996 var := match var
997 local
998 BackendInfo binfo;
999 VariableKind varKind;
1000 case Variable.VARIABLE(backendinfo = binfo as BackendInfo.BACKEND_INFO(varKind = varKind as VariableKind.RECORD())) algorithm
1001
4/4
✓ Branch 0 taken 700 times.
✓ Branch 1 taken 302 times.
✓ Branch 2 taken 700 times.
✓ Branch 3 taken 302 times.
1304 varKind.children := list(PointerWeak.downgrade(
1002 VariablePointers.getVarSafe(variables, ComponentRef.stripSubscriptsAll(child.name), SOME(sourceInfo())))
1003 for child in var.children);
1004 // set parent for all children
1005
4/4
✓ Branch 0 taken 700 times.
✓ Branch 1 taken 302 times.
✓ Branch 2 taken 700 times.
✓ Branch 3 taken 302 times.
1304 varKind.children := list(PointerWeak.downgrade(
1006 BVariable.setParent(PointerWeak.upgrade(child), var_ptr)) for child in varKind.children);
1007 302 binfo.varKind := varKind;
1008 302 var.backendinfo := binfo;
1009 then var;
1010 else var;
1011 end match;
1012 302 Pointer.update(var_ptr, var);
1013 end lowerRecordChildren;
1014
1015 public function lowerUnkownRecordChildren
1016 input Pointer<Variable> var_ptr;
1017 input VariablePointers variables;
1018 algorithm
1019
2/2
✓ Branch 1 taken 21 times.
✓ Branch 2 taken 102 times.
123 if BVariable.isUnknownRecord(var_ptr) then
1020 102 lowerRecordChildren(var_ptr, variables);
1021 end if;
1022 end lowerUnkownRecordChildren;
1023
1024 protected function lowerEquationData
1025 "Lowers all equations to backend structure.
1026 kabdelhak: Splitting up the creation of the equation array and the equation
1027 pointer arrays in two steps is slightly less effective, but way more readable
1028 and maintainable."
1029 input list<FEquation> eq_lst;
1030 input list<Algorithm> al_lst;
1031 input list<FEquation> init_eq_lst;
1032 input list<Algorithm> init_al_lst;
1033 output EqData eqData;
1034 input output VarData varData;
1035 protected
1036 UnorderedSet<VariablePointer> set = UnorderedSet.new(BVariable.hash, BVariable.equalName);
1037 list<Pointer<Equation>> equation_lst, continuous_lst, clocked_lst, discretes_lst, initials_lst, auxiliaries_lst, simulation_lst, removed_lst;
1038 EquationPointers equations;
1039 Pointer<Integer> idx = Pointer.create(0);
1040 algorithm
1041 193 equation_lst := lowerEquationsAndAlgorithms(eq_lst, al_lst, init_eq_lst, init_al_lst);
1042
2/2
✓ Branch 0 taken 4121 times.
✓ Branch 1 taken 193 times.
4314 for eqn_ptr in equation_lst loop
1043 // uniquely name the equation
1044 4121 Equation.createName(eqn_ptr, idx, NBEquation.SIMULATION_STR);
1045 // make all iterators the same and lower them
1046 4121 Equation.renameIterators(eqn_ptr, "$i");
1047 4121 lowerEquationIterators(Pointer.access(eqn_ptr), VarData.getVariables(varData), set);
1048 end for;
1049 193 varData := VarData.addTypedList(varData, UnorderedSet.toList(set), NBVariable.VarData.VarType.ITERATOR);
1050 193 equations := EquationPointers.fromList(equation_lst);
1051 193 equations := lowerComponentReferences(equations, VarData.getVariables(varData));
1052
1053 193 (simulation_lst, continuous_lst, clocked_lst, discretes_lst, initials_lst, auxiliaries_lst, removed_lst) := BEquation.typeList(EquationPointers.toList(equations));
1054
1055 193 equations := EquationPointers.removeList(clocked_lst, equations);
1056 193 equations := Resizable.resize(equations, varData);
1057
1058 193 eqData := BEquation.EQ_DATA_SIM(
1059 uniqueIndex = idx,
1060 equations = equations,
1061 simulation = EquationPointers.fromList(simulation_lst),
1062 continuous = EquationPointers.fromList(continuous_lst),
1063 clocked = EquationPointers.fromList(clocked_lst),
1064 discretes = EquationPointers.fromList(discretes_lst),
1065 initials = EquationPointers.fromList(initials_lst),
1066 auxiliaries = EquationPointers.fromList(auxiliaries_lst),
1067 removed = EquationPointers.fromList(removed_lst)
1068 );
1069
1070 end lowerEquationData;
1071
1072 function lowerEquationsAndAlgorithms
1073 "ToDo! Replace instNode in all Crefs
1074 Converts all frontend equations and algorithms to backend equations."
1075 input list<FEquation> eq_lst;
1076 input list<Algorithm> al_lst;
1077 input list<FEquation> init_eq_lst;
1078 input list<Algorithm> init_al_lst;
1079 output list<Pointer<Equation>> equations = {};
1080 algorithm
1081 // ---------------------------
1082 // convert all equations
1083 // ---------------------------
1084
2/2
✓ Branch 0 taken 3977 times.
✓ Branch 1 taken 193 times.
4170 for eq in eq_lst loop
1085 // returns a list of equations since for and if equations might be split up
1086 3977 equations := listAppend(lowerEquation(eq, false), equations);
1087 end for;
1088
1089 // ---------------------------
1090 // convert all algorithms
1091 // ---------------------------
1092
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 193 times.
204 for alg in al_lst loop
1093 11 equations := lowerAlgorithm(alg, false) :: equations;
1094 end for;
1095
1096 // ---------------------------
1097 // convert all initial equations
1098 // ---------------------------
1099
2/2
✓ Branch 0 taken 83 times.
✓ Branch 1 taken 193 times.
276 for eq in init_eq_lst loop
1100 // returns a list of equations since for and if equations might be split up
1101 83 equations := listAppend(lowerEquation(eq, true), equations);
1102 end for;
1103
1104 // ---------------------------
1105 // convert all initial algorithms
1106 // ---------------------------
1107
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 193 times.
199 for alg in init_al_lst loop
1108 6 equations := lowerAlgorithm(alg, true) :: equations;
1109 end for;
1110 end lowerEquationsAndAlgorithms;
1111
1112 function lowerEquation
1113 input FEquation frontend_equation "Original Frontend equation.";
1114 input Boolean init "True if an initial equation should be created.";
1115 input Boolean in_for = false;
1116 output list<Pointer<Equation>> backend_equations "Resulting Backend equations.";
1117 algorithm
1118 backend_equations := match frontend_equation
1119 local
1120 Expression lhs, rhs;
1121 Type ty;
1122 DAE.ElementSource source;
1123 EquationAttributes attr;
1124 Statement stmt;
1125 Algorithm alg;
1126
1127 case FEquation.EQUALITY(lhs = lhs, rhs = rhs, ty = ty, source = source) algorithm
1128 3767 attr := lowerEquationAttributes(ty, init);
1129 backend_equations := match ty
1130 237 case Type.ARRAY() then {Pointer.create(BEquation.ARRAY_EQUATION(ty, lhs, rhs, source, attr, Type.complexSize(ty)))};
1131 34 case Type.COMPLEX() then {Pointer.create(BEquation.RECORD_EQUATION(ty, lhs, rhs, source, attr, Type.recordFieldCount(ty)))};
1132 1 case Type.TUPLE() then {Pointer.create(BEquation.RECORD_EQUATION(ty, lhs, rhs, source, attr, Type.tupleFieldCount(ty)))};
1133 3495 else {Pointer.create(BEquation.SCALAR_EQUATION(ty, lhs, rhs, source, attr))};
1134 end match;
1135 then backend_equations;
1136
1137 245 case FEquation.FOR() then lowerForEquation(frontend_equation, init);
1138 22 case FEquation.IF() then lowerIfEquation(frontend_equation, init, in_for);
1139 55 case FEquation.WHEN() then lowerWhenEquation(frontend_equation, init);
1140 269 case FEquation.ASSERT() then lowerAssert(frontend_equation, init);
1141
1142 // wrap no return call in algorithm
1143 case FEquation.NORETCALL() algorithm
1144 5 stmt := Statement.NORETCALL(frontend_equation.exp, frontend_equation.source);
1145 5 alg := Algorithm.ALGORITHM({stmt}, {}, {}, NONE(), NFInstNode.NO_SCOPE, frontend_equation.source);
1146 5 alg := Algorithm.setInputsOutputs(alg);
1147 5 then {lowerAlgorithm(alg, init)};
1148
1149 // These have to be called inside a when equation body since they need
1150 // to get passed a condition from surrounding when equation.
1151 case FEquation.TERMINATE() algorithm
1152 ✗ Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed for TERMINATE expression without condition:\n" + FEquation.toString(frontend_equation)});
1153 ✗ then fail();
1154 case FEquation.REINIT() algorithm
1155 ✗ Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed for REINIT expression without condition:\n" + FEquation.toString(frontend_equation)});
1156 ✗ then fail();
1157
1158 else algorithm
1159 ✗ Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed for\n" + FEquation.toString(frontend_equation)});
1160 ✗ then fail();
1161 end match;
1162 end lowerEquation;
1163
1164 function lowerForEquation
1165 input FEquation frontend_equation;
1166 input Boolean init;
1167 output list<Pointer<Equation>> backend_equations = {};
1168 protected
1169 Expression range;
1170 list<Pointer<Equation>> new_body = {};
1171 Equation body_elem;
1172 list<FEquation> body;
1173 list<IfEquationBody> bodies;
1174 ComponentRef iterator;
1175 Boolean isAlgorithm;
1176 Algorithm alg;
1177 Integer size;
1178 algorithm
1179 backend_equations := match frontend_equation
1180 case FEquation.FOR(range = SOME(range)) algorithm
1181
1/2
✓ Branch 1 taken 245 times.
✗ Branch 2 not taken.
245 if not Expression.emptyRange(range) then
1182 // Treat each body equation individually because they can have different equation attributes
1183 // E.g.: DISCRETE, EvalStages
1184 245 iterator := ComponentRef.fromNode(frontend_equation.iterator, Type.INTEGER(), {}, NFComponentRef.Origin.ITERATOR);
1185
2/2
✓ Branch 0 taken 267 times.
✓ Branch 1 taken 245 times.
512 for eq in frontend_equation.body loop
1186
2/2
✓ Branch 1 taken 271 times.
✓ Branch 2 taken 267 times.
538 for body_elem_ptr in lowerEquation(eq, init, true) loop
1187 271 body_elem := Pointer.access(body_elem_ptr);
1188 new_body := match body_elem
1189 case Equation.IF_EQUATION() algorithm
1190 15 bodies := IfEquationBody.split(body_elem.body);
1191
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 15 times.
30 for body in bodies loop
1192 15 new_body := Pointer.create(BEquation.IF_EQUATION(IfEquationBody.size(body), body, body_elem.source, body_elem.attr)) :: new_body;
1193 end for;
1194 then new_body;
1195 else body_elem_ptr :: new_body;
1196 end match;
1197 end for;
1198 end for;
1199
2/2
✓ Branch 0 taken 271 times.
✓ Branch 1 taken 245 times.
516 for body_elem_ptr in new_body loop
1200 271 body_elem := Pointer.access(body_elem_ptr);
1201 271 isAlgorithm := Equation.isAlgorithm(body_elem_ptr);
1202 542 body_elem := BEquation.FOR_EQUATION(
1203 size = Expression.rangeSize(range) * Equation.size(body_elem_ptr),
1204 iter = Iterator.SINGLE(iterator, range, NONE()),
1205 body = {body_elem},
1206 source = frontend_equation.source,
1207 attr = Equation.getAttributes(body_elem)
1208 );
1209
1210 // merge iterators of each for equation instead of having nested loops (for {i in 1:10, j in 1:3, k in 1:5})
1211 271 body_elem := Equation.mergeIterators(body_elem);
1212 // inline if size 1
1213 271 body_elem := Equation.simplify(body_elem);
1214
1215 // if the body was an algorithm (asserts) merge it back to an algorithm
1216
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 264 times.
271 if isAlgorithm then
1217 7 alg := Algorithm.ALGORITHM(Equation.toStatement(body_elem), {}, {}, NONE(), NFInstNode.NO_SCOPE, frontend_equation.source);
1218 7 alg := Algorithm.setInputsOutputs(alg);
1219
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
7 size := sum(ComponentRef.size(out, false) for out in alg.outputs);
1220 7 body_elem := Equation.ALGORITHM(size, alg, alg.source, DAE.EXPAND(), Equation.getAttributes(body_elem));
1221 end if;
1222
1223 271 Pointer.update(body_elem_ptr, body_elem);
1224 backend_equations := body_elem_ptr :: backend_equations;
1225 end for;
1226 else
1227 ✗ if Flags.isSet(Flags.FAILTRACE) then
1228 ✗ Error.addMessage(Error.COMPILER_WARNING,{getInstanceName()
1229 + ": Empty for-equation got removed:\n" + FEquation.toString(frontend_equation)});
1230 end if;
1231 end if;
1232 then backend_equations;
1233
1234 else algorithm
1235 ✗ Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed for\n" + FEquation.toString(frontend_equation)});
1236 ✗ then fail();
1237 end match;
1238 end lowerForEquation;
1239
1240 function lowerIfEquation
1241 input FEquation frontend_equation;
1242 input Boolean init;
1243 input Boolean in_for;
1244 output list<Pointer<Equation>> backend_equations;
1245 algorithm
1246 backend_equations := match frontend_equation
1247 local
1248 list<FEquation.Branch> branches;
1249 DAE.ElementSource source;
1250 IfEquationBody ifEqBody;
1251 list<IfEquationBody> bodies;
1252
1253 case FEquation.IF(branches = branches, source = source) algorithm
1254 try
1255
4/4
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 14 times.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 4 times.
26 ifEqBody := lowerIfEquationBody(branches, init, in_for or FEquation.sizeOf(frontend_equation) == 0);
1256 else
1257 ✗ Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed for:\n" + FEquation.toString(frontend_equation)});
1258 ✗ fail();
1259 end try;
1260
1261
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 22 times.
22 if Expression.isEnd(ifEqBody.condition) then
1262 // if the condition is end from the start, there is no alternatives.
1263 // remove surrounding if structure and return body equations
1264 ✗ backend_equations := ifEqBody.then_eqns;
1265 else
1266 // split up the if equations to parse them indvidually
1267 22 bodies := IfEquationBody.split(ifEqBody);
1268
4/4
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 22 times.
✓ Branch 2 taken 25 times.
✓ Branch 3 taken 22 times.
47 backend_equations := list(IfEquationBody.toEquation(body, source, init) for body in bodies);
1269 end if;
1270 then backend_equations;
1271
1272 else algorithm
1273 ✗ Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed for\n" + FEquation.toString(frontend_equation)});
1274 ✗ then fail();
1275
1276 end match;
1277 end lowerIfEquation;
1278
1279 function lowerIfEquationBody
1280 input list<FEquation.Branch> branches;
1281 input Boolean init;
1282 input Boolean allow_imbalance;
1283 output IfEquationBody ifEq;
1284 algorithm
1285 ifEq := match branches
1286 local
1287 FEquation.Branch branch;
1288 list<FEquation.Branch> rest;
1289 list<Pointer<Equation>> eqns;
1290 Expression condition;
1291 IfEquationBody result;
1292
1293 // lower current branch
1294 case branch::rest
1295 algorithm
1296 30 (eqns, condition) := lowerIfBranch(branch, init);
1297
2/2
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 24 times.
30 if Expression.isTrue(condition) then
1298 // finish recursion when a condition is found to be true because
1299 // following branches can never be reached. Also the last plain else
1300 // case has default Boolean true value in the NF.
1301 6 result := BEquation.IF_EQUATION_BODY(Expression.END(), eqns, NONE());
1302 elseif Expression.isFalse(condition) then
1303 // discard a branch and continue with the rest if a condition is
1304 // found to be false, because it can never be reached.
1305 ✗ result := lowerIfEquationBody(rest, init, allow_imbalance);
1306 else
1307
3/4
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
24 if listEmpty(rest) and (init or allow_imbalance) then
1308 16 result := BEquation.IF_EQUATION_BODY(condition, eqns, NONE());
1309 else
1310 16 result := BEquation.IF_EQUATION_BODY(condition, eqns, SOME(lowerIfEquationBody(rest, init, allow_imbalance)));
1311 end if;
1312 end if;
1313 then result;
1314
1315 // We should never get an empty list here since the last condition has to
1316 // be TRUE. If-Equations have to have a plain else case for consistency!
1317 else algorithm
1318 ✗ Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed due to invalid missing else case."});
1319 ✗ then fail();
1320 end match;
1321 end lowerIfEquationBody;
1322
1323 function lowerIfBranch
1324 input FEquation.Branch branch;
1325 input Boolean init;
1326 output list<Pointer<Equation>> eqns;
1327 output Expression cond;
1328 algorithm
1329 (eqns, cond) := match branch
1330 case FEquation.BRANCH() algorithm
1331
1/2
✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
30 if Expression.isFalse(branch.condition) then
1332 // Save some time by not lowering body if condition is false.
1333 eqns := {};
1334 else
1335 30 eqns := lowerIfBranchBody(branch.body, init);
1336 end if;
1337
1/2
✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
30 then (eqns, branch.condition);
1338
1339 case FEquation.INVALID_BRANCH() algorithm
1340 // what to do with error message from invalid branch? Is that even needed?
1341 ✗ Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed for invalid branch that should not exist outside of frontend."});
1342 ✗ then fail();
1343
1344 else algorithm
1345 ✗ Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed without proper error message."});
1346 ✗ then fail();
1347
1348 end match;
1349 end lowerIfBranch;
1350
1351 function lowerIfBranchBody
1352 input list<FEquation.Equation> body;
1353 input Boolean init;
1354 input output list<Pointer<Equation>> eqns = {};
1355 algorithm
1356 eqns := match body
1357 local
1358 FEquation.Equation elem;
1359 list<FEquation.Equation> rest;
1360 case {} then eqns;
1361 36 case elem::rest then lowerIfBranchBody(rest, init, listAppend(lowerEquation(elem, init), eqns));
1362 end match;
1363 end lowerIfBranchBody;
1364
1365 function lowerAssert
1366 input FEquation frontend_eq;
1367 input Boolean init;
1368 output list<Pointer<Equation>> backend_equations;
1369 algorithm
1370 backend_equations := match frontend_eq
1371 local
1372 Algorithm alg;
1373 Expression cond;
1374
1375 case FEquation.ASSERT() algorithm
1376 269 EquationAttributes.default(EquationKind.EMPTY, init);
1377
2/2
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 261 times.
269 cond := if Expression.isCall(frontend_eq.condition) then frontend_eq.condition else Expression.CALL(Call.makeTypedCall(
1378 fn = NFBuiltinFuncs.NO_EVENT,
1379 args = {frontend_eq.condition},
1380 variability = Expression.variability(frontend_eq.condition),
1381 purity = NFPrefixes.Purity.PURE));
1382 538 alg := Algorithm.ALGORITHM({Statement.ASSERT(cond, frontend_eq.message, frontend_eq.level, frontend_eq.source)},
1383 {}, {}, NONE(), frontend_eq.scope, frontend_eq.source);
1384 269 then {lowerAlgorithm(alg, init)};
1385
1386 else algorithm
1387 ✗ Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed for " + FEquation.toString(frontend_eq)});
1388 ✗ then fail();
1389 end match;
1390 end lowerAssert;
1391
1392 function lowerWhenEquation
1393 input FEquation frontend_eq;
1394 input Boolean init;
1395 output list<Pointer<Equation>> backend_equations;
1396 algorithm
1397 backend_equations := match frontend_eq
1398 local
1399 BEquation.WhenEquationBody whenEqBody;
1400 list<BEquation.WhenEquationBody> bodies;
1401
1402 case FEquation.WHEN() algorithm
1403 // When equation inside initial actually not allowed. Throw error?
1404
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 55 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 55 times.
55 SOME(whenEqBody) := lowerWhenEquationBody(frontend_eq.branches);
1405 55 bodies := BEquation.WhenEquationBody.split(whenEqBody);
1406
6/6
✓ Branch 0 taken 74 times.
✓ Branch 1 taken 55 times.
✓ Branch 2 taken 74 times.
✓ Branch 3 taken 55 times.
✓ Branch 5 taken 6 times.
✓ Branch 6 taken 68 times.
135 then list(Pointer.create(BEquation.WHEN_EQUATION(
1407 size = BEquation.WhenEquationBody.size(b),
1408 body = b,
1409 source = frontend_eq.source,
1410 attr = EquationAttributes.default(if BEquation.WhenEquationBody.size(b) > 0 then EquationKind.DISCRETE else EquationKind.EMPTY, init)
1411 )) for b in bodies);
1412
1413 else algorithm
1414 ✗ Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed for " + FEquation.toString(frontend_eq)});
1415 ✗ then fail();
1416
1417 end match;
1418 end lowerWhenEquation;
1419
1420 function lowerWhenEquationBody
1421 input list<FEquation.Branch> branches;
1422 output Option<BEquation.WhenEquationBody> whenEq;
1423 algorithm
1424 whenEq := match branches
1425 local
1426 FEquation.Branch branch;
1427 list<FEquation.Branch> rest;
1428 list<BEquation.WhenStatement> stmts;
1429 Expression condition;
1430
1431 // End of the line
1432 case {} then NONE();
1433
1434 // lower current branch
1435 case branch::rest
1436 algorithm
1437 87 (stmts, condition) := lowerWhenBranch(branch);
1438 87 then SOME(BEquation.WHEN_EQUATION_BODY(condition, stmts, lowerWhenEquationBody(rest)));
1439
1440 else algorithm
1441 ✗ Error.addMessage(Error.INTERNAL_ERROR, {getInstanceName() + " failed."});
1442 ✗ then fail();
1443
1444 end match;
1445 end lowerWhenEquationBody;
1446
1447 function lowerWhenBranch
1448 input FEquation.Branch branch;
1449 output list<BEquation.WhenStatement> stmts;
1450 output Expression cond;
1451 algorithm
1452 (stmts, cond) := match branch
1453 local
1454 Expression condition;
1455 list<FEquation.Equation> body;
1456 case FEquation.BRANCH(condition = condition, body = body)
1457 // ToDo! Use condition variability here to have proper type of the
1458 // auxiliary that will be created for the condition.
1459 87 then (lowerWhenBranchBody(condition, body), condition);
1460
1461 case FEquation.INVALID_BRANCH() algorithm
1462 // what to do with error message from invalid branch? Is that even needed?
1463 ✗ Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed for invalid branch that should not exist outside of frontend."});
1464 ✗ then fail();
1465
1466 else algorithm
1467 ✗ Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed without proper error message."});
1468 ✗ then fail();
1469
1470 end match;
1471 end lowerWhenBranch;
1472
1473 function lowerWhenBranchBody
1474 input Expression condition;
1475 input list<FEquation.Equation> body;
1476 input output list<BEquation.WhenStatement> stmts = {};
1477 algorithm
1478 stmts := match body
1479 local
1480 FEquation.Equation elem;
1481 list<FEquation.Equation> rest;
1482 124 case elem::rest then lowerWhenBranchBody(condition, rest, lowerWhenBranchStatement(elem, condition, stmts));
1483 else stmts;
1484 end match;
1485 end lowerWhenBranchBody;
1486
1487 function lowerWhenBranchStatement
1488 input FEquation.Equation eq;
1489 input Expression condition;
1490 input output list<BEquation.WhenStatement> stmts;
1491 algorithm
1492 stmts := match eq
1493 local
1494 ComponentRef cref;
1495 Expression rhs;
1496 FEquation.Branch head;
1497 list<FEquation.Branch> tail;
1498 UnorderedMap<ComponentRef, Expression> if_map;
1499
1500 ✗ case FEquation.TERMINATE() then BEquation.TERMINATE(eq.message, eq.source) :: stmts;
1501 ✗ case FEquation.REINIT(cref = Expression.CREF(cref = cref)) then BEquation.REINIT(cref, eq.reinitExp, eq.source) :: stmts;
1502 ✗ case FEquation.NORETCALL() then BEquation.NORETCALL(eq.exp, eq.source) :: stmts;
1503 6 case FEquation.ASSERT() then BEquation.ASSERT(eq.condition, eq.message, eq.level, eq.source) :: stmts;
1504 118 case FEquation.EQUALITY() then BEquation.ASSIGN(eq.lhs, eq.rhs, eq.source) :: stmts;
1505 case FEquation.IF() algorithm
1506 // create a map to collect all individual assignments. traverse in reverse to create innermost first
1507 ✗ if_map := UnorderedMap.new<Expression>(ComponentRef.hash, ComponentRef.isEqual);
1508 ✗ head :: tail := listReverse(eq.branches);
1509 // lower the head to initialize each cref
1510 ✗ lowerWhenBranchIf(head, if_map, true);
1511 // lower all remaining branches and collect the if conditions
1512 ✗ for branch in tail loop
1513 ✗ lowerWhenBranchIf(branch, if_map, false);
1514 end for;
1515 // create all assignments from the collected if-expressions
1516 ✗ for tpl in UnorderedMap.toList(if_map) loop
1517 ✗ (cref, rhs) := tpl;
1518 ✗ stmts := BEquation.ASSIGN(Expression.fromCref(cref), rhs, eq.source) :: stmts;
1519 end for;
1520 then stmts;
1521
1522 /* ToDo! implement proper cases for FOR --> need FOR_ASSIGN?
1523 case FEquation.FOR(iterator = iterator, range = SOME(range), body = body, source = source)
1524 */
1525
1526 else algorithm
1527 ✗ Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed for:\n" + FEquation.toString(eq)});
1528 ✗ then fail();
1529 end match;
1530 end lowerWhenBranchStatement;
1531
1532 function lowerWhenBranchIf
1533 "inlines IF-equations to IF-expressions in WHEN-equations"
1534 input FEquation.Branch branch;
1535 input UnorderedMap<ComponentRef, Expression> if_map;
1536 input Boolean first "allow adding new lhs crefs only if its the first observed branch";
1537 algorithm
1538 () := match branch
1539 local
1540 ComponentRef cref;
1541 Expression exp;
1542
1543 case FEquation.BRANCH() algorithm
1544 ✗ for eq in branch.body loop
1545 () := match eq
1546 case FEquation.EQUALITY(lhs = Expression.CREF(cref = cref)) algorithm
1547 exp := match UnorderedMap.get(cref, if_map)
1548 // we update the saved cref rhs with the branch information
1549 ✗ case SOME(exp) guard(not first) then Expression.IF(Expression.typeOf(exp), branch.condition, eq.rhs, exp);
1550 // we create the first entry for the cref
1551 ✗ case NONE() guard(first) then eq.rhs;
1552 // fail cases
1553 case SOME(_) algorithm
1554 ✗ Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed because branch has multiple assignments for the same cref:\n" + FEquation.Branch.toString(branch, "")});
1555 ✗ then fail();
1556 else algorithm
1557 ✗ Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed because branch equation has an assignment that is missing in other branches:\n" + FEquation.toString(eq)});
1558 ✗ then fail();
1559 end match;
1560 // update the cref -> rhs
1561 ✗ UnorderedMap.add(cref, exp, if_map);
1562 then ();
1563
1564 else algorithm
1565 ✗ Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed for branch equation:\n" + FEquation.toString(eq)});
1566 ✗ then fail();
1567 end match;
1568 end for;
1569 then ();
1570 else algorithm
1571 ✗ Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed for:\n" + FEquation.Branch.toString(branch, "")});
1572 ✗ then fail();
1573 end match;
1574 end lowerWhenBranchIf;
1575
1576 public function lowerAlgorithm
1577 input Algorithm alg;
1578 input Boolean init;
1579 output Pointer<Equation> eq;
1580 protected
1581 Integer size;
1582 list<ComponentRef> outputs;
1583 EquationAttributes attr;
1584 algorithm
1585
4/4
✓ Branch 0 taken 79 times.
✓ Branch 1 taken 322 times.
✓ Branch 2 taken 79 times.
✓ Branch 3 taken 322 times.
401 size := sum(ComponentRef.size(out, false) for out in alg.outputs);
1586
1587
2/2
✓ Branch 0 taken 276 times.
✓ Branch 1 taken 46 times.
322 if listEmpty(alg.outputs) then
1588 276 attr := EquationAttributes.default(EquationKind.EMPTY, init);
1589 elseif Algorithm.isDiscrete(alg) then
1590 20 attr := EquationAttributes.default(EquationKind.DISCRETE, init);
1591 else
1592 26 attr := EquationAttributes.default(EquationKind.CONTINUOUS, init);
1593 end if;
1594 322 eq := Pointer.create(Equation.ALGORITHM(size, alg, alg.source, DAE.EXPAND(), attr));
1595 end lowerAlgorithm;
1596
1597 function lowerEquationAttributes
1598 input Type ty;
1599 input Boolean init;
1600 output EquationAttributes attr;
1601 algorithm
1602
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 3771 times.
3773 if Type.isClock(ty) then
1603 2 attr := EquationAttributes.default(EquationKind.CLOCKED, init, SOME(-1));
1604 elseif Type.isDiscrete(ty) then
1605 211 attr := EquationAttributes.default(EquationKind.DISCRETE, init);
1606 else
1607 3560 attr := EquationAttributes.default(EquationKind.CONTINUOUS, init);
1608 end if;
1609 end lowerEquationAttributes;
1610
1611 protected function lowerComponentReferences
1612 input output EquationPointers equations;
1613 input VariablePointers variables;
1614 algorithm
1615 386 equations := EquationPointers.mapExp(equations, function lowerComponentReferenceExp(variables = variables, complete = true),
1616 SOME(function lowerComponentReference(variables = variables, complete = true)));
1617 end lowerComponentReferences;
1618
1619 public function lowerComponentReferenceExp
1620 input output Expression exp;
1621 input VariablePointers variables;
1622 input Boolean complete = true "if false it will not report lowering errors";
1623 algorithm
1624 exp := match exp
1625 local
1626 Call call;
1627
1628 case Expression.CREF() guard(not ComponentRef.isNameNode(exp.cref))
1629 111489 then Expression.CREF(exp.ty, lowerComponentReference(exp.cref, variables, complete));
1630
1631 case Expression.CALL(call = call as Call.TYPED_ARRAY_CONSTRUCTOR()) algorithm
1632
5/6
✓ Branch 0 taken 2474 times.
✓ Branch 1 taken 2304 times.
✓ Branch 2 taken 2474 times.
✓ Branch 3 taken 2304 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 2474 times.
7082 call.iters := list(Util.applyTuple21(tpl, function lowerInstNode(variables = variables, complete = complete)) for tpl in call.iters);
1633 2304 exp.call := call;
1634 then exp;
1635
1636 case Expression.CALL(call = call as Call.TYPED_REDUCTION()) algorithm
1637
5/6
✓ Branch 0 taken 61 times.
✓ Branch 1 taken 61 times.
✓ Branch 2 taken 61 times.
✓ Branch 3 taken 61 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 61 times.
183 call.iters := list(Util.applyTuple21(tpl, function lowerInstNode(variables = variables, complete = complete)) for tpl in call.iters);
1638 61 exp.call := call;
1639 then exp;
1640
1641 else exp;
1642 end match;
1643
1644 // also lower dimensions in the case of resizable variables
1645
2/2
✓ Branch 0 taken 125 times.
✓ Branch 1 taken 282266 times.
282516 exp := Expression.applyToType(exp, function Type.applyToDims(func = function lowerDimension(variables = variables, complete = complete)));
1646 end lowerComponentReferenceExp;
1647
1648 public function lowerComponentReference
1649 input output ComponentRef cref;
1650 input VariablePointers variables;
1651 input Boolean complete = true "if false it will not report lowering errors";
1652 protected
1653 Pointer<Variable> var;
1654 algorithm
1655 try
1656
1/2
✓ Branch 1 taken 114047 times.
✗ Branch 2 not taken.
114047 if not ComponentRef.isWild(cref) then
1657
2/2
✓ Branch 0 taken 88 times.
✓ Branch 1 taken 113959 times.
114135 var := VariablePointers.getVarSafe(variables, ComponentRef.stripSubscriptsAll(cref), if complete then SOME(sourceInfo()) else NONE());
1658 113971 cref := lowerComponentReferenceInstNode(cref, var);
1659
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 113959 times.
113983 cref := ComponentRef.mapSubscripts(cref, function Subscript.mapExp(func = function lowerComponentReferenceExp(variables = variables, complete = complete)));
1660 end if;
1661 else
1662
1/4
✗ Branch 1 not taken.
✓ Branch 2 taken 76 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
76 if Flags.isSet(Flags.FAILTRACE) and complete then
1663 ✗ Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed for " + ComponentRef.toString(cref)});
1664 end if;
1665 end try;
1666 end lowerComponentReference;
1667
1668 protected function lowerDimension
1669 input output Dimension dim;
1670 input VariablePointers variables;
1671 input Boolean complete;
1672 algorithm
1673 dim := match dim
1674 case Dimension.RESIZABLE() algorithm
1675
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2440 times.
4889 dim.exp := Expression.map(dim.exp, function lowerComponentReferenceExp(variables = variables, complete = complete));
1676 then dim;
1677
1678 else dim;
1679 end match;
1680 end lowerDimension;
1681
1682 function collectIterators
1683 "collects all iterators in expressions and creates variables for them.
1684 in bindings they are only known locally but they still need a respective variable"
1685 input output Expression exp;
1686 input VariablePointers variables;
1687 input UnorderedSet<VariablePointer> set;
1688 algorithm
1689 try
1690 () := match exp
1691 local
1692 Call call;
1693
1694 case Expression.CREF() guard(not (VariablePointers.containsCref(ComponentRef.stripSubscriptsAll(exp.cref), variables)
1695 or ComponentRef.isNameNode(exp.cref) or ComponentRef.isWild(exp.cref))) algorithm
1696 847 UnorderedSet.add(lowerIterator(exp.cref), set);
1697 then ();
1698
1699 case Expression.CALL(call = call as Call.TYPED_ARRAY_CONSTRUCTOR()) algorithm
1700
2/2
✓ Branch 0 taken 2282 times.
✓ Branch 1 taken 2127 times.
4409 for tpl in call.iters loop
1701 2282 collectIterator(Util.tuple21(tpl), variables, set);
1702 end for;
1703 then ();
1704
1705 case Expression.CALL(call = call as Call.TYPED_REDUCTION()) algorithm
1706
2/2
✓ Branch 0 taken 61 times.
✓ Branch 1 taken 61 times.
122 for tpl in call.iters loop
1707 61 collectIterator(Util.tuple21(tpl), variables, set);
1708 end for;
1709 then ();
1710 else ();
1711 end match;
1712 else
1713 ✗ Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed for " + Expression.toString(exp)});
1714 ✗ fail();
1715 end try;
1716 end collectIterators;
1717
1718 function collectIterator
1719 "collects all iterators in bindings and creates variables for them.
1720 in bindings they are only known locally but they still need a respective variable"
1721 input InstNode iterator;
1722 input VariablePointers variables;
1723 input UnorderedSet<VariablePointer> set;
1724 protected
1725 ComponentRef cref;
1726 algorithm
1727 2343 cref := ComponentRef.fromNode(iterator, InstNode.getType(iterator), {}, NFComponentRef.Origin.ITERATOR);
1728 2343 cref := ComponentRef.stripSubscriptsAll(cref);
1729
2/2
✓ Branch 1 taken 152 times.
✓ Branch 2 taken 2191 times.
2343 if not VariablePointers.containsCref(cref, variables) then
1730 2191 UnorderedSet.add(lowerIterator(cref), set);
1731 end if;
1732 end collectIterator;
1733
1734 function lowerInstNode
1735 input output InstNode node;
1736 input VariablePointers variables;
1737 input Boolean complete = true;
1738 protected
1739 ComponentRef cref = ComponentRef.fromNode(node, Type.INTEGER(), {}, NFComponentRef.Origin.ITERATOR);
1740 Pointer<Variable> var;
1741 algorithm
1742 try
1743
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2535 times.
2535 var := VariablePointers.getVarSafe(variables, ComponentRef.stripSubscriptsAll(cref), if complete then SOME(sourceInfo()) else NONE());
1744 2535 node := InstNode.VAR_NODE(InstNode.name(node), PointerWeak.downgrade(var));
1745 else
1746 end try;
1747 end lowerInstNode;
1748
1749 public
1750 function lowerComponentReferenceInstNode
1751 "Adds the pointer to a variable to a component reference. This function needs
1752 to be public since it is needed whenever a component reference is extracted
1753 from a variable."
1754 input output ComponentRef cref;
1755 input Pointer<Variable> var;
1756 algorithm
1757 cref := match cref
1758 local
1759 ComponentRef qual;
1760
1761 case qual as ComponentRef.CREF()
1762 algorithm
1763 282368 qual.node := ComponentRef.storeNode(InstNode.VAR_NODE(
1764 InstNode.name(ComponentRef.node(qual)), PointerWeak.downgrade(var)));
1765 then qual;
1766
1767 else cref;
1768 end match;
1769 end lowerComponentReferenceInstNode;
1770
1771 function lowerEquationIterators
1772 "lowers all iterators that occur in this equation and
1773 add the generated variables to a set"
1774 input output Equation eqn;
1775 input VariablePointers variables;
1776 input UnorderedSet<VariablePointer> set;
1777 protected
1778 Iterator iter = Equation.getForIterator(eqn);
1779 list<ComponentRef> iterators;
1780 algorithm
1781 // get all iterators from the for-loop-frames (if there are any)
1782 31666 (iterators, _) := Iterator.getFrames(iter);
1783
2/2
✓ Branch 0 taken 2551 times.
✓ Branch 1 taken 31666 times.
34217 for iter in iterators loop
1784 2551 UnorderedSet.add(lowerIterator(iter), set);
1785 end for;
1786
1787 // get all iterators from the equation body
1788 31666 Equation.map(eqn, function collectIterators(variables = variables, set = set));
1789 end lowerEquationIterators;
1790
1791 function lowerIterator
1792 input ComponentRef iterator;
1793 output Pointer<Variable> var_ptr = lowerVariable(Variable.fromCref(iterator));
1794 end lowerIterator;
1795
1796 function lowerIteratorCref
1797 input output ComponentRef iterator;
1798 algorithm
1799 10 iterator := BVariable.getVarName(lowerIterator(iterator));
1800 end lowerIteratorCref;
1801
1802 function lowerIteratorExp
1803 input output Expression exp;
1804 algorithm
1805 exp := match exp
1806 case Expression.CREF() algorithm
1807 5 exp.cref := lowerIteratorCref(exp.cref);
1808 then exp;
1809 else exp;
1810 end match;
1811 end lowerIteratorExp;
1812
1813 function lowerFunctions
1814 input output UnorderedMap<Path, Function> funcMap;
1815 algorithm
1816 193 UnorderedMap.apply(funcMap, function Differentiate.resolvePartialDerivatives(funcMap = funcMap));
1817 end lowerFunctions;
1818
1819 function backenddaeinfo
1820 input BackendDAE bdae;
1821 algorithm
1822
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 188 times.
188 if Flags.isSet(Flags.DUMP_BACKENDDAE_INFO) then
1823 () := match bdae
1824 local
1825 VarData varData;
1826 EqData eqData;
1827 String p_ode, p_alg, p_ode_e, p_alg_e, p_clk, p_ini, p_ini_0;
1828 String states, discretes, discrete_states, clocked_states, clocks, inputs;
1829
1830 case MAIN(varData = varData as VarData.VAR_DATA_SIM(), eqData=EqData.EQ_DATA_SIM()) algorithm
1831 // collect partition size info
1832 ✗ p_ode := intString(listLength(bdae.ode));
1833 ✗ p_alg := intString(listLength(bdae.algebraic));
1834 ✗ p_ode_e := intString(listLength(bdae.ode_event));
1835 ✗ p_alg_e := intString(listLength(bdae.alg_event));
1836 p_clk := "0";
1837 ✗ p_ini := intString(listLength(bdae.init));
1838 ✗ p_ini_0 := if isSome(bdae.init_0) then intString(listLength(Util.getOption(bdae.init_0))) else "0";
1839
1840 // collect variable info
1841 ✗ states := intString(VariablePointers.scalarSize(varData.states)) + " (" + intString(VariablePointers.size(varData.states)) + ")";
1842 ✗ discretes := intString(VariablePointers.scalarSize(varData.discretes)) + " (" + intString(VariablePointers.size(varData.discretes)) + ")";
1843 ✗ discrete_states := intString(VariablePointers.scalarSize(varData.discrete_states)) + " (" + intString(VariablePointers.size(varData.discrete_states)) + ")";
1844 ✗ clocked_states := intString(VariablePointers.scalarSize(varData.clocked_states)) + " (" + intString(VariablePointers.size(varData.clocked_states)) + ")";
1845 ✗ clocks := intString(VariablePointers.scalarSize(varData.clocks)) + " (" + intString(VariablePointers.size(varData.clocks)) + ")";
1846 ✗ inputs := intString(VariablePointers.scalarSize(varData.top_level_inputs)) + " (" + intString(VariablePointers.size(varData.top_level_inputs)) + ")";
1847
1848 ✗ if Flags.isSet(Flags.DUMP_STATESELECTION_INFO) then
1849 ✗ states := states + " " + List.toString(VariablePointers.toList(varData.states), BVariable.nameString);
1850 else
1851 ✗ states := states + " ('-d=stateselection' for the list of states)";
1852 end if;
1853
1854 ✗ if Flags.isSet(Flags.DUMP_DISCRETEVARS_INFO) then
1855 ✗ discretes := discretes + " " + List.toString(VariablePointers.toList(varData.discretes), BVariable.nameString);
1856 ✗ clocks := clocks + " " + List.toString(VariablePointers.toList(varData.clocks), BVariable.nameString);
1857 ✗ inputs := inputs + " " + List.toString(VariablePointers.toList(varData.top_level_inputs), BVariable.nameString);
1858 else
1859 ✗ discretes := discretes + " ('-d=discreteinfo' for the list of discrete variables)";
1860 ✗ clocks := clocks + " ('-d=discreteinfo' for the list of clocks variables)";
1861 ✗ inputs := inputs + " ('-d=discreteinfo' for the list of top level inputs)";
1862 end if;
1863
1864 ✗ if Flags.isSet(Flags.DUMP_STATESELECTION_INFO) or Flags.isSet(Flags.DUMP_DISCRETEVARS_INFO) then
1865 ✗ discrete_states := discrete_states + " " + List.toString(VariablePointers.toList(varData.discrete_states), BVariable.nameString);
1866 ✗ clocked_states := clocked_states + " " + List.toString(VariablePointers.toList(varData.clocked_states), BVariable.nameString);
1867 else
1868 ✗ discrete_states := discrete_states + " ('-d=discreteinfo' or '-d=stateselection' for the list of discrete states)";
1869 ✗ clocked_states := clocked_states + " ('-d=discreteinfo' or '-d=stateselection' for the list of clocked states)";
1870 end if;
1871
1872 ✗ Error.addCompilerNotification(
1873 "Partition statistics after passing the back-end:\n"
1874 + " * Number of ODE partitions: ..................... " + p_ode + "\n"
1875 + " * Number of algebraic partitions: ............... " + p_alg + "\n"
1876 + " * Number of ODE event partitions: ............... " + p_ode_e + "\n"
1877 + " * Number of algebraic event partitions: ......... " + p_alg_e + "\n"
1878 + " * Number of clocked partitions: ................. " + p_clk + "\n"
1879 + " * Number of initial partitions: ................. " + p_ini + "\n"
1880 + " * Number of initial(lambda=0) partitions: ....... " + p_ini_0);
1881
1882 ✗ Error.addCompilerNotification(
1883 "Variable statistics after passing the back-end:\n"
1884 + " * Number of states: ............................. " + states + "\n"
1885 + " * Number of discrete states: .................... " + discrete_states + "\n"
1886 + " * Number of clocked states: ..................... " + clocked_states + "\n"
1887 + " * Number of discrete variables: ................. " + discretes + "\n"
1888 + " * Number of clocks: ............................. " + clocks + "\n"
1889 + " * Number of top-level inputs: ................... " + inputs);
1890
1891 // collect strong component info simulation
1892 ✗ strongcomponentinfo("Simulation", {bdae.ode, bdae.algebraic, bdae.ode_event, bdae.alg_event});
1893 // collect strong component info initialization
1894 ✗ strongcomponentinfo("Initialization", {bdae.init});
1895 ✗ if isSome(bdae.init_0) then
1896 ✗ strongcomponentinfo("Initialization (lambda=0)", {Util.getOption(bdae.init_0)});
1897 end if;
1898
1899 then ();
1900 end match;
1901 end if;
1902 end backenddaeinfo;
1903
1904 function strongcomponentinfo
1905 input String phase;
1906 input list<list<Partition>> systems;
1907 protected
1908 CountCollector c = CountCollector.COUNT_COLLECTOR(0,0,0,0,0,0,0,0,0,0,0,0);
1909 Pointer<CountCollector> collector_ptr = Pointer.create(c);
1910 String single_sc, multi_sc, for_sc, alg_sc;
1911 algorithm
1912 ✗ for lst in systems loop
1913 ✗ for system in lst loop
1914 ✗ Partition.mapStrongComponents(system, function StrongComponent.strongComponentInfo(collector_ptr = collector_ptr));
1915 end for;
1916 end for;
1917 ✗ c := Pointer.access(collector_ptr);
1918 ✗ single_sc := intString(c.single_scalar + c.single_array + c.single_record) + " (scalar:" + intString(c.single_scalar) + ", array:" + intString(c.single_array) + ", record:" + intString(c.single_record) + ")";
1919 ✗ multi_sc := intString(c.multi_algorithm + c.multi_when + c.multi_if) + " (algorithm:" + intString(c.multi_algorithm) + ", when:" + intString(c.multi_when) + ", if:" + intString(c.multi_if) + ", tuple:" + intString(c.multi_tpl) + ")";
1920 ✗ for_sc := intString(c.resizable_for + c.generic_for + c.entwined_for) + " (resizable: " + intString(c.resizable_for) + ", generic: " + intString(c.generic_for) + ", entwined:" + intString(c.entwined_for) + ")";
1921 ✗ alg_sc := intString(c.loop_lin + c.loop_nlin) + " (linear: " + intString(c.loop_lin) + ", nonlinear:" + intString(c.loop_nlin) + ")";
1922
1923 ✗ Error.addCompilerNotification(
1924 "[" + phase + "] Strong Component statistics after passing the back-end:\n"
1925 + " * Number of single strong components: ........... " + single_sc + "\n"
1926 + " * Number of multi strong components: ............ " + multi_sc + "\n"
1927 + " * Number of for-loop strong components: ......... " + for_sc + "\n"
1928 + " * Number of algebraic-loop strong components: ... " + alg_sc);
1929 end strongcomponentinfo;
1930
1931 function debugFollowEquations
1932 input BackendDAE bdae;
1933 input Option<UnorderedSet<String>> eq_filter_opt = NONE();
1934 input String str;
1935 algorithm
1936 () := match bdae
1937 local
1938 String tmp = "";
1939
1940 case MAIN() algorithm
1941 ✗ tmp := StringUtil.headline_1("[debugFollowEquations]: " + str) + "\n";
1942 ✗ tmp := tmp + EqData.toString(bdae.eqData, 1, eq_filter_opt);
1943 ✗ print(tmp);
1944 then ();
1945 else ();
1946 end match;
1947 end debugFollowEquations;
1948
1949 function debugLowering
1950 input BackendDAE bdae;
1951 algorithm
1952 () := match bdae
1953 case MAIN() algorithm
1954 ✗ EqData.map(bdae.eqData, checkLoweredCrefEqn);
1955 ✗ VariablePointers.mapPtr(VarData.getVariables(bdae.varData), checkLoweredCrefVar);
1956 then ();
1957 else ();
1958 end match;
1959 end debugLowering;
1960
1961 function checkLoweredCrefVar
1962 input Pointer<Variable> var;
1963 protected
1964 UnorderedSet<ComponentRef> set = UnorderedSet.new(ComponentRef.hash, ComponentRef.isEqual);
1965 algorithm
1966 ✗ BVariable.mapExp(var, function checkLoweredCrefExp(set = set));
1967 ✗ if not UnorderedSet.isEmpty(set) then
1968 ✗ print("[failtrace] the variable:\n" + BVariable.pointerToString(var) + "\n");
1969 ✗ print("[failtrace] has following non-lowered component references: " + List.toString(UnorderedSet.toList(set), ComponentRef.toString) + "\n");
1970 end if;
1971 end checkLoweredCrefVar;
1972
1973 function checkLoweredCrefEqn
1974 input output Equation eqn;
1975 protected
1976 UnorderedSet<ComponentRef> set = UnorderedSet.new(ComponentRef.hash, ComponentRef.isEqual);
1977 algorithm
1978 ✗ Equation.map(eqn, function checkLoweredCrefExp(set = set), SOME(function checkLoweredCref(set = set)));
1979 ✗ if not UnorderedSet.isEmpty(set) then
1980 ✗ print("[failtrace] the equation:\n" + Equation.toString(eqn) + "\n");
1981 ✗ print("[failtrace] has following non-lowered component references: " + List.toString(UnorderedSet.toList(set), ComponentRef.toString) + "\n");
1982 end if;
1983 end checkLoweredCrefEqn;
1984
1985 function checkLoweredCrefExp
1986 input output Expression exp;
1987 input UnorderedSet<ComponentRef> set;
1988 algorithm
1989 () := match exp
1990 case Expression.CREF() algorithm
1991 ✗ checkLoweredCref(exp.cref, set);
1992 then ();
1993 else ();
1994 end match;
1995 end checkLoweredCrefExp;
1996
1997 function checkLoweredCref
1998 input output ComponentRef cref;
1999 input UnorderedSet<ComponentRef> set;
2000 algorithm
2001 () := match cref
2002 case ComponentRef.CREF() guard InstNode.isVar(ComponentRef.node(cref)) then ();
2003 case ComponentRef.CREF() guard InstNode.isName(ComponentRef.node(cref)) then ();
2004 case ComponentRef.CREF() algorithm
2005 ✗ UnorderedSet.add(cref, set);
2006 then ();
2007 else ();
2008 end match;
2009 end checkLoweredCref;
2010
2011 annotation(__OpenModelica_Interface="nbackend");
2012 end NBackendDAE;
2013