Skip to content

Commit

Permalink
- Start generating co-simulation FMUs. The FMU doesn't contain valid …
Browse files Browse the repository at this point in the history
…code yet but will soon.

git-svn-id: https://openmodelica.org/svn/OpenModelica/trunk@24938 f25d12d1-65f4-0310-ae8a-bbce733d8d8e
  • Loading branch information
adeas31 committed Mar 5, 2015
1 parent c712037 commit 04830c8
Show file tree
Hide file tree
Showing 10 changed files with 110 additions and 28 deletions.
3 changes: 2 additions & 1 deletion Compiler/FrontEnd/ModelicaBuiltin.mo
Expand Up @@ -2270,7 +2270,8 @@ The only required argument is the className, while all others have some default
Example command:
translateModelFMU(className, version=\"2.0\");"
input TypeName className "the class that should translated";
input String version = "1.0" "The output directory for imported FMU files. <default> will put the files to current working directory.";
input String version = "1.0" "FMU version, 1.0 or 2.0.";
input String fmuType = "me" "FMU type, me (model exchange), cs (co-simulation).";
input String fileNamePrefix = "<default>" "fileNamePrefix. <default> = \"className\"";
output String generatedFileName "Returns the full path of the generated FMU.";
external "builtin";
Expand Down
23 changes: 16 additions & 7 deletions Compiler/Script/CevalScript.mo
Expand Up @@ -1326,25 +1326,33 @@ algorithm
then
(cache,ret_val,st_1);*/

case (cache,env,"translateModelFMU", {Values.CODE(Absyn.C_TYPENAME(className)),Values.STRING(str1),Values.STRING(filenameprefix)},st,_)
case (cache,env,"translateModelFMU", {Values.CODE(Absyn.C_TYPENAME(className)),Values.STRING(str1),Values.STRING(str2),Values.STRING(filenameprefix)},st,_)
equation
true = FMI.checkFMIVersion(str1);
true = FMI.checkFMIType(str2);
str = Absyn.pathString(className);
filenameprefix = if filenameprefix == "<default>" then str else filenameprefix;
filenameprefix = Util.stringReplaceChar(filenameprefix,".","_");
defaulSimOpt = buildSimulationOptionsFromModelExperimentAnnotation(st, className, filenameprefix, SOME(defaultSimulationOptions));
simSettings = convertSimulationOptionsToSimCode(defaulSimOpt);
(cache,ret_val,st_1) = translateModelFMU(cache, env, className, st, str1, filenameprefix, true, SOME(simSettings));
(cache,ret_val,st_1) = translateModelFMU(cache, env, className, st, str1, str2, filenameprefix, true, SOME(simSettings));
then
(cache,ret_val,st_1);

case (cache,_,"translateModelFMU", {Values.CODE(Absyn.C_TYPENAME(_)),Values.STRING(str1),Values.STRING(_)},st,_)
case (cache,_,"translateModelFMU", {Values.CODE(Absyn.C_TYPENAME(_)),Values.STRING(str1),Values.STRING(_),Values.STRING(_)},st,_)
equation
false = FMI.checkFMIVersion(str1);
Error.addMessage(Error.UNKNOWN_FMU_VERSION, {str1});
then
(cache,Values.STRING(""),st);

case (cache,_,"translateModelFMU", {Values.CODE(Absyn.C_TYPENAME(_)),Values.STRING(_),Values.STRING(str1),Values.STRING(_)},st,_)
equation
false = FMI.checkFMIType(str1);
Error.addMessage(Error.UNKNOWN_FMU_TYPE, {str1});
then
(cache,Values.STRING(""),st);

case (cache,_,"translateModelFMU", {Values.CODE(Absyn.C_TYPENAME(_)),Values.STRING(_),Values.STRING(_)},st,_)
then
(cache,Values.STRING(""),st);
Expand Down Expand Up @@ -3940,6 +3948,7 @@ protected function translateModelFMU " author: Frenkel TUD
input Absyn.Path className "path for the model";
input GlobalScript.SymbolTable inInteractiveSymbolTable;
input String inFMUVersion;
input String inFMUType;
input String inFileNamePrefix;
input Boolean addDummy "if true, add a dummy state";
input Option<SimCode.SimulationSettings> inSimSettingsOpt;
Expand All @@ -3948,19 +3957,19 @@ protected function translateModelFMU " author: Frenkel TUD
output GlobalScript.SymbolTable outInteractiveSymbolTable;
algorithm
(outCache,outValue,outInteractiveSymbolTable):=
match (inCache,inEnv,className,inInteractiveSymbolTable,inFMUVersion,inFileNamePrefix,addDummy,inSimSettingsOpt)
match (inCache,inEnv,className,inInteractiveSymbolTable,inFMUVersion,inFMUType,inFileNamePrefix,addDummy,inSimSettingsOpt)
local
FCore.Cache cache;
FCore.Graph env;
BackendDAE.BackendDAE indexed_dlow;
GlobalScript.SymbolTable st;
list<String> libs;
Values.Value outValMsg;
String file_dir, FMUVersion, fileNamePrefix, str;
case (cache,env,_,st,FMUVersion,fileNamePrefix,_,_) /* mo file directory */
String file_dir, FMUVersion, FMUType, fileNamePrefix, str;
case (cache,env,_,st,FMUVersion,FMUType,fileNamePrefix,_,_) /* mo file directory */
equation
(cache, outValMsg, st,_, libs,_, _) =
SimCodeMain.translateModelFMU(cache,env,className,st,FMUVersion,fileNamePrefix,addDummy,inSimSettingsOpt);
SimCodeMain.translateModelFMU(cache,env,className,st,FMUVersion,FMUType,fileNamePrefix,addDummy,inSimSettingsOpt);

// compile
fileNamePrefix = stringAppend(fileNamePrefix,"_FMU");
Expand Down
6 changes: 4 additions & 2 deletions Compiler/Script/StaticScript.mo
Expand Up @@ -266,7 +266,7 @@ public function elabCallInteractive "This function elaborates the functions defi
Boolean impl;
GlobalScript.SymbolTable st;
Ident cname_str,str;
DAE.Exp filenameprefix,exp_1,crefExp,outputFile,dumpExtractionSteps,fmuversion;
DAE.Exp filenameprefix,exp_1,crefExp,outputFile,dumpExtractionSteps,fmuversion,fmuType;
DAE.Type recordtype;
list<Absyn.NamedArg> args;
list<DAE.Exp> excludeList;
Expand Down Expand Up @@ -328,6 +328,8 @@ public function elabCallInteractive "This function elaborates the functions defi
cname_str = Absyn.pathString(className);
(cache,fmuversion) = Static.getOptionalNamedArg(cache,env, SOME(st), impl, "version",
DAE.T_STRING_DEFAULT, args, DAE.SCONST("1.0"),pre,info);
(cache,fmuType) = Static.getOptionalNamedArg(cache,env, SOME(st), impl, "fmuType",
DAE.T_STRING_DEFAULT, args, DAE.SCONST("me"),pre,info);
(cache, filenameprefix) = Static.getOptionalNamedArg(cache,env, SOME(st), impl, "fileNamePrefix",
DAE.T_STRING_DEFAULT, args, DAE.SCONST(cname_str),pre,info);
recordtype =
Expand All @@ -337,7 +339,7 @@ public function elabCallInteractive "This function elaborates the functions defi
NONE(),DAE.emptyTypeSource);
then
(cache,Expression.makePureBuiltinCall("translateModelFMU",
{DAE.CODE(Absyn.C_TYPENAME(className),DAE.T_UNKNOWN_DEFAULT),fmuversion,filenameprefix},DAE.T_STRING_DEFAULT),DAE.PROP(recordtype,DAE.C_VAR()),SOME(st));
{DAE.CODE(Absyn.C_TYPENAME(className),DAE.T_UNKNOWN_DEFAULT),fmuversion,fmuType,filenameprefix},DAE.T_STRING_DEFAULT),DAE.PROP(recordtype,DAE.C_VAR()),SOME(st));

