Skip to content

Commit 2ed993a

Browse files
committed
Allow generation of source-code FMUs
All generated (modelica-exchange) FMUs now include the source code of the runtime, so that it is possible to compile an (almost) static FMU. By default, the runtime is still linked to the generated FMU, but this can be changed by using -d=buildStaticSourceFMU. The makefiles for the FMUs have been changed, such that we first generate a source-code FMU, copying in all the files. Then a second Makefile is used to compile the binary. Both make commands are executed by default for translateModelFMU, but this API function will only generate pure source-code FMUs in the future (buildModelFMU will also compile the FMU, and there should be an API to compile additional targets for an existing FMU). FMUs no longer use garbage collection by default since some simulators used libgc, and it just caused all sorts of headaches.
1 parent 4cdc91b commit 2ed993a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+1258
-891
lines changed

Compiler/Script/CevalScript.mo

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -218,16 +218,20 @@ end isCompleteFunction;
218218
public function compileModel "Compiles a model given a file-prefix, helper function to buildModel."
219219
input String fileprefix;
220220
input list<String> libs;
221+
input String workingDir = "";
222+
input list<String> makeVars = {};
221223
protected
222224
String omhome = Settings.getInstallationDirectoryPath(),omhome_1 = System.stringReplace(omhome, "\"", "");
223225
String pd = System.pathDelimiter();
224-
String libsfilename,libs_str,s_call,filename,winCompileMode;
226+
String cdWorkingDir,setMakeVars,libsfilename,libs_str,s_call,filename,winCompileMode;
225227
String fileDLL = fileprefix + System.getDllExt(),fileEXE = fileprefix + System.getExeExt(),fileLOG = fileprefix + ".log";
226228
Integer numParallel,res;
227229
Boolean isWindows = System.os() == "Windows_NT";
230+
list<String> makeVarsNoBinding;
228231
algorithm
229232
libsfilename := fileprefix + ".libs";
230233
libs_str := stringDelimitList(libs, " ");
234+
makeVarsNoBinding := makeVars; // OMC is stupid and wants to constant evaluate inputs with bindings for iterator variables...
231235

232236
System.writeFile(libsfilename, libs_str);
233237
if isWindows then
@@ -238,11 +242,15 @@ algorithm
238242
// set OPENMODELICAHOME=DIR && actually adds the space between the DIR and &&
239243
// to the environment variable! Don't ask me why, ask Microsoft.
240244
omhome := "set OPENMODELICAHOME=\"" + System.stringReplace(omhome_1, "/", "\\") + "\"&& ";
245+
setMakeVars := sum("set "+var+"&& " for var in makeVarsNoBinding);
246+
cdWorkingDir := if stringLength(workingDir) == 0 then "" else ("cd \"" + workingDir + "\"");
241247
winCompileMode := if Config.getRunningTestsuite() then "serial" else "parallel";
242-
s_call := stringAppendList({omhome,"\"",omhome_1,pd,"share",pd,"omc",pd,"scripts",pd,"Compile","\""," ",fileprefix," ",Config.simulationCodeTarget()," ", winCompileMode});
248+
s_call := stringAppendList({omhome,cdWorkingDir,setMakeVars,"\"",omhome_1,pd,"share",pd,"omc",pd,"scripts",pd,"Compile","\""," ",fileprefix," ",Config.simulationCodeTarget()," ", winCompileMode});
243249
else
244250
numParallel := if Config.getRunningTestsuite() then 1 else Config.noProc();
245-
s_call := stringAppendList({System.getMakeCommand()," -j",intString(numParallel)," -f ",fileprefix,".makefile"});
251+
cdWorkingDir := if stringLength(workingDir) == 0 then "" else (" -C \"" + workingDir + "\"");
252+
setMakeVars := sum(" "+var for var in makeVarsNoBinding);
253+
s_call := stringAppendList({System.getMakeCommand()," -j",intString(numParallel),cdWorkingDir," -f ",fileprefix,".makefile",setMakeVars});
246254
end if;
247255
if Flags.isSet(Flags.DYN_LOAD) then
248256
Debug.traceln("compileModel: running " + s_call);

