Skip to content

Commit

Permalink
- add fmi feature dynamic external function, for more information hav…
Browse files Browse the repository at this point in the history
  • Loading branch information
Jens Frenkel committed Jun 1, 2011
1 parent 0185aaa commit 781997c
Show file tree
Hide file tree
Showing 7 changed files with 418 additions and 33 deletions.
59 changes: 54 additions & 5 deletions Compiler/BackEnd/SimCode.mo
Expand Up @@ -306,6 +306,7 @@ uniontype Function
list<String> libs; //need this one for C#
String language "C or Fortran";
Absyn.Info info;
Boolean dynamicLoad;
end EXTERNAL_FUNCTION;
record RECORD_CONSTRUCTOR
Absyn.Path name;
Expand Down Expand Up @@ -1650,6 +1651,7 @@ algorithm
Absyn.Path name;
DAE.ElementSource source;
Absyn.Info info;
Boolean dynamicLoad;

// Modelica functions.
case (DAE.FUNCTION(path = fpath, source = source,
Expand Down Expand Up @@ -1683,7 +1685,7 @@ algorithm
inVars = Util.listMap(DAEUtil.getInputVars(daeElts), daeInOutSimVar);
biVars = Util.listMap(DAEUtil.getBidirVars(daeElts), daeInOutSimVar);
(recordDecls,rt_1) = elaborateRecordDeclarations(daeElts, recordDecls, rt);
(fn_includes, fn_includeDirs, fn_libs) = generateExtFunctionIncludes(fpath,ann);
(fn_includes, fn_includeDirs, fn_libs,dynamicLoad) = generateExtFunctionIncludes(fpath,ann);
includes = Util.listUnion(fn_includes, includes);
includeDirs = Util.listUnion(fn_includeDirs, includeDirs);
libs = Util.listUnion(fn_libs, libs);
Expand All @@ -1693,7 +1695,7 @@ algorithm
info = DAEUtil.getElementSourceFileInfo(source);
then
(EXTERNAL_FUNCTION(fpath, extfnname, funArgs, simextargs, extReturn,
inVars, outVars, biVars, fn_libs, lang, info),
inVars, outVars, biVars, fn_libs, lang, info, dynamicLoad),
rt_1,recordDecls,includes,includeDirs,libs);

// Record constructor.
Expand Down Expand Up @@ -8718,21 +8720,24 @@ protected function generateExtFunctionIncludes
output list<String> includes;
output list<String> includeDirs;
output list<String> libs;
output Boolean dynamcLoad;
algorithm
(includes,includeDirs,libs):=
(includes,includeDirs,libs,dynamcLoad):=
match (path,inAbsynAnnotationOption)
local
SCode.Mod mod;
Boolean b;

case (path,SOME(SCode.ANNOTATION(mod)))
equation
b = generateExtFunctionDynamicLoad(mod);
libs = generateExtFunctionIncludesLibstr(mod);
includes = generateExtFunctionIncludesIncludestr(mod);
libs = generateExtFunctionLibraryDirectoryFlags(path,mod,libs);
includeDirs = generateExtFunctionIncludeDirectoryFlags(path,mod,includes);
then
(includes,includeDirs,libs);
case (_,NONE()) then ({},{},{});
(includes,includeDirs,libs,b);
case (_,NONE()) then ({},{},{},false);
end match;
end generateExtFunctionIncludes;

Expand Down Expand Up @@ -8919,6 +8924,26 @@ algorithm
end matchcontinue;
end generateExtFunctionIncludesIncludestr;

protected function generateExtFunctionDynamicLoad
input SCode.Mod inMod;
output Boolean outDynamicLoad;
algorithm
outDynamicLoad:= matchcontinue (inMod)
local
list<Absyn.Exp> arr;
list<String> libs;
list<list<String>> libsList;
Boolean b;
case (_)
equation
SCode.MOD(binding = SOME((Absyn.BOOL(b), _))) =
Mod.getUnelabedSubMod(inMod, "DynamicLoad");
then
b;
else false;
end matchcontinue;
end generateExtFunctionDynamicLoad;

protected function matchFnRefs
"Used together with getMatchingExps"
input tuple<DAE.Exp,list<DAE.Exp>> itpl;
Expand Down Expand Up @@ -10799,6 +10824,30 @@ algorithm
SIMVAR(name=name) := var;
end varName;

public function countDynamicExternalFunctions
input list<Function> inFncLst;
output Integer outDynLoadFuncs;
algorithm
outDynLoadFuncs:= matchcontinue(inFncLst)
local
list<Function> rest;
Function fn;
Integer i;
case({})
then
0;
case(EXTERNAL_FUNCTION(dynamicLoad=true)::rest)
equation
i = countDynamicExternalFunctions(rest);
then
intAdd(i,1);
case(fn::rest)
equation
i = countDynamicExternalFunctions(rest);
then
i;
end matchcontinue;
end countDynamicExternalFunctions;


end SimCode;
57 changes: 45 additions & 12 deletions Compiler/susan_codegen/SimCode/SimCodeC.tpl
Expand Up @@ -2357,13 +2357,20 @@ template functionHeader(Function fn, Boolean inFunc)
match fn
case FUNCTION(__) then
<<
<%functionHeaderNormal(underscorePath(name), functionArguments, outVars, inFunc)%>
<%functionHeaderBoxed(underscorePath(name), functionArguments, outVars, isBoxedFunction(fn))%>
<%functionHeaderNormal(underscorePath(name), functionArguments, outVars, inFunc, false)%>
<%functionHeaderBoxed(underscorePath(name), functionArguments, outVars, isBoxedFunction(fn), false)%>
>>
case EXTERNAL_FUNCTION(dynamicLoad=true) then
<<
<%functionHeaderNormal(underscorePath(name), funArgs, outVars, inFunc, true)%>
<%functionHeaderBoxed(underscorePath(name), funArgs, outVars, isBoxedFunction(fn), true)%>

<%extFunDefDynamic(fn)%>
>>
case EXTERNAL_FUNCTION(__) then
<<
<%functionHeaderNormal(underscorePath(name), funArgs, outVars, inFunc)%>
<%functionHeaderBoxed(underscorePath(name), funArgs, outVars, isBoxedFunction(fn))%>
<%functionHeaderNormal(underscorePath(name), funArgs, outVars, inFunc, false)%>
<%functionHeaderBoxed(underscorePath(name), funArgs, outVars, isBoxedFunction(fn), false)%>

<%extFunDef(fn)%>
>>
Expand Down Expand Up @@ -2460,16 +2467,16 @@ template recordDefinitionHeader(String origName, String encName, Integer numFiel
>>
end recordDefinitionHeader;

template functionHeaderNormal(String fname, list<Variable> fargs, list<Variable> outVars, Boolean inFunc)
::= functionHeaderImpl(fname, fargs, outVars, inFunc, false)
template functionHeaderNormal(String fname, list<Variable> fargs, list<Variable> outVars, Boolean inFunc, Boolean dynamicLoad)
::= functionHeaderImpl(fname, fargs, outVars, inFunc, false, dynamicLoad)
end functionHeaderNormal;

template functionHeaderBoxed(String fname, list<Variable> fargs, list<Variable> outVars, Boolean isBoxed)
template functionHeaderBoxed(String fname, list<Variable> fargs, list<Variable> outVars, Boolean isBoxed, Boolean dynamicLoad)
::= if acceptMetaModelicaGrammar() then
if isBoxed then '#define boxptr_<%fname%> _<%fname%><%\n%>' else functionHeaderImpl(fname, fargs, outVars, false, true)
if isBoxed then '#define boxptr_<%fname%> _<%fname%><%\n%>' else functionHeaderImpl(fname, fargs, outVars, false, true, dynamicLoad)
end functionHeaderBoxed;

template functionHeaderImpl(String fname, list<Variable> fargs, list<Variable> outVars, Boolean inFunc, Boolean boxed)
template functionHeaderImpl(String fname, list<Variable> fargs, list<Variable> outVars, Boolean inFunc, Boolean boxed, Boolean dynamicLoad)
"Generates function header for a Modelica/MetaModelica function. Generates a

boxed version of the header if boxed = true, otherwise a normal header"
Expand Down Expand Up @@ -2505,10 +2512,10 @@ template functionHeaderImpl(String fname, list<Variable> fargs, list<Variable> o
} <%fname%>_rettype<%boxStr%>;
<%inFnStr%>

<%fname%>_rettype<%boxStr%> <%boxPtrStr%>_<%fname%>(<%fargsStr%>);
<%if dynamicLoad then '' else '<%fname%>_rettype<%boxStr%> <%boxPtrStr%>_<%fname%>(<%fargsStr%>);'%>
>> else <<

void <%boxPtrStr%>_<%fname%>(<%fargsStr%>);
<%if dynamicLoad then '' else 'void <%boxPtrStr%>_<%fname%>(<%fargsStr%>);'%>
>>
end functionHeaderImpl;

Expand Down Expand Up @@ -2545,6 +2552,19 @@ case func as EXTERNAL_FUNCTION(__) then
'extern <%extReturnType(extReturn)%> <%fn_name%>(<%fargsStr%>);'
end extFunDef;

template extFunDefDynamic(Function fn)
"Generates function header for an external function."
::=
match fn
case func as EXTERNAL_FUNCTION(__) then
let fn_name = extFunctionName(extName, language)
let fargsStr = extFunDefArgs(extArgs, language)
<<
typedef <%extReturnType(extReturn)%> (*ptrT_<%fn_name%>)(<%fargsStr%>);
extern ptrT_<%fn_name%> ptr_<%fn_name%>;
>>
end extFunDefDynamic;

template extFunctionName(String name, String language)
::=
match language
Expand Down Expand Up @@ -2807,6 +2827,10 @@ case efn as EXTERNAL_FUNCTION(__) then
}
>>
<<
<% if dynamicLoad then
<<
ptrT_<%extFunctionName(extName, language)%> ptr_<%extFunctionName(extName, language)%>=NULL;
>> %>
<%fnBody%>

<% if inFunc then
Expand Down Expand Up @@ -3246,6 +3270,14 @@ template extFunCallC(Function fun, Text &preExp /*BUFP*/, Text &varDecls /*BUFP*
::=
match fun
case EXTERNAL_FUNCTION(__) then
let fname = if dynamicLoad then 'ptr_<%extFunctionName(extName, language)%>' else '<%extName%>'
let dynamicCheck = if dynamicLoad then
<<
if (<%fname%>==NULL) {
MODELICA_TERMINATE("dynamic external function <%extFunctionName(extName, language)%> not set!")
} else
>>
else ''
let args = (extArgs |> arg =>
extArg(arg, &preExp /*BUFC*/, &varDecls /*BUFD*/)
;separator=", ")
Expand All @@ -3256,7 +3288,8 @@ case EXTERNAL_FUNCTION(__) then
<<
<%extArgs |> arg => extFunCallVardecl(arg, &varDecls /*BUFD*/) ;separator="\n"%>
<%match extReturn case SIMEXTARG(__) then extFunCallVardecl(extReturn, &varDecls /*BUFD*/)%>
<%returnAssign%><%extName%>(<%args%>);
<%dynamicCheck%>
<%returnAssign%><%fname%>(<%args%>);
<%extArgs |> arg => extFunCallVarcopy(arg) ;separator="\n"%>
<%match extReturn case SIMEXTARG(__) then extFunCallVarcopy(extReturn)%>
>>
Expand Down
63 changes: 59 additions & 4 deletions Compiler/susan_codegen/SimCode/SimCodeFMU.tpl
Expand Up @@ -99,7 +99,7 @@ match simCode
case SIMCODE(modelInfo = MODELINFO(varInfo = vi as VARINFO(__))) then
let fmiVersion = '1.0'
let modelName = dotPath(modelInfo.name)
let modelIdentifier = underscorePath(modelInfo.name)
let modelIdentifier = fileNamePrefix
let description = ''
let author = ''
let version= ''
Expand Down Expand Up @@ -237,6 +237,8 @@ case MODELINFO(vars=SIMVARS(__)) then
<%vars.stringAliasVars |> var =>
ScalarVariable(var)
;separator="\n"%>
<%System.tmpTickReset(0)%>
<%externalFunctions(modelInfo)%>
</ModelVariables>
>>
end ModelVariables;
Expand Down Expand Up @@ -333,6 +335,27 @@ template ScalarVariableTypeRealAttribute(String unit, String displayUnit)
>>
end ScalarVariableTypeRealAttribute;

