Skip to content

Commit

Permalink
- do not evaluate functions if we do partial instantiation
Browse files Browse the repository at this point in the history
- handle smooth in Derive.mo (needed for Modelica.Media)
- replace constant with binding even if you cannot constant evaluate
- BackEnd/BackendDAECreate.mo (fixes to make some Media models simulate)
  + force inline of record = functionCall(...) in complex equations
  + handle normal equations in extendRecordEqns (as we have a recursive call)
- split function evaluation/generation outside of Ceval.cevalCallFunction
  to be easier to manage.


- FUTURE: we should treat the constant evaluation of subscripts and constant evaluation of component reference
  separately in Static.elabCref1 to be sure we always replace constants with their bindings (this will
  get Modelica.Electrical.Digital going and maybe others).



git-svn-id: https://openmodelica.org/svn/OpenModelica/trunk@10235 f25d12d1-65f4-0310-ae8a-bbce733d8d8e
  • Loading branch information
adrpo committed Oct 27, 2011
1 parent e5e4238 commit 32255d6
Show file tree
Hide file tree
Showing 10 changed files with 360 additions and 15 deletions.
34 changes: 34 additions & 0 deletions Compiler/BackEnd/BackendDAECreate.mo
Expand Up @@ -1239,6 +1239,30 @@ algorithm
list<BackendDAE.MultiDimEquation> arreqns;
DAE.ElementSource source;
Boolean b1,b2;
Absyn.Path fpath;
list<DAE.Exp> exps;
Boolean tuple_;
Boolean builtin;
DAE.InlineType inlineType;
DAE.TailCall tailCall;

// normal first try to force the inline of function calls and extend the equations
case (DAE.COMPLEX_EQUATION(lhs = e1, rhs = e2,source = source),funcs)
equation
// no MetaModelica
false = RTOpts.acceptMetaModelicaGrammar();
(e1_1,b1) = ExpressionSimplify.simplify(e1);
(e2_1,b2) = ExpressionSimplify.simplify(e2);
source = DAEUtil.addSymbolicTransformationSimplify(b1,source,e1,e1_1);
source = DAEUtil.addSymbolicTransformationSimplify(b2,source,e2,e2_1);
ty = Expression.typeof(e1_1);
i = Expression.sizeOf(ty);
(e1_1,source) = Inline.forceInlineExp(e1_1,(SOME(funcs),{DAE.NORM_INLINE()}),source);
(e2_1,source) = Inline.forceInlineExp(e2_1,(SOME(funcs),{DAE.NORM_INLINE()}),source);
// extend
((complexEqs,arreqns)) = extendRecordEqns(BackendDAE.COMPLEX_EQUATION(-1,e1_1,e2_1,source),funcs);
then
(complexEqs,arreqns);

// normal first try to inline function calls and extend the equations
case (DAE.COMPLEX_EQUATION(lhs = e1, rhs = e2,source = source),funcs)
Expand All @@ -1256,6 +1280,7 @@ algorithm
((complexEqs,arreqns)) = extendRecordEqns(BackendDAE.COMPLEX_EQUATION(-1,e1_1,e2_1,source),funcs);
then
(complexEqs,arreqns);

case (DAE.COMPLEX_EQUATION(lhs = e1, rhs = e2,source = source),funcs)
equation
(e1_1,b1) = ExpressionSimplify.simplify(e1);
Expand All @@ -1268,6 +1293,7 @@ algorithm
complexEqs = List.fill(BackendDAE.COMPLEX_EQUATION(-1,e1_1,e2_1,source), i);
then
(complexEqs,{});

// initial first try to inline function calls and extend the equations
case (DAE.INITIAL_COMPLEX_EQUATION(lhs = e1, rhs = e2,source = source),funcs)
equation
Expand All @@ -1284,6 +1310,7 @@ algorithm
((complexEqs,arreqns)) = extendRecordEqns(BackendDAE.COMPLEX_EQUATION(-1,e1_1,e2_1,source),funcs);
then
(complexEqs,arreqns);

case (DAE.INITIAL_COMPLEX_EQUATION(lhs = e1, rhs = e2,source = source),funcs)
equation
(e1_1,b1) = ExpressionSimplify.simplify(e1);
Expand All @@ -1296,6 +1323,7 @@ algorithm
complexEqs = List.fill(BackendDAE.COMPLEX_EQUATION(-1,e1_1,e2_1,source), i);
then
(complexEqs,{});

case (_,_)
equation
print("- BackendDAECreate.lowerComplexEqn failed!\n");
Expand Down Expand Up @@ -3785,6 +3813,12 @@ algorithm
multiEqs2 = listAppend(multiEqs,multiEqs1);
then
((complexEqs1,multiEqs2));

// due to recursive call above we might get normal equations here!
case (inEqn,funcs)
then
(({inEqn}, {}));

end match;
end extendRecordEqns;