case (cache,env,Absyn.CREF_IDENT(name = "translateModelXML"),{Absyn.CREF(componentRef = cr)},args,impl,SOME(st),pre,_)
equation
Expand Down
19 changes: 11 additions & 8 deletions Compiler/SimCode/SimCodeMain.mo
Expand Up @@ -120,6 +120,7 @@ protected function generateModelCodeFMU "
input DAE.DAElist dae;
input Absyn.Path className;
input String FMUVersion;
input String FMUType;
input String filenamePrefix;
input Option<SimCode.SimulationSettings> simSettingsOpt;
output BackendDAE.BackendDAE outIndexedBackendDAE;
Expand Down Expand Up @@ -149,7 +150,7 @@ algorithm
SimCodeUtil.execStat("SimCode");

System.realtimeTick(ClockIndexes.RT_CLOCK_TEMPLATES);
callTargetTemplatesFMU(simCode, Config.simCodeTarget(), FMUVersion);
callTargetTemplatesFMU(simCode, Config.simCodeTarget(), FMUVersion, FMUType);
timeTemplates := System.realtimeTock(ClockIndexes.RT_CLOCK_TEMPLATES);
end generateModelCodeFMU;

Expand Down Expand Up @@ -204,6 +205,7 @@ public function translateModelFMU
input Absyn.Path className "path for the model";
input GlobalScript.SymbolTable inInteractiveSymbolTable;
input String inFMUVersion;
input String inFMUType;
input String inFileNamePrefix;
input Boolean addDummy "if true, add a dummy state";
input Option<SimCode.SimulationSettings> inSimSettingsOpt;
Expand All @@ -216,9 +218,9 @@ public function translateModelFMU
output list<tuple<String,Values.Value>> resultValues;
algorithm
(outCache,outValue,outInteractiveSymbolTable,outBackendDAE,outStringLst,outFileDir,resultValues):=
matchcontinue (inCache,inEnv,className,inInteractiveSymbolTable,inFMUVersion,inFileNamePrefix,addDummy, inSimSettingsOpt)
matchcontinue (inCache,inEnv,className,inInteractiveSymbolTable,inFMUVersion,inFMUType,inFileNamePrefix,addDummy,inSimSettingsOpt)
local
String FMUVersion,filenameprefix,file_dir,resstr;
String FMUVersion,FMUType,filenameprefix,file_dir,resstr;
DAE.DAElist dae;
FCore.Graph graph;
BackendDAE.BackendDAE dlow,dlow_1,indexed_dlow_1;
Expand All @@ -233,7 +235,7 @@ algorithm
Boolean symbolicJacActivated;
Boolean fmi20;

