OMCompiler/Compiler/BackEnd/SynchronousFeatures.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 package SynchronousFeatures | ||
| 37 | " file: SynchronousFeatures.mo | ||
| 38 | package: SynchronousFeatures | ||
| 39 | description: This package contains functions that belong to synchronous features. | ||
| 40 | - base-clock partitioning | ||
| 41 | - sub-clock partitioning" | ||
| 42 | |||
| 43 | |||
| 44 | public import Absyn; | ||
| 45 | public import BackendDAE; | ||
| 46 | public import DAE; | ||
| 47 | |||
| 48 | protected | ||
| 49 | |||
| 50 | import BackendDAEOptimize; | ||
| 51 | import BackendDAEUtil; | ||
| 52 | import BackendDump; | ||
| 53 | import BackendEquation; | ||
| 54 | import BackendVariable; | ||
| 55 | import ComponentReference; | ||
| 56 | protected import ComponentReferenceBasics; | ||
| 57 | import DAEDump; | ||
| 58 | import DAEUtil; | ||
| 59 | import Error; | ||
| 60 | import ErrorTypes; | ||
| 61 | import Expression; | ||
| 62 | import Flags; | ||
| 63 | import HashTable; | ||
| 64 | import List; | ||
| 65 | import MMath; | ||
| 66 | import StringUtil; | ||
| 67 | import Types; | ||
| 68 | import Util; | ||
| 69 | import MetaModelica.Dangerous.listReverseInPlace; | ||
| 70 | |||
| 71 | |||
| 72 | // ============================================================================= | ||
| 73 | // clock partitioning | ||
| 74 | // | ||
| 75 | // ============================================================================= | ||
| 76 | |||
| 77 | public function clockPartitioning | ||
| 78 | "Finds independent partitions of the equation system by base-clock partitioning and TLM." | ||
| 79 | input BackendDAE.BackendDAE inDAE; | ||
| 80 | output BackendDAE.BackendDAE outDAE; | ||
| 81 | algorithm | ||
| 82 | outDAE := match inDAE | ||
| 83 | local | ||
| 84 | BackendDAE.EqSystem syst; | ||
| 85 | BackendDAE.Shared shared; | ||
| 86 | |||
| 87 | case BackendDAE.DAE({syst}, shared) | ||
| 88 | 1069 | then clockPartitioning1(syst, shared); | |
| 89 | |||
| 90 | // TODO: Improve support for partitioned systems of equations | ||
| 91 | else algorithm | ||
| 92 | ✗ | BackendDAE.DAE({syst}, shared) := BackendDAEOptimize.collapseIndependentBlocks(inDAE); | |
| 93 | ✗ | then clockPartitioning1(syst, shared); | |
| 94 | end match; | ||
| 95 | end clockPartitioning; | ||
| 96 | |||
| 97 | public function synchronousFeatures | ||
| 98 | input BackendDAE.BackendDAE inDAE; | ||
| 99 | output BackendDAE.BackendDAE outDAE; | ||
| 100 | protected | ||
| 101 | BackendDAE.EqSystems systs, contSysts, clockedSysts; | ||
| 102 | BackendDAE.Shared shared; | ||
| 103 | algorithm | ||
| 104 | 1077 | (clockedSysts, contSysts) := List.splitOnTrue(inDAE.eqs, BackendDAEUtil.isClockedSyst); | |
| 105 | |||
| 106 |
2/2✓ Branch 0 taken 39 times.
✓ Branch 1 taken 1038 times.
|
1077 | if not listEmpty(clockedSysts) then |
| 107 | 39 | shared := inDAE.shared; | |
| 108 | |||
| 109 | 39 | (clockedSysts, shared) := treatClockedStates(clockedSysts, shared); | |
| 110 | |||
| 111 | 39 | systs := listAppend(contSysts, clockedSysts); | |
| 112 | 39 | outDAE := BackendDAE.DAE(systs, shared); | |
| 113 | |||
| 114 |
2/2✓ Branch 1 taken 3 times.
✓ Branch 2 taken 36 times.
|
39 | if Flags.isSet(Flags.DUMP_SYNCHRONOUS) then |
| 115 | 3 | print("synchronous features post-phase: synchronousFeatures\n\n"); | |
| 116 | 3 | BackendDump.dumpEqSystems(systs, "clock partitioning"); | |
| 117 | 3 | BackendDump.dumpBasePartitions(shared.partitionsInfo.basePartitions, "Base clocks"); | |
| 118 | 3 | BackendDump.dumpSubPartitions(shared.partitionsInfo.subPartitions, "Sub clocks"); | |
| 119 | end if; | ||
| 120 | else | ||
| 121 | outDAE := inDAE; | ||
| 122 | end if; | ||
| 123 | end synchronousFeatures; | ||
| 124 | |||
| 125 | public function contPartitioning | ||
| 126 | input BackendDAE.BackendDAE inDAE; | ||
| 127 | output BackendDAE.BackendDAE outDAE; | ||
| 128 | protected | ||
| 129 | BackendDAE.EqSystems systs, clockedSysts, clockedSysts1; | ||
| 130 | BackendDAE.Shared shared; | ||
| 131 | BackendDAE.EqSystem syst; | ||
| 132 | list<BackendDAE.Equation> unpartRemEqs; | ||
| 133 | algorithm | ||
| 134 | 219 | (clockedSysts, systs) := List.splitOnTrue(inDAE.eqs, BackendDAEUtil.isClockedSyst); | |
| 135 | 219 | shared := inDAE.shared; | |
| 136 | |||
| 137 |
1/2✓ Branch 0 taken 219 times.
✗ Branch 1 not taken.
|
219 | if not listEmpty(systs) then |
| 138 |
2/4✗ Branch 2 not taken.
✓ Branch 3 taken 219 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 219 times.
|
219 | BackendDAE.DAE({syst}, shared) := BackendDAEOptimize.collapseIndependentBlocks(BackendDAE.DAE(systs, shared)); |
| 139 | 219 | (systs, clockedSysts1, unpartRemEqs) := baseClockPartitioning(syst, shared); | |
| 140 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 219 times.
|
219 | assert(listEmpty(clockedSysts1), "Get clocked system in SynchronousFeatures.addContVarsEqs"); |
| 141 | 219 | shared.removedEqs := BackendEquation.addList(unpartRemEqs, shared.removedEqs); | |
| 142 | end if; | ||
| 143 | |||
| 144 | 219 | outDAE := BackendDAE.DAE(listAppend(systs, clockedSysts), shared); | |
| 145 | end contPartitioning; | ||
| 146 | |||
| 147 | protected function clockPartitioning1 | ||
| 148 | input BackendDAE.EqSystem inSyst; | ||
| 149 | input BackendDAE.Shared inShared; | ||
| 150 | output BackendDAE.BackendDAE outDAE; | ||
| 151 | protected | ||
| 152 | BackendDAE.EqSystem syst; | ||
| 153 | list<BackendDAE.EqSystem> contSysts, clockedSysts; | ||
| 154 | BackendDAE.Shared shared = inShared; | ||
| 155 | list<BackendDAE.EqSystem> systs; | ||
| 156 | list<DAE.ComponentRef> holdComps; | ||
| 157 | list<BackendDAE.Equation> unpartRemEqs; | ||
| 158 | algorithm | ||
| 159 | 1069 | syst := substitutePartitionOpExps(inSyst, inShared); | |
| 160 | 1069 | (contSysts, clockedSysts, unpartRemEqs) := baseClockPartitioning(syst, shared); | |
| 161 | |||
| 162 | 1068 | (contSysts, holdComps) := removeHoldExpsSyst(contSysts); | |
| 163 | |||
| 164 | 1068 | (clockedSysts, shared) := subClockPartitioning1(clockedSysts, shared, holdComps); | |
| 165 | |||
| 166 | 1068 | unpartRemEqs := createBoolClockWhenClauses(shared, unpartRemEqs); | |
| 167 | 1068 | shared.removedEqs := BackendEquation.addList(unpartRemEqs, shared.removedEqs); | |
| 168 | |||
| 169 | 1068 | systs := listAppend(contSysts, clockedSysts); | |
| 170 | 1068 | outDAE := BackendDAE.DAE(systs, shared); | |
| 171 | |||
| 172 |
2/2✓ Branch 0 taken 1029 times.
✓ Branch 1 taken 39 times.
|
1068 | if not listEmpty(clockedSysts) then |
| 173 |
2/2✓ Branch 1 taken 36 times.
✓ Branch 2 taken 3 times.
|
39 | if Flags.isSet(Flags.DUMP_SYNCHRONOUS) then |
| 174 | 3 | print("synchronous features pre-phase: synchronousFeatures\n\n"); | |
| 175 | 3 | BackendDump.dumpEqSystems(systs, "clock partitioning"); | |
| 176 | 3 | BackendDump.dumpBasePartitions(shared.partitionsInfo.basePartitions, "Base clocks"); | |
| 177 | 3 | BackendDump.dumpSubPartitions(shared.partitionsInfo.subPartitions, "Sub clocks"); | |
| 178 | end if; | ||
| 179 | end if; | ||
| 180 | end clockPartitioning1; | ||
| 181 | |||
| 182 | protected function createBoolClockWhenClauses | ||
| 183 | input BackendDAE.Shared inShared; | ||
| 184 | input list<BackendDAE.Equation> inRemovedEqs; | ||
| 185 | output list<BackendDAE.Equation> outRemovedEqs = inRemovedEqs; | ||
| 186 | protected | ||
| 187 | BackendDAE.BasePartition basePartition; | ||
| 188 | algorithm | ||
| 189 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 1068 times.
✓ Branch 2 taken 1029 times.
✓ Branch 3 taken 39 times.
|
2182 | for i in 1:arrayLength(inShared.partitionsInfo.basePartitions) loop |
| 190 | 46 | basePartition := inShared.partitionsInfo.basePartitions[i]; | |
| 191 | outRemovedEqs := match basePartition.clock | ||
| 192 | local | ||
| 193 | DAE.Exp c, e; | ||
| 194 | BackendDAE.WhenEquation whenEq; | ||
| 195 | BackendDAE.Equation eq; | ||
| 196 | case DAE.EVENT_CLOCK(c, _) | ||
| 197 | algorithm | ||
| 198 | 22 | e := DAE.CALL(Absyn.IDENT("$_clkfire"), {DAE.ICONST(i)}, DAE.callAttrBuiltinOther); | |
| 199 | 22 | whenEq := BackendDAE.WHEN_STMTS(c, {BackendDAE.NORETCALL(e, DAE.emptyElementSource)}, NONE()); | |
| 200 | 11 | eq := BackendDAE.WHEN_EQUATION(0, whenEq, DAE.emptyElementSource, BackendDAE.EQ_ATTR_DEFAULT_DYNAMIC); | |
| 201 | then eq::outRemovedEqs; | ||
| 202 | else outRemovedEqs; | ||
| 203 | end match; | ||
| 204 | end for; | ||
| 205 | end createBoolClockWhenClauses; | ||
| 206 | |||
| 207 | public function getBoolClockWhenClauses | ||
| 208 | "Collect event-clock when equations" | ||
| 209 | input output BackendDAE.Equation eq; | ||
| 210 | input output list<BackendDAE.Equation> eqLst; | ||
| 211 | algorithm | ||
| 212 |
2/2✓ Branch 1 taken 695 times.
✓ Branch 2 taken 11 times.
|
706 | if hasBoolClockWhenClause(eq) then |
| 213 | eqLst := eq::eqLst; | ||
| 214 | end if; | ||
| 215 | end getBoolClockWhenClauses; | ||
| 216 | |||
| 217 | protected function hasBoolClockWhenClause | ||
| 218 | "Returns true if equation is a event-clock when equation with a $_clkfire call." | ||
| 219 | input BackendDAE.Equation eqn; | ||
| 220 | output Boolean hasBool=false; | ||
| 221 | algorithm | ||
| 222 | () := match eqn | ||
| 223 | case BackendDAE.WHEN_EQUATION( | ||
| 224 | size = 0, | ||
| 225 | whenEquation = BackendDAE.WHEN_STMTS( | ||
| 226 | whenStmtLst={BackendDAE.NORETCALL( | ||
| 227 | exp=DAE.CALL(path=Absyn.IDENT("$_clkfire")))})) | ||
| 228 | algorithm | ||
| 229 | hasBool := true; | ||
| 230 | then (); | ||
| 231 | else (); | ||
| 232 | end match; | ||
| 233 | end hasBoolClockWhenClause; | ||
| 234 | |||
| 235 | protected function treatClockedStates | ||
| 236 | "Convert continuous equations in clocked partitions to clocked equations | ||
| 237 | and call markClockedStates. author: rfranke" | ||
| 238 | input list<BackendDAE.EqSystem> inSysts; | ||
| 239 | input BackendDAE.Shared inShared; | ||
| 240 | output list<BackendDAE.EqSystem> outSysts = {}; | ||
| 241 | output BackendDAE.Shared shared = inShared; | ||
| 242 | algorithm | ||
| 243 |
4/4✓ Branch 0 taken 61 times.
✓ Branch 1 taken 39 times.
✓ Branch 2 taken 61 times.
✓ Branch 3 taken 39 times.
|
100 | outSysts := list( |
| 244 | match syst | ||
| 245 | local | ||
| 246 | BackendDAE.EquationArray eqs; | ||
| 247 | Integer idx; | ||
| 248 | BackendDAE.SubPartition subPartition; | ||
| 249 | String solverMethod; | ||
| 250 | list<BackendDAE.Equation> lstEqs = {}; | ||
| 251 | BackendDAE.Equation eq; | ||
| 252 | list<DAE.ComponentRef> derVars = {}; | ||
| 253 | BackendDAE.Var var; | ||
| 254 | DAE.Exp exp, exp2; | ||
| 255 | DAE.Type ty; | ||
| 256 | case BackendDAE.EQSYSTEM(orderedEqs = eqs) | ||
| 257 | algorithm | ||
| 258 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 61 times.
|
61 | BackendDAE.CLOCKED_PARTITION(idx) := syst.partitionKind; |
| 259 | 61 | subPartition := shared.partitionsInfo.subPartitions[idx]; | |
| 260 | 61 | solverMethod := BackendDump.optionString(getSubClockSolverOpt(subPartition.clock)); | |
| 261 | // check solverMethod | ||
| 262 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 61 times.
|
61 | if StringUtil.startsWith(solverMethod, "Explicit") then |
| 263 | ✗ | if solverMethod <> "ExplicitEuler" then | |
| 264 | ✗ | Error.addMessage(Error.CLOCK_SOLVERMETHOD, {"ExplicitEuler", solverMethod}); | |
| 265 | solverMethod := "ExplicitEuler"; | ||
| 266 | end if; | ||
| 267 | elseif stringLength(solverMethod) > 0 and solverMethod <> "ImplicitEuler" | ||
| 268 | and solverMethod <> "SemiImplicitEuler" and solverMethod <> "ImplicitTrapezoid" then | ||
| 269 | ✗ | Error.addMessage(Error.CLOCK_SOLVERMETHOD, {"ImplicitEuler", solverMethod}); | |
| 270 | solverMethod := "ImplicitEuler"; | ||
| 271 | end if; | ||
| 272 | // replace der(x) with $DER.x and collect derVars x | ||
| 273 |
1/2✓ Branch 1 taken 61 times.
✗ Branch 2 not taken.
|
586 | for i in 1:BackendEquation.getNumberOfEquations(eqs) loop |
| 274 | 525 | eq := BackendEquation.get(eqs, i); | |
| 275 | 525 | (eq, (derVars, _)) := BackendEquation.traverseExpsOfEquation(eq, getDerVars1, (derVars, BackendEquation.getForEquationIterIdent(eq))); | |
| 276 | lstEqs := eq :: lstEqs; | ||
| 277 | end for; | ||
| 278 | // add all $DER.x as additional variables | ||
| 279 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 61 times.
|
65 | for derVar in derVars loop |
| 280 | 4 | var := listGet(BackendVariable.getVar(derVar, syst.orderedVars), 1); | |
| 281 | 4 | var := BackendDAE.VAR(ComponentReference.crefPrefixDer(derVar), BackendDAE.VARIABLE(), DAE.BIDIR(), DAE.NON_PARALLEL(), var.varType, NONE(), NONE(), var.arryDim, DAE.emptyElementSource, NONE(), NONE(), NONE(), NONE(), DAE.NON_CONNECTOR(), DAE.NOT_INNER_OUTER(), false, false, false); | |
| 282 | 4 | syst.orderedVars := BackendVariable.addVar(var, syst.orderedVars); | |
| 283 | end for; | ||
| 284 | // add defining equations for $DER.x, depending on solverMethod | ||
| 285 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 61 times.
|
65 | for derVar in derVars loop |
| 286 | 4 | var := listGet(BackendVariable.getVar(derVar, syst.orderedVars), 1); | |
| 287 | 4 | ty := var.varType; | |
| 288 | // add forIter subscript and use element type if var is array | ||
| 289 | derVar := match var.varType | ||
| 290 | case DAE.T_ARRAY(ty = ty) | ||
| 291 | 1 | then ComponentReference.crefApplySubs(derVar, {DAE.INDEX(DAE.CREF(DAE.CREF_IDENT("i", DAE.T_INTEGER_DEFAULT, {}), DAE.T_INTEGER_DEFAULT))}); | |
| 292 | else derVar; | ||
| 293 | end match; | ||
| 294 | 8 | exp := DAE.CALL(Absyn.IDENT(name = "der"), {DAE.CREF(derVar, ty)}, DAE.callAttrBuiltinImpureReal); | |
| 295 | 4 | exp := substituteFiniteDifference(exp); | |
| 296 | 4 | exp2 := DAE.CREF(ComponentReference.crefPrefixDer(derVar), ty); | |
| 297 |
3/4✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 time.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
|
4 | if solverMethod == "ExplicitEuler" then |
| 298 | // introduce states to delay derivatives; see MLS 3.3, section 16.8.2 Solver Methods | ||
| 299 | ✗ | exp2 := DAE.CALL(Absyn.IDENT(name = "previous"), {exp2}, DAE.callAttrBuiltinImpureReal); | |
| 300 | elseif solverMethod == "ImplicitTrapezoid" then | ||
| 301 | // evaluate derivatives at beginning and end of interval; see MLS 3.3, section 16.8.2 Solver Methods | ||
| 302 | ✗ | exp2 := DAE.BINARY(exp2, DAE.ADD(DAE.T_REAL_DEFAULT), | |
| 303 | DAE.CALL(Absyn.IDENT(name = "previous"), {exp2}, DAE.callAttrBuiltinImpureReal)); | ||
| 304 | ✗ | exp2 := DAE.BINARY(DAE.RCONST(0.5), DAE.MUL(DAE.T_REAL_DEFAULT), exp2); | |
| 305 | end if; | ||
| 306 | // clocked continuous states are fixed at first tick | ||
| 307 | 4 | exp2 := DAE.IFEXP(DAE.CALL(Absyn.IDENT(name = "firstTick"), {}, DAE.callAttrBuiltinImpureBool), | |
| 308 | DAE.RCONST(0), exp2); | ||
| 309 | // create for-equation or regular equation | ||
| 310 | eq := match var.varType | ||
| 311 | local | ||
| 312 | DAE.Dimension dim; | ||
| 313 | case DAE.T_ARRAY(dims = {dim}) | ||
| 314 | 1 | then BackendDAE.FOR_EQUATION( | |
| 315 | DAE.CREF(DAE.CREF_IDENT("i", DAE.T_INTEGER_DEFAULT, {}), DAE.T_INTEGER_DEFAULT), | ||
| 316 | DAE.ICONST(1), DAEUtil.dimExp(dim), | ||
| 317 | BackendDAE.EQUATION(exp, exp2, var.source, BackendDAE.EQ_ATTR_DEFAULT_DYNAMIC), | ||
| 318 | var.source, BackendDAE.EQ_ATTR_DEFAULT_DYNAMIC); | ||
| 319 | 3 | else BackendDAE.EQUATION(exp, exp2, var.source, BackendDAE.EQ_ATTR_DEFAULT_DYNAMIC); | |
| 320 | end match; | ||
| 321 | lstEqs := eq :: lstEqs; | ||
| 322 | end for; | ||
| 323 | 61 | syst.orderedEqs := BackendEquation.listEquation(listReverse(lstEqs)); | |
| 324 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 61 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
61 | if solverMethod == "SemiImplicitEuler" then |
| 325 | // access previous values of clocked continuous states | ||
| 326 | ✗ | for i in 1:BackendEquation.getNumberOfEquations(eqs) loop | |
| 327 | ✗ | eq := BackendEquation.get(eqs, i); | |
| 328 | ✗ | (eq, _) := BackendEquation.traverseExpsOfEquation(eq, shiftDerVars1, derVars); | |
| 329 | ✗ | eqs := BackendEquation.setAtIndex(eqs, i, eq); | |
| 330 | end for; | ||
| 331 | end if; | ||
| 332 | 61 | shared := markClockedStates(syst, shared, derVars); | |
| 333 | 61 | then BackendDAEUtil.clearEqSyst(syst); | |
| 334 | end match | ||
| 335 | for syst in inSysts); | ||
| 336 | end treatClockedStates; | ||
| 337 | |||
| 338 | protected function getDerVars1 "helper to getDerVars" | ||
| 339 | input DAE.Exp inExp; | ||
| 340 | input tuple<list<DAE.ComponentRef>, Option<DAE.Ident>> inDerVars; | ||
| 341 | output DAE.Exp outExp; | ||
| 342 | output tuple<list<DAE.ComponentRef>, Option<DAE.Ident>> outDerVars; | ||
| 343 | algorithm | ||
| 344 | 1050 | (outExp, outDerVars) := Expression.traverseExpBottomUp(inExp, getDerVars, inDerVars); | |
| 345 | end getDerVars1; | ||
| 346 | |||
| 347 | protected function getDerVars | ||
| 348 | "Get all crefs that appear in a der() operator and replace der(x) with $DER.x. | ||
| 349 | author: rfranke" | ||
| 350 | input DAE.Exp inExp; | ||
| 351 | input tuple<list<DAE.ComponentRef>, Option<DAE.Ident>> inDerVars; | ||
| 352 | output DAE.Exp outExp; | ||
| 353 | output tuple<list<DAE.ComponentRef>, Option<DAE.Ident>> outDerVars = inDerVars; | ||
| 354 | algorithm | ||
| 355 | outExp := match inExp | ||
| 356 | local | ||
| 357 | list<DAE.ComponentRef> derVars; | ||
| 358 | Option<DAE.Ident> optForIter; | ||
| 359 | DAE.Ident forIter; | ||
| 360 | DAE.ComponentRef x; | ||
| 361 | DAE.Type ty; | ||
| 362 | DAE.Exp der_x; | ||
| 363 | case DAE.CALL(path = Absyn.IDENT(name = "der"), | ||
| 364 | expLst = {DAE.CREF(componentRef = x, ty = ty)}) | ||
| 365 | algorithm | ||
| 366 | // build $DER.x | ||
| 367 | 4 | der_x := DAE.CREF(ComponentReference.crefPrefixDer(x), ty); | |
| 368 | // strip optional forIter and append x to derVars | ||
| 369 | 4 | (derVars, optForIter) := inDerVars; | |
| 370 | () := match optForIter | ||
| 371 | case SOME(forIter) | ||
| 372 | algorithm | ||
| 373 | 1 | x := ComponentReference.crefStripIterSub(x, forIter); | |
| 374 | then (); | ||
| 375 | else (); | ||
| 376 | end match; | ||
| 377 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | if not ComponentReferenceBasics.crefInLst(x, derVars) then |
| 378 | derVars := x :: derVars; | ||
| 379 | end if; | ||
| 380 | 4 | outDerVars := (derVars, optForIter); | |
| 381 | then der_x; | ||
| 382 | else inExp; | ||
| 383 | end match; | ||
| 384 | end getDerVars; | ||
| 385 | |||
| 386 | protected function shiftDerVars1 "helper to shiftDerVars" | ||
| 387 | input DAE.Exp inExp; | ||
| 388 | input list<DAE.ComponentRef> inDerVars; | ||
| 389 | output DAE.Exp outExp; | ||
| 390 | output list<DAE.ComponentRef> outDerVars; | ||
| 391 | algorithm | ||
| 392 | ✗ | (outExp, outDerVars) := Expression.traverseExpBottomUp(inExp, shiftDerVars, inDerVars); | |
| 393 | end shiftDerVars1; | ||
| 394 | |||
| 395 | protected function shiftDerVars | ||
| 396 | "Apply previous() operator to all inDerVars. | ||
| 397 | author: rfranke" | ||
| 398 | input DAE.Exp inExp; | ||
| 399 | input list<DAE.ComponentRef> inDerVars; | ||
| 400 | output DAE.Exp outExp; | ||
| 401 | output list<DAE.ComponentRef> outDerVars = inDerVars; | ||
| 402 | algorithm | ||
| 403 | outExp := match inExp | ||
| 404 | local | ||
| 405 | List<DAE.Exp> expLst; | ||
| 406 | DAE.CallAttributes attr; | ||
| 407 | DAE.ComponentRef x; | ||
| 408 | DAE.Exp exp; | ||
| 409 | // introduce previous() | ||
| 410 | case DAE.CREF(componentRef = x) | ||
| 411 | guard ComponentReferenceBasics.crefInLst(x, inDerVars) | ||
| 412 | algorithm | ||
| 413 | ✗ | exp := DAE.CALL(Absyn.IDENT(name = "previous"), {inExp}, DAE.callAttrBuiltinImpureReal); | |
| 414 | then exp; | ||
| 415 | // check for possibly introduced der(previous()) | ||
| 416 | case DAE.CALL(path = Absyn.IDENT(name = "der"), | ||
| 417 | expLst = {DAE.CALL(path = Absyn.IDENT(name = "previous"), expLst = expLst)}, | ||
| 418 | attr = attr as DAE.CALL_ATTR()) | ||
| 419 | algorithm | ||
| 420 | ✗ | exp := DAE.CALL(Absyn.IDENT(name = "der"), expLst, attr); | |
| 421 | then exp; | ||
| 422 | // check for possibly introduced previous(previous()) | ||
| 423 | case DAE.CALL(path = Absyn.IDENT(name = "previous"), | ||
| 424 | expLst = {DAE.CALL(path = Absyn.IDENT(name = "previous"), expLst = expLst)}, | ||
| 425 | attr = attr as DAE.CALL_ATTR()) | ||
| 426 | algorithm | ||
| 427 | ✗ | exp := DAE.CALL(Absyn.IDENT(name = "previous"), expLst, attr); | |
| 428 | then exp; | ||
| 429 | // do nothing per default | ||
| 430 | else inExp; | ||
| 431 | end match; | ||
| 432 | end shiftDerVars; | ||
| 433 | |||
| 434 | protected function substituteFiniteDifference1 "helper to substituteFiniteDifference" | ||
| 435 | input DAE.Exp inExp; | ||
| 436 | input list<DAE.ComponentRef> inDerVars; | ||
| 437 | output DAE.Exp outExp; | ||
| 438 | output list<DAE.ComponentRef> outDerVars; | ||
| 439 | algorithm | ||
| 440 | ✗ | (outExp, outDerVars) := Expression.traverseExpBottomUp(inExp, substituteFiniteDifference, inDerVars); | |
| 441 | end substituteFiniteDifference1; | ||
| 442 | |||
| 443 | protected function substituteFiniteDifference | ||
| 444 | "Convert continous-time to clocked expression by replacing | ||
| 445 | der(x) -> (x - previous(x)) / interval(). | ||
| 446 | author: rfranke" | ||
| 447 | input DAE.Exp inExp; | ||
| 448 | input list<DAE.ComponentRef> inDerVars = {}; | ||
| 449 | output DAE.Exp outExp; | ||
| 450 | output list<DAE.ComponentRef> outDerVars; | ||
| 451 | algorithm | ||
| 452 | (outExp, outDerVars) := match inExp | ||
| 453 | local | ||
| 454 | List<DAE.Exp> expLst; | ||
| 455 | DAE.CallAttributes attr; | ||
| 456 | DAE.ComponentRef x; | ||
| 457 | DAE.Type ty; | ||
| 458 | DAE.Exp exp; | ||
| 459 | case DAE.CALL(path = Absyn.IDENT(name = "der"), | ||
| 460 | expLst = expLst as {DAE.CREF(componentRef = x)}, | ||
| 461 | attr = attr as DAE.CALL_ATTR(ty = ty)) | ||
| 462 | algorithm | ||
| 463 | 4 | exp := DAE.CALL(Absyn.IDENT(name = "previous"), expLst, attr); | |
| 464 | 4 | exp := DAE.BINARY(DAE.CREF(x, ty), DAE.SUB(DAE.T_REAL_DEFAULT), exp); | |
| 465 | 4 | exp := DAE.BINARY(exp, DAE.DIV(DAE.T_REAL_DEFAULT), | |
| 466 | DAE.CALL(Absyn.IDENT(name = "interval"), {}, | ||
| 467 | DAE.callAttrBuiltinImpureReal)); | ||
| 468 | then (exp, x :: inDerVars); | ||
| 469 | else (inExp, inDerVars); | ||
| 470 | end match; | ||
| 471 | end substituteFiniteDifference; | ||
| 472 | |||
| 473 | protected function markClockedStates | ||
| 474 | "Collect discrete states and mark them for further processing. | ||
| 475 | Use VarKind CLOCKED_STATE. Moreover set the isStartFixed flag, | ||
| 476 | the fixed attribute and list the crefs of all discrete states in | ||
| 477 | outShared.partitionsInfo.subPartitions[subPartIdx].prevVars." | ||
| 478 | input BackendDAE.EqSystem inSyst; | ||
| 479 | input BackendDAE.Shared inShared; | ||
| 480 | input list<DAE.ComponentRef> derVars; | ||
| 481 | output BackendDAE.Shared outShared = inShared; | ||
| 482 | protected | ||
| 483 | BackendDAE.Equation eq; | ||
| 484 | list<DAE.ComponentRef> prevVars = {}; | ||
| 485 | array<Boolean> isPrevVarArr, isDerVarArr; | ||
| 486 | list<Integer> varIxs; | ||
| 487 | BackendDAE.Var var; | ||
| 488 | Integer idx; | ||
| 489 | BackendDAE.SubPartition subPartition; | ||
| 490 | algorithm | ||
| 491 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 61 times.
|
61 | BackendDAE.CLOCKED_PARTITION(idx) := inSyst.partitionKind; |
| 492 | 61 | subPartition := outShared.partitionsInfo.subPartitions[idx]; | |
| 493 | |||
| 494 | 61 | isPrevVarArr := arrayCreate(BackendVariable.varsSize(inSyst.orderedVars), false); | |
| 495 | 61 | isDerVarArr := arrayCreate(BackendVariable.varsSize(inSyst.orderedVars), false); | |
| 496 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 61 times.
|
65 | for cr in derVars loop |
| 497 | 4 | varIxs := getVarIxs(cr, inSyst.orderedVars); | |
| 498 |
2/2✓ Branch 1 taken 4 times.
✓ Branch 2 taken 4 times.
|
8 | for idx in varIxs loop |
| 499 | 4 | arrayUpdate(isDerVarArr, idx, true); | |
| 500 | end for; | ||
| 501 | end for; | ||
| 502 |
1/2✓ Branch 1 taken 61 times.
✗ Branch 2 not taken.
|
61 | for i in 1:BackendEquation.getNumberOfEquations(inSyst.orderedEqs) loop |
| 503 | 529 | eq := BackendEquation.get(inSyst.orderedEqs, i); | |
| 504 | 529 | (_, (prevVars, _)) := BackendEquation.traverseExpsOfEquation(eq, collectPrevVars, (prevVars, BackendEquation.getForEquationIterIdent(eq))); | |
| 505 | end for; | ||
| 506 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 61 times.
|
61 | for i in 1:BackendEquation.getNumberOfEquations(inSyst.removedEqs) loop |
| 507 | ✗ | eq := BackendEquation.get(inSyst.removedEqs, i); | |
| 508 | ✗ | (_, (prevVars, _)) := BackendEquation.traverseExpsOfEquation(eq, collectPrevVars, (prevVars, BackendEquation.getForEquationIterIdent(eq))); | |
| 509 | end for; | ||
| 510 | |||
| 511 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 59 times.
|
61 | if not Flags.isSet(Flags.NF_SCALARIZE) then |
| 512 |
4/4✓ Branch 0 taken 35 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 35 times.
✓ Branch 3 taken 2 times.
|
37 | prevVars := list(ComponentReferenceBasics.crefStripLastSubs(cr) for cr in prevVars); |
| 513 | end if; | ||
| 514 | |||
| 515 |
2/2✓ Branch 0 taken 281 times.
✓ Branch 1 taken 61 times.
|
342 | for cr in prevVars loop |
| 516 | 281 | varIxs := getVarIxs(cr, inSyst.orderedVars); | |
| 517 |
2/2✓ Branch 1 taken 281 times.
✓ Branch 2 taken 281 times.
|
562 | for idx in varIxs loop |
| 518 | 281 | arrayUpdate(isPrevVarArr, idx, true); | |
| 519 | end for; | ||
| 520 | end for; | ||
| 521 | prevVars := {}; | ||
| 522 |
1/2✓ Branch 0 taken 61 times.
✗ Branch 1 not taken.
|
590 | for i in 1:arrayLength(isPrevVarArr) loop |
| 523 |
2/2✓ Branch 1 taken 197 times.
✓ Branch 2 taken 332 times.
|
529 | if isPrevVarArr[i] then |
| 524 | 197 | var := BackendVariable.getVarAt(inSyst.orderedVars, i); | |
| 525 | 197 | var := BackendVariable.setVarKind(var, BackendDAE.CLOCKED_STATE( | |
| 526 | previousName = ComponentReference.crefPrefixPrevious(var.varName), | ||
| 527 | isStartFixed = isDerVarArr[i])); | ||
| 528 | 197 | var := BackendVariable.setVarFixed(var, true); | |
| 529 | 197 | BackendVariable.setVarAt(inSyst.orderedVars, i, var); | |
| 530 | 197 | prevVars := var.varName::prevVars; | |
| 531 | end if; | ||
| 532 | end for; | ||
| 533 | |||
| 534 | 61 | subPartition.prevVars := prevVars; | |
| 535 | 61 | arrayUpdate(outShared.partitionsInfo.subPartitions, idx, subPartition); | |
| 536 | end markClockedStates; | ||
| 537 | |||
| 538 | protected function collectPrevVars | ||
| 539 | input DAE.Exp inExp; | ||
| 540 | input tuple<list<DAE.ComponentRef>, Option<DAE.Ident>> inPrevVars; | ||
| 541 | output DAE.Exp outExp; | ||
| 542 | output tuple<list<DAE.ComponentRef>, Option<DAE.Ident>> outPrevVars; | ||
| 543 | algorithm | ||
| 544 | 1058 | (outExp, outPrevVars) := Expression.traverseExpBottomUp(inExp, collectPrevVars1, inPrevVars); | |
| 545 | end collectPrevVars; | ||
| 546 | |||
| 547 | protected function collectPrevVars1 | ||
| 548 | "Append cref found in previous(cref) to outPrevVars. | ||
| 549 | Optionally strip for iterator to get array variable (no NF_SCALARIZE)." | ||
| 550 | input DAE.Exp inExp; | ||
| 551 | input tuple<list<DAE.ComponentRef>, Option<DAE.Ident>> inPrevVars; | ||
| 552 | output DAE.Exp outExp = inExp; | ||
| 553 | output tuple<list<DAE.ComponentRef>, Option<DAE.Ident>> outPrevVars; | ||
| 554 | algorithm | ||
| 555 | outPrevVars := match inExp | ||
| 556 | local | ||
| 557 | list<DAE.ComponentRef> inPrevCompRefs; | ||
| 558 | Option<DAE.Ident> inForIter; | ||
| 559 | DAE.Ident forIter; | ||
| 560 | DAE.ComponentRef cr; | ||
| 561 | case DAE.CALL(path=Absyn.IDENT("previous"), expLst={DAE.CREF(cr, _)}) | ||
| 562 | algorithm | ||
| 563 | 281 | (inPrevCompRefs, inForIter) := inPrevVars; | |
| 564 | () := match inForIter | ||
| 565 | case SOME(forIter) | ||
| 566 | algorithm | ||
| 567 | 5 | cr := ComponentReference.crefStripIterSub(cr, forIter); | |
| 568 | then (); | ||
| 569 | else (); | ||
| 570 | end match; | ||
| 571 | 281 | then (cr :: inPrevCompRefs, inForIter); | |
| 572 | else inPrevVars; | ||
| 573 | end match; | ||
| 574 | end collectPrevVars1; | ||
| 575 | |||
| 576 | protected function subClockPartitioning1 | ||
| 577 | "Do subclock partitioning and inferencing and create clocked partitions and base clocks array." | ||
| 578 | input list<BackendDAE.EqSystem> inSysts; | ||
| 579 | input BackendDAE.Shared inShared; | ||
| 580 | input list<DAE.ComponentRef> inHoldComps; | ||
| 581 | output list<BackendDAE.EqSystem> outSysts = {}; | ||
| 582 | output BackendDAE.Shared outShared = inShared; | ||
| 583 | protected | ||
| 584 | DAE.ClockKind baseClock; | ||
| 585 | HashTable.HashTable varsPartition; | ||
| 586 | Integer i, j, n, nBaseClocks; | ||
| 587 | DAE.ComponentRef cr; | ||
| 588 | array<Boolean> hasHoldOperator; | ||
| 589 | list<BackendDAE.EqSystem> systs; | ||
| 590 | list<BackendDAE.SubClock> lstSubClocks1, lstSubClocks = {}; | ||
| 591 | BackendDAE.PartitionsInfo partitionsInfo; | ||
| 592 | array<BackendDAE.BasePartition> basePartitions; | ||
| 593 | array<BackendDAE.SubPartition> subPartitions; | ||
| 594 | algorithm | ||
| 595 | 1068 | nBaseClocks := listLength(inSysts); | |
| 596 | 1068 | basePartitions := arrayCreate(nBaseClocks, BackendDAE.BASE_PARTITION(DAE.INFERRED_CLOCK(), 0)); | |
| 597 | 1068 | varsPartition := HashTable.emptyHashTable(); | |
| 598 | |||
| 599 | i := 0; j := 1; | ||
| 600 |
2/2✓ Branch 0 taken 46 times.
✓ Branch 1 taken 1068 times.
|
1114 | for syst in inSysts loop |
| 601 | 46 | (systs, baseClock, lstSubClocks1) := subClockPartitioning(syst, outShared, i); | |
| 602 | 46 | n := listLength(systs); | |
| 603 | 46 | arrayUpdate(basePartitions, j, BackendDAE.BASE_PARTITION(baseClock, n)); | |
| 604 | 46 | outSysts := List.append_reverse(systs, outSysts); | |
| 605 | 46 | lstSubClocks := List.append_reverse(lstSubClocks1, lstSubClocks); | |
| 606 | 46 | i := i + n; | |
| 607 | 46 | j := j + 1; | |
| 608 | end for; | ||
| 609 | 1068 | outSysts := listReverseInPlace(outSysts); | |
| 610 | 1068 | lstSubClocks := listReverseInPlace(lstSubClocks); | |
| 611 | |||
| 612 | 1068 | hasHoldOperator := arrayCreate(listLength(lstSubClocks), false); | |
| 613 | //Create hash cr -> subpartition index | ||
| 614 | i := 1; | ||
| 615 |
2/2✓ Branch 0 taken 61 times.
✓ Branch 1 taken 1068 times.
|
1129 | for syst in outSysts loop |
| 616 |
1/2✓ Branch 1 taken 61 times.
✗ Branch 2 not taken.
|
586 | for j in 1:BackendVariable.varsSize(syst.orderedVars) loop |
| 617 | 525 | BackendDAE.VAR(varName=cr) := BackendVariable.getVarAt(syst.orderedVars, j); | |
| 618 | 525 | varsPartition := BaseHashTable.add((cr, i), varsPartition); | |
| 619 | end for; | ||
| 620 | 61 | i := i + 1; | |
| 621 | end for; | ||
| 622 | //Detect subpartitions whose variables are used in hold operator | ||
| 623 |
2/2✓ Branch 0 taken 15 times.
✓ Branch 1 taken 1068 times.
|
1083 | for cr in inHoldComps loop |
| 624 | 15 | i := BaseHashTable.get(cr, varsPartition); | |
| 625 | 15 | arrayUpdate(hasHoldOperator, i, true); | |
| 626 | end for; | ||
| 627 | |||
| 628 | i := 1; | ||
| 629 | 1068 | subPartitions := arrayCreate( listLength(lstSubClocks), | |
| 630 | BackendDAE.SUB_PARTITION(BackendDAE.DEFAULT_SUBCLOCK, false, {}) ); | ||
| 631 |
2/2✓ Branch 0 taken 61 times.
✓ Branch 1 taken 1068 times.
|
1129 | for subclock in lstSubClocks loop |
| 632 | 61 | arrayUpdate(subPartitions, i, BackendDAE.SUB_PARTITION(subclock, hasHoldOperator[i], {})); | |
| 633 | 61 | i := i + 1; | |
| 634 | end for; | ||
| 635 | |||
| 636 | partitionsInfo := outShared.partitionsInfo; | ||
| 637 | 1068 | partitionsInfo.basePartitions := basePartitions; | |
| 638 | partitionsInfo.subPartitions := subPartitions; | ||
| 639 |
1/2✓ Branch 0 taken 1068 times.
✗ Branch 1 not taken.
|
1068 | outShared.partitionsInfo := partitionsInfo; |
| 640 | end subClockPartitioning1; | ||
| 641 | |||
| 642 | protected function removeHoldExpsSyst | ||
| 643 | "Collect clocked variable, which used in continuous partition. | ||
| 644 | Replace expression hold(expr_i) -> $getPart(expr_i)." | ||
| 645 | input list<BackendDAE.EqSystem> inSysts; | ||
| 646 | output list<BackendDAE.EqSystem> outSysts = {}; | ||
| 647 | output list<DAE.ComponentRef> outHoldComps = {}; | ||
| 648 | algorithm | ||
| 649 |
2/2✓ Branch 0 taken 18954 times.
✓ Branch 1 taken 1068 times.
|
20022 | for syst1 in inSysts loop |
| 650 | syst1 := match syst1 | ||
| 651 | local | ||
| 652 | BackendDAE.EquationArray eqs; | ||
| 653 | BackendDAE.EqSystem syst; | ||
| 654 | list<BackendDAE.Equation> lstEqs; | ||
| 655 | Integer i; | ||
| 656 | BackendDAE.Equation eq; | ||
| 657 | case syst as BackendDAE.EQSYSTEM(orderedEqs = eqs) | ||
| 658 | algorithm | ||
| 659 | lstEqs := {}; | ||
| 660 |
2/2✓ Branch 1 taken 18284 times.
✓ Branch 2 taken 670 times.
|
176673 | for i in 1:BackendEquation.getNumberOfEquations(eqs) loop |
| 661 | 157719 | eq := BackendEquation.get(eqs, i); | |
| 662 | 157719 | (eq, outHoldComps) := BackendEquation.traverseExpsOfEquation(eq, removeHoldExp1, outHoldComps); | |
| 663 | lstEqs := eq::lstEqs; | ||
| 664 | end for; | ||
| 665 | 18954 | syst.orderedEqs := BackendEquation.listEquation(listReverse(lstEqs)); | |
| 666 | then syst; | ||
| 667 | end match; | ||
| 668 | 18954 | outSysts := BackendDAEUtil.clearEqSyst(syst1) :: outSysts; | |
| 669 | end for; | ||
| 670 | end removeHoldExpsSyst; | ||
| 671 | |||
| 672 | protected function removeHoldExp1 | ||
| 673 | input DAE.Exp inExp; | ||
| 674 | input list<DAE.ComponentRef> inComps; | ||
| 675 | output DAE.Exp outExp; | ||
| 676 | output list<DAE.ComponentRef> outComps; | ||
| 677 | algorithm | ||
| 678 | 317809 | (outExp, outComps) := Expression.traverseExpBottomUp(inExp, removeHoldExp, inComps); | |
| 679 | end removeHoldExp1; | ||
| 680 | |||
| 681 | protected function removeHoldExp | ||
| 682 | input DAE.Exp inExp; | ||
| 683 | input list<DAE.ComponentRef> inComps; | ||
| 684 | output DAE.Exp outExp; | ||
| 685 | output list<DAE.ComponentRef> outComps; | ||
| 686 | algorithm | ||
| 687 | (outExp, outComps) := match inExp | ||
| 688 | local | ||
| 689 | DAE.Exp e; | ||
| 690 | DAE.ComponentRef cr; | ||
| 691 | case DAE.CALL(Absyn.IDENT("hold"), {e}, _) | ||
| 692 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
|
15 | algorithm DAE.CREF(cr, _) := e; |
| 693 | 15 | then (substGetPartition(e), cr::inComps); | |
| 694 | else (inExp, inComps); | ||
| 695 | end match; | ||
| 696 | end removeHoldExp; | ||
| 697 | |||
| 698 | protected function getSubPartitionAdjacency | ||
| 699 | "gets the adjacency matrix for the sub clock partitions and a dependency graph which is used to determine the execution order. | ||
| 700 | The edge weights are the sub-clocks resulting from the sub clock interfaces. | ||
| 701 | The sub clock interfaces are both original and inverted to get from one partition to another. | ||
| 702 | The dependency graph is based on the causality of the sub partition interface functions. | ||
| 703 | author: vwaurich 2017-06" | ||
| 704 | input Integer numPartitions; | ||
| 705 | input Integer baseClockEq; | ||
| 706 | input list<Integer> subPartitionInterfaceEqs; | ||
| 707 | input array<Integer> eqPartMap; | ||
| 708 | input array<Integer> varPartMap; | ||
| 709 | input array<Boolean> clockedVarsMask; | ||
| 710 | input BackendDAE.EquationArray eqs; | ||
| 711 | input BackendDAE.Variables vars; | ||
| 712 | output array<list<tuple<Integer,BackendDAE.SubClock>>> partAdjacency;//idx: partition, entries: connections to other partitions with subclocks | ||
| 713 | output array<Integer> order; | ||
| 714 | protected | ||
| 715 | Boolean infered; | ||
| 716 | Integer part, part1, part2, var1, var2; | ||
| 717 | list<Integer> partLst,orderLst; | ||
| 718 | BackendDAE.SubClock subClk1,subClk2; | ||
| 719 | array<Integer> partitionParents; | ||
| 720 | array<Boolean> partitionParentsVisited; | ||
| 721 | array<Boolean> partitionInterfacesClockVars; | ||
| 722 | algorithm | ||
| 723 | //build adjacency matrix for subclock partitions and dependency (parent) graph | ||
| 724 | 46 | partAdjacency := arrayCreate(numPartitions,{}); | |
| 725 | 46 | partitionParents := arrayCreate(numPartitions,-1); | |
| 726 | 46 | partitionInterfacesClockVars := arrayCreate(numPartitions,false); | |
| 727 |
2/2✓ Branch 0 taken 21 times.
✓ Branch 1 taken 46 times.
|
67 | for subPartEq in subPartitionInterfaceEqs loop |
| 728 | //part1,subClk1 is the output of the sub partition interface function calls, this is used for ordering | ||
| 729 | 21 | (infered,part1,var1,subClk1,part2,var2,subClk2) := getConnectedSubPartitions(BackendEquation.get(eqs,subPartEq),varPartMap,vars); | |
| 730 | //for adjacency relations, check only concrete sub partition interfaces not infered ones | ||
| 731 |
2/4✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 21 times.
✗ Branch 3 not taken.
|
21 | if part1 <> 0 and part2 <> 0 then |
| 732 | 21 | addPartAdjacencyEdge(part1,subClk1,part2,subClk2,partAdjacency); | |
| 733 | end if; | ||
| 734 | //reset previously obtained opposite parent relation if it interfaces clock-variables | ||
| 735 | //this is to prefer signal flow relations over clock relations in case of conflicts | ||
| 736 |
1/4✗ Branch 1 not taken.
✓ Branch 2 taken 21 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
21 | if partitionParents[part2] == part1 and partitionInterfacesClockVars[part2] then |
| 737 | ✗ | partitionParents[part2] := -1; | |
| 738 | end if; | ||
| 739 |
3/4✓ Branch 1 taken 6 times.
✓ Branch 2 taken 15 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 6 times.
|
21 | partitionInterfacesClockVars[part1] := not (clockedVarsMask[var1] and clockedVarsMask[var2]); |
| 740 | //avoid mutually dependent parents that would result in stack overflow later on | ||
| 741 |
1/2✓ Branch 1 taken 21 times.
✗ Branch 2 not taken.
|
21 | if partitionParents[part2] <> part1 then |
| 742 | 21 | partitionParents[part1] := part2; | |
| 743 | end if; | ||
| 744 | end for; | ||
| 745 | |||
| 746 | //get the order | ||
| 747 | 46 | partLst := List.intRange(numPartitions); | |
| 748 | 46 | partitionParentsVisited := arrayCreate(numPartitions,false); | |
| 749 | orderLst := {}; | ||
| 750 |
2/2✓ Branch 0 taken 93 times.
✓ Branch 1 taken 46 times.
|
139 | while not listEmpty(partLst) loop |
| 751 | 93 | part::partLst := partLst; | |
| 752 |
2/2✓ Branch 1 taken 13 times.
✓ Branch 2 taken 80 times.
|
93 | if not partitionParentsVisited[part] then |
| 753 | //partition without parent, not yet visited | ||
| 754 |
3/4✓ Branch 1 taken 34 times.
✓ Branch 2 taken 46 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 34 times.
|
80 | if partitionParents[part] == -1 or partitionParents[part] == part then |
| 755 | orderLst := part::orderLst; | ||
| 756 | 46 | partitionParentsVisited[part] := true; | |
| 757 | //partition with parents, parent visited | ||
| 758 | elseif partitionParentsVisited[partitionParents[part]] then | ||
| 759 | orderLst := part::orderLst; | ||
| 760 | 21 | partitionParentsVisited[part] := true; | |
| 761 | //partition with parents, parent not yet visited | ||
| 762 | else | ||
| 763 | partLst := part::partLst; | ||
| 764 | 13 | partLst := partitionParents[part]::partLst; | |
| 765 | end if; | ||
| 766 | end if; | ||
| 767 | end while; | ||
| 768 | 46 | order := listArray(listReverse(orderLst)); | |
| 769 | end getSubPartitionAdjacency; | ||
| 770 | |||
| 771 | protected function getSubClockForClkConstructor | ||
| 772 | "gets the corresponding subclock between 2 clock constructors | ||
| 773 | author: vwaurich 2017-06" | ||
| 774 | input DAE.ClockKind refClock; | ||
| 775 | input DAE.ClockKind clk; | ||
| 776 | output BackendDAE.SubClock subClk; | ||
| 777 | algorithm | ||
| 778 | subClk := match(refClock,clk) | ||
| 779 | local | ||
| 780 | Integer i1,i2,i3,i4; | ||
| 781 | Real r1,r2; | ||
| 782 | case(DAE.RATIONAL_CLOCK(DAE.ICONST(i1),DAE.ICONST(i2)), DAE.INFERRED_CLOCK()) | ||
| 783 | ✗ | then BackendDAE.SUBCLOCK(MMath.RATIONAL(i2,i1), MMath.RAT0,NONE()); | |
| 784 | case(DAE.RATIONAL_CLOCK(DAE.ICONST(i1),DAE.ICONST(i2)), DAE.RATIONAL_CLOCK(DAE.ICONST(i3),DAE.ICONST(i4))) | ||
| 785 | 4 | then BackendDAE.SUBCLOCK(MMath.divRational(MMath.RATIONAL(i2,i1),MMath.RATIONAL(i4,i3)),MMath.RAT0,NONE()); | |
| 786 | case(DAE.REAL_CLOCK(DAE.RCONST(r1)), DAE.INFERRED_CLOCK()) | ||
| 787 | ✗ | then BackendDAE.SUBCLOCK(MMath.RATIONAL(1, realInt(1.0/r1)), MMath.RAT0, NONE()); | |
| 788 | case(DAE.REAL_CLOCK(DAE.RCONST(r1)), DAE.REAL_CLOCK(DAE.RCONST(r2))) | ||
| 789 | ✗ | then BackendDAE.SUBCLOCK(MMath.divRational(MMath.RATIONAL(1, realInt(1.0/r1)),MMath.RATIONAL(1,realInt(1.0/r2))), MMath.RAT0, NONE()); | |
| 790 | else | ||
| 791 | algorithm | ||
| 792 | //Please add the missing cases. | ||
| 793 | ✗ | Error.addInternalError(getInstanceName() + " failed.\n", sourceInfo()); | |
| 794 | ✗ | then fail(); | |
| 795 | end match; | ||
| 796 | end getSubClockForClkConstructor; | ||
| 797 | |||
| 798 | protected function setSolverSubClock | ||
| 799 | "if the base clock is a solver clock, put the solver in the subclock and clean the base clock from the solver clock | ||
| 800 | author: vwaurich 2017-06" | ||
| 801 | input DAE.ClockKind baseClkIn; | ||
| 802 | input BackendDAE.SubClock inSubClock; | ||
| 803 | output DAE.ClockKind baseClkOut; | ||
| 804 | output BackendDAE.SubClock outSubClock; | ||
| 805 | algorithm | ||
| 806 | (baseClkOut, outSubClock) := match baseClkIn | ||
| 807 | local | ||
| 808 | String solver; | ||
| 809 | DAE.ClockKind clk; | ||
| 810 | case DAE.SOLVER_CLOCK(c = DAE.CLKCONST(clk=clk), solverMethod=DAE.SCONST(solver)) algorithm | ||
| 811 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
4 | outSubClock := setSubClockSolver(inSubClock, if solver == "" then NONE() else SOME(solver)); |
| 812 | then (clk, outSubClock); | ||
| 813 | else (baseClkIn, inSubClock); | ||
| 814 | end match; | ||
| 815 | end setSolverSubClock; | ||
| 816 | |||
| 817 | protected function findSubClocks | ||
| 818 | "gets the sub clocks for each partition by coloring the partition adjacency starting by the real and bool clocks. | ||
| 819 | author: vwaurich 2017-06" | ||
| 820 | input Integer numPartitions; | ||
| 821 | input Integer baseClockEq; | ||
| 822 | input DAE.ClockKind baseClk; | ||
| 823 | input list<Integer> baseClockConstructors; | ||
| 824 | input list<Integer> subPartitionInterfaceEqs; | ||
| 825 | input array<Integer> eqPartMap; | ||
| 826 | input array<Integer> varPartMap; | ||
| 827 | input BackendDAE.EquationArray eqs; | ||
| 828 | input array<list<tuple<Integer,BackendDAE.SubClock>>> partAdjacency;//idx: partition, entries: connections to other partitions with subclocks | ||
| 829 | output DAE.ClockKind baseClkOut; | ||
| 830 | output array<BackendDAE.SubClock> outSubClocks; | ||
| 831 | protected | ||
| 832 | Integer part1,part2; | ||
| 833 | list<Integer> partLst; | ||
| 834 | BackendDAE.SubClock subClk1,subClk2; | ||
| 835 | DAE.ClockKind clk; | ||
| 836 | array<Boolean> partIsAssigned; | ||
| 837 | list<tuple<Integer,BackendDAE.SubClock>> adjParts; | ||
| 838 | algorithm | ||
| 839 | 46 | outSubClocks := arrayCreate(numPartitions,BackendDAE.DEFAULT_SUBCLOCK); | |
| 840 | 46 | partIsAssigned := arrayCreate(numPartitions, false); //mark which partition is assigned | |
| 841 | |||
| 842 | //if there are multiple clock constructors in the sub partition, refer them to the base clock, ignore infered clocks | ||
| 843 |
2/2✓ Branch 0 taken 108 times.
✓ Branch 1 taken 46 times.
|
154 | for clockEq in baseClockConstructors loop |
| 844 |
4/4✓ Branch 0 taken 68 times.
✓ Branch 1 taken 40 times.
✓ Branch 2 taken 25 times.
✓ Branch 3 taken 43 times.
|
108 | if not intEq(baseClockEq, clockEq) and not intEq(baseClockEq,-1) then |
| 845 | 25 | part1 := arrayGet(eqPartMap,clockEq); | |
| 846 | 25 | clk := getBaseClock(BackendEquation.get(eqs,clockEq)); | |
| 847 |
2/2✓ Branch 1 taken 4 times.
✓ Branch 2 taken 21 times.
|
25 | if not isInferedBaseClock(clk) then |
| 848 | 4 | subClk1 := getSubClockForClkConstructor(baseClk, clk); | |
| 849 | 4 | arrayUpdate(outSubClocks, part1, subClk1); | |
| 850 | 4 | arrayUpdate(partIsAssigned, part1, true); | |
| 851 | end if; | ||
| 852 | end if; | ||
| 853 | end for; | ||
| 854 | |||
| 855 | //assign subclock partitions | ||
| 856 |
2/2✓ Branch 1 taken 6 times.
✓ Branch 2 taken 40 times.
|
46 | if isInferedBaseClock(baseClk) then |
| 857 | baseClkOut := baseClk; | ||
| 858 | 6 | partLst := List.intRange(numPartitions); //traverse all partitions, start with base clock partition | |
| 859 | else | ||
| 860 | 40 | part1 := arrayGet(eqPartMap,baseClockEq); | |
| 861 | 40 | partLst := part1::List.intRange(numPartitions); //traverse all partitions, start with base clock partition | |
| 862 | //if the baseClk is a solver clock, set the corresponding subClock solver | ||
| 863 | 40 | (baseClkOut, subClk1) := setSolverSubClock(baseClk, outSubClocks[part1]); | |
| 864 | 40 | arrayUpdate(outSubClocks, part1, subClk1); //set the solver clock | |
| 865 | 40 | arrayUpdate(partIsAssigned, part1, true); | |
| 866 | end if; | ||
| 867 | |||
| 868 |
2/2✓ Branch 0 taken 124 times.
✓ Branch 1 taken 46 times.
|
170 | while not listEmpty(partLst) loop |
| 869 | 124 | part1::partLst := partLst; | |
| 870 | 124 | adjParts := arrayGet(partAdjacency, part1); | |
| 871 | //check adjacent partitions | ||
| 872 |
2/2✓ Branch 0 taken 124 times.
✓ Branch 1 taken 80 times.
|
204 | for adjPart in adjParts loop |
| 873 | 80 | part2 := Util.tuple21(adjPart); | |
| 874 |
2/2✓ Branch 1 taken 17 times.
✓ Branch 2 taken 63 times.
|
80 | if not arrayGet(partIsAssigned, part2) then |
| 875 | 17 | subClk1 := arrayGet(outSubClocks, part1); | |
| 876 | 17 | subClk2 := Util.tuple22(adjPart); | |
| 877 | 17 | subClk2 := computeAbsoluteSubClock(subClk1,subClk2); | |
| 878 |
1/2✓ Branch 1 taken 17 times.
✗ Branch 2 not taken.
|
17 | if not isInferedSubClock(subClk2) then |
| 879 | 17 | arrayUpdate(outSubClocks, part2, subClk2); | |
| 880 | 17 | arrayUpdate(partIsAssigned, part2, true); | |
| 881 | partLst := part2::partLst; | ||
| 882 | end if; | ||
| 883 | end if; | ||
| 884 | end for; | ||
| 885 | end while; | ||
| 886 | end findSubClocks; | ||
| 887 | |||
| 888 | protected function computeAbsoluteSubClock | ||
| 889 | "merges 2 subsequent sub clocks. | ||
| 890 | author: vwaurich 2017-06" | ||
| 891 | input BackendDAE.SubClock preClock;//the known subpartition clock | ||
| 892 | input BackendDAE.SubClock subSeqClock; //the sub partitin clock which shall be determined | ||
| 893 | output BackendDAE.SubClock subClk = BackendDAE.DEFAULT_SUBCLOCK; | ||
| 894 | algorithm | ||
| 895 | subClk := match(preClock, subSeqClock) | ||
| 896 | local | ||
| 897 | MMath.Rational f1,f2; | ||
| 898 | MMath.Rational s1,s2; | ||
| 899 | Option<String> solver1,solver2; | ||
| 900 | case(BackendDAE.SUBCLOCK(f1,s1,solver1), BackendDAE.SUBCLOCK(f2,s2,solver2)) | ||
| 901 | algorithm | ||
| 902 | 17 | solver1 := mergeSolver(solver1,solver2); | |
| 903 | 17 | then BackendDAE.SUBCLOCK(MMath.divRational(f1, f2), MMath.addRational(MMath.multRational(s1, f2), s2), solver1); | |
| 904 | case(BackendDAE.SUBCLOCK(_,_,_),BackendDAE.INFERED_SUBCLOCK()) | ||
| 905 | then subSeqClock; | ||
| 906 | else | ||
| 907 | algorithm | ||
| 908 | ✗ | Error.addInternalError(getInstanceName() + " failed.\n", sourceInfo()); | |
| 909 | ✗ | then fail(); | |
| 910 | end match; | ||
| 911 | end computeAbsoluteSubClock; | ||
| 912 | |||
| 913 | protected function mergeSolver | ||
| 914 | "merges the solver methods of 2 sub clocks. | ||
| 915 | author: vwaurich 2017-06" | ||
| 916 | input Option<String> solver1; | ||
| 917 | input Option<String> solver2; | ||
| 918 | output Option<String> sOut; | ||
| 919 | algorithm | ||
| 920 | sOut := match(solver1,solver2) | ||
| 921 | local | ||
| 922 | String s1,s2; | ||
| 923 | case(NONE(),SOME(s2)) | ||
| 924 | then SOME(s2); | ||
| 925 | case(SOME(s1),NONE()) | ||
| 926 | then SOME(s1); | ||
| 927 | case(SOME(s1),SOME(s2)) | ||
| 928 | algorithm | ||
| 929 | ✗ | if not stringEq(s1,s2) then Error.addCompilerNotification("Infered sub clock partitions have different solvers:"+s1+" <->"+s2+".\n"); end if; | |
| 930 | then SOME(s1); | ||
| 931 | else | ||
| 932 | then NONE(); | ||
| 933 | end match; | ||
| 934 | end mergeSolver; | ||
| 935 | |||
| 936 | protected function addPartAdjacencyEdge | ||
| 937 | "add an edge between 2 partitions in the partition adjacency matrix. | ||
| 938 | author: vwaurich 2017-06" | ||
| 939 | input Integer part1; | ||
| 940 | input BackendDAE.SubClock sub1; | ||
| 941 | input Integer part2; | ||
| 942 | input BackendDAE.SubClock sub2; | ||
| 943 | input array<list<tuple<Integer,BackendDAE.SubClock>>> partAdjacency; | ||
| 944 | protected | ||
| 945 | list<tuple<Integer,BackendDAE.SubClock>> partEdges; | ||
| 946 | algorithm | ||
| 947 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
|
21 | if intGt(part1,0) and intGt(part2,0) then |
| 948 | //from first partition to secod partition | ||
| 949 | 21 | partEdges := arrayGet(partAdjacency,part1); | |
| 950 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 21 times.
|
29 | for edge in partEdges loop |
| 951 | //there is already a connection to this partition | ||
| 952 | 8 | if intEq(Util.tuple21(edge),part2) then | |
| 953 | //if not subClkEqual(Util.tuple22(edge),sub2) then Error.addCompilerNotification("Multiple subclock-interfaces between sub clock partitions.\n");end if; | ||
| 954 | end if; | ||
| 955 | end for; | ||
| 956 | 42 | arrayUpdate(partAdjacency,part1,(part2,sub1)::partEdges); | |
| 957 | //from second partition to first partition | ||
| 958 | 21 | partEdges := arrayGet(partAdjacency,part2); | |
| 959 | 42 | arrayUpdate(partAdjacency,part2,(part1,sub2)::partEdges); | |
| 960 | end if; | ||
| 961 | end addPartAdjacencyEdge; | ||
| 962 | |||
| 963 | protected function setSubClockFactor | ||
| 964 | "sets the factor of a sub clock | ||
| 965 | author: vwaurich 2017-06" | ||
| 966 | input BackendDAE.SubClock subClk; | ||
| 967 | input MMath.Rational factor; | ||
| 968 | output BackendDAE.SubClock subClkOut; | ||
| 969 | algorithm | ||
| 970 | subClkOut := match subClk | ||
| 971 | local | ||
| 972 | MMath.Rational shift; | ||
| 973 | Option<String> solver; | ||
| 974 | case BackendDAE.SUBCLOCK(_,shift,solver) | ||
| 975 | 18 | then BackendDAE.SUBCLOCK(factor,shift,solver); | |
| 976 | else | ||
| 977 | then subClk; | ||
| 978 | end match; | ||
| 979 | end setSubClockFactor; | ||
| 980 | |||
| 981 | protected function getSubClockFactor | ||
| 982 | "gets the factor of a sub clock | ||
| 983 | author: vwaurich 2017-06" | ||
| 984 | input BackendDAE.SubClock subClk; | ||
| 985 | output MMath.Rational factor; | ||
| 986 | algorithm | ||
| 987 | factor := match subClk | ||
| 988 | local | ||
| 989 | case BackendDAE.SUBCLOCK(factor,_,_) | ||
| 990 | then factor; | ||
| 991 | else | ||
| 992 | then MMath.RAT1; | ||
| 993 | end match; | ||
| 994 | end getSubClockFactor; | ||
| 995 | |||
| 996 | protected function getSubClockShift | ||
| 997 | "gets the shift value of a sub clock | ||
| 998 | author: vwaurich 2017-06" | ||
| 999 | input BackendDAE.SubClock subClk; | ||
| 1000 | output MMath.Rational shift; | ||
| 1001 | algorithm | ||
| 1002 | shift := match subClk | ||
| 1003 | local | ||
| 1004 | case BackendDAE.SUBCLOCK(_,shift,_) | ||
| 1005 | then shift; | ||
| 1006 | else | ||
| 1007 | then MMath.RAT0; | ||
| 1008 | end match; | ||
| 1009 | end getSubClockShift; | ||
| 1010 | |||
| 1011 | protected function getSubClockSolverOpt | ||
| 1012 | "gets the solver method option of a sub clock | ||
| 1013 | author: vwaurich 2017-06" | ||
| 1014 | input BackendDAE.SubClock subClk; | ||
| 1015 | output Option<String> solver; | ||
| 1016 | algorithm | ||
| 1017 | solver := match subClk | ||
| 1018 | local | ||
| 1019 | case BackendDAE.SUBCLOCK(_,_,solver) | ||
| 1020 | then solver; | ||
| 1021 | else | ||
| 1022 | then NONE(); | ||
| 1023 | end match; | ||
| 1024 | end getSubClockSolverOpt; | ||
| 1025 | |||
| 1026 | protected function setSubClockShift | ||
| 1027 | "sets the shift value of a sub clock | ||
| 1028 | author: vwaurich 2017-06" | ||
| 1029 | input BackendDAE.SubClock subClk; | ||
| 1030 | input MMath.Rational shift; | ||
| 1031 | output BackendDAE.SubClock subClkOut; | ||
| 1032 | algorithm | ||
| 1033 | subClkOut := match subClk | ||
| 1034 | local | ||
| 1035 | MMath.Rational factor; | ||
| 1036 | Option<String> solver; | ||
| 1037 | case BackendDAE.SUBCLOCK(factor,_,solver) | ||
| 1038 | 16 | then BackendDAE.SUBCLOCK(factor,shift,solver); | |
| 1039 | else | ||
| 1040 | then subClk; | ||
| 1041 | end match; | ||
| 1042 | end setSubClockShift; | ||
| 1043 | |||
| 1044 | protected function setSubClockSolver | ||
| 1045 | "sets the solver method option of a sub clock | ||
| 1046 | author: vwaurich 2017-06" | ||
| 1047 | input BackendDAE.SubClock subClk; | ||
| 1048 | input Option<String> solver; | ||
| 1049 | output BackendDAE.SubClock subClkOut; | ||
| 1050 | algorithm | ||
| 1051 | subClkOut := match subClk | ||
| 1052 | local | ||
| 1053 | MMath.Rational factor,shift; | ||
| 1054 | case BackendDAE.SUBCLOCK(factor,shift,_) | ||
| 1055 | 2 | then BackendDAE.SUBCLOCK(factor,shift,solver); | |
| 1056 | else | ||
| 1057 | then subClk; | ||
| 1058 | end match; | ||
| 1059 | end setSubClockSolver; | ||
| 1060 | |||
| 1061 | protected function getConnectedSubPartitions | ||
| 1062 | "get the connected partitions and the transformating sub clock for a sub partition interface equation. | ||
| 1063 | used to build the sub clock partition adjacency | ||
| 1064 | author: vwaurich 2017-06" | ||
| 1065 | input BackendDAE.Equation eq; | ||
| 1066 | input array<Integer> varPartMap; | ||
| 1067 | input BackendDAE.Variables vars; | ||
| 1068 | output Boolean infered = false; | ||
| 1069 | output Integer part1; | ||
| 1070 | output Integer var1=-1; | ||
| 1071 | output BackendDAE.SubClock sub1; | ||
| 1072 | output Integer part2; | ||
| 1073 | output Integer var2=-1; | ||
| 1074 | output BackendDAE.SubClock sub2; | ||
| 1075 | algorithm | ||
| 1076 | sub1 := BackendDAE.DEFAULT_SUBCLOCK; | ||
| 1077 | sub2 := BackendDAE.DEFAULT_SUBCLOCK; | ||
| 1078 | (part1, var1, part2, var2) := match eq | ||
| 1079 | local | ||
| 1080 | Integer v1,v2,p1,p2; | ||
| 1081 | Integer factor,counter,resolution; | ||
| 1082 | String solver; | ||
| 1083 | DAE.ComponentRef cref1,cref2; | ||
| 1084 | case BackendDAE.EQUATION(exp=DAE.CREF(componentRef=cref1), scalar=DAE.CALL(path=Absyn.IDENT("superSample"),expLst={DAE.CREF(componentRef=cref2),DAE.ICONST(factor)})) | ||
| 1085 | algorithm | ||
| 1086 | 8 | infered := intEq(factor,0);//the sub clock has to be infered | |
| 1087 |
2/4✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
|
8 | (_,{v1}) := BackendVariable.getVar(cref1,vars); |
| 1088 | 8 | p1 := varPartMap[v1]; | |
| 1089 |
2/4✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
|
8 | (_,{v2}) := BackendVariable.getVar(cref2,vars); |
| 1090 | 8 | p2 := varPartMap[v2]; | |
| 1091 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
|
8 | if infered then |
| 1092 | sub1 := BackendDAE.INFERED_SUBCLOCK(); | ||
| 1093 | sub2 := BackendDAE.INFERED_SUBCLOCK(); | ||
| 1094 | else | ||
| 1095 | 4 | sub1 := setSubClockFactor(sub1, MMath.divRational(MMath.RAT1, MMath.RATIONAL(factor,1))); | |
| 1096 | 4 | sub2 := setSubClockFactor(sub2,MMath.RATIONAL(factor,1)); | |
| 1097 | end if; | ||
| 1098 | then (p1,v1,p2,v2); | ||
| 1099 | case BackendDAE.EQUATION(exp=DAE.CREF(componentRef=cref1), scalar=DAE.CALL(path=Absyn.IDENT("subSample"),expLst={DAE.CREF(componentRef=cref2),DAE.ICONST(factor)})) | ||
| 1100 | algorithm | ||
| 1101 | 5 | infered := intEq(factor,0);//the sub clock has to be infered | |
| 1102 |
2/4✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
|
5 | (_,{v1}) := BackendVariable.getVar(cref1,vars); |
| 1103 | 5 | p1 := varPartMap[v1]; | |
| 1104 |
2/4✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
|
5 | (_,{v2}) := BackendVariable.getVar(cref2,vars); |
| 1105 | 5 | p2 := varPartMap[v2]; | |
| 1106 |
1/2✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
|
5 | if infered then |
| 1107 | sub1 := BackendDAE.INFERED_SUBCLOCK(); | ||
| 1108 | sub2 := BackendDAE.INFERED_SUBCLOCK(); | ||
| 1109 | else | ||
| 1110 | 5 | sub1 := setSubClockFactor(sub1, MMath.RATIONAL(factor,1)); | |
| 1111 | 5 | sub2 := setSubClockFactor(sub2, MMath.divRational(MMath.RAT1, MMath.RATIONAL(factor,1))); | |
| 1112 | end if; | ||
| 1113 | then (p1,v1,p2,v2); | ||
| 1114 | case BackendDAE.EQUATION(exp=DAE.CREF(componentRef=cref1), scalar=DAE.CALL(path=Absyn.IDENT("shiftSample"),expLst={DAE.CREF(componentRef=cref2),DAE.ICONST(counter),DAE.ICONST(resolution)})) | ||
| 1115 | algorithm | ||
| 1116 |
2/4✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
|
5 | (_,{v1}) := BackendVariable.getVar(cref1,vars); |
| 1117 | 5 | p1 := varPartMap[v1]; | |
| 1118 |
2/4✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
|
5 | (_,{v2}) := BackendVariable.getVar(cref2,vars); |
| 1119 | 5 | p2 := varPartMap[v2]; | |
| 1120 | 5 | sub1 := setSubClockShift(sub1, MMath.subRational(MMath.RAT0, MMath.RATIONAL(counter, resolution))); | |
| 1121 | 5 | sub2 := setSubClockShift(sub2,MMath.RATIONAL(counter,resolution)); | |
| 1122 | then (p1,v1,p2,v2); | ||
| 1123 | case BackendDAE.EQUATION(exp=DAE.CREF(componentRef=cref1), scalar=DAE.CALL(path=Absyn.IDENT("backSample"),expLst={DAE.CREF(componentRef=cref2),DAE.ICONST(counter),DAE.ICONST(resolution)})) | ||
| 1124 | algorithm | ||
| 1125 |
2/4✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
|
3 | (_,{v1}) := BackendVariable.getVar(cref1,vars); |
| 1126 | 3 | p1 := varPartMap[v1]; | |
| 1127 |
2/4✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
|
3 | (_,{v2}) := BackendVariable.getVar(cref2,vars); |
| 1128 | 3 | p2 := varPartMap[v2]; | |
| 1129 | 3 | sub1 := setSubClockShift(sub1, MMath.RATIONAL(counter,resolution)); | |
| 1130 | 3 | sub2 := setSubClockShift(sub2, MMath.subRational(MMath.RAT0, MMath.RATIONAL(counter, resolution))); | |
| 1131 | then (p1,v1,p2,v2); | ||
| 1132 | case BackendDAE.EQUATION(exp=DAE.CREF(componentRef=cref1), scalar=DAE.CLKCONST(clk=DAE.SOLVER_CLOCK(c=DAE.CREF(componentRef=cref2), solverMethod=DAE.SCONST(solver)))) | ||
| 1133 | algorithm | ||
| 1134 | ✗ | (_,{v1}) := BackendVariable.getVar(cref1,vars); | |
| 1135 | ✗ | p1 := varPartMap[v1]; | |
| 1136 | ✗ | (_,{v2}) := BackendVariable.getVar(cref2,vars); | |
| 1137 | ✗ | p2 := varPartMap[v2]; | |
| 1138 | ✗ | sub1 := setSubClockSolver(sub1, SOME(solver)); | |
| 1139 | ✗ | sub2 := setSubClockSolver(sub2, SOME(solver)); | |
| 1140 | then (p1,v1,p2,v2); | ||
| 1141 | |||
| 1142 | else | ||
| 1143 | then (-1,-1,-1,-1); | ||
| 1144 | end match; | ||
| 1145 | end getConnectedSubPartitions; | ||
| 1146 | |||
| 1147 | protected function chooseBaseClock | ||
| 1148 | "among all clock constructors, choose one as a base clock. No particular strategy applied. | ||
| 1149 | author: vwaurich 2017-06" | ||
| 1150 | input list<Integer> clockEqs; | ||
| 1151 | input Integer numPartitions; | ||
| 1152 | input array<Integer> eqPartMap; | ||
| 1153 | input BackendDAE.EquationArray eqs; | ||
| 1154 | output DAE.ClockKind outBaseClock = DAE.INFERRED_CLOCK(); | ||
| 1155 | output Integer baseClockEqIdx = -1; | ||
| 1156 | protected | ||
| 1157 | array<BackendDAE.SubClock> subClkPartMap; | ||
| 1158 | BackendDAE.Equation eq; | ||
| 1159 | algorithm | ||
| 1160 | //find baseClock, take the last, if there are several | ||
| 1161 | 46 | subClkPartMap := arrayCreate(numPartitions, BackendDAE.DEFAULT_SUBCLOCK); | |
| 1162 |
2/2✓ Branch 0 taken 108 times.
✓ Branch 1 taken 46 times.
|
154 | for clockEq in clockEqs loop |
| 1163 | 108 | eq := BackendEquation.get(eqs,clockEq); | |
| 1164 |
2/2✓ Branch 1 taken 44 times.
✓ Branch 2 taken 64 times.
|
108 | if isBaseClockEq(eq) then |
| 1165 | 44 | outBaseClock := getBaseClock(eq); | |
| 1166 | baseClockEqIdx := clockEq; | ||
| 1167 | end if; | ||
| 1168 | end for; | ||
| 1169 | end chooseBaseClock; | ||
| 1170 | |||
| 1171 | protected function isBaseClockEq | ||
| 1172 | input BackendDAE.Equation eq; | ||
| 1173 | output Boolean isBaseClock; | ||
| 1174 | algorithm | ||
| 1175 | isBaseClock := match eq | ||
| 1176 | local | ||
| 1177 | DAE.ClockKind clk; | ||
| 1178 | case BackendDAE.EQUATION(exp=DAE.CREF(),scalar=DAE.CLKCONST(clk=DAE.INFERRED_CLOCK())) | ||
| 1179 | algorithm | ||
| 1180 | then false; | ||
| 1181 | case BackendDAE.EQUATION(exp=DAE.CREF(),scalar=DAE.CLKCONST()) | ||
| 1182 | algorithm | ||
| 1183 | then true; | ||
| 1184 | else | ||
| 1185 | then false; | ||
| 1186 | end match; | ||
| 1187 | end isBaseClockEq; | ||
| 1188 | |||
| 1189 | protected function getBaseClock | ||
| 1190 | input BackendDAE.Equation eq; | ||
| 1191 | output DAE.ClockKind baseClk; | ||
| 1192 | algorithm | ||
| 1193 | baseClk := match eq | ||
| 1194 | local | ||
| 1195 | DAE.ClockKind clk; | ||
| 1196 | case BackendDAE.EQUATION(exp=DAE.CREF(),scalar=DAE.CLKCONST(clk=DAE.INFERRED_CLOCK())) | ||
| 1197 | algorithm | ||
| 1198 | then DAE.INFERRED_CLOCK(); | ||
| 1199 | case BackendDAE.EQUATION(exp=DAE.CREF(),scalar=DAE.CLKCONST(clk=clk)) | ||
| 1200 | algorithm | ||
| 1201 | then clk; | ||
| 1202 | else | ||
| 1203 | algorithm | ||
| 1204 | then DAE.INFERRED_CLOCK(); | ||
| 1205 | end match; | ||
| 1206 | end getBaseClock; | ||
| 1207 | |||
| 1208 | protected function removeEdge | ||
| 1209 | "removes edges in adjacency matrices betwenn equation and variable | ||
| 1210 | author: vwaurich 2017-06" | ||
| 1211 | input Integer eq; | ||
| 1212 | input Integer var; | ||
| 1213 | input BackendDAE.AdjacencyMatrix m; | ||
| 1214 | input BackendDAE.AdjacencyMatrixT mT; | ||
| 1215 | protected | ||
| 1216 | list<Integer> row; | ||
| 1217 | algorithm | ||
| 1218 | 21 | row := arrayGet(m,eq); | |
| 1219 | 21 | row := List.deleteMemberOnTrue(var,row,intEq); | |
| 1220 | 21 | arrayUpdate(m,eq,row); | |
| 1221 | 21 | row := arrayGet(mT,var); | |
| 1222 | 21 | row := List.deleteMemberOnTrue(eq,row,intEq); | |
| 1223 | 21 | arrayUpdate(mT,var,row); | |
| 1224 | end removeEdge; | ||
| 1225 | |||
| 1226 | protected function findBaseClockInterfaces | ||
| 1227 | "gets all equations which define a base clock and all equations which separate sub partitions. | ||
| 1228 | author: vwaurich 2017-06" | ||
| 1229 | input BackendDAE.EquationArray eqs; | ||
| 1230 | input BackendDAE.Variables vars; | ||
| 1231 | input BackendDAE.AdjacencyMatrix m; | ||
| 1232 | input BackendDAE.AdjacencyMatrixT mT; | ||
| 1233 | output list<Integer> clockEqs={}; | ||
| 1234 | output list<Integer> subClockInterfaceEqIdxs={}; | ||
| 1235 | output list<BackendDAE.Equation> subClockInterfaceEqs = {}; | ||
| 1236 | protected | ||
| 1237 | Integer eqIdx; | ||
| 1238 | BackendDAE.Equation eq; | ||
| 1239 | algorithm | ||
| 1240 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 46 times.
|
743 | for eqIdx in 1:BackendEquation.getNumberOfEquations(eqs) loop |
| 1241 | 697 | eq := BackendEquation.get(eqs,eqIdx); | |
| 1242 | 697 | (clockEqs, subClockInterfaceEqIdxs, subClockInterfaceEqs) := findBaseClockInterfaces1(eq, eqIdx, eqs, vars, m, mT, clockEqs, subClockInterfaceEqIdxs, subClockInterfaceEqs); | |
| 1243 | end for; | ||
| 1244 | end findBaseClockInterfaces; | ||
| 1245 | |||
| 1246 | protected function findBaseClockInterfaces1 | ||
| 1247 | "adds the equation to the lost of base clock defining eqs or to the equations which separate sub partitions | ||
| 1248 | author: vwaurich 2017-06" | ||
| 1249 | input BackendDAE.Equation eq; | ||
| 1250 | input Integer eqIdx; | ||
| 1251 | input BackendDAE.EquationArray eqs; | ||
| 1252 | input BackendDAE.Variables vars; | ||
| 1253 | input BackendDAE.AdjacencyMatrix m; | ||
| 1254 | input BackendDAE.AdjacencyMatrixT mT; | ||
| 1255 | input list<Integer> clockEqsIn; | ||
| 1256 | input list<Integer> subClockInterfaceEqIdxsIn; | ||
| 1257 | input list<BackendDAE.Equation> subClockInterfaceEqsIn; | ||
| 1258 | output list<Integer> clockEqsOut; | ||
| 1259 | output list<Integer> subClockInterfaceEqIdxsOut; | ||
| 1260 | output list<BackendDAE.Equation> subClockInterfaceEqsOut; | ||
| 1261 | algorithm | ||
| 1262 | (clockEqsOut, subClockInterfaceEqIdxsOut, subClockInterfaceEqsOut) := match eq | ||
| 1263 | local | ||
| 1264 | DAE.ComponentRef cref1; | ||
| 1265 | Integer varIdx; | ||
| 1266 | list<DAE.Exp> expLst; | ||
| 1267 | case BackendDAE.EQUATION(scalar=DAE.CLKCONST(clk=DAE.INFERRED_CLOCK())) | ||
| 1268 | algorithm | ||
| 1269 | then (eqIdx::clockEqsIn, subClockInterfaceEqIdxsIn, subClockInterfaceEqsIn); | ||
| 1270 | |||
| 1271 | case BackendDAE.EQUATION(scalar=DAE.CLKCONST(clk=DAE.RATIONAL_CLOCK(_))) | ||
| 1272 | algorithm | ||
| 1273 | then (eqIdx::clockEqsIn, subClockInterfaceEqIdxsIn,subClockInterfaceEqsIn); | ||
| 1274 | |||
| 1275 | case BackendDAE.EQUATION(scalar=DAE.CLKCONST(clk=DAE.REAL_CLOCK(_))) | ||
| 1276 | algorithm | ||
| 1277 | then (eqIdx::clockEqsIn, subClockInterfaceEqIdxsIn,subClockInterfaceEqsIn); | ||
| 1278 | |||
| 1279 | case BackendDAE.EQUATION(scalar=DAE.CLKCONST(clk=DAE.EVENT_CLOCK(_))) | ||
| 1280 | algorithm | ||
| 1281 | then (eqIdx::clockEqsIn, subClockInterfaceEqIdxsIn,subClockInterfaceEqsIn); | ||
| 1282 | |||
| 1283 | //solver clocks can act as subpartitioninterfaces since they assign a solver to another clock | ||
| 1284 | case BackendDAE.EQUATION(scalar=DAE.CLKCONST(clk=DAE.SOLVER_CLOCK(DAE.CREF(_),_))) | ||
| 1285 | algorithm | ||
| 1286 | then (clockEqsIn, eqIdx::subClockInterfaceEqIdxsIn, eq::subClockInterfaceEqsIn); | ||
| 1287 | |||
| 1288 | case BackendDAE.EQUATION(scalar=DAE.CLKCONST(clk=DAE.SOLVER_CLOCK(DAE.CLKCONST(_),_))) | ||
| 1289 | algorithm | ||
| 1290 | then (eqIdx::clockEqsIn, subClockInterfaceEqIdxsIn,subClockInterfaceEqsIn); | ||
| 1291 | |||
| 1292 | case BackendDAE.EQUATION(scalar=DAE.CALL(path=Absyn.IDENT("superSample"), expLst={DAE.CREF(componentRef=cref1),_})) | ||
| 1293 | algorithm | ||
| 1294 |
2/4✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
|
8 | (_,{varIdx}) := BackendVariable.getVar(cref1,vars); |
| 1295 | 8 | removeEdge(eqIdx,varIdx,m,mT); | |
| 1296 | then (clockEqsIn, eqIdx::subClockInterfaceEqIdxsIn, eq::subClockInterfaceEqsIn); | ||
| 1297 | |||
| 1298 | case BackendDAE.EQUATION(scalar=DAE.CALL(path=Absyn.IDENT("subSample"), expLst={DAE.CREF(componentRef=cref1),_})) | ||
| 1299 | algorithm | ||
| 1300 |
2/4✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
|
5 | (_,{varIdx}) := BackendVariable.getVar(cref1,vars); |
| 1301 | 5 | removeEdge(eqIdx,varIdx,m,mT); | |
| 1302 | then (clockEqsIn, eqIdx::subClockInterfaceEqIdxsIn, eq::subClockInterfaceEqsIn); | ||
| 1303 | |||
| 1304 | //shiftSample with 3 arguments | ||
| 1305 | case BackendDAE.EQUATION(scalar=DAE.CALL(path=Absyn.IDENT("shiftSample"), expLst={DAE.CREF(componentRef=cref1),_,_})) | ||
| 1306 | algorithm | ||
| 1307 |
2/4✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
|
5 | (_,{varIdx}) := BackendVariable.getVar(cref1,vars); |
| 1308 | 5 | removeEdge(eqIdx,varIdx,m,mT); | |
| 1309 | then (clockEqsIn, eqIdx::subClockInterfaceEqIdxsIn, eq::subClockInterfaceEqsIn); | ||
| 1310 | |||
| 1311 | //shiftSample with 2 arguments | ||
| 1312 | case BackendDAE.EQUATION(scalar=DAE.CALL(path=Absyn.IDENT("shiftSample"), expLst={DAE.CREF(componentRef=cref1),_})) | ||
| 1313 | algorithm | ||
| 1314 | ✗ | (_,{varIdx}) := BackendVariable.getVar(cref1,vars); | |
| 1315 | ✗ | removeEdge(eqIdx,varIdx,m,mT); | |
| 1316 | then (clockEqsIn, eqIdx::subClockInterfaceEqIdxsIn, eq::subClockInterfaceEqsIn); | ||
| 1317 | |||
| 1318 | //Backsample with 3 arguments | ||
| 1319 | case BackendDAE.EQUATION(scalar=DAE.CALL(path=Absyn.IDENT("backSample"), expLst={DAE.CREF(componentRef=cref1),_,_})) | ||
| 1320 | algorithm | ||
| 1321 |
2/4✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
|
3 | (_,{varIdx}) := BackendVariable.getVar(cref1,vars); |
| 1322 | 3 | removeEdge(eqIdx,varIdx,m,mT); | |
| 1323 | then (clockEqsIn, eqIdx::subClockInterfaceEqIdxsIn, eq::subClockInterfaceEqsIn); | ||
| 1324 | |||
| 1325 | //Backsample with 2 arguments | ||
| 1326 | case BackendDAE.EQUATION(scalar=DAE.CALL(path=Absyn.IDENT("backSample"), expLst={DAE.CREF(componentRef=cref1),_})) | ||
| 1327 | algorithm | ||
| 1328 | ✗ | (_,{varIdx}) := BackendVariable.getVar(cref1,vars); | |
| 1329 | ✗ | removeEdge(eqIdx,varIdx,m,mT); | |
| 1330 | then (clockEqsIn, eqIdx::subClockInterfaceEqIdxsIn, eq::subClockInterfaceEqsIn); | ||
| 1331 | |||
| 1332 | case BackendDAE.EQUATION() | ||
| 1333 | algorithm | ||
| 1334 | //print("Thats also not a base clock "+BackendDump.equationString(eq)+"\n"); | ||
| 1335 | then (clockEqsIn, subClockInterfaceEqIdxsIn, subClockInterfaceEqsIn); | ||
| 1336 | else | ||
| 1337 | algorithm | ||
| 1338 | then (clockEqsIn, subClockInterfaceEqIdxsIn, subClockInterfaceEqsIn); | ||
| 1339 | end match; | ||
| 1340 | end findBaseClockInterfaces1; | ||
| 1341 | |||
| 1342 | protected function findHighestWhenPrefixIdx | ||
| 1343 | "since new $whenClk vars are introduced, determine the highest index to avopid duplicates. | ||
| 1344 | author: vwaurich 2017-06" | ||
| 1345 | input BackendDAE.Var inVar; | ||
| 1346 | input Integer idxIn; | ||
| 1347 | output BackendDAE.Var outVar = inVar; | ||
| 1348 | output Integer idxOut = idxIn; | ||
| 1349 | protected | ||
| 1350 | DAE.ComponentRef name; | ||
| 1351 | list<String> chars, chars1, chars2; | ||
| 1352 | algorithm | ||
| 1353 | 637 | name := inVar.varName; | |
| 1354 | 637 | chars := stringListStringChar(ComponentReference.crefStr(name)); | |
| 1355 |
2/2✓ Branch 1 taken 234 times.
✓ Branch 2 taken 403 times.
|
637 | if intGt(listLength(chars),9) then |
| 1356 | 403 | (chars1,chars2) := List.split(chars,8); | |
| 1357 |
2/4✗ Branch 1 not taken.
✓ Branch 2 taken 403 times.
✓ Branch 5 taken 403 times.
✗ Branch 6 not taken.
|
403 | if stringEq(stringDelimitList(chars1,""), BackendDAE.WHENCLK_PRREFIX) then |
| 1358 | ✗ | idxOut := intMax(idxIn, stringInt(stringDelimitList(chars2,""))); | |
| 1359 | end if; | ||
| 1360 | end if; | ||
| 1361 | end findHighestWhenPrefixIdx; | ||
| 1362 | |||
| 1363 | protected function replaceSampledClocks | ||
| 1364 | "Clock contructors inside samples are added as an additional equation in order to separate clocks and dynamic equations if they are still marked as BackendDAE.DYNAMIC_EQUATION. | ||
| 1365 | author: vwaurich 2017-06" | ||
| 1366 | input BackendDAE.EquationArray eqsIn; | ||
| 1367 | input BackendDAE.Variables varsIn; | ||
| 1368 | output BackendDAE.EquationArray eqsOut; | ||
| 1369 | output BackendDAE.Variables varsOut; | ||
| 1370 | protected | ||
| 1371 | Integer prefIdx; | ||
| 1372 | BackendDAE.EquationArray eqs; | ||
| 1373 | list<BackendDAE.Equation> newEqs; | ||
| 1374 | list<BackendDAE.Var> newVars; | ||
| 1375 | algorithm | ||
| 1376 | //get the max $whenclk-Variable in the system in order to use a higher index | ||
| 1377 | 46 | prefIdx := BackendVariable.traverseBackendDAEVars(varsIn,findHighestWhenPrefixIdx,1); | |
| 1378 | 46 | (eqs,(_, _,newEqs, newVars)) := BackendEquation.traverseEquationArray_WithUpdate(eqsIn, replaceSampledClocks1, (varsIn,prefIdx+1,{},{})); | |
| 1379 | 46 | eqsOut := BackendEquation.addList(newEqs, eqs); | |
| 1380 | 46 | varsOut := BackendVariable.addVars(newVars, varsIn); | |
| 1381 | end replaceSampledClocks; | ||
| 1382 | |||
| 1383 | protected function replaceSampledClocks1 | ||
| 1384 | "author: vwaurich 2017-06" | ||
| 1385 | input BackendDAE.Equation eqIn; | ||
| 1386 | input tuple<BackendDAE.Variables, Integer, list<BackendDAE.Equation>, list<BackendDAE.Var>> tplIn; | ||
| 1387 | output BackendDAE.Equation eqOut; | ||
| 1388 | output tuple<BackendDAE.Variables, Integer, list<BackendDAE.Equation>, list<BackendDAE.Var>> tplOut; | ||
| 1389 | algorithm | ||
| 1390 | (eqOut, tplOut) := match(eqIn,tplIn) | ||
| 1391 | local | ||
| 1392 | Integer suffixIdx,suffixIdx0; | ||
| 1393 | BackendDAE.EquationAttributes attr; | ||
| 1394 | BackendDAE.Variables vars; | ||
| 1395 | DAE.Exp e1,e2; | ||
| 1396 | DAE.ElementSource source; | ||
| 1397 | list<BackendDAE.Equation> newEqs; | ||
| 1398 | list<BackendDAE.Var> newVars; | ||
| 1399 | list<Integer> dimSize; | ||
| 1400 | Option<Integer> recordSize; | ||
| 1401 | case(BackendDAE.EQUATION(e1, e2, source, BackendDAE.EQUATION_ATTRIBUTES(kind=BackendDAE.DYNAMIC_EQUATION())),(vars, suffixIdx0, newEqs, newVars)) | ||
| 1402 | algorithm | ||
| 1403 | 524 | (e1,(newEqs, newVars, suffixIdx)) := Expression.traverseExpTopDown(e1, replaceSampledClocks2, (newEqs, newVars, suffixIdx0)); | |
| 1404 | 524 | (e2,(newEqs, newVars, suffixIdx)) := Expression.traverseExpTopDown(e2, replaceSampledClocks2, (newEqs, newVars, suffixIdx)); | |
| 1405 |
2/2✓ Branch 0 taken 60 times.
✓ Branch 1 taken 464 times.
|
524 | if intEq(suffixIdx-suffixIdx0, 1) then |
| 1406 | 60 | attr := BackendEquation.defaultClockedEqAttr(suffixIdx0); | |
| 1407 | else | ||
| 1408 | attr := BackendDAE.EQ_ATTR_DEFAULT_DYNAMIC; | ||
| 1409 | end if; | ||
| 1410 | 524 | then (BackendDAE.EQUATION(e1,e2,source,attr),(vars, suffixIdx, newEqs, newVars)); | |
| 1411 | case(BackendDAE.ARRAY_EQUATION(dimSize, e1, e2, source, BackendDAE.EQUATION_ATTRIBUTES(kind=BackendDAE.DYNAMIC_EQUATION()), recordSize),(vars, suffixIdx0, newEqs, newVars)) | ||
| 1412 | algorithm | ||
| 1413 | ✗ | (e1,(newEqs, newVars, suffixIdx)) := Expression.traverseExpTopDown(e1, replaceSampledClocks2, (newEqs, newVars, suffixIdx0)); | |
| 1414 | ✗ | (e2,(newEqs, newVars, suffixIdx)) := Expression.traverseExpTopDown(e2, replaceSampledClocks2, (newEqs, newVars, suffixIdx)); | |
| 1415 | ✗ | if intEq(suffixIdx - suffixIdx0, 1) then | |
| 1416 | ✗ | attr := BackendEquation.defaultClockedEqAttr(suffixIdx0); | |
| 1417 | else | ||
| 1418 | attr := BackendDAE.EQ_ATTR_DEFAULT_DYNAMIC; | ||
| 1419 | end if; | ||
| 1420 | ✗ | then (BackendDAE.ARRAY_EQUATION(dimSize, e1, e2, source, attr, recordSize), (vars, suffixIdx, newEqs, newVars)); | |
| 1421 | else | ||
| 1422 | algorithm | ||
| 1423 | then (eqIn,tplIn); | ||
| 1424 | end match; | ||
| 1425 | end replaceSampledClocks1; | ||
| 1426 | |||
| 1427 | protected function replaceSampledClocks2 | ||
| 1428 | "author: vwaurich 2017-06" | ||
| 1429 | input DAE.Exp inExp; | ||
| 1430 | input tuple<list<BackendDAE.Equation>, list<BackendDAE.Var>, Integer> tplIn;//<addEq, addVar, suffixIdx> | ||
| 1431 | output DAE.Exp outExp; | ||
| 1432 | output Boolean cont; | ||
| 1433 | output tuple<list<BackendDAE.Equation>, list<BackendDAE.Var>, Integer> tplOut;//<addEq, addVar, suffixIdx> | ||
| 1434 | algorithm | ||
| 1435 | (outExp,cont, tplOut) := match(inExp,tplIn) | ||
| 1436 | local | ||
| 1437 | Integer suffixIdx; | ||
| 1438 | DAE.ComponentRef cr; | ||
| 1439 | DAE.Exp varExp, clk; | ||
| 1440 | BackendDAE.Equation addEq; | ||
| 1441 | BackendDAE.Var addVar; | ||
| 1442 | list<BackendDAE.Equation> newEqs; | ||
| 1443 | list<BackendDAE.Var> newVars; | ||
| 1444 | case(DAE.CALL(path=Absyn.IDENT("sample"), expLst={varExp as DAE.CREF(_), clk as DAE.CLKCONST(_)}),(newEqs,newVars,suffixIdx)) | ||
| 1445 | algorithm | ||
| 1446 | 60 | cr := DAE.CREF_IDENT(BackendDAE.WHENCLK_PRREFIX + intString(suffixIdx), DAE.T_CLOCK_DEFAULT, {}); | |
| 1447 | 60 | addVar := BackendVariable.makeVar(cr); | |
| 1448 | 60 | addEq := BackendDAE.EQUATION(Expression.crefToExp(cr), clk, DAE.emptyElementSource, BackendDAE.EQ_ATTR_DEFAULT_DYNAMIC); | |
| 1449 | 60 | then(substGetPartition(varExp), false, (addEq::newEqs, addVar::newVars, suffixIdx+1)); | |
| 1450 | else | ||
| 1451 | then (inExp, true, tplIn); | ||
| 1452 | end match; | ||
| 1453 | end replaceSampledClocks2; | ||
| 1454 | |||
| 1455 | protected function subClockPartitioning | ||
| 1456 | "Does sub-partitioning for base partition and get base clock | ||
| 1457 | and vars, equations and sub-clocks of subpartitions. | ||
| 1458 | author: vwaurich 2017-06" | ||
| 1459 | input BackendDAE.EqSystem inEqSystem; | ||
| 1460 | input BackendDAE.Shared inShared; | ||
| 1461 | input Integer off; | ||
| 1462 | output list<BackendDAE.EqSystem> outSysts; | ||
| 1463 | output DAE.ClockKind outBaseClock; | ||
| 1464 | output list<BackendDAE.SubClock> outSubClocks; | ||
| 1465 | protected | ||
| 1466 | AvlTreePathFunction.Tree funcs; | ||
| 1467 | BackendDAE.EquationArray eqs, remEqs, clockEqs; | ||
| 1468 | BackendDAE.Variables vars, clockVars; | ||
| 1469 | BackendDAE.AdjacencyMatrix m, mT, rm, rmT; | ||
| 1470 | Integer partitionsCnt; | ||
| 1471 | array<Integer> remEqPartMap; | ||
| 1472 | list<BackendDAE.Equation> newClockEqs; | ||
| 1473 | list<BackendDAE.Var> newClockVars; | ||
| 1474 | array<Option<Boolean>> contPartitions; | ||
| 1475 | array<Integer> subclksCnt; | ||
| 1476 | array<Integer> order; | ||
| 1477 | array<BackendDAE.SubClock> subclocks; | ||
| 1478 | array<Boolean> clockedEqsMask, clockedVarsMask, usedVars, usedRemovedVars; | ||
| 1479 | |||
| 1480 | Integer baseClockEqIdx,eqIdx,varIdx; | ||
| 1481 | list<Integer> baseClockEquations, subClockInterfaceEqIdxs; | ||
| 1482 | list<BackendDAE.Equation> subClockInterfaceEqs; | ||
| 1483 | array<Integer> varPartMap, eqPartMap; | ||
| 1484 | array<list<tuple<Integer,BackendDAE.SubClock>>> partAdjacency;//idx: partition, entries: connections to other partitions with subclocks | ||
| 1485 | BackendDAE.EqSystem sys; | ||
| 1486 | algorithm | ||
| 1487 | 46 | funcs := BackendDAEUtil.getFunctions(inShared); | |
| 1488 | 46 | BackendDAE.EQSYSTEM(orderedVars = vars, orderedEqs = eqs, removedEqs = remEqs) := inEqSystem; | |
| 1489 | |||
| 1490 | //separate clock-constructors from dynamic equations, e.g. x = sample(time, Clock(0.1)) -> x=time [clocked(whenclk1)]; whenclk1=Clock(0.1); | ||
| 1491 | 46 | (eqs,vars) := replaceSampledClocks(eqs,vars); | |
| 1492 | 46 | sys := BackendDAEUtil.setEqSystVars(inEqSystem, vars); | |
| 1493 | 46 | sys := BackendDAEUtil.setEqSystEqs(sys, eqs); | |
| 1494 | |||
| 1495 | //get adjacency matrix | ||
| 1496 | 92 | (sys, m, mT) := BackendDAEUtil.getAdjacencyMatrix(sys, BackendDAE.SUBCLOCK_IDX(), SOME(funcs), BackendDAEUtil.isInitializationDAE(inShared)); | |
| 1497 | |||
| 1498 | //find baseclocks and sub partition interfaces, remove edges in adjacency matrices for sub partition interfaces | ||
| 1499 | 46 | (baseClockEquations, subClockInterfaceEqIdxs, subClockInterfaceEqs) := findBaseClockInterfaces(eqs,vars,m,mT); | |
| 1500 | //print("all baseClockEquations "+stringDelimitList(List.map(baseClockEquations,intString),", ")+"\n"); | ||
| 1501 | //print("all subClockInterfaceEqIdxs "+stringDelimitList(List.map(subClockInterfaceEqIdxs,intString),", ")+"\n"); | ||
| 1502 | //BackendDump.dumpBipartiteGraphEqSystem(sys, inShared, "Synchronous_"+intString(off)); | ||
| 1503 | |||
| 1504 | //old implementation, used for partitioning | ||
| 1505 | 46 | (clockEqs, clockedEqsMask) := splitClockEqs(eqs); //masks false if clock equation | |
| 1506 | 46 | (clockVars, clockedVarsMask) := splitClockVars(vars); | |
| 1507 | 92 | (rm, rmT) := BackendDAEUtil.removedAdjacencyMatrix(sys, BackendDAE.SUBCLOCK_IDX(), SOME(funcs), BackendDAEUtil.isInitializationDAE(inShared)); | |
| 1508 | |||
| 1509 | //partitioning of equations and variables | ||
| 1510 | 46 | remEqPartMap := arrayCreate(arrayLength(rm), 0); | |
| 1511 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
|
92 | eqPartMap := arrayCreate(arrayLength(m), 0); |
| 1512 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
|
92 | varPartMap := arrayCreate(arrayLength(mT), 0); |
| 1513 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
|
92 | usedRemovedVars := arrayCreate(arrayLength(rmT), false); |
| 1514 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
|
92 | usedVars := arrayCreate(arrayLength(mT), false); |
| 1515 | 46 | partitionsCnt := partitionIndependentBlocksMasked(m, mT, rm, rmT, arrayCreate(BackendEquation.getNumberOfEquations(eqs), true), eqPartMap, varPartMap, remEqPartMap, usedVars, usedRemovedVars); | |
| 1516 | /* | ||
| 1517 | print("eqPartMap "+stringDelimitList(List.mapArray(eqPartMap,intString)," | ")+"\n"); | ||
| 1518 | print("varPartMap "+stringDelimitList(List.mapArray(varPartMap,intString)," | ")+"\n"); | ||
| 1519 | print("partitionsCnt :"+intString(partitionsCnt)+"\n"); | ||
| 1520 | varAtts := {}; | ||
| 1521 | eqAtts := {}; | ||
| 1522 | for i in 1:arrayLength(eqPartMap) loop | ||
| 1523 | print("eq "+intString(i)+" is partition "+intString(arrayGet(eqPartMap,i))+"\n"); | ||
| 1524 | eqAtts := (false, "p"+intString(arrayGet(eqPartMap,i)))::eqAtts; | ||
| 1525 | end for; | ||
| 1526 | for i in 1:arrayLength(varPartMap) loop | ||
| 1527 | print("var "+intString(i)+" is partition "+intString(arrayGet(varPartMap,i))+"\n"); | ||
| 1528 | varAtts := (false, "p"+intString(arrayGet(varPartMap,i)))::varAtts; | ||
| 1529 | end for; | ||
| 1530 | BackendDump.dumpBipartiteGraphStrongComponent2(vars,eqs,m,listReverse(varAtts),listReverse(eqAtts),"BipartiteGraph_SynchronousPart_"+intString(off)); | ||
| 1531 | */ | ||
| 1532 | |||
| 1533 | //find the defining base clock | ||
| 1534 | 46 | (outBaseClock,baseClockEqIdx) := chooseBaseClock(baseClockEquations, partitionsCnt, eqPartMap, eqs); | |
| 1535 | //print("base clock equation "+intString(baseClockEqIdx)+" "+DAEDump.clockKindString(outBaseClock)+"\n"); | ||
| 1536 | |||
| 1537 | // and get adjacency matrix for subpartitions, remove the sample()-vars first since they are not handled as connections (necessary to get the right order) | ||
| 1538 | 46 | (partAdjacency,order) := getSubPartitionAdjacency(partitionsCnt, baseClockEqIdx, subClockInterfaceEqIdxs, eqPartMap, varPartMap, clockedVarsMask, eqs, vars); | |
| 1539 | //print("order "+stringDelimitList(List.mapArray(order,intString)," | ")+"\n"); | ||
| 1540 | |||
| 1541 | //Detect clocked continuous partitions and create new subclock equations | ||
| 1542 | 92 | (m, mT) := BackendDAEUtil.adjacencyMatrixMasked(inEqSystem, BackendDAE.SUBCLOCK_IDX(), clockedEqsMask, SOME(funcs), BackendDAEUtil.isInitializationDAE(inShared)); | |
| 1543 | 46 | (newClockEqs, newClockVars, contPartitions, subclksCnt) | |
| 1544 | := collectSubclkInfo(eqs, inEqSystem.removedEqs, partitionsCnt, eqPartMap, remEqPartMap, vars, mT); | ||
| 1545 | |||
| 1546 | //propagate subclocks across the system, consider solver clocks | ||
| 1547 | 46 | (outBaseClock, subclocks) := findSubClocks(partitionsCnt, baseClockEqIdx, outBaseClock, baseClockEquations, subClockInterfaceEqIdxs, eqPartMap, varPartMap, eqs, partAdjacency); | |
| 1548 | /* | ||
| 1549 | for i in 1:arrayLength(subclocks) loop | ||
| 1550 | print("partition "+intString(i)+" has subClock "+BackendDump.subClockString(arrayGet(subclocks,i))+"\n"); | ||
| 1551 | end for; | ||
| 1552 | */ | ||
| 1553 | |||
| 1554 | //dont consider the clock-contructor calls as equations for the system | ||
| 1555 |
1/2✓ Branch 0 taken 46 times.
✗ Branch 1 not taken.
|
743 | for eqIdx in 1:arrayLength(clockedEqsMask) loop |
| 1556 |
2/2✓ Branch 1 taken 172 times.
✓ Branch 2 taken 525 times.
|
697 | if not arrayGet(clockedEqsMask,eqIdx) then arrayUpdate(eqPartMap,eqIdx,0); end if; |
| 1557 | end for; | ||
| 1558 |
1/2✓ Branch 0 taken 46 times.
✗ Branch 1 not taken.
|
742 | for varIdx in 1:arrayLength(clockedVarsMask) loop |
| 1559 |
2/2✓ Branch 1 taken 171 times.
✓ Branch 2 taken 525 times.
|
696 | if not arrayGet(clockedVarsMask,varIdx) then arrayUpdate(varPartMap,varIdx,0); end if; |
| 1560 | end for; | ||
| 1561 | |||
| 1562 | //get the equations and variables for the subpartitions | ||
| 1563 | 46 | (outSysts, outSubClocks) := orderSubPartitions(partitionsCnt, subclocks, order, eqPartMap, varPartMap, remEqPartMap, eqs, vars, remEqs, inShared, off); | |
| 1564 | //print("outSubClocks: \n"+stringDelimitList(List.map(outSubClocks,BackendDump.subClockString),"\n")+"\n"); | ||
| 1565 | //BackendDump.dumpEqSystems(outSysts, "outSysts"); | ||
| 1566 | //BackendDump.dumpBipartiteGraphEqSystem(listHead(outSysts), inShared, "SynchronousDone"+intString(off)); | ||
| 1567 | end subClockPartitioning; | ||
| 1568 | |||
| 1569 | protected function orderSubPartitions | ||
| 1570 | "collects equations and vars for subpartitions, brings them in the execution order and merges subsequent partitions with the same sub clock. | ||
| 1571 | author: vwaurich 2017-06" | ||
| 1572 | input Integer numParts; | ||
| 1573 | input array<BackendDAE.SubClock> subclocks; | ||
| 1574 | input array<Integer> order; | ||
| 1575 | input array<Integer> eqPartMap; | ||
| 1576 | input array<Integer> varPartMap; | ||
| 1577 | input array<Integer> remEqPartMap; | ||
| 1578 | input BackendDAE.EquationArray eqs; | ||
| 1579 | input BackendDAE.Variables vars; | ||
| 1580 | input BackendDAE.EquationArray remEqs; | ||
| 1581 | input BackendDAE.Shared shared; | ||
| 1582 | input Integer partitionOffset; | ||
| 1583 | output list<BackendDAE.EqSystem> systs = {}; | ||
| 1584 | output list<BackendDAE.SubClock> subClksOut = {}; | ||
| 1585 | protected | ||
| 1586 | Boolean considerRemovedEqs; | ||
| 1587 | Integer part; | ||
| 1588 | list<Integer> mergedParts; | ||
| 1589 | array<list<Integer>> partVarMap,partEqMap,partRemEqMap; | ||
| 1590 | BackendDAE.EqSystem sys; | ||
| 1591 | BackendDAE.SubClock clk,clk2; | ||
| 1592 | list<BackendDAE.Equation> eqLst, remEqLst; | ||
| 1593 | list<BackendDAE.Var> varLst; | ||
| 1594 | list<list<Integer>> mergedOrder; | ||
| 1595 | algorithm | ||
| 1596 | considerRemovedEqs := intGe(arrayLength(remEqPartMap),1); | ||
| 1597 | |||
| 1598 | //build mapping between partition and variables | ||
| 1599 | 46 | partVarMap := arrayCreate(numParts, {}); | |
| 1600 |
1/2✓ Branch 0 taken 46 times.
✗ Branch 1 not taken.
|
742 | for varIdx in 1:arrayLength(varPartMap) loop |
| 1601 | 696 | part := arrayGet(varPartMap,varIdx); | |
| 1602 |
2/2✓ Branch 0 taken 525 times.
✓ Branch 1 taken 171 times.
|
696 | if part > 0 then |
| 1603 | 525 | arrayUpdate(partVarMap, part, listAppend(partVarMap[part], {varIdx}));//array append list at idx | |
| 1604 | end if; | ||
| 1605 | end for; | ||
| 1606 | |||
| 1607 | //build mapping between partitions and equations | ||
| 1608 | 46 | partEqMap := arrayCreate(numParts, {}); | |
| 1609 |
1/2✓ Branch 0 taken 46 times.
✗ Branch 1 not taken.
|
743 | for eqIdx in 1:arrayLength(eqPartMap) loop |
| 1610 | 697 | part := arrayGet(eqPartMap,eqIdx); | |
| 1611 |
2/2✓ Branch 0 taken 525 times.
✓ Branch 1 taken 172 times.
|
697 | if part > 0 then |
| 1612 | 525 | arrayUpdate(partEqMap, part, listAppend(partEqMap[part], {eqIdx}));//array append list at idx | |
| 1613 | end if; | ||
| 1614 | end for; | ||
| 1615 | |||
| 1616 | //build mapping between partitions and removed equations | ||
| 1617 | 46 | partRemEqMap := arrayCreate(numParts, {}); | |
| 1618 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
|
46 | if considerRemovedEqs then |
| 1619 | ✗ | for reqIdx in 1:arrayLength(partRemEqMap) loop | |
| 1620 | ✗ | part := arrayGet(remEqPartMap,reqIdx); | |
| 1621 | ✗ | if part > 0 then | |
| 1622 | ✗ | arrayUpdate(partRemEqMap, part, listAppend(partRemEqMap[part], {reqIdx}));//array append list at idx | |
| 1623 | end if; | ||
| 1624 | end for; | ||
| 1625 | end if; | ||
| 1626 | |||
| 1627 | //merge partitions in subsequent order with same subclocks | ||
| 1628 | mergedOrder := {}; | ||
| 1629 | mergedParts :={}; | ||
| 1630 | 46 | clk := arrayGet(subclocks,order[1]); | |
| 1631 |
2/2✓ Branch 1 taken 67 times.
✓ Branch 2 taken 46 times.
|
113 | for part in order loop |
| 1632 | 67 | clk2 := arrayGet(subclocks,part); | |
| 1633 |
2/2✓ Branch 1 taken 46 times.
✓ Branch 2 taken 21 times.
|
67 | if subClkEqual(clk,clk2) then |
| 1634 | //these 2 partitions have the same subclock, put them in one partition | ||
| 1635 | mergedParts := part::mergedParts; | ||
| 1636 | else | ||
| 1637 | //this partition has a different subclock | ||
| 1638 | 21 | mergedOrder := listReverse(mergedParts)::mergedOrder; | |
| 1639 | mergedParts := {part}; | ||
| 1640 | 21 | clk := arrayGet(subclocks,part); | |
| 1641 | end if; | ||
| 1642 | end for; | ||
| 1643 | 46 | mergedOrder := listReverse(mergedParts)::mergedOrder; | |
| 1644 | 46 | mergedOrder := listReverse(mergedOrder); | |
| 1645 | |||
| 1646 | part := 1; | ||
| 1647 | //build equation systems for ordered sub partitions | ||
| 1648 |
2/2✓ Branch 0 taken 67 times.
✓ Branch 1 taken 46 times.
|
113 | for mergedParts in mergedOrder loop |
| 1649 | eqLst := {}; | ||
| 1650 | varLst := {}; | ||
| 1651 | remEqLst := {}; | ||
| 1652 |
2/2✓ Branch 0 taken 67 times.
✓ Branch 1 taken 67 times.
|
134 | for partIdx in mergedParts loop |
| 1653 |
2/2✓ Branch 1 taken 525 times.
✓ Branch 2 taken 67 times.
|
592 | for e in arrayGet(partEqMap, partIdx) loop |
| 1654 | 525 | eqLst := BackendEquation.get(eqs,e)::eqLst; | |
| 1655 | end for; | ||
| 1656 |
2/2✓ Branch 1 taken 525 times.
✓ Branch 2 taken 67 times.
|
592 | for v in arrayGet(partVarMap, partIdx) loop |
| 1657 | 525 | varLst := BackendVariable.getVarAt(vars,v)::varLst; | |
| 1658 | end for; | ||
| 1659 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 67 times.
|
67 | for r in arrayGet(partRemEqMap, partIdx) loop |
| 1660 | ✗ | remEqLst := BackendEquation.get(remEqs,r)::remEqLst; | |
| 1661 | end for; | ||
| 1662 | 67 | clk := arrayGet(subclocks,partIdx); | |
| 1663 | end for; | ||
| 1664 |
3/4✓ Branch 0 taken 6 times.
✓ Branch 1 taken 61 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
|
67 | if not listEmpty(eqLst) or not listEmpty(remEqLst) then |
| 1665 | 61 | (sys, _) := createEqSystem(listReverse(eqLst), listReverse(varLst), remEqLst, (true, true)); | |
| 1666 | //sys := BackendDAEUtil.sortEqnsDAEWork(sys,shared); | ||
| 1667 | 122 | sys.partitionKind := BackendDAE.CLOCKED_PARTITION(partitionOffset+part); | |
| 1668 | subClksOut := clk::subClksOut; | ||
| 1669 | systs := sys::systs; | ||
| 1670 | 61 | part := part+1; | |
| 1671 | end if; | ||
| 1672 | end for; | ||
| 1673 | //reverse system order due to listappending | ||
| 1674 | 46 | systs := listReverse(systs); | |
| 1675 | 46 | subClksOut := listReverse(subClksOut); | |
| 1676 | end orderSubPartitions; | ||
| 1677 | |||
| 1678 | protected function isInferedSubClock | ||
| 1679 | input BackendDAE.SubClock subClk; | ||
| 1680 | output Boolean isInfered; | ||
| 1681 | algorithm | ||
| 1682 | isInfered := match subClk | ||
| 1683 | case BackendDAE.INFERED_SUBCLOCK() | ||
| 1684 | then true; | ||
| 1685 | else | ||
| 1686 | false; | ||
| 1687 | end match; | ||
| 1688 | end isInferedSubClock; | ||
| 1689 | |||
| 1690 | protected function isInferedBaseClock | ||
| 1691 | input DAE.ClockKind subClk; | ||
| 1692 | output Boolean isInfered; | ||
| 1693 | algorithm | ||
| 1694 | isInfered := match subClk | ||
| 1695 | case DAE.INFERRED_CLOCK() | ||
| 1696 | then true; | ||
| 1697 | else | ||
| 1698 | false; | ||
| 1699 | end match; | ||
| 1700 | end isInferedBaseClock; | ||
| 1701 | |||
| 1702 | protected function setFactor | ||
| 1703 | input MMath.Rational oldVal; | ||
| 1704 | input MMath.Rational newVal; | ||
| 1705 | output MMath.Rational outVal; | ||
| 1706 | algorithm | ||
| 1707 | outVal := match (oldVal, newVal) | ||
| 1708 | case (MMath.RATIONAL(1, 1), _) then newVal; | ||
| 1709 | case (_, MMath.RATIONAL(1, 1)) then oldVal; | ||
| 1710 | else | ||
| 1711 | algorithm | ||
| 1712 | ✗ | if not MMath.equals(oldVal, newVal) then | |
| 1713 | ✗ | Error.addMessage(Error.SUBCLOCK_CONFLICT, {"factor", MMath.rationalString(oldVal), MMath.rationalString(newVal)}); | |
| 1714 | ✗ | fail(); | |
| 1715 | end if; | ||
| 1716 | then newVal; | ||
| 1717 | end match; | ||
| 1718 | end setFactor; | ||
| 1719 | |||
| 1720 | protected function setShift | ||
| 1721 | input MMath.Rational oldVal; | ||
| 1722 | input MMath.Rational newVal; | ||
| 1723 | output MMath.Rational outVal; | ||
| 1724 | algorithm | ||
| 1725 | outVal := match (oldVal, newVal) | ||
| 1726 | case (MMath.RATIONAL(0, _), _) then newVal; | ||
| 1727 | case (_, MMath.RATIONAL(0, _)) then oldVal; | ||
| 1728 | else | ||
| 1729 | algorithm | ||
| 1730 | ✗ | if not MMath.equals(oldVal, newVal) then | |
| 1731 | ✗ | Error.addMessage(Error.SUBCLOCK_CONFLICT, {"shift", MMath.rationalString(oldVal), MMath.rationalString(newVal)}); | |
| 1732 | ✗ | fail(); | |
| 1733 | end if; | ||
| 1734 | then newVal; | ||
| 1735 | end match; | ||
| 1736 | end setShift; | ||
| 1737 | |||
| 1738 | protected function collectSubclkInfoExp | ||
| 1739 | input DAE.Exp inExp; | ||
| 1740 | input tuple< list<BackendDAE.Equation>, list<BackendDAE.Var>, array<Option<Boolean>>, SourceInfo, | ||
| 1741 | array<Integer>, Integer, array<Integer>, BackendDAE.Variables, BackendDAE.AdjacencyMatrix > inTpl; | ||
| 1742 | output DAE.Exp outExp; | ||
| 1743 | output tuple< list<BackendDAE.Equation>, list<BackendDAE.Var>, array<Option<Boolean>>, SourceInfo, | ||
| 1744 | array<Integer>, Integer, array<Integer>, BackendDAE.Variables, BackendDAE.AdjacencyMatrix > outTpl; | ||
| 1745 | protected | ||
| 1746 | list<BackendDAE.Equation> newEqs; | ||
| 1747 | list<BackendDAE.Var> newVars; | ||
| 1748 | array<Option<Boolean>> contPartitions; | ||
| 1749 | Integer partitionIdx; | ||
| 1750 | array<Integer> partitions; | ||
| 1751 | BackendDAE.Variables vars; | ||
| 1752 | BackendDAE.AdjacencyMatrix mT; | ||
| 1753 | Absyn.Path path; | ||
| 1754 | list<DAE.Exp> expLst; | ||
| 1755 | DAE.CallAttributes attr; | ||
| 1756 | array<Integer> clksCnt; | ||
| 1757 | Integer clkCnt; | ||
| 1758 | SourceInfo source; | ||
| 1759 | algorithm | ||
| 1760 | 4245 | (newEqs, newVars, contPartitions, source, clksCnt, partitionIdx, partitions, vars, mT) := inTpl; | |
| 1761 | 4245 | clkCnt := arrayGet(clksCnt, partitionIdx); | |
| 1762 | (outExp, newEqs, newVars, clkCnt) := match inExp | ||
| 1763 | case DAE.CALL(path, expLst, attr) | ||
| 1764 | 433 | then | |
| 1765 | collectSubclkInfoCall( path, expLst, attr, newEqs, newVars, contPartitions, partitionIdx, clkCnt, | ||
| 1766 | partitions, vars, mT, source ); | ||
| 1767 | 3812 | else | |
| 1768 | (inExp, newEqs, newVars, clkCnt); | ||
| 1769 | end match; | ||
| 1770 | 4245 | arrayUpdate(clksCnt, partitionIdx, clkCnt); | |
| 1771 | 4245 | outTpl := (newEqs, newVars, contPartitions, source, clksCnt, partitionIdx, partitions, vars, mT); | |
| 1772 | end collectSubclkInfoExp; | ||
| 1773 | |||
| 1774 | protected function createSubClockVar | ||
| 1775 | input Integer inPartitionIdx; | ||
| 1776 | input Integer inClkCnt; | ||
| 1777 | input Absyn.Path inPath; | ||
| 1778 | input list<DAE.Exp> inExpLst; | ||
| 1779 | input DAE.CallAttributes inAttr; | ||
| 1780 | input array<Integer> inPartitions; | ||
| 1781 | input BackendDAE.Variables inVars; | ||
| 1782 | input BackendDAE.AdjacencyMatrix mT; | ||
| 1783 | output BackendDAE.Var outVar; | ||
| 1784 | output BackendDAE.Equation outEq; | ||
| 1785 | protected | ||
| 1786 | DAE.ComponentRef cr; | ||
| 1787 | list<Integer> varIxs; | ||
| 1788 | Integer i; | ||
| 1789 | DAE.Exp e, subclk; | ||
| 1790 | algorithm | ||
| 1791 | ✗ | DAE.CREF(componentRef = cr) := listHead(inExpLst); | |
| 1792 | ✗ | (_, varIxs) := BackendVariable.getVar(cr, inVars); | |
| 1793 | ✗ | i := listHead(varIxs); | |
| 1794 | ✗ | i := listHead(arrayGet(mT, i)) "Equation idx, containing var"; | |
| 1795 | ✗ | i := arrayGet(inPartitions, i) "Partitions, from which var get"; | |
| 1796 | ✗ | subclk := DAE.CREF(getSubClkName(i, 1), DAE.T_CLOCK_DEFAULT); | |
| 1797 | ✗ | e := DAE.CALL(inPath, subclk::listRest(inExpLst), inAttr); | |
| 1798 | ✗ | (outVar, outEq) := createSubClock(inPartitionIdx, inClkCnt, e); | |
| 1799 | end createSubClockVar; | ||
| 1800 | |||
| 1801 | protected function setContClockedPartition | ||
| 1802 | input Boolean inIsContClockedPartition; | ||
| 1803 | input Integer inPartitionIdx; | ||
| 1804 | input array<Option<Boolean>> inContPartitions; | ||
| 1805 | input SourceInfo source; | ||
| 1806 | protected | ||
| 1807 | Option<Boolean> isContClockedPartition; | ||
| 1808 | Boolean isContClockedPrevPartition; | ||
| 1809 | algorithm | ||
| 1810 | 299 | isContClockedPartition := arrayGet(inContPartitions, inPartitionIdx); | |
| 1811 | isContClockedPartition := match isContClockedPartition | ||
| 1812 |
2/2✓ Branch 0 taken 35 times.
✓ Branch 1 taken 2 times.
|
37 | case NONE() then |
| 1813 | SOME(inIsContClockedPartition); | ||
| 1814 |
2/2✓ Branch 0 taken 258 times.
✓ Branch 1 taken 4 times.
|
262 | case SOME(isContClockedPrevPartition) then |
| 1815 | SOME(inIsContClockedPartition or isContClockedPrevPartition); | ||
| 1816 | end match; | ||
| 1817 | 299 | arrayUpdate(inContPartitions, inPartitionIdx, isContClockedPartition); | |
| 1818 | end setContClockedPartition; | ||
| 1819 | |||
| 1820 | protected function collectSubclkInfoCall | ||
| 1821 | input Absyn.Path inPath; | ||
| 1822 | input list<DAE.Exp> inExpLst; | ||
| 1823 | input DAE.CallAttributes inAttr; | ||
| 1824 | input list<BackendDAE.Equation> inNewEqs; | ||
| 1825 | input list<BackendDAE.Var> inNewVars; | ||
| 1826 | input array<Option<Boolean>> inContPartitions; | ||
| 1827 | input Integer inPartitionIdx; | ||
| 1828 | input Integer inClkCnt; | ||
| 1829 | input array<Integer> inPartitions; | ||
| 1830 | input BackendDAE.Variables inVars; | ||
| 1831 | input BackendDAE.AdjacencyMatrix mT; | ||
| 1832 | input SourceInfo source; | ||
| 1833 | output DAE.Exp outExp; | ||
| 1834 | output list<BackendDAE.Equation> outNewEqs; | ||
| 1835 | output list<BackendDAE.Var> outNewVars; | ||
| 1836 | output Integer outClkCnt; | ||
| 1837 | algorithm | ||
| 1838 | (outExp, outNewEqs, outNewVars, outClkCnt) := match (inPath, listLength(inExpLst)) | ||
| 1839 | local | ||
| 1840 | BackendDAE.Var var; | ||
| 1841 | BackendDAE.Equation eq; | ||
| 1842 | case (Absyn.IDENT("der"), _) | ||
| 1843 | algorithm | ||
| 1844 | 4 | setContClockedPartition(true, inPartitionIdx, inContPartitions, source); | |
| 1845 | 4 | then | |
| 1846 | (DAE.CALL(inPath, inExpLst, inAttr), inNewEqs, inNewVars, inClkCnt); | ||
| 1847 | case (Absyn.IDENT("delay"), _) | ||
| 1848 | algorithm | ||
| 1849 | ✗ | setContClockedPartition(true, inPartitionIdx, inContPartitions, source); | |
| 1850 | ✗ | then | |
| 1851 | (DAE.CALL(inPath, inExpLst, inAttr), inNewEqs, inNewVars, inClkCnt); | ||
| 1852 | case (Absyn.IDENT("spatialDistribution"), _) | ||
| 1853 | algorithm | ||
| 1854 | ✗ | setContClockedPartition(true, inPartitionIdx, inContPartitions, source); | |
| 1855 | ✗ | then | |
| 1856 | (DAE.CALL(inPath, inExpLst, inAttr), inNewEqs, inNewVars, inClkCnt); | ||
| 1857 | case (Absyn.IDENT("initial"), _) | ||
| 1858 | algorithm | ||
| 1859 | ✗ | setContClockedPartition(true, inPartitionIdx, inContPartitions, source); | |
| 1860 | ✗ | then | |
| 1861 | (DAE.CALL(inPath, inExpLst, inAttr), inNewEqs, inNewVars, inClkCnt); | ||
| 1862 | case (Absyn.IDENT("terminal"), _) | ||
| 1863 | algorithm | ||
| 1864 | ✗ | setContClockedPartition(true, inPartitionIdx, inContPartitions, source); | |
| 1865 | ✗ | then | |
| 1866 | (DAE.CALL(inPath, inExpLst, inAttr), inNewEqs, inNewVars, inClkCnt); | ||
| 1867 | case (Absyn.IDENT("smooth"), _) | ||
| 1868 | algorithm | ||
| 1869 | ✗ | setContClockedPartition(true, inPartitionIdx, inContPartitions, source); | |
| 1870 | ✗ | then | |
| 1871 | (DAE.CALL(inPath, inExpLst, inAttr), inNewEqs, inNewVars, inClkCnt); | ||
| 1872 | case (Absyn.IDENT("sample"), 3) | ||
| 1873 | algorithm | ||
| 1874 | ✗ | setContClockedPartition(true, inPartitionIdx, inContPartitions, source); | |
| 1875 | ✗ | then | |
| 1876 | (DAE.CALL(inPath, inExpLst, inAttr), inNewEqs, inNewVars, inClkCnt); | ||
| 1877 | case (Absyn.IDENT("pre"), _) | ||
| 1878 | algorithm | ||
| 1879 | ✗ | setContClockedPartition(true, inPartitionIdx, inContPartitions, source); | |
| 1880 | ✗ | then | |
| 1881 | (DAE.CALL(inPath, inExpLst, inAttr), inNewEqs, inNewVars, inClkCnt); | ||
| 1882 | case (Absyn.IDENT("edge"), _) | ||
| 1883 | algorithm | ||
| 1884 | ✗ | setContClockedPartition(true, inPartitionIdx, inContPartitions, source); | |
| 1885 | ✗ | then | |
| 1886 | (DAE.CALL(inPath, inExpLst, inAttr), inNewEqs, inNewVars, inClkCnt); | ||
| 1887 | case (Absyn.IDENT("change"), _) | ||
| 1888 | algorithm | ||
| 1889 | ✗ | setContClockedPartition(true, inPartitionIdx, inContPartitions, source); | |
| 1890 | ✗ | then | |
| 1891 | (DAE.CALL(inPath, inExpLst, inAttr), inNewEqs, inNewVars, inClkCnt); | ||
| 1892 | case (Absyn.IDENT("reinit"), _) | ||
| 1893 | algorithm | ||
| 1894 | ✗ | setContClockedPartition(true, inPartitionIdx, inContPartitions, source); | |
| 1895 | ✗ | then | |
| 1896 | (DAE.CALL(inPath, inExpLst, inAttr), inNewEqs, inNewVars, inClkCnt); | ||
| 1897 | |||
| 1898 | case (Absyn.IDENT("previous"), _) | ||
| 1899 | algorithm | ||
| 1900 | 277 | setContClockedPartition(false, inPartitionIdx, inContPartitions, source); | |
| 1901 | 277 | then | |
| 1902 | (DAE.CALL(inPath, inExpLst, inAttr), inNewEqs, inNewVars, inClkCnt); | ||
| 1903 | case (Absyn.IDENT("firstTick"), _) | ||
| 1904 | algorithm | ||
| 1905 | 4 | setContClockedPartition(false, inPartitionIdx, inContPartitions, source); | |
| 1906 | 4 | then | |
| 1907 | // Note: remove optional argument (inExpLst) to avoid algebraic loop | ||
| 1908 | (DAE.CALL(inPath, {}, inAttr), inNewEqs, inNewVars, inClkCnt); | ||
| 1909 | case (Absyn.IDENT("interval"), _) | ||
| 1910 | algorithm | ||
| 1911 | 14 | setContClockedPartition(false, inPartitionIdx, inContPartitions, source); | |
| 1912 | 14 | then | |
| 1913 | // Note: remove optional argument (inExpLst) to avoid algebraic loop | ||
| 1914 | (DAE.CALL(inPath, {}, inAttr), inNewEqs, inNewVars, inClkCnt); | ||
| 1915 | |||
| 1916 | case (Absyn.IDENT("sample"), 2) | ||
| 1917 | algorithm | ||
| 1918 | 29 | (var, eq) := createSubClock(inPartitionIdx, inClkCnt, listGet(inExpLst, 2)); | |
| 1919 | 58 | then | |
| 1920 | (substGetPartition(listGet(inExpLst, 1)), eq::inNewEqs, var::inNewVars, inClkCnt + 1); | ||
| 1921 | case (Absyn.IDENT("subSample"), 2) | ||
| 1922 | 5 | then | |
| 1923 | (substGetPartition(listGet(inExpLst, 1)), inNewEqs, inNewVars, inClkCnt + 1); | ||
| 1924 | |||
| 1925 | case (Absyn.IDENT("superSample"), 2) | ||
| 1926 | 8 | then | |
| 1927 | (substGetPartition(listGet(inExpLst, 1)), inNewEqs, inNewVars, inClkCnt + 1); | ||
| 1928 | |||
| 1929 | |||
| 1930 | case (Absyn.IDENT("shiftSample"), 3) | ||
| 1931 | 5 | then | |
| 1932 | (substGetPartition(listGet(inExpLst, 1)), inNewEqs, inNewVars, inClkCnt + 1); | ||
| 1933 | |||
| 1934 | case (Absyn.IDENT("backSample"), 3) | ||
| 1935 | 3 | then | |
| 1936 | (substGetPartition(listGet(inExpLst, 1)), inNewEqs, inNewVars, inClkCnt + 1); | ||
| 1937 | |||
| 1938 | case (Absyn.IDENT("noClock"), 1) | ||
| 1939 | ✗ | then | |
| 1940 | (substGetPartition(listGet(inExpLst, 1)), inNewEqs, inNewVars, inClkCnt); | ||
| 1941 | 84 | else | |
| 1942 | (DAE.CALL(inPath, inExpLst, inAttr), inNewEqs, inNewVars, inClkCnt); | ||
| 1943 | end match; | ||
| 1944 | end collectSubclkInfoCall; | ||
| 1945 | |||
| 1946 | protected function createSubClockVarFactor | ||
| 1947 | input Integer inPartitionIdx; | ||
| 1948 | input Integer inClkCnt; | ||
| 1949 | input Absyn.Path inPath; | ||
| 1950 | input list<DAE.Exp> inExpLst; | ||
| 1951 | input DAE.CallAttributes inAttr; | ||
| 1952 | input array<Integer> inPartitions; | ||
| 1953 | input BackendDAE.Variables inVars; | ||
| 1954 | input BackendDAE.AdjacencyMatrix mT; | ||
| 1955 | input list<BackendDAE.Equation> inNewEqs; | ||
| 1956 | input list<BackendDAE.Var> inNewVars; | ||
| 1957 | output DAE.Exp outExp; | ||
| 1958 | output list<BackendDAE.Equation> outNewEqs = inNewEqs; | ||
| 1959 | output list<BackendDAE.Var> outNewVars = inNewVars; | ||
| 1960 | output Integer outClkCnt = inClkCnt; | ||
| 1961 | algorithm | ||
| 1962 | ✗ | outExp := substGetPartition(listHead(inExpLst)); | |
| 1963 | //To do this, the eqPartMap has to exclude the subPartition interfaces. Anyway, its not used anymore | ||
| 1964 | /* | ||
| 1965 | (outExp, outNewEqs, outNewVars, outClkCnt) := match listGet(inExpLst, 2) | ||
| 1966 | local | ||
| 1967 | BackendDAE.Var var; | ||
| 1968 | BackendDAE.Equation eq; | ||
| 1969 | case DAE.ICONST(0) | ||
| 1970 | then (e, inNewEqs, inNewVars, inClkCnt); | ||
| 1971 | else | ||
| 1972 | algorithm | ||
| 1973 | (var, eq) = createSubClockVar(inPartitionIdx, inClkCnt, inPath, inExpLst, inAttr, inPartitions, inVars, mT); | ||
| 1974 | then | ||
| 1975 | (e, eq::inNewEqs, var::inNewVars, inClkCnt + 1); | ||
| 1976 | end match; | ||
| 1977 | */ | ||
| 1978 | end createSubClockVarFactor; | ||
| 1979 | |||
| 1980 | protected function substGetPartition | ||
| 1981 | input DAE.Exp inExp; | ||
| 1982 | output DAE.Exp outExp; | ||
| 1983 | protected | ||
| 1984 | DAE.CallAttributes attrs; | ||
| 1985 | algorithm | ||
| 1986 | 125 | attrs := DAE.CALL_ATTR(Expression.typeof(inExp), false, true, true, false, DAE.NO_INLINE(), DAE.NO_TAIL(), DAE.NoReturn.RETURNS); | |
| 1987 | 125 | outExp := DAE.CALL(Absyn.IDENT("$getPart"), {inExp}, attrs); | |
| 1988 | end substGetPartition; | ||
| 1989 | |||
| 1990 | protected function getSubClkName | ||
| 1991 | input Integer inPartitionIdx; | ||
| 1992 | input Integer inClkIdx; | ||
| 1993 | input DAE.Type inTy = DAE.T_CLOCK_DEFAULT; | ||
| 1994 | output DAE.ComponentRef outRef; | ||
| 1995 | protected | ||
| 1996 | String name; | ||
| 1997 | algorithm | ||
| 1998 | 140 | name := "$subclk" + intString(inPartitionIdx) + "_" + intString(inClkIdx); | |
| 1999 | 140 | outRef := DAE.CREF_IDENT(name, inTy, {}); | |
| 2000 | end getSubClkName; | ||
| 2001 | |||
| 2002 | protected function createSubClock | ||
| 2003 | input Integer inPartitionIdx; | ||
| 2004 | input Integer inCnt; | ||
| 2005 | input DAE.Exp inExp; | ||
| 2006 | output BackendDAE.Var outVar; | ||
| 2007 | output BackendDAE.Equation outEq; | ||
| 2008 | protected | ||
| 2009 | DAE.Type ty; | ||
| 2010 | DAE.ComponentRef cr; | ||
| 2011 | algorithm | ||
| 2012 | ty := DAE.T_CLOCK_DEFAULT; | ||
| 2013 | 140 | cr := getSubClkName(inPartitionIdx, inCnt, ty); | |
| 2014 | 140 | (outVar, outEq) := createEqVarPair(cr, ty, inExp); | |
| 2015 | end createSubClock; | ||
| 2016 | |||
| 2017 | protected function collectSubclkInfo | ||
| 2018 | "Create new clock equations and variables from equations: | ||
| 2019 | - r = sample(e, clk) -- clockVar: $subclki_n; clockEq: $subclki_n = clk; eq: r = $getPart(e); | ||
| 2020 | - r = subSample(e, e1) -- clockVar: $subclki_n; clockEq: $subclki_n = subSample($subclkj_1, e1); eq: r = $getPart(e); | ||
| 2021 | - r = shiftSample(e, e1, e2) -- clockVar: $subclki_n; clockEq: $subclki_n = shiftSample($subclkj_1, e1, e2); eq: r = $getPart(e); | ||
| 2022 | - r = backSample(e, e1, e2) -- clockVar: $subclki_n; clockEq: $subclki_n = backSample($subclkj_1, e1, e2); eq: r = $getPart(e); | ||
| 2023 | - r = noClock(e) -- eq: r = $getPart(e); | ||
| 2024 | where subclki_n -- n subclock of partition, which r expression belongs; | ||
| 2025 | subclkj_n -- n subclock of partition, which e expression belongs; | ||
| 2026 | clockVar, clockEq -- new clock variables and equations; | ||
| 2027 | eq -- replaced equation. | ||
| 2028 | Detect clocked continuous partitions according the rule: | ||
| 2029 | If equation contains operator der, delay, spatialDistribution, event related operators | ||
| 2030 | , or when clause, it is a clocked continuous equation. | ||
| 2031 | If a clocked partition is not a clocked continuous partition and it contains operator previous | ||
| 2032 | , or interval, it is a clocked discrete equation." | ||
| 2033 | input BackendDAE.EquationArray inEqs; | ||
| 2034 | input BackendDAE.EquationArray inRemovedEqs; | ||
| 2035 | input Integer inPartitionCnt; | ||
| 2036 | input array<Integer> inPartitions; | ||
| 2037 | input array<Integer> inReqsPartitions; | ||
| 2038 | input BackendDAE.Variables inVars; | ||
| 2039 | input BackendDAE.AdjacencyMatrix mT; | ||
| 2040 | output list<BackendDAE.Equation> outNewEqs; | ||
| 2041 | output list<BackendDAE.Var> outNewVars; | ||
| 2042 | output array<Option<Boolean>> outContPartitions; | ||
| 2043 | output array<Integer> oClksCnt; | ||
| 2044 | protected | ||
| 2045 | BackendDAE.Equation eq; | ||
| 2046 | Integer i, j, cnt; | ||
| 2047 | BackendDAE.Equation eq; | ||
| 2048 | DAE.ComponentRef cr; | ||
| 2049 | BackendDAE.Var var; | ||
| 2050 | array<list<Integer>> partitionsWhenClocks; | ||
| 2051 | algorithm | ||
| 2052 | 46 | outContPartitions := arrayCreate(inPartitionCnt, NONE()); | |
| 2053 | 46 | partitionsWhenClocks := arrayCreate(inPartitionCnt, {}); | |
| 2054 | 46 | oClksCnt := arrayCreate(inPartitionCnt, 1); | |
| 2055 | |||
| 2056 | 46 | (outNewEqs, outNewVars) := collectEquationArrayClocks ( | |
| 2057 | inEqs, inPartitionCnt, inPartitions, partitionsWhenClocks, oClksCnt, | ||
| 2058 | outContPartitions, inVars, mT, {}, {} | ||
| 2059 | ); | ||
| 2060 | 46 | (outNewEqs, outNewVars) := collectEquationArrayClocks ( | |
| 2061 | inRemovedEqs, inPartitionCnt, inReqsPartitions, partitionsWhenClocks, oClksCnt, | ||
| 2062 | outContPartitions, inVars, mT, outNewEqs, outNewVars | ||
| 2063 | ); | ||
| 2064 | |||
| 2065 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
|
113 | for i in 1:inPartitionCnt loop |
| 2066 |
2/2✓ Branch 1 taken 105 times.
✓ Branch 2 taken 67 times.
|
172 | for j in arrayGet(partitionsWhenClocks, i) loop |
| 2067 | //For each when clock j in partition i create equation "$subclki_n = $whenclkj" | ||
| 2068 | 105 | cnt := arrayGet(oClksCnt, i); | |
| 2069 | 105 | cr := DAE.CREF_IDENT(BackendDAE.WHENCLK_PRREFIX + intString(j), DAE.T_CLOCK_DEFAULT, {}); | |
| 2070 | 105 | (var, eq) := createSubClock(i, cnt, DAE.CREF(cr, DAE.T_CLOCK_DEFAULT)); | |
| 2071 | 105 | outNewEqs := eq::outNewEqs; | |
| 2072 | 105 | outNewVars := var::outNewVars; | |
| 2073 | 105 | arrayUpdate(oClksCnt, i, cnt + 1); | |
| 2074 | end for; | ||
| 2075 | //If no subclock for partition i is detected, create new one "$subclki_1 = Clock()" | ||
| 2076 |
2/2✓ Branch 1 taken 6 times.
✓ Branch 2 taken 61 times.
|
67 | if arrayGet(oClksCnt, i) == 1 then |
| 2077 | 6 | (var, eq) := createSubClock(i, 1, DAE.CLKCONST(DAE.INFERRED_CLOCK())); | |
| 2078 | 6 | outNewEqs := eq::outNewEqs; | |
| 2079 | 6 | outNewVars := var::outNewVars; | |
| 2080 | 6 | arrayUpdate(oClksCnt, i, 2); | |
| 2081 | end if; | ||
| 2082 | end for; | ||
| 2083 | end collectSubclkInfo; | ||
| 2084 | |||
| 2085 | protected function collectEquationArrayClocks | ||
| 2086 | input BackendDAE.EquationArray eqs; | ||
| 2087 | input Integer partitionsCnt; | ||
| 2088 | input array<Integer> partitions; | ||
| 2089 | input array<list<Integer>> partitionsWhenClocks; | ||
| 2090 | input array<Integer> clksCnt; | ||
| 2091 | input array<Option<Boolean>> contPartitions; | ||
| 2092 | input BackendDAE.Variables inVars; | ||
| 2093 | input BackendDAE.AdjacencyMatrix mT; | ||
| 2094 | input list<BackendDAE.Equation> inNewEqs; | ||
| 2095 | input list<BackendDAE.Var> inNewVars; | ||
| 2096 | output list<BackendDAE.Equation> outNewEqs = inNewEqs; | ||
| 2097 | output list<BackendDAE.Var> outNewVars = inNewVars; | ||
| 2098 | protected | ||
| 2099 | BackendDAE.Equation eq; | ||
| 2100 | BackendDAE.EquationAttributes eqAttr; | ||
| 2101 | Integer partitionIdx; | ||
| 2102 | SourceInfo source; | ||
| 2103 | algorithm | ||
| 2104 |
2/2✓ Branch 1 taken 46 times.
✓ Branch 2 taken 46 times.
|
789 | for i in 1:BackendEquation.getNumberOfEquations(eqs) loop |
| 2105 | 697 | eq := BackendEquation.get(eqs, i); | |
| 2106 | 697 | partitionIdx := arrayGet(partitions, i); | |
| 2107 | 697 | DAE.SOURCE(info = source) := BackendEquation.equationSource(eq); | |
| 2108 | |||
| 2109 |
1/2✓ Branch 0 taken 697 times.
✗ Branch 1 not taken.
|
697 | if partitionIdx <>0 then |
| 2110 | 697 | eqAttr := BackendEquation.getEquationAttributes(eq); | |
| 2111 | eqAttr := match eqAttr | ||
| 2112 | local | ||
| 2113 | Integer whenIdx; | ||
| 2114 | list<Integer> partitionsWhenClocksLst; | ||
| 2115 | case BackendDAE.EQUATION_ATTRIBUTES(kind=BackendDAE.CLOCKED_EQUATION(whenIdx)) | ||
| 2116 | algorithm | ||
| 2117 | 127 | partitionsWhenClocksLst := partitionsWhenClocks[partitionIdx]; | |
| 2118 |
3/4✓ Branch 0 taken 127 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 105 times.
✓ Branch 4 taken 22 times.
|
127 | if whenIdx <> 0 and List.notMember(whenIdx, partitionsWhenClocksLst) then |
| 2119 | 105 | arrayUpdate(partitionsWhenClocks, partitionIdx, whenIdx::partitionsWhenClocksLst); | |
| 2120 | end if; | ||
| 2121 | 127 | eqAttr.kind := BackendDAE.DYNAMIC_EQUATION(); | |
| 2122 | then eqAttr; | ||
| 2123 | else eqAttr; | ||
| 2124 | end match; | ||
| 2125 | 697 | eq := BackendEquation.setEquationAttributes(eq, eqAttr); | |
| 2126 | |||
| 2127 | 697 | (eq, (outNewEqs, outNewVars, _, _, _, _, _, _, _)) | |
| 2128 | := BackendEquation.traverseExpsOfEquation ( | ||
| 2129 | eq, collectSubclkInfoExp1, ( outNewEqs, outNewVars, contPartitions, source, | ||
| 2130 | clksCnt, partitionIdx, partitions, inVars, mT ) ); | ||
| 2131 | 697 | BackendEquation.setAtIndex(eqs, i, eq); | |
| 2132 | end if; | ||
| 2133 | end for; | ||
| 2134 | end collectEquationArrayClocks; | ||
| 2135 | |||
| 2136 | protected function collectSubclkInfoExp1 | ||
| 2137 | input DAE.Exp inExp; | ||
| 2138 | input tuple< list<BackendDAE.Equation>, list<BackendDAE.Var>, array<Option<Boolean>>, SourceInfo, | ||
| 2139 | array<Integer>, Integer, array<Integer>, BackendDAE.Variables, BackendDAE.AdjacencyMatrix > inTpl; | ||
| 2140 | output DAE.Exp outExp; | ||
| 2141 | output tuple< list<BackendDAE.Equation>, list<BackendDAE.Var>, array<Option<Boolean>>, SourceInfo, | ||
| 2142 | array<Integer>, Integer, array<Integer>, BackendDAE.Variables, BackendDAE.AdjacencyMatrix > outTpl; | ||
| 2143 | algorithm | ||
| 2144 | 1394 | (outExp, outTpl) := Expression.traverseExpBottomUp(inExp, collectSubclkInfoExp, inTpl); | |
| 2145 | end collectSubclkInfoExp1; | ||
| 2146 | |||
| 2147 | protected function splitClockEqs | ||
| 2148 | input BackendDAE.EquationArray inEqs; | ||
| 2149 | output BackendDAE.EquationArray outClockEqs; | ||
| 2150 | output array<Boolean> outClockEqsMask; | ||
| 2151 | protected | ||
| 2152 | list<BackendDAE.Equation> clockEqs = {}; | ||
| 2153 | BackendDAE.Equation eq; | ||
| 2154 | Integer i; | ||
| 2155 | algorithm | ||
| 2156 | 46 | outClockEqsMask := arrayCreate(BackendEquation.getNumberOfEquations(inEqs), true); | |
| 2157 |
1/2✓ Branch 1 taken 46 times.
✗ Branch 2 not taken.
|
743 | for i in 1:BackendEquation.getNumberOfEquations(inEqs) loop |
| 2158 | 697 | eq := BackendEquation.get(inEqs, i); | |
| 2159 |
2/2✓ Branch 1 taken 172 times.
✓ Branch 2 taken 525 times.
|
697 | if isClockEquation(eq) then |
| 2160 | clockEqs := eq::clockEqs; | ||
| 2161 | 172 | arrayUpdate(outClockEqsMask, i, false); | |
| 2162 | end if; | ||
| 2163 | end for; | ||
| 2164 | 46 | outClockEqs := BackendEquation.listEquation(clockEqs); | |
| 2165 | end splitClockEqs; | ||
| 2166 | |||
| 2167 | protected function splitClockVars | ||
| 2168 | input BackendDAE.Variables inVars; | ||
| 2169 | output BackendDAE.Variables outClockVars; | ||
| 2170 | output array<Boolean> outClockVarsMask; | ||
| 2171 | protected | ||
| 2172 | list<BackendDAE.Var> clockVars = {}; | ||
| 2173 | BackendDAE.Var var; | ||
| 2174 | algorithm | ||
| 2175 | 46 | outClockVarsMask := arrayCreate(BackendVariable.varsSize(inVars), true); | |
| 2176 |
1/2✓ Branch 1 taken 46 times.
✗ Branch 2 not taken.
|
742 | for i in 1:BackendVariable.varsSize(inVars) loop |
| 2177 | 696 | var := BackendVariable.getVarAt(inVars, i); | |
| 2178 |
2/2✓ Branch 1 taken 171 times.
✓ Branch 2 taken 525 times.
|
696 | if Types.isClockOrSubTypeClock(var.varType) then |
| 2179 | clockVars := var :: clockVars; | ||
| 2180 | 171 | arrayUpdate(outClockVarsMask, i, false); | |
| 2181 | end if; | ||
| 2182 | end for; | ||
| 2183 | 46 | outClockVars := BackendVariable.listVar(clockVars); | |
| 2184 | end splitClockVars; | ||
| 2185 | |||
| 2186 | protected function substitutePartitionOpExps | ||
| 2187 | "Each non-trivial expression (non-literal, non-constant, non-parameter, non-variable), expr_i, appearing | ||
| 2188 | as first argument of any clock conversion operator or in base clock constructor is recursively replaced by a unique variable, $var_i, | ||
| 2189 | and the equation $var_i = expr_i is added to the equation set. | ||
| 2190 | Also when clauses are created for event clocks." | ||
| 2191 | input BackendDAE.EqSystem inSyst; | ||
| 2192 | input BackendDAE.Shared inShared; | ||
| 2193 | output BackendDAE.EqSystem outSyst = inSyst; | ||
| 2194 | protected | ||
| 2195 | list<BackendDAE.Equation> newEqs = {}; | ||
| 2196 | list<BackendDAE.Var> newVars = {}; | ||
| 2197 | Integer cnt = 1; | ||
| 2198 | algorithm | ||
| 2199 |
2/2✓ Branch 2 taken 158348 times.
✓ Branch 3 taken 1069 times.
|
159417 | for eq in BackendEquation.equationList(inSyst.orderedEqs) loop |
| 2200 | 158348 | (eq, (newEqs, newVars, cnt, _)) := BackendEquation.traverseExpsOfEquation(eq, substitutePartitionOpExp, (newEqs, newVars, cnt, inShared)); | |
| 2201 | newEqs := eq::newEqs; | ||
| 2202 | end for; | ||
| 2203 | 1069 | outSyst.orderedEqs := BackendEquation.listEquation(listReverse(newEqs)); | |
| 2204 | outSyst.orderedVars := BackendVariable.addVars(newVars, inSyst.orderedVars); | ||
| 2205 | 1069 | outSyst := BackendDAEUtil.clearEqSyst(outSyst); | |
| 2206 | end substitutePartitionOpExps; | ||
| 2207 | |||
| 2208 | protected function substitutePartitionOpExp | ||
| 2209 | input DAE.Exp inExp; | ||
| 2210 | input tuple<list<BackendDAE.Equation>,list<BackendDAE.Var>, Integer, BackendDAE.Shared> inTpl; | ||
| 2211 | output DAE.Exp outExp; | ||
| 2212 | output tuple<list<BackendDAE.Equation>,list<BackendDAE.Var>, Integer, BackendDAE.Shared> outTpl; | ||
| 2213 | algorithm | ||
| 2214 | 319067 | (outExp, outTpl) := Expression.traverseExpBottomUp(inExp, substitutePartitionOpExp1, inTpl); | |
| 2215 | end substitutePartitionOpExp; | ||
| 2216 | |||
| 2217 | protected function substitutePartitionOpExp1 | ||
| 2218 | input DAE.Exp inExp; | ||
| 2219 | input tuple<list<BackendDAE.Equation>,list<BackendDAE.Var>, Integer, BackendDAE.Shared> inTpl; | ||
| 2220 | output DAE.Exp outExp; | ||
| 2221 | output tuple<list<BackendDAE.Equation>,list<BackendDAE.Var>, Integer, BackendDAE.Shared> outTpl; | ||
| 2222 | protected | ||
| 2223 | Absyn.Path path; | ||
| 2224 | BackendDAE.Shared shared; | ||
| 2225 | DAE.CallAttributes attr; | ||
| 2226 | DAE.ClockKind clk; | ||
| 2227 | Integer cnt; | ||
| 2228 | list<BackendDAE.Equation> newEqs; | ||
| 2229 | list<BackendDAE.Var> newVars; | ||
| 2230 | list<DAE.Exp> exps; | ||
| 2231 | algorithm | ||
| 2232 |
3/3✓ Branch 0 taken 125 times.
✓ Branch 1 taken 35643 times.
✓ Branch 2 taken 1241957 times.
|
1277725 | (newEqs, newVars, cnt, shared) := inTpl; |
| 2233 | (outExp, outTpl) := match inExp | ||
| 2234 | case DAE.CLKCONST(clk) algorithm | ||
| 2235 | 125 | (clk, newEqs, newVars, cnt) := substClock(clk, newEqs, newVars, cnt, shared); | |
| 2236 | 125 | then (DAE.CLKCONST(clk), (newEqs, newVars, cnt, shared)); | |
| 2237 | |||
| 2238 | case DAE.CALL(path=path, expLst=exps, attr=attr) | ||
| 2239 | 35643 | then substituteExpsCall(path, exps, attr, newEqs, newVars, cnt, shared); | |
| 2240 | |||
| 2241 | 1241957 | else (inExp, inTpl); | |
| 2242 | end match; | ||
| 2243 | end substitutePartitionOpExp1; | ||
| 2244 | |||
| 2245 | protected function substClock | ||
| 2246 | input DAE.ClockKind inClk; | ||
| 2247 | input list<BackendDAE.Equation> inNewEqs; | ||
| 2248 | input list<BackendDAE.Var> inNewVars; | ||
| 2249 | input Integer inCnt; | ||
| 2250 | input BackendDAE.Shared inShared; | ||
| 2251 | output DAE.ClockKind outClk; | ||
| 2252 | output list<BackendDAE.Equation> outNewEqs; | ||
| 2253 | output list<BackendDAE.Var> outNewVars; | ||
| 2254 | output Integer outCnt; | ||
| 2255 | protected | ||
| 2256 | DAE.Exp e, i, f; | ||
| 2257 | Integer cnt; | ||
| 2258 | list<BackendDAE.Equation> eqs; | ||
| 2259 | list<BackendDAE.Var> vars; | ||
| 2260 | algorithm | ||
| 2261 | (outClk, outNewEqs, outNewVars, outCnt) := match inClk | ||
| 2262 | case DAE.EVENT_CLOCK(e, f) algorithm | ||
| 2263 |
2/4✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11 times.
|
11 | ({e}, eqs, vars, cnt) := substExp({e}, inNewEqs, inNewVars, inCnt); |
| 2264 | 11 | then (DAE.EVENT_CLOCK(e, f), eqs, vars, cnt); | |
| 2265 | |||
| 2266 | case DAE.REAL_CLOCK(e) algorithm | ||
| 2267 | 15 | (e, eqs, vars, cnt) := substClockExp(e, inNewEqs, inNewVars, inCnt, inShared); | |
| 2268 | 15 | then (DAE.REAL_CLOCK(e), eqs, vars, cnt); | |
| 2269 | |||
| 2270 | case DAE.RATIONAL_CLOCK(e, i) algorithm | ||
| 2271 | 17 | (e, eqs, vars, cnt) := substClockExp(e, inNewEqs, inNewVars, inCnt, inShared); | |
| 2272 | 17 | then (DAE.RATIONAL_CLOCK(e, i), eqs, vars, cnt); | |
| 2273 | |||
| 2274 | else (inClk, inNewEqs, inNewVars, inCnt); | ||
| 2275 | end match; | ||
| 2276 | end substClock; | ||
| 2277 | |||
| 2278 | protected function isKnownOrConstantExp "author: lochel | ||
| 2279 | Returns true if the given expression is constant or at least known (parameter dependent)." | ||
| 2280 | input DAE.Exp inExp; | ||
| 2281 | input BackendDAE.Variables inKnownVars; | ||
| 2282 | output Boolean outKnown; | ||
| 2283 | algorithm | ||
| 2284 | 32 | (_, (outKnown, _)) := Expression.traverseExpTopDown(inExp, isKnownOrConstantExp_traverser, (true, inKnownVars)); | |
| 2285 | end isKnownOrConstantExp; | ||
| 2286 | |||
| 2287 | protected function isKnownOrConstantExp_traverser | ||
| 2288 | input DAE.Exp inExp; | ||
| 2289 | input tuple<Boolean, BackendDAE.Variables> inTpl; | ||
| 2290 | output DAE.Exp outExp = inExp; | ||
| 2291 | output Boolean outContinue; | ||
| 2292 | output tuple<Boolean, BackendDAE.Variables> outTpl; | ||
| 2293 | protected | ||
| 2294 | BackendDAE.Variables globalKnownVars; | ||
| 2295 | Boolean isKnown; | ||
| 2296 | algorithm | ||
| 2297 |
2/3✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 32 times.
|
34 | (isKnown, globalKnownVars) := inTpl; |
| 2298 | isKnown := match inExp | ||
| 2299 | local | ||
| 2300 | DAE.ComponentRef componentRef; | ||
| 2301 | case DAE.CALL() then false; | ||
| 2302 | 2 | case DAE.CREF(componentRef=componentRef) then BackendVariable.containsCref(componentRef, globalKnownVars); | |
| 2303 | else isKnown; | ||
| 2304 | end match; | ||
| 2305 | |||
| 2306 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 32 times.
|
36 | outTpl := (isKnown, globalKnownVars); |
| 2307 | outContinue := isKnown; | ||
| 2308 | end isKnownOrConstantExp_traverser; | ||
| 2309 | |||
| 2310 | protected function substClockExp | ||
| 2311 | input DAE.Exp inExp; | ||
| 2312 | input list<BackendDAE.Equation> inNewEqs; | ||
| 2313 | input list<BackendDAE.Var> inNewVars; | ||
| 2314 | input Integer inCnt; | ||
| 2315 | input BackendDAE.Shared inShared; | ||
| 2316 | output DAE.Exp outExp; | ||
| 2317 | output list<BackendDAE.Equation> outNewEqs; | ||
| 2318 | output list<BackendDAE.Var> outNewVars; | ||
| 2319 | output Integer outCnt; | ||
| 2320 | algorithm | ||
| 2321 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 30 times.
|
32 | if isKnownOrConstantExp(inExp, inShared.globalKnownVars) then |
| 2322 | outExp := inExp; | ||
| 2323 | outNewEqs := inNewEqs; | ||
| 2324 | outNewVars := inNewVars; | ||
| 2325 | outCnt := inCnt; | ||
| 2326 | else | ||
| 2327 |
2/4✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
2 | ({outExp}, outNewEqs, outNewVars, outCnt) := substExp({inExp}, inNewEqs, inNewVars, inCnt); |
| 2328 | end if; | ||
| 2329 | end substClockExp; | ||
| 2330 | |||
| 2331 | protected function substituteExpsCall | ||
| 2332 | input Absyn.Path inPath; | ||
| 2333 | input list<DAE.Exp> inExps; | ||
| 2334 | input DAE.CallAttributes inAttr; | ||
| 2335 | input list<BackendDAE.Equation> inEqs; | ||
| 2336 | input list<BackendDAE.Var> inVars; | ||
| 2337 | input Integer inCnt; | ||
| 2338 | input BackendDAE.Shared inShared; | ||
| 2339 | output DAE.Exp outExp; | ||
| 2340 | output tuple<list<BackendDAE.Equation>,list<BackendDAE.Var>, Integer, BackendDAE.Shared> outTpl; | ||
| 2341 | protected | ||
| 2342 | Boolean replace; | ||
| 2343 | list<DAE.Exp> exps; | ||
| 2344 | list<BackendDAE.Equation> eqs; | ||
| 2345 | list<BackendDAE.Var> vars; | ||
| 2346 | Integer cnt; | ||
| 2347 | algorithm | ||
| 2348 | replace := match (inPath, listLength(inExps)) | ||
| 2349 | case (Absyn.IDENT("hold"), 1) then true; | ||
| 2350 | case (Absyn.IDENT("sample"), 2) then true; | ||
| 2351 | case (Absyn.IDENT("subSample"), 2) then true; | ||
| 2352 | case (Absyn.IDENT("superSample"), 2) then true; | ||
| 2353 | case (Absyn.IDENT("shiftSample"), 3) then true; | ||
| 2354 | case (Absyn.IDENT("backSample"), 3) then true; | ||
| 2355 | case (Absyn.IDENT("noClock"), 1) then true; | ||
| 2356 | else false; | ||
| 2357 | end match; | ||
| 2358 | 35643 | (exps, eqs, vars, cnt) := | |
| 2359 | if replace then substExp(inExps, inEqs, inVars, inCnt) | ||
| 2360 | else (inExps, inEqs, inVars, inCnt); | ||
| 2361 | 35643 | outExp := DAE.CALL(inPath, exps, inAttr); | |
| 2362 | 35643 | outTpl := (eqs, vars, cnt, inShared); | |
| 2363 | end substituteExpsCall; | ||
| 2364 | |||
| 2365 | protected function createVar | ||
| 2366 | input DAE.ComponentRef inComp; | ||
| 2367 | input DAE.Type inType; | ||
| 2368 | output BackendDAE.Var outVar; | ||
| 2369 | algorithm | ||
| 2370 | 151 | outVar := BackendDAE.VAR ( | |
| 2371 | varName = inComp, varKind = BackendDAE.VARIABLE(), | ||
| 2372 | varDirection = DAE.BIDIR(), varParallelism = DAE.NON_PARALLEL(), | ||
| 2373 | varType = inType, bindExp = NONE(), tplExp = NONE(), | ||
| 2374 | arryDim = {}, source = DAE.emptyElementSource, | ||
| 2375 | values = DAEUtil.setProtectedAttr(DAEUtil.getEmptyVarAttr(inType), true), tearingSelectOption = SOME(BackendDAE.DEFAULT()), | ||
| 2376 | hideResult = NONE(), | ||
| 2377 | comment = NONE(), connectorType = DAE.NON_CONNECTOR(), | ||
| 2378 | innerOuter = DAE.NOT_INNER_OUTER(), unreplaceable = false, initNonlinear = false, encrypted = false); | ||
| 2379 | end createVar; | ||
| 2380 | |||
| 2381 | protected function createEqVarPair | ||
| 2382 | input DAE.ComponentRef inComp; | ||
| 2383 | input DAE.Type inType; | ||
| 2384 | input DAE.Exp inExp; | ||
| 2385 | output BackendDAE.Var outVar; | ||
| 2386 | output BackendDAE.Equation outEq; | ||
| 2387 | algorithm | ||
| 2388 | 151 | outVar := createVar(inComp, inType); | |
| 2389 | 151 | outEq := BackendDAE.EQUATION( exp = DAE.CREF(componentRef = inComp, ty = inType), scalar = inExp, | |
| 2390 | source = DAE.emptyElementSource, attr = BackendDAE.EQ_ATTR_DEFAULT_DYNAMIC ); | ||
| 2391 | end createEqVarPair; | ||
| 2392 | |||
| 2393 | protected function substExp | ||
| 2394 | input list<DAE.Exp> inExps; | ||
| 2395 | input list<BackendDAE.Equation> inEqs; | ||
| 2396 | input list<BackendDAE.Var> inVars; | ||
| 2397 | input Integer inCnt; | ||
| 2398 | output tuple<list<DAE.Exp>, list<BackendDAE.Equation>, list<BackendDAE.Var>, Integer> outTpl; | ||
| 2399 | protected | ||
| 2400 | Boolean create; | ||
| 2401 | DAE.Exp e; | ||
| 2402 | algorithm | ||
| 2403 | 138 | e := listHead(inExps); | |
| 2404 | create := match e | ||
| 2405 | case DAE.CREF() then false; | ||
| 2406 | case DAE.RCONST() then false; | ||
| 2407 | case DAE.SCONST() then false; | ||
| 2408 | case DAE.BCONST() then false; | ||
| 2409 | case DAE.ENUM_LITERAL() then false; | ||
| 2410 | case DAE.CLKCONST() then true; | ||
| 2411 | else true; | ||
| 2412 | end match; | ||
| 2413 | outTpl := match create | ||
| 2414 | local | ||
| 2415 | DAE.ComponentRef cr; | ||
| 2416 | DAE.Type ty; | ||
| 2417 | BackendDAE.Equation eq; | ||
| 2418 | BackendDAE.Var var; | ||
| 2419 | case true | ||
| 2420 | algorithm | ||
| 2421 | 11 | ty := Expression.typeof(e); | |
| 2422 | 11 | cr := DAE.CREF_IDENT("$var" + intString(inCnt), ty, {}); | |
| 2423 | 11 | (var, eq) := createEqVarPair(cr, ty, e); | |
| 2424 | 33 | then (DAE.CREF(cr, ty)::listRest(inExps), eq::inEqs, var::inVars, inCnt + 1); | |
| 2425 | case false | ||
| 2426 | 127 | then (inExps, inEqs, inVars, inCnt); | |
| 2427 | end match; | ||
| 2428 | end substExp; | ||
| 2429 | |||
| 2430 | protected function getVarIxs | ||
| 2431 | input DAE.ComponentRef inComp; | ||
| 2432 | input BackendDAE.Variables inVariables; | ||
| 2433 | output list<Integer> outIntegerLst; | ||
| 2434 | algorithm | ||
| 2435 | outIntegerLst := matchcontinue inComp | ||
| 2436 | local | ||
| 2437 | list<Integer> ixs; | ||
| 2438 | case _ | ||
| 2439 | algorithm | ||
| 2440 | 421 | (_, ixs) := BackendVariable.getVar(inComp, inVariables); | |
| 2441 | 356 | then ixs; | |
| 2442 | else | ||
| 2443 | then {}; | ||
| 2444 | end matchcontinue; | ||
| 2445 | end getVarIxs; | ||
| 2446 | |||
| 2447 | protected function baseClockPartitioning | ||
| 2448 | "Do base clock partitioning and detect kind of new partitions(clocked or continuous)." | ||
| 2449 | input BackendDAE.EqSystem inSyst; | ||
| 2450 | input BackendDAE.Shared inShared; | ||
| 2451 | output list<BackendDAE.EqSystem> outContSysts = {}; | ||
| 2452 | output list<BackendDAE.EqSystem> outClockedSysts = {}; | ||
| 2453 | output list<BackendDAE.Equation> outUnpartRemEqs; | ||
| 2454 | protected | ||
| 2455 | BackendDAE.Variables vars; | ||
| 2456 | BackendDAE.EquationArray eqs; | ||
| 2457 | AvlTreePathFunction.Tree funcs; | ||
| 2458 | BackendDAE.AdjacencyMatrix m, mT, rm, rmT; | ||
| 2459 | BackendDAE.EqSystem syst; | ||
| 2460 | BackendDAE.EqSystems systs; | ||
| 2461 | Integer partitionCnt, i, j; | ||
| 2462 | DAE.ComponentRef cr; | ||
| 2463 | list<Integer> varIxs; | ||
| 2464 | BackendDAE.EqSystem syst; | ||
| 2465 | array<Integer> eqPartMap, varPartMap, reqsPartition; | ||
| 2466 | array<Boolean> varsPartition, rvarsPartition; | ||
| 2467 | BackendDAE.Equation eq; | ||
| 2468 | list<tuple<DAE.ComponentRef, Boolean>> refsInfo; | ||
| 2469 | tuple<DAE.ComponentRef, Boolean> refInfo; | ||
| 2470 | Option<Boolean> partitionType; | ||
| 2471 | Boolean isClocked, isInitial; | ||
| 2472 | array<Option<Boolean>> clockedEqs, clockedVars, clockedPartitions; | ||
| 2473 | SourceInfo info; | ||
| 2474 | algorithm | ||
| 2475 | 1288 | funcs := BackendDAEUtil.getFunctions(inShared); | |
| 2476 | 1288 | isInitial := BackendDAEUtil.isInitializationDAE(inShared); | |
| 2477 | 1288 | (syst, m, mT) := BackendDAEUtil.getAdjacencyMatrixfromOption(inSyst, BackendDAE.BASECLOCK_IDX(), SOME(funcs), isInitial); | |
| 2478 | 1288 | (rm, rmT) := BackendDAEUtil.removedAdjacencyMatrix(inSyst, BackendDAE.BASECLOCK_IDX(), SOME(funcs), isInitial); | |
| 2479 | |||
| 2480 | 1288 | BackendDAE.EQSYSTEM(orderedVars = vars, orderedEqs = eqs) := syst; | |
| 2481 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1288 times.
|
2576 | eqPartMap := arrayCreate(arrayLength(m), 0); |
| 2482 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1288 times.
|
2576 | varPartMap := arrayCreate(arrayLength(mT), 0); |
| 2483 | |||
| 2484 | 1288 | reqsPartition := arrayCreate(arrayLength(rm), 0); | |
| 2485 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1288 times.
|
2576 | varsPartition := arrayCreate(arrayLength(mT), false); |
| 2486 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1288 times.
|
2576 | rvarsPartition := arrayCreate(arrayLength(rmT), false); |
| 2487 | |||
| 2488 | 1288 | partitionCnt := partitionIndependentBlocks0(m, mT, rm, rmT, eqPartMap, varPartMap, reqsPartition, varsPartition, rvarsPartition); | |
| 2489 | |||
| 2490 |
2/2✓ Branch 0 taken 480 times.
✓ Branch 1 taken 808 times.
|
1288 | if partitionCnt > 1 then |
| 2491 | 480 | (systs, outUnpartRemEqs) := partitionIndependentBlocksSplitBlocks(partitionCnt, syst, eqPartMap, reqsPartition, mT, rmT, false, funcs, BackendDAEUtil.isInitializationDAE(inShared)); | |
| 2492 | else | ||
| 2493 | 808 | (systs, outUnpartRemEqs) := ({syst}, {}); | |
| 2494 | end if; | ||
| 2495 | |||
| 2496 | //Partitioning finished | ||
| 2497 | 1287 | clockedEqs := arrayCreate(BackendEquation.getNumberOfEquations(eqs), NONE()); | |
| 2498 | 1287 | clockedVars := arrayCreate(BackendVariable.varsSize(vars), NONE()); | |
| 2499 | 1287 | clockedPartitions := arrayCreate(if partitionCnt > 0 then partitionCnt else 1, NONE()); | |
| 2500 | //Detect clocked equations and variables | ||
| 2501 | j := 0; | ||
| 2502 |
2/2✓ Branch 1 taken 170062 times.
✓ Branch 2 taken 1287 times.
|
171349 | for eq in BackendEquation.equationList(eqs) loop |
| 2503 | 170062 | j := j+1; | |
| 2504 | 170062 | (partitionType, refsInfo) := detectEqPartition(eq); | |
| 2505 | 170062 | info := BackendEquation.equationInfo(eq); | |
| 2506 | 170062 | arrayUpdate(clockedEqs, j, setClockedPartition(partitionType, arrayGet(clockedEqs, j), NONE(), info)); | |
| 2507 |
2/2✓ Branch 0 taken 136 times.
✓ Branch 1 taken 170062 times.
|
170198 | for refInfo in refsInfo loop |
| 2508 | 136 | (cr, isClocked) := refInfo; | |
| 2509 | 136 | varIxs := getVarIxs(cr, vars); | |
| 2510 |
2/2✓ Branch 1 taken 71 times.
✓ Branch 2 taken 136 times.
|
207 | for i in varIxs loop |
| 2511 |
2/2✓ Branch 1 taken 35 times.
✓ Branch 2 taken 36 times.
|
142 | arrayUpdate(clockedVars, i, setClockedPartition(SOME(isClocked), arrayGet(clockedVars, i), SOME(cr), info)); |
| 2512 | end for; | ||
| 2513 | end for; | ||
| 2514 | end for; | ||
| 2515 | //Clocked vars should belong to clocked equation | ||
| 2516 |
2/2✓ Branch 0 taken 1263 times.
✓ Branch 1 taken 24 times.
|
219758 | for i in 1:arrayLength(clockedVars) loop |
| 2517 | 218471 | partitionType := arrayGet(clockedVars, i); | |
| 2518 | 218471 | cr := BackendVariable.varCref(BackendVariable.getVarAt(vars, i)); | |
| 2519 |
2/2✓ Branch 1 taken 476112 times.
✓ Branch 2 taken 218471 times.
|
694583 | for j in arrayGet(mT, i) loop |
| 2520 | 476112 | info := BackendEquation.equationInfo(BackendEquation.get(eqs, j)); | |
| 2521 | 476112 | arrayUpdate(clockedEqs, j, setClockedPartition(partitionType, arrayGet(clockedEqs, j), SOME(cr), info)); | |
| 2522 | end for; | ||
| 2523 | end for; | ||
| 2524 | //Detect clocked partitions (clocked equations should belong to clocked partitions) | ||
| 2525 |
2/2✓ Branch 0 taken 1263 times.
✓ Branch 1 taken 24 times.
|
171349 | for i in 1:arrayLength(clockedEqs) loop |
| 2526 | 170062 | partitionType := arrayGet(clockedEqs, i); | |
| 2527 | 170062 | info := BackendEquation.equationInfo(BackendEquation.get(eqs, i)); | |
| 2528 | 170062 | j := arrayGet(eqPartMap, i); | |
| 2529 | 170062 | arrayUpdate(clockedPartitions, j, setClockedPartition(partitionType, arrayGet(clockedPartitions, j), NONE(), info)); | |
| 2530 | end for; | ||
| 2531 | |||
| 2532 | i := 1; | ||
| 2533 |
2/2✓ Branch 1 taken 19433 times.
✓ Branch 2 taken 1287 times.
|
20720 | for syst in systs loop |
| 2534 | (outContSysts, outClockedSysts) := match arrayGet(clockedPartitions, i) | ||
| 2535 | case SOME(false) | ||
| 2536 | 29 | then (setSystPartition(syst, BackendDAE.CONTINUOUS_TIME_PARTITION()) :: outContSysts, outClockedSysts); | |
| 2537 | /* Other partitions where none of the variables in the partition are associated with any of the operators above have an | ||
| 2538 | * unspecified partition kind and are considered continuous-time partitions. */ | ||
| 2539 | case NONE() | ||
| 2540 | 19358 | then (setSystPartition(syst, BackendDAE.UNSPECIFIED_PARTITION()) :: outContSysts, outClockedSysts); | |
| 2541 | case SOME(true) then (outContSysts, syst :: outClockedSysts); | ||
| 2542 | end match; | ||
| 2543 | 19433 | i := i + 1; | |
| 2544 | end for; | ||
| 2545 | end baseClockPartitioning; | ||
| 2546 | |||
| 2547 | protected function isClockExp | ||
| 2548 | input DAE.Exp inExp; | ||
| 2549 | output Boolean out; | ||
| 2550 | algorithm | ||
| 2551 | 170378 | out := Types.isClockOrSubTypeClock(Expression.typeof(inExp)); | |
| 2552 | end isClockExp; | ||
| 2553 | |||
| 2554 | protected function isClockEquation | ||
| 2555 | input BackendDAE.Equation inEq; | ||
| 2556 | output Boolean out; | ||
| 2557 | algorithm | ||
| 2558 | out := match inEq | ||
| 2559 | local | ||
| 2560 | DAE.Exp e; | ||
| 2561 | list<list<BackendDAE.Equation>> trueEqs; | ||
| 2562 | list<BackendDAE.Equation> falseEqs, listEqs; | ||
| 2563 | BackendDAE.Equation eq; | ||
| 2564 | SourceInfo info; | ||
| 2565 | 154077 | case BackendDAE.EQUATION(scalar = e) then isClockExp(e); | |
| 2566 | 14528 | case BackendDAE.ARRAY_EQUATION(right = e) then isClockExp(e); | |
| 2567 | 15 | case BackendDAE.FOR_EQUATION(body = eq) then isClockEquation(eq); | |
| 2568 | 170 | case BackendDAE.SOLVED_EQUATION(exp = e) then isClockExp(e); | |
| 2569 | ✗ | case BackendDAE.RESIDUAL_EQUATION(exp = e) then isClockExp(e); | |
| 2570 | case BackendDAE.ALGORITHM() then false; | ||
| 2571 | case BackendDAE.WHEN_EQUATION(whenEquation=BackendDAE.WHEN_STMTS(whenStmtLst={BackendDAE.ASSIGN(right=e)})) | ||
| 2572 | algorithm | ||
| 2573 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 849 times.
|
849 | if isClockExp(e) then |
| 2574 | ✗ | DAE.SOURCE(info = info) := BackendEquation.equationSource(inEq); | |
| 2575 | ✗ | Error.addSourceMessageAndFail(Error.INVALID_CLOCK_EQUATION, {}, info); | |
| 2576 | end if; | ||
| 2577 | then false; | ||
| 2578 | case BackendDAE.WHEN_EQUATION(whenEquation=BackendDAE.WHEN_STMTS(whenStmtLst={BackendDAE.REINIT(value=e)})) | ||
| 2579 | algorithm | ||
| 2580 | ✗ | if isClockExp(e) then | |
| 2581 | ✗ | DAE.SOURCE(info = info) := BackendEquation.equationSource(inEq); | |
| 2582 | ✗ | Error.addSourceMessageAndFail(Error.INVALID_CLOCK_EQUATION, {}, info); | |
| 2583 | end if; | ||
| 2584 | then false; | ||
| 2585 | 754 | case BackendDAE.COMPLEX_EQUATION(right = e) then isClockExp(e); | |
| 2586 | case BackendDAE.IF_EQUATION(eqnstrue = trueEqs, eqnsfalse = falseEqs) | ||
| 2587 | algorithm | ||
| 2588 | ✗ | for listEqs in trueEqs loop | |
| 2589 | ✗ | for eq in listEqs loop | |
| 2590 | ✗ | if isClockEquation(eq) then | |
| 2591 | ✗ | DAE.SOURCE(info = info) := BackendEquation.equationSource(eq); | |
| 2592 | ✗ | Error.addSourceMessageAndFail(Error.INVALID_CLOCK_EQUATION, {}, info); | |
| 2593 | end if; | ||
| 2594 | end for; | ||
| 2595 | end for; | ||
| 2596 | ✗ | for eq in falseEqs loop | |
| 2597 | ✗ | if isClockEquation(eq) then | |
| 2598 | ✗ | DAE.SOURCE(info = info) := BackendEquation.equationSource(eq); | |
| 2599 | ✗ | Error.addSourceMessageAndFail(Error.INVALID_CLOCK_EQUATION, {}, info); | |
| 2600 | end if; | ||
| 2601 | end for; | ||
| 2602 | then false; | ||
| 2603 | else | ||
| 2604 | algorithm | ||
| 2605 | ✗ | Error.addInternalError(getInstanceName() + " failed.\n", sourceInfo()); | |
| 2606 | ✗ | then fail(); | |
| 2607 | end match; | ||
| 2608 | end isClockEquation; | ||
| 2609 | |||
| 2610 | protected function detectEqPartition | ||
| 2611 | "Detect clocked equation and variables according the rule: | ||
| 2612 | - variable u in sample(u) and a variable y in y = hold(ud) is in a continuous-time partition; | ||
| 2613 | - variables u and y in y = sample(uc), y = subSample(u), y = superSample(u), y = | ||
| 2614 | shiftSample(u), y = backSample(u), y = previous(u), are in a clocked partition; | ||
| 2615 | - equations in a clocked when clause in a clocked partition;" | ||
| 2616 | input BackendDAE.Equation inEq; | ||
| 2617 | output Option<Boolean> outPartitionType; | ||
| 2618 | output list<tuple<DAE.ComponentRef, Boolean>> refsInfo; | ||
| 2619 | protected | ||
| 2620 | Option<Boolean> partitionType; | ||
| 2621 | Boolean isClockEq; | ||
| 2622 | SourceInfo info; | ||
| 2623 | algorithm | ||
| 2624 | partitionType := match BackendEquation.getEquationAttributes(inEq) | ||
| 2625 | local | ||
| 2626 | case BackendDAE.EQUATION_ATTRIBUTES(kind = BackendDAE.CLOCKED_EQUATION()) | ||
| 2627 | then SOME(true); | ||
| 2628 | else NONE(); | ||
| 2629 | end match; | ||
| 2630 | 170062 | info := BackendEquation.equationInfo(inEq); | |
| 2631 | 170062 | (_, (partitionType, refsInfo, _)) := | |
| 2632 | BackendEquation.traverseExpsOfEquation(inEq, detectEqPartitionExp, (partitionType, {}, info)); | ||
| 2633 | 170062 | isClockEq := isClockEquation(inEq); | |
| 2634 |
2/2✓ Branch 0 taken 112 times.
✓ Branch 1 taken 169950 times.
|
170062 | outPartitionType := if isClockEq then setClockedPartition(SOME(true), partitionType, NONE(), info) |
| 2635 | else partitionType; | ||
| 2636 | end detectEqPartition; | ||
| 2637 | |||
| 2638 | protected function printPartitionType | ||
| 2639 | input Option<Boolean> isClockedPartition; | ||
| 2640 | output String out; | ||
| 2641 | algorithm | ||
| 2642 | out := match isClockedPartition | ||
| 2643 | case SOME(false) then "CONT_PARTITION"; | ||
| 2644 | case SOME(true) then "CLOCKED_PARTITION"; | ||
| 2645 | else "UNSPECIFIED_PARTITION"; | ||
| 2646 | end match; | ||
| 2647 | end printPartitionType; | ||
| 2648 | |||
| 2649 | protected function detectEqPartitionExp | ||
| 2650 | input DAE.Exp inExp; | ||
| 2651 | input tuple<Option<Boolean>, list<tuple<DAE.ComponentRef, Boolean>>, SourceInfo> inTpl; | ||
| 2652 | output DAE.Exp outExp; | ||
| 2653 | output tuple<Option<Boolean>, list<tuple<DAE.ComponentRef, Boolean>>, SourceInfo> outTpl; | ||
| 2654 | algorithm | ||
| 2655 | 344843 | (outExp, outTpl) := Expression.traverseExpTopDown(inExp, detectEqPartitionExp1, inTpl); | |
| 2656 | end detectEqPartitionExp; | ||
| 2657 | |||
| 2658 | protected function detectEqPartitionExp1 | ||
| 2659 | input DAE.Exp inExp; | ||
| 2660 | input tuple<Option<Boolean>, list<tuple<DAE.ComponentRef, Boolean>>, SourceInfo> inTpl; | ||
| 2661 | output DAE.Exp outExp = inExp; | ||
| 2662 | output Boolean cont; | ||
| 2663 | output tuple<Option<Boolean>, list<tuple<DAE.ComponentRef, Boolean>>, SourceInfo> outTpl; | ||
| 2664 | protected | ||
| 2665 | list<tuple<DAE.ComponentRef, Boolean>> refs; | ||
| 2666 | Option<Boolean> partition; | ||
| 2667 | SourceInfo info; | ||
| 2668 | algorithm | ||
| 2669 | 1425398 | (partition, refs, info) := inTpl; | |
| 2670 | (partition, refs, cont) := match inExp | ||
| 2671 | local | ||
| 2672 | Absyn.Path path; | ||
| 2673 | list<DAE.Exp> exps; | ||
| 2674 | DAE.Exp e; | ||
| 2675 | DAE.ComponentRef cr; | ||
| 2676 | case DAE.CLKCONST(DAE.EVENT_CLOCK(e, _)) | ||
| 2677 | algorithm | ||
| 2678 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
|
11 | DAE.CREF(cr, _) := e; |
| 2679 | 22 | then (partition, (cr, false)::refs, false); | |
| 2680 | case DAE.CALL(path = path, expLst = exps) | ||
| 2681 | 40700 | then detectEqPartitionCall(path, exps, refs, partition, info); | |
| 2682 | 1384687 | else (partition, refs, true); | |
| 2683 | end match; | ||
| 2684 | 1425398 | outTpl := (partition, refs, info); | |
| 2685 | end detectEqPartitionExp1; | ||
| 2686 | |||
| 2687 | protected function detectEqPartitionCall | ||
| 2688 | input Absyn.Path inPath; | ||
| 2689 | input list<DAE.Exp> inExps; | ||
| 2690 | input list<tuple<DAE.ComponentRef, Boolean>> inRefs; | ||
| 2691 | input Option<Boolean> inPartition; | ||
| 2692 | input SourceInfo info; | ||
| 2693 | output Option<Boolean> outPartition; | ||
| 2694 | output list<tuple<DAE.ComponentRef, Boolean>> outRefs; | ||
| 2695 | output Boolean cont; | ||
| 2696 | algorithm | ||
| 2697 | (outPartition, outRefs, cont) := match (inPath, inExps) | ||
| 2698 | local | ||
| 2699 | DAE.Exp e; | ||
| 2700 | case (Absyn.IDENT("hold"), {e}) | ||
| 2701 | 15 | then detectEqPartitionCall1(false, true, inPartition, e, inRefs, info); | |
| 2702 | case (Absyn.IDENT("sample"), {e, _}) | ||
| 2703 | 89 | then detectEqPartitionCall1(true, false, inPartition, e, inRefs, info); | |
| 2704 | case (Absyn.IDENT("subSample"), {e, _}) | ||
| 2705 | 5 | then detectEqPartitionCall1(true, true, inPartition, e, inRefs, info); | |
| 2706 | case (Absyn.IDENT("superSample"), {e, _}) | ||
| 2707 | 8 | then detectEqPartitionCall1(true, true, inPartition, e, inRefs, info); | |
| 2708 | case (Absyn.IDENT("shiftSample"), {e, _, _}) | ||
| 2709 | 5 | then detectEqPartitionCall1(true, true, inPartition, e, inRefs, info); | |
| 2710 | case (Absyn.IDENT("backSample"), {e, _, _}) | ||
| 2711 | 3 | then detectEqPartitionCall1(true, true, inPartition, e, inRefs, info); | |
| 2712 | case (Absyn.IDENT("noClock"), {e}) | ||
| 2713 | ✗ | then detectEqPartitionCall1(true, true, inPartition, e, inRefs, info); | |
| 2714 | 40575 | else (inPartition, inRefs, true); | |
| 2715 | end match; | ||
| 2716 | end detectEqPartitionCall; | ||
| 2717 | |||
| 2718 | protected function detectEqPartitionCall1 | ||
| 2719 | input Boolean expClocked; | ||
| 2720 | input Boolean refClocked; | ||
| 2721 | input Option<Boolean> inPartition; | ||
| 2722 | input DAE.Exp inExp; | ||
| 2723 | input list<tuple<DAE.ComponentRef, Boolean>> inRefs; | ||
| 2724 | input SourceInfo info; | ||
| 2725 | output Option<Boolean> outPartition; | ||
| 2726 | output list<tuple<DAE.ComponentRef, Boolean>> outRefs; | ||
| 2727 | output Boolean cont = false; | ||
| 2728 | algorithm | ||
| 2729 | (outPartition, outRefs) := match inExp | ||
| 2730 | local | ||
| 2731 | DAE.ComponentRef cr; | ||
| 2732 | case DAE.CREF(cr, _) | ||
| 2733 | algorithm | ||
| 2734 |
4/4✓ Branch 0 taken 89 times.
✓ Branch 1 taken 36 times.
✓ Branch 3 taken 15 times.
✓ Branch 4 taken 110 times.
|
464 | then (setClockedPartition(SOME(expClocked), inPartition, NONE(), info), (cr, refClocked)::inRefs); |
| 2735 | else | ||
| 2736 | algorithm | ||
| 2737 | ✗ | Error.addInternalError(getInstanceName() + " failed.\n", sourceInfo()); | |
| 2738 | ✗ | then fail(); | |
| 2739 | end match; | ||
| 2740 | end detectEqPartitionCall1; | ||
| 2741 | |||
| 2742 | protected function setSystPartition | ||
| 2743 | input BackendDAE.EqSystem inSyst; | ||
| 2744 | input BackendDAE.BaseClockPartitionKind inPartitionKind; | ||
| 2745 | output BackendDAE.EqSystem outSyst; | ||
| 2746 | algorithm | ||
| 2747 | outSyst := match inSyst | ||
| 2748 | local | ||
| 2749 | BackendDAE.EqSystem syst; | ||
| 2750 | case syst as BackendDAE.EQSYSTEM() | ||
| 2751 | algorithm | ||
| 2752 | 19387 | syst.partitionKind := inPartitionKind; | |
| 2753 | then syst; | ||
| 2754 | end match; | ||
| 2755 | end setSystPartition; | ||
| 2756 | |||
| 2757 | protected function getPartitionConflictError | ||
| 2758 | input Option<DAE.ComponentRef> inComp; | ||
| 2759 | output ErrorTypes.Message msg; | ||
| 2760 | output ErrorTypes.MessageTokens tokens; | ||
| 2761 | algorithm | ||
| 2762 | (msg, tokens) := match inComp | ||
| 2763 | local DAE.ComponentRef cr; | ||
| 2764 | ✗ | case SOME(cr) then ( Error.CONT_CLOCKED_PARTITION_CONFLICT_VAR, | |
| 2765 | {ComponentReferenceBasics.printComponentRefStr(cr)} ); | ||
| 2766 | else (Error.CONT_CLOCKED_PARTITION_CONFLICT_EQ, {}); | ||
| 2767 | end match; | ||
| 2768 | end getPartitionConflictError; | ||
| 2769 | |||
| 2770 | protected function setClockedPartition | ||
| 2771 | input Option<Boolean> inNewPartitionType; | ||
| 2772 | input Option<Boolean> inOldPartitionType; | ||
| 2773 | input Option<DAE.ComponentRef> inComp; | ||
| 2774 | input SourceInfo info; | ||
| 2775 | output Option<Boolean> outPartitionType; | ||
| 2776 | algorithm | ||
| 2777 | outPartitionType := match (inOldPartitionType, inNewPartitionType) | ||
| 2778 | local | ||
| 2779 | Boolean newVal, oldVal; | ||
| 2780 | ErrorTypes.Message msg; | ||
| 2781 | ErrorTypes.MessageTokens tokens; | ||
| 2782 | case (NONE(), _) then inNewPartitionType; | ||
| 2783 | case (_, NONE()) then inOldPartitionType; | ||
| 2784 | case (SOME(oldVal), SOME(newVal)) guard (oldVal == newVal) | ||
| 2785 | then inNewPartitionType; | ||
| 2786 | else | ||
| 2787 | algorithm | ||
| 2788 | ✗ | (msg, tokens) := getPartitionConflictError(inComp); | |
| 2789 | ✗ | Error.addSourceMessage(msg, tokens, info); | |
| 2790 | ✗ | then fail(); | |
| 2791 | end match; | ||
| 2792 | end setClockedPartition; | ||
| 2793 | |||
| 2794 | public function partitionIndependentBlocks0 | ||
| 2795 | input BackendDAE.AdjacencyMatrix m; | ||
| 2796 | input BackendDAE.AdjacencyMatrixT mT; | ||
| 2797 | input BackendDAE.AdjacencyMatrix rm; | ||
| 2798 | input BackendDAE.AdjacencyMatrixT rmT; | ||
| 2799 | input array<Integer> eqPartMap,varPartMap, rixs; | ||
| 2800 | input array<Boolean> vars, rvars; | ||
| 2801 | output Integer on = 0; | ||
| 2802 | algorithm | ||
| 2803 |
2/2✓ Branch 0 taken 2361 times.
✓ Branch 1 taken 47 times.
|
296093 | for i in arrayLength(m):-1:1 loop |
| 2804 |
2/2✓ Branch 1 taken 66205 times.
✓ Branch 2 taken 227480 times.
|
293685 | on := if partitionIndependentBlocksWork(i, false, on + 1, m, mT, rm, rmT, eqPartMap, varPartMap, rixs, vars, rvars) then on + 1 else on; |
| 2805 | end for; | ||
| 2806 |
2/2✓ Branch 0 taken 1972 times.
✓ Branch 1 taken 436 times.
|
5692 | for i in arrayLength(rm):-1:1 loop |
| 2807 |
2/2✓ Branch 1 taken 1577 times.
✓ Branch 2 taken 1707 times.
|
3284 | on := if partitionIndependentBlocksWork(i, true, on + 1, m, mT, rm, rmT, eqPartMap, varPartMap, rixs, vars, rvars) then on + 1 else on; |
| 2808 | end for; | ||
| 2809 | end partitionIndependentBlocks0; | ||
| 2810 | |||
| 2811 | protected function partitionIndependentBlocks | ||
| 2812 | input BackendDAE.AdjacencyMatrix m; | ||
| 2813 | input BackendDAE.AdjacencyMatrixT mT; | ||
| 2814 | input array<Integer> eqPartMap; //partitions | ||
| 2815 | input array<Integer> varPartMap; //usedVars, usedRemovedVars | ||
| 2816 | output Integer on = 0; | ||
| 2817 | algorithm | ||
| 2818 | ✗ | for eq in arrayLength(m):-1:1 loop | |
| 2819 | ✗ | print("check eq "+intString(eq)+"\n"); | |
| 2820 | ✗ | if not intEq(arrayGet(eqPartMap,eq),-2) then //marked with -2 means that it is a sub partition interface | |
| 2821 | ✗ | on := if partitionIndependentBlocks2(eq, on+1, m, mT, eqPartMap, varPartMap) then on+1 else on; | |
| 2822 | end if; | ||
| 2823 | end for; | ||
| 2824 | end partitionIndependentBlocks; | ||
| 2825 | |||
| 2826 | |||
| 2827 | protected function partitionIndependentBlocks2 | ||
| 2828 | input Integer eqIdx; | ||
| 2829 | input Integer partIdx; | ||
| 2830 | input BackendDAE.AdjacencyMatrix m; | ||
| 2831 | input BackendDAE.AdjacencyMatrixT mT; | ||
| 2832 | input array<Integer> eqPartMap; | ||
| 2833 | input array<Integer> varPartMap; | ||
| 2834 | output Boolean ochange; | ||
| 2835 | algorithm | ||
| 2836 | ✗ | ochange := arrayGet(eqPartMap, eqIdx) == -1; | |
| 2837 | ✗ | if ochange then | |
| 2838 | ✗ | arrayUpdate(eqPartMap, eqIdx, partIdx); | |
| 2839 | ✗ | for var in arrayGet(m, eqIdx) loop | |
| 2840 | ✗ | if not intGt(arrayGet(varPartMap, intAbs(var)),0) then | |
| 2841 | ✗ | arrayUpdate(varPartMap, intAbs(var), partIdx); | |
| 2842 | ✗ | for newEq in arrayGet(mT, intAbs(var)) loop | |
| 2843 | ✗ | partitionIndependentBlocks2(intAbs(newEq), partIdx, m, mT, eqPartMap, varPartMap); | |
| 2844 | end for; | ||
| 2845 | end if; | ||
| 2846 | end for; | ||
| 2847 | end if; | ||
| 2848 | end partitionIndependentBlocks2; | ||
| 2849 | |||
| 2850 | protected function partitionIndependentBlocksMasked | ||
| 2851 | input BackendDAE.AdjacencyMatrix m; | ||
| 2852 | input BackendDAE.AdjacencyMatrixT mT; | ||
| 2853 | input BackendDAE.AdjacencyMatrix rm; | ||
| 2854 | input BackendDAE.AdjacencyMatrixT rmT; | ||
| 2855 | input array<Boolean> mask; //clockedEqsMask | ||
| 2856 | input array<Integer> eqPartMap, varPartMap, remEqPartMap; //eqPartMap, varPartMap, remEqPartMap | ||
| 2857 | input array<Boolean> vars, rvars; //usedVars, usedRemovedVars | ||
| 2858 | output Integer on; | ||
| 2859 | algorithm | ||
| 2860 | on := 0; | ||
| 2861 |
1/2✓ Branch 0 taken 46 times.
✗ Branch 1 not taken.
|
743 | for i in arrayLength(m):-1:1 loop |
| 2862 |
1/2✓ Branch 1 taken 697 times.
✗ Branch 2 not taken.
|
697 | if mask[i] then |
| 2863 |
2/2✓ Branch 1 taken 67 times.
✓ Branch 2 taken 630 times.
|
697 | if partitionIndependentBlocksWork(i, false, on + 1, m, mT, rm, rmT, eqPartMap, varPartMap, remEqPartMap, vars, rvars) then |
| 2864 | on := on + 1; | ||
| 2865 | end if; | ||
| 2866 | end if; | ||
| 2867 | end for; | ||
| 2868 |
1/2✓ Branch 0 taken 46 times.
✗ Branch 1 not taken.
|
46 | for i in arrayLength(rm):-1:1 loop |
| 2869 | ✗ | if partitionIndependentBlocksWork(i, true, on + 1, m, mT, rm, rmT, eqPartMap, varPartMap, remEqPartMap, vars, rvars) then | |
| 2870 | on := on + 1; | ||
| 2871 | end if; | ||
| 2872 | end for; | ||
| 2873 | end partitionIndependentBlocksMasked; | ||
| 2874 | |||
| 2875 | protected function partitionIndependentBlocksWork | ||
| 2876 | input Integer idx; | ||
| 2877 | input Boolean isRemovedIdx; | ||
| 2878 | |||
| 2879 | input Integer partIdx; | ||
| 2880 | input BackendDAE.AdjacencyMatrix m; | ||
| 2881 | input BackendDAE.AdjacencyMatrixT mT; | ||
| 2882 | input BackendDAE.AdjacencyMatrix rm; | ||
| 2883 | input BackendDAE.AdjacencyMatrixT rmT; | ||
| 2884 | input array<Integer> eqPartMap, varPartMap, rixs; | ||
| 2885 | input array<Boolean> vars, rvars; | ||
| 2886 | output Boolean ochange; | ||
| 2887 | protected | ||
| 2888 | Integer eqIdx, rmIdx; | ||
| 2889 | list<Integer> workListEq = {}, workListRm = {}; | ||
| 2890 | algorithm | ||
| 2891 | ochange := false; | ||
| 2892 |
2/2✓ Branch 0 taken 3284 times.
✓ Branch 1 taken 294382 times.
|
297666 | if isRemovedIdx then |
| 2893 |
2/2✓ Branch 1 taken 1577 times.
✓ Branch 2 taken 1707 times.
|
3284 | if arrayGet(rixs, idx) == 0 then |
| 2894 | 1577 | arrayUpdate(rixs, idx, partIdx); | |
| 2895 | workListRm := {idx}; | ||
| 2896 | ochange := true; | ||
| 2897 | end if; | ||
| 2898 | else | ||
| 2899 |
2/2✓ Branch 1 taken 66272 times.
✓ Branch 2 taken 228110 times.
|
294382 | if arrayGet(eqPartMap, idx) == 0 then |
| 2900 | 66272 | arrayUpdate(eqPartMap, idx, partIdx); | |
| 2901 | workListEq := {idx}; | ||
| 2902 | ochange := true; | ||
| 2903 | end if; | ||
| 2904 | end if; | ||
| 2905 |
2/2✓ Branch 0 taken 229817 times.
✓ Branch 1 taken 67849 times.
|
297666 | if not ochange then |
| 2906 | 229817 | return; | |
| 2907 | end if; | ||
| 2908 | |||
| 2909 |
4/4✓ Branch 0 taken 71133 times.
✓ Branch 1 taken 294382 times.
✓ Branch 2 taken 3284 times.
✓ Branch 3 taken 67849 times.
|
365515 | while not (listEmpty(workListEq) and listEmpty(workListRm)) loop |
| 2910 |
2/2✓ Branch 0 taken 294382 times.
✓ Branch 1 taken 3284 times.
|
297666 | if not listEmpty(workListEq) then |
| 2911 | 294382 | eqIdx :: workListEq := workListEq; | |
| 2912 |
2/2✓ Branch 1 taken 294382 times.
✓ Branch 2 taken 788652 times.
|
1083034 | for varIdx in arrayGet(m, eqIdx) loop |
| 2913 |
2/2✓ Branch 1 taken 350775 times.
✓ Branch 2 taken 437877 times.
|
788652 | if not arrayGet(vars, intAbs(varIdx)) then |
| 2914 | 350775 | arrayUpdate(vars, intAbs(varIdx), true); | |
| 2915 | 350775 | arrayUpdate(varPartMap, intAbs(varIdx), partIdx); | |
| 2916 |
2/2✓ Branch 1 taken 788652 times.
✓ Branch 2 taken 350775 times.
|
1139427 | for nextEqIdx in arrayGet(mT, intAbs(varIdx)) loop |
| 2917 |
2/2✓ Branch 1 taken 228079 times.
✓ Branch 2 taken 560573 times.
|
788652 | if arrayGet(eqPartMap, intAbs(nextEqIdx)) == 0 then |
| 2918 | workListEq := intAbs(nextEqIdx) :: workListEq; | ||
| 2919 | 228079 | arrayUpdate(eqPartMap, intAbs(nextEqIdx), partIdx); | |
| 2920 | end if; | ||
| 2921 | end for; | ||
| 2922 |
2/2✓ Branch 1 taken 2304 times.
✓ Branch 2 taken 350775 times.
|
353079 | for nextEqIdx in arrayGet(rmT, intAbs(varIdx)) loop |
| 2923 |
2/2✓ Branch 1 taken 1706 times.
✓ Branch 2 taken 598 times.
|
2304 | if arrayGet(rixs, intAbs(nextEqIdx)) == 0 then |
| 2924 | workListRm := intAbs(nextEqIdx) :: workListRm; | ||
| 2925 | 1706 | arrayUpdate(rixs, intAbs(nextEqIdx), partIdx); | |
| 2926 | end if; | ||
| 2927 | end for; | ||
| 2928 | end if; | ||
| 2929 | end for; | ||
| 2930 | else | ||
| 2931 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3284 times.
|
3284 | rmIdx :: workListRm := workListRm; |
| 2932 |
2/2✓ Branch 1 taken 3284 times.
✓ Branch 2 taken 2304 times.
|
5588 | for varIdx in arrayGet(rm, rmIdx) loop |
| 2933 |
2/2✓ Branch 1 taken 2053 times.
✓ Branch 2 taken 251 times.
|
2304 | if not arrayGet(rvars, intAbs(varIdx)) then |
| 2934 | 2053 | arrayUpdate(rvars, intAbs(varIdx), true); | |
| 2935 |
2/2✓ Branch 1 taken 7521 times.
✓ Branch 2 taken 2053 times.
|
9574 | for nextEqIdx in arrayGet(mT, intAbs(varIdx)) loop |
| 2936 |
2/2✓ Branch 1 taken 31 times.
✓ Branch 2 taken 7490 times.
|
7521 | if arrayGet(eqPartMap, intAbs(nextEqIdx)) == 0 then |
| 2937 | workListEq := intAbs(nextEqIdx) :: workListEq; | ||
| 2938 | 31 | arrayUpdate(eqPartMap, intAbs(nextEqIdx), partIdx); | |
| 2939 | end if; | ||
| 2940 | end for; | ||
| 2941 |
2/2✓ Branch 1 taken 2304 times.
✓ Branch 2 taken 2053 times.
|
4357 | for nextEqIdx in arrayGet(rmT, intAbs(varIdx)) loop |
| 2942 |
2/2✓ Branch 1 taken 1 time.
✓ Branch 2 taken 2303 times.
|
2304 | if arrayGet(rixs, intAbs(nextEqIdx)) == 0 then |
| 2943 | workListRm := intAbs(nextEqIdx) :: workListRm; | ||
| 2944 | 1 | arrayUpdate(rixs, intAbs(nextEqIdx), partIdx); | |
| 2945 | end if; | ||
| 2946 | end for; | ||
| 2947 | end if; | ||
| 2948 | end for; | ||
| 2949 | end if; | ||
| 2950 | end while; | ||
| 2951 | end partitionIndependentBlocksWork; | ||
| 2952 | |||
| 2953 | public function partitionIndependentBlocksSplitBlocks | ||
| 2954 | "Partitions the independent blocks into list<array<...>> by first constructing | ||
| 2955 | an array<list<...>> structure for the algorithm complexity" | ||
| 2956 | input Integer n; | ||
| 2957 | input BackendDAE.EqSystem inSyst; | ||
| 2958 | input array<Integer> ixs; | ||
| 2959 | input array<Integer> rixs; | ||
| 2960 | input BackendDAE.AdjacencyMatrix mT; | ||
| 2961 | input BackendDAE.AdjacencyMatrix rmT; | ||
| 2962 | input Boolean throwNoError; | ||
| 2963 | input AvlTreePathFunction.Tree funcs; | ||
| 2964 | input Boolean isInitial; | ||
| 2965 | output list<BackendDAE.EqSystem> systs = {}; | ||
| 2966 | output list<BackendDAE.Equation> unpartRemovedEqs; | ||
| 2967 | output array<Integer> varPartMap; | ||
| 2968 | protected | ||
| 2969 | array<list<BackendDAE.Equation>> ea, rea; | ||
| 2970 | array<list<BackendDAE.Var>> va; | ||
| 2971 | Integer i1, i2; | ||
| 2972 | Boolean b, b1 = true; | ||
| 2973 | BackendDAE.EqSystem syst; | ||
| 2974 | array<Integer> varsPartition; | ||
| 2975 | list<BackendDAE.Var> lstVars; | ||
| 2976 | algorithm | ||
| 2977 | 1242 | ea := arrayCreate(n, {}); | |
| 2978 | 1242 | rea := arrayCreate(n, {}); | |
| 2979 | 1242 | va := arrayCreate(n, {}); | |
| 2980 | 1242 | varPartMap := arrayCreate(n, -1); | |
| 2981 | 1242 | i1 := BackendEquation.equationArraySize(inSyst.orderedEqs); | |
| 2982 | 1242 | i2 := BackendVariable.varsSize(inSyst.orderedVars); | |
| 2983 | |||
| 2984 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1242 times.
|
1242 | if i1 <> i2 and not throwNoError then |
| 2985 | ✗ | Error.addSourceMessage(if i1 > i2 then Error.OVERDET_EQN_SYSTEM else Error.UNDERDET_EQN_SYSTEM, {String(i1), String(i2)}, Absyn.dummyInfo); | |
| 2986 | ✗ | BackendDAEUtil.checkAdjacencyMatrixSolvability(inSyst, funcs, isInitial); | |
| 2987 | ✗ | fail(); | |
| 2988 | end if; | ||
| 2989 | |||
| 2990 | 1242 | partitionEquations(inSyst.orderedEqs, ixs, ea); | |
| 2991 | 1242 | unpartRemovedEqs := partitionEquations(inSyst.removedEqs, rixs, rea); | |
| 2992 | |||
| 2993 | 1242 | varsPartition := arrayCreate(BackendVariable.varsSize(inSyst.orderedVars), 0); | |
| 2994 |
1/2✓ Branch 1 taken 1242 times.
✗ Branch 2 not taken.
|
317428 | for i in 1:BackendVariable.varsSize(inSyst.orderedVars) loop |
| 2995 | 316186 | setVarPartition(varsPartition, i, mT[i], ixs); | |
| 2996 | 316186 | setVarPartition(varsPartition, i, rmT[i], rixs); | |
| 2997 | end for; | ||
| 2998 |
1/2✓ Branch 0 taken 1242 times.
✗ Branch 1 not taken.
|
317428 | for i in arrayLength(varsPartition):-1:1 loop |
| 2999 |
2/2✓ Branch 1 taken 316185 times.
✓ Branch 2 taken 1 time.
|
316186 | if varsPartition[i] <> 0 then |
| 3000 | 316185 | lstVars := va[varsPartition[i]]; | |
| 3001 | 632370 | arrayUpdate(va, varsPartition[i], BackendVariable.getVarAt(inSyst.orderedVars, i)::lstVars); | |
| 3002 | end if; | ||
| 3003 | end for; | ||
| 3004 | |||
| 3005 |
1/2✓ Branch 0 taken 1242 times.
✗ Branch 1 not taken.
|
1242 | for i in 1:n loop |
| 3006 |
2/2✓ Branch 0 taken 18626 times.
✓ Branch 1 taken 48034 times.
|
85286 | (syst, (b, _)) := createEqSystem(ea[i], va[i], rea[i], (true, throwNoError)); |
| 3007 | systs := syst :: systs; | ||
| 3008 | 66659 | b1 := b1 and b; | |
| 3009 | end for; | ||
| 3010 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1241 times.
|
1241 | true := throwNoError or b1; |
| 3011 | 1241 | systs := listReverse(systs); | |
| 3012 | end partitionIndependentBlocksSplitBlocks; | ||
| 3013 | |||
| 3014 | protected function setVarPartition | ||
| 3015 | input array<Integer> varsPartition; | ||
| 3016 | input Integer i; | ||
| 3017 | input list<Integer> eqsIxs; | ||
| 3018 | input array<Integer> eqsPartitions; | ||
| 3019 | protected | ||
| 3020 | Integer partitionIdx; | ||
| 3021 | algorithm | ||
| 3022 |
2/2✓ Branch 0 taken 705438 times.
✓ Branch 1 taken 632372 times.
|
1337810 | for eq in eqsIxs loop |
| 3023 | 705438 | partitionIdx := eqsPartitions[eq]; | |
| 3024 |
1/2✓ Branch 0 taken 705438 times.
✗ Branch 1 not taken.
|
705438 | if partitionIdx <> 0 then |
| 3025 |
3/4✓ Branch 1 taken 389253 times.
✓ Branch 2 taken 316185 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 389253 times.
|
705438 | assert(varsPartition[i] == 0 or varsPartition[i] == partitionIdx, "SynchronousFeatures.setVarPartition failed"); |
| 3026 | 705438 | arrayUpdate(varsPartition, i, partitionIdx); | |
| 3027 | end if; | ||
| 3028 | end for; | ||
| 3029 | end setVarPartition; | ||
| 3030 | |||
| 3031 | protected function createEqSystem | ||
| 3032 | input list<BackendDAE.Equation> el; | ||
| 3033 | input list<BackendDAE.Var> vl; | ||
| 3034 | input list<BackendDAE.Equation> rel; | ||
| 3035 | input tuple<Boolean, Boolean> iTpl; | ||
| 3036 | output BackendDAE.EqSystem syst; | ||
| 3037 | output tuple<Boolean, Boolean> oTpl; | ||
| 3038 | protected | ||
| 3039 | BackendDAE.EquationArray arr, remArr; | ||
| 3040 | BackendDAE.Variables vars; | ||
| 3041 | Integer i1, i2; | ||
| 3042 | String s1, s2, s3, s4; | ||
| 3043 | list<String> crs; | ||
| 3044 | Boolean success, throwNoError; | ||
| 3045 | algorithm | ||
| 3046 | 66721 | (success, throwNoError) := iTpl; | |
| 3047 | 66721 | vars := BackendVariable.listVar1(vl); | |
| 3048 | 66721 | arr := BackendEquation.listEquation(el); | |
| 3049 | 66721 | remArr := BackendEquation.listEquation(rel); | |
| 3050 | 66721 | i1 := BackendEquation.equationArraySize(arr); | |
| 3051 | 66721 | i2 := BackendVariable.varsSize(vars); | |
| 3052 | |||
| 3053 | // Can this even be triggered? We check that all variables are defined somewhere, so everything should be balanced already? | ||
| 3054 |
2/2✓ Branch 0 taken 1 time.
✓ Branch 1 taken 66720 times.
|
66721 | if i1 <> i2 and not throwNoError then |
| 3055 | 1 | s1 := intString(i1); | |
| 3056 | 1 | s2 := intString(i2); | |
| 3057 | 1 | crs := List.mapMap(vl, BackendVariable.varCref, ComponentReferenceBasics.printComponentRefStr); | |
| 3058 | 1 | s3 := stringDelimitList(crs, "\n"); | |
| 3059 | 1 | s4 := BackendDump.dumpEqnsStr(el); | |
| 3060 | 1 | Error.addSourceMessage(Error.IMBALANCED_EQUATIONS, {s1, s2, s3, s4}, Absyn.dummyInfo); | |
| 3061 | 1 | fail(); | |
| 3062 | end if; | ||
| 3063 | |||
| 3064 | 66720 | syst := BackendDAEUtil.createEqSystem(vars, arr, {}, BackendDAE.UNKNOWN_PARTITION(), remArr); | |
| 3065 | 66720 | success := success and i1==i2; | |
| 3066 |
4/4✓ Branch 0 taken 18625 times.
✓ Branch 1 taken 48095 times.
✓ Branch 2 taken 379 times.
✓ Branch 3 taken 66341 times.
|
85724 | oTpl := (success, throwNoError); |
| 3067 | end createEqSystem; | ||
| 3068 | |||
| 3069 | protected function partitionEquations | ||
| 3070 | input BackendDAE.EquationArray arr; | ||
| 3071 | input array<Integer> ixs; | ||
| 3072 | input array<list<BackendDAE.Equation>> ea; | ||
| 3073 | output list<BackendDAE.Equation> restEqs = {}; | ||
| 3074 | protected | ||
| 3075 | Integer ix; | ||
| 3076 | list<BackendDAE.Equation> lst; | ||
| 3077 | BackendDAE.Equation eq; | ||
| 3078 | algorithm | ||
| 3079 |
2/2✓ Branch 1 taken 925 times.
✓ Branch 2 taken 1559 times.
|
272304 | for i in BackendEquation.getNumberOfEquations(arr):-1:1 loop |
| 3080 | 269820 | ix := ixs[i]; | |
| 3081 | 269820 | eq := BackendEquation.get(arr, i); | |
| 3082 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 269820 times.
|
269820 | if ix == 0 then |
| 3083 | restEqs := eq::restEqs; | ||
| 3084 | else | ||
| 3085 | 269820 | lst := ea[ix]; | |
| 3086 | lst := eq::lst; | ||
| 3087 | // print("adding eq " + intString(n) + " to group " + intString(ix) + "\n"); | ||
| 3088 | 269820 | arrayUpdate(ea, ix, lst); | |
| 3089 | end if; | ||
| 3090 | end for; | ||
| 3091 | end partitionEquations; | ||
| 3092 | |||
| 3093 | protected function subClkEqual | ||
| 3094 | "outputs true if 2 subclocks are equal | ||
| 3095 | vwaurich 2017-06" | ||
| 3096 | input BackendDAE.SubClock sc1; | ||
| 3097 | input BackendDAE.SubClock sc2; | ||
| 3098 | output Boolean isEqual; | ||
| 3099 | algorithm | ||
| 3100 | isEqual := match(sc1,sc2) | ||
| 3101 | local | ||
| 3102 | case(BackendDAE.INFERED_SUBCLOCK(), BackendDAE.INFERED_SUBCLOCK()) | ||
| 3103 | then true; | ||
| 3104 | case(BackendDAE.SUBCLOCK(), BackendDAE.SUBCLOCK()) | ||
| 3105 |
5/6✓ Branch 1 taken 54 times.
✓ Branch 2 taken 13 times.
✓ Branch 4 taken 46 times.
✓ Branch 5 taken 8 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 46 times.
|
67 | then MMath.equals(sc1.factor,sc2.factor) and MMath.equals(sc1. shift,sc2. shift) and Util.optionEqual(sc1.solver,sc2.solver,stringEqual); |
| 3106 | else | ||
| 3107 | then false; | ||
| 3108 | end match; | ||
| 3109 | end subClkEqual; | ||
| 3110 | |||
| 3111 | protected function subClockTreeString | ||
| 3112 | input array<tuple<BackendDAE.SubClock, Integer>> treeIn; | ||
| 3113 | output String sOut=""; | ||
| 3114 | protected | ||
| 3115 | tuple<BackendDAE.SubClock, Integer> tpl; | ||
| 3116 | BackendDAE.SubClock subClock; | ||
| 3117 | Integer i,idx=1; | ||
| 3118 | algorithm | ||
| 3119 | ✗ | for tpl in treeIn loop | |
| 3120 | ✗ | (subClock,i) := tpl; | |
| 3121 | ✗ | sOut := intString(idx)+": ["+intString(i)+"]: "+BackendDump.subClockString(subClock)+"\n"+sOut; | |
| 3122 | ✗ | idx:=idx+1; | |
| 3123 | end for; | ||
| 3124 | end subClockTreeString; | ||
| 3125 | |||
| 3126 | annotation(__OpenModelica_Interface="backend"); | ||
| 3127 | end SynchronousFeatures; | ||
| 3128 |