Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 87.7% 57 / 0 / 65
Functions: -% 0 / 1 / 1
Branches: 86.4% 38 / 0 / 44

OMCompiler/Compiler/SimCode/SimCodeUtilShared.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 SimCodeUtilShared "Simulation-related SimCode generator helpers shared by the old and new backends.
37
38 This package holds the SimCode generator functions that both SimCodeUtil (old
39 backend) and NSimCode (new backend) need but that are *not* bootstrap-safe: they
40 pull in the full simulation datatypes (SimCode.ModelInfo) and the inliner, so they
41 must stay out of SimCodeFunctionUtil. SimCodeFunctionUtil is part of the bootstrap
42 set, where SimCode is only a stub and nothing simulation-related is available.
43
44 Keeping these here lets the new backend reuse them without depending on the entire
45 16k-line SimCodeUtil (interface 'backend'); this module is tagged 'simcode_util'
46 like SimCodeFunctionUtil, so both backends already depend on it."
47
48 import Absyn;
49 import AvlTreePathFunction;
50 import DAE;
51 import HashTableCrIListArray;
52 import HashTableCrILst;
53 import UnorderedMap;
54 import Inline;
55 import SimCode;
56 import SimCodeFunction;
57 import SimCodeFunctionUtil;
58 import SimCodeVar;
59 import Util;
60
61 protected
62
63 import BaseHashTable;
64 import ComponentReference;
65 import ComponentReferenceBasics;
66 import Config;
67 import DAEUtil;
68 import Error;
69 import Flags;
70 import List;
71
72 public
73
74 protected function simulationFindLiterals
75 "Finds all literal expressions in functionsa"
76 input list<DAE.Function> fns;
77 output list<DAE.Function> ofns;
78 output tuple<Integer, UnorderedMap<DAE.Exp, Integer>, list<DAE.Exp>> literals;
79 algorithm
80 1257 (ofns, literals) := DAEUtil.traverseDAEFunctions(
81 fns, SimCodeFunctionUtil.findLiteralsHelper,
82 (0, SimCodeFunctionUtil.newExpIndexMap(), {}));
83 // Broke things :(
84 // ((i, ht, literals)) := BackendDAEUtil.traverseBackendDAEExpsNoCopyWithUpdate(dae, findLiteralsHelper, (i, ht, literals));
85 end simulationFindLiterals;
86
87 public function createFunctions
88 input Absyn.Program inProgram;
89 input AvlTreePathFunction.Tree functionTree;
90 output list<String> outLibs;
91 output list<String> outLibPaths;
92 output list<String> outIncludes;
93 output list<String> outIncludeDirs;
94 output list<SimCodeFunction.RecordDeclaration> outRecordDecls;
95 output list<SimCodeFunction.Function> outFunctions;
96 output tuple<Integer, UnorderedMap<DAE.Exp, Integer>, list<DAE.Exp>> outLiterals;
97 protected
98 list<DAE.Function> funcelems;
99 list<DAE.Exp> lits;
100 algorithm
101 try
102 // get all the used functions from the function tree
103 1257 funcelems := DAEUtil.getFunctionList(functionTree);
104 1257 funcelems := Inline.inlineCallsInFunctions(funcelems, (NONE(), {DAE.NORM_INLINE(), DAE.AFTER_INDEX_RED_INLINE()}));
105 1257 (funcelems, outLiterals as (_, _, lits)) := simulationFindLiterals(funcelems);
106 1257 (outFunctions, outRecordDecls, outIncludes, outIncludeDirs, outLibs, outLibPaths) := SimCodeFunctionUtil.elaborateFunctions(inProgram, funcelems, {}, lits, {}); // Do we need metarecords here as well?
107 else
108 ✗ Error.addInternalError("Creation of Modelica functions failed.", sourceInfo());
109 ✗ fail();
110 end try;
111 end createFunctions;
112
113 public function createVarToArrayIndexMapping
114 "Creates a mapping for each array-cref to the array dimensions (int list) and to the indices (for the code generation) used to store the array content.
115 Only the Cpp templates and HpcOm read the mappings, other targets get empty tables."
116 input SimCode.ModelInfo iModelInfo;
117 output HashTableCrIListArray.HashTable oVarToArrayIndexMapping;
118 output HashTableCrILst.HashTable oVarToIndexMapping; //same as oVarToArrayIndexMapping, but does not merge array variables into one list
119 protected
120 SimCodeVar.SimVars sim_vars;
121 list<tuple<list<SimCodeVar.SimVar>, Integer>> vars;
122 Integer table_size = 0;
123 list<SimCodeVar.SimVar> var_lst;
124 Integer var_type;
125 array<Integer> currentVarIndices; //current variable index real,int,bool,string
126 algorithm
127
6/6
✓ Branch 1 taken 1242 times.
✓ Branch 2 taken 8 times.
✓ Branch 4 taken 52 times.
✓ Branch 5 taken 1190 times.
✓ Branch 8 taken 4 times.
✓ Branch 9 taken 48 times.
1250 if not (Flags.isSet(Flags.HPCOM) or Config.simCodeTarget() == "Cpp") then
128 1194 oVarToArrayIndexMapping := HashTableCrIListArray.emptyHashTableSized(1);
129 1194 oVarToIndexMapping := HashTableCrILst.emptyHashTableSized(1);
130 1194 return;
131 end if;
132
133 // Collect the variable lists into a list for easier handling.
134 56 sim_vars := iModelInfo.vars;
135 56 vars := {
136 (sim_vars.stateVars, 1),
137 (sim_vars.derivativeVars, 1),
138 (sim_vars.algVars, 1),
139 (sim_vars.discreteAlgVars, 1),
140 (sim_vars.intAlgVars, 2),
141 (sim_vars.boolAlgVars, 3),
142 (sim_vars.stringAlgVars, 4),
143 (sim_vars.paramVars, 1),
144 (sim_vars.intParamVars, 2),
145 (sim_vars.boolParamVars, 3),
146 (sim_vars.stringParamVars, 4),
147 //(sim_vars.inputVars, 1),
148 //(sim_vars.utputVars, 1),
149 (sim_vars.constVars, 1),
150 (sim_vars.intConstVars, 2),
151 (sim_vars.boolConstVars, 3),
152 (sim_vars.stringConstVars, 4),
153 (sim_vars.realOptimizeConstraintsVars, 1),
154 (sim_vars.realOptimizeFinalConstraintsVars, 1),
155 (sim_vars.aliasVars, 1),
156 (sim_vars.intAliasVars, 2),
157 (sim_vars.boolAliasVars, 3),
158 (sim_vars.stringAliasVars, 4)
159 };
160
161 // Count the number of variables to determine an appropriate size for the hash tables.
162
2/2
✓ Branch 0 taken 1176 times.
✓ Branch 1 taken 56 times.
1232 for vl in vars loop
163 1176 (var_lst, _) := vl;
164 1176 table_size := table_size + listLength(var_lst);
165 end for;
166 56 table_size := Util.nextPrime(realInt(table_size * 1.4));
167
168 56 oVarToArrayIndexMapping := HashTableCrIListArray.emptyHashTableSized(table_size);
169 56 oVarToIndexMapping := HashTableCrILst.emptyHashTableSized(table_size);
170 56 currentVarIndices := arrayCreate(4, 1); //0 is reserved for unused variables
171
172 // Add the variables to the tables.
173
2/2
✓ Branch 0 taken 1176 times.
✓ Branch 1 taken 56 times.
1232 for vl in vars loop
174 1176 (var_lst, var_type) := vl;
175 1176 (currentVarIndices, oVarToArrayIndexMapping, oVarToIndexMapping) :=
176 addVarToArrayIndexMappings(var_lst, var_type, currentVarIndices, oVarToArrayIndexMapping, oVarToIndexMapping);
177 end for;
178 end createVarToArrayIndexMapping;
179
180 public function addVarToArrayIndexMappings
181 input list<SimCodeVar.SimVar> vars;
182 input Integer iVarType; //1 = real ; 2 = int ; 3 = bool ; 4 = string
183 input output array<Integer> currentVarIndices;
184 input output HashTableCrIListArray.HashTable varToArrayIndexMapping;
185 input output HashTableCrILst.HashTable varToIndexMapping;
186 algorithm
187
2/2
✓ Branch 0 taken 17336 times.
✓ Branch 1 taken 1186 times.
18522 for v in vars loop
188 17336 (currentVarIndices, varToArrayIndexMapping, varToIndexMapping) :=
189 addVarToArrayIndexMapping(v, iVarType, currentVarIndices, varToArrayIndexMapping, varToIndexMapping);
190 end for;
191 end addVarToArrayIndexMappings;
192
193 public function addVarToArrayIndexMapping "author: marcusw
194 Adds the given variable to the array-mapping and to the var-mapping. If the variable is part of an array 'a' which is not already part of the
195 given hash table, a new hash table element with size 'a.length' is allocated. The allocated arrays are row-major based."
196 input SimCodeVar.SimVar iVar;
197 input Integer iVarType; //1 = real ; 2 = int ; 3 = bool ; 4 = string
198 input output array<Integer> currentVarIndices;
199 input output HashTableCrIListArray.HashTable varToArrayIndexMapping;
200 input output HashTableCrILst.HashTable varToIndexMapping;
201 protected
202 DAE.ComponentRef name, arrayName;
203 Integer varIdx, arrayIndex;
204 array<Integer> varIndices;
205 list<Integer> arrayDimensions;
206 list<String> numArrayElement;
207 list<DAE.Subscript> arraySubscripts;
208 algorithm
209 () := match iVar
210 case SimCodeVar.SIMVAR(name=name, numArrayElement=numArrayElement)
211 algorithm
212 17622 (currentVarIndices,varIdx) := getArrayIdxByVar(iVar, iVarType, varToIndexMapping, currentVarIndices);
213 //print("Adding variable " + ComponentReferenceBasics.printComponentRefStr(name) + " with type " + intString(iVarType) + " to map with index " + intString(varIdx) + "\n");
214 17622 varToIndexMapping := BaseHashTable.add((name, {varIdx}), varToIndexMapping);
215 17622 arraySubscripts := ComponentReference.crefLastSubs(name);
216
3/4
✓ Branch 0 taken 9593 times.
✓ Branch 1 taken 8029 times.
✓ Branch 3 taken 9593 times.
✗ Branch 4 not taken.
17622 if listEmpty(numArrayElement) or checkIfSubscriptsContainsUnhandlableIndices(arraySubscripts) then
217 arrayName := name;
218 else
219 9593 arrayName := ComponentReferenceBasics.crefStripLastSubs(name);
220 end if;
221
222
2/2
✓ Branch 1 taken 38 times.
✓ Branch 2 taken 17584 times.
17622 if isArrayVar(iVar) then
223 // store array dimensions and index of first element to indicate a contiguous array
224
4/4
✓ Branch 2 taken 44 times.
✓ Branch 3 taken 38 times.
✓ Branch 4 taken 44 times.
✓ Branch 5 taken 38 times.
82 arrayDimensions := list(stringInt(e) for e in List.lastN(numArrayElement, listLength(numArrayElement)));
225 38 varIndices := arrayCreate(1, varIdx);
226 38 varToArrayIndexMapping := BaseHashTable.add((arrayName, (arrayDimensions, varIndices)), varToArrayIndexMapping);
227 elseif ComponentReferenceBasics.crefEqual(arrayName, name) then
228 // scalar variable
229 10756 varIndices := arrayCreate(1, varIdx);
230 10756 varToArrayIndexMapping := BaseHashTable.add((arrayName, ({1},varIndices)), varToArrayIndexMapping);
231 else
232 // store array dimensions and build up list of indices for elements
233
2/2
✓ Branch 1 taken 5013 times.
✓ Branch 2 taken 1815 times.
6828 if BaseHashTable.hasKey(arrayName, varToArrayIndexMapping) then
234 5013 (arrayDimensions,varIndices) := BaseHashTable.get(arrayName, varToArrayIndexMapping);
235 else
236 //print("Try to calculate array dimensions out of " + intString(listLength(numArrayElement)) + " array elements " + "\n");
237
4/4
✓ Branch 2 taken 1980 times.
✓ Branch 3 taken 1815 times.
✓ Branch 4 taken 1980 times.
✓ Branch 5 taken 1815 times.
3795 arrayDimensions := list(stringInt(e) for e in List.lastN(numArrayElement, listLength(arraySubscripts)));
238 //print("Allocating new array with " + intString(List.fold(arrayDimensions, intMul, 1)) + " elements.\n");
239 1815 varIndices := arrayCreate(List.fold(arrayDimensions, intMul, 1), 0);
240 end if;
241 //print("Num of array elements {" + stringDelimitList(List.map(arrayDimensions, intString), ",") + "} : " + intString(listLength(arraySubscripts)) + " arraySubs "+ExpressionDump.printSubscriptLstStr(arraySubscripts) + " arrayDimensions[ "+stringDelimitList(List.map(arrayDimensions,intString),",")+"]\n");
242 6828 arrayIndex := getScalarElementIndex(arraySubscripts, arrayDimensions);
243 //print("VarIndices: " + intString(arrayLength(varIndices)) + " arrayIndex: " + intString(arrayIndex) + " varIndex: " + intString(varIdx) + "\n");
244 6828 varIndices := arrayUpdate(varIndices, arrayIndex, varIdx);
245 6828 varToArrayIndexMapping := BaseHashTable.add((arrayName, (arrayDimensions,varIndices)), varToArrayIndexMapping);
246 end if;
247 then
248 ();
249
250 else
251 algorithm
252 ✗ Error.addMessage(Error.INTERNAL_ERROR, {"Unknown case for addVarToArrayIndexMapping.\n"});
253 then
254 ();
255 end match;
256 end addVarToArrayIndexMapping;
257
258 protected function checkIfSubscriptsContainsUnhandlableIndices "author: marcusw
259 Returns false if at least one subscript can not be handled as constant index."
260 input list<DAE.Subscript> iSubscripts;
261 output Boolean oContainsUnhandledSubscripts = false;
262 protected
263 DAE.Subscript subscript;
264 algorithm
265
2/2
✓ Branch 0 taken 8084 times.
✓ Branch 1 taken 9593 times.
17677 for subscript in iSubscripts loop
266
1/2
✓ Branch 1 taken 8084 times.
✗ Branch 2 not taken.
8084 if DAEUtil.getSubscriptIndex(subscript) < 0 then
267 oContainsUnhandledSubscripts := true;
268 break;
269 end if;
270 end for;
271 end checkIfSubscriptsContainsUnhandlableIndices;
272
273 protected function getArrayIdxByVar "author: marcusw
274 Get the storage-index of the given variable. If the variable is an alias, the storage position of the alias variable is returned.
275 If the variable is a negated alias, then the negated storage position of the alias variable is returned."
276 input SimCodeVar.SimVar iVar;
277 input Integer iVarType;
278 input HashTableCrILst.HashTable iVarToIndexMapping;
279 input output array<Integer> iCurrentVarIndices;
280 output Integer oVarIndex;
281 protected
282 DAE.ComponentRef varName, name;
283 Integer varIdx;
284 array<Integer> tmpCurrentVarIndices;
285 algorithm
286 oVarIndex := match(iVar, iCurrentVarIndices)
287 case(SimCodeVar.SIMVAR(name=name, aliasvar=SimCodeVar.NOALIAS()), tmpCurrentVarIndices)
288 algorithm
289 //print("getArrayIdxByVar: Handling common variable\n");
290 11828 (varIdx,tmpCurrentVarIndices) := getVarToArrayIndexByType(iVar, iVarType, tmpCurrentVarIndices);
291 then varIdx;
292 case(SimCodeVar.SIMVAR(name=name, aliasvar=SimCodeVar.NEGATEDALIAS(varName)), _)
293 algorithm
294 //print("getArrayIdxByVar: Handling negated alias variable pointing to " + ComponentReferenceBasics.printComponentRefStr(varName) + "\n");
295
1/2
✓ Branch 1 taken 817 times.
✗ Branch 2 not taken.
817 if(BaseHashTable.hasKey(varName, iVarToIndexMapping)) then
296
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 817 times.
817 varIdx::_ := BaseHashTable.get(varName, iVarToIndexMapping);
297 817 varIdx := intMul(varIdx,-1);
298 elseif ComponentReference.isTime(varName) then
299 varIdx := 0;
300 else
301 ✗ Error.addMessage(Error.INTERNAL_ERROR, {"Negated alias to unknown variable given."});
302 ✗ fail();
303 end if;
304 then varIdx;
305 case(SimCodeVar.SIMVAR(name=name, aliasvar=SimCodeVar.ALIAS(varName)), _)
306 algorithm
307 //print("getArrayIdxByVar: Handling alias variable pointing to " + ComponentReferenceBasics.printComponentRefStr(varName) + "\n");
308
1/2
✓ Branch 1 taken 4977 times.
✗ Branch 2 not taken.
4977 if(BaseHashTable.hasKey(varName, iVarToIndexMapping)) then
309
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4977 times.
4977 varIdx::_ := BaseHashTable.get(varName, iVarToIndexMapping);
310 elseif ComponentReference.isTime(varName) then
311 varIdx := 0;
312 else
313 ✗ Error.addMessage(Error.INTERNAL_ERROR, {"Alias to unknown variable given."});
314 ✗ fail();
315 end if;
316 then varIdx;
317 end match;
318 end getArrayIdxByVar;
319
320 protected function getVarToArrayIndexByType "author: marcusw
321 Return the the current variable index of the given tuple, regarding the given type. The index-tuple is incremented and returned."
322 input SimCodeVar.SimVar iVar;
323 input Integer iVarType; //1 = real ; 2 = int ; 3 = bool ; 4 = string
324 output Integer oVarIdx;
325 input output array<Integer> iCurrentVarIndices;
326 algorithm
327 try
328 11828 oVarIdx := arrayGet(iCurrentVarIndices, iVarType);
329 11828 arrayUpdate(iCurrentVarIndices, iVarType, oVarIdx + getNumElems(iVar));
330 else
331 ✗ Error.addMessage(Error.INTERNAL_ERROR, {"GetVarToArrayIndexByType with unknown type called."});
332 oVarIdx := -1;
333 end try;
334 end getVarToArrayIndexByType;
335
336 public function getScalarElementIndex
337 "Calculate the one based memory offset for consecutive row major storage,
338 author: rfranke"
339 input list<DAE.Subscript> arraySubscripts;
340 input list<Integer> arrayDimensions;
341 output Integer arrayIndex;
342 protected
343 Integer idx, fac;
344 algorithm
345 arrayIndex := 1; // one based
346 fac := 1;
347
2/2
✓ Branch 1 taken 13499 times.
✓ Branch 2 taken 15113 times.
28612 for i in listLength(arraySubscripts):-1:1 loop
348 18332 idx := DAEUtil.getSubscriptIndex(listGet(arraySubscripts, i));
349 18332 arrayIndex := arrayIndex + (idx - 1) * fac;
350 18332 fac := fac * listGet(arrayDimensions, i);
351 end for;
352 end getScalarElementIndex;
353
354 public function getNumElems
355 "Get number of scalar elements of a variable, rolling out arrays.
356 author: rfranke"
357 input SimCodeVar.SimVar var;
358 output Integer numElems;
359 algorithm
360 numElems := match var
361 case SimCodeVar.SIMVAR(type_ = DAE.T_ARRAY()) algorithm
362 numElems := 1;
363
2/2
✓ Branch 0 taken 1325 times.
✓ Branch 1 taken 1185 times.
2510 for d in var.numArrayElement loop
364 1325 numElems := numElems * stringInt(d);
365 end for;
366 then numElems;
367 else 1;
368 end match;
369 end getNumElems;
370
371 function isArrayVar
372 input SimCodeVar.SimVar var;
373 output Boolean isArray;
374 algorithm
375 isArray := match var
376 case SimCodeVar.SIMVAR(type_ = DAE.T_ARRAY()) then true;
377 else false;
378 end match;
379 end isArrayVar;
380
381 annotation(__OpenModelica_Interface="simcode_util");
382 end SimCodeUtilShared;
383