Expand Down
6 changes: 6 additions & 0 deletions Compiler/BackEnd/Derive.mo
Expand Up @@ -501,6 +501,12 @@ algorithm
call2 = Expression.makeBuiltinCall("cross",{e1_1,e2},tp);
then
DAE.BINARY(call1,DAE.ADD_ARR(tp),call2);

case (DAE.CALL(path = fname as Absyn.IDENT("smooth"),expLst = {e1,e2},attr=DAE.CALL_ATTR(ty=tp)),inVariables)
equation
e2_1 = differentiateExpTime(e2, inVariables);
then
e2_1;

case (DAE.CALL(path = fname as Absyn.IDENT("transpose"),expLst=expl,attr=DAE.CALL_ATTR(ty=tp)),inVariables)
equation
Expand Down
145 changes: 144 additions & 1 deletion Compiler/FrontEnd/Ceval.mo
Expand Up @@ -1173,6 +1173,10 @@ algorithm
String error_Str;
DAE.Function func;
SCode.Restriction res;
SCode.Redeclare prefixRedeclare;
SCode.Replaceable prefixReplaceable;
SCode.Partial prefixPartial;
Boolean isReplaceable;

// External functions that are "known" should be evaluated without compilation, e.g. all math functions
case (cache,env,(e as DAE.CALL(path = funcpath,expLst = expl)),vallst,impl,st,msg)
Expand All @@ -1198,6 +1202,144 @@ algorithm
then
(cache,Values.RECORD(funcpath,vallst,varNames,-1),st);

// evaluate or generate non-partial and non-replaceable functions
case (cache,env, DAE.CALL(path = funcpath, attr = DAE.CALL_ATTR(builtin = false)), vallst, impl, st, msg)
equation
failure(cevalIsExternalObjectConstructor(cache, funcpath, env, msg));
Debug.fprintln("dynload", "CALL: try to evaluate or generate function: " +& Absyn.pathString(funcpath));

true = isCompleteFunction(cache, env, funcpath);

(cache, newval, st) = cevalCallFunctionEvaluateOrGenerate(inCache,inEnv,inExp,inValuesValueLst,impl,inSymTab,inMsg);

Debug.fprintln("dynload", "CALL: constant evaluation success: " +& Absyn.pathString(funcpath));
then
(cache, newval, st);

// partial and replaceable functions should not be evaluated!
case (cache,env, DAE.CALL(path = funcpath, attr = DAE.CALL_ATTR(builtin = false)), vallst, impl, st, msg)
equation
failure(cevalIsExternalObjectConstructor(cache, funcpath, env, msg));
Debug.fprintln("dynload", "CALL: try to evaluate or generate function: " +& Absyn.pathString(funcpath));

false = isCompleteFunction(cache, env, funcpath);

Debug.fprintln("dynload", "CALL: constant evaluation failed: " +& Absyn.pathString(funcpath));
then
fail();

end matchcontinue;
end cevalCallFunction;

protected function isCompleteFunction
"a function is complete if is:
- not partial
- not replaceable (without redeclare)
- replaceable and called functions are not partial or not replaceable (without redeclare)"
input Env.Cache inCache;
input Env.Env inEnv;
input Absyn.Path inFuncPath;
output Boolean isComplete;
algorithm
isComplete := matchcontinue(inCache, inEnv, inFuncPath)
local
Env.Cache cache;
Env.Env env;
SCode.Element c;
String name;
Absyn.Path fpath;
list<Absyn.Path> functionDependencies;
list<Boolean> bLst;
list<SCode.AlgorithmSection> algs;
list<SCode.Element> els;
Option<SCode.ExternalDecl> extDeclOpt;

// if is partial instantiation no function evaluation/generation
case (cache, env, fpath)
equation
true = System.getPartialInstantiation();
then
false;

// partial functions are not complete!
case (cache, env, fpath)
equation
(_, SCode.CLASS(partialPrefix = SCode.PARTIAL()), _) = Lookup.lookupClass(cache, env, fpath, true);
then
false;

// replaceable functions are not fine if they don't have an algorithm section!
case (cache, env, fpath)
equation
(_,
c as SCode.CLASS(prefixes = SCode.PREFIXES(redeclarePrefix = SCode.NOT_REDECLARE(), replaceablePrefix = SCode.REPLACEABLE(_))),
_) =
Lookup.lookupClass(cache, env, fpath, true);
then
false;

case (cache, env, fpath)
then true;

end matchcontinue;
end isCompleteFunction;