template externalFunctions(ModelInfo modelInfo)
"Generates external function definitions."
::=
match modelInfo
case MODELINFO(__) then
(functions |> fn => externalFunction(fn) ; separator="\n")
end externalFunctions;

template externalFunction(Function fn)
"Generates external function definitions."
::=
match fn
case EXTERNAL_FUNCTION(dynamicLoad=true) then
let fname = extFunctionName(extName, language)
<<
<ExternalFunction
name="<%fname%>"
valueReference="<%System.tmpTick()%>"/>
>>
end externalFunction;


template fmumodel_identifierFile(SimCode simCode, String guid)
"Generates code for ModelDescription file for FMU target."
Expand Down Expand Up @@ -401,7 +424,7 @@ let numberOfBooleans = intAdd(varInfo.numBoolAlgVars,intAdd(varInfo.numBoolParam
#define NUMBER_OF_INTEGERS <%numberOfIntegers%>
#define NUMBER_OF_STRINGS <%numberOfStrings%>
#define NUMBER_OF_BOOLEANS <%numberOfBooleans%>
#define NUMBER_OF_EXTERNALFUNCTIONS 0
#define NUMBER_OF_EXTERNALFUNCTIONS <%countDynamicExternalFunctions(functions)%>

// define variable data for model
<%System.tmpTickReset(0)%>
Expand All @@ -428,6 +451,8 @@ let numberOfBooleans = intAdd(varInfo.numBoolAlgVars,intAdd(varInfo.numBoolParam
#define STATES { <%vars.stateVars |> SIMVAR(__) => '<%cref(name)%>_' ;separator=", "%> }
#define STATESDERIVATIVES { <%vars.derivativeVars |> SIMVAR(__) => '<%cref(name)%>_' ;separator=", "%> }

<%System.tmpTickReset(0)%>
<%(functions |> fn => defineExternalFunction(fn) ; separator="\n")%>
>>
end ModelDefineData;

Expand All @@ -449,6 +474,17 @@ match simVar
>>
end DefineVariables;

template defineExternalFunction(Function fn)
"Generates external function definitions."
::=
match fn
case EXTERNAL_FUNCTION(dynamicLoad=true) then
let fname = extFunctionName(extName, language)
<<
#define $P<%fname%> <%System.tmpTick()%>
>>
end defineExternalFunction;

template setStartValues(ModelInfo modelInfo)
"Generates code in c file for function setStartValues() which will set start values for all variables."
::=
Expand Down Expand Up @@ -753,9 +789,11 @@ template setExternalFunction(ModelInfo modelInfo)
::=
match modelInfo
case MODELINFO(vars=SIMVARS(__)) then
let externalFuncs = setExternalFunctionsSwitch(functions)
<<
fmiStatus setExternalFunction(ModelInstance* c, const fmiValueReference vr, const void* value){
switch (vr) {
<%externalFuncs%>
default:
return fmiError;
}
Expand All @@ -765,6 +803,23 @@ case MODELINFO(vars=SIMVARS(__)) then
>>
end setExternalFunction;

template setExternalFunctionsSwitch(list<Function> functions)
"Generates external function definitions."
::=
(functions |> fn => setExternalFunctionSwitch(fn) ; separator="\n")
end setExternalFunctionsSwitch;

template setExternalFunctionSwitch(Function fn)
"Generates external function definitions."
::=
match fn
case EXTERNAL_FUNCTION(dynamicLoad=true) then
let fname = extFunctionName(extName, language)
<<
case $P<%fname%> : ptr_<%fname%>=(ptrT_<%fname%>)value; break;
>>
end setExternalFunctionSwitch;

template SwitchVars(SimVar simVar, String arrayName)
"Generates code for defining variables in c file for FMU target. "
::=
Expand Down Expand Up @@ -841,8 +896,8 @@ case SIMCODE(modelInfo=MODELINFO(__), makefileParams=MAKEFILE_PARAMS(__), simula
MAINFILE=<%fileNamePrefix%><% if acceptMetaModelicaGrammar() then ".conv"%>.c

.PHONY: <%fileNamePrefix%>
<%fileNamePrefix%>: $(MAINFILE) <%fileNamePrefix%>_functions.c <%fileNamePrefix%>_functions.h <%fileNamePrefix%>_records.c
<%\t%> $(CXX) -I. -o <%fileNamePrefix%>$(DLLEXT) $(MAINFILE) <%dirExtra%> <%libsPos1%> <%libsPos2%> -lsim -linteractive $(CFLAGS) $(SENDDATALIBS) $(LDFLAGS) <%match System.os() case "OSX" then "-lf2c" else "-Wl,-Bstatic -lf2c -Wl,-Bdynamic"%> <%fileNamePrefix%>_records.c
<%fileNamePrefix%>: $(MAINFILE) <%fileNamePrefix%>_FMU.c <%fileNamePrefix%>_functions.c <%fileNamePrefix%>_functions.h <%fileNamePrefix%>_records.c
<%\t%> $(CXX) -shared -I. -o <%fileNamePrefix%>$(DLLEXT) <%fileNamePrefix%>_FMU.c $(MAINFILE) <%dirExtra%> <%libsPos1%> <%libsPos2%> -lsim -linteractive $(CFLAGS) $(SENDDATALIBS) $(LDFLAGS) <%match System.os() case "OSX" then "-lf2c" else "-Wl,-Bstatic -lf2c -Wl,-Bdynamic"%> <%fileNamePrefix%>_records.c

<%\t%> mkdir -p <%fileNamePrefix%>
<%\t%> mkdir -p <%fileNamePrefix%>/binaries
Expand Down
6 changes: 6 additions & 0 deletions Compiler/susan_codegen/SimCode/SimCodeTV.mo
Expand Up @@ -358,6 +358,7 @@ package SimCode
list<String> libs;
String language;
Absyn.Info info;
Boolean dynamicLoad;
end EXTERNAL_FUNCTION;
record RECORD_CONSTRUCTOR
Absyn.Path name;
Expand Down Expand Up @@ -521,6 +522,11 @@ package SimCode
output String s;
end twodigit;

function countDynamicExternalFunctions
input list<Function> inFncLst;
output Integer outDynLoadFuncs;
end countDynamicExternalFunctions;

end SimCode;


Expand Down

0 comments on commit 781997c

Please sign in to comment.