diff --git a/Compiler/BackEnd/BackendDAEUtil.mo b/Compiler/BackEnd/BackendDAEUtil.mo index ccc14e0b713..9ee385485ee 100644 --- a/Compiler/BackEnd/BackendDAEUtil.mo +++ b/Compiler/BackEnd/BackendDAEUtil.mo @@ -492,6 +492,14 @@ algorithm outSystem := BackendDAE.EQSYSTEM(vars, eqns, m, mt, matching, inSystem.stateSets, inSystem.partitionKind, removedEqs); end copyEqSystem; +public function mergeEqSystems + input BackendDAE.EqSystem System1; + input output BackendDAE.EqSystem System2; +algorithm + System2.orderedEqs := BackendEquation.mergeEquationArray(System1.orderedEqs,System2.orderedEqs); + System2.orderedVars := BackendVariable.mergeVariables(System1.orderedVars,System2.orderedVars); +end mergeEqSystems; + public function copyBackendDAEShared " author: Frenkel TUD, wbraun Copy the shared part of an BackendDAE to avoid changes in diff --git a/Compiler/BackEnd/BackendInline.mo b/Compiler/BackEnd/BackendInline.mo index fd1918ab3ea..39a6f6b1656 100644 --- a/Compiler/BackEnd/BackendInline.mo +++ b/Compiler/BackEnd/BackendInline.mo @@ -46,10 +46,21 @@ public import Inline; public import SCode; public import Values; -protected import Debug; -protected import ExpressionDump; -protected import Flags; -protected import List; +protected + import BackendVarTransform; + import BackendDAEUtil; + import BackendDump; + import BackendEquation; + import BackendVariable; + import BackendDAEOptimize; + import ComponentReference; + import Debug; + import DAEDump; + import DAEUtil; + import ExpressionDump; + import Flags; + import InlineArrayEquations; + import List; // ============================================================================= // late inline functions stuff @@ -70,7 +81,11 @@ public function normalInlineFunction input BackendDAE.BackendDAE inDAE; output BackendDAE.BackendDAE outDAE; algorithm - outDAE := inlineCalls({DAE.NORM_INLINE()}, inDAE); + if Flags.getConfigEnum(Flags.INLINE_METHOD) == 1 then + outDAE := inlineCalls({DAE.NORM_INLINE()}, inDAE); + else + outDAE := inlineCallsBDAE({DAE.NORM_INLINE()}, inDAE); + end if; end normalInlineFunction; // ============================================================================= @@ -102,7 +117,7 @@ algorithm outBackendDAE := BackendDAE.DAE(eqs, shared); else if Flags.isSet(Flags.FAILTRACE) then - Debug.traceln("Inline.inlineCalls failed"); + Debug.traceln("BackendInline.inlineCalls failed"); end if; fail(); end try; @@ -677,5 +692,632 @@ algorithm end matchcontinue; end inlineReinitStmt; +// ============================================================================= +// inline append functions +// +// ============================================================================= + +protected function inlineCallsBDAE +"searches for calls where the inline flag is true, and inlines them" + input list inITLst; + input BackendDAE.BackendDAE inBackendDAE; + output BackendDAE.BackendDAE outBackendDAE; +protected + list itlst; + Inline.Functiontuple tpl; + BackendDAE.EqSystems eqs; + BackendDAE.Shared shared; +algorithm + try + + if Flags.isSet(Flags.DUMPBACKENDINLINE) then + if Flags.getConfigEnum(Flags.INLINE_METHOD) == 1 then + print("\n############ BackendInline Method: replace ############"); + elseif Flags.getConfigEnum(Flags.INLINE_METHOD) == 2 then + print("\n############ BackendInline Method: append ############"); + end if; + end if; + + shared := inBackendDAE.shared; + eqs := inBackendDAE.eqs; + tpl := (SOME(shared.functionTree), inITLst); + if Flags.getConfigEnum(Flags.INLINE_METHOD) == 1 then + eqs := List.map1(eqs, BackendInline.inlineEquationSystem, tpl); + elseif Flags.getConfigEnum(Flags.INLINE_METHOD) == 2 then + eqs := List.map1(eqs, inlineEquationSystemAppend, (tpl,shared)); + end if; + if Flags.isSet(Flags.DUMPBACKENDINLINE) then + BackendDump.dumpEqSystems(eqs, "Result DAE after Inline."); + end if; + // TODO: use new BackendInline also for other parts + shared.knownVars := BackendInline.inlineVariables(shared.knownVars, tpl); + shared.externalObjects := BackendInline.inlineVariables(shared.externalObjects, tpl); + shared.initialEqs := BackendInline.inlineEquationArray(shared.initialEqs, tpl); + shared.removedEqs := BackendInline.inlineEquationArray(shared.removedEqs, tpl); + + outBackendDAE := BackendDAE.DAE(eqs, shared); + else + if Flags.isSet(Flags.FAILTRACE) then + Debug.traceln("BackendInline.inlineCallsBDAE failed"); + end if; + fail(); + end try; + + // fix "tuple = tuple" expression after inline functions + outBackendDAE := BackendDAEOptimize.simplifyComplexFunction1(outBackendDAE, false); +end inlineCallsBDAE; + + +protected function inlineEquationSystemAppend + input BackendDAE.EqSystem eqs; + input tuple tpl_shard; + output BackendDAE.EqSystem oeqs = eqs; +protected + BackendDAE.EqSystem new; + Boolean inlined=true; + BackendDAE.EquationArray eqnsArray; + BackendDAE.Shared shared; + Inline.Functiontuple tpl; +algorithm + (tpl, shared) := tpl_shard; + //inlineVariables(oeqs.orderedVars, tpl); + (eqnsArray, new, inlined, shared) := inlineEquationArrayAppend(oeqs.orderedEqs, tpl, shared); + //inlineEquationArray(oeqs.removedEqs, tpl); + if inlined then + oeqs.orderedEqs := eqnsArray; + new := inlineEquationSystemAppend(new, (tpl, shared)); + oeqs := BackendDAEUtil.mergeEqSystems(new, oeqs); + end if; +end inlineEquationSystemAppend; + +protected function inlineEquationArrayAppend " +function: inlineEquationArray + inlines function calls in an equation array" + input BackendDAE.EquationArray inEquationArray; + input Inline.Functiontuple fns; + input BackendDAE.Shared iShared; + output BackendDAE.EquationArray outEquationArray; + output BackendDAE.EqSystem outEqs; + output Boolean oInlined; + output BackendDAE.Shared shared = iShared; +protected + Integer i1,i2,size; + array> eqarr; +algorithm + try + BackendDAE.EQUATION_ARRAY(size,i1,i2,eqarr) := inEquationArray; + (outEqs, oInlined, shared) := inlineEquationOptArrayAppend(inEquationArray, fns, shared); + outEquationArray := BackendDAE.EQUATION_ARRAY(size,i1,i2,eqarr); + else + if Flags.isSet(Flags.FAILTRACE) then + Debug.trace("BackendInline.inlineEquationArrayAppend failed\n"); + end if; + end try; + +end inlineEquationArrayAppend; + +protected function inlineEquationOptArrayAppend +"functio: inlineEquationrOptArray + inlines calls in a equation option" + input BackendDAE.EquationArray inEqnArray; + input Inline.Functiontuple fns; + input BackendDAE.Shared iShared; + output BackendDAE.EqSystem outEqs; + output Boolean oInlined = false; + output BackendDAE.Shared shared = iShared; +protected + Option eqn; + Boolean inlined; + BackendDAE.EqSystem tmpEqs; +algorithm + outEqs := BackendDAEUtil.createEqSystem( BackendVariable.listVar({}), BackendEquation.listEquation({})); + for i in 1:inEqnArray.numberOfElement loop + (eqn, tmpEqs, inlined, shared) := inlineEqOptAppend(inEqnArray.equOptArr[i], fns, shared); + if inlined then + outEqs := BackendDAEUtil.mergeEqSystems(tmpEqs, outEqs); + arrayUpdate(inEqnArray.equOptArr, i, eqn); + oInlined := true; + end if; + end for; +end inlineEquationOptArrayAppend; + +protected function inlineEqOptAppend " +function: inlineEqOpt + inlines function calls in equations" + input Option inEquationOption; + input Inline.Functiontuple inElementList; + input BackendDAE.Shared iShared; + output Option outEquationOption; + output BackendDAE.EqSystem outEqs; + output Boolean inlined; + output BackendDAE.Shared shared = iShared; +protected + BackendDAE.Equation eqn, eqn1; +algorithm + outEqs := BackendDAEUtil.createEqSystem( BackendVariable.listVar({}), BackendEquation.listEquation({})); + if isSome(inEquationOption) then + SOME(eqn) := inEquationOption; + (eqn1,outEqs,inlined,shared) := inlineEqAppend(eqn,inElementList,outEqs,shared); + + // debug + if Flags.isSet(Flags.DUMPBACKENDINLINE_VERBOSE) and inlined then + print("Equation before inline: "+BackendDump.equationString(eqn)+"\n"); + BackendDump.dumpEqSystem(outEqs, "Tmp DAE after Inline Eqn: "+BackendDump.equationString(eqn1)+"\n"); + end if; + outEquationOption := SOME(eqn1); + else + outEquationOption := NONE(); + inlined := false; + end if; +end inlineEqOptAppend; + +protected function inlineEqAppend " + inlines function calls in equations" + input BackendDAE.Equation inEquation; + input Inline.Functiontuple fns; + input BackendDAE.EqSystem inEqs; + input BackendDAE.Shared iShared; + output BackendDAE.Equation outEquation; + output BackendDAE.EqSystem outEqs; + output Boolean inlined; + output BackendDAE.Shared shared = iShared; +algorithm + (outEquation,outEqs,inlined) := matchcontinue(inEquation) + local + DAE.Exp e1,e2; + DAE.ElementSource source; + Boolean b1,b2,b3; + BackendDAE.EquationAttributes attr; + BackendDAE.Equation eqn; + Integer size; + list explst; + DAE.ComponentRef cref; + BackendDAE.WhenEquation weq,weq_1; + list stmts, stmts1; + DAE.Expand crefExpand; + list> eqnslst; + list eqns; + + case BackendDAE.EQUATION(e1,e2,source,attr) + equation + (e1,source,outEqs,b1,shared) = inlineCallsAppend(e1,fns,source,inEqs,shared); + (e2,source,outEqs,b2,shared) = inlineCallsAppend(e2,fns,source,outEqs,shared); + b3 = b1 or b2; + then + (BackendEquation.generateEquation(e1,e2,source,attr),outEqs,b3); + + case BackendDAE.COMPLEX_EQUATION(left=e1, right=e2, source=source, attr=attr) + equation + (e1,source,outEqs,b1,shared) = inlineCallsAppend(e1,fns,source,inEqs,shared); + (e2,source,outEqs,b2,shared) = inlineCallsAppend(e2,fns,source,outEqs,shared); + b3 = b1 or b2; + if b2 and Expression.isScalar(e1) and Expression.isTuple(e2) then + e2 = DAE.TSUB(e2, 1, Expression.typeof(e1)); + end if; + then + (BackendEquation.generateEquation(e1,e2,source,attr),outEqs,b3); + + case BackendDAE.ARRAY_EQUATION(left=e1, right=e2, source=source, attr=attr) + equation + (e1,source,outEqs,b1,shared) = inlineCallsAppend(e1,fns,source,inEqs,shared); + (e2,source,outEqs,b2,shared) = inlineCallsAppend(e2,fns,source,outEqs,shared); + b3 = b1 or b2; + then + (BackendEquation.generateEquation(e1,e2,source,attr),outEqs,b3); + + case BackendDAE.SOLVED_EQUATION(cref,e2,source,attr) + equation + (e2,source,outEqs,b2,shared) = inlineCallsAppend(e2,fns,source,inEqs,shared); + then + (BackendDAE.SOLVED_EQUATION(cref,e2,source,attr),outEqs,b2); + + case BackendDAE.RESIDUAL_EQUATION(e1,source,attr) + equation + (e1,source,outEqs,b1,shared) = inlineCallsAppend(e1,fns,source,inEqs,shared); + then + (BackendDAE.RESIDUAL_EQUATION(e1,source,attr),outEqs,b1); + + case eqn as BackendDAE.ALGORITHM(size, DAE.ALGORITHM_STMTS(statementLst=stmts),source,crefExpand,attr) + equation + (stmts1,b1) = Inline.inlineStatements(stmts,fns,{},false); + if b1 then + eqn = BackendDAE.ALGORITHM(size,DAE.ALGORITHM_STMTS(stmts1),source,crefExpand,attr); + end if; + then + (eqn,inEqs,b1); + + case eqn as BackendDAE.WHEN_EQUATION(size,weq,source,attr) + equation + (weq_1,source,b1) = inlineWhenEq(weq,fns,source); + if b1 then + eqn = BackendDAE.WHEN_EQUATION(size,weq_1,source,attr); + end if; + then + (eqn,inEqs, b1); + + case eqn as BackendDAE.IF_EQUATION(explst,eqnslst,eqns,source,attr) + equation + (explst,source,b1) = Inline.inlineExps(explst,fns,source); + (eqnslst,b2) = inlineEqsLst(eqnslst,fns,{},false); + (eqns,b3) = inlineEqs(eqns,fns,{},false); + b3 = b1 or b2 or b3; + if b3 then + eqn = BackendDAE.IF_EQUATION(explst,eqnslst,eqns,source,attr); + end if; + then + (eqn, inEqs, b3); + + else (inEquation,inEqs,false); + + end matchcontinue; +end inlineEqAppend; + +protected function inlineCallsAppend " +function: inlineCalls + inlines calls in a DAE.Exp" + input DAE.Exp inExp; + input Inline.Functiontuple fns; + input DAE.ElementSource inSource; + input BackendDAE.EqSystem inEqs; + input BackendDAE.Shared iShared; + output DAE.Exp outExp; + output DAE.ElementSource outSource; + output BackendDAE.EqSystem outEqs; + output Boolean inlined; + output BackendDAE.Shared shared = iShared; +algorithm + (outExp,outSource,outEqs,inlined) := matchcontinue (inExp) + local + DAE.Exp e,e1,e2; + DAE.ElementSource source; + list assrtLst; + Boolean b; + + case (e) + equation + (e1,(_,outEqs,b,_)) = Expression.traverseExpBottomUp(e,inlineCallsWork,(fns,inEqs,false,false)); + //source = DAEUtil.addSymbolicTransformation(b, inSource,DAE.OP_INLINE(DAE.PARTIAL_EQUATION(e),DAE.PARTIAL_EQUATION(e1))); + source = inSource; + e2 = e1; + //(DAE.PARTIAL_EQUATION(e2),source) = ExpressionSimplify.simplifyAddSymbolicOperation(DAE.PARTIAL_EQUATION(e1), source); + // debug + if Flags.isSet(Flags.DUMPBACKENDINLINE_VERBOSE) then + print("\ninExp: " + ExpressionDump.printExpStr(inExp)); + print("\noutExp: " + ExpressionDump.printExpStr(e2)); + end if; + then + (e2,source,outEqs,b); + + else (inExp,inSource,inEqs,false); + end matchcontinue; +end inlineCallsAppend; + +protected function inlineCallsWork +"replaces an expression call with the statements from the function" + input DAE.Exp inExp; + input tuple inTuple; + output DAE.Exp outExp; + output tuple outTuple; +algorithm + (outExp,outTuple) := matchcontinue (inExp,inTuple) + local + Inline.Functiontuple fns,fns1; + list fn; + Absyn.Path p; + list args; + list outputCrefs; + list> argmap; + list lst_cr; + DAE.ElementSource source; + DAE.Exp newExp,newExp1, e1, cond, msg, level, newAssrtCond, newAssrtMsg, newAssrtLevel, e2, e3; + DAE.InlineType inlineType; + DAE.Statement assrt; + HashTableCG.HashTable checkcr; + list stmts,assrtStmts, assrtLstIn, assrtLst; + Boolean generateEvents, b, b1; + Boolean inCoplexFunction, inArrayEq; + Option comment; + DAE.Type ty; + String funcname; + BackendDAE.EqSystem eqSys, newEqSys; + Boolean insideIfExp; + + case (e1 as DAE.IFEXP(), (fns,eqSys,b,insideIfExp)) + then fail(); + + case (DAE.CALL(attr=DAE.CALL_ATTR(builtin=true)),_) + then (inExp,inTuple); + + case (e1 as DAE.CALL(p,args,DAE.CALL_ATTR(ty=ty,inlineType=inlineType)),(fns,eqSys,b,false)) + guard Inline.checkInlineType(inlineType,fns) and Flags.getConfigEnum(Flags.INLINE_METHOD)==2 + equation + (fn,comment) = Inline.getFunctionBody(p,fns); + funcname = Util.modelicaStringToCStr(Absyn.pathString(p), false); + if Flags.isSet(Flags.DUMPBACKENDINLINE_VERBOSE) then + print("Inline Function " +funcname+" type: "+DAEDump.dumpInlineTypeStr(inlineType)+"\n"); + print("in : " + ExpressionDump.printExpStr(inExp) + "\n"); + end if; + + // get inputs, body and output + (outputCrefs, newEqSys) = createEqnSysfromFunction(fn,args,funcname); + newExp = Expression.makeTuple(list( Expression.crefExp(cr) for cr in outputCrefs)); + if Flags.isSet(Flags.DUMPBACKENDINLINE_VERBOSE) then + print("out: " + ExpressionDump.printExpStr(newExp) + "\n"); + end if; + + // MSL 3.2.1 need GenerateEvents to disable this + if not Inline.hasGenerateEventsAnnotation(comment) then + _ = BackendDAEUtil.traverseBackendDAEExpsEqSystemWithUpdate(newEqSys, addNoEvent, false); + end if; + newEqSys = BackendDAEUtil.mergeEqSystems(newEqSys, eqSys); + then + (newExp,(fns,newEqSys,true,false)); + + //fallback use old implementation + case (e1 as DAE.CALL(p,args,DAE.CALL_ATTR(ty=ty,inlineType=inlineType)),(fns,eqSys,b,insideIfExp)) + equation + //TODO sace assertLst + (newExp, _) = Inline.inlineCall(inExp, {}, fns); + + if Flags.isSet(Flags.DUMPBACKENDINLINE_VERBOSE) then + funcname = Util.modelicaStringToCStr(Absyn.pathString(p), false); + print("\nBackendInline fallback replace implementation: " +funcname+" type: " +DAEDump.dumpInlineTypeStr(inlineType)+"\n"); + print("in : " + ExpressionDump.printExpStr(inExp) + "\n"); + print("out: " + ExpressionDump.printExpStr(newExp) + "\n"); + end if; + then (newExp,(fns,eqSys,b,insideIfExp)); + + else (inExp,inTuple); + end matchcontinue; +end inlineCallsWork; + +function addNoEvent + input DAE.Exp inExp; + input Boolean inB; + output DAE.Exp outExp; + output Boolean outB = inB; +algorithm + outExp := Expression.addNoEventToRelationsAndConds(inExp); + outExp := Expression.addNoEventToEventTriggeringFunctions(outExp); +end addNoEvent; + +protected function createReplacementVariables + input DAE.ComponentRef inCref; + input String funcName; + input BackendVarTransform.VariableReplacements inRepls; + output DAE.ComponentRef crVar; + output list outVars = {}; + output BackendVarTransform.VariableReplacements outRepls = inRepls; +protected + DAE.Exp eVar, e; + list arrExp; + list crefs, crefs1; + DAE.ComponentRef cr; + BackendDAE.Var var; +algorithm + // create variable and expression from cref + var := BackendVariable.createTmpVar(inCref, funcName); + crVar := BackendVariable.varCref(var); + eVar := Expression.crefExp(crVar); + + //TODO: handle record cases + false := Expression.isRecord(eVar); + + // create top-level replacement + outRepls := BackendVarTransform.addReplacement(outRepls, inCref, eVar, NONE()); + + // handle array cases for replacements + crefs := ComponentReference.expandCref(inCref, false); + crefs1 := ComponentReference.expandCref(crVar, false); + try + arrExp := Expression.getArrayOrRangeContents(eVar); + else + arrExp := {eVar}; + end try; + + // error handling + if listLength(crefs) <> listLength(arrExp) then + if Flags.isSet(Flags.FAILTRACE) then + Debug.traceln("BackendInline.createReplacementVariables failed with array handling "+ExpressionDump.printExpStr(eVar)+"\n"); + end if; + fail(); + end if; + + // add every array scalar to replacements + for c in crefs loop + cr :: crefs1 := crefs1; + e :: arrExp := arrExp; + var.varName := cr; + outVars := var::outVars; + outRepls := BackendVarTransform.addReplacement(outRepls, c, e, NONE()); + end for; + outVars := listReverse(outVars); +end createReplacementVariables; + +protected function createEqnSysfromFunction + input list fns; + input list inArgs; + input String funcname; + output list oOutput = {}; + output BackendDAE.EqSystem outEqs; +protected + list args = inArgs, left_lst; + BackendVarTransform.VariableReplacements repl; + list fnInputs = {}; + DAE.Type tp; + list> argmap; + HashTableCG.HashTable checkcr; + list tmpOutput = {}; + DAE.ComponentRef cr; + BackendDAE.Var var; + BackendDAE.IncidenceMatrix m; + array ass1, ass2; + list eqlst = {}; +algorithm + if Flags.isSet(Flags.DUMPBACKENDINLINE_VERBOSE) then + print("\ncreate EqnSys from function: "+funcname); + end if; + outEqs := BackendDAEUtil.createEqSystem( BackendVariable.listVar({}), BackendEquation.listEquation({})); + repl := BackendVarTransform.emptyReplacements(); + + for fn in fns loop + _ := match(fn) + local + DAE.ComponentRef crVar; + list st; + DAE.Exp eVar, eBind, e; + list arrExp; + BackendDAE.Equation eq; + Integer varDim; + list crefs; + Integer n,i; + DAE.Dimensions dims; + DAE.Dimension dim; + list varLst; + + // assume inArgs is syncron to fns.inputs + case (DAE.VAR(componentRef=cr,direction=DAE.INPUT(),kind=DAE.VARIABLE())) + algorithm + fnInputs := cr :: fnInputs; + then (); + + //fns.outputs + case DAE.VAR(componentRef=cr,direction=DAE.OUTPUT(),kind=DAE.VARIABLE()) + guard (not Expression.isRecordType(ComponentReference.crefTypeFull(cr))) and ComponentReference.crefDepth(cr) > 0 + algorithm + // create variables + (crVar, varLst, repl) := createReplacementVariables(cr, funcname, repl); + outEqs := BackendVariable.addVarsDAE(varLst, outEqs); + // collect output variables + oOutput := crVar::oOutput; + then (); + + case (DAE.VAR(componentRef=cr,protection=DAE.PROTECTED(),binding=NONE())) + guard not Expression.isRecordType(ComponentReference.crefTypeFull(cr)) + algorithm + // create variables + (crVar, varLst, repl) := createReplacementVariables(cr, funcname, repl); + varLst := list(BackendVariable.setVarTS(_var, SOME(BackendDAE.AVOID())) for _var in varLst); + outEqs := BackendVariable.addVarsDAE(varLst, outEqs); + then (); + + case (DAE.VAR(componentRef=cr,protection=DAE.PROTECTED(),binding=SOME(eBind))) + guard not Expression.isRecordType(ComponentReference.crefTypeFull(cr)) + algorithm + // create variables + (crVar, varLst, repl) := createReplacementVariables(cr, funcname, repl); + // add variables + eVar := Expression.crefExp(crVar); + varLst := list(BackendVariable.setVarTS(_var, SOME(BackendDAE.AVOID())) for _var in varLst); + outEqs := BackendVariable.addVarsDAE(varLst, outEqs); + // add equation for binding + eq := BackendEquation.generateEquation(eVar,eBind); + outEqs := BackendEquation.equationAddDAE(eq, outEqs); + then (); + + case (DAE.ALGORITHM(algorithm_ = DAE.ALGORITHM_STMTS(st))) + equation + eqlst = List.map(st, BackendEquation.statementEq); + outEqs = BackendEquation.equationsAddDAE(eqlst, outEqs); + then (); + end match; + end for; + + // bring output variables in the right order + oOutput := listReverse(oOutput); + + /* TODO: remove this check for a square system */ + if (BackendDAEUtil.systemSize(outEqs) <> BackendVariable.daenumVariables(outEqs)) then + if Flags.isSet(Flags.FAILTRACE) then + Debug.trace("newBackendInline.createEqnSysfromFunction failed for function " + funcname + "with different sizes\n"); + print(intString(BackendDAEUtil.systemSize(outEqs)) + " <> " + intString(BackendVariable.daenumVariables(outEqs))); + end if; + fail(); + end if; + + // debug + if Flags.isSet(Flags.DUMPBACKENDINLINE_VERBOSE) then + print("\noriginal function body of: "+funcname); + BackendDump.printEqSystem(outEqs); + print("\nDump replacements: "); + BackendVarTransform.dumpReplacements(repl); + end if; + + // scalarize array equations + outEqs.orderedEqs := BackendEquation.listEquation(InlineArrayEquations.getScalarArrayEqns(BackendEquation.equationList(outEqs.orderedEqs))); + + // replace protected and output variables in function body + outEqs := BackendVarTransform.performReplacementsEqSystem(outEqs, repl); + + // debug + if Flags.isSet(Flags.DUMPBACKENDINLINE_VERBOSE) then + print("\n replaced protected and output for: "+funcname); + BackendDump.printEqSystem(outEqs); + end if; + + + // replace inputs variables + argmap := List.threadTuple(listReverse(fnInputs), args); + (argmap,checkcr) := Inline.extendCrefRecords(argmap, HashTableCG.emptyHashTable()); + BackendDAEUtil.traverseBackendDAEExpsEqSystemWithUpdate(outEqs, replaceArgs, (argmap,checkcr,true)); + + + // debug + if Flags.isSet(Flags.DUMPBACKENDINLINE_VERBOSE) then + print("\nreplaced input arguments for: "+funcname); + BackendDump.printEqSystem(outEqs); + end if; + +end createEqnSysfromFunction; + +protected function addReplacement + input DAE.ComponentRef iCr; + input DAE.Exp iExp; + input BackendVarTransform.VariableReplacements iRepl; + output BackendVarTransform.VariableReplacements oRepl; +algorithm + oRepl := match(iCr,iExp,iRepl) + local + DAE.Type tp; + BackendVarTransform.VariableReplacements repl; + list crefs; + list arrExp; + DAE.Exp e; + + case (DAE.CREF_IDENT(identType=tp),_,_) + guard not Expression.isRecordType(tp) and not Expression.isArrayType(tp) + then BackendVarTransform.addReplacement(iRepl, iCr, iExp, NONE()); + + case (DAE.CREF_IDENT(identType=tp),_,_) + guard Expression.isArrayType(tp) + algorithm + crefs := ComponentReference.expandCref(iCr, false); + repl := iRepl; + arrExp := Expression.getArrayOrRangeContents(iExp); + for c in crefs loop + e :: arrExp := arrExp; + repl := BackendVarTransform.addReplacement(repl, c, e, NONE()); + end for; + then repl; + else fail(); + end match; +end addReplacement; + +protected function replaceArgs +"finds DAE.CREF and replaces them with new exps if the cref is in the argmap" + input DAE.Exp inExp; + input tuple>,HashTableCG.HashTable,Boolean> inTuple; + output DAE.Exp outExp; + output tuple>,HashTableCG.HashTable,Boolean> outTuple; +algorithm + (outExp,outTuple) := Expression.Expression.traverseExpBottomUp(inExp,Inline.replaceArgs,inTuple); + if not Util.tuple33(outTuple) then + if Flags.isSet(Flags.FAILTRACE) then + Debug.traceln("BackendInline.replaceArgs failed"); + end if; + fail(); + end if; +end replaceArgs; + annotation(__OpenModelica_Interface="backend"); end BackendInline; diff --git a/Compiler/FrontEnd/Inline.mo b/Compiler/FrontEnd/Inline.mo index 5e98b27e8e0..85b5c9fd958 100644 --- a/Compiler/FrontEnd/Inline.mo +++ b/Compiler/FrontEnd/Inline.mo @@ -776,7 +776,7 @@ algorithm end match; end checkExpsTypeEquiv; -protected function inlineCall +public function inlineCall "replaces an inline call with the expression from the function" input output DAE.Exp exp; input output list assrtLst; @@ -902,7 +902,7 @@ algorithm end inlineAssert; -protected function hasGenerateEventsAnnotation +public function hasGenerateEventsAnnotation input Option comment; output Boolean b; algorithm @@ -1137,7 +1137,7 @@ algorithm end match; end addReplacement; -protected function checkInlineType " +public function checkInlineType " Author: Frenkel TUD, 2010-05" input DAE.InlineType inIT; input Functiontuple fns; @@ -1156,7 +1156,7 @@ algorithm end matchcontinue; end checkInlineType; -protected function extendCrefRecords +public function extendCrefRecords "extends crefs from records" input list> inArgmap; input HashTableCG.HashTable inCheckCr; @@ -1314,7 +1314,7 @@ algorithm end matchcontinue; end extendCrefRecords2; -protected function getFunctionBody +public function getFunctionBody "returns the body of a function" input Absyn.Path p; input Functiontuple fns; @@ -1366,7 +1366,7 @@ algorithm end match; end getRhsExp; -protected function replaceArgs +public function replaceArgs "finds DAE.CREF and replaces them with new exps if the cref is in the argmap" input DAE.Exp inExp; input tuple>,HashTableCG.HashTable,Boolean> inTuple; diff --git a/Compiler/Util/Flags.mo b/Compiler/Util/Flags.mo index 26a6a76a5ed..f93720f60e6 100644 --- a/Compiler/Util/Flags.mo +++ b/Compiler/Util/Flags.mo @@ -499,6 +499,10 @@ constant DebugFlag SERIALIZED_SIZE = DEBUG_FLAG(162, "reportSerializedSize", fal Util.gettext("Reports serialized sizes of various data structures used in the compiler.")); constant DebugFlag BACKEND_KEEP_ENV_GRAPH = DEBUG_FLAG(163, "backendKeepEnv", true, Util.gettext("When enabled, the environment is kept when entering the backend, which enables CevalFunction (function interpretation) to work. This module not essential for the backend to function in most cases, but can improve simulation performance by evaluating functions. The drawback to keeping the environment graph in memory is that it is huge (~80% of the total memory in use when returning the frontend DAE).")); +constant DebugFlag DUMPBACKENDINLINE = DEBUG_FLAG(164, "dumpBackendInline", false, + Util.gettext("Dumps debug output while inline function.")); +constant DebugFlag DUMPBACKENDINLINE_VERBOSE = DEBUG_FLAG(165, "dumpBackendInlineVerbose", false, + Util.gettext("Dumps debug output while inline function.")); // This is a list of all debug flags, to keep track of which flags are used. A // flag can not be used unless it's in this list, and the list is checked at @@ -668,7 +672,9 @@ constant list allDebugFlags = { TOTAL_TEARING_DUMPVERBOSE, PARALLEL_CODEGEN, SERIALIZED_SIZE, - BACKEND_KEEP_ENV_GRAPH + BACKEND_KEEP_ENV_GRAPH, + DUMPBACKENDINLINE, + DUMPBACKENDINLINE_VERBOSE }; public @@ -1269,6 +1275,13 @@ constant ConfigFlag CT_STATE_MACHINES = CONFIG_FLAG(94, "ctStateMachines", constant ConfigFlag DAE_MODE = CONFIG_FLAG(95, "daeMode", NONE(), EXTERNAL(), BOOL_FLAG(false), NONE(), Util.gettext("Generates additional code for DAE mode, where dynamic equations are not causelized.")); +constant ConfigFlag INLINE_METHOD = CONFIG_FLAG(96, "inlineMethod", + NONE(), EXTERNAL(), ENUM_FLAG(1, {("replace",1), ("append",2)}), + SOME(STRING_OPTION({"replace", "append"})), + Util.gettext("Sets the inline method to use.\n"+ + "replace : This method inlines by replacing in place all expressions. Might lead to very long expression.\n"+ + "append : This method inlines by adding additional variables to the whole system. Might lead to much bigger system.") + ); protected // This is a list of all configuration flags. A flag can not be used unless it's @@ -1369,7 +1382,8 @@ constant list allConfigFlags = { MAX_SIZE_NONLINEAR_TEARING, NO_TEARING_FOR_COMPONENT, CT_STATE_MACHINES, - DAE_MODE + DAE_MODE, + INLINE_METHOD }; public function new