protected function cevalCallFunctionEvaluateOrGenerate
"This function evaluates CALL expressions, i.e. function calls.
They are currently evaluated by generating code for the function and
then dynamicly load the function and call it."
input Env.Cache inCache;
input Env.Env inEnv;
input DAE.Exp inExp;
input list<Values.Value> inValuesValueLst;
input Boolean impl;
input Option<Interactive.SymbolTable> inSymTab;
input Msg inMsg;
output Env.Cache outCache;
output Values.Value outValue;
output Option<Interactive.SymbolTable> outSymTab;
algorithm
(outCache,outValue,outSymTab) := matchcontinue (inCache,inEnv,inExp,inValuesValueLst,impl,inSymTab,inMsg)
local
Values.Value newval;
list<Env.Frame> env;
DAE.Exp e;
Absyn.Path funcpath;
list<DAE.Exp> expl;
Boolean builtin;
list<Values.Value> vallst;
Msg msg;
Env.Cache cache;
list<Interactive.CompiledCFunction> cflist;
Option<Interactive.SymbolTable> st;
Absyn.Program p;
Integer libHandle, funcHandle;
String fNew,fOld;
Real buildTime, edit, build;
AbsynDep.Depends aDep;
Option<list<SCode.Element>> a;
list<Interactive.InstantiatedClass> b;
list<Interactive.Variable> c;
list<Interactive.CompiledCFunction> cf;
list<Interactive.LoadedFile> lf;
Absyn.TimeStamp ts;
String funcstr,f;
list<Interactive.CompiledCFunction> newCF;
String name;
Boolean ppref, fpref, epref;
Absyn.ClassDef body;
Absyn.Info info;
Absyn.Within w;
Absyn.Path complexName;
list<Absyn.Path> functionDependencies;
list<Expression.Var> varLst;
list<String> varNames;
SCode.Element sc;
SCode.ClassDef cdef;
String error_Str;
DAE.Function func;
SCode.Restriction res;

// try function interpretation
case (cache,env, DAE.CALL(path = funcpath, attr = DAE.CALL_ATTR(builtin = false)), vallst, impl, st, msg)
equation
Expand Down Expand Up @@ -1347,8 +1489,9 @@ algorithm
Debug.fprint("failtrace", "- codegeneration is turned off. switch \"nogen\" flag off\n");
then
fail();

end matchcontinue;
end cevalCallFunction;
end cevalCallFunctionEvaluateOrGenerate;

protected function cevalIsExternalObjectConstructor
input Env.Cache cache;
Expand Down
61 changes: 61 additions & 0 deletions Compiler/FrontEnd/Inline.mo
Expand Up @@ -940,6 +940,32 @@ algorithm
end matchcontinue;
end inlineExp;

public function forceInlineExp "
function: inlineExp
inlines calls in an DAE.Exp"
input DAE.Exp inExp;
input Functiontuple inElementList;
input DAE.ElementSource source;
output DAE.Exp outExp;
output DAE.ElementSource outSource;
algorithm
(outExp,outSource) := matchcontinue (inExp,inElementList,source)
local
Functiontuple fns;
DAE.Exp e,e_1,e_2;
Boolean b;
case (e,fns,source)
equation
((e_1,(fns,b))) = Expression.traverseExp(e,forceInlineCall,(fns,false));
source = DAEUtil.condAddSymbolicTransformation(b,source,DAE.OP_INLINE(e,e_1));
(e_2,b) = ExpressionSimplify.simplify(e_1);
source = DAEUtil.addSymbolicTransformationSimplify(b,source,e_1,e_2);
then
(e_2,source);
else (inExp,source);
end matchcontinue;
end forceInlineExp;

protected function inlineExps "
function: inlineExp
inlines calls in an DAE.Exp"
Expand Down Expand Up @@ -1001,6 +1027,41 @@ algorithm
end matchcontinue;
end inlineCall;

public function forceInlineCall
"function: inlineCall
replaces an inline call with the expression from the function"
input tuple<DAE.Exp, tuple<Functiontuple,Boolean>> inTuple;
output tuple<DAE.Exp, tuple<Functiontuple,Boolean>> outTuple;
algorithm
outTuple := matchcontinue(inTuple)
local
Functiontuple fns,fns1;
list<DAE.Element> fn;
Absyn.Path p;
list<DAE.Exp> args;
Boolean tup,built;
DAE.ExpType t;
list<DAE.ComponentRef> crefs;
list<tuple<DAE.ComponentRef, DAE.Exp>> argmap;
DAE.Exp newExp,newExp1, e1;
DAE.InlineType inlineType;
case ((e1 as DAE.CALL(p,args,DAE.CALL_ATTR(inlineType=inlineType)),(fns,_)))
equation
fn = getFunctionBody(p,fns);
crefs = List.map(fn,getInputCrefs);
crefs = List.select(crefs,removeWilds);
argmap = List.threadTuple(crefs,args);
argmap = extendCrefRecords(argmap);
newExp = getRhsExp(fn);
((newExp,argmap)) = Expression.traverseExp(newExp,replaceArgs,argmap);
// for inlinecalls in functions
((newExp1,(fns1,_))) = Expression.traverseExp(newExp,forceInlineCall,(fns,true));
then
((newExp1,(fns,true)));
else inTuple;
end matchcontinue;
end forceInlineCall;

protected function checkInlineType "
Author: Frenkel TUD, 2010-05"
input DAE.InlineType inIT;
Expand Down

0 comments on commit 32255d6

Please sign in to comment.