Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 42.6% 29 / 0 / 68
Functions: -% 0 / 0 / 0
Branches: -% 0 / 0 / 0

OMCompiler/Compiler/Template/CodegenCppHpcom.tpl
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 // This file defines template-extensions for transforming Modelica code into parallel hpcom-code.
37 //
38 // There are one root template intended to be called from the code generator:
39 // translateModel. These template do not return any
40 // result but instead write the result to files. All other templates return
41 // text and are used by the root templates (most of them indirectly).
42
43 package CodegenCppHpcom
44
45 import interface SimCodeBackendTV;
46 import interface SimCodeTV;
47 import CodegenUtil.*;
48 import CodegenCppCommon.*;
49 import CodegenCppInit.*;
50 import CodegenCpp.*; //unqualified import, no need the CodegenC is optional when calling a template; or mandatory when the same named template exists in this package (name hiding)
51
52
53
54 1 template translateModel(SimCode simCode)
55 ::=
56 match simCode
57 case SIMCODE(modelInfo = MODELINFO(__), makefileParams = MAKEFILE_PARAMS(__), hpcomData = HPCOMDATA(__)) then
58 let target = simulationCodeTarget()
59 let &extraFuncs = buffer "" /*BUFD*/
60 let &extraFuncsDecl = buffer "" /*BUFD*/
61 let &extraResidualsFuncsDecl = buffer "" /*BUFD*/
62 let &dummyTypeElemCreation = buffer "" //remove this workaround if GCC > 4.4 is the default compiler
63 let stateDerVectorName = "__zDot"
64 let useMemoryOptimization = Flags.isSet(Flags.HPCOM_MEMORY_OPT)
65
66 let className = lastIdentOfPath(modelInfo.name)
67 let numRealVars = numRealvarsHpcom(modelInfo, hpcomData.hpcOmMemory)
68 let numIntVars = numIntvarsHpcom(modelInfo, hpcomData.hpcOmMemory)
69 let numBoolVars = numBoolvarsHpcom(modelInfo, hpcomData.hpcOmMemory)
70 let numStringVars = numStringvars(modelInfo)
71 let numPreVars = numPreVarsHpcom(modelInfo, hpcomData.hpcOmMemory)
72
73 let() = textFile(simulationMainFile(target, simCode, &extraFuncs, &extraFuncsDecl, "",
74 (if Flags.isSet(USEMPI) then "#include <mpi.h>" else ""),
75 (if Flags.isSet(USEMPI) then mpiInit() else ""),
76 (if Flags.isSet(USEMPI) then mpiFinalize() else ""),
77 numRealVars, numIntVars, numBoolVars, numStringVars, numPreVars),
78 'OMCpp<%fileNamePrefix%>Main.cpp')
79 let() = textFile(simulationCppFile(simCode, contextOther, updateHpcom(allEquations, simCode, &extraFuncs, &extraFuncsDecl, "", contextOther, stateDerVectorName, false),
80 '<%numRealVars%>-1', '<%numIntVars%>-1', '<%numBoolVars%>-1', '<%numStringVars%>-1', &extraFuncs, &extraFuncsDecl, className,
81 additionalHpcomConstructorDefinitions(hpcomData.schedules),
82 additionalHpcomConstructorBodyStatements(hpcomData.schedules, className, CodegenUtil.dotPath(modelInfo.name)),
83 additionalHpcomDestructorBodyStatements(hpcomData.schedules),
84 stateDerVectorName, false), 'OMCpp<%fileNamePrefix%>.cpp')
85
86 let() = textFile(simulationHeaderFile(simCode ,contextOther, &extraFuncs, &extraFuncsDecl, "",
87 additionalHpcomIncludes(simCode, &extraFuncs, &extraFuncsDecl, className, false),
88 "",
89 additionalHpcomProtectedMemberDeclaration(simCode, &extraFuncs, &extraFuncsDecl, "", false),
90 memberVariableDefine(modelInfo, varToArrayIndexMapping, '<%numRealVars%>-1', '<%numIntVars%>-1', '<%numBoolVars%>-1', '<%numStringVars%>-1', Flags.isSet(Flags.GEN_DEBUG_SYMBOLS), false),
91 false), 'OMCpp<%fileNamePrefix%>.h')
92
93 let() = textFile(simulationTypesHeaderFile(simCode, &extraFuncs, &extraFuncsDecl, "", &dummyTypeElemCreation, modelInfo.functions, literals,stateDerVectorName,false), 'OMCpp<%fileNamePrefix%>Types.h')
94 let() = textFile(simulationMakefile(target,simCode, &extraFuncs, &extraFuncsDecl, ""), '<%fileNamePrefix%>.makefile')
95
96 let &extraFuncsFun = buffer "" /*BUFD*/
97 let &extraFuncsDeclFun = buffer "" /*BUFD*/
98 let() = textFile(simulationFunctionsHeaderFile(simCode, &extraFuncsFun, &extraFuncsDeclFun, "",modelInfo.functions, literals,stateDerVectorName,false), 'OMCpp<%fileNamePrefix%>Functions.h')
99 let() = textFile(simulationFunctionsFile(simCode, &extraFuncsFun, &extraFuncsDeclFun, "", modelInfo.functions, literals,externalFunctionIncludes,stateDerVectorName,false), 'OMCpp<%fileNamePrefix%>Functions.cpp')
100 let &extraFuncsInit = buffer "" /*BUFD*/
101 let &extraFuncsDeclInit = buffer "" /*BUFD*/
102 let &complexStartExpressions = buffer ""
103 let() = textFile(modelInitXMLFile(simCode, numRealVars, numIntVars, numBoolVars, numStringVars, "", "", "", false, "", complexStartExpressions, stateDerVectorName),'<%fileNamePrefix%>_init.xml')
104 let() = textFile(simulationInitCppFile(simCode ,&extraFuncsInit, &extraFuncsDeclInit, '<%className%>Initialize', dummyTypeElemCreation, stateDerVectorName, false, complexStartExpressions), 'OMCpp<%fileNamePrefix%>Initialize.cpp')
105
106 let _ = match boolOr(Flags.isSet(Flags.HARDCODED_START_VALUES), Flags.isSet(Flags.GEN_DEBUG_SYMBOLS))
107 case true then
108 let()= textFile(simulationInitParameterCppFile(simCode, &extraFuncsInit, &extraFuncsDeclInit, '<%className%>Initialize', stateDerVectorName, false),'OMCpp<%fileNamePrefix%>InitializeParameter.cpp')
109 let()= textFile(simulationInitAlgVarsCppFile(simCode , &extraFuncsInit , &extraFuncsDeclInit, '<%className%>Initialize', stateDerVectorName, false),'OMCpp<%fileNamePrefix%>InitializeAlgVars.cpp')
110 ""
111 else
112 ""
113
114 let() = textFile(simulationInitHeaderFile(simCode, &extraFuncsInit, &extraFuncsDeclInit, '<%className%>Initialize'), 'OMCpp<%fileNamePrefix%>Initialize.h')
115
116 let &jacobianVarsInit = buffer "" /*BUFD*/
117 let() = textFile(simulationJacobianHeaderFile(simCode, &extraFuncs, &extraFuncsDecl, "", &jacobianVarsInit, Flags.isSet(Flags.GEN_DEBUG_SYMBOLS)), 'OMCpp<%fileNamePrefix%>Jacobian.h')
118 let() = textFile(simulationJacobianCppFile(simCode, &extraFuncs, &extraFuncsDecl, "", &jacobianVarsInit, stateDerVectorName, false), 'OMCpp<%fileNamePrefix%>Jacobian.cpp')
119 let() = textFile(simulationStateSelectionCppFile(simCode, &extraFuncs, &extraFuncsDecl, "", stateDerVectorName, false), 'OMCpp<%fileNamePrefix%>StateSelection.cpp')
120 let() = textFile(simulationStateSelectionHeaderFile(simCode, &extraFuncs, &extraFuncsDecl, ""), 'OMCpp<%fileNamePrefix%>StateSelection.h')
121
122 let()= textFile(simulationMixedSystemCppFile(simCode, updateResiduals(simCode, extraResidualsFuncsDecl, className, stateDerVectorName /*=__zDot*/, false),
123 &extraFuncs, &extraFuncsDecl, "", stateDerVectorName, false),'OMCpp<%fileNamePrefix%>Mixed.cpp')
124 let() = textFile(simulationMixedSystemHeaderFile(simCode, &extraResidualsFuncsDecl), 'OMCpp<%fileNamePrefix%>Mixed.h')
125 let() = textFile(simulationWriteOutputHeaderFile(simCode, &extraFuncs, &extraFuncsDecl, ""), 'OMCpp<%fileNamePrefix%>WriteOutput.h')
126 let() = textFile(simulationWriteOutputCppFile(simCode, &extraFuncs, &extraFuncsDecl, "", stateDerVectorName, false), 'OMCpp<%fileNamePrefix%>WriteOutput.cpp')
127 let() = textFile(simulationFactoryFile(simCode, &extraFuncs, &extraFuncsDecl, ""), 'OMCpp<%fileNamePrefix%>FactoryExport.cpp')
128
129 let() = textFile(simulationMainRunScript(simCode, &extraFuncs, &extraFuncsDecl, ""), '<%fileNamePrefix%><%simulationMainRunScriptSuffix(simCode, &extraFuncs, &extraFuncsDecl, "")%>')
130 let jac = (jacobianMatrices |> JAC_MATRIX(columns=mat) =>
131 (mat |> JAC_COLUMN(columnEqns=eqs) => algloopfiles(eqs,simCode, &extraFuncs, &extraFuncsDecl, "", contextAlgloopJacobian, 0, stateDerVectorName, false) ;separator="")
132 ;separator="")
133 let alg = algloopfiles(listAppend(allEquations, initialEquations), simCode, &extraFuncs, &extraFuncsDecl, "", contextAlgloop, 0, stateDerVectorName, false)
134 let clk = getSubPartitions(clockedPartitions) |> subPartition hasindex i fromindex 1 =>
135 match subPartition
136 case SUBPARTITION(__) then
137 algloopfiles(listAppend(equations, removedEquations), simCode, &extraFuncs, &extraFuncsDecl, "", contextAlgloop, i, stateDerVectorName, false)
138 ; separator = "\n"
139 let() = textFile(algloopMainfile(simCode, &extraFuncs, &extraFuncsDecl, "", contextAlgloop), 'OMCpp<%fileNamePrefix%>AlgLoopMain.cpp')
140 let() = textFile(calcHelperMainfile(simCode, &extraFuncs, &extraFuncsDecl, ""), 'OMCpp<%fileNamePrefix%>CalcHelperMain.cpp')
141 ""
142 // empty result of the top-level template .., only side effects
143 end match
144 end translateModel;
145
146 // HEADER
147 1 template additionalHpcomIncludes(SimCode simCode, Text& extraFuncs, Text& extraFuncsDecl, Text extraFuncsNamespace, Boolean useFlatArrayNotation)
148 "Generates code for header file for simulation target."
149 ::=
150 match simCode
151 case SIMCODE(__) then
152 <<
153 <%additionalHpcomIncludesForParallelCode(simCode, extraFuncs, extraFuncsDecl, extraFuncsNamespace)%>
154 >>
155 end match
156 end additionalHpcomIncludes;
157
158 1 template additionalHpcomIncludesForParallelCode(SimCode simCode, Text& extraFuncs, Text& extraFuncsDecl, Text extraFuncsNamespace)
159 ::=
160 let type = getConfigString(HPCOM_CODE)
161 match type
162 case ("openmp") then
163 <<
164 #include <omp.h>
165 >>
166 case ("pthreads")
167 case ("pthreads_spin") then
168 <<
169 >>
170 case ("tbb") then
171 <<
172 #include <tbb/tbb.h>
173 #include <tbb/flow_graph.h>
174 #include <tbb/tbb_stddef.h>
175 #if TBB_INTERFACE_VERSION >= 8000
176 #include <tbb/task_arena.h>
177 #endif
178 >>
179 case ("mpi") then // MF: mpi.h
180 <<
181 #include <mpi.h>
182 >>
183 else ""
184 end match
185 end additionalHpcomIncludesForParallelCode;
186
187 1 template additionalHpcomProtectedMemberDeclaration(SimCode simCode, Text& extraFuncs, Text& extraFuncsDecl, Text extraFuncsNamespace, Boolean useFlatArrayNotation)
188 "Generates class declarations."
189 ::=
190 match simCode
191 case SIMCODE(modelInfo = MODELINFO(__), hpcomData=HPCOMDATA(schedules=schedulesOpt)) then
192 let &extraFuncsDecl += generateAdditionalFunctionHeaders(hpcomData.schedules)
193 let &extraFuncsDecl += generateAdditionalHpcomVarHeaders(hpcomData.schedules)
194 let type = getConfigString(HPCOM_CODE)
195
196 <<
197 static long unsigned int getThreadNumber()
198 {
199 <% match type
200 case ("openmp") then
201 <<
202 return (long unsigned int)omp_get_thread_num();
203 >>
204 case ("mpi") then
205 <<
206 return -1; //not supported
207 >>
208 case ("tbb") then
209 <<
210 return -1; //not supported
211 >>
212 else
213 <<
214 #if defined(USE_THREAD)
215 return std::hash<std::thread::id>()(std::this_thread::get_id());
216 #else
217 return 0;
218 #endif
219 >>
220 end match %>
221 }
222 <% if boolNot(stringEq(getConfigString(PROFILING_LEVEL),"none")) then
223 <<
224 std::vector<MeasureTimeData*> *measureTimeArrayHpcom;
225 std::vector<MeasureTimeData*> *measureTimeSchedulerArrayHpcom_evaluateODE;
226 std::vector<MeasureTimeData*> *measureTimeSchedulerArrayHpcom_evaluateDAE;
227 std::vector<MeasureTimeData*> *measureTimeSchedulerArrayHpcom_evaluateZeroFuncs;
228 //MeasureTimeValues *measuredStartValuesODE, *measuredEndValuesODE;
229 MeasureTimeValues *measuredSchedulerStartValues, *measuredSchedulerEndValues;
230
231 #ifdef MEASURETIME_MODELFUNCTIONS
232 std::vector<MeasureTimeData*> *measureTimeThreadArrayOdeHpcom;
233 std::vector<MeasureTimeData*> *measureTimeThreadArrayDaeHpcom;
234 std::vector<MeasureTimeData*> *measureTimeThreadArrayZeroFuncHpcom;
235 <%List.intRange(getConfigInt(NUM_PROC)) |> threadIdx => 'MeasureTimeValues* measuredSchedulerStartValues_<%intSub(threadIdx,1)%>;'; separator="\n"%>
236 <%List.intRange(getConfigInt(NUM_PROC)) |> threadIdx => 'MeasureTimeValues* measuredSchedulerEndValues_<%intSub(threadIdx,1)%>;'; separator="\n"%>
237 #endif //MEASURETIME_MODELFUNCTIONS
238 >>%>
239 >>
240 end match
241 end additionalHpcomProtectedMemberDeclaration;
242
243 ✗ template generateAdditionalStructHeaders(Schedule odeSchedule)
244 ::=
245 let type = getConfigString(HPCOM_CODE)
246 match odeSchedule
247 case TASKDEPSCHEDULE(__) then
248 match type
249 case ("openmp") then
250 <<
251 >>
252 case ("tbb") then
253 <<
254 //Required for Intel TBB
255 struct VoidFunctionBody {
256 function<void(void)> void_function;
257 VoidFunctionBody(function<void(void)> void_function) : void_function(void_function) { }
258 FORCE_INLINE void operator()( tbb::flow::continue_msg ) const
259 {
260 void_function();
261 }
262 };
263 #if TBB_INTERFACE_VERSION >= 8000
264 struct TbbArenaFunctor
265 {
266 tbb::flow::graph * g;
267 tbb::flow::broadcast_node<tbb::flow::continue_msg> * sn;
268
269 TbbArenaFunctor( )
270 {
271 g = NULL;
272 sn = NULL;
273 }
274
275 TbbArenaFunctor( tbb::flow::graph & in_g , tbb::flow::broadcast_node<tbb::flow::continue_msg> & in_sn )
276 {
277 g = &in_g;
278 sn = &in_sn;
279 }
280
281 void operator()()
282 {
283 sn->try_put( tbb::flow::continue_msg() );
284 g->wait_for_all();
285 }
286
287 };
288 #endif
289 >>
290 else ""
291 end match
292 else ""
293 end match
294 end generateAdditionalStructHeaders;
295
296 1 template generateAdditionalFunctionHeaders(Option<tuple<Schedule,Schedule,Schedule>> schedulesOpt)
297 ::=
298 let type = getConfigString(HPCOM_CODE)
299 <<
300 FORCE_INLINE void evaluateParallel(const UPDATETYPE command, int evaluateMode);
301 <%match schedulesOpt
302 case SOME((odeSchedule as THREADSCHEDULE(__),_,_)) then
303 match type
304 case ("openmp") then
305 <<
306 >>
307 else
308 let headers = listRest(arrayList(odeSchedule.threadTasks)) |> tt hasindex i0 fromindex 1 => generateThreadFunctionHeaderDecl(i0); separator="\n"
309 <<
310 <%headers%>
311 >>
312 end match
313 case SOME((odeSchedule as TASKDEPSCHEDULE(__),daeSchedule as TASKDEPSCHEDULE(__),zeroFuncSchedule as TASKDEPSCHEDULE(__))) then
314 match type
315 case ("openmp") then
316 <<
317 >>
318 case ("tbb") then
319 let voidfuncsOde = odeSchedule.tasks |> task => (
320 match task
321 case ((task as CALCTASK(__),parents)) then
322 <<
323 void taskFuncOde_<%task.index%>();
324 >>
325 else ""
326 ); separator="\n"
327 let voidfuncsDae = daeSchedule.tasks |> task => (
328 match task
329 case ((task as CALCTASK(__),parents)) then
330 <<
331 void taskFuncAll_<%task.index%>();
332 >>
333 else ""
334 ); separator="\n"
335 let voidfuncsZeroFunc = zeroFuncSchedule.tasks |> task => (
336 match task
337 case ((task as CALCTASK(__),parents)) then
338 <<
339 void taskFuncZeroFunc_<%task.index%>();
340 >>
341 else ""
342 ); separator="\n"
343 <<
344 <%generateAdditionalStructHeaders(odeSchedule)%>
345
346 <%voidfuncsOde%>
347 <%voidfuncsDae%>
348 <%voidfuncsZeroFunc%>
349 >>
350 else ""
351 end match
352 else ""
353 end match%>
354 >>
355 end generateAdditionalFunctionHeaders;
356
357 1 template generateAdditionalHpcomVarHeaders(Option<tuple<Schedule,Schedule,Schedule>> schedulesOpt)
358 ::=
359 let type = getConfigString(HPCOM_CODE)
360 <<
361 UPDATETYPE _command;
362 int _evaluateMode;
363 <%
364 match schedulesOpt
365 case SOME((odeSchedule as LEVELSCHEDULE(useFixedAssignments=true),_,_)) then
366 match type
367 case ("pthreads")
368 case ("pthreads_spin") then
369 <<
370 <%List.intRange(getConfigInt(NUM_PROC)) |> thIdx hasindex i0 fromindex 0 => generateThreadHeaderDecl(i0, type)%>
371 <%createBarrierByName("levelBarrier","", getConfigInt(NUM_PROC), type)%>
372 <%createLockByLockName("measureTimeArrayLock", "", type)%>
373 bool _simulationFinished;
374 >>
375 else ""
376 end match
377 case SOME((odeSchedule as THREADSCHEDULE(__),daeSchedule as THREADSCHEDULE(__),zeroFuncSchedule as THREADSCHEDULE(__))) then
378 let odeLocks = createLockArrayByName(listLength(odeSchedule.outgoingDepTasks),"_lockOde",type)//odeSchedule.outgoingDepTasks |> task => createLockByDepTask(task, "_lockOde", type); separator="\n"
379 let daeLocks = createLockArrayByName(listLength(daeSchedule.outgoingDepTasks),"_lockDae",type)//daeSchedule.outgoingDepTasks |> task => createLockByDepTask(task, "_lockDae", type); separator="\n"
380 let zeroFuncLocks = createLockArrayByName(listLength(zeroFuncSchedule.outgoingDepTasks),"_lockZeroFunc",type)//daeSchedule.outgoingDepTasks |> task => createLockByDepTask(task, "_lockDae", type); separator="\n"
381 match type
382 case ("openmp") then
383 let threadDecl = arrayList(odeSchedule.threadTasks) |> tt hasindex i0 fromindex 0 => generateThreadHeaderDecl(i0, type); separator="\n"
384 <<
385 <%odeLocks%>
386 <%daeLocks%>
387 <%zeroFuncLocks%>
388 <%threadDecl%>
389 >>
390 case "mpi" then
391 <<
392 //MF Todo BLABLUB
393 >>
394 else
395 let threadDecl = listRest(arrayList(odeSchedule.threadTasks)) |> tt hasindex i0 fromindex 1 => generateThreadHeaderDecl(i0, type); separator="\n"
396 let thLocks = listRest(arrayList(odeSchedule.threadTasks)) |> tt hasindex i0 fromindex 1 => createLockByLockName(i0, "th_lock", type); separator="\n"
397 let thLocks1 = listRest(arrayList(odeSchedule.threadTasks)) |> tt hasindex i0 fromindex 1 => createLockByLockName(i0, "th_lock1", type); separator="\n"
398 <<
399 bool _terminateThreads;
400 <%odeLocks%>
401 <%daeLocks%>
402 <%zeroFuncLocks%>
403 <%thLocks%>
404 <%thLocks1%>
405 <%threadDecl%>
406 >>
407 end match
408 case SOME((odeSchedule as TASKDEPSCHEDULE(__),_,_)) then
409 match type
410 case ("openmp") then
411 << >>
412 case ("tbb") then
413 <<
414 tbb::flow::graph _tbbGraphOde;
415 tbb::flow::broadcast_node<tbb::flow::continue_msg> _tbbStartNodeOde;
416 tbb::flow::graph _tbbGraphAll;
417 tbb::flow::broadcast_node<tbb::flow::continue_msg> _tbbStartNodeAll;
418 tbb::flow::graph _tbbGraphZeroFunc;
419 tbb::flow::broadcast_node<tbb::flow::continue_msg> _tbbStartNodeZeroFunc;
420 std::vector<tbb::flow::continue_node<tbb::flow::continue_msg>* > _tbbNodeListOde;
421 std::vector<tbb::flow::continue_node<tbb::flow::continue_msg>* > _tbbNodeListAll;
422 std::vector<tbb::flow::continue_node<tbb::flow::continue_msg>* > _tbbNodeListZeroFunc;
423 #if TBB_INTERFACE_VERSION >= 8000
424 tbb::task_arena _tbbArena;
425 TbbArenaFunctor _tbbArenaFunctorOde;
426 TbbArenaFunctor _tbbArenaFunctorAll;
427 TbbArenaFunctor _tbbArenaFunctorZeroFunc;
428 #endif
429 >>
430 else ""
431 end match
432 else ""
433 end match
434 %>
435 >>
436 end generateAdditionalHpcomVarHeaders;
437
438 1 template generateThreadHeaderDecl(Integer threadIdx, String iType)
439 ::=
440 match iType
441 case ("openmp") then
442 <<
443 >>
444 else
445 <<
446 thread* evaluateThread<%threadIdx%>;
447 >>
448 end match
449 end generateThreadHeaderDecl;
450
451 ✗ template generateThreadFunctionHeaderDecl(Integer threadIdx)
452 ::=
453 <<
454 void evaluateThreadFunc<%threadIdx%>();
455 >>
456 end generateThreadFunctionHeaderDecl;
457
458 1 template additionalHpcomConstructorDefinitions(Option<tuple<Schedule,Schedule,Schedule>> scheduleOpt)
459 ::=
460 let type = getConfigString(HPCOM_CODE)
461 match scheduleOpt
462 case SOME((odeSchedule as LEVELSCHEDULE(useFixedAssignments=true),_,_)) then
463 match type
464 case ("pthreads")
465 case ("pthreads_spin") then
466 <<
467 ,_command(IContinuous::UNDEF_UPDATE)
468 ,_simulationFinished(false)
469 ,<%initializeBarrierByName("levelBarrier","",getConfigInt(NUM_PROC),type)%>
470 >>
471 else ""
472 case SOME((odeSchedule as TASKDEPSCHEDULE(__),daeSchedule as TASKDEPSCHEDULE(__),zeroFuncSchedule as TASKDEPSCHEDULE(__))) then
473 match type
474 case ("tbb") then
475 <<
476 ,_tbbGraphOde()
477 ,_tbbGraphAll()
478 ,_tbbGraphZeroFunc()
479 ,_tbbStartNodeOde(_tbbGraphOde)
480 ,_tbbStartNodeAll(_tbbGraphAll)
481 ,_tbbStartNodeZeroFunc(_tbbGraphZeroFunc)
482 ,_tbbNodeListOde(<%listLength(odeSchedule.tasks)%>,NULL)
483 ,_tbbNodeListAll(<%listLength(daeSchedule.tasks)%>,NULL)
484 ,_tbbNodeListZeroFunc(<%listLength(zeroFuncSchedule.tasks)%>,NULL)
485 >>
486 else ""
487 end match
488 else ""
489 end match
490 end additionalHpcomConstructorDefinitions;
491
492 1 template additionalHpcomConstructorBodyStatements(Option<tuple<Schedule,Schedule,Schedule>> schedulesOpt, String modelNamePrefixStr, String fullModelName)
493 ::=
494 let type = getConfigString(HPCOM_CODE)
495 let threadMeasureTimeBlocks = if boolNot(stringEq(getConfigString(PROFILING_LEVEL),"none")) then generateThreadMeasureTimeDeclaration(fullModelName, getConfigInt(NUM_PROC)) else ""
496 let schedulerSpecificReturn = match schedulesOpt
497 case SOME((odeSchedule as LEVELSCHEDULE(useFixedAssignments=true),daeSchedule as LEVELSCHEDULE(useFixedAssignments=true),zeroFuncSchedule as LEVELSCHEDULE(useFixedAssignments=true))) then
498 match type
499 case ("pthreads")
500 case ("pthreads_spin") then
501 let threadFuncs = List.intRange(intSub(getConfigInt(NUM_PROC),1)) |> tt hasindex i0 fromindex 1 => generateThread(i0, type, modelNamePrefixStr,"evaluateThreadFunc"); separator="\n"
502 <<
503 <%threadFuncs%>
504
505 <%if boolNot(stringEq(getConfigString(PROFILING_LEVEL),"none")) then
506 <<
507 #ifdef MEASURETIME_MODELFUNCTIONS
508 measureTimeSchedulerArrayHpcom_evaluateODE = new std::vector<MeasureTimeData*>(size_t(<%listLength(odeSchedule.tasksOfLevels)%>), NULL);
509 MeasureTime::addResultContentBlock("<%fullModelName%>","functions_HPCOM_Sections_ODE",measureTimeSchedulerArrayHpcom_evaluateODE);
510 measuredSchedulerStartValues = MeasureTime::getZeroValues();
511 measuredSchedulerEndValues = MeasureTime::getZeroValues();
512 <%List.intRange(listLength(odeSchedule.tasksOfLevels)) |> levelIdx => '(*measureTimeSchedulerArrayHpcom_evaluateODE)[<%intSub(levelIdx,1)%>] = new MeasureTimeData("evaluateODE_level_<%levelIdx%>");'; separator="\n"%>
513
514 measureTimeSchedulerArrayHpcom_evaluateDAE = new std::vector<MeasureTimeData*>(size_t(<%listLength(daeSchedule.tasksOfLevels)%>), NULL);
515 MeasureTime::addResultContentBlock("<%fullModelName%>","functions_HPCOM_Sections_DAE",measureTimeSchedulerArrayHpcom_evaluateDAE);
516 measuredSchedulerStartValues = MeasureTime::getZeroValues();
517 measuredSchedulerEndValues = MeasureTime::getZeroValues();
518 <%List.intRange(listLength(daeSchedule.tasksOfLevels)) |> levelIdx => '(*measureTimeSchedulerArrayHpcom_evaluateDAE)[<%intSub(levelIdx,1)%>] = new MeasureTimeData("evaluateDAE_level_<%levelIdx%>");'; separator="\n"%>
519
520 measureTimeSchedulerArrayHpcom_evaluateZeroFuncs = new std::vector<MeasureTimeData*>(size_t(<%listLength(zeroFuncSchedule.tasksOfLevels)%>), NULL);
521 MeasureTime::addResultContentBlock("<%fullModelName%>","functions_HPCOM_Sections_ZeroFuncs",measureTimeSchedulerArrayHpcom_evaluateZeroFuncs);
522 measuredSchedulerStartValues = MeasureTime::getZeroValues();
523 measuredSchedulerEndValues = MeasureTime::getZeroValues();
524 <%List.intRange(listLength(zeroFuncSchedule.tasksOfLevels)) |> levelIdx => '(*measureTimeSchedulerArrayHpcom_evaluateZeroFuncs)[<%intSub(levelIdx,1)%>] = new MeasureTimeData("evaluateZeroFunc_level_<%levelIdx%>");'; separator="\n"%>
525 #endif //MEASURETIME_MODELFUNCTIONS
526 >>
527 %>
528 >>
529 else ""
530 end match
531 case SOME((odeSchedule as THREADSCHEDULE(__),daeSchedule as THREADSCHEDULE(__),zeroFuncSchedule as THREADSCHEDULE(__))) then
532 let initLocksOde = initializeArrayLocks(listLength(odeSchedule.outgoingDepTasks),"_lockOde",type)//odeSchedule.outgoingDepTasks |> task => initializeLockByDepTask(task, "_lockOde", type); separator="\n"
533 let assignLocksOde = assignArrayLocks(listLength(odeSchedule.outgoingDepTasks),"_lockOde",type)//odeSchedule.outgoingDepTasks |> task => assignLockByDepTask(task, "_lockOde", type); separator="\n"
534 let initLocksDae = initializeArrayLocks(listLength(daeSchedule.outgoingDepTasks),"_lockDae",type)//daeSchedule.outgoingDepTasks |> task => initializeLockByDepTask(task, "_lockDae", type); separator="\n"
535 let assignLocksDae = assignArrayLocks(listLength(daeSchedule.outgoingDepTasks),"_lockDae",type)//daeSchedule.outgoingDepTasks |> task => assignLockByDepTask(task, "_lockDae", type); separator="\n"
536 let initLocksZeroFunc = initializeArrayLocks(listLength(zeroFuncSchedule.outgoingDepTasks),"_lockZeroFunc",type)//daeSchedule.outgoingDepTasks |> task => initializeLockByDepTask(task, "_lockDae", type); separator="\n"
537 let assignLocksZeroFunc = assignArrayLocks(listLength(zeroFuncSchedule.outgoingDepTasks),"_lockZeroFunc",type)//daeSchedule.outgoingDepTasks |> task => assignLockByDepTask(task, "_lockDae", type); separator="\n"
538
539 match type
540 case ("openmp") then
541 let threadFuncs = arrayList(odeSchedule.threadTasks) |> tt hasindex i0 fromindex 0 => generateThread(i0, type, modelNamePrefixStr,"evaluateThreadFunc"); separator="\n"
542 <<
543 omp_set_dynamic(0);
544 <%threadFuncs%>
545 <%initLocksOde%>
546 <%initLocksDae%>
547 <%initLocksZeroFunc%>
548 >>
549 case ("mpi") then
550 <<
551 //MF: Initialize MPI related stuff - nothing todo?
552 >>
553 else
554 let threadFuncs = listRest(arrayList(odeSchedule.threadTasks)) |> tt hasindex i0 fromindex 1 => generateThread(i0, type, modelNamePrefixStr,"evaluateThreadFunc"); separator="\n"
555 let threadLocksInit = listRest(arrayList(odeSchedule.threadTasks)) |> tt hasindex i0 fromindex 1 => initializeLockByLockName(i0, "th_lock", type); separator="\n"
556 let threadLocksInit1 = listRest(arrayList(odeSchedule.threadTasks)) |> tt hasindex i0 fromindex 1 => initializeLockByLockName(i0, "th_lock1", type); separator="\n"
557 let threadAssignLocks = listRest(arrayList(odeSchedule.threadTasks)) |> tt hasindex i0 fromindex 1 => assignLockByLockName(i0, "th_lock", type); separator="\n"
558 let threadAssignLocks1 = listRest(arrayList(odeSchedule.threadTasks)) |> tt hasindex i0 fromindex 1 => assignLockByLockName(i0, "th_lock1", type); separator="\n"
559 <<
560 _terminateThreads = false;
561 _command = IContinuous::UNDEF_UPDATE;
562 _evaluateMode = -1;
563
564 <%initLocksOde%>
565 <%initLocksDae%>
566 <%initLocksZeroFunc%>
567 <%threadLocksInit%>
568 <%threadLocksInit1%>
569
570 <%assignLocksDae%>
571 <%assignLocksOde%>
572 <%assignLocksZeroFunc%>
573 <%threadAssignLocks%>
574 <%threadAssignLocks1%>
575
576 <%threadFuncs%>
577 >>
578 case SOME((odeSchedule as TASKDEPSCHEDULE(__),daeSchedule as TASKDEPSCHEDULE(__),zeroFuncSchedule as TASKDEPSCHEDULE(__))) then
579 match type
580 case ("tbb") then
581 let tbbVars = generateTbbConstructorExtension(odeSchedule.tasks, daeSchedule.tasks, zeroFuncSchedule.tasks, modelNamePrefixStr)
582 <<
583 <%tbbVars%>
584 >>
585 else ""
586 else ""
587 end match
588 <<
589 <%schedulerSpecificReturn%>
590 <%threadMeasureTimeBlocks%>
591 >>
592 end additionalHpcomConstructorBodyStatements;
593
594 ✗ template generateThreadMeasureTimeDeclaration(String fullModelName, Integer numberOfThreads)
595 ::=
596 <<
597 #ifdef MEASURETIME_MODELFUNCTIONS
598 measureTimeThreadArrayOdeHpcom = new std::vector<MeasureTimeData*>(size_t(<%numberOfThreads%>), NULL);
599 measureTimeThreadArrayDaeHpcom = new std::vector<MeasureTimeData*>(size_t(<%numberOfThreads%>), NULL);
600 measureTimeThreadArrayZeroFuncHpcom = new std::vector<MeasureTimeData*>(size_t(<%numberOfThreads%>), NULL);
601 MeasureTime::addResultContentBlock("<%fullModelName%>","evaluateODE_threads",measureTimeThreadArrayOdeHpcom);
602 MeasureTime::addResultContentBlock("<%fullModelName%>","evaluateDAE_threads",measureTimeThreadArrayDaeHpcom);
603 MeasureTime::addResultContentBlock("<%fullModelName%>","evaluateZeroFunc_threads",measureTimeThreadArrayZeroFuncHpcom);
604 <%List.intRange(numberOfThreads) |> threadIdx => 'measuredSchedulerStartValues_<%intSub(threadIdx,1)%> = MeasureTime::getZeroValues();'; separator="\n"%>
605 <%List.intRange(numberOfThreads) |> threadIdx => 'measuredSchedulerEndValues_<%intSub(threadIdx,1)%> = MeasureTime::getZeroValues();'; separator="\n"%>
606 <%List.intRange(numberOfThreads) |> threadIdx => '(*measureTimeThreadArrayOdeHpcom)[<%intSub(threadIdx,1)%>] = new MeasureTimeData("evaluateODE_thread_<%threadIdx%>");'; separator="\n"%>
607 <%List.intRange(numberOfThreads) |> threadIdx => '(*measureTimeThreadArrayDaeHpcom)[<%intSub(threadIdx,1)%>] = new MeasureTimeData("evaluateDAE_thread_<%threadIdx%>");'; separator="\n"%>
608 <%List.intRange(numberOfThreads) |> threadIdx => '(*measureTimeThreadArrayZeroFuncHpcom)[<%intSub(threadIdx,1)%>] = new MeasureTimeData("evaluateZeroFunc_thread_<%threadIdx%>");'; separator="\n"%>
609 #endif //MEASURETIME_MODELFUNCTIONS
610 >>
611 end generateThreadMeasureTimeDeclaration;
612
613 ✗ template initializeArrayLocks(Integer numComms, String lockName, String iType)
614 ::=
615 match(iType)
616 case "openmp" then
617 <<
618 for(unsigned i=0;i<<%numComms%>;++i)
619 omp_init_lock(&<%lockName%>_[i]);
620 >>
621 case "pthreads" then
622 <<
623 for(unsigned i=0;i<<%numComms%>;++i)
624 <%lockName%>_[i] = new alignedLock();
625 >>
626 case "pthreads_spin" then
627 <<
628 for(unsigned i=0;i<<%numComms%>;++i)
629 <%lockName%>_[i] = new alignedSpinlock();
630 >>
631 else
632 <<
633 //Unsupported parallel instrumentation
634 >>
635 end initializeArrayLocks;
636
637 ✗ template assignArrayLocks(Integer numComms, String lockName, String iType)
638 ::=
639 match iType
640 case ("openmp") then
641 <<
642 for(unsigned i=0;i<<%numComms%>;++i)
643 omp_set_lock(&<%lockName%>_[i]);
644 >>
645 case ("pthreads")
646 case ("pthreads_spin") then
647 <<
648 for(unsigned i=0;i<<%numComms%>;++i)
649 <%lockName%>_[i]->lock();
650 >>
651
652 else
653 <<
654 //Unsupported parallel instrumentation
655 >>
656 end match
657 end assignArrayLocks;
658
659 ✗ template createLockArrayByName(Integer numComms, String lockName, String iType)
660 ::=
661 match(iType)
662 case "openmp" then
663 <<
664 omp_lock_t <%lockName%>_[<%numComms%>];
665 >>
666 case "pthreads" then
667 <<
668 alignedLock* <%lockName%>_[<%numComms%>];
669 >>
670 case "pthreads_spin" then
671 <<
672 alignedSpinlock* <%lockName%>_[<%numComms%>];
673 >>
674 else
675 <<
676 //Unsupported parallel instrumentation
677 >>
678 end createLockArrayByName;
679
680 ✗ template destroyArrayLocks(Integer numComms, String lockName, String iType)
681 ::=
682 match(iType)
683 case "openmp" then
684 <<
685 for(unsigned i=0;i<<%numComms%>;++i)
686 omp_destroy_lock(&<%lockName%>_[i]);
687 >>
688 case "pthreads"
689 case "pthreads_spin" then
690 <<
691 for(unsigned i=0;i<<%numComms%>;++i)
692 delete <%lockName%>_[i];
693 >>
694 else
695 <<
696 //Unsupported parallel instrumentation
697 >>
698 end destroyArrayLocks;
699
700 1 template additionalHpcomDestructorBodyStatements(Option<tuple<Schedule,Schedule,Schedule>> schedulesOpt)
701 ::=
702 let type = getConfigString(HPCOM_CODE)
703
704 let schedulerSpecificCode = match schedulesOpt
705 case SOME((odeSchedule as LEVELSCHEDULE(useFixedAssignments=true),_,_)) then
706 match type
707 case ("pthreads")
708 case ("pthreads_spin") then
709 <<
710 _simulationFinished = true;
711 //_evaluateBarrier.wait();
712 _levelBarrier.wait();
713 //_evaluateBarrier.wait();
714 _levelBarrier.wait();
715 >>
716 else ""
717 case SOME((odeSchedule as THREADSCHEDULE(__),daeSchedule as THREADSCHEDULE(__),zeroFuncSchedule as THREADSCHEDULE(__))) then
718 let destroyLocksOde = destroyArrayLocks(listLength(odeSchedule.outgoingDepTasks),"_lockOde",type)//odeSchedule.outgoingDepTasks |> task => destroyLockByDepTask(task, "_lockOde", type); separator="\n"
719 let destroyLocksDae = destroyArrayLocks(listLength(daeSchedule.outgoingDepTasks),"_lockDae",type)//daeSchedule.outgoingDepTasks |> task => destroyLockByDepTask(task, "_lockDae", type); separator="\n"
720 let destroyLocksZeroFunc = destroyArrayLocks(listLength(zeroFuncSchedule.outgoingDepTasks),"_lockZeroFunc",type)//daeSchedule.outgoingDepTasks |> task => destroyLockByDepTask(task, "_lockDae", type); separator="\n"
721 match type
722 case ("openmp") then
723 <<
724 <%destroyLocksOde%>
725 <%destroyLocksDae%>
726 <%destroyLocksZeroFunc%>
727 >>
728 case "mpi" then
729 <<
730 //MF: Destruct MPI related stuff - nothing at the moment.
731 >>
732 else
733 let destroyThreads = listRest(arrayList(odeSchedule.threadTasks)) |> tt hasindex i0 fromindex 1 => function_HPCOM_destroyThread(i0, type); separator="\n"
734 let threadLocksDel = listRest(arrayList(odeSchedule.threadTasks)) |> tt hasindex i0 fromindex 1 => destroyLockByLockName(i0, "th_lock", type); separator="\n"
735 let threadLocksDel1 = listRest(arrayList(odeSchedule.threadTasks)) |> tt hasindex i0 fromindex 1 => destroyLockByLockName(i0, "th_lock1", type); separator="\n"
736 let joinThreads = listRest(arrayList(odeSchedule.threadTasks)) |> tt hasindex i0 fromindex 1 => function_HPCOM_joinThread(i0, type); separator="\n"
737 let threadReleaseLocks = listRest(arrayList(odeSchedule.threadTasks)) |> tt hasindex i0 fromindex 1 => releaseLockByLockName(i0, "th_lock", type); separator="\n"
738 <<
739 _terminateThreads = true;
740 <%threadReleaseLocks%>
741 <%joinThreads%>
742 <%destroyLocksOde%>
743 <%destroyLocksDae%>
744 <%destroyLocksZeroFunc%>
745 <%threadLocksDel%>
746 <%threadLocksDel1%>
747 <%destroyThreads%>
748 >>
749 case SOME((odeSchedule as TASKDEPSCHEDULE(__),_,_)) then
750 match type
751 case ("tbb") then
752 <<
753 for(std::vector<tbb::flow::continue_node<tbb::flow::continue_msg>* >::iterator it = _tbbNodeListOde.begin(); it != _tbbNodeListOde.end(); it++)
754 delete *it;
755 for(std::vector<tbb::flow::continue_node<tbb::flow::continue_msg>* >::iterator it = _tbbNodeListAll.begin(); it != _tbbNodeListAll.end(); it++)
756 delete *it;
757 for(std::vector<tbb::flow::continue_node<tbb::flow::continue_msg>* >::iterator it = _tbbNodeListZeroFunc.begin(); it != _tbbNodeListZeroFunc.end(); it++)
758 delete *it;
759 >>
760 else ""
761 else ""
762 end match
763 <<
764 #ifdef MEASURETIME_MODELFUNCTIONS
765 <%List.intRange(getConfigInt(NUM_PROC)) |> threadIdx => 'delete measuredSchedulerStartValues_<%intSub(threadIdx,1)%>;'; separator="\n"%>
766 <%List.intRange(getConfigInt(NUM_PROC)) |> threadIdx => 'delete measuredSchedulerEndValues_<%intSub(threadIdx,1)%>;'; separator="\n"%>
767 #endif //MEASURETIME_MODELFUNCTIONS
768 <%schedulerSpecificCode%>
769 >>
770 end additionalHpcomDestructorBodyStatements;
771
772 1 template updateHpcom(list<SimEqSystem> allEquationsPlusWhen, SimCode simCode, Text& extraFuncs, Text& extraFuncsDecl, Text extraFuncsNamespace, Context context, Text stateDerVectorName /*=__zDot*/, Boolean useFlatArrayNotation)
773 ::=
774 let &varDecls = buffer "" /*BUFD*/
775
776 match simCode
777 case SIMCODE(modelInfo = MODELINFO(__), hpcomData=HPCOMDATA(__)) then
778 let &extraFuncsPar = buffer ""
779 let parCode = generateParallelEvaluate(allEquationsPlusWhen, modelInfo.name, simCode, extraFuncsPar ,extraFuncsDecl, extraFuncsNamespace, hpcomData.schedules, context, stateDerVectorName, lastIdentOfPath(modelInfo.name), useFlatArrayNotation)
780 <<
781 <%equationFunctions(allEquations, simCode, &extraFuncs, &extraFuncsDecl, extraFuncsNamespace, contextSimulationDiscrete,stateDerVectorName,useFlatArrayNotation,false)%>
782
783 <%createEvaluateConditions(allEquations, simCode, &extraFuncs, &extraFuncsDecl, extraFuncsNamespace, contextOther, stateDerVectorName, useFlatArrayNotation)%>
784
785 <%clockedFunctions(getSubPartitions(clockedPartitions), simCode, &extraFuncs, &extraFuncsDecl, extraFuncsNamespace, contextSimulationDiscrete, stateDerVectorName, useFlatArrayNotation, boolNot(stringEq(getConfigString(PROFILING_LEVEL), "none")))%>
786
787 <%parCode%>
788
789 <%extraFuncsPar%>
790 >>
791 end match
792 end updateHpcom;
793
794 1 template generateParallelEvaluate(list<SimEqSystem> allEquationsPlusWhen, Absyn.Path name,
795 SimCode simCode, Text& extraFuncs, Text& extraFuncsDecl, Text extraFuncsNamespace, Option<tuple<Schedule, Schedule, Schedule>> schedulesOpt, Context context, Text stateDerVectorName /*=__zDot*/,
796 String modelNamePrefixStr, Boolean useFlatArrayNotation)
797 ::=
798 match simCode
799 case SIMCODE(modelInfo = MODELINFO(__)) then
800 let &varDecls = buffer "" /*BUFD*/
801 let measureTimeEvaluateOdeStart = if boolNot(stringEq(getConfigString(PROFILING_LEVEL),"none")) then generateMeasureTimeStartCode("measuredFunctionStartValues", "evaluateODE", "MEASURETIME_MODELFUNCTIONS") else ""
802 let measureTimeEvaluateOdeEnd = if boolNot(stringEq(getConfigString(PROFILING_LEVEL),"none")) then generateMeasureTimeEndCode("measuredFunctionStartValues", "measuredFunctionEndValues", "(*measureTimeFunctionsArray)[0]", "evaluateODE", "MEASURETIME_MODELFUNCTIONS") else ""
803
804 let measureTimeEvaluateAllStart = if boolNot(stringEq(getConfigString(PROFILING_LEVEL),"none")) then generateMeasureTimeStartCode("measuredFunctionStartValues", "evaluateAll", "MEASURETIME_MODELFUNCTIONS") else ""
805 let measureTimeEvaluateAllEnd = if boolNot(stringEq(getConfigString(PROFILING_LEVEL),"none")) then generateMeasureTimeEndCode("measuredFunctionStartValues", "measuredFunctionEndValues", "(*measureTimeFunctionsArray)[1]", "evaluateAll", "MEASURETIME_MODELFUNCTIONS") else ""
806
807 let measureTimeEvaluateZeroFuncStart = if boolNot(stringEq(getConfigString(PROFILING_LEVEL),"none")) then generateMeasureTimeStartCode("measuredFunctionStartValues", "evaluateZeroFuncs", "MEASURETIME_MODELFUNCTIONS") else ""
808 let measureTimeEvaluateZeroFuncEnd = if boolNot(stringEq(getConfigString(PROFILING_LEVEL),"none")) then generateMeasureTimeEndCode("measuredFunctionStartValues", "measuredFunctionEndValues", "(*measureTimeFunctionsArray)[4]", "evaluateZeroFuncs", "MEASURETIME_MODELFUNCTIONS") else ""
809
810 let type = getConfigString(HPCOM_CODE)
811
812 // Head of function is the same for all schedulers and parallelization methods:
813 let functionHead =
814 <<
815 //using type: <%type%>
816
817 void <%lastIdentOfPath(name)%>::evaluateZeroFuncs(const UPDATETYPE command)
818 {
819 <%measureTimeEvaluateZeroFuncStart%>
820 evaluateParallel(command, 1);
821 <%measureTimeEvaluateZeroFuncEnd%>
822 }
823
824 bool <%lastIdentOfPath(name)%>::evaluateAll(const UPDATETYPE command)
825 {
826 <%measureTimeEvaluateAllStart%>
827
828 <%createTimeConditionTreatments(timeEventLength(simCode), clockedPartitions)%>
829
830 <%varDecls%>
831
832 evaluateParallel(command, -1);
833 <%measureTimeEvaluateAllEnd%>
834
835 return _state_var_reinitialized;
836 }
837
838 void <%lastIdentOfPath(name)%>::evaluateODE(const UPDATETYPE command)
839 {
840 <%measureTimeEvaluateOdeStart%>
841 evaluateParallel(command, 0);
842 <%measureTimeEvaluateOdeEnd%>
843 }
844
845 //evaluateMode = 0 : evaluateODE
846 //evaluateMode < 0 : evaluateAll
847 //evaluateMode > 0 : evaluateZeroFunc
848 void <%lastIdentOfPath(name)%>::evaluateParallel(const UPDATETYPE command, int evaluateMode)
849 >>
850
851 match schedulesOpt
852 case SOME((odeSchedule as EMPTYSCHEDULE(tasks=SERIALTASKLIST(tasks=taskListOde)), daeSchedule as EMPTYSCHEDULE(tasks=SERIALTASKLIST(tasks=taskListDae)), zeroFuncsSchedule as EMPTYSCHEDULE(tasks=SERIALTASKLIST(tasks=taskListZeroFunc)))) then
853 <<
854 <%functionHead%>
855 {
856 if(evaluateMode == 0) //evaluate ODE
857 {
858 <%parallelThreadCodeWithSplit(allEquationsPlusWhen, taskListOde, 1, 1, "", "", &varDecls, simCode, extraFuncs, extraFuncsDecl, lastIdentOfPath(name), "evaluateODE_Th1", useFlatArrayNotation)%>
859 }
860 else if(evaluateMode < 0) //evaluate All
861 {
862 <%parallelThreadCodeWithSplit(allEquationsPlusWhen, taskListDae, 1, 1, "", "", &varDecls, simCode, extraFuncs, extraFuncsDecl, lastIdentOfPath(name), "evaluateAll_Th1", useFlatArrayNotation)%>
863 }
864 else //evaluate ZeroFuncs
865 {
866 <%parallelThreadCodeWithSplit(allEquationsPlusWhen, taskListZeroFunc, 1, 1, "", "", &varDecls, simCode, extraFuncs, extraFuncsDecl, lastIdentOfPath(name), "evaluateZeroFunc_Th1", useFlatArrayNotation)%>
867 }
868 }
869 >>
870 case SOME((odeSchedule as LEVELSCHEDULE(useFixedAssignments=false, tasksOfLevels=tasksOfLevelsOde), daeSchedule as LEVELSCHEDULE(useFixedAssignments=false, tasksOfLevels=tasksOfLevelsDae), zeroFuncSchedule as LEVELSCHEDULE(useFixedAssignments=false, tasksOfLevels=tasksOfLevelsZeroFunc))) then
871 let odeEqs = tasksOfLevelsOde |> tasks => generateLevelCodeForLevel(allEquationsPlusWhen, tasks, type, &varDecls, simCode, extraFuncs, extraFuncsDecl, lastIdentOfPath(name), useFlatArrayNotation); separator="\n"
872 let daeEqs = tasksOfLevelsDae |> tasks => generateLevelCodeForLevel(allEquationsPlusWhen, tasks, type, &varDecls, simCode, extraFuncs, extraFuncsDecl, lastIdentOfPath(name), useFlatArrayNotation); separator="\n"
873 let zeroFuncEqs = tasksOfLevelsZeroFunc |> tasks => generateLevelCodeForLevel(allEquationsPlusWhen, tasks, type, &varDecls, simCode, extraFuncs, extraFuncsDecl, lastIdentOfPath(name), useFlatArrayNotation); separator="\n"
874
875 match type
876 case ("openmp") then
877 let &extraFuncsDecl +=
878 <<
879 void evaluateODE_Parallel();
880 void evaluateAll_Parallel();
881 void evaluateZeroFuncs_Parallel();
882 >>
883
884 <<
885 void <%lastIdentOfPath(name)%>::evaluateODE_Parallel()
886 {
887 #pragma omp parallel num_threads(<%getConfigInt(NUM_PROC)%>)
888 {
889 <%odeEqs%>
890 }
891 }
892
893 void <%lastIdentOfPath(name)%>::evaluateAll_Parallel()
894 {
895 #pragma omp parallel num_threads(<%getConfigInt(NUM_PROC)%>)
896 {
897 <%daeEqs%>
898 }
899 }
900
901 void <%lastIdentOfPath(name)%>::evaluateZeroFuncs_Parallel()
902 {
903 #pragma omp parallel num_threads(<%getConfigInt(NUM_PROC)%>)
904 {
905 <%zeroFuncEqs%>
906 }
907 }
908
909 <%functionHead%>
910 {
911 this->_evaluateMode = _evaluateMode;
912 this->_command = command;
913 if(evaluateMode == 0)
914 {
915 evaluateODE_Parallel();
916 }
917 else if(evaluateMode < 0)
918 {
919 evaluateAll_Parallel();
920 }
921 else
922 {
923 evaluateZeroFuncs_Parallel();
924 }
925 }
926 >>
927 else
928 <<
929 <%functionHead%>
930 {
931 throw std::runtime_error("Type <%type%> is unsupported for level scheduling.");
932 }
933 >>
934 end match
935 case SOME((odeSchedule as LEVELSCHEDULE(useFixedAssignments=true), daeSchedule as LEVELSCHEDULE(useFixedAssignments=true), zeroFuncSchedule as LEVELSCHEDULE(useFixedAssignments=true))) then
936 match type
937 case ("openmp") then
938 let odeEqs = HpcOmCodegenUtil.convertFixedLevelScheduleToLevelThreadLists(odeSchedule, getConfigInt(NUM_PROC)) |> tasks hasindex i0 fromindex 0 => generateLevelFixedCodeForLevel(allEquationsPlusWhen, tasks, type, &varDecls, name, simCode, extraFuncs, extraFuncsDecl, lastIdentOfPath(name), useFlatArrayNotation); separator="\n"
939 let daeEqs = HpcOmCodegenUtil.convertFixedLevelScheduleToLevelThreadLists(daeSchedule, getConfigInt(NUM_PROC)) |> tasks hasindex i0 fromindex 0 => generateLevelFixedCodeForLevel(allEquationsPlusWhen, tasks, type, &varDecls, name, simCode, extraFuncs, extraFuncsDecl, lastIdentOfPath(name), useFlatArrayNotation); separator="\n"
940 let zeroFuncEqs = HpcOmCodegenUtil.convertFixedLevelScheduleToLevelThreadLists(zeroFuncSchedule, getConfigInt(NUM_PROC)) |> tasks hasindex i0 fromindex 0 => generateLevelFixedCodeForLevel(allEquationsPlusWhen, tasks, type, &varDecls, name, simCode, extraFuncs, extraFuncsDecl, lastIdentOfPath(name), useFlatArrayNotation); separator="\n"
941
942 let &extraFuncsDecl +=
943 <<
944 void evaluateODE_Parallel();
945 void evaluateAll_Parallel();
946 void evaluateZeroFuncs_Parallel();
947 >>
948
949 <<
950 void <%lastIdentOfPath(name)%>::evaluateODE_Parallel()
951 {
952 #pragma omp parallel num_threads(<%getConfigInt(NUM_PROC)%>)
953 {
954 int threadNum = getThreadNumber();
955 <%odeEqs%>
956 }
957 }
958
959 void <%lastIdentOfPath(name)%>::evaluateAll_Parallel()
960 {
961 #pragma omp parallel num_threads(<%getConfigInt(NUM_PROC)%>)
962 {
963 int threadNum = getThreadNumber();
964 <%daeEqs%>
965 }
966 }
967
968 void <%lastIdentOfPath(name)%>::evaluateZeroFuncs_Parallel()
969 {
970 #pragma omp parallel num_threads(<%getConfigInt(NUM_PROC)%>)
971 {
972 int threadNum = getThreadNumber();
973 <%zeroFuncEqs%>
974 }
975 }
976
977 <%functionHead%>
978 {
979 this->_evaluateMode = _evaluateMode;
980 this->_command = command;
981 if(evaluateMode == 0)
982 {
983 evaluateODE_Parallel();
984 }
985 else if(evaluateMode < 0)
986 {
987 evaluateAll_Parallel();
988 }
989 else
990 {
991 evaluateZeroFuncs_Parallel();
992 }
993 }
994 >>
995 case ("pthreads")
996 case ("pthreads_spin") then
997 let eqsFuncs = arrayList(HpcOmCodegenUtil.convertFixedLevelScheduleToTaskLists(odeSchedule, daeSchedule, zeroFuncSchedule, getConfigInt(NUM_PROC))) |> tasks hasindex i0 fromindex 0 => generateLevelFixedCodeForThread(allEquationsPlusWhen, tasks, i0, type, &varDecls, name, simCode, extraFuncs, extraFuncsDecl, lastIdentOfPath(name), useFlatArrayNotation); separator="\n"
998 let threadLocks = List.intRange(getConfigInt(NUM_PROC)) |> tt => createLockByLockName('threadLock<%tt%>', "", type); separator="\n"
999 <<
1000 <%eqsFuncs%>
1001
1002 <%functionHead%>
1003 {
1004 this->_command = command;
1005 this->_evaluateMode = evaluateMode;
1006
1007 if(evaluateMode == 0) //evaluate ODE
1008 {
1009 _levelBarrier.wait();
1010 evaluateThreadFuncODE_0();
1011 _levelBarrier.wait();
1012
1013 <%generateStateVarPrefetchCode(simCode, extraFuncs, extraFuncsDecl, extraFuncsNamespace)%>
1014 }
1015 else if(evaluateMode < 0) //evaluate All
1016 {
1017 _levelBarrier.wait();
1018 evaluateThreadFuncAll_0();
1019 _levelBarrier.wait();
1020 }
1021 else //evaluate ZeroFuncs
1022 {
1023 _levelBarrier.wait();
1024 evaluateThreadFuncZeroFunc_0();
1025 _levelBarrier.wait();
1026 }
1027 }
1028 >>
1029 else
1030 <<
1031 <%functionHead%>
1032 {
1033 throw std::runtime_error("Type <%type%> is unsupported for levelfix scheduling.");
1034 }
1035 >>
1036 end match
1037 case SOME((odeSchedule as THREADSCHEDULE(threadTasks=threadTasksOde), daeSchedule as THREADSCHEDULE(threadTasks=threadTasksDae), zeroFuncSchedule as THREADSCHEDULE(threadTasks=threadTasksZeroFunc))) then
1038 match type
1039 case ("openmp") then
1040 let threadAssignLocksOde = arrayList(threadTasksOde) |> tt hasindex i0 fromindex 0 => function_HPCOM_assignThreadLocks(arrayGet(threadTasksOde, intAdd(i0, 1)), "_lockOde", i0, type); separator="\n"
1041 let threadReleaseLocksOde = arrayList(threadTasksOde) |> tt hasindex i0 fromindex 0 => function_HPCOM_releaseThreadLocks(arrayGet(threadTasksOde, intAdd(i0, 1)), "_lockOde", i0, type); separator="\n"
1042 let threadAssignLocksDae = arrayList(threadTasksOde) |> tt hasindex i0 fromindex 0 => function_HPCOM_assignThreadLocks(arrayGet(threadTasksDae, intAdd(i0, 1)), "_lockDae", i0, type); separator="\n"
1043 let threadReleaseLocksDae = arrayList(threadTasksOde) |> tt hasindex i0 fromindex 0 => function_HPCOM_releaseThreadLocks(arrayGet(threadTasksDae, intAdd(i0, 1)), "_lockDae", i0, type); separator="\n"
1044 let threadAssignLocksZeroFunc = arrayList(threadTasksZeroFunc) |> tt hasindex i0 fromindex 0 => function_HPCOM_assignThreadLocks(arrayGet(threadTasksZeroFunc, intAdd(i0, 1)), "_lockZeroFunc", i0, type); separator="\n"
1045 let threadReleaseLocksZeroFunc = arrayList(threadTasksZeroFunc) |> tt hasindex i0 fromindex 0 => function_HPCOM_releaseThreadLocks(arrayGet(threadTasksZeroFunc, intAdd(i0, 1)), "_lockZeroFunc", i0, type); separator="\n"
1046
1047 let odeEqs = arrayList(threadTasksOde) |> tt hasindex i0 => parallelThreadCodeWithSplit(allEquationsPlusWhen,tt,i0,intSub(arrayLength(threadTasksOde),1),type,"_lockOde",&varDecls,simCode, extraFuncs, extraFuncsDecl, lastIdentOfPath(name), "evaluateODE", useFlatArrayNotation); separator="\n"
1048 let daeEqs = arrayList(threadTasksDae) |> tt hasindex i0 => parallelThreadCodeWithSplit(allEquationsPlusWhen,tt,i0,intSub(arrayLength(threadTasksDae),1),type,"_lockDae",&varDecls,simCode, extraFuncs, extraFuncsDecl, lastIdentOfPath(name), "evaluateAll", useFlatArrayNotation); separator="\n"
1049 let zeroFuncEqs = arrayList(threadTasksZeroFunc) |> tt hasindex i0 => parallelThreadCodeWithSplit(allEquationsPlusWhen,tt,i0,intSub(arrayLength(threadTasksZeroFunc),1),type,"_lockZeroFunc",&varDecls,simCode, extraFuncs, extraFuncsDecl, lastIdentOfPath(name), "evaluateZeroFunc", useFlatArrayNotation); separator="\n"
1050
1051 let &extraFuncsDecl +=
1052 <<
1053 void evaluateODE_Parallel();
1054 void evaluateAll_Parallel();
1055 void evaluateZeroFuncs_Parallel();
1056 >>
1057 <<
1058 void <%lastIdentOfPath(name)%>::evaluateODE_Parallel()
1059 {
1060 #pragma omp parallel num_threads(<%getConfigInt(NUM_PROC)%>)
1061 {
1062 int threadNum = getThreadNumber();
1063 <%threadAssignLocksOde%>
1064 #pragma omp barrier
1065 <%odeEqs%>
1066 #pragma omp barrier
1067 <%threadReleaseLocksOde%>
1068 }
1069 }
1070
1071 void <%lastIdentOfPath(name)%>::evaluateAll_Parallel()
1072 {
1073 #pragma omp parallel num_threads(<%getConfigInt(NUM_PROC)%>)
1074 {
1075 int threadNum = getThreadNumber();
1076 <%threadAssignLocksDae%>
1077 #pragma omp barrier
1078 <%daeEqs%>
1079 #pragma omp barrier
1080 <%threadReleaseLocksDae%>
1081 }
1082 }
1083
1084 void <%lastIdentOfPath(name)%>::evaluateZeroFuncs_Parallel()
1085 {
1086 #pragma omp parallel num_threads(<%getConfigInt(NUM_PROC)%>)
1087 {
1088 int threadNum = getThreadNumber();
1089 <%threadAssignLocksZeroFunc%>
1090 #pragma omp barrier
1091 <%zeroFuncEqs%>
1092 #pragma omp barrier
1093 <%threadReleaseLocksZeroFunc%>
1094 }
1095 }
1096
1097 <%functionHead%>
1098 {
1099 this->_evaluateMode = _evaluateMode;
1100 this->_command = command;
1101 if(evaluateMode == 0)
1102 {
1103 evaluateODE_Parallel();
1104 }
1105 else if(evaluateMode < 0)
1106 {
1107 evaluateAll_Parallel();
1108 }
1109 else
1110 {
1111 evaluateZeroFuncs_Parallel();
1112 }
1113 }
1114 >>
1115 case ("mpi") then
1116 <<
1117 <%functionHead%>
1118 {
1119 // MFlehmig: Todo
1120 }
1121 >>
1122 else
1123 let &mainThreadCode = buffer "" /*BUFD*/
1124 let threadFuncs = List.intRange(arrayLength(odeSchedule.threadTasks)) |> threadIdx => generateThreadFunc(allEquationsPlusWhen, arrayGet(odeSchedule.threadTasks, threadIdx), arrayGet(daeSchedule.threadTasks, threadIdx), arrayGet(zeroFuncSchedule.threadTasks, threadIdx), type, intSub(threadIdx, 1), modelNamePrefixStr, &varDecls, simCode, extraFuncs, extraFuncsDecl, lastIdentOfPath(name), &mainThreadCode, useFlatArrayNotation); separator="\n"
1125 let threadAssignLocks1 = listRest(arrayList(odeSchedule.threadTasks)) |> tt hasindex i0 fromindex 1 => assignLockByLockName(i0, "th_lock1", type); separator="\n"
1126 let threadReleaseLocks = listRest(arrayList(odeSchedule.threadTasks)) |> tt hasindex i0 fromindex 1 => releaseLockByLockName(i0, "th_lock", type); separator="\n"
1127 <<
1128 <%threadFuncs%>
1129
1130 <%functionHead%>
1131 {
1132 this->_evaluateMode = _evaluateMode;
1133 this->_command = command;
1134 <%threadReleaseLocks%>
1135 <%mainThreadCode%>
1136 <%threadAssignLocks1%>
1137 }
1138 >>
1139 end match
1140 case SOME((odeSchedule as TASKDEPSCHEDULE(__), daeSchedule as TASKDEPSCHEDULE(__), zeroFuncSchedule as TASKDEPSCHEDULE(__))) then
1141 match type
1142 case ("openmp") then
1143 let odeTaskEqs = function_HPCOM_TaskDep(odeSchedule.tasks, allEquationsPlusWhen, type, &varDecls, simCode, extraFuncs, extraFuncsDecl, extraFuncsNamespace, useFlatArrayNotation); separator="\n"
1144 let daeTaskEqs = function_HPCOM_TaskDep(daeSchedule.tasks, allEquationsPlusWhen, type, &varDecls, simCode, extraFuncs, extraFuncsDecl, extraFuncsNamespace, useFlatArrayNotation); separator="\n"
1145 let zeroFuncTaskEqs = function_HPCOM_TaskDep(zeroFuncSchedule.tasks, allEquationsPlusWhen, type, &varDecls, simCode, extraFuncs, extraFuncsDecl, extraFuncsNamespace, useFlatArrayNotation); separator="\n"
1146 <<
1147 <%functionHead%>
1148 {
1149 this->_evaluateMode = _evaluateMode;
1150 this->_command = command;
1151 <%&varDecls%>
1152 if(_evaluateMode == 0)
1153 {
1154 <%odeTaskEqs%>
1155 }
1156 else if(_evaluateMode < 0)
1157 {
1158 <%daeTaskEqs%>
1159 }
1160 else
1161 {
1162 <%zeroFuncTaskEqs%>
1163 }
1164 }
1165 >>
1166 case ("tbb") then
1167 let taskFuncs = function_HPCOM_TaskDep_voidfunc(odeSchedule.tasks, daeSchedule.tasks, zeroFuncSchedule.tasks, allEquationsPlusWhen,type, name, &varDecls, simCode, extraFuncs, extraFuncsDecl, extraFuncsNamespace, useFlatArrayNotation); separator="\n"
1168 <<
1169 //void functions for functionhandling in tbb_nodes
1170 <%taskFuncs%>
1171
1172 <%functionHead%>
1173 {
1174 this->_evaluateMode = _evaluateMode;
1175 this->_command = command;
1176 <%&varDecls%>
1177 if(_evaluateMode == 0)
1178 {
1179 #if TBB_INTERFACE_VERSION >= 8000
1180 _tbbArena.execute(_tbbArenaFunctorOde);
1181 #else
1182 _tbbStartNodeOde.try_put(tbb::flow::continue_msg());
1183 _tbbGraphOde.wait_for_all();
1184 #endif
1185 }
1186 else if(_evaluateMode < 0)
1187 {
1188 #if TBB_INTERFACE_VERSION >= 8000
1189 _tbbArena.execute(_tbbArenaFunctorAll);
1190 #else
1191 _tbbStartNodeAll.try_put(tbb::flow::continue_msg());
1192 _tbbGraphAll.wait_for_all();
1193 #endif
1194 }
1195 else
1196 {
1197 #if TBB_INTERFACE_VERSION >= 8000
1198 _tbbArena.execute(_tbbArenaFunctorZeroFunc);
1199 #else
1200 _tbbStartNodeZeroFunc.try_put(tbb::flow::continue_msg());
1201 _tbbGraphZeroFunc.wait_for_all();
1202 #endif
1203 }
1204 }
1205 >>
1206 else ""
1207 end match
1208 else ""
1209 end generateParallelEvaluate;
1210
1211 1 template generateStateVarPrefetchCode(SimCode simCode, Text& extraFuncs, Text& extraFuncsDecl, Text extraFuncsNamespace)
1212 ::=
1213 match simCode
1214 case SIMCODE(modelInfo = MODELINFO(vars = vars as SIMVARS(__))) then
1215 <<
1216 <%(List.intRange3(0, 8, intSub(listLength(vars.stateVars), 1)) |> index =>
1217 'PREFETCH(&__z[<%index%>], 0, 3);'
1218 ;separator="\n")%>
1219 >>
1220 else ''
1221 end match
1222 end generateStateVarPrefetchCode;
1223
1224 ✗ template generateLevelCodeForLevel(list<SimEqSystem> allEquationsPlusWhen, TaskList tasksOfLevel, String iType, Text &varDecls, SimCode simCode, Text& extraFuncs, Text& extraFuncsDecl, Text extraFuncsNamespace, Boolean useFlatArrayNotation)
1225 ::=
1226 match(tasksOfLevel)
1227 case(PARALLELTASKLIST(__)) then
1228 let odeEqs = tasks |> task => generateLevelCodeForTask(allEquationsPlusWhen,task,iType, &varDecls, simCode, extraFuncs, extraFuncsDecl, extraFuncsNamespace, useFlatArrayNotation); separator="\n"
1229 <<
1230 #pragma omp sections
1231 {
1232 <%odeEqs%>
1233 }
1234 >>
1235 case(SERIALTASKLIST(__)) then
1236 let odeEqs = tasks |> task => generateLevelCodeForTask(allEquationsPlusWhen,task,iType, &varDecls, simCode, extraFuncs, extraFuncsDecl, extraFuncsNamespace, useFlatArrayNotation); separator="\n"
1237 <<
1238 #pragma omp master
1239 {
1240 <%odeEqs%>
1241 }
1242 #pragma omp barrier
1243 >>
1244 else
1245 <<
1246 >>
1247 end match
1248 end generateLevelCodeForLevel;
1249
1250 ✗ template generateLevelCodeForTask(list<SimEqSystem> allEquationsPlusWhen, Task iTask, String iType, Text &varDecls, SimCode simCode, Text& extraFuncs, Text& extraFuncsDecl, Text extraFuncsNamespace, Boolean useFlatArrayNotation)
1251 ::=
1252 <<
1253 #pragma omp section
1254 {
1255 <%taskCode(allEquationsPlusWhen, iTask, iType, "", &varDecls, simCode, extraFuncs, extraFuncsDecl, extraFuncsNamespace, useFlatArrayNotation)%>
1256 }
1257 >>
1258 end generateLevelCodeForTask;
1259
1260 ✗ template generateLevelFixedCodeForLevel(list<SimEqSystem> allEquationsPlusWhen, array<list<HpcOmSimCode.Task>> tasksOfLevel, String iType, Text &varDecls, Absyn.Path name, SimCode simCode, Text& extraFuncs, Text& extraFuncsDecl, Text extraFuncsNamespace, Boolean useFlatArrayNotation)
1261 ::=
1262 let eqs = (arrayList(tasksOfLevel) |> threadTasks hasindex i0 =>
1263 <<
1264 if(threadNum == <%i0%>) {
1265 <%threadTasks |> t => taskCode(allEquationsPlusWhen, t, iType, "", varDecls, simCode, extraFuncs, extraFuncsDecl, extraFuncsNamespace, useFlatArrayNotation); separator="\n"%>
1266 }
1267 >>; separator="\n")
1268
1269 <<
1270 <%eqs%>
1271 #pragma omp barrier
1272 >>
1273 end generateLevelFixedCodeForLevel;
1274
1275 1 template generateLevelFixedCodeForThread(list<SimEqSystem> allEquationsPlusWhen, tuple<list<list<HpcOmSimCode.Task>>,list<list<HpcOmSimCode.Task>>,list<list<HpcOmSimCode.Task>>> tasksOfLevels,
1276 Integer iThreadIdx, String iType, Text &varDecls, Absyn.Path name, SimCode simCode, Text& extraFuncs, Text& extraFuncsDecl,
1277 Text extraFuncsNamespace, Boolean useFlatArrayNotation)
1278 ::=
1279 match iType
1280 case ("pthreads")
1281 case ("pthreads_spin") then
1282 match(tasksOfLevels)
1283 case((odeTasksOfLevel, daeTasksOfLevel, zeroFuncTasksOfLevel)) then
1284 let odeEqs = odeTasksOfLevel |> tasks hasindex levelIdx => generateLevelFixedCodeForThreadLevel(allEquationsPlusWhen, tasks, iThreadIdx, "evaluateODE", iType, levelIdx, &varDecls, simCode, extraFuncs, extraFuncsDecl, extraFuncsNamespace, useFlatArrayNotation); separator="\n"
1285 let daeEqs = daeTasksOfLevel |> tasks hasindex levelIdx => generateLevelFixedCodeForThreadLevel(allEquationsPlusWhen, tasks, iThreadIdx, "evaluateDAE", iType, levelIdx, &varDecls, simCode, extraFuncs, extraFuncsDecl, extraFuncsNamespace, useFlatArrayNotation); separator="\n"
1286 let zeroFuncEqs = zeroFuncTasksOfLevel |> tasks hasindex levelIdx => generateLevelFixedCodeForThreadLevel(allEquationsPlusWhen, tasks, iThreadIdx, "evaluateZeroFuncs", iType, levelIdx, &varDecls, simCode, extraFuncs, extraFuncsDecl, extraFuncsNamespace, useFlatArrayNotation); separator="\n"
1287 let &extraFuncsDecl +=
1288 <<
1289 void evaluateThreadFuncODE_<%iThreadIdx%>();
1290 void evaluateThreadFuncAll_<%iThreadIdx%>();
1291 void evaluateThreadFuncZeroFunc_<%iThreadIdx%>();
1292 void evaluateThreadFunc<%iThreadIdx%>();
1293 <%\n%>
1294 >>
1295 <<
1296 void <%lastIdentOfPath(name)%>::evaluateThreadFuncODE_<%iThreadIdx%>()
1297 {
1298 <%odeEqs%>
1299 }
1300
1301 void <%lastIdentOfPath(name)%>::evaluateThreadFuncAll_<%iThreadIdx%>()
1302 {
1303 <%daeEqs%>
1304 }
1305
1306 void <%lastIdentOfPath(name)%>::evaluateThreadFuncZeroFunc_<%iThreadIdx%>()
1307 {
1308 <%zeroFuncEqs%>
1309 }
1310
1311 <%if (intGt(iThreadIdx, 0)) then
1312 <<
1313 void <%lastIdentOfPath(name)%>::evaluateThreadFunc<%iThreadIdx%>()
1314 {
1315 <%if boolNot(stringEq(getConfigString(PROFILING_LEVEL),"none")) then
1316 <<
1317 MeasureTimeValues *valuesStart = MeasureTime::getZeroValues();
1318 MeasureTimeValues *valuesEnd = MeasureTime::getZeroValues();
1319 >>%>
1320
1321 while(!_simulationFinished)
1322 {
1323 //_evaluateBarrier.wait();
1324 _levelBarrier.wait();
1325 if(_simulationFinished)
1326 {
1327 //_evaluateBarrier.wait();
1328 _levelBarrier.wait();
1329 break;
1330 }
1331 <%if boolNot(stringEq(getConfigString(PROFILING_LEVEL),"none")) then '<%generateMeasureTimeStartCode("valuesStart", 'evaluateODEThread<%iThreadIdx%>', "MEASURETIME_MODELFUNCTIONS")%>'%>
1332 if(_evaluateMode == 0)
1333 {
1334 evaluateThreadFuncODE_<%iThreadIdx%>();
1335 <%if boolNot(stringEq(getConfigString(PROFILING_LEVEL),"none")) then
1336 <<
1337 <%generateMeasureTimeEndCode("valuesStart", "valuesEnd", '(*measureTimeThreadArrayOdeHpcom)[<%iThreadIdx%>]', 'evaluateODEThread<%iThreadIdx%>', "MEASURETIME_MODELFUNCTIONS")%>
1338 >>%>
1339 }
1340 else if(_evaluateMode < 0)
1341 {
1342 evaluateThreadFuncAll_<%iThreadIdx%>();
1343 <%if boolNot(stringEq(getConfigString(PROFILING_LEVEL),"none")) then
1344 <<
1345 <%generateMeasureTimeEndCode("valuesStart", "valuesEnd", '(*measureTimeThreadArrayDaeHpcom)[<%iThreadIdx%>]', 'evaluateDaeThread<%iThreadIdx%>', "MEASURETIME_MODELFUNCTIONS")%>
1346 >>%>
1347 }
1348 else
1349 {
1350 evaluateThreadFuncZeroFunc_<%iThreadIdx%>();
1351 <%if boolNot(stringEq(getConfigString(PROFILING_LEVEL),"none")) then
1352 <<
1353 <%generateMeasureTimeEndCode("valuesStart", "valuesEnd", '(*measureTimeThreadArrayZeroFuncHpcom)[<%iThreadIdx%>]', 'evaluateZeroFuncThread<%iThreadIdx%>', "MEASURETIME_MODELFUNCTIONS")%>
1354 >>%>
1355 }
1356
1357 //_evaluateBarrier.wait();
1358 _levelBarrier.wait();
1359 }
1360 <%if boolNot(stringEq(getConfigString(PROFILING_LEVEL),"none")) then
1361 <<
1362 delete valuesStart;
1363 delete valuesEnd;
1364 >>%>
1365 }
1366 >>
1367 %>
1368 >>
1369 else ""
1370 end generateLevelFixedCodeForThread;
1371
1372 7 template generateLevelFixedCodeForThreadLevel(list<SimEqSystem> allEquationsPlusWhen, list<HpcOmSimCode.Task> tasksOfLevel,
1373 Integer iThreadIdx, String functionName, String iType, Integer iLevelIdx, Text &varDecls, SimCode simCode, Text& extraFuncs, Text& extraFuncsDecl, Text extraFuncsNamespace, Boolean useFlatArrayNotation)
1374 ::=
1375 let tasks = tasksOfLevel |> t => taskCode(allEquationsPlusWhen, t, iType, "", varDecls, simCode, extraFuncs, extraFuncsDecl, extraFuncsNamespace, useFlatArrayNotation); separator="\n"
1376 <<
1377 //Start of Level <%iLevelIdx%>
1378 <%if intEq(iThreadIdx, 0) then
1379 <<
1380 <%generateMeasureTimeStartCode("measuredSchedulerStartValues", '<%functionName%>_level_<%intAdd(iLevelIdx,1)%>', "MEASURETIME_MODELFUNCTIONS")%>
1381 >>
1382 %>
1383
1384 <%if(stringEq(tasks,"")) then '' else ''%>
1385 <%tasks%>
1386 _levelBarrier.wait();
1387
1388 <%if intEq(iThreadIdx, 0) then
1389 <<
1390 <%generateMeasureTimeEndCode("measuredSchedulerStartValues", "measuredSchedulerEndValues", '(*measureTimeSchedulerArrayHpcom_<%functionName%>)[<%iLevelIdx%>]', '<%functionName%>_level_<%intAdd(iLevelIdx,1)%>', "MEASURETIME_MODELFUNCTIONS")%>
1391 >>
1392 %>
1393 //End of Level <%iLevelIdx%>
1394 >>
1395 end generateLevelFixedCodeForThreadLevel;
1396
1397 ✗ template function_HPCOM_TaskDep(list<tuple<Task,list<Integer>>> tasks, list<SimEqSystem> allEquationsPlusWhen, String iType,
1398 Text &varDecls, SimCode simCode, Text& extraFuncs, Text& extraFuncsDecl, Text extraFuncsNamespace, Boolean useFlatArrayNotation)
1399 ::=
1400 let odeEqs = tasks |> t => function_HPCOM_TaskDep0(t,allEquationsPlusWhen, iType, &varDecls, simCode, extraFuncs, extraFuncsDecl, extraFuncsNamespace, useFlatArrayNotation); separator="\n"
1401 <<
1402
1403 int t[0];
1404 #pragma omp parallel
1405 {
1406 #pragma omp master
1407 {
1408 <%odeEqs%>
1409 }
1410 }
1411 >>
1412 end function_HPCOM_TaskDep;
1413
1414 ✗ template function_HPCOM_TaskDep0(tuple<Task,list<Integer>> taskIn, list<SimEqSystem> allEquationsPlusWhen, String iType, Text &varDecls,
1415 SimCode simCode, Text& extraFuncs, Text& extraFuncsDecl, Text extraFuncsNamespace, Boolean useFlatArrayNotation)
1416 ::=
1417 match taskIn
1418 case ((task as CALCTASK(__),parents)) then
1419 let taskEqs = taskCode(allEquationsPlusWhen, task, iType, "", &varDecls, simCode, extraFuncs, extraFuncsDecl, extraFuncsNamespace,useFlatArrayNotation); separator="\n"
1420 let parentDependencies = parents |> p => 't[<%p%>]'; separator = ","
1421 let taskDependencies = parents |> p => '<%p%>'; separator = ","
1422 let depIn = if intGt(listLength(parents),0) then 'depend(in:<%parentDependencies%>) ' else ""
1423 <<
1424 //TG_NODE: <%task.index%> TG_PARENTS: <%taskDependencies%>
1425 #pragma omp task <%depIn%>depend(out:t[<%task.index%>])
1426 {
1427 <%taskEqs%>
1428 }
1429 >>
1430 end match
1431 end function_HPCOM_TaskDep0;
1432
1433 ✗ template generateTbbConstructorExtension(list<tuple<Task,list<Integer>>> odeTasks, list<tuple<Task,list<Integer>>> daeTasks, list<tuple<Task,list<Integer>>> zeroFuncTasks, String modelNamePrefixStr)
1434 ::=
1435 let odeNodes = odeTasks |> t hasindex i fromindex 0 => generateTbbConstructorExtensionNodes(t,i,"Ode",modelNamePrefixStr); separator="\n"
1436 let odeEdges = odeTasks |> t hasindex i fromindex 0 => generateTbbConstructorExtensionEdges(t,i,"Ode",modelNamePrefixStr); separator="\n"
1437 let daeNodes = daeTasks |> t hasindex i fromindex 0 => generateTbbConstructorExtensionNodes(t,i,"All",modelNamePrefixStr); separator="\n"
1438 let daeEdges = daeTasks |> t hasindex i fromindex 0 => generateTbbConstructorExtensionEdges(t,i,"All",modelNamePrefixStr); separator="\n"
1439 let zeroFuncNodes = zeroFuncTasks |> t hasindex i fromindex 0 => generateTbbConstructorExtensionNodes(t,i,"ZeroFunc",modelNamePrefixStr); separator="\n"
1440 let zeroFuncEdges = zeroFuncTasks |> t hasindex i fromindex 0 => generateTbbConstructorExtensionEdges(t,i,"ZeroFunc",modelNamePrefixStr); separator="\n"
1441 <<
1442 tbb::flow::continue_node<tbb::flow::continue_msg> *tbb_task;
1443 <%odeNodes%>
1444 <%odeEdges%>
1445 <%daeNodes%>
1446 <%daeEdges%>
1447 <%zeroFuncNodes%>
1448 <%zeroFuncEdges%>
1449 #if TBB_INTERFACE_VERSION >= 8000
1450 _tbbArena = tbb::task_arena(<%getConfigInt(NUM_PROC)%>);
1451 _tbbArenaFunctorOde = TbbArenaFunctor(_tbbGraphOde,_tbbStartNodeOde);
1452 _tbbArenaFunctorAll = TbbArenaFunctor(_tbbGraphAll,_tbbStartNodeAll);
1453 _tbbArenaFunctorZeroFunc = TbbArenaFunctor(_tbbGraphZeroFunc,_tbbStartNodeZeroFunc);
1454 #endif
1455 >>
1456 end generateTbbConstructorExtension;
1457
1458 ✗ template generateTbbConstructorExtensionNodes(tuple<Task,list<Integer>> taskIn, Integer taskIndex, String funcSuffix, String modelNamePrefixStr)
1459 ::=
1460 match taskIn
1461 case ((task as CALCTASK(__),parents)) then
1462 <<
1463 tbb_task = new tbb::flow::continue_node<tbb::flow::continue_msg>(_tbbGraph<%funcSuffix%>,VoidFunctionBody(bind<void>(&<%modelNamePrefixStr%>::taskFunc<%funcSuffix%>_<%task.index%>,this)));
1464 _tbbNodeList<%funcSuffix%>.at(<%taskIndex%>) = tbb_task;
1465 >>
1466 end match
1467 end generateTbbConstructorExtensionNodes;
1468
1469 ✗ template generateTbbConstructorExtensionEdges(tuple<Task,list<Integer>> taskIn, Integer taskIndex, String funcSuffix, String modelNamePrefixStr)
1470 ::=
1471 match taskIn
1472 case ((task as CALCTASK(__),parents)) then
1473 let parentEdges = parents |> p => 'tbb::flow::make_edge(*(_tbbNodeList<%funcSuffix%>.at(<%intSub(p,1)%>)),*(_tbbNodeList<%funcSuffix%>.at(<%taskIndex%>)));'; separator = "\n"
1474 let startNodeEdge = if intEq(0, listLength(parents)) then 'tbb::flow::make_edge(_tbbStartNode<%funcSuffix%>,*(_tbbNodeList<%funcSuffix%>.at(<%taskIndex%>)));' else ""
1475 <<
1476 <%parentEdges%>
1477 <%startNodeEdge%>
1478 >>
1479 end match
1480 end generateTbbConstructorExtensionEdges;
1481
1482 ✗ template function_HPCOM_TaskDep_voidfunc(list<tuple<Task,list<Integer>>> odeTasks, list<tuple<Task,list<Integer>>> daeTasks, list<tuple<Task,list<Integer>>> zeroFuncTasks, list<SimEqSystem> allEquationsPlusWhen,
1483 String iType, Absyn.Path name, Text &varDecls, SimCode simCode, Text& extraFuncs, Text& extraFuncsDecl, Text extraFuncsNamespace, Boolean useFlatArrayNotation)
1484 ::=
1485 let funcTasksOde = odeTasks |> t => function_HPCOM_TaskDep_voidfunc0(t,allEquationsPlusWhen,iType, "Ode", name, &varDecls, simCode, extraFuncs, extraFuncsDecl, extraFuncsNamespace, useFlatArrayNotation); separator="\n"
1486 let funcTasksDae = daeTasks |> t => function_HPCOM_TaskDep_voidfunc0(t,allEquationsPlusWhen,iType, "All", name, &varDecls, simCode, extraFuncs, extraFuncsDecl, extraFuncsNamespace, useFlatArrayNotation); separator="\n"
1487 let funcTasksZeroFunc = zeroFuncTasks |> t => function_HPCOM_TaskDep_voidfunc0(t,allEquationsPlusWhen,iType, "ZeroFunc", name, &varDecls, simCode, extraFuncs, extraFuncsDecl, extraFuncsNamespace, useFlatArrayNotation); separator="\n"
1488 <<
1489 <%funcTasksOde%>
1490 <%funcTasksDae%>
1491 <%funcTasksZeroFunc%>
1492 >>
1493 end function_HPCOM_TaskDep_voidfunc;
1494
1495 ✗ template function_HPCOM_TaskDep_voidfunc0(tuple<Task,list<Integer>> taskIn, list<SimEqSystem> allEquationsPlusWhen, String iType, String funcSuffix, Absyn.Path name, Text &varDecls, SimCode simCode, Text& extraFuncs, Text& extraFuncsDecl, Text extraFuncsNamespace, Boolean useFlatArrayNotation)
1496 ::=
1497 match taskIn
1498 case ((task as CALCTASK(__),parents)) then
1499 let &tempvarDecl = buffer "" /*BUFD*/
1500 let taskEqs = taskCode(allEquationsPlusWhen, task, iType, "", &tempvarDecl, simCode, extraFuncs, extraFuncsDecl, extraFuncsNamespace,useFlatArrayNotation); separator="\n"
1501 <<
1502 void <%lastIdentOfPath(name)%>::taskFunc<%funcSuffix%>_<%task.index%>()
1503 {
1504 <%tempvarDecl%>
1505 <%taskEqs%>
1506 }
1507 >>
1508 end match
1509 end function_HPCOM_TaskDep_voidfunc0;
1510
1511 /*
1512 template function_HPCOM_Thread(list<SimEqSystem> allEquationsPlusWhen, array<list<Task>> threadTasksOde, array<list<Task>> threadTasksDae, array<list<Task>> threadTasksZeroFunc, String iType,Text &varDecls, SimCode simCode, Text& extraFuncs, Text& extraFuncsDecl, Text extraFuncsNamespace, Boolean useFlatArrayNotation)
1513 ::=
1514 let odeEqs = arrayList(threadTasksOde) |> tt hasindex i0 => parallelThreadCodeWithSplit(allEquationsPlusWhen,tt,i0,iType,"_lockOde",&varDecls,simCode, extraFuncs, extraFuncsDecl, extraFuncsNamespace, "evaluateODE", useFlatArrayNotation); separator="\n"
1515 let daeEqs = arrayList(threadTasksDae) |> tt hasindex i0 => parallelThreadCodeWithSplit(allEquationsPlusWhen,tt,i0,iType,"_lockDae",&varDecls,simCode, extraFuncs, extraFuncsDecl, extraFuncsNamespace, "evaluateAll", useFlatArrayNotation); separator="\n"
1516 let zeroFuncEqs = arrayList(threadTasksDae) |> tt hasindex i0 => parallelThreadCodeWithSplit(allEquationsPlusWhen,tt,i0,iType,"_lockZeroFunc",&varDecls,simCode, extraFuncs, extraFuncsDecl, extraFuncsNamespace, "evaluateZeroFunc", useFlatArrayNotation); separator="\n"
1517 match iType
1518 case ("mpi") then
1519 <<
1520 int world_rank;
1521 MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
1522 if(_evaluateMode == 0)
1523 {
1524 <%odeEqs%>
1525 }
1526 else if(_evaluateMode < 0)
1527 {
1528 <%daeEqs%>
1529 }
1530 else
1531 {
1532 <%zeroFuncEqs%>
1533 }
1534 >>
1535 else
1536 <<
1537 if(_evaluateMode == 0)
1538 {
1539 <%generateMeasureTimeStartCode("measuredSchedulerStartValues", "evaluateODE_threads", "MEASURETIME_MODELFUNCTIONS")%>
1540 <%odeEqs%>
1541 <%generateMeasureTimeEndCode("measuredSchedulerStartValues", "measuredSchedulerEndValues", "(*measureTimeThreadArrayOdeHpcom)[threadNum]", "evaluateODE_threads", "MEASURETIME_MODELFUNCTIONS")%>
1542 }
1543 else if(_evaluateMode < 0)
1544 {
1545 <%generateMeasureTimeStartCode("measuredSchedulerStartValues", "evaluateDAE_threads", "MEASURETIME_MODELFUNCTIONS")%>
1546 <%daeEqs%>
1547 <%generateMeasureTimeEndCode("measuredSchedulerStartValues", "measuredSchedulerEndValues", "(*measureTimeThreadArrayDaeHpcom)[threadNum]", "evaluateDAE_threads", "MEASURETIME_MODELFUNCTIONS")%>
1548 }
1549 else
1550 {
1551 <%generateMeasureTimeStartCode("measuredSchedulerStartValues", "evaluateZeroFunc_threads", "MEASURETIME_MODELFUNCTIONS")%>
1552 <%zeroFuncEqs%>
1553 <%generateMeasureTimeEndCode("measuredSchedulerStartValues", "measuredSchedulerEndValues", "(*measureTimeThreadArrayZeroFuncHpcom)[threadNum]", "evaluateZeroFunc_threads", "MEASURETIME_MODELFUNCTIONS")%>
1554 }
1555 >>
1556 end match
1557 end function_HPCOM_Thread;
1558 */
1559 ✗ template generateThreadFunc(list<SimEqSystem> allEquationsPlusWhen, list<Task> threadTasksOde, list<Task> threadTasksDae, list<Task> threadTasksZeroFunc, String iType, Integer iThreadIdx, String modelNamePrefixStr, Text &varDecls, SimCode simCode, Text& extraFuncs, Text& extraFuncsDecl, Text extraFuncsNamespace, Text& mainThreadCode, Boolean useFlatArrayNotation)
1560 ::=
1561 let &varDeclsLoc = buffer "" /*BUFD*/
1562 let taskEqsOde = parallelThreadCode(allEquationsPlusWhen, threadTasksOde, iThreadIdx, iType, "_lockOde", &varDeclsLoc, simCode, extraFuncs, extraFuncsDecl, extraFuncsNamespace, "evaluateODE", useFlatArrayNotation); separator="\n"
1563 let taskEqsDae = parallelThreadCode(allEquationsPlusWhen, threadTasksDae, iThreadIdx, iType, "_lockDae", &varDeclsLoc, simCode, extraFuncs, extraFuncsDecl, extraFuncsNamespace, "evaluateAll", useFlatArrayNotation); separator="\n"
1564 let taskEqsZeroFunc = parallelThreadCode(allEquationsPlusWhen, threadTasksZeroFunc, iThreadIdx, iType, "_lockZeroFunc", &varDeclsLoc, simCode, extraFuncs, extraFuncsDecl, extraFuncsNamespace, "evaluateZeroFunc", useFlatArrayNotation); separator="\n"
1565 let assLock = assignLockByLockName(iThreadIdx, "th_lock", iType); separator="\n"
1566 let relLock = releaseLockByLockName(iThreadIdx, "th_lock1", iType); separator="\n"
1567 let &extraFuncsDecl +=
1568 <<
1569 void evaluateThreadFuncODE_<%iThreadIdx%>();
1570 void evaluateThreadFuncAll_<%iThreadIdx%>();
1571 void evaluateThreadFuncZeroFunc_<%iThreadIdx%>();
1572 >>
1573
1574 if (intGt(iThreadIdx, 0)) then
1575 <<
1576 void <%modelNamePrefixStr%>::evaluateThreadFuncODE_<%iThreadIdx%>()
1577 {
1578 <%taskEqsOde%>
1579 }
1580
1581 void <%modelNamePrefixStr%>::evaluateThreadFuncAll_<%iThreadIdx%>()
1582 {
1583 <%taskEqsDae%>
1584 }
1585
1586 void <%modelNamePrefixStr%>::evaluateThreadFuncZeroFunc_<%iThreadIdx%>()
1587 {
1588 <%taskEqsZeroFunc%>
1589 }
1590
1591 void <%modelNamePrefixStr%>::evaluateThreadFunc<%iThreadIdx%>()
1592 {
1593 #ifdef MEASURETIME_MODELFUNCTIONS
1594 MeasureTimeValues *measuredSchedulerStartValues = measuredSchedulerStartValues_<%intSub(iThreadIdx,1)%>;
1595 MeasureTimeValues *measuredSchedulerEndValues = measuredSchedulerEndValues_<%intSub(iThreadIdx,1)%>;
1596 #endif //MEASURETIME_MODELFUNCTIONS
1597 <%&varDeclsLoc%>
1598 while(1)
1599 {
1600 <%assLock%>
1601 if(_terminateThreads)
1602 return;
1603
1604 if(_evaluateMode == 0)
1605 {
1606 evaluateThreadFuncODE_<%iThreadIdx%>();
1607 }
1608 else if(_evaluateMode < 0)
1609 {
1610 evaluateThreadFuncAll_<%iThreadIdx%>();
1611 }
1612 else
1613 {
1614 evaluateThreadFuncZeroFunc_<%iThreadIdx%>();
1615 }
1616 <%relLock%>
1617 }
1618 }
1619 >>
1620 else
1621 let &mainThreadCode += &varDeclsLoc
1622 let &mainThreadCode +=
1623 <<
1624 #ifdef MEASURETIME_MODELFUNCTIONS
1625 MeasureTimeValues *measuredSchedulerStartValues = measuredSchedulerStartValues_0;
1626 MeasureTimeValues *measuredSchedulerEndValues = measuredSchedulerEndValues_0;
1627 #endif //MEASURETIME_MODELFUNCTIONS
1628 if(_evaluateMode == 0)
1629 {
1630 evaluateThreadFuncODE_<%iThreadIdx%>();
1631 }
1632 else if(_evaluateMode < 0)
1633 {
1634 evaluateThreadFuncAll_<%iThreadIdx%>();
1635 }
1636 else
1637 {
1638 evaluateThreadFuncZeroFunc_<%iThreadIdx%>();
1639 }
1640 >>
1641 <<
1642 void <%modelNamePrefixStr%>::evaluateThreadFuncODE_<%iThreadIdx%>()
1643 {
1644 <%taskEqsOde%>
1645 }
1646
1647 void <%modelNamePrefixStr%>::evaluateThreadFuncAll_<%iThreadIdx%>()
1648 {
1649 <%taskEqsDae%>
1650 }
1651
1652 void <%modelNamePrefixStr%>::evaluateThreadFuncZeroFunc_<%iThreadIdx%>()
1653 {
1654 <%taskEqsZeroFunc%>
1655 }
1656 >>
1657 end generateThreadFunc;
1658
1659 ✗ template function_HPCOM_assignThreadLocks(list<Task> iThreadTasks, String iLockPrefix, Integer iThreadNum, String iType)
1660 ::=
1661 let lockAssign = iThreadTasks |> tt => '<%(
1662 match(tt)
1663 case(task as DEPTASK(outgoing=true)) then
1664 assignLockByDepTask(task, iLockPrefix, iType)
1665 else ""
1666 end match)%>'; separator="\n"
1667 <<
1668 <%if intNe(iThreadNum, 0) then 'else ' else ''%>if(threadNum == <%iThreadNum%>)
1669 {
1670 <%lockAssign%>
1671 }
1672 >>
1673 end function_HPCOM_assignThreadLocks;
1674
1675 ✗ template function_HPCOM_releaseThreadLocks(list<Task> iThreadTasks, String iLockPrefix, Integer iThreadNum, String iType)
1676 ::=
1677 let lockAssign = iThreadTasks |> tt => '<%(
1678 match(tt)
1679 case(DEPTASK(outgoing=false)) then
1680 releaseLockByDepTask(tt, iLockPrefix, iType)
1681 else ""
1682 end match)%>'; separator="\n"
1683 <<
1684 <%if intNe(iThreadNum, 0) then 'else ' else ''%>if(threadNum == <%iThreadNum%>)
1685 {
1686 <%lockAssign%>
1687 }
1688 >>
1689 end function_HPCOM_releaseThreadLocks;
1690
1691 ✗ template parallelThreadCodeWithSplit(list<SimEqSystem> allEquationsPlusWhen, list<Task> threadTaskList, Integer iThreadNum, Integer iMaxThreadNumber,
1692 String iType, String lockPrefix, Text &varDecls, SimCode simCode, Text& extraFuncs, Text& extraFuncsDecl,
1693 Text extraFuncsNamespace, String extraFunctionName, Boolean useFlatArrayNotation)
1694 ::=
1695 let functionCalls = List.partition(threadTaskList, 100) |> tt hasindex i0 => parallelThreadCode(allEquationsPlusWhen,tt,i0,iType,lockPrefix,&varDecls,simCode, extraFuncs, extraFuncsDecl, extraFuncsNamespace, '<%extraFunctionName%>_Th<%iThreadNum%>', useFlatArrayNotation); separator="\n"
1696 match iType
1697 case ("openmp") then
1698 <<
1699 <%if intEq(iThreadNum, 0) then 'switch(threadNum) <%\n%>{<%\n%>' else '' %>case <%iThreadNum%>:
1700 <%functionCalls%>
1701 break;
1702 <%if intEq(iThreadNum, iMaxThreadNumber) then '<%\n%>}' else ''%>
1703 >>
1704 case ("mpi") then
1705 <<
1706 if (world_rank == <%iThreadNum%>)
1707 {
1708 <%functionCalls%>
1709 }
1710 >>
1711 else
1712 <<
1713 <%functionCalls%>
1714 >>
1715 end match
1716 end parallelThreadCodeWithSplit;
1717
1718 ✗ template parallelThreadCode(list<SimEqSystem> allEquationsPlusWhen, list<Task> threadTaskList, Integer iPartitionIndex,
1719 String iType, String lockPrefix, Text &varDecls, SimCode simCode, Text& extraFuncs, Text& extraFuncsDecl, Text extraFuncsNamespace, String extraFunctionName, Boolean useFlatArrayNotation)
1720 ::=
1721 let threadTasks = threadTaskList |> tt => taskCode(allEquationsPlusWhen,tt,iType,lockPrefix,&varDecls,simCode, extraFuncs, extraFuncsDecl, extraFuncsNamespace,useFlatArrayNotation); separator="\n"
1722 let &extraFuncs +=
1723 <<
1724 void <%extraFuncsNamespace%>::<%extraFunctionName%>_<%iPartitionIndex%>()
1725 {
1726 <%threadTasks%>
1727 }<%\n%><%\n%>
1728 >>
1729 let &extraFuncsDecl += 'void <%extraFunctionName%>_<%iPartitionIndex%>();'
1730
1731 <<
1732 <%extraFunctionName%>_<%iPartitionIndex%>();
1733 >>
1734 end parallelThreadCode;
1735
1736 102 template taskCode(list<SimEqSystem> allEquationsPlusWhen, Task iTask, String iType, String lockPrefix, Text &varDecls,
1737 SimCode simCode, Text& extraFuncs, Text& extraFuncsDecl, Text extraFuncsNamespace, Boolean useFlatArrayNotation)
1738 ::=
1739 match iTask
1740 case (task as CALCTASK(__)) then
1741 let odeEqs = task.eqIdc |> eq => equationNamesHPCOM_(eq,allEquationsPlusWhen,contextSimulationNonDiscrete,&varDecls, simCode, extraFuncs, extraFuncsDecl, extraFuncsNamespace, useFlatArrayNotation); separator="\n"
1742 let &varDeclsLocal = buffer "" /*BUFL*/
1743 <<
1744 // Task <%task.index%>
1745 <%odeEqs%>
1746 // End Task <%task.index%>
1747 >>
1748 case (task as CALCTASK_LEVEL(__)) then
1749 let odeEqs = task.eqIdc |> eq => equationNamesHPCOM_(eq,allEquationsPlusWhen,contextSimulationNonDiscrete,&varDecls, simCode, extraFuncs, extraFuncsDecl, extraFuncsNamespace, useFlatArrayNotation); separator="\n"
1750 let taskStr = task.nodeIdc |> task => '<%task%>';separator=","
1751 let &varDeclsLocal = buffer "" /*BUFL*/
1752 <<
1753 // Tasks <%taskStr%>
1754 <%odeEqs%>
1755 >>
1756 case(task as DEPTASK(outgoing=false)) then
1757 let assLck = assignLockByDepTask(task, lockPrefix, iType); separator="\n"
1758 <<
1759 <%assLck%>
1760 >>
1761 case(task as DEPTASK(outgoing=true)) then
1762 let relLck = releaseLockByDepTask(task, lockPrefix, iType); separator="\n"
1763 <<
1764 <%relLck%>
1765 >>
1766 end match
1767 end taskCode;
1768
1769 171 template equationNamesHPCOM_(Integer idx, list<SimEqSystem> allEquationsPlusWhen, Context context, Text &varDecls, SimCode simCode, Text& extraFuncs, Text& extraFuncsDecl, Text extraFuncsNamespace, Boolean useFlatArrayNotation)
1770 ::=
1771 let eq = equationHPCOM_(getSimCodeEqByIndex(allEquationsPlusWhen, idx), idx, context, &varDecls, simCode, extraFuncs, extraFuncsDecl, extraFuncsNamespace, useFlatArrayNotation)
1772 <<
1773 <%eq%>
1774 >>
1775 end equationNamesHPCOM_;
1776
1777 171 template equationHPCOM_(SimEqSystem eq, Integer idx, Context context, Text &varDecls, SimCode simCode, Text& extraFuncs, Text& extraFuncsDecl, Text extraFuncsNamespace, Boolean useFlatArrayNotation)
1778 ::=
1779 equation_function_call(eq, context, simCode, "evaluate")
1780 end equationHPCOM_;
1781
1782 ✗ template function_HPCOM_joinThread(String threadIdx, String iType)
1783 ::=
1784 match iType
1785 case ("openmp") then
1786 <<
1787 >>
1788 else
1789 <<
1790 evaluateThread<%threadIdx%>->join();
1791 >>
1792 end match
1793 end function_HPCOM_joinThread;
1794
1795 ✗ template function_HPCOM_destroyThread(String threadIdx, String iType)
1796 ::=
1797 match iType
1798 case ("openmp") then
1799 <<
1800 >>
1801 else
1802 <<
1803 delete evaluateThread<%threadIdx%>;
1804 >>
1805 end match
1806 end function_HPCOM_destroyThread;
1807
1808 ✗ template generateThread(Integer threadIdx, String iType, String modelNamePrefixStr, String funcName)
1809 ::=
1810 match iType
1811 case ("openmp") then
1812 <<
1813 >>
1814 else
1815 <<
1816 evaluateThread<%threadIdx%> = new thread(bind(&<%modelNamePrefixStr%>::<%funcName%><%threadIdx%>, this));
1817 >>
1818 end match
1819 end generateThread;
1820
1821 ✗ template getLockNameByDepTask(Task depTask)
1822 ::=
1823 match depTask
1824 case(task as DEPTASK(__)) then
1825 '[<%task.id%>]'
1826 else
1827 'invalidLockTask'
1828 end match
1829 end getLockNameByDepTask;
1830
1831 ✗ template initializeLockByDepTask(Task depTask, String lockPrefix, String iType)
1832 ::=
1833 let lockName = getLockNameByDepTask(depTask)
1834 <<
1835 <%initializeLockByLockName(lockName, lockPrefix, iType)%>
1836 >>
1837 end initializeLockByDepTask;
1838
1839 ✗ template initializeLockByLockName(String lockName, String lockPrefix, String iType)
1840 ::=
1841 match iType
1842 case ("openmp") then
1843 <<
1844 omp_init_lock(&<%lockPrefix%>_<%lockName%>);
1845 >>
1846 case ("pthreads") then
1847 <<
1848 <%lockPrefix%>_<%lockName%> = new alignedLock();
1849 >>
1850 case ("pthreads_spin") then
1851 <<
1852 <%lockPrefix%>_<%lockName%> = new alignedSpinlock();
1853 >>
1854 end match
1855 end initializeLockByLockName;
1856
1857 1 template initializeBarrierByName(String lockName, String lockPrefix, Integer numberOfThreads, String iType)
1858 ::=
1859 match iType
1860 case ("pthreads")
1861 case ("pthreads_spin") then
1862 <<
1863 <%lockPrefix%>_<%lockName%>(<%numberOfThreads%>)
1864 >>
1865 end match
1866 end initializeBarrierByName;
1867
1868 ✗ template createLockByDepTask(Task depTask, String lockPrefix, String iType)
1869 ::=
1870 let lockName = getLockNameByDepTask(depTask)
1871 <<
1872 <%createLockByLockName(lockName, lockPrefix, iType)%>
1873 >>
1874 end createLockByDepTask;
1875
1876 2 template createLockByLockName(String lockName, String lockPrefix, String iType)
1877 ::=
1878 match iType
1879 case ("openmp") then
1880 <<
1881 omp_lock_t <%lockPrefix%>_<%lockName%>;
1882 >>
1883 case ("pthreads") then
1884 <<
1885 alignedLock* <%lockPrefix%>_<%lockName%>;
1886 >>
1887 case ("pthreads_spin") then
1888 <<
1889 alignedSpinlock* <%lockPrefix%>_<%lockName%>;
1890 >>
1891 end match
1892 end createLockByLockName;
1893
1894 1 template createBarrierByName(String lockName, String lockPrefix, Integer numOfThreads, String iType)
1895 ::=
1896 match iType
1897 case ("pthreads")
1898 case ("pthreads_spin") then
1899 <<
1900 busywaiting_barrier <%lockPrefix%>_<%lockName%>;
1901 >>
1902 end match
1903 end createBarrierByName;
1904
1905 ✗ template destroyLockByDepTask(Task depTask, String lockPrefix, String iType)
1906 ::=
1907 let lockName = getLockNameByDepTask(depTask)
1908 <<
1909 <%destroyLockByLockName(lockName, lockPrefix, iType)%>
1910 >>
1911 end destroyLockByDepTask;
1912
1913 ✗ template destroyLockByLockName(String lockName, String lockPrefix, String iType)
1914 ::=
1915 match iType
1916 case ("openmp") then
1917 <<
1918 omp_destroy_lock(&<%lockPrefix%>_<%lockName%>);
1919 >>
1920 case ("pthreads")
1921 case ("pthreads_spin") then
1922 <<
1923 delete <%lockPrefix%>_<%lockName%>;
1924 >>
1925 else
1926 <<
1927 >>
1928 end match
1929 end destroyLockByLockName;
1930
1931 ✗ template assignLockByDepTask(Task depTask, String lockPrefix, String iType)
1932 ::=
1933 match(depTask)
1934 case(DEPTASK(__)) then
1935 let lockName = getLockNameByDepTask(depTask)
1936 //let commInfoStr = printCommunicationInfoVariables(depTask.communicationInfo)
1937 <<
1938 <%assignLockByLockName(lockName, lockPrefix, iType)%>
1939 >>
1940 end match
1941 end assignLockByDepTask;
1942
1943 ✗ template printCommunicationInfoVariables(CommunicationInfo commInfo)
1944 ::=
1945 ""
1946 /*
1947 match(commInfo)
1948 case(COMMUNICATION_INFO(__)) then
1949 let floatVarsStr = floatVars |> v => '<%CodegenCpp.MemberVariableDefine2(v, "", false, true)%>' ;separator="\n"
1950 let intVarsStr = intVars |> v => '<%CodegenCpp.MemberVariableDefine2(v, "", false, true)%>' ;separator="\n"
1951 let boolVarsStr = boolVars |> v => '<%CodegenCpp.MemberVariableDefine2(v, "", false, true)%>' ;separator="\n"
1952 <<
1953 <%floatVarsStr%>
1954 >>
1955 else
1956 <<
1957 //unsupported communcation info
1958 >>
1959 end match
1960 */
1961 end printCommunicationInfoVariables;
1962
1963 ✗ template assignLockByLockName(String lockName, String lockPrefix, String iType)
1964 ::=
1965 match iType
1966 case ("openmp") then
1967 <<
1968 omp_set_lock(&<%lockPrefix%>_<%lockName%>);
1969 >>
1970 case ("pthreads")
1971 case ("pthreads_spin") then
1972 <<
1973 <%lockPrefix%>_<%lockName%>->lock();
1974 >>
1975 end match
1976 end assignLockByLockName;
1977
1978 ✗ template releaseLockByDepTask(Task depTask, String lockPrefix, String iType)
1979 ::=
1980 let lockName = getLockNameByDepTask(depTask)
1981 <<
1982 <%releaseLockByLockName(lockName, lockPrefix, iType)%>
1983 >>
1984 end releaseLockByDepTask;
1985
1986
1987 ✗ template releaseLockByLockName(String lockName, String lockPrefix, String iType)
1988 ::=
1989 match iType
1990 case ("openmp") then
1991 <<
1992 omp_unset_lock(&<%lockPrefix%>_<%lockName%>);
1993 >>
1994 case ("pthreads") then
1995 <<
1996 <%lockPrefix%>_<%lockName%>->unlock();
1997 >>
1998 case ("pthreads_spin") then
1999 <<
2000 <%lockPrefix%>_<%lockName%>->unlock();
2001 >>
2002 end match
2003 end releaseLockByLockName;
2004
2005
2006 ✗ template mpiFinalize()
2007 "Finalize the MPI environment in main function."
2008 ::=
2009 <<
2010 } // End sequential
2011 MPI_Finalize();
2012 >>
2013 end mpiFinalize;
2014
2015 ✗ template mpiInit()
2016 "Initialize the MPI environment in main function."
2017 ::=
2018 <<
2019 char** argvNotConst = const_cast<char**>(argv);
2020 MPI_Init(&argc, &argvNotConst);
2021 int world_rank, world_size;
2022 MPI_Comm_size(MPI_COMM_WORLD, &world_size);
2023 MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
2024 std::cout << "Hello world! This is MPI process " << world_rank
2025 << " of " << world_size << " processes." << endl;
2026
2027 // Run simulation in sequential
2028 if (0 == world_rank) {
2029 std::cout << "Remark: Simulation is not (yet) MPI parallel!\n";
2030 >>
2031 end mpiInit;
2032
2033 1 template mpiRunCommandInRunScript(String type, Text &getNumOfProcs, Text &execCommandLinux)
2034 "If MPI is used:
2035 - Add the run execution command 'mpirun -np $NPROCESSORS',
2036 - number of MPI processors can be passed as command line argument to simulation
2037 run script."
2038 ::=
2039 match type
2040 case "mpi" then
2041 let &execCommandLinux += "mpirun -np ${NPROCESSORS}"
2042 let &getNumOfProcs += "\nif [ $# -gt 0 ]; then\n NPROCESSORS=$1\n shift \nelse\n NPROCESSORS=1\nfi\n\n"
2043 ""
2044 else
2045 let &execCommandLinux += "exec"
2046 ""
2047 end match
2048 end mpiRunCommandInRunScript;
2049
2050 1 template simulationMainRunScript(SimCode simCode, Text& extraFuncs, Text& extraFuncsDecl, Text extraFuncsNamespace)
2051 "Generates code for header file for simulation target."
2052 ::=
2053 let type = if Flags.isSet(Flags.USEMPI) then "mpi" else ''
2054 let &preRunCommandLinux = buffer ""
2055 let &execCommandLinux = buffer ""
2056 let _ = mpiRunCommandInRunScript(type, &preRunCommandLinux, &execCommandLinux)
2057 let preRunCommandWindows = ""
2058
2059 CodegenCpp.simulationMainRunScript(simCode, extraFuncs, extraFuncsDecl, extraFuncsNamespace, preRunCommandLinux, preRunCommandWindows, execCommandLinux)
2060 end simulationMainRunScript;
2061
2062 1 template getAdditionalMakefileFlags(Text& additionalLinkerFlags_GCC, Text& additionalLinkerFlags_MSVC, Text& additionalCFlags_GCC, Text& additionalCFlags_MSVC)
2063 ::=
2064 let type = getConfigString(HPCOM_CODE)
2065
2066 let &additionalCFlags_GCC += if stringEq(type,"openmp") then " -fopenmp" else ""
2067 let &additionalCFlags_GCC += if stringEq(type,"tbb") then ' -I"$(INTEL_TBB_INCLUDE)"' else ""
2068
2069 let &additionalCFlags_MSVC += if stringEq(type,"openmp") then "/openmp" else ""
2070
2071 let &additionalLinkerFlags_GCC += if stringEq(type,"tbb") then "-L$(INTEL_TBB_LIBS) $(INTEL_TBB_LIBRARIES) " else ""
2072 let &additionalLinkerFlags_GCC += if stringEq(type,"openmp") then " -fopenmp" else ""
2073 <<
2074 >>
2075 end getAdditionalMakefileFlags;
2076
2077 1 template simulationMakefile(String target, SimCode simCode, Text& extraFuncs, Text& extraFuncsDecl, Text extraFuncsNamespace)
2078 "Adds specific compiler flags for HPCOM mode to simulation makefile."
2079 ::=
2080 let &additionalCFlags_GCC = buffer ""
2081 let &additionalCFlags_MSVC = buffer ""
2082 let &additionalLinkerFlags_GCC = buffer ""
2083 let &additionalLinkerFlags_MSVC = buffer ""
2084
2085 <<
2086 <%getAdditionalMakefileFlags(additionalLinkerFlags_GCC, additionalLinkerFlags_MSVC, additionalCFlags_GCC, additionalCFlags_MSVC)%>
2087 <%CodegenCpp.simulationMakefile(target, simCode, extraFuncs ,extraFuncsDecl, extraFuncsNamespace, additionalLinkerFlags_GCC,
2088 additionalLinkerFlags_MSVC, additionalCFlags_GCC, additionalCFlags_MSVC,
2089 Flags.isSet(Flags.USEMPI))%>
2090 >>
2091 end simulationMakefile;
2092
2093 1 template numPreVarsHpcom(ModelInfo modelInfo, Option<MemoryMap> hpcOmMemoryOpt)
2094 ::=
2095 match(hpcOmMemoryOpt)
2096 case(SOME(hpcomMemory as MEMORYMAP_ARRAY(floatArraySize=floatArraySize,intArraySize=intArraySize,boolArraySize=boolArraySize))) then
2097 '<%floatArraySize%> + <%intArraySize%> + <%boolArraySize%>'
2098 else
2099 CodegenCpp.getPreVarsCount(modelInfo)
2100 end numPreVarsHpcom;
2101
2102 1 template numRealvarsHpcom(ModelInfo modelInfo, Option<MemoryMap> hpcOmMemoryOpt)
2103 ::=
2104 match(hpcOmMemoryOpt)
2105 case(SOME(hpcomMemory as MEMORYMAP_ARRAY(floatArraySize=floatArraySize))) then
2106 '<%floatArraySize%>'
2107 else
2108 '<%CodegenCpp.numRealvars(modelInfo)%>'
2109 end numRealvarsHpcom;
2110
2111 1 template numIntvarsHpcom(ModelInfo modelInfo, Option<MemoryMap> hpcOmMemoryOpt)
2112 ::=
2113 match(hpcOmMemoryOpt)
2114 case(SOME(hpcomMemory as MEMORYMAP_ARRAY(intArraySize=intArraySize))) then
2115 '<%intArraySize%>'
2116 else
2117 CodegenCpp.numIntvars(modelInfo)
2118 end numIntvarsHpcom;
2119
2120 1 template numBoolvarsHpcom(ModelInfo modelInfo, Option<MemoryMap> hpcOmMemoryOpt)
2121 ::=
2122 match(hpcOmMemoryOpt)
2123 case(SOME(hpcomMemory as MEMORYMAP_ARRAY(boolArraySize=boolArraySize))) then
2124 '<%boolArraySize%>'
2125 else
2126 CodegenCpp.numBoolvars(modelInfo)
2127 end numBoolvarsHpcom;
2128
2129 ✗ template numStringvarsHpcom(ModelInfo modelInfo, Option<MemoryMap> hpcOmMemoryOpt)
2130 ::=
2131 match(hpcOmMemoryOpt)
2132 case(SOME(hpcomMemory as MEMORYMAP_ARRAY(stringArraySize=stringArraySize))) then
2133 '<%stringArraySize%>'
2134 else
2135 CodegenCpp.numStringvars(modelInfo)
2136 end numStringvarsHpcom;
2137
2138 annotation(__OpenModelica_Interface="codegen_cpp_ext");
2139 end CodegenCppHpcom;
2140