case (cache,graph,_,st as GlobalScript.SYMBOLTABLE(ast=p),FMUVersion,filenameprefix,_, _)
case (cache,graph,_,st as GlobalScript.SYMBOLTABLE(ast=p),FMUVersion,FMUType,filenameprefix,_, _)
equation
/* calculate stuff that we need to create SimCode data structure */
System.realtimeTick(ClockIndexes.RT_CLOCK_FRONTEND);
Expand All @@ -256,7 +258,7 @@ algorithm
timeBackend = System.realtimeTock(ClockIndexes.RT_CLOCK_BACKEND);

(indexed_dlow_1,libs,file_dir,timeSimCode,timeTemplates) =
generateModelCodeFMU(dlow_1, p, dae, className, FMUVersion, filenameprefix, inSimSettingsOpt);
generateModelCodeFMU(dlow_1, p, dae, className, FMUVersion, FMUType, filenameprefix, inSimSettingsOpt);

//reset config flag
Flags.setConfigBool(Flags.GENERATE_SYMBOLIC_LINEARIZATION, symbolicJacActivated);
Expand All @@ -271,7 +273,7 @@ algorithm
resstr = stringAppendList({"SimCode: The model ",resstr," has been translated to FMU"});
then
(cache,Values.STRING(resstr),st,indexed_dlow_1,libs,file_dir, resultValues);
case (_,_,_,_,_,_,_, _)
case (_,_,_,_,_,_,_,_,_)
equation
resstr = Absyn.pathStringNoQual(className);
resstr = stringAppendList({"SimCode: The model ",resstr," could not be translated to FMU"});
Expand Down Expand Up @@ -475,7 +477,7 @@ algorithm
then ();

case (_, _, "sfmi") equation
Tpl.tplNoret2(CodegenSparseFMI.translateModel, simCode, "2.0");
Tpl.tplNoret3(CodegenSparseFMI.translateModel, simCode, "2.0", "me");
then ();

case (_, outIndexedBackendDAE, "QSS") equation
Expand Down Expand Up @@ -567,6 +569,7 @@ protected function callTargetTemplatesFMU
input SimCode.SimCode simCode;
input String target;
input String FMUVersion;
input String FMUType;
algorithm
_ := match (simCode,target)
local
Expand All @@ -580,7 +583,7 @@ algorithm
else
Tpl.tplNoret2(SimCodeDump.dumpSimCodeToC, simCode, false);
end if;
Tpl.tplNoret2(CodegenFMU.translateModel, simCode, FMUVersion);
Tpl.tplNoret3(CodegenFMU.translateModel, simCode, FMUVersion, FMUType);
then ();
case (_,"Cpp")
equation
Expand Down
30 changes: 24 additions & 6 deletions Compiler/Template/CodegenFMU.tpl
Expand Up @@ -50,7 +50,7 @@ import CodegenUtil.*;
import CodegenC.*; //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)


