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 |