Compiler/Script/CevalScriptBackend.mo

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2608,7 +2608,10 @@ protected function translateModelFMU " author: Frenkel TUD
26082608
output FCore.Cache outCache;
26092609
output Values.Value outValue;
26102610
output GlobalScript.SymbolTable outInteractiveSymbolTable;
2611+
protected
2612+
Boolean staticSourceCodeFMU;
26112613
algorithm
2614+
staticSourceCodeFMU := Flags.isSet(Flags.BUILD_STATIC_SOURCE_FMU);
26122615
(outCache,outValue,outInteractiveSymbolTable):=
26132616
match (inCache,inEnv,className,inInteractiveSymbolTable,inFMUVersion,inFMUType,inFileNamePrefix,addDummy,inSimSettingsOpt)
26142617
local
@@ -2618,18 +2621,37 @@ algorithm
26182621
GlobalScript.SymbolTable st;
26192622
list<String> libs;
26202623
Values.Value outValMsg;
2621-
String file_dir, FMUVersion, FMUType, fileNamePrefix, str;
2624+
String file_dir, FMUVersion, FMUType, fileNamePrefix, str, fmutmp;
26222625
case (cache,env,_,st,FMUVersion,FMUType,fileNamePrefix,_,_) /* mo file directory */
26232626
equation
26242627
(cache, outValMsg, st,_, libs,_, _) =
26252628
SimCodeMain.translateModelFMU(cache,env,className,st,FMUVersion,FMUType,fileNamePrefix,addDummy,inSimSettingsOpt);
26262629

26272630
// compile
2628-
fileNamePrefix = stringAppend(fileNamePrefix,"_FMU");
2629-
CevalScript.compileModel(fileNamePrefix , libs);
2630-
2631-
then
2632-
(cache,outValMsg,st);
2631+
CevalScript.compileModel(fileNamePrefix+"_FMU" , libs);
2632+
if Config.simCodeTarget() <> "Cpp" then
2633+
fmutmp = fileNamePrefix + ".fmutmp";
2634+
/* Let's just assume we have a pristine source directory in fmutmp
2635+
if System.directoryExists(fmutmp) then
2636+
System.removeDirectory(fmutmp);
2637+
end if;
2638+
unzip(...);
2639+
*/
2640+
// CevalScript.compileModel(fileNamePrefix , libs, workingDir=fmutmp+"/sources", makeVars={"CC=arm-linux-gnueabi-gcc","FMIPLATFORM=arm-linux-gnueabi","DLLEXT=.so"});
2641+
CevalScript.compileModel(fileNamePrefix , libs, workingDir=fmutmp+"/sources", makeVars={
2642+
"CC="+System.getCCompiler(),
2643+
"'CFLAGS="+System.getCFlags()+"'",
2644+
"CPPFLAGS=",
2645+
"'LDFLAGS="+System.getLDFlags()+" "+(if staticSourceCodeFMU then System.getRTLibsFMU() /*TODO: Should not be needed, once we remove the need for lapack/expat*/ else System.getRTLibsSim())+"'",
2646+
"FMIPLATFORM="+System.modelicaPlatform(),
2647+
"DLLEXT="+System.getDllExt(),
2648+
"'LD="+System.getLinker()+"'",
2649+
if staticSourceCodeFMU then "OPENMODELICA_DYNAMIC=" else "OPENMODELICA_DYNAMIC=1"
2650+
});
2651+
// CevalScript.compileModel(fileNamePrefix , libs, workingDir=fmutmp+"/sources", makeVars={});
2652+
System.removeDirectory(fmutmp);
2653+
end if;
2654+
then (cache,outValMsg,st);
26332655
else /* mo file directory */
26342656
equation
26352657
str = Error.printMessagesStr(false);