template translateModel(SimCode simCode, String FMUVersion)
template translateModel(SimCode simCode, String FMUVersion, String FMUType)
"Generates C code and Makefile for compiling a FMU of a
Modelica model."
::=
Expand All @@ -71,13 +71,13 @@ case sc as SIMCODE(modelInfo=modelInfo as MODELINFO(__)) then
let()= textFile(simulationInitFile(simCode,guid), '<%fileNamePrefix%>_init.xml')
let x = covertTextFileToCLiteral('<%fileNamePrefix%>_init.xml','<%fileNamePrefix%>_init.c')
let()= textFile(fmumodel_identifierFile(simCode,guid,FMUVersion), '<%fileNamePrefix%>_FMU.c')
let()= textFile(fmuModelDescriptionFile(simCode,guid,FMUVersion), 'modelDescription.xml')
let()= textFile(fmuModelDescriptionFile(simCode,guid,FMUVersion,FMUType), 'modelDescription.xml')
let()= textFile(fmudeffile(simCode,FMUVersion), '<%fileNamePrefix%>.def')
let()= textFile(fmuMakefile(target,simCode,FMUVersion), '<%fileNamePrefix%>_FMU.makefile')
"" // Return empty result since result written to files directly
end translateModel;

template fmuModelDescriptionFile(SimCode simCode, String guid, String FMUVersion)
template fmuModelDescriptionFile(SimCode simCode, String guid, String FMUVersion, String FMUType)
"Generates code for ModelDescription file for FMU target."
::=
match simCode
Expand All @@ -86,7 +86,7 @@ case SIMCODE(__) then
<?xml version="1.0" encoding="UTF-8"?>
<%
if isFMIVersion20(FMUVersion) then fmi2ModelDescription(simCode,guid)
else fmiModelDescription(simCode,guid)
else fmiModelDescription(simCode,guid,FMUType)
%>
>>
end fmuModelDescriptionFile;
Expand Down Expand Up @@ -307,7 +307,7 @@ case SIMVAR(nominalValue = nominalValue) then
end NominalString2;