Compiler/SimCode/SimCodeFunctionUtil.mo

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2755,6 +2755,7 @@ public function createMakefileParams
27552755
input list<String> libs;
27562756
input list<String> libPaths;
27572757
input Boolean isFunction;
2758+
input Boolean isFMU=false;
27582759
output SimCode.MakefileParams makefileParams;
27592760
protected
27602761
String omhome, ccompiler, cxxcompiler, linker, exeext, dllext, cflags, ldflags, rtlibs, platform, fopenmp,compileDir;
@@ -2771,7 +2772,7 @@ algorithm
27712772
(if Flags.isSet(Flags.HPCOM) then "-fopenmp" else "");
27722773
cflags := if stringEq(Config.simCodeTarget(),"JavaScript") then "-Os -Wno-warn-absolute-paths" else cflags;
27732774
ldflags := System.getLDFlags();
2774-
rtlibs := if isFunction then System.getRTLibs() else System.getRTLibsSim();
2775+
rtlibs := if isFunction then System.getRTLibs() else (if isFMU then System.getRTLibsFMU() else System.getRTLibsSim());
27752776
platform := System.modelicaPlatform();
27762777
compileDir := System.pwd() + System.pathDelimiter();
27772778
makefileParams := SimCode.MAKEFILE_PARAMS(ccompiler, cxxcompiler, linker, exeext, dllext,

Compiler/SimCode/SimCodeMain.mo

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ algorithm
147147
(libs,libPaths,includes, includeDirs, recordDecls, functions, literals) :=
148148
SimCodeUtil.createFunctions(p, inBackendDAE);
149149
simCode := createSimCode(inBackendDAE, inInitDAE, inUseHomotopy, inRemovedInitialEquationLst, inPrimaryParameters, inAllPrimaryParameters,
150-
className, filenamePrefix, fileDir, functions, includes, includeDirs, libs, libPaths, simSettingsOpt, recordDecls, literals, Absyn.FUNCTIONARGS({},{}));
150+
className, filenamePrefix, fileDir, functions, includes, includeDirs, libs, libPaths, simSettingsOpt, recordDecls, literals, Absyn.FUNCTIONARGS({},{}), isFMU=true);
151151
timeSimCode := System.realtimeTock(ClockIndexes.RT_CLOCK_SIMCODE);
152152
SimCodeFunctionUtil.execStat("SimCode");
153153

@@ -439,6 +439,7 @@ protected function createSimCode "
439439
input list<SimCode.RecordDeclaration> recordDecls;
440440
input tuple<Integer, HashTableExpToIndex.HashTable, list<DAE.Exp>> literals;
441441
input Absyn.FunctionArgs args;
442+
input Boolean isFMU=false;
442443
output SimCode.SimCode simCode;
443444
algorithm
444445
simCode := matchcontinue(inBackendDAE, inClassName, filenamePrefix, inString11, functions, externalFunctionIncludes, includeDirs, libs, libPaths,simSettingsOpt, recordDecls, literals, args)
@@ -472,7 +473,7 @@ algorithm
472473
then HpcOmSimCodeMain.createSimCode(inBackendDAE, inInitDAE, inUseHomotopy, inRemovedInitialEquationLst, inPrimaryParameters, inAllPrimaryParameters, inClassName, filenamePrefix, inString11, functions, externalFunctionIncludes, includeDirs, libs, libPaths,simSettingsOpt, recordDecls, literals, args);
473474

474475
else equation
475-
(tmpSimCode, _) = SimCodeUtil.createSimCode(inBackendDAE, inInitDAE, inUseHomotopy, inRemovedInitialEquationLst, inPrimaryParameters, inAllPrimaryParameters, inClassName, filenamePrefix, inString11, functions, externalFunctionIncludes, includeDirs, libs,libPaths, simSettingsOpt, recordDecls, literals, args);
476+
(tmpSimCode, _) = SimCodeUtil.createSimCode(inBackendDAE, inInitDAE, inUseHomotopy, inRemovedInitialEquationLst, inPrimaryParameters, inAllPrimaryParameters, inClassName, filenamePrefix, inString11, functions, externalFunctionIncludes, includeDirs, libs,libPaths, simSettingsOpt, recordDecls, literals, args, isFMU=isFMU);
476477
then tmpSimCode;
477478
end matchcontinue;
478479
end createSimCode;
@@ -591,12 +592,22 @@ algorithm
591592
_ := match (simCode,target)
592593
local
593594
String str;
595+
String fmutmp;
594596

595597
case (SimCode.SIMCODE(),"C")
596598
algorithm
599+
fmutmp := simCode.fileNamePrefix + ".fmutmp";
600+
if System.directoryExists(fmutmp) then
601+
if not System.removeDirectory(fmutmp) then
602+
print("Failed to remove directory: " + fmutmp + "\n");
603+
fail();
604+
end if;
605+
end if;
606+
Util.createDirectoryTree(fmutmp + "/sources/include/");
597607
if Flags.isSet(Flags.MODEL_INFO_JSON) then
598608
SerializeModelInfo.serialize(simCode, Flags.isSet(Flags.INFO_XML_OPERATIONS));
599-
true := System.covertTextFileToCLiteral(simCode.fileNamePrefix+"_info.json", simCode.fileNamePrefix+"_info.c");
609+
str := fmutmp + "/sources/" + simCode.fileNamePrefix;
610+
true := System.covertTextFileToCLiteral(simCode.fileNamePrefix+"_info.json", str+"_info.c");
600611
else
601612
Tpl.tplNoret2(SimCodeDump.dumpSimCodeToC, simCode, false);
602613
end if;

Compiler/SimCode/SimCodeUtil.mo

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@ public function createSimCode "entry point to create SimCode from BackendDAE."
165165
input list<SimCode.RecordDeclaration> recordDecls;
166166
input tuple<Integer, HashTableExpToIndex.HashTable, list<DAE.Exp>> literals;
167167
input Absyn.FunctionArgs args;
168+
input Boolean isFMU=false;
168169
output SimCode.SimCode simCode;
169170
output tuple<Integer, list<tuple<Integer, Integer>>> outMapping "the highest simEqIndex in the mapping and the mapping simEq-Index -> scc-Index itself";
170171
protected
@@ -280,7 +281,7 @@ algorithm
280281

281282
((uniqueEqIndex, algorithmAndEquationAsserts)) := BackendDAEUtil.foldEqSystem(dlow, createAlgorithmAndEquationAsserts, (uniqueEqIndex, {}));
282283
discreteModelVars := BackendDAEUtil.foldEqSystem(dlow, extractDiscreteModelVars, {});
283-
makefileParams := SimCodeFunctionUtil.createMakefileParams(includeDirs, libs, libPaths, false);
284+
makefileParams := SimCodeFunctionUtil.createMakefileParams(includeDirs, libs, libPaths, false, isFMU);
284285
(delayedExps, maxDelayedExpIndex) := extractDelayedExpressions(dlow);
285286