// Code for generating modelDescription.xml file for FMI 1.0 ModelExchange.
template fmiModelDescription(SimCode simCode, String guid)
template fmiModelDescription(SimCode simCode, String guid, String FMUType)
"Generates code for ModelDescription file for FMU target."
::=
// <%UnitDefinitions(simCode)%>
Expand All @@ -320,6 +320,7 @@ case SIMCODE(__) then
<%TypeDefinitions(modelInfo, "1.0")%>
<%DefaultExperiment(simulationSettingsOpt)%>
<%ModelVariables(modelInfo, "1.0")%>
<%if isFMICSType(FMUType) then Implementation()%>
</fmiModelDescription>
>>
end fmiModelDescription;
Expand All @@ -336,7 +337,7 @@ case SIMCODE(modelInfo = MODELINFO(varInfo = vi as VARINFO(__), vars = SIMVARS(s
let generationTool= 'OpenModelica Compiler <%getVersionNr()%>'
let generationDateAndTime = xsdateTime(getCurrentDateTime())
let variableNamingConvention = 'structured'
let numberOfContinuousStates = if intEq(vi.numStateVars,1) then statesnumwithDummy(listStates) else vi.numStateVars
let numberOfContinuousStates = if intEq(vi.numStateVars,1) then statesnumwithDummy(listStates) else vi.numStateVars
let numberOfEventIndicators = vi.numZeroCrossings
<<
fmiVersion="<%fmiVersion%>"
Expand Down Expand Up @@ -662,6 +663,23 @@ template externalFunction(Function fn)
>>
end externalFunction;

template Implementation()
"Generate Co-simulation Implementation section"
::=
<<
<Implementation>
<CoSimulation_StandAlone>
<Capabilities
canHandleVariableCommunicationStepSize="true"
canHandleEvents="true"
canBeInstantiatedOnlyOncePerProcess="true"
canInterpolateInputs="true"
maxOutputDerivativeOrder="1"/>
</CoSimulation_StandAlone>
</Implementation>
>>
end Implementation;

template ModelStructure(SimCode simCode, list<JacobianMatrix> jacobianMatrixes)
"Generates Model Structure."
::=
Expand Down
4 changes: 2 additions & 2 deletions Compiler/Template/CodegenSparseFMI.tpl
Expand Up @@ -50,7 +50,7 @@ import CodegenUtil.*;
import CodegenFMU.*;
import CodegenC.*;

template translateModel(SimCode simCode, String FMUVersion)
template translateModel(SimCode simCode, String FMUVersion, String FMUType)
"Generates C code and Makefile for compiling a FMU of a
Modelica model."
::=
Expand All @@ -59,7 +59,7 @@ case sc as SIMCODE(modelInfo=modelInfo as MODELINFO(__)) then
let guid = getUUIDStr()
let target = simulationCodeTarget()
let()= textFile(fmumodel_identifierFile(simCode,guid,FMUVersion), '<%fileNamePrefix%>_FMI.cpp')
let()= textFile(CodegenFMU.fmuModelDescriptionFile(simCode,guid,FMUVersion), 'modelDescription.xml')
let()= textFile(CodegenFMU.fmuModelDescriptionFile(simCode,guid,FMUVersion,FMUType), 'modelDescription.xml')
"" // Return empty result since result written to files directly
end translateModel;

Expand Down
5 changes: 5 additions & 0 deletions Compiler/Template/SimCodeTV.mo
Expand Up @@ -3421,6 +3421,11 @@ package FMI
output Boolean success;
end isFMIVersion20;

function isFMICSType "Checks if FMU type is co-simulation"
input String inFMIType;
output Boolean success;
end isFMICSType;

function getEnumerationTypeFromTypes
input list<TypeDefinitions> inTypeDefinitionsList;
input String inBaseType;
Expand Down
21 changes: 21 additions & 0 deletions Compiler/Template/Tpl.mo
Expand Up @@ -1637,6 +1637,27 @@ algorithm
textStringBuf(txt);
end tplPrint3;

public function tplNoret3
input Tpl_Fun inFun;
input ArgType1 inArg;
input ArgType2 inArg2;
input ArgType2 inArg3;

partial function Tpl_Fun
input Text in_txt;
input ArgType1 inArgA;
input ArgType2 inArgB;
input ArgType2 inArgC;
output Text out_txt;
end Tpl_Fun;
protected
Integer nErr;
algorithm
nErr := Error.getNumErrorMessages();
_ := tplCallWithFailError3(inFun, inArg, inArg2, inArg3);
failIfTrue(Error.getNumErrorMessages() > nErr);
end tplNoret3;

public function tplNoret2
input Tpl_Fun inFun;
input ArgType1 inArg;
Expand Down
6 changes: 4 additions & 2 deletions Compiler/Util/Error.mo
Expand Up @@ -890,10 +890,12 @@ public constant Message FILE_NOT_FOUND_ERROR = MESSAGE(7007, SCRIPTING(), ERROR(
Util.gettext("File not Found: %s."));
public constant Message UNKNOWN_FMU_VERSION = MESSAGE(7008, SCRIPTING(), ERROR(),
Util.gettext("Unknown FMU version %s. Only version 1.0 & 2.0 are supported."));
public constant Message UNKNOWN_FMU_TYPE = MESSAGE(7009, SCRIPTING(), ERROR(),
Util.gettext("Unknown FMU type %s. Supported types are me (model exchange) & cs (co-simulation)."));
// FIGARO_ERROR added by Alexander Carlqvist
public constant Message FIGARO_ERROR = MESSAGE(7009, SCRIPTING(), ERROR(),
public constant Message FIGARO_ERROR = MESSAGE(7010, SCRIPTING(), ERROR(),
Util.notrans("Figaro: %s."));
public constant Message SUSAN_NOTIFY = MESSAGE(7010, TRANSLATION(), NOTIFICATION(),
public constant Message SUSAN_NOTIFY = MESSAGE(7011, TRANSLATION(), NOTIFICATION(),
Util.notrans("%s"));

protected import ErrorExt;
Expand Down
21 changes: 21 additions & 0 deletions Compiler/Util/FMI.mo
Expand Up @@ -242,6 +242,27 @@ algorithm
end match;
end isFMIVersion20;

public function checkFMIType "Checks if the FMU type is supported."
input String inFMIType;
output Boolean success;
algorithm
success := match (inFMIType)
case ("me") then true;
case ("cs") then true;
else false;
end match;
end checkFMIType;

public function isFMICSType "Checks if FMU type is co-simulation"
input String inFMIType;
output Boolean success;
algorithm
success := match (inFMIType)
case ("cs") then true;
else false;
end match;
end isFMICSType;

public function getEnumerationTypeFromTypes
input list<TypeDefinitions> inTypeDefinitionsList;
input String inBaseType;
Expand Down

0 comments on commit 04830c8

Please sign in to comment.