286287
// append removed equation to all equations, since these are actually
@@ -4134,11 +4135,11 @@ protected
41344135
list<BackendDAE.Equation> eqs;
41354136
algorithm
41364137
try
4137-
(varsWithBind,varsWithoutBind) := List.separateOnTrue(varLstIn,BackendVariable.varHasBindExp);
4138-
(comps,ass1,ass2) := BackendDAEUtil.causalizeVarBindSystem(varsWithBind);
4139-
order := List.map1(List.flatten(comps),Array.getIndexFirst,ass1);
4140-
varsWithBind := List.map1(order,List.getIndexFirst,varsWithBind);
4141-
varLstOut := listAppend(varsWithoutBind,varsWithBind);
4138+
(varsWithBind,varsWithoutBind) := List.separateOnTrue(varLstIn,BackendVariable.varHasBindExp);
4139+
(comps,ass1,ass2) := BackendDAEUtil.causalizeVarBindSystem(varsWithBind);
4140+
order := List.map1(List.flatten(comps),Array.getIndexFirst,ass1);
4141+
varsWithBind := List.map1(order,List.getIndexFirst,varsWithBind);
4142+
varLstOut := listAppend(varsWithoutBind,varsWithBind);
41424143
else
41434144
varLstOut := varLstIn;
41444145
end try;

Compiler/Template/CodegenC.tpl

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -161,41 +161,41 @@ end simulationHeaderFile;
161161
match simCode
162162
case simCode as SIMCODE(__) then
163163
// external objects
164-
let()= textFileConvertLines(simulationFile_exo(simCode,guid), '<%fileNamePrefix%>_01exo.c')
164+
let()= textFileConvertLines(simulationFile_exo(simCode,guid), '<%modelNamePrefix%>_01exo.c')
165165
// non-linear systems
166-
let()= textFileConvertLines(simulationFile_nls(simCode,guid), '<%fileNamePrefix%>_02nls.c')
166+
let()= textFileConvertLines(simulationFile_nls(simCode,guid), '<%modelNamePrefix%>_02nls.c')
167167
// linear systems
168-
let()= textFileConvertLines(simulationFile_lsy(simCode,guid), '<%fileNamePrefix%>_03lsy.c')
168+
let()= textFileConvertLines(simulationFile_lsy(simCode,guid), '<%modelNamePrefix%>_03lsy.c')
169169
// state set
170-
let()= textFileConvertLines(simulationFile_set(simCode,guid), '<%fileNamePrefix%>_04set.c')
170+
let()= textFileConvertLines(simulationFile_set(simCode,guid), '<%modelNamePrefix%>_04set.c')
171171
// events: sample, zero crossings, relations
172-
let()= textFileConvertLines(simulationFile_evt(simCode,guid), '<%fileNamePrefix%>_05evt.c')
172+
let()= textFileConvertLines(simulationFile_evt(simCode,guid), '<%modelNamePrefix%>_05evt.c')
173173
// initialization
174-
let()= textFileConvertLines(simulationFile_inz(simCode,guid), '<%fileNamePrefix%>_06inz.c')
174+
let()= textFileConvertLines(simulationFile_inz(simCode,guid), '<%modelNamePrefix%>_06inz.c')
175175
// delay
176-
let()= textFileConvertLines(simulationFile_dly(simCode,guid), '<%fileNamePrefix%>_07dly.c')
176+
let()= textFileConvertLines(simulationFile_dly(simCode,guid), '<%modelNamePrefix%>_07dly.c')
177177
// update bound start values, update bound parameters
178-
let()= textFileConvertLines(simulationFile_bnd(simCode,guid), '<%fileNamePrefix%>_08bnd.c')
178+
let()= textFileConvertLines(simulationFile_bnd(simCode,guid), '<%modelNamePrefix%>_08bnd.c')
179179
// algebraic
180-
let()= textFileConvertLines(simulationFile_alg(simCode,guid), '<%fileNamePrefix%>_09alg.c')
180+
let()= textFileConvertLines(simulationFile_alg(simCode,guid), '<%modelNamePrefix%>_09alg.c')
181181
// asserts
182-
let()= textFileConvertLines(simulationFile_asr(simCode,guid), '<%fileNamePrefix%>_10asr.c')
182+
let()= textFileConvertLines(simulationFile_asr(simCode,guid), '<%modelNamePrefix%>_10asr.c')
183183
// mixed systems
184184
let &mixheader = buffer ""
185-
let()= textFileConvertLines(simulationFile_mix(simCode,guid,&mixheader), '<%fileNamePrefix%>_11mix.c')
186-
let()= textFile(&mixheader, '<%fileNamePrefix%>_11mix.h')
185+
let()= textFileConvertLines(simulationFile_mix(simCode,guid,&mixheader), '<%modelNamePrefix%>_11mix.c')
186+
let()= textFile(&mixheader, '<%modelNamePrefix%>_11mix.h')
187187
// jacobians
188-
let()= textFileConvertLines(simulationFile_jac(simCode,guid), '<%fileNamePrefix%>_12jac.c')
189-
let()= textFile(simulationFile_jac_header(simCode,guid), '<%fileNamePrefix%>_12jac.h')
188+
let()= textFileConvertLines(simulationFile_jac(simCode,guid), '<%modelNamePrefix%>_12jac.c')
189+
let()= textFile(simulationFile_jac_header(simCode,guid), '<%modelNamePrefix%>_12jac.h')
190190
// optimization
191-
let()= textFileConvertLines(simulationFile_opt(simCode,guid), '<%fileNamePrefix%>_13opt.c')
192-
let()= textFile(simulationFile_opt_header(simCode,guid), '<%fileNamePrefix%>_13opt.h')
191+
let()= textFileConvertLines(simulationFile_opt(simCode,guid), '<%modelNamePrefix%>_13opt.c')
192+
let()= textFile(simulationFile_opt_header(simCode,guid), '<%modelNamePrefix%>_13opt.h')
193193
// linearization
194-
let()= textFileConvertLines(simulationFile_lnz(simCode,guid), '<%fileNamePrefix%>_14lnz.c')
194+
let()= textFileConvertLines(simulationFile_lnz(simCode,guid), '<%modelNamePrefix%>_14lnz.c')
195195
// synchronous
196-
let()= textFileConvertLines(simulationFile_syn(simCode,guid), '<%fileNamePrefix%>_15syn.c')
196+
let()= textFileConvertLines(simulationFile_syn(simCode,guid), '<%modelNamePrefix%>_15syn.c')
197197
// main file
198-
let()= textFileConvertLines(simulationFile(simCode,guid,isModelExchangeFMU), '<%fileNamePrefix%>.c')
198+
let()= textFileConvertLines(simulationFile(simCode,guid,isModelExchangeFMU), '<%modelNamePrefix%>.c')
199199
""
200200
end match
201201
end generateSimulationFiles;
@@ -816,7 +816,7 @@ template simulationFile(SimCode simCode, String guid, Boolean isModelExchangeFMU
816816
match simCode
817817
case simCode as SIMCODE(hpcomData=HPCOMDATA(__)) then
818818
let modelNamePrefixStr = modelNamePrefix(simCode)
819-
let mainInit = if boolOr(Flags.isSet(Flags.PARMODAUTO), Flags.isSet(HPCOM)) then
819+
let mainInit = if boolOr(isModelExchangeFMU, boolOr(Flags.isSet(Flags.PARMODAUTO), Flags.isSet(HPCOM))) then
820820
<<
821821
mmc_init_nogc();
822822
omc_alloc_interface = omc_alloc_interface_pooled;
@@ -947,6 +947,8 @@ template simulationFile(SimCode simCode, String guid, Boolean isModelExchangeFMU
947947
return 1;
948948
}
949949

950+
<% if boolNot(isModelExchangeFMU) then
951+
<<
950952
#if defined(threadData)
951953
#undef threadData
952954
#endif
@@ -966,6 +968,8 @@ template simulationFile(SimCode simCode, String guid, Boolean isModelExchangeFMU
966968
}
967969
<%\n%>
968970
>>
971+
%>
972+
>>
969973
/* adrpo: leave a newline at the end of file to get ridsymbolName(String fileNamePrefix of the warning */
970974
end match
971975
end simulationFile;

0 commit comments

Comments
 (0)