diff --git a/.gitignore b/.gitignore index 6b676be2e59..508701febca 100644 --- a/.gitignore +++ b/.gitignore @@ -141,6 +141,7 @@ Compiler/boot/LoadCompilerInterface.mos Compiler/boot/Makefile Compiler/boot/Makefile.depends Compiler/boot/Makefile.sources +Compiler/boot/patches/*.patch Compiler/runtime/Makefile Compiler/runtime/config.unix.h Compiler/runtime/omc_communication.cc diff --git a/Compiler/BackEnd/BackendDAECreate.mo b/Compiler/BackEnd/BackendDAECreate.mo index daccdaa15f6..a98988fab01 100644 --- a/Compiler/BackEnd/BackendDAECreate.mo +++ b/Compiler/BackEnd/BackendDAECreate.mo @@ -68,7 +68,7 @@ protected import HashTable; protected import HashTableCrToExpSourceTpl; protected import Inline; protected import List; -protected import SimCodeUtil; +protected import SimCodeFunctionUtil; protected import SCode; protected import System; protected import Types; @@ -154,7 +154,7 @@ algorithm neqStr := intString(BackendDAEUtil.equationSize(eqnarr)); nvarStr := intString(BackendVariable.varsSize(vars_1)); Error.assertionOrAddSourceMessage(not Flags.isSet(Flags.DUMP_BACKENDDAE_INFO),Error.BACKENDDAEINFO_LOWER,{neqStr,nvarStr},Absyn.dummyInfo); - SimCodeUtil.execStat("Generate backend data structure"); + SimCodeFunctionUtil.execStat("Generate backend data structure"); end lower; protected function lower2 diff --git a/Compiler/BackEnd/BackendDAEOptimize.mo b/Compiler/BackEnd/BackendDAEOptimize.mo index 15663e53ba1..eeb5d224dc0 100644 --- a/Compiler/BackEnd/BackendDAEOptimize.mo +++ b/Compiler/BackEnd/BackendDAEOptimize.mo @@ -70,12 +70,10 @@ protected import ExpressionSolve; protected import ExpressionSimplify; protected import Error; protected import Flags; -protected import Graph; protected import HashTableExpToIndex; protected import List; protected import RewriteRules; protected import SCode; -protected import System; protected import SynchronousFeatures; protected import Types; protected import Util; diff --git a/Compiler/BackEnd/BackendDAETransform.mo b/Compiler/BackEnd/BackendDAETransform.mo index a1a2687d277..ed4188bae58 100644 --- a/Compiler/BackEnd/BackendDAETransform.mo +++ b/Compiler/BackEnd/BackendDAETransform.mo @@ -42,13 +42,11 @@ encapsulated package BackendDAETransform RCS: $Id$ " -public import Absyn; public import BackendDAE; public import DAE; protected import BackendDAEUtil; protected import BackendDump; -protected import BackendDAEOptimize; protected import BackendEquation; protected import BackendVariable; protected import ComponentReference; @@ -59,7 +57,6 @@ protected import Expression; protected import ExpressionDump; protected import Flags; protected import List; -protected import Matching; protected import SCode; protected import Sorting; protected import SymbolicJacobian; @@ -82,32 +79,36 @@ public function strongComponentsScalar "author: PA input array mapIncRowEqn; output BackendDAE.EqSystem outSystem; output BackendDAE.StrongComponents outComps "list of components"; -protected - list> comps; - array ass1, ass2; - BackendDAE.IncidenceMatrixT mt; - BackendDAE.EquationArray eqs; - BackendDAE.Variables vars; - array markarray; - BackendDAE.StateSets stateSets; - BackendDAE.BaseClockPartitionKind partitionKind; algorithm - try - BackendDAE.EQSYSTEM(vars, eqs, SOME(_), SOME(mt), BackendDAE.MATCHING(ass1=ass1, ass2=ass2), stateSets=stateSets, partitionKind=partitionKind) := inSystem; - - comps := Sorting.TarjanTransposed(mt, ass2); + (outSystem, outComps) := matchcontinue inSystem + local + list> comps_m; + array ass1, ass2; + BackendDAE.IncidenceMatrixT mt; + BackendDAE.EquationArray eqs; + BackendDAE.Variables vars; + array markarray; + BackendDAE.StrongComponents comps; + BackendDAE.EqSystem syst; + case syst as BackendDAE.EQSYSTEM(orderedEqs=eqs, m=SOME(_), mT=SOME(mt), matching=BackendDAE.MATCHING(ass1=ass1, ass2=ass2)) + algorithm + comps_m := Sorting.TarjanTransposed(mt, ass2); - markarray := arrayCreate(BackendDAEUtil.equationArraySize(eqs), -1); - outComps := analyseStrongComponentsScalar(comps, inSystem, inShared, ass1, ass2, mapEqnIncRow, mapIncRowEqn, 1, markarray); - ass1 := varAssignmentNonScalar(ass1, mapIncRowEqn); + markarray := arrayCreate(BackendDAEUtil.equationArraySize(eqs), -1); + comps := analyseStrongComponentsScalar(comps_m, inSystem, inShared, ass1, ass2, mapEqnIncRow, mapIncRowEqn, 1, markarray); + ass1 := varAssignmentNonScalar(ass1, mapIncRowEqn); - // noscalass2 = eqnAssignmentNonScalar(1, arrayLength(mapEqnIncRow), mapEqnIncRow, ass2, {}); - // Frenkel TUD: Do not hand over the scalar incidence Matrix because following modules does not check if scalar or not - outSystem := BackendDAE.EQSYSTEM(vars, eqs, NONE(), NONE(), BackendDAE.MATCHING(ass1, ass2, outComps), stateSets, partitionKind); - else - Error.addInternalError("function strongComponentsScalar failed (sorting strong components)", sourceInfo()); - fail(); - end try; + // noscalass2 = eqnAssignmentNonScalar(1, arrayLength(mapEqnIncRow), mapEqnIncRow, ass2, {}); + // Frenkel TUD: Do not hand over the scalar incidence Matrix because following modules does not check if scalar or not + syst.m := NONE(); syst.mT := NONE(); syst.matching := BackendDAE.MATCHING(ass1, ass2, comps); + then + (syst, comps); + else + algorithm + Error.addInternalError("function strongComponentsScalar failed (sorting strong components)", sourceInfo()); + then + fail(); + end matchcontinue; end strongComponentsScalar; public function eqnAssignmentNonScalar @@ -159,7 +160,6 @@ protected BackendDAE.StrongComponent acomp; Integer mark = imark; algorithm - for comp in inComps loop (acomp, mark) := analyseStrongComponentScalar(comp, syst, shared, inAss1, inAss2, mapEqnIncRow, mapIncRowEqn, mark, markarray); outComps := acomp :: outComps; @@ -181,12 +181,12 @@ protected function analyseStrongComponentScalar "author: Frenkel TUD 2011-05" output BackendDAE.StrongComponent outComp; output Integer omark = imark + 1; protected - list comp, vlst; - list varlst; - list> var_varindx_lst; - BackendDAE.Variables vars; - list eqn_lst; - BackendDAE.EquationArray eqns; + list comp, vlst; + list varlst; + list> var_varindx_lst; + BackendDAE.Variables vars; + list eqn_lst; + BackendDAE.EquationArray eqns; algorithm try BackendDAE.EQSYSTEM(orderedVars=vars, orderedEqs=eqns) := syst; diff --git a/Compiler/BackEnd/BackendDAEUtil.mo b/Compiler/BackEnd/BackendDAEUtil.mo index f041ddbbc56..6c83252e325 100644 --- a/Compiler/BackEnd/BackendDAEUtil.mo +++ b/Compiler/BackEnd/BackendDAEUtil.mo @@ -91,7 +91,6 @@ protected import Global; protected import HpcOmEqSystems; protected import HpcOmTaskGraph; protected import IndexReduction; -protected import Initialization; protected import Inline; protected import InlineArrayEquations; protected import List; @@ -100,7 +99,7 @@ protected import OnRelaxation; protected import RemoveSimpleEquations; protected import ResolveLoops; protected import SCode; -protected import SimCodeUtil; +protected import SimCodeFunctionUtil; protected import StateMachineFeatures; protected import SymbolicJacobian; protected import SynchronousFeatures; @@ -561,15 +560,9 @@ public function addVarsToEqSystem output BackendDAE.EqSystem osyst; protected BackendDAE.Variables vars; - BackendDAE.EquationArray eqs; - Option m,mT; - BackendDAE.Matching matching; - BackendDAE.StateSets stateSets; - BackendDAE.BaseClockPartitionKind partitionKind; algorithm - BackendDAE.EQSYSTEM(vars, eqs, m, mT, matching, stateSets, partitionKind) := syst; - vars := BackendVariable.addVars(varlst, vars); - osyst := BackendDAE.EQSYSTEM(vars, eqs, m, mT, matching, stateSets, partitionKind); + BackendDAE.EQSYSTEM(orderedVars=vars) := syst; + osyst := setEqSystVars(syst, BackendVariable.addVars(varlst, vars)); end addVarsToEqSystem; public function numberOfZeroCrossings "author: lochel" @@ -1986,10 +1979,9 @@ only to get the functionsTree. output BackendDAE.EqSystem oSyst; protected - BackendDAE.BaseClockPartitionKind partitionKind; array ass1, ass2; BackendDAE.Variables v; - BackendDAE.Variables vars; + BackendDAE.EqSystem syst; BackendDAE.Variables iVars = BackendVariable.listVar(iVarlst); BackendDAE.EquationArray ordererdEqs, arrEqs; list indx_lst_v, indx_lst_e, ind_mark, statevarindx_lst; @@ -2000,30 +1992,33 @@ protected DAE.FunctionTree funcs; BackendDAE.IncidenceMatrix m; algorithm + oSyst := match iSyst + case syst as BackendDAE.EQSYSTEM( orderedEqs=ordererdEqs, orderedVars=v, + matching=BackendDAE.MATCHING(ass1=ass1, ass2=ass2) ) + algorithm + (_, statevarindx_lst) := BackendVariable.getAllStateVarIndexFromVariables(v); + indx_lst_v := BackendVariable.getVarIndexFromVariables(iVars, v); - BackendDAE.EQSYSTEM(orderedEqs = ordererdEqs, orderedVars = v, matching = BackendDAE.MATCHING(ass1=ass1, ass2=ass2), partitionKind = partitionKind) := iSyst; - - (_,statevarindx_lst) := BackendVariable.getAllStateVarIndexFromVariables(v); - indx_lst_v := BackendVariable.getVarIndexFromVariables(iVars, v); - - indx_lst_v := List.appendNoCopy(indx_lst_v, statevarindx_lst) "overestimate"; - indx_lst_e := List.map1r(indx_lst_v,arrayGet,ass1); + indx_lst_v := List.appendNoCopy(indx_lst_v, statevarindx_lst) "overestimate"; + indx_lst_e := List.map1r(indx_lst_v, arrayGet, ass1); - indx_arr := arrayCreate(equationArraySizeDAE(iSyst), 0); - funcs := getFunctions(shared); - (_, m, _) := getIncidenceMatrix(iSyst, BackendDAE.SPARSE(), SOME(funcs)); + indx_arr := arrayCreate(equationArraySizeDAE(iSyst), 0); + funcs := getFunctions(shared); + (_, m, _) := getIncidenceMatrix(iSyst, BackendDAE.SPARSE(), SOME(funcs)); - indx_arr := markStateEquationsWork(indx_lst_e, m, ass1, indx_arr); + indx_arr := markStateEquationsWork(indx_lst_e, m, ass1, indx_arr); - indx_lst_e := Array.foldIndex(indx_arr, translateArrayList, {}); + indx_lst_e := Array.foldIndex(indx_arr, translateArrayList, {}); - el := BackendEquation.getEqns(indx_lst_e, ordererdEqs); - arrEqs := BackendEquation.listEquation(el); + el := BackendEquation.getEqns(indx_lst_e, ordererdEqs); + arrEqs := BackendEquation.listEquation(el); + vl := BackendEquation.equationsVars(arrEqs, v); - vl := BackendEquation.equationsVars(arrEqs, v); - vars := BackendVariable.listVar1(vl); - - oSyst := BackendDAE.EQSYSTEM(vars, arrEqs, NONE(), NONE(), BackendDAE.NO_MATCHING(), {}, partitionKind); + syst.orderedVars := BackendVariable.listVar1(vl); + syst.orderedEqs := arrEqs; + syst.stateSets := {}; + then BackendDAEUtil.clearEqSyst(syst); + end match; end reduceEqSystem; protected function translateArrayList @@ -3306,27 +3301,21 @@ public function updateIncidenceMatrix input list inIntegerLst; output BackendDAE.EqSystem osyst; algorithm - osyst := matchcontinue (syst,inIndxType,functionTree,inIntegerLst) + osyst := matchcontinue syst local BackendDAE.IncidenceMatrix m; BackendDAE.IncidenceMatrixT mt; BackendDAE.Variables vars; BackendDAE.EquationArray daeeqns; - BackendDAE.Matching matching; - BackendDAE.StateSets stateSets; - BackendDAE.BaseClockPartitionKind partitionKind; - case (BackendDAE.EQSYSTEM(vars,daeeqns,SOME(m),SOME(mt),matching,stateSets,partitionKind),_,_,_) + case BackendDAE.EQSYSTEM(orderedVars=vars, orderedEqs=daeeqns, m=SOME(m), mT=SOME(mt)) equation - (m,mt) = updateIncidenceMatrix1(vars,daeeqns,inIndxType,functionTree,m,mt,inIntegerLst); - then - BackendDAE.EQSYSTEM(vars,daeeqns,SOME(m),SOME(mt),matching,stateSets,partitionKind); - + (m,mt) = updateIncidenceMatrix1(vars, daeeqns, inIndxType, functionTree, m, mt, inIntegerLst); + then BackendDAEUtil.setEqSystMatrices(syst, SOME(m), SOME(mt)); else equation Error.addMessage(Error.INTERNAL_ERROR,{"BackendDAEUtil.updateIncididenceMatrix failed"}); - then - fail(); + then fail(); end matchcontinue; end updateIncidenceMatrix; @@ -3394,40 +3383,42 @@ public function updateIncidenceMatrixScalar output array> oMapEqnIncRow; output array oMapIncRowEqn; algorithm - (osyst,oMapEqnIncRow,oMapIncRowEqn) := matchcontinue (syst,inIndxType,functionTree,inIntegerLst,iMapEqnIncRow,iMapIncRowEqn) + (osyst, oMapEqnIncRow, oMapIncRowEqn) := matchcontinue syst local BackendDAE.IncidenceMatrix m; BackendDAE.IncidenceMatrixT mt; - Integer oldsize,newsize,oldsize1,newsize1,deltasize; + Integer oldsize, newsize, oldsize1, newsize1, deltasize; list eqns; BackendDAE.Variables vars; BackendDAE.EquationArray daeeqns; BackendDAE.Matching matching; array> mapEqnIncRow; array mapIncRowEqn; - BackendDAE.StateSets stateSets; - BackendDAE.BaseClockPartitionKind partitionKind; - case (BackendDAE.EQSYSTEM(vars,daeeqns,SOME(m),SOME(mt),matching,stateSets,partitionKind),_,_,_,_,_) + case BackendDAE.EQSYSTEM(orderedVars=vars, orderedEqs=daeeqns, m=SOME(m), mT=SOME(mt)) equation // extend the mapping arrays oldsize = arrayLength(iMapEqnIncRow); newsize = equationArraySize(daeeqns); - mapEqnIncRow = Array.expand(newsize-oldsize,iMapEqnIncRow,{}); + mapEqnIncRow = Array.expand(newsize-oldsize, iMapEqnIncRow, {}); oldsize1 = arrayLength(iMapIncRowEqn); newsize1 = equationSize(daeeqns); deltasize = newsize1-oldsize1; - mapIncRowEqn = Array.expand(deltasize,iMapIncRowEqn,0); + mapIncRowEqn = Array.expand(deltasize, iMapIncRowEqn, 0); // extend the incidenceMatrix - m = Array.expand(deltasize,m,{}); - mt = Array.expand(deltasize,mt,{}); + m = Array.expand(deltasize, m, {}); + mt = Array.expand(deltasize, mt, {}); // fill the extended parts first - (m,mt,mapEqnIncRow,mapIncRowEqn) = updateIncidenceMatrixScalar2(oldsize+1,newsize,oldsize1,vars,daeeqns,m,mt,mapEqnIncRow,mapIncRowEqn,inIndxType,functionTree); + (m, mt, mapEqnIncRow, mapIncRowEqn) = + updateIncidenceMatrixScalar2( oldsize+1, newsize, oldsize1, vars, daeeqns, m, mt, mapEqnIncRow, + mapIncRowEqn, inIndxType, functionTree ); // update the old eqns = List.removeOnTrue(oldsize, intLt, inIntegerLst); - (m,mt,mapEqnIncRow,mapIncRowEqn) = updateIncidenceMatrixScalar1(vars,daeeqns,m,mt,eqns,mapEqnIncRow,mapIncRowEqn,inIndxType,functionTree); + (m,mt,mapEqnIncRow,mapIncRowEqn) = + updateIncidenceMatrixScalar1( vars, daeeqns, m, mt, eqns, mapEqnIncRow, + mapIncRowEqn, inIndxType, functionTree ); then - (BackendDAE.EQSYSTEM(vars,daeeqns,SOME(m),SOME(mt),matching,stateSets,partitionKind),mapEqnIncRow,mapIncRowEqn); + (BackendDAEUtil.setEqSystMatrices(syst, SOME(m), SOME(mt)), mapEqnIncRow, mapIncRowEqn); else equation @@ -3671,7 +3662,7 @@ public function getIncidenceMatrixfromOption output BackendDAE.IncidenceMatrix outM; output BackendDAE.IncidenceMatrix outMT; algorithm - (outSyst, outM, outMT) := match (inSyst, inIndxType, inFunctionTree) + (outSyst, outM, outMT) := match inSyst local BackendDAE.IncidenceMatrix m, mT; BackendDAE.Variables v; @@ -3680,15 +3671,15 @@ algorithm BackendDAE.StateSets stateSets; BackendDAE.BaseClockPartitionKind partitionKind; - case(BackendDAE.EQSYSTEM(orderedVars=v, orderedEqs=eq, m=NONE(), matching=matching, stateSets=stateSets, partitionKind=partitionKind), _, _) equation + case BackendDAE.EQSYSTEM(orderedVars=v, orderedEqs=eq, m=NONE()) equation (m, mT) = incidenceMatrix(inSyst, inIndxType, inFunctionTree); - then (BackendDAE.EQSYSTEM(v, eq, SOME(m), SOME(mT), matching, stateSets, partitionKind), m, mT); + then (BackendDAEUtil.setEqSystMatrices(inSyst, SOME(m), SOME(mT)), m, mT); - case(BackendDAE.EQSYSTEM(orderedVars=v, orderedEqs=eq, m=SOME(m), mT=NONE(), matching=matching, stateSets=stateSets, partitionKind=partitionKind), _, _) equation + case BackendDAE.EQSYSTEM(orderedVars=v, orderedEqs=eq, m=SOME(m), mT=NONE()) equation mT = transposeMatrix(m, BackendVariable.varsSize(v)); - then (BackendDAE.EQSYSTEM(v, eq, SOME(m), SOME(mT), matching, stateSets, partitionKind), m, mT); + then (BackendDAEUtil.setEqSystMatrices(inSyst, SOME(m), SOME(mT)), m, mT); - case(BackendDAE.EQSYSTEM(m=SOME(m), mT=SOME(mT)), _, _) + case BackendDAE.EQSYSTEM(m=SOME(m), mT=SOME(mT)) then (inSyst, m, mT); end match; end getIncidenceMatrixfromOption; @@ -3702,15 +3693,11 @@ public function getIncidenceMatrix "this function returns the incidence matrix, output BackendDAE.IncidenceMatrix outM; output BackendDAE.IncidenceMatrix outMT; protected - BackendDAE.Variables v; BackendDAE.EquationArray eq; - BackendDAE.Matching matching; - BackendDAE.StateSets stateSets; - BackendDAE.BaseClockPartitionKind partitionKind; algorithm - BackendDAE.EQSYSTEM(orderedVars=v,orderedEqs=eq,matching=matching,stateSets=stateSets,partitionKind=partitionKind) := inEqSystem; - (outM, outMT) := incidenceMatrix(inEqSystem, inIndxType,functionTree); - outEqSystem := BackendDAE.EQSYSTEM(v, eq, SOME(outM), SOME(outMT), matching, stateSets,partitionKind); + BackendDAE.EQSYSTEM(orderedEqs=eq) := inEqSystem; + (outM, outMT) := incidenceMatrix(inEqSystem, inIndxType, functionTree); + outEqSystem := BackendDAEUtil.setEqSystMatrices(inEqSystem, SOME(outM), SOME(outMT)); end getIncidenceMatrix; public function getIncidenceMatrixScalar "function getIncidenceMatrixScalar" @@ -3723,15 +3710,11 @@ public function getIncidenceMatrixScalar "function getIncidenceMatrixScalar" output array> outMapEqnIncRow; output array outMapIncRowEqn; protected - BackendDAE.Variables v; BackendDAE.EquationArray eq; - BackendDAE.Matching matching; - BackendDAE.StateSets stateSets; - BackendDAE.BaseClockPartitionKind partitionKind; algorithm - BackendDAE.EQSYSTEM(orderedVars=v,orderedEqs=eq,matching=matching,stateSets=stateSets,partitionKind=partitionKind) := syst; - (outM,outMT,outMapEqnIncRow,outMapIncRowEqn) := incidenceMatrixScalar(syst, inIndxType, functionTree); - osyst := BackendDAE.EQSYSTEM(v, eq, SOME(outM), SOME(outMT), matching, stateSets, partitionKind); + BackendDAE.EQSYSTEM(orderedEqs=eq) := syst; + (outM, outMT, outMapEqnIncRow, outMapIncRowEqn) := incidenceMatrixScalar(syst, inIndxType, functionTree); + osyst := BackendDAEUtil.setEqSystMatrices(syst, SOME(outM), SOME(outMT)); end getIncidenceMatrixScalar; @@ -6591,34 +6574,6 @@ algorithm end match; end traverseBackendDAEExpsOptEqnWithUpdate; -public function traverseAlgorithmExps " - This function goes through the Algorithm structure and finds all the - expressions and performs the function on them -" - replaceable type Type_a subtypeof Any; - input DAE.Algorithm inAlgorithm; - input FuncExpType func; - input Type_a inTypeA; - output Type_a outTypeA; - partial function FuncExpType - input DAE.Exp inExp; - input Type_a inTypeA; - output DAE.Exp outExp; - output Type_a outA; - end FuncExpType; -algorithm - outTypeA := match (inAlgorithm,func,inTypeA) - local - list stmts; - Type_a ext_arg_1; - case (DAE.ALGORITHM_STMTS(statementLst = stmts),_,_) - equation - (_,ext_arg_1) = DAEUtil.traverseDAEEquationsStmts(stmts,func,inTypeA); - then - ext_arg_1; - end match; -end traverseAlgorithmExps; - public function traverseAlgorithmExpsWithUpdate " This function goes through the Algorithm structure and finds all the expressions and performs the function on them @@ -6749,7 +6704,7 @@ algorithm // transformation phase (matching and sorting using index reduction method) sode := causalizeDAE(optdae, NONE(), matchingAlgorithm, daeHandler, true); - SimCodeUtil.execStat("matching and sorting"); + SimCodeFunctionUtil.execStat("matching and sorting"); if Flags.isSet(Flags.GRAPHML) then HpcOmTaskGraph.dumpBipartiteGraph(sode, fileNamePrefix); @@ -6763,13 +6718,13 @@ algorithm (optsode, Util.SUCCESS()) := postOptimizeDAE(sode, postOptModules, matchingAlgorithm, daeHandler); sode1 := FindZeroCrossings.findZeroCrossings(optsode); - SimCodeUtil.execStat("findZeroCrossings"); + SimCodeFunctionUtil.execStat("findZeroCrossings"); _ := traverseBackendDAEExpsNoCopyWithUpdate(sode1, ExpressionSimplify.simplifyTraverseHelper, 0) "simplify all expressions"; - SimCodeUtil.execStat("SimplifyAllExp"); + SimCodeFunctionUtil.execStat("SimplifyAllExp"); outSODE := calculateValues(sode1); - SimCodeUtil.execStat("calculateValue"); + SimCodeFunctionUtil.execStat("calculateValue"); if Flags.isSet(Flags.DUMP_INDX_DAE) then BackendDump.dumpBackendDAE(outSODE, "dumpindxdae"); @@ -6830,7 +6785,7 @@ algorithm BackendDAE.DAE(systs, shared) = optModule(inDAE); systs = filterEmptySystems(systs); dae = BackendDAE.DAE(systs, shared); - SimCodeUtil.execStat("preOpt " + moduleStr); + SimCodeFunctionUtil.execStat("preOpt " + moduleStr); if Flags.isSet(Flags.OPT_DAE_DUMP) then print(stringAppendList({"\npre-optimization module ", moduleStr, ":\n\n"})); BackendDump.printBackendDAE(dae); @@ -6839,7 +6794,7 @@ algorithm then (dae1, status); case (_, (_, moduleStr, b)::rest) equation - SimCodeUtil.execStat(" preOpt " + moduleStr); + SimCodeFunctionUtil.execStat(" preOpt " + moduleStr); str = stringAppendList({"pre-optimization module ", moduleStr, " failed."}); Error.addMessage(Error.INTERNAL_ERROR, {str}); (dae,status) = preOptimizeDAE(inDAE,rest); @@ -6881,7 +6836,7 @@ algorithm BackendDAE.DAE(systs,shared) := inDAE; // reduce index (systs,shared,args,causalized) := mapCausalizeDAE(systs,shared,inMatchingOptions,matchingAlgorithm,stateDeselection,{},{},false); - //SimCodeUtil.execStat("matching"); + //SimCodeFunctionUtil.execStat("matching"); // do late inline outDAE := if dolateinline then BackendInline.lateInlineFunction(BackendDAE.DAE(systs,shared)) else BackendDAE.DAE(systs,shared); // do state selection @@ -6889,7 +6844,7 @@ algorithm // sort assigned equations to blt form systs := mapSortEqnsDAE(systs,shared,{}); outDAE := BackendDAE.DAE(systs,shared); - //SimCodeUtil.execStat("sorting"); + //SimCodeFunctionUtil.execStat("sorting"); end causalizeDAE; protected function mapCausalizeDAE " @@ -6971,10 +6926,10 @@ algorithm nvars = BackendVariable.daenumVariables(syst); neqns = systemSize(syst); syst = Causalize.singularSystemCheck(nvars,neqns,syst,match_opts,matchingAlgorithm,arg,ishared); - // SimCodeUtil.execStat("transformDAE -> singularSystemCheck " + mAmethodstr); + // SimCodeFunctionUtil.execStat("transformDAE -> singularSystemCheck " + mAmethodstr); // match the system and reduce index if neccessary (syst,shared,arg) = matchingAlgorithmfunc(syst, ishared, false, match_opts, sssHandler, arg); - // SimCodeUtil.execStat("transformDAE -> matchingAlgorithm " + mAmethodstr + " index Reduction Method " + str1); + // SimCodeFunctionUtil.execStat("transformDAE -> matchingAlgorithm " + mAmethodstr + " index Reduction Method " + str1); then (syst,shared,SOME(arg),true); case (_,_,_,(_,mAmethodstr),(_,str1,_,_),_) @@ -7009,7 +6964,7 @@ algorithm equation // do state selection outDAE = sDfunc(BackendDAE.DAE(systs,shared),args); - //SimCodeUtil.execStat("transformDAE -> state selection " + methodstr); + //SimCodeFunctionUtil.execStat("transformDAE -> state selection " + methodstr); then outDAE; else inDAE; @@ -7120,7 +7075,7 @@ algorithm BackendDAE.DAE(systs, shared) = optModule(inDAE); systs = filterEmptySystems(systs); dae = BackendDAE.DAE(systs, shared); - SimCodeUtil.execStat("postOpt " + moduleStr); + SimCodeFunctionUtil.execStat("postOpt " + moduleStr); if Flags.isSet(Flags.OPT_DAE_DUMP) then print(stringAppendList({"\npost-optimization module ", moduleStr, ":\n\n"})); BackendDump.printBackendDAE(dae); @@ -7131,7 +7086,7 @@ algorithm case (_, (_, moduleStr, b)::rest, _, _) equation - SimCodeUtil.execStat("postOpt " + moduleStr); + SimCodeFunctionUtil.execStat("postOpt " + moduleStr); str = stringAppendList({"post-optimization module ", moduleStr, " failed."}); Error.addMessage(Error.INTERNAL_ERROR, {str}); (dae,status) = postOptimizeDAE(inDAE,rest,matchingAlgorithm,daeHandler); @@ -8178,44 +8133,49 @@ algorithm end setFunctionTree; public function setEqSystEqs -" That function replace the KnownVars in BackendDAE. - author: wbraun" input BackendDAE.EqSystem inSyst; input BackendDAE.EquationArray inEqs; output BackendDAE.EqSystem outSyst; -protected - BackendDAE.Variables vars; - Option m; - Option mT; - BackendDAE.Matching matching; - BackendDAE.StateSets stateSets; - BackendDAE.BaseClockPartitionKind partitionKind; - BackendDAE.EquationArray initialEqs; - BackendDAE.EquationArray removedEqs; - BackendDAE.EventInfo eventInfo; algorithm - BackendDAE.EQSYSTEM(orderedVars=vars, m=m, mT=mT, matching=matching, stateSets=stateSets, partitionKind=partitionKind) := inSyst; - outSyst := BackendDAE.EQSYSTEM(orderedVars=vars, orderedEqs=inEqs, m=m, mT=mT, matching=matching, stateSets=stateSets, partitionKind=partitionKind); + outSyst := match inSyst + local + BackendDAE.EqSystem syst; + case syst as BackendDAE.EQSYSTEM() + algorithm syst.orderedEqs := inEqs; + then syst; + end match; end setEqSystEqs; public function setEqSystVars -" That function replace the KnownVars in BackendDAE. - author: wbraun" input BackendDAE.EqSystem inSyst; input BackendDAE.Variables inVars; output BackendDAE.EqSystem outSyst; -protected - BackendDAE.EquationArray eqs; - Option m; - Option mT; - BackendDAE.Matching matching; - BackendDAE.StateSets stateSets; - BackendDAE.BaseClockPartitionKind partitionKind; algorithm - BackendDAE.EQSYSTEM(orderedEqs=eqs, m=m, mT=mT, matching=matching, stateSets=stateSets, partitionKind=partitionKind) := inSyst; - outSyst := BackendDAE.EQSYSTEM(orderedVars=inVars, orderedEqs=eqs, m=m, mT=mT, matching=matching, stateSets=stateSets, partitionKind=partitionKind); + outSyst := match inSyst + local + BackendDAE.EqSystem syst; + case syst as BackendDAE.EQSYSTEM() + algorithm syst.orderedVars := inVars; + then syst; + end match; end setEqSystVars; +public function setEqSystMatrices + input BackendDAE.EqSystem inSyst; + input Option m = NONE(); + input Option mT = NONE(); + output BackendDAE.EqSystem outSyst; +algorithm + outSyst := match inSyst + local + BackendDAE.EqSystem syst; + case syst as BackendDAE.EQSYSTEM() + algorithm + syst.m := m; syst.mT := mT; + then syst; + end match; +end setEqSystMatrices; + public function clearEqSyst input BackendDAE.EqSystem inSyst; output BackendDAE.EqSystem outSyst; @@ -8234,208 +8194,112 @@ public function setEqSystMatching input BackendDAE.EqSystem inSyst; input BackendDAE.Matching matching; output BackendDAE.EqSystem outSyst; -protected - BackendDAE.Variables vars; - BackendDAE.EquationArray eqs; - Option m; - Option mT; - BackendDAE.StateSets stateSets; - BackendDAE.BaseClockPartitionKind partitionKind; algorithm - BackendDAE.EQSYSTEM(orderedVars=vars, orderedEqs=eqs, m=m, mT=mT, stateSets=stateSets, partitionKind=partitionKind) := inSyst; - outSyst := BackendDAE.EQSYSTEM(orderedVars=vars, orderedEqs=eqs, m=m, mT=mT, stateSets=stateSets, matching=matching, partitionKind=partitionKind); + outSyst := match inSyst + local + BackendDAE.EqSystem syst; + case syst as BackendDAE.EQSYSTEM() + algorithm syst.matching := matching; + then syst; + end match; end setEqSystMatching; public function setSharedRemovedEqns input BackendDAE.Shared inShared; input BackendDAE.EquationArray removedEqs; output BackendDAE.Shared outShared; -protected - BackendDAE.Variables knownVars, externalObjects, aliasVars; - list constraints; - list classAttrs; - FCore.Cache cache; - FCore.Graph graph; - DAE.FunctionTree functionTree; - BackendDAE.ExternalObjectClasses extObjClasses; - BackendDAE.BackendDAEType backendDAEType; - BackendDAE.SymbolicJacobians symjacs; - BackendDAE.ExtraInfo info; - BackendDAE.EquationArray initialEqs; - BackendDAE.EventInfo eventInfo; -algorithm - BackendDAE.SHARED( knownVars=knownVars, externalObjects=externalObjects, constraints=constraints, classAttrs=classAttrs, cache=cache, - graph=graph, extObjClasses=extObjClasses, backendDAEType=backendDAEType, symjacs=symjacs, info=info, - initialEqs=initialEqs, eventInfo=eventInfo, aliasVars=aliasVars, functionTree=functionTree ) := inShared; - outShared := BackendDAE.SHARED( knownVars=knownVars, externalObjects=externalObjects, constraints=constraints, classAttrs=classAttrs, cache=cache, - graph=graph, functionTree=functionTree, extObjClasses=extObjClasses, backendDAEType=backendDAEType, - symjacs=symjacs, info=info, aliasVars=aliasVars, initialEqs=initialEqs, removedEqs=removedEqs, eventInfo=eventInfo ); +algorithm + outShared := match inShared + local + BackendDAE.Shared shared; + case shared as BackendDAE.SHARED() + algorithm shared.removedEqs := removedEqs; + then shared; + end match; end setSharedRemovedEqns; public function setSharedInitialEqns input BackendDAE.Shared inShared; input BackendDAE.EquationArray initialEqs; output BackendDAE.Shared outShared; -protected - BackendDAE.Variables knownVars, externalObjects, aliasVars; - list constraints; - list classAttrs; - FCore.Cache cache; - FCore.Graph graph; - DAE.FunctionTree functionTree; - BackendDAE.ExternalObjectClasses extObjClasses; - BackendDAE.BackendDAEType backendDAEType; - BackendDAE.SymbolicJacobians symjacs; - BackendDAE.ExtraInfo info; - BackendDAE.EquationArray removedEqs; - BackendDAE.EventInfo eventInfo; -algorithm - BackendDAE.SHARED( knownVars=knownVars, externalObjects=externalObjects, constraints=constraints, classAttrs=classAttrs, cache=cache, - graph=graph, extObjClasses=extObjClasses, backendDAEType=backendDAEType, symjacs=symjacs, info=info, - removedEqs=removedEqs, eventInfo=eventInfo, aliasVars=aliasVars, functionTree=functionTree ) := inShared; - outShared := BackendDAE.SHARED( knownVars=knownVars, externalObjects=externalObjects, constraints=constraints, classAttrs=classAttrs, cache=cache, - graph=graph, functionTree=functionTree, extObjClasses=extObjClasses, backendDAEType=backendDAEType, - symjacs=symjacs, info=info, aliasVars=aliasVars, initialEqs=initialEqs, removedEqs=removedEqs, eventInfo=eventInfo ); +algorithm + outShared := match inShared + local + BackendDAE.Shared shared; + case shared as BackendDAE.SHARED() + algorithm shared.initialEqs := initialEqs; + then shared; + end match; end setSharedInitialEqns; public function setSharedSymJacs input BackendDAE.Shared inShared; input BackendDAE.SymbolicJacobians symjacs; output BackendDAE.Shared outShared; -protected - BackendDAE.Variables knownVars, externalObjects, aliasVars; - list constraints; - list classAttrs; - FCore.Cache cache; - FCore.Graph graph; - DAE.FunctionTree functionTree; - BackendDAE.ExternalObjectClasses extObjClasses; - BackendDAE.BackendDAEType backendDAEType; - BackendDAE.EquationArray initialEqs; - BackendDAE.ExtraInfo info; - BackendDAE.EquationArray removedEqs; - BackendDAE.EventInfo eventInfo; -algorithm - BackendDAE.SHARED( knownVars=knownVars, externalObjects=externalObjects, constraints=constraints, classAttrs=classAttrs, cache=cache, - graph=graph, extObjClasses=extObjClasses, backendDAEType=backendDAEType, initialEqs=initialEqs, info=info, - removedEqs=removedEqs, eventInfo=eventInfo, aliasVars=aliasVars, functionTree=functionTree ) := inShared; - outShared := BackendDAE.SHARED( knownVars=knownVars, externalObjects=externalObjects, constraints=constraints, classAttrs=classAttrs, cache=cache, - graph=graph, functionTree=functionTree, extObjClasses=extObjClasses, backendDAEType=backendDAEType, - symjacs=symjacs, info=info, aliasVars=aliasVars, initialEqs=initialEqs, removedEqs=removedEqs, eventInfo=eventInfo ); +algorithm + outShared := match inShared + local + BackendDAE.Shared shared; + case shared as BackendDAE.SHARED() + algorithm shared.symjacs := symjacs; + then shared; + end match; end setSharedSymJacs; -public function setSharedFunctionTree "replaces the aliasVars in the BackendDAE.Shared -author:Waurich TUD 2014-11" +public function setSharedFunctionTree input BackendDAE.Shared inShared; input DAE.FunctionTree inFunctionTree; output BackendDAE.Shared outShared; -protected - BackendDAE.Variables knownVars, externalObjects, aliasVars; - list constraints; - list classAttrs; - FCore.Cache cache; - FCore.Graph graph; - BackendDAE.ExternalObjectClasses extObjClasses; - BackendDAE.BackendDAEType backendDAEType; - BackendDAE.SymbolicJacobians symjacs; - BackendDAE.ExtraInfo info; - BackendDAE.EquationArray initialEqs; - BackendDAE.EquationArray removedEqs; - BackendDAE.EventInfo eventInfo; -algorithm - BackendDAE.SHARED( knownVars=knownVars, externalObjects=externalObjects, constraints=constraints, classAttrs=classAttrs, cache=cache, - graph=graph, extObjClasses=extObjClasses, backendDAEType=backendDAEType, symjacs=symjacs, info=info, - initialEqs=initialEqs, removedEqs=removedEqs, eventInfo=eventInfo, aliasVars=aliasVars ) := inShared; - outShared := BackendDAE.SHARED( knownVars=knownVars, externalObjects=externalObjects, constraints=constraints, classAttrs=classAttrs, cache=cache, - graph=graph, functionTree=inFunctionTree, extObjClasses=extObjClasses, backendDAEType=backendDAEType, aliasVars=aliasVars, - symjacs=symjacs, info=info, initialEqs=initialEqs, removedEqs=removedEqs, eventInfo=eventInfo ); +algorithm + outShared := match inShared + local + BackendDAE.Shared shared; + case shared as BackendDAE.SHARED() + algorithm shared.functionTree := inFunctionTree; + then shared; + end match; end setSharedFunctionTree; - - public function setSharedEventInfo input BackendDAE.Shared inShared; input BackendDAE.EventInfo eventInfo; output BackendDAE.Shared outShared; -protected - BackendDAE.Variables knownVars, externalObjects, aliasVars; - BackendDAE.EquationArray initialEqs; - BackendDAE.EquationArray removedEqs; - list constraints; - list classAttrs; - FCore.Cache cache; - FCore.Graph graph; - DAE.FunctionTree functionTree; - BackendDAE.ExternalObjectClasses extObjClasses; - BackendDAEType backendDAEType; - BackendDAE.SymbolicJacobians symjacs; - BackendDAE.ExtraInfo info; -algorithm - BackendDAE.SHARED( knownVars=knownVars, externalObjects=externalObjects, aliasVars=aliasVars, - initialEqs=initialEqs, removedEqs=removedEqs, constraints=constraints, classAttrs=classAttrs, - cache=cache, graph=graph, functionTree=functionTree, extObjClasses=extObjClasses, - backendDAEType=backendDAEType, symjacs=symjacs, info=info ) := inShared; - outShared := BackendDAE.SHARED( knownVars=knownVars, externalObjects=externalObjects, aliasVars=aliasVars, - initialEqs=initialEqs, removedEqs=removedEqs, constraints=constraints, classAttrs=classAttrs, - cache=cache, graph=graph, functionTree =functionTree, extObjClasses=extObjClasses, info=info, - eventInfo=eventInfo, backendDAEType=backendDAEType, symjacs=symjacs ); +algorithm + outShared := match inShared + local + BackendDAE.Shared shared; + case shared as BackendDAE.SHARED() + algorithm shared.eventInfo := eventInfo; + then shared; + end match; end setSharedEventInfo; public function setSharedKnVars -" That function replace the KnownVars in BackendDAE. - author: wbraun" input BackendDAE.Shared inShared; input BackendDAE.Variables knownVars; output BackendDAE.Shared outShared; -protected - BackendDAE.Variables aliasVars, externalObjects; - list constraints; - list classAttrs; - FCore.Cache cache; - FCore.Graph graph; - DAE.FunctionTree functionTree; - BackendDAE.ExternalObjectClasses extObjClasses; - BackendDAE.BackendDAEType backendDAEType; - BackendDAE.SymbolicJacobians symjacs; - BackendDAE.ExtraInfo info; - BackendDAE.EquationArray initialEqs; - BackendDAE.EquationArray removedEqs; - BackendDAE.EventInfo eventInfo; -algorithm - BackendDAE.SHARED( externalObjects=externalObjects, constraints=constraints, classAttrs=classAttrs, cache=cache, - graph=graph, functionTree=functionTree, extObjClasses=extObjClasses, backendDAEType=backendDAEType, - symjacs=symjacs, info=info, aliasVars=aliasVars, initialEqs=initialEqs, removedEqs=removedEqs, eventInfo=eventInfo ) := inShared; - outShared := BackendDAE.SHARED( knownVars=knownVars, externalObjects=externalObjects, constraints=constraints, classAttrs=classAttrs, cache=cache, - graph=graph, functionTree=functionTree, extObjClasses=extObjClasses, backendDAEType=backendDAEType, - symjacs=symjacs, info=info, aliasVars=aliasVars, initialEqs=initialEqs, removedEqs=removedEqs, eventInfo=eventInfo ); +algorithm + outShared := match inShared + local + BackendDAE.Shared shared; + case shared as BackendDAE.SHARED() + algorithm shared.knownVars := knownVars; + then shared; + end match; end setSharedKnVars; -public function setSharedAliasVars "replaces the aliasVars in the BackendDAE.Shared -author:Waurich TUD 2014-11" +public function setSharedAliasVars input BackendDAE.Shared inShared; input BackendDAE.Variables aliasVars; output BackendDAE.Shared outShared; -protected - BackendDAE.Variables knownVars, externalObjects; - list constraints; - list classAttrs; - FCore.Cache cache; - FCore.Graph graph; - DAE.FunctionTree functionTree; - BackendDAE.ExternalObjectClasses extObjClasses; - BackendDAE.BackendDAEType backendDAEType; - BackendDAE.SymbolicJacobians symjacs; - BackendDAE.ExtraInfo info; - BackendDAE.EquationArray initialEqs; - BackendDAE.EquationArray removedEqs; - BackendDAE.EventInfo eventInfo; -algorithm - BackendDAE.SHARED( knownVars=knownVars, externalObjects=externalObjects, constraints=constraints, classAttrs=classAttrs, cache=cache, - graph=graph, functionTree=functionTree, extObjClasses=extObjClasses, backendDAEType=backendDAEType, - symjacs=symjacs, info=info, initialEqs=initialEqs, removedEqs=removedEqs, eventInfo=eventInfo ) := inShared; - outShared := BackendDAE.SHARED( knownVars=knownVars, externalObjects=externalObjects, constraints=constraints, classAttrs=classAttrs, cache=cache, - graph=graph, functionTree=functionTree, extObjClasses=extObjClasses, backendDAEType=backendDAEType, - symjacs=symjacs, info=info, aliasVars=aliasVars, initialEqs=initialEqs, removedEqs=removedEqs, eventInfo=eventInfo ); +algorithm + outShared := match inShared + local + BackendDAE.Shared shared; + case shared as BackendDAE.SHARED() + algorithm shared.aliasVars := aliasVars; + then shared; + end match; end setSharedAliasVars; public function emptyEventInfo diff --git a/Compiler/BackEnd/BackendDump.mo b/Compiler/BackEnd/BackendDump.mo index b138d268e2f..6d92ce0b6b6 100644 --- a/Compiler/BackEnd/BackendDump.mo +++ b/Compiler/BackEnd/BackendDump.mo @@ -53,7 +53,6 @@ public import HashSet; public import Tpl; protected import Absyn; -protected import BackendDAETransform; protected import BackendDAEUtil; protected import BackendEquation; protected import BackendVariable; diff --git a/Compiler/BackEnd/BackendEquation.mo b/Compiler/BackEnd/BackendEquation.mo index abbccfe5f16..892f12d51c2 100644 --- a/Compiler/BackEnd/BackendEquation.mo +++ b/Compiler/BackEnd/BackendEquation.mo @@ -53,7 +53,6 @@ protected import ClassInf; protected import ComponentReference; protected import DAEUtil; protected import Debug; -protected import FCore; protected import Error; protected import Expression; protected import ExpressionDump; diff --git a/Compiler/BackEnd/BackendInline.mo b/Compiler/BackEnd/BackendInline.mo index ef0186c0b37..8040e143dce 100644 --- a/Compiler/BackEnd/BackendInline.mo +++ b/Compiler/BackEnd/BackendInline.mo @@ -41,29 +41,15 @@ encapsulated package BackendInline The entry point is the inlineCalls function, or inlineCallsInFunctions " -public import Absyn; public import BackendDAE; -public import BaseHashTable; public import DAE; -public import FCore; -public import HashTableCG; public import Inline; public import SCode; public import Values; -protected import Ceval; -protected import ClassInf; -protected import ComponentReference; -protected import Config; protected import Debug; -protected import Error; -protected import Expression; -protected import ExpressionDump; -protected import ExpressionSimplify; protected import Flags; protected import List; -protected import Types; -protected import VarTransform; // ============================================================================= // late inline functions stuff @@ -120,21 +106,16 @@ protected function inlineEquationSystem input Inline.Functiontuple tpl; output BackendDAE.EqSystem oeqs; algorithm - oeqs := match (eqs,tpl) + oeqs := match eqs local BackendDAE.EqSystem syst; BackendDAE.Variables orderedVars; BackendDAE.EquationArray orderedEqs; - BackendDAE.Matching matching; - Boolean b1,b2; - BackendDAE.StateSets stateSets; - BackendDAE.BaseClockPartitionKind partitionKind; - case (syst as BackendDAE.EQSYSTEM(orderedVars=orderedVars, orderedEqs=orderedEqs,matching=matching,stateSets=stateSets,partitionKind=partitionKind),_) + case syst as BackendDAE.EQSYSTEM(orderedVars=orderedVars, orderedEqs=orderedEqs) equation - (orderedVars,b1) = inlineVariables(orderedVars,tpl); - (orderedEqs,b2) = inlineEquationArray(orderedEqs,tpl); - syst = if b1 or b2 then BackendDAE.EQSYSTEM(orderedVars,orderedEqs,NONE(),NONE(),matching,stateSets,partitionKind) else syst; + _ = inlineVariables(orderedVars, tpl); + _ = inlineEquationArray(orderedEqs, tpl); then syst; end match; diff --git a/Compiler/BackEnd/BackendQSS.mo b/Compiler/BackEnd/BackendQSS.mo index 5c340e576d5..6490e7edb51 100644 --- a/Compiler/BackEnd/BackendQSS.mo +++ b/Compiler/BackEnd/BackendQSS.mo @@ -55,7 +55,7 @@ protected import BackendVariable; protected import ComponentReference; protected import HpcOmSimCode; protected import List; -protected import SimCodeUtil; +protected import SimCodeFunctionUtil; public uniontype QSSinfo "- equation indices in static blocks and DEVS structure" @@ -614,7 +614,7 @@ end generateHandler; // then computeAlgs(tail,states,listAppend(i_algs,{cref})); // case ((SimCode.SES_LINEAR(vars=vars)) :: tail,_,_) // equation -// vars_cref = List.map(vars,SimCodeUtil.varName); +// vars_cref = List.map(vars,SimCodeFunctionUtil.varName); // then computeAlgs(tail,states,listAppend(i_algs,vars_cref)); // case ({},_,_) // equation @@ -802,9 +802,9 @@ algorithm case (SimCode.SES_SIMPLE_ASSIGN(cref=cref,exp=exp), SimCodeVar.SIMVARS(paramVars=paramVars,intParamVars=intParamVars,boolParamVars=boolParamVars)) equation - failure(_ = List.position(cref,List.map(paramVars,SimCodeUtil.varName))); - failure(_ = List.position(cref,List.map(intParamVars,SimCodeUtil.varName))); - failure(_ = List.position(cref,List.map(boolParamVars,SimCodeUtil.varName))); + failure(_ = List.position(cref,List.map(paramVars,SimCodeFunctionUtil.varName))); + failure(_ = List.position(cref,List.map(intParamVars,SimCodeFunctionUtil.varName))); + failure(_ = List.position(cref,List.map(boolParamVars,SimCodeFunctionUtil.varName))); t = stringAppend("parameter Real ",System.stringReplace(replaceCref(cref,{},{},{}),".","_")); t = stringAppend(t," = "); t = stringAppend(t,ExpressionDump.printExpStr(replaceVars(exp,{},{},{}))); diff --git a/Compiler/BackEnd/BackendVarTransform.mo b/Compiler/BackEnd/BackendVarTransform.mo index e83462c607f..bf3741c9dde 100644 --- a/Compiler/BackEnd/BackendVarTransform.mo +++ b/Compiler/BackEnd/BackendVarTransform.mo @@ -47,7 +47,6 @@ public import HashTable3; protected import Absyn; protected import BaseHashTable; protected import BaseHashSet; -protected import BackendDAEUtil; protected import BackendEquation; protected import BackendVariable; protected import ClassInf; diff --git a/Compiler/BackEnd/BackendVariable.mo b/Compiler/BackEnd/BackendVariable.mo index e20a1ac9bd3..072871e0709 100644 --- a/Compiler/BackEnd/BackendVariable.mo +++ b/Compiler/BackEnd/BackendVariable.mo @@ -40,14 +40,12 @@ encapsulated package BackendVariable public import BackendDAE; public import DAE; -public import FCore; public import SCode; public import Values; protected import Absyn; protected import Array; protected import BackendDAEUtil; -protected import BackendDump; protected import BaseHashSet; protected import BaseHashTable; protected import ComponentReference; @@ -60,7 +58,6 @@ protected import ExpressionSimplify; protected import Flags; protected import HashSet; protected import List; -protected import System; protected import Util; protected import Types; diff --git a/Compiler/BackEnd/BinaryTree.mo b/Compiler/BackEnd/BinaryTree.mo index e1b5d254f1e..f849cc91aa4 100644 --- a/Compiler/BackEnd/BinaryTree.mo +++ b/Compiler/BackEnd/BinaryTree.mo @@ -46,7 +46,6 @@ public import DAE; protected import BaseHashTable; protected import ComponentReference; -protected import Debug; protected import Error; protected import List; protected import System; diff --git a/Compiler/BackEnd/Causalize.mo b/Compiler/BackEnd/Causalize.mo index 32e81552969..6c6c32e6c8b 100644 --- a/Compiler/BackEnd/Causalize.mo +++ b/Compiler/BackEnd/Causalize.mo @@ -43,7 +43,6 @@ public import BackendDAE; public import BackendDAEFunc; public import DAE; -protected import Absyn; protected import BackendDAEUtil; protected import BackendDump; protected import BackendEquation; diff --git a/Compiler/BackEnd/CommonSubExpression.mo b/Compiler/BackEnd/CommonSubExpression.mo index f51ca220c4e..c08c251a477 100644 --- a/Compiler/BackEnd/CommonSubExpression.mo +++ b/Compiler/BackEnd/CommonSubExpression.mo @@ -46,7 +46,6 @@ protected import BackendDump; protected import BackendEquation; protected import BackendVarTransform; protected import BackendVariable; -protected import BaseHashSet; protected import BaseHashTable; protected import ComponentReference; protected import Expression; @@ -97,8 +96,7 @@ algorithm local BackendDAE.Variables orderedVars; BackendDAE.EquationArray orderedEqs; - BackendDAE.StateSets stateSets; - BackendDAE.BaseClockPartitionKind partitionKind; + BackendDAE.EqSystem syst; list varList; list eqList; HashTableExpToExp.HashTable HT; @@ -108,34 +106,40 @@ algorithm Boolean bCSE_EACHCALL; Boolean bCSE_BINARY; - case (BackendDAE.EQSYSTEM(orderedVars, orderedEqs, _, _, _, stateSets, partitionKind), (index, bCSE_CALL, bCSE_EACHCALL, bCSE_BINARY)) equation + case ( syst as BackendDAE.EQSYSTEM(orderedVars=orderedVars, orderedEqs=orderedEqs), + (index, bCSE_CALL, bCSE_EACHCALL, bCSE_BINARY) ) + equation //if Flags.isSet(Flags.DUMP_CSE) then // BackendDump.dumpVariables(orderedVars, "########### Updated Variable List ###########"); // BackendDump.dumpEquationArray(orderedEqs, "########### Updated Equation List ###########"); //end if; - HT = HashTableExpToExp.emptyHashTableSized(49999); //2053 4013 25343 536870879 - HT2 = HashTableExpToIndex.emptyHashTableSized(49999); - HT3 = HashTableExpToIndex.emptyHashTableSized(49999); - if Flags.isSet(Flags.DUMP_CSE_VERBOSE) then - print("collect statistics\n========================================\n"); - end if; - (HT, HT2, index, _, _, _) = BackendEquation.traverseEquationArray(orderedEqs, createStatistics, (HT, HT2, index, bCSE_CALL, bCSE_EACHCALL, bCSE_BINARY)); + HT = HashTableExpToExp.emptyHashTableSized(49999); //2053 4013 25343 536870879 + HT2 = HashTableExpToIndex.emptyHashTableSized(49999); + HT3 = HashTableExpToIndex.emptyHashTableSized(49999); + if Flags.isSet(Flags.DUMP_CSE_VERBOSE) then + print("collect statistics\n========================================\n"); + end if; + (HT, HT2, index, _, _, _) = + BackendEquation.traverseEquationArray(orderedEqs, createStatistics, ( HT, HT2, index, bCSE_CALL, + bCSE_EACHCALL, bCSE_BINARY )); //BaseHashTable.dumpHashTable(HT); //BaseHashTable.dumpHashTable(HT2); - if Flags.isSet(Flags.DUMP_CSE_VERBOSE) then - print("\nstart substitution\n========================================\n"); - end if; - (orderedEqs, (HT, HT2, _, eqList, varList, _, _, _)) = BackendEquation.traverseEquationArray_WithUpdate(orderedEqs, substituteCSE, (HT, HT2, HT3, {}, {}, bCSE_CALL, bCSE_EACHCALL, bCSE_BINARY)); - if Flags.isSet(Flags.DUMP_CSE_VERBOSE) then - print("\n"); - end if; - orderedEqs = BackendEquation.addEquations(eqList, orderedEqs); - orderedVars = BackendVariable.addVars(varList, orderedVars); + if Flags.isSet(Flags.DUMP_CSE_VERBOSE) then + print("\nstart substitution\n========================================\n"); + end if; + (orderedEqs, (HT, HT2, _, eqList, varList, _, _, _)) = + BackendEquation.traverseEquationArray_WithUpdate ( + orderedEqs, substituteCSE, (HT, HT2, HT3, {}, {}, bCSE_CALL, bCSE_EACHCALL, bCSE_BINARY) ); + if Flags.isSet(Flags.DUMP_CSE_VERBOSE) then + print("\n"); + end if; + syst.orderedEqs = BackendEquation.addEquations(eqList, orderedEqs); + syst.orderedVars = BackendVariable.addVars(varList, orderedVars); if Flags.isSet(Flags.DUMP_CSE) then - BackendDump.dumpVariables(orderedVars, "########### Updated Variable List ###########"); - BackendDump.dumpEquationArray(orderedEqs, "########### Updated Equation List ###########"); + BackendDump.dumpVariables(syst.orderedVars, "########### Updated Variable List ###########"); + BackendDump.dumpEquationArray(syst.orderedEqs, "########### Updated Equation List ###########"); end if; - then (BackendDAEUtil.createEqSystem(orderedVars, orderedEqs, stateSets, partitionKind), (index, bCSE_CALL, bCSE_EACHCALL, bCSE_BINARY)); + then (BackendDAEUtil.clearEqSyst(syst), (index, bCSE_CALL, bCSE_EACHCALL, bCSE_BINARY)); else (inSystem, inTpl); end matchcontinue; @@ -851,35 +855,32 @@ author:Waurich TUD 2014-11" output BackendDAE.EqSystem sysOut; output BackendDAE.Shared sharedOut; algorithm - (sysOut, sharedOut) := matchcontinue(tplsIn, m, mT, sysIn, sharedIn, deleteEqLstIn, deleteCrefsIn) + (sysOut, sharedOut) := matchcontinue (tplsIn, m, mT, sysIn, sharedIn, deleteEqLstIn, deleteCrefsIn) local Integer sharedVar, eqIdx1, eqIdx2, varIdx1, varIdx2, varIdxRepl, varIdxAlias, eqIdxDel, eqIdxLeft; list eqIdcs, eqs1, eqs2, vars1, vars2, aliasVars; list rest; BackendDAE.Var var1, var2; BackendVarTransform.VariableReplacements repl; - BackendDAE.StateSets stateSets; - BackendDAE.BaseClockPartitionKind partitionKind; BackendDAE.Variables vars; BackendDAE.EquationArray eqs; - BackendDAE.EqSystem eqSys; + BackendDAE.EqSystem syst; BackendDAE.Shared shared; DAE.Exp varExp; DAE.ComponentRef cref; list eqLst; - case({}, _, _, BackendDAE.EQSYSTEM(orderedVars=vars, orderedEqs=eqs, stateSets=stateSets, partitionKind=partitionKind), _, _, _) + case({}, _, _, syst as BackendDAE.EQSYSTEM(orderedVars=vars, orderedEqs=eqs), _, _, _) equation // remove superfluous equations eqLst = BackendEquation.equationList(eqs); eqLst = List.deletePositions(eqLst, List.map1(deleteEqLstIn, intSub, 1)); - eqs = BackendEquation.listEquation(eqLst); + syst.orderedEqs = BackendEquation.listEquation(eqLst); // remove alias from vars - vars = BackendVariable.deleteCrefs(deleteCrefsIn, vars); - eqSys = BackendDAEUtil.createEqSystem(vars, eqs, stateSets, partitionKind); - then (eqSys, sharedIn); + syst.orderedVars = BackendVariable.deleteCrefs(deleteCrefsIn, vars); + then (BackendDAEUtil.clearEqSyst(syst), sharedIn); case ( ASSIGNMENT_CSE(eqIdcs={eqIdx1, eqIdx2}, aliasVars={varIdx1, varIdx2})::rest, _, _, - BackendDAE.EQSYSTEM(orderedVars=vars, orderedEqs=eqs, stateSets=stateSets, partitionKind=partitionKind), + syst as BackendDAE.EQSYSTEM(orderedVars=vars, orderedEqs=eqs), _, _, _ ) equation // update the equations @@ -903,20 +904,20 @@ algorithm eqIdcs = arrayGet(mT, varIdxRepl); eqLst = BackendEquation.getEqns(eqIdcs, eqs); (eqLst, _) = BackendVarTransform.replaceEquations(eqLst, repl, NONE()); - eqs = List.threadFold(eqIdcs, eqLst, BackendEquation.setAtIndexFirst, eqs); + syst.orderedEqs = List.threadFold(eqIdcs, eqLst, BackendEquation.setAtIndexFirst, eqs); // transfer initial value if BackendVariable.varHasStartValue(var2) and not BackendVariable.varHasStartValue(var1) then var1 = BackendVariable.setVarStartValue(var1, BackendVariable.varStartValue(var2)); var1 = BackendVariable.setVarFixed(var1, BackendVariable.varFixed(var2)) ; end if; - vars = BackendVariable.setVarAt(vars, varIdxAlias, var1); + syst.orderedVars = BackendVariable.setVarAt(vars, varIdxAlias, var1); // add alias to shared var2 = BackendVariable.setBindExp(var2, SOME(varExp)); shared = updateAllAliasVars(sharedIn, repl); shared = BackendVariable.addAliasVarDAE(var2, shared); - eqSys = BackendDAEUtil.createEqSystem(vars, eqs, stateSets, partitionKind); - then commonSubExpressionUpdate(rest, m, mT, eqSys, shared, eqIdxDel::deleteEqLstIn, cref::deleteCrefsIn); - case(_::rest, _, _, _, _, _, _) + syst = BackendDAEUtil.clearEqSyst(syst); + then commonSubExpressionUpdate(rest, m, mT, syst, shared, eqIdxDel::deleteEqLstIn, cref::deleteCrefsIn); + case (_::rest, _, _, _, _, _, _) then commonSubExpressionUpdate(rest, m, mT, sysIn, sharedIn, deleteEqLstIn, deleteCrefsIn); end matchcontinue; end commonSubExpressionUpdate; diff --git a/Compiler/BackEnd/DumpGraphML.mo b/Compiler/BackEnd/DumpGraphML.mo index 031b121446c..394f3914a19 100644 --- a/Compiler/BackEnd/DumpGraphML.mo +++ b/Compiler/BackEnd/DumpGraphML.mo @@ -40,7 +40,6 @@ encapsulated package DumpGraphML public import BackendDAE; public import DAE; -protected import Array; protected import BackendDump; protected import BackendEquation; protected import BackendDAETransform; diff --git a/Compiler/BackEnd/DynamicOptimization.mo b/Compiler/BackEnd/DynamicOptimization.mo index 36ba21c8e50..1fa417aa386 100644 --- a/Compiler/BackEnd/DynamicOptimization.mo +++ b/Compiler/BackEnd/DynamicOptimization.mo @@ -57,7 +57,6 @@ protected import Differentiate; protected import Expression; protected import ExpressionSolve; protected import ExpressionSimplify; -protected import Error; protected import Flags; protected import List; @@ -407,22 +406,16 @@ protected function inputDerivativesForDynOptWork "author: " algorithm - (osyst, outChanged) := matchcontinue(isyst) + (osyst, outChanged) := matchcontinue isyst local - BackendDAE.Variables orderedVars "ordered Variables, only states and alg. vars"; BackendDAE.EquationArray orderedEqs "ordered Equations"; - Option m; - Option mT; - BackendDAE.Matching matching; list idercr={}, icr={}; DAE.ComponentRef cr; String s; - BackendDAE.StateSets stateSets; - BackendDAE.BaseClockPartitionKind partitionKind; list varLst={}; BackendDAE.Variables vars; - case BackendDAE.EQSYSTEM(orderedVars, orderedEqs, _, _, _, stateSets, partitionKind) algorithm + case BackendDAE.EQSYSTEM(orderedEqs=orderedEqs) algorithm vars := BackendVariable.daeKnVars(outShared); ((_, idercr, icr, varLst)) := BackendDAEUtil.traverseBackendDAEExpsEqnsWithUpdate(orderedEqs, traverserinputDerivativesForDynOpt, (vars, idercr, icr, varLst)); @@ -443,7 +436,7 @@ algorithm end for; _ := BackendVariable.daeKnVars(outShared); //BackendDump.printVariables(vars); - then (BackendDAEUtil.createEqSystem(orderedVars, orderedEqs, stateSets, partitionKind), true); + then (isyst, true); else (isyst, inChanged); end matchcontinue; @@ -578,43 +571,46 @@ algorithm local BackendDAE.Variables vars; BackendDAE.EquationArray eqns; - BackendDAE.StateSets stateSets; - BackendDAE.BaseClockPartitionKind partitionKind; - list eindex,vindx; - Integer eindex_,vindx_; + list eindex, vindx; + Integer eindex_, vindx_; BackendDAE.Shared shared; DAE.Exp e1, e2, varexp; BackendDAE.Var v; DAE.ComponentRef cr; DAE.FunctionTree funcs; BackendDAE.JacobianType jacType; + BackendDAE.EqSystem syst; Boolean linear; - case (BackendDAE.EQSYSTEM(orderedVars=vars,orderedEqs=eqns,stateSets=stateSets,partitionKind=partitionKind),shared,(BackendDAE.EQUATIONSYSTEM(eqns=eindex,vars=vindx, jacType=jacType))) + case ( syst as BackendDAE.EQSYSTEM(orderedVars=vars, orderedEqs=eqns), shared, + (BackendDAE.EQUATIONSYSTEM(eqns=eindex, vars=vindx, jacType=jacType)) ) guard l2p_all or (if l2p_l then isConstOrlinear(jacType) else not isConstOrlinear(jacType)) - equation - if l2p_l then - end if; - (eqns,vars,shared) = res2Con(eqns, vars, eindex, vindx,shared); - then (BackendDAEUtil.createEqSystem(vars, eqns, stateSets, partitionKind), shared); + algorithm + (eqns, vars, shared) := res2Con(eqns, vars, eindex, vindx, shared); + syst.orderedEqs := eqns; syst.orderedVars := vars; + then (BackendDAEUtil.clearEqSyst(syst), shared); - case (BackendDAE.EQSYSTEM(orderedVars=vars,orderedEqs=eqns,stateSets=stateSets,partitionKind=partitionKind),shared,(BackendDAE.TORNSYSTEM(BackendDAE.TEARINGSET(residualequations=eindex,tearingvars=vindx),linear=linear))) + case ( syst as BackendDAE.EQSYSTEM(orderedVars=vars, orderedEqs=eqns), shared, + (BackendDAE.TORNSYSTEM(BackendDAE.TEARINGSET(residualequations=eindex, tearingvars=vindx), linear=linear)) ) guard l2p_all or (if l2p_l then linear else not linear) - equation - (eqns,vars,shared) = res2Con(eqns, vars, eindex, vindx,shared); - then (BackendDAEUtil.createEqSystem(vars, eqns, stateSets, partitionKind), shared); - - case (BackendDAE.EQSYSTEM(orderedVars=vars,orderedEqs=eqns,stateSets=stateSets,partitionKind=partitionKind),shared,BackendDAE.SINGLEEQUATION(eqn=eindex_,var=vindx_)) + algorithm + (eqns, vars, shared) := res2Con(eqns, vars, eindex, vindx, shared); + syst.orderedEqs := eqns; syst.orderedVars := vars; + then (BackendDAEUtil.clearEqSyst(syst), shared); + + case ( syst as BackendDAE.EQSYSTEM(orderedVars=vars, orderedEqs=eqns), + shared as BackendDAE.SHARED(functionTree = funcs), + BackendDAE.SINGLEEQUATION(eqn=eindex_, var=vindx_) ) guard l2p_all or not l2p_l - equation - BackendDAE.EQUATION(exp=e1, scalar=e2) = BackendEquation.equationNth1(eqns, eindex_); - (v as BackendDAE.VAR(varName = cr)) = BackendVariable.getVarAt(vars, vindx_); - varexp = Expression.crefExp(cr); - varexp = if BackendVariable.isStateVar(v) then Expression.expDer(varexp) else varexp; - BackendDAE.SHARED(functionTree = funcs) = shared; - failure(ExpressionSolve.solve2(e1, e2, varexp, SOME(funcs), NONE())); - (eqns,vars,shared) = res2Con(eqns, vars, {eindex_}, {vindx_},shared); - then (BackendDAEUtil.createEqSystem(vars, eqns, stateSets, partitionKind), shared); + algorithm + BackendDAE.EQUATION(exp=e1, scalar=e2) := BackendEquation.equationNth1(eqns, eindex_); + (v as BackendDAE.VAR(varName = cr)) := BackendVariable.getVarAt(vars, vindx_); + varexp := Expression.crefExp(cr); + varexp := if BackendVariable.isStateVar(v) then Expression.expDer(varexp) else varexp; + failure(ExpressionSolve.solve2(e1, e2, varexp, SOME(funcs), NONE())); + (eqns, vars, shared) := res2Con(eqns, vars, {eindex_}, {vindx_}, shared); + syst.orderedEqs := eqns; syst.orderedVars := vars; + then (BackendDAEUtil.clearEqSyst(syst), shared); else (isyst,ishared); @@ -746,7 +742,7 @@ algorithm BackendDAE.SHARED(functionTree = funcs, knownVars = knownVars) := shared; for syst in systlst loop - BackendDAE.EQSYSTEM(orderedVars=vars,orderedEqs=eqns,matching=BackendDAE.MATCHING(comps=comps),stateSets=stateSets,partitionKind=partitionKind) := syst; + BackendDAE.EQSYSTEM(orderedVars=vars,orderedEqs=eqns,matching=BackendDAE.MATCHING(comps=comps)) := syst; b := false; for comp in comps loop //BackendDump.dumpComponent(comp); @@ -867,7 +863,7 @@ algorithm // remove empty entries from vars/eqns //vars := BackendVariable.listVar1(BackendVariable.varList(vars)); //eqns := BackendEquation.listEquation(BackendEquation.equationList(eqns)); - new_systlst := BackendDAEUtil.createEqSystem(vars, eqns, stateSets, partitionKind) :: new_systlst; + new_systlst := BackendDAEUtil.clearEqSyst(syst) :: new_systlst; else new_systlst := syst :: new_systlst; end if; diff --git a/Compiler/BackEnd/EvaluateFunctions.mo b/Compiler/BackEnd/EvaluateFunctions.mo index 14111ad52e5..ba68627d756 100644 --- a/Compiler/BackEnd/EvaluateFunctions.mo +++ b/Compiler/BackEnd/EvaluateFunctions.mo @@ -48,7 +48,6 @@ protected import ClassInf; protected import ComponentReference; protected import DAEUtil; protected import DAEDump; -protected import Debug; protected import Expression; protected import ExpressionDump; protected import ExpressionSimplify; diff --git a/Compiler/BackEnd/EvaluateParameter.mo b/Compiler/BackEnd/EvaluateParameter.mo index 829ef8e7d8c..a1b9e3eebf4 100644 --- a/Compiler/BackEnd/EvaluateParameter.mo +++ b/Compiler/BackEnd/EvaluateParameter.mo @@ -66,7 +66,6 @@ public import DAE; public import FCore; protected import Array; -protected import BackendDAETransform; protected import BackendDAEUtil; protected import BackendDump; protected import BackendEquation; @@ -77,7 +76,6 @@ protected import BaseHashSet; protected import Ceval; protected import ComponentReference; protected import DAEUtil; -protected import Debug; protected import Error; protected import Expression; protected import ExpressionDump; @@ -1099,18 +1097,15 @@ protected function replaceEvaluatedParametersSystemEqns input BackendVarTransform.VariableReplacements repl; output BackendDAE.EqSystem osyst; protected - BackendDAE.Variables vars; - BackendDAE.EquationArray eqns,eqns1; - list eqns_1,lsteqns; + BackendDAE.EquationArray eqns, eqns1; + list lsteqns; Boolean b; - BackendDAE.StateSets stateSets; - BackendDAE.BaseClockPartitionKind partitionKind; algorithm - BackendDAE.EQSYSTEM(orderedVars=vars, orderedEqs=eqns, stateSets=stateSets, partitionKind=partitionKind) := isyst; + BackendDAE.EQSYSTEM(orderedEqs=eqns) := isyst; lsteqns := BackendEquation.equationList(eqns); - (eqns_1,b) := BackendVarTransform.replaceEquations(lsteqns, repl, NONE()); - eqns1 := if b then BackendEquation.listEquation(eqns_1) else eqns; - osyst := if b then BackendDAEUtil.createEqSystem(vars, eqns1, stateSets, partitionKind) else isyst; + (lsteqns, b) := BackendVarTransform.replaceEquations(lsteqns, repl, NONE()); + eqns1 := if b then BackendEquation.listEquation(lsteqns) else eqns; + osyst := if b then BackendDAEUtil.clearEqSyst(BackendDAEUtil.setEqSystEqs(isyst, eqns1)) else isyst; end replaceEvaluatedParametersSystemEqns; annotation(__OpenModelica_Interface="backend"); diff --git a/Compiler/BackEnd/FindZeroCrossings.mo b/Compiler/BackEnd/FindZeroCrossings.mo index 7aaacd0f18e..6fb62121ac9 100644 --- a/Compiler/BackEnd/FindZeroCrossings.mo +++ b/Compiler/BackEnd/FindZeroCrossings.mo @@ -50,7 +50,6 @@ protected import BackendVariable; protected import CheckModel; protected import ComponentReference; protected import DAEDump; -protected import Debug; protected import Error; protected import Expression; protected import ExpressionDump; @@ -243,22 +242,23 @@ protected function encapsulateWhenConditions_EqSystem "author: lochel" output BackendDAE.EqSystem outEqSystem; output Integer outIndex; output HashTableExpToIndex.HashTable outHT; -protected - BackendDAE.Variables orderedVars; - BackendDAE.EquationArray orderedEqs; - BackendDAE.StateSets stateSets; - BackendDAE.BaseClockPartitionKind partitionKind; - list varLst; - list eqnLst; algorithm - BackendDAE.EQSYSTEM(orderedVars=orderedVars, orderedEqs=orderedEqs, stateSets=stateSets, partitionKind=partitionKind) := inEqSystem; - - ((orderedEqs, varLst, eqnLst, outIndex, outHT)) := BackendEquation.traverseEquationArray(orderedEqs, encapsulateWhenConditions_Equation, (BackendEquation.emptyEqns(), {}, {}, inIndex, inHT)); - - orderedVars := BackendVariable.addVars(varLst, orderedVars); - orderedEqs := BackendEquation.addEquations(eqnLst, orderedEqs); - - outEqSystem := BackendDAEUtil.createEqSystem(orderedVars, orderedEqs, stateSets, partitionKind); + outEqSystem := match inEqSystem + local + BackendDAE.Variables orderedVars; + BackendDAE.EquationArray orderedEqs; + BackendDAE.EqSystem syst; + list varLst; + list eqnLst; + case syst as BackendDAE.EQSYSTEM(orderedVars=orderedVars, orderedEqs=orderedEqs) + algorithm + ((orderedEqs, varLst, eqnLst, outIndex, outHT)) := + BackendEquation.traverseEquationArray( orderedEqs, encapsulateWhenConditions_Equation, + (BackendEquation.emptyEqns(), {}, {}, inIndex, inHT) ); + syst.orderedVars := BackendVariable.addVars(varLst, orderedVars); + syst.orderedEqs := BackendEquation.addEquations(eqnLst, orderedEqs); + then BackendDAEUtil.clearEqSyst(syst); + end match; end encapsulateWhenConditions_EqSystem; protected function encapsulateWhenConditions_Equation "author: lochel" diff --git a/Compiler/BackEnd/HpcOmEqSystems.mo b/Compiler/BackEnd/HpcOmEqSystems.mo index 0f720aa6dcc..b7fc94cc061 100644 --- a/Compiler/BackEnd/HpcOmEqSystems.mo +++ b/Compiler/BackEnd/HpcOmEqSystems.mo @@ -53,7 +53,6 @@ protected import BackendDAETransform; protected import BackendVariable; protected import BackendVarTransform; protected import ComponentReference; -protected import Debug; protected import Expression; protected import ExpressionSimplify; protected import ExpressionSolve; diff --git a/Compiler/BackEnd/HpcOmMemory.mo b/Compiler/BackEnd/HpcOmMemory.mo index 7e82478d321..ebcd48de518 100644 --- a/Compiler/BackEnd/HpcOmMemory.mo +++ b/Compiler/BackEnd/HpcOmMemory.mo @@ -30,31 +30,33 @@ */ encapsulated package HpcOmMemory - public import BackendDAE; - public import DAE; - public import HashTableCrILst; - public import HpcOmSimCode; - public import HpcOmTaskGraph; - public import SimCode; - public import SimCodeVar; - - protected import Array; - protected import BackendDAEUtil; - protected import BackendDump; - protected import BackendEquation; - protected import BackendVariable; - protected import BaseHashTable; - protected import ComponentReference; - protected import Config; - protected import Debug; - protected import Error; - protected import Expression; - protected import Flags; - protected import GraphML; - protected import HpcOmScheduler; - protected import List; - protected import SimCodeUtil; - protected import Util; +import BackendDAE; +import DAE; +import HashTableCrILst; +import HpcOmSimCode; +import HpcOmTaskGraph; +import SimCode; +import SimCodeVar; + +protected + +import Array; +import BackendDAEUtil; +import BackendDump; +import BackendEquation; +import BackendVariable; +import BaseHashTable; +import ComponentReference; +import Config; +import Error; +import Expression; +import Flags; +import GraphML; +import HpcOmScheduler; +import List; +import SimCodeUtil; +import SimCodeFunctionUtil; +import Util; // ------------------------------------------- // STRUCTURES @@ -2867,7 +2869,7 @@ encapsulated package HpcOmMemory threadText := "Th -1"; if(Util.isSome(simVarOpt)) then simVar := Util.getOption(simVarOpt); - varCompRef := SimCodeUtil.varName(simVar); + varCompRef := SimCodeFunctionUtil.varName(simVar); description := ComponentReference.printComponentRefStr(varCompRef); isValidVar := BaseHashTable.hasKey(varCompRef, iVarNameSCVarIdxMapping); diff --git a/Compiler/BackEnd/HpcOmScheduler.mo b/Compiler/BackEnd/HpcOmScheduler.mo index 91b30c17c9b..5cfd86a40ec 100644 --- a/Compiler/BackEnd/HpcOmScheduler.mo +++ b/Compiler/BackEnd/HpcOmScheduler.mo @@ -42,22 +42,23 @@ public import HpcOmSimCode; public import SimCode; public import SimCodeVar; -protected import Absyn; -protected import Array; -protected import BackendDAEUtil; -protected import BackendVarTransform; -protected import ComponentReference; -protected import DAE; -protected import Debug; -protected import Error; -protected import Expression; -protected import Flags; -protected import HpcOmSchedulerExt; -protected import HpcOmSimCodeMain; -protected import List; -protected import SimCodeUtil; -protected import System; -protected import Util; +protected +import Absyn; +import Array; +import BackendDAEUtil; +import BackendVarTransform; +import ComponentReference; +import DAE; +import Error; +import Expression; +import Flags; +import HpcOmSchedulerExt; +import HpcOmSimCodeMain; +import List; +import SimCodeUtil; +import SimCodeFunctionUtil; +import System; +import Util; public type TaskAssignment = array; //the information which node is assigned to which processor @@ -183,7 +184,7 @@ protected HpcOmSimCode.Schedule tmpSchedule; array> allCalcTasks; algorithm - (oSchedule,oThreadReadyTimes) := matchcontinue(iNodeList,iThreadReadyTimes, iTaskGraph, iTaskGraphT, iCommCosts, iCompTaskMapping, + (oSchedule,oThreadReadyTimes) := match(iNodeList,iThreadReadyTimes, iTaskGraph, iTaskGraphT, iCommCosts, iCompTaskMapping, iSccSimEqMapping, iSimVarMapping, iLockWithPredecessorHandler, iSchedule) case((head as HpcOmSimCode.CALCTASK(weighting=weighting,index=index,calcTime=calcTime,eqIdc=(eqIdc as firstEq::_))) ::rest,_,_,_,_,_,_,_,_,HpcOmSimCode.THREADSCHEDULE(threadTasks=allThreadTasks, outgoingDepTasks=outgoingDepTasks,allCalcTasks=allCalcTasks)) @@ -191,70 +192,52 @@ algorithm //get all predecessors (childs) (predecessors, _) = getSuccessorsByTask(head, iTaskGraphT, allCalcTasks); (successors, successorIdc) = getSuccessorsByTask(head, iTaskGraph, allCalcTasks); - false = listEmpty(predecessors); //in this case the node has predecessors - //get last child finished time - lastChild = getTaskWithHighestFinishTime(predecessors, NONE()); - HpcOmSimCode.CALCTASK(timeFinished=lastChildFinishTime) = lastChild; - //find the best thread for scheduling + if(boolNot(listEmpty(predecessors))) then //in this case the node has predecessors + lastChild = getTaskWithHighestFinishTime(predecessors, NONE()); + HpcOmSimCode.CALCTASK(timeFinished=lastChildFinishTime) = lastChild; + else + lastChildFinishTime = 0.0; + end if; + threadFinishTimes = calculateFinishTimes(lastChildFinishTime, head, predecessors, iCommCosts, iThreadReadyTimes); ((threadId, threadFinishTime)) = getThreadFinishTimesMin(1,threadFinishTimes,-1,0.0); tmpThreadReadyTimes = arrayUpdate(iThreadReadyTimes, threadId, threadFinishTime); threadTasks = arrayGet(allThreadTasks,threadId); - //find all predecessors which are scheduled to another thread and thus require a lock - //print("\tDort: Scheduling task " + intString(index) + " to thread " + intString(threadId) + "\n"); - (lockTasks,newOutgoingDepTasks) = iLockWithPredecessorHandler(head,predecessors,threadId,iCommCosts,iCompTaskMapping,iSimVarMapping); - outgoingDepTasks = listAppend(outgoingDepTasks,newOutgoingDepTasks); - //threadTasks = listAppend(List.map(newLockIdc,convertLockIdToAssignTask), threadTasks); - threadTasks = listAppend(lockTasks, threadTasks); - - //print("Eq idc: " + stringDelimitList(List.map(eqIdc, intString), ",") + "\n"); - simEqIdc = List.map(List.map1(eqIdc,getSimEqSysIdxForComp,iSccSimEqMapping), List.last); - //simEqIdc = List.sort(simEqIdc,intGt); + //print("Scheduling task " + intString(index) + " to thread " + intString(threadId) + "\n"); + if(boolNot(listEmpty(predecessors))) then //in this case the node has predecessors + //find all predecessors which are scheduled to another thread and thus require a lock + (lockTasks,newOutgoingDepTasks) = iLockWithPredecessorHandler(head,predecessors,threadId,iCommCosts,iCompTaskMapping,iSimVarMapping); + outgoingDepTasks = listAppend(outgoingDepTasks,newOutgoingDepTasks); + //threadTasks = listAppend(List.map(newLockIdc,convertLockIdToAssignTask), threadTasks); + threadTasks = listAppend(lockTasks, threadTasks); + + //print("Eq idc: " + stringDelimitList(List.map(eqIdc, intString), ",") + "\n"); + simEqIdc = List.map(List.map1(eqIdc,getSimEqSysIdxForComp,iSccSimEqMapping), List.last); + //simEqIdc = List.sort(simEqIdc,intGt); + else + simEqIdc = List.flatten(List.map1(eqIdc,getSimEqSysIdxForComp,iSccSimEqMapping)); + end if; newTask = HpcOmSimCode.CALCTASK(weighting,index,calcTime,threadFinishTime,threadId,simEqIdc); threadTasks = newTask::threadTasks; allThreadTasks = arrayUpdate(allThreadTasks,threadId,threadTasks); - //print("Successors: " + stringDelimitList(List.map(successorIdc, intString), ",") + "\n"); - //add all successors with refcounter = 1 - (allCalcTasks,tmpNodeList) = updateRefCounterBySuccessorIdc(allCalcTasks,successorIdc,{}); - tmpNodeList = listAppend(tmpNodeList, rest); - tmpNodeList = List.sort(tmpNodeList, compareTasksByWeighting); - ((_,newTaskRefCount)) = arrayGet(allCalcTasks,index); - arrayUpdate(allCalcTasks,index,(newTask,newTaskRefCount)); - (tmpSchedule,tmpThreadReadyTimes) = createListSchedule1(tmpNodeList,tmpThreadReadyTimes,iTaskGraph, iTaskGraphT, iCommCosts, iCompTaskMapping, iSccSimEqMapping, iSimVarMapping, iLockWithPredecessorHandler, HpcOmSimCode.THREADSCHEDULE(allThreadTasks,outgoingDepTasks,{},allCalcTasks)); - then (tmpSchedule,tmpThreadReadyTimes); - case((head as HpcOmSimCode.CALCTASK(weighting=weighting,index=index,calcTime=calcTime,eqIdc=(eqIdc as firstEq::_)))::rest - ,_,_,_,_,_,_,_,_, - HpcOmSimCode.THREADSCHEDULE(threadTasks=allThreadTasks,outgoingDepTasks=outgoingDepTasks,allCalcTasks=allCalcTasks)) - equation - (successors, successorIdc) = getSuccessorsByTask(head, iTaskGraph, allCalcTasks); - //find the best thread for scheduling - threadFinishTimes = calculateFinishTimes(0.0, head, {}, iCommCosts, iThreadReadyTimes); - ((threadId, threadFinishTime)) = getThreadFinishTimesMin(1,threadFinishTimes,-1,0.0); - - tmpThreadReadyTimes = arrayUpdate(iThreadReadyTimes, threadId, threadFinishTime); - threadTasks = arrayGet(allThreadTasks,threadId); - simEqIdc = List.flatten(List.map1(eqIdc,getSimEqSysIdxForComp,iSccSimEqMapping)); - newTask = HpcOmSimCode.CALCTASK(weighting,index,calcTime,threadFinishTime,threadId,simEqIdc); - allThreadTasks = arrayUpdate(allThreadTasks,threadId,newTask::threadTasks); //add all successors with refcounter = 1 (allCalcTasks,tmpNodeList) = updateRefCounterBySuccessorIdc(allCalcTasks,successorIdc,{}); tmpNodeList = listAppend(tmpNodeList, rest); tmpNodeList = List.sort(tmpNodeList, compareTasksByWeighting); ((_,newTaskRefCount)) = arrayGet(allCalcTasks,index); arrayUpdate(allCalcTasks,index,(newTask,newTaskRefCount)); - //print("\tHier, task " + intString(index) + "\n"); - (tmpSchedule,tmpThreadReadyTimes) = createListSchedule1(tmpNodeList, tmpThreadReadyTimes, iTaskGraph, iTaskGraphT, iCommCosts, iCompTaskMapping, iSccSimEqMapping, iSimVarMapping, iLockWithPredecessorHandler, HpcOmSimCode.THREADSCHEDULE(allThreadTasks,outgoingDepTasks,{},allCalcTasks)); + (tmpSchedule,tmpThreadReadyTimes) = createListSchedule1(tmpNodeList,tmpThreadReadyTimes,iTaskGraph, iTaskGraphT, iCommCosts, iCompTaskMapping, iSccSimEqMapping, iSimVarMapping, iLockWithPredecessorHandler, HpcOmSimCode.THREADSCHEDULE(allThreadTasks,outgoingDepTasks,{},allCalcTasks)); then (tmpSchedule,tmpThreadReadyTimes); case({},_,_,_,_,_,_,_,_,_) then (iSchedule,iThreadReadyTimes); else equation print("HpcOmScheduler.createListSchedule1 failed\n"); - then fail(); - end matchcontinue; + then (iSchedule,iThreadReadyTimes); + end match; end createListSchedule1; @@ -2156,7 +2139,6 @@ algorithm (threadIdx, taskList) := iIdxTaskList; for taskIdx in iTaskList loop components := arrayGet(iComps, taskIdx); //Components of the task - //print("createFixedLevelScheduleForLevel0: Handling task with idx: " + intString(taskIdx) + "\n"); simEqs := List.flatten(List.map(List.map1(components,Array.getIndexFirst,iSccSimEqMapping), listReverse)); if(intGt(listLength(simEqs), 0)) then simEqs := simEqs; @@ -3296,7 +3278,7 @@ algorithm threadIdx = 1; compIdx = arrayLength(iSccSimEqMapping)+1; // the next available component index taskIdx = arrayLength(iTaskGraph)+1; - simVarIdx = List.fold(List.map(algVars,SimCodeUtil.varIndex),intMax,0)+1;// the next available simVar index + simVarIdx = List.fold(List.map(algVars,SimCodeFunctionUtil.varIndex),intMax,0)+1;// the next available simVar index simEqSysIdx = SimCodeUtil.getMaxSimEqSystemIndex(iSimCode)+1;// the next available simEqSys index lsIdx = List.fold(List.map(List.flatten(odes),SimCodeUtil.getLSindex),intMax,0)+1;// the next available linear system index nlsIdx = List.fold(List.map(List.flatten(odes),SimCodeUtil.getNLSindex),intMax,0)+1;// the next available nonlinear system index @@ -3993,7 +3975,7 @@ algorithm crefLst := List.map1(simEqSysIdcs,SimCodeUtil.getAssignedCrefsOfSimEq,simCodeIn); crefs := List.flatten(crefLst); //print("crefs :\n"+stringDelimitList(List.map(crefs,ComponentReference.debugPrintComponentRefTypeStr),"\n")+"\n"); - simVarLst := List.map1(crefs,SimCodeUtil.get,ht); + simVarLst := List.map1(crefs,SimCodeFunctionUtil.get,ht); // build the new crefs, new simVars numVars := listLength(simVarLst); @@ -5494,7 +5476,7 @@ author:Waurich TUD 2013-10" output array tdsLevelOut; // = the longest path to a leaf node, considering only execution costs (no! commCosts), used for tds protected Integer size, lastNodeInCP; - Real cp,cpWithComm, lastExeCost; + Real cp,cpWithComm; list endNodes; array alap, lact, last, tdsLevel; array> taskGraphT; @@ -5512,7 +5494,6 @@ algorithm (alap,last,lact,tdsLevelOut) := computeGraphValuesTopDown1(endNodes,iTaskGraph,taskGraphT,iTaskGraphMeta,alap,last,lact,tdsLevel,visitedNodes); cpWithComm := Array.fold(alap,realMax,0.0); lastNodeInCP := Array.position(alap,cpWithComm,size); - lastExeCost := HpcOmTaskGraph.getExeCostReqCycles(lastNodeInCP,iTaskGraphMeta); cp := Array.fold(last,realMax,0.0); alapOut := Array.map1(alap,realSubr,cpWithComm); lactOut := Array.map1(lact,realSubr,cp); @@ -5759,7 +5740,6 @@ algorithm parTime := HpcOmTaskGraph.roundReal(parTime,2); oCriticalPathInfo := HpcOmTaskGraph.dumpCriticalPathInfo((criticalPaths,cpCosts),(criticalPathsWoC,cpCostsWoC)); cpCostsWoC := HpcOmTaskGraph.roundReal(cpCostsWoC,2); - if Flags.isSet(Flags.HPCOM_DUMP) then print("the serialCosts: "+realString(serTime)+"\n"); print("the parallelCosts: "+realString(parTime)+"\n"); @@ -5771,7 +5751,16 @@ algorithm i := i + 1; end for; end if; - printPredictedExeTimeInfo(serTime,parTime,realDiv(serTime,parTime),realDiv(serTime,cpCostsWoC),iNumProc); + speedUp := 0.0; + speedUpMax := 0.0; + if(realNe(parTime, 0.0)) then + speedUp := realDiv(serTime,parTime); + end if; + if(realNe(cpCostsWoC, 0.0)) then + speedUpMax := realDiv(serTime,cpCostsWoC); + end if; + + printPredictedExeTimeInfo(serTime,parTime,speedUp,speedUpMax,iNumProc); end analyseScheduledTaskGraphLevel; protected function getLevelParallelTime"computes the the time for the parallel computation of a parallel section @@ -6398,29 +6387,32 @@ public function convertFixedLevelScheduleToTaskLists author:marcusw" input HpcOmSimCode.Schedule iOdeSchedule; //mapping level -> tasks input HpcOmSimCode.Schedule iDaeSchedule; + input HpcOmSimCode.Schedule iZeroFuncSchedule; input Integer iNumOfThreads; - output array>,list>>> oThreadLevelTasks; //mapping thread -> (level -> tasks ODE, level -> tasks DAE) + output array>,list>,list>>> oThreadLevelTasks; //mapping thread -> (level -> tasks ODE, level -> tasks DAE, level -> tasks ZeroFunc) protected - list tasksOfLevelsOde, tasksOfLevelsDae; - list>> tmpThreadLevelTasksDae, tmpThreadLevelTasksOde; //level -> thread -> tasklist - array>, list>>> tmpResultLists; + list tasksOfLevelsOde, tasksOfLevelsDae, tasksOfLevelsZeroFunc; + list>> tmpThreadLevelTasksDae, tmpThreadLevelTasksOde, tmpThreadLevelTasksZeroFunc; //level -> thread -> tasklist + array>, list>, list>>> tmpResultLists; algorithm - oThreadLevelTasks := match(iOdeSchedule, iDaeSchedule, iNumOfThreads) - case(HpcOmSimCode.LEVELSCHEDULE(tasksOfLevels=tasksOfLevelsOde,useFixedAssignments=true),HpcOmSimCode.LEVELSCHEDULE(tasksOfLevels=tasksOfLevelsDae,useFixedAssignments=true),_) + oThreadLevelTasks := match(iOdeSchedule, iDaeSchedule, iZeroFuncSchedule, iNumOfThreads) + case(HpcOmSimCode.LEVELSCHEDULE(tasksOfLevels=tasksOfLevelsOde,useFixedAssignments=true),HpcOmSimCode.LEVELSCHEDULE(tasksOfLevels=tasksOfLevelsDae,useFixedAssignments=true),HpcOmSimCode.LEVELSCHEDULE(tasksOfLevels=tasksOfLevelsZeroFunc,useFixedAssignments=true),_) equation - tmpResultLists = arrayCreate(iNumOfThreads, ({},{})); + tmpResultLists = arrayCreate(iNumOfThreads, ({},{},{})); tmpThreadLevelTasksOde = List.map1(tasksOfLevelsOde, convertFixedLevelScheduleToTaskListsForLevel, iNumOfThreads); tmpThreadLevelTasksDae = List.map1(tasksOfLevelsDae, convertFixedLevelScheduleToTaskListsForLevel, iNumOfThreads); + tmpThreadLevelTasksZeroFunc = List.map1(tasksOfLevelsZeroFunc, convertFixedLevelScheduleToTaskListsForLevel, iNumOfThreads); //print("convertFixedLevelScheduleToTaskLists: len of tmpThreadLevelTasksOde=" + intString(listLength(tmpThreadLevelTasksOde)) + "\n"); - tmpResultLists = List.fold(tmpThreadLevelTasksOde, function convertFixedLevelScheduleToTaskLists1(iCurrentThreadIdx=1, iModifyOdeSystem=true), tmpResultLists); - tmpResultLists = List.fold(tmpThreadLevelTasksDae, function convertFixedLevelScheduleToTaskLists1(iCurrentThreadIdx=1, iModifyOdeSystem=false), tmpResultLists); + tmpResultLists = List.fold(tmpThreadLevelTasksOde, function convertFixedLevelScheduleToTaskLists1(iCurrentThreadIdx=1, iModifiedSystemIdx=0), tmpResultLists); + tmpResultLists = List.fold(tmpThreadLevelTasksDae, function convertFixedLevelScheduleToTaskLists1(iCurrentThreadIdx=1, iModifiedSystemIdx=1), tmpResultLists); + tmpResultLists = List.fold(tmpThreadLevelTasksZeroFunc, function convertFixedLevelScheduleToTaskLists1(iCurrentThreadIdx=1, iModifiedSystemIdx=2), tmpResultLists); //print("convertFixedLevelScheduleToTaskLists: len of tmpResultLists[0]=" + intString(listLength(Util.tuple21(arrayGet(tmpResultLists, 1)))) + "\n"); tmpResultLists = revertTaskLists(1, tmpResultLists); //print("convertFixedLevelScheduleToTaskLists: len of tmpResultLists[0]=" + intString(listLength(Util.tuple21(arrayGet(tmpResultLists, 1)))) + "\n"); then tmpResultLists; else equation - tmpResultLists = arrayCreate(iNumOfThreads, ({},{})); + tmpResultLists = arrayCreate(iNumOfThreads, ({},{},{})); then tmpResultLists; end match; end convertFixedLevelScheduleToTaskLists; @@ -6430,25 +6422,29 @@ protected function convertFixedLevelScheduleToTaskLists1 author:marcusw" input array> iLevelTasks; input Integer iCurrentThreadIdx; - input Boolean iModifyOdeSystem; - input array>, list>>> iResultList; - output array>, list>>> oResultList; + input Integer iModifiedSystemIdx; //0 = ODE, 1 = DAE, 2 = ZeroFunc + input array>, list>, list>>> iResultList; + output array>, list>, list>>> oResultList; protected - array>, list>>> tmpResultList; - list> entryOde, entryDae; + array>, list>, list>>> tmpResultList; + list> entryOde, entryDae, entryZeroFunc; algorithm - oResultList := matchcontinue(iLevelTasks, iCurrentThreadIdx, iModifyOdeSystem, iResultList) + oResultList := matchcontinue(iLevelTasks, iCurrentThreadIdx, iModifiedSystemIdx, iResultList) case(_,_,_,_) equation true = intLe(iCurrentThreadIdx, arrayLength(iLevelTasks)); - (entryOde, entryDae) = arrayGet(iResultList, iCurrentThreadIdx); - if(iModifyOdeSystem) then + (entryOde, entryDae, entryZeroFunc) = arrayGet(iResultList, iCurrentThreadIdx); + if(intEq(iModifiedSystemIdx,0)) then entryOde = arrayGet(iLevelTasks, iCurrentThreadIdx)::entryOde; else - entryDae = arrayGet(iLevelTasks, iCurrentThreadIdx)::entryDae; + if(intEq(iModifiedSystemIdx, 1)) then + entryDae = arrayGet(iLevelTasks, iCurrentThreadIdx)::entryDae; + else + entryZeroFunc = arrayGet(iLevelTasks, iCurrentThreadIdx)::entryZeroFunc; + end if; end if; - tmpResultList = arrayUpdate(iResultList, iCurrentThreadIdx, (entryOde, entryDae)); - tmpResultList = convertFixedLevelScheduleToTaskLists1(iLevelTasks, iCurrentThreadIdx+1, iModifyOdeSystem, tmpResultList); + tmpResultList = arrayUpdate(iResultList, iCurrentThreadIdx, (entryOde, entryDae, entryZeroFunc)); + tmpResultList = convertFixedLevelScheduleToTaskLists1(iLevelTasks, iCurrentThreadIdx+1, iModifiedSystemIdx, tmpResultList); then tmpResultList; else iResultList; end matchcontinue; @@ -6456,20 +6452,21 @@ end convertFixedLevelScheduleToTaskLists1; protected function revertTaskLists input Integer iCurrentArrayIdx; - input array>, list>>> iResultList; - output array>, list>>> oResultList; + input array>, list>, list>>> iResultList; + output array>, list>, list>>> oResultList; protected - list> entryOde, entryDae; - array>, list>>> tmpResultList; + list> entryOde, entryDae, entryZeroFunc; + array>, list>, list>>> tmpResultList; algorithm oResultList := matchcontinue(iCurrentArrayIdx, iResultList) case(_,_) equation true = intLe(iCurrentArrayIdx, arrayLength(iResultList)); - ((entryOde,entryDae)) = arrayGet(iResultList, iCurrentArrayIdx); + ((entryOde,entryDae,entryZeroFunc)) = arrayGet(iResultList, iCurrentArrayIdx); entryOde = listReverse(entryOde); entryDae = listReverse(entryDae); - tmpResultList = arrayUpdate(iResultList, iCurrentArrayIdx, (entryOde,entryDae)); + entryZeroFunc = listReverse(entryZeroFunc); + tmpResultList = arrayUpdate(iResultList, iCurrentArrayIdx, (entryOde,entryDae,entryZeroFunc)); tmpResultList = revertTaskLists(iCurrentArrayIdx+1, tmpResultList); then tmpResultList; else iResultList; @@ -6502,7 +6499,7 @@ end revertTaskList; //---------------- protected function setScheduleLockIds "Function creates unique Ids for every tuple of out and ingoing locks - author: mhartung" + author: mhartung" input HpcOmSimCode.Schedule iSchedule; output HpcOmSimCode.Schedule oSchedule; protected @@ -6572,7 +6569,7 @@ algorithm end replaceDepTasksInListByLockIds; -protected function findTaskWithLockId "Function returns a DepTask with the id regarding lockIds or the identity of the given task" +protected function findTaskWithLockId "Function returns a DepTask with the id regarding lockIds or the identity of the given task" input array>> lockIds; input HpcOmSimCode.Task iTask; output HpcOmSimCode.Task oTask; @@ -6708,4 +6705,4 @@ end intListListString; annotation(__OpenModelica_Interface="backend"); -end HpcOmScheduler; \ No newline at end of file +end HpcOmScheduler; diff --git a/Compiler/BackEnd/HpcOmTaskGraph.mo b/Compiler/BackEnd/HpcOmTaskGraph.mo index 0feebf82cd3..b3887abe2dc 100644 --- a/Compiler/BackEnd/HpcOmTaskGraph.mo +++ b/Compiler/BackEnd/HpcOmTaskGraph.mo @@ -48,10 +48,8 @@ protected import BackendEquation; protected import BackendVariable; protected import ComponentReference; protected import DAEDump; -protected import Debug; protected import Error; protected import Expression; -protected import ExpressionSolve; protected import Flags; protected import HpcOmBenchmark; protected import HpcOmEqSystems; @@ -87,7 +85,7 @@ end Communication; public uniontype ComponentInfo record COMPONENTINFO Boolean isPartOfODESystem; // true if the component belongs to the ode system - Boolean isPartOfEventSystem; // true if the component belongs to the event system + Boolean isPartOfZeroFuncSystem; // true if the component belongs to the event system Boolean isRemovedComponent; // true if the component was added via appendRemovedEquations (e.g. it is a assert) end COMPONENTINFO; end ComponentInfo; @@ -103,7 +101,7 @@ public uniontype TaskGraphMeta // stores all the metadata for the TaskGraph array> compParamMapping; // maps each scc to a list of parameters that are required for calculation. The indices are related to the known-parameter object of SHARED. array compNames; // the name of the components (e.g. '{18:7}') array compDescs; // a description of the components (e.g. 'R5.R * R5.i = C2.vinternal FOR R5.i') - array> exeCosts; // the execution cost for the nodes + array> exeCosts; // the execution cost for the components array commCosts; // the communication cost tuple(_,numberOfVars,requiredCycles) for an edge from array[parentSCC] to tuple(childSCC,_,_) array nodeMark; // used for level informations -> this is currently not a nodeMark, its a componentMark array compInformations; // used to store additional informations about the components @@ -2180,6 +2178,146 @@ end getNodesWithRefCountZero0; // Functions to get the event-graph //---------------------------------- +public function getZeroFuncsSystem "gets the graph containing all zero funcs. This graph is important for event handling. This function does not support nodes with more than one inComp! +author: marcusw" + input TaskGraph iTaskGraph; + input TaskGraphMeta iTaskGraphMeta; + input BackendDAE.BackendDAE iBackendDAE; + input Integer iNumberOfSccs; + input list iZeroCrossingEquationIdc; + input array iSimCodeEqCompMapping; + output TaskGraph oTaskGraph; + output TaskGraphMeta oTaskGraphMeta; +protected + list zeroCrossingNodes, nodeList, newNodeList, predecessors, successors, successorsTmp, predecessorsTmp; + array zeroFuncNodeMarks; //value < 0 : All successors are not part of the zero funcs system ; value > 0 : Node is part of zero funcs system + array sccNodeMapping; + array handledNodes, whenNodeMarks; + TaskGraph iTaskGraphTCopy, iTaskGraphCopy; + TaskGraph zeroFuncTaskGraph; + TaskGraphMeta zeroFuncTaskGraphMeta; + list whenNodes; + Integer inCompsEntry; + array> zeroFuncInComps, inComps; + array> eqCompMapping; + Integer eqIdx, compIdx, nodeIdx, successor, predecessor, zeroFuncNodeMark, successorMark, zeroFuncNodeCount, zeroFuncNodeIdx; + array nodeToZeroFuncNodeMapping; //mapping for each task graph node idx to zero func graph node idx + Boolean stop; +algorithm + //print("Zero crossing equations: " + stringDelimitList(List.map(iZeroCrossingEquationIdc, intString), ",") + "\n"); + TASKGRAPHMETA(inComps=inComps, eqCompMapping=eqCompMapping) := iTaskGraphMeta; + zeroFuncNodeMarks := arrayCreate(arrayLength(iTaskGraph), 0); + handledNodes := arrayCreate(arrayLength(iTaskGraph), false); + nodeToZeroFuncNodeMapping := arrayCreate(arrayLength(iTaskGraph), -1); + whenNodes := getEventNodes(iBackendDAE,eqCompMapping); + //print("Got when nodes " + stringDelimitList(List.map(whenNodes, intString), ",") + "\n"); + whenNodeMarks := arrayCreate(arrayLength(iTaskGraph), false); + sccNodeMapping := getSccNodeMapping(iNumberOfSccs, iTaskGraphMeta); + iTaskGraphCopy := arrayCopy(iTaskGraph); + iTaskGraphTCopy := BackendDAEUtil.transposeMatrix(iTaskGraph,arrayLength(iTaskGraph)); + + //Mark all nodes that are part of the zero funcs system + for eqIdx in iZeroCrossingEquationIdc loop + compIdx := arrayGet(iSimCodeEqCompMapping, eqIdx); + nodeIdx := arrayGet(sccNodeMapping, compIdx); + zeroFuncNodeMarks := arrayUpdate(zeroFuncNodeMarks, nodeIdx, 1); + //print("Setting node mark of node " + intString(nodeIdx) + " to 1\n"); + end for; + + //Mark all nodes that contains when equations + for nodeIdx in whenNodes loop + whenNodeMarks := arrayUpdate(whenNodeMarks, nodeIdx, true); + end for; + + //Traverse graph, start with leaf nodes - mark all nodes that have no successor which belongs to the zero funcs system + nodeList := getRootNodes(iTaskGraphTCopy); + zeroFuncNodeCount := 0; + zeroFuncNodeIdx := 1; + while boolNot(listEmpty(nodeList)) loop + newNodeList := {}; + for nodeIdx in nodeList loop //breath first search + //print("Handling node " + intString(nodeIdx) + "\n"); + if(boolNot(arrayGet(handledNodes, nodeIdx))) then //check if we have already handled the node + //print("\tNode was not already handled\n"); + handledNodes := arrayUpdate(handledNodes, nodeIdx, true); + predecessors := arrayGet(iTaskGraphTCopy, nodeIdx); + //print("\tPredecessors: " + stringDelimitList(List.map(predecessors, intString), ",") + "\n"); + successors := arrayGet(iTaskGraphCopy, nodeIdx); + //print("\tSuccessors: " + stringDelimitList(List.map(successors, intString), ",") + "\n"); + zeroFuncNodeMark := -1; + + if(arrayGet(whenNodeMarks, nodeIdx)) then //Check if node contains when equation -> remove if true + for predecessor in predecessors loop + successorsTmp := arrayGet(iTaskGraphCopy, predecessor); + arrayUpdate(iTaskGraphCopy, predecessor, listAppend(successorsTmp, successors)); + end for; + for successor in successors loop + predecessorsTmp := arrayGet(iTaskGraphTCopy, successor); + arrayUpdate(iTaskGraphTCopy, successor, listAppend(predecessorsTmp, predecessors)); + end for; + else + if(intGt(arrayGet(zeroFuncNodeMarks, nodeIdx), 0)) then + zeroFuncNodeMark := zeroFuncNodeIdx; + else + stop := false; + while(boolAnd(boolNot(stop), boolNot(listEmpty(successors)))) loop + //print("\tSuccessor list not empty\n"); + successor::successors := successors; + successorMark := arrayGet(zeroFuncNodeMarks, successor); + if(intGt(successorMark, 0)) then + zeroFuncNodeMark := zeroFuncNodeIdx; + stop := true; + end if; + end while; + end if; + + if(intGt(zeroFuncNodeMark, 0)) then + zeroFuncNodeCount := zeroFuncNodeCount + 1; + nodeToZeroFuncNodeMapping := arrayUpdate(nodeToZeroFuncNodeMapping, nodeIdx, zeroFuncNodeCount); + zeroFuncNodeIdx := zeroFuncNodeIdx + 1; + end if; + //print("\tSetting node mark to " + intString(zeroFuncNodeMark) + "\n"); + end if; + zeroFuncNodeMarks := arrayUpdate(zeroFuncNodeMarks, nodeIdx, zeroFuncNodeMark); + newNodeList := listAppend(newNodeList, predecessors); //add all nodes of previous level + end if; + end for; + nodeList := newNodeList; + end while; + + //Setup a new graph that contains only nodes which are part of the event system + zeroFuncTaskGraph := arrayCreate(zeroFuncNodeCount, {}); + zeroFuncInComps := arrayCreate(zeroFuncNodeCount, {}); + + //Setup the adjacence list for the new graph + nodeIdx := arrayLength(zeroFuncNodeMarks); + while (intGt(nodeIdx, 0)) loop + zeroFuncNodeIdx := arrayGet(zeroFuncNodeMarks, nodeIdx); + if(intGt(zeroFuncNodeIdx, 0)) then //node is part of zero func system + successors := arrayGet(iTaskGraphCopy, nodeIdx); + //print("Node " + intString(nodeIdx) + " is part of zero func system\n"); + //print("Components are: " + stringDelimitList(List.map(arrayGet(inComps, nodeIdx), intString), ",") + "\n"); + zeroFuncInComps := arrayUpdate(zeroFuncInComps, zeroFuncNodeIdx, arrayGet(inComps, nodeIdx)); + newNodeList := {}; + while(boolNot(listEmpty(successors))) loop + successor::successors := successors; + successor := arrayGet(zeroFuncNodeMarks, successor); + if(intGt(successor, 0)) then //successor is part of zero func system + newNodeList := successor::newNodeList; + end if; + end while; + zeroFuncTaskGraph := arrayUpdate(zeroFuncTaskGraph, zeroFuncNodeIdx, newNodeList); + end if; + nodeIdx := nodeIdx - 1; + end while; + + zeroFuncTaskGraphMeta := copyTaskGraphMeta(iTaskGraphMeta); + zeroFuncTaskGraphMeta := setInCompsInMeta(zeroFuncInComps, zeroFuncTaskGraphMeta); + + oTaskGraph := zeroFuncTaskGraph; + oTaskGraphMeta := zeroFuncTaskGraphMeta; +end getZeroFuncsSystem; + public function getEventSystem "gets the graph and the adjacencyLst only for the EventSystem. This means that all branches which leads to a node solving a whencondition or another boolean condition will remain. author: marcusw" @@ -2231,10 +2369,10 @@ algorithm case(BackendDAE.ZERO_CROSSING(occurEquLst=occurEquLst), _) equation occurEquLst = List.filter1OnTrue(occurEquLst, intGt, 0); - //print("getComponentsOfZeroCrossing: simEqs: " + stringDelimitList(List.map(occurEquLst, intString), ",") + "\n"); + print("getComponentsOfZeroCrossing: simEqs: " + stringDelimitList(List.map(occurEquLst, intString), ",") + "\n"); tmpCompIdc = List.map1(occurEquLst, Array.getIndexFirst, iSimCodeEqCompMapping); tmpCompIdc = List.filter1OnTrue(tmpCompIdc, intGt, 0); - //print("getComponentsOfZeroCrossing: components: " + stringDelimitList(List.map(tmpCompIdc, intString), ",") + "\n"); + print("getComponentsOfZeroCrossing: components: " + stringDelimitList(List.map(tmpCompIdc, intString), ",") + "\n"); then tmpCompIdc; else {}; end matchcontinue; @@ -2470,7 +2608,7 @@ algorithm name := ("TaskGraph_"+fileName+".graphml"); schedulerInfo := arrayCreate(arrayLength(taskGraph), (-1,-1,-1.0)); sccSimEqMapping := arrayCreate(arrayLength(taskGraph),{-1}); - HpcOmTaskGraph.dumpAsGraphMLSccLevel(taskGraph, taskGraphData,dae, name, "", {}, {}, sccSimEqMapping, schedulerInfo, HpcOmTaskGraph.GRAPHDUMPOPTIONS(false,false,true,true)); + HpcOmTaskGraph.dumpAsGraphMLSccLevel(taskGraph, taskGraphData, name, "", {}, {}, sccSimEqMapping, schedulerInfo, HpcOmTaskGraph.GRAPHDUMPOPTIONS(false,false,true,true)); end dumpTaskGraph; public function dumpBipartiteGraph @@ -2502,7 +2640,6 @@ public function dumpAsGraphMLSccLevel "author: marcusw, waurich Write out the given graph as a graphml file." input TaskGraph iGraph; input TaskGraphMeta iGraphData; - input BackendDAE.BackendDAE iBackendDAE; input String iFileName; input String iCriticalPathInfo; //Critical path as String input list> iCriticalPath; //Critical path as list of edges @@ -2513,7 +2650,7 @@ public function dumpAsGraphMLSccLevel "author: marcusw, waurich protected GraphML.GraphInfo graphInfo; algorithm - graphInfo := convertToGraphMLSccLevel(iGraph,iGraphData,iBackendDAE,iCriticalPathInfo,iCriticalPath,iCriticalPathWoC,iSccSimEqMapping,iSchedulerInfo,iGraphDumpOptions); + graphInfo := convertToGraphMLSccLevel(iGraph,iGraphData,iCriticalPathInfo,iCriticalPath,iCriticalPathWoC,iSccSimEqMapping,iSchedulerInfo,iGraphDumpOptions); GraphML.dumpGraph(graphInfo, iFileName); end dumpAsGraphMLSccLevel; @@ -2521,7 +2658,6 @@ public function convertToGraphMLSccLevel "author: marcusw, waurich Convert the given graph into a graphml-structure." input TaskGraph iGraph; input TaskGraphMeta iGraphData; - input BackendDAE.BackendDAE iBackendDAE; input String iCriticalPathInfo; //Critical path as String input list> iCriticalPath; //Critical path as list of edges input list> iCriticalPathWoC; //Critical path without communciation as list of edges @@ -2581,7 +2717,7 @@ algorithm (graphInfo,(_,commVarsBoolAttIdx)) = GraphML.addAttribute("-1", "CommVarsBool", GraphML.TYPE_INTEGER(), GraphML.TARGET_EDGE(), graphInfo); (graphInfo,(_,annotAttIdx)) = GraphML.addAttribute("annotation", "Annotations", GraphML.TYPE_STRING(), GraphML.TARGET_NODE(), graphInfo); (graphInfo,(_,critPathAttIdx)) = GraphML.addAttribute("", "CriticalPath", GraphML.TYPE_STRING(), GraphML.TARGET_GRAPH(), graphInfo); - (graphInfo,(_,partOfEventAttIdx)) = GraphML.addAttribute("false", "IsPartOfEventSystem", GraphML.TYPE_BOOLEAN(), GraphML.TARGET_NODE(), graphInfo); + (graphInfo,(_,partOfEventAttIdx)) = GraphML.addAttribute("false", "isPartOfZeroFuncSystem", GraphML.TYPE_BOOLEAN(), GraphML.TARGET_NODE(), graphInfo); (graphInfo,(_,partOfOdeAttIdx)) = GraphML.addAttribute("false", "IsPartOfOdeSystem", GraphML.TYPE_BOOLEAN(), GraphML.TARGET_NODE(), graphInfo); (graphInfo,(_,removedCompAttIdx)) = GraphML.addAttribute("false", "IsRemovedComponent", GraphML.TYPE_BOOLEAN(), GraphML.TARGET_NODE(), graphInfo); graphInfo = GraphML.addGraphAttributeValue((critPathAttIdx, iCriticalPathInfo), iGraphIdx, graphInfo); @@ -2647,7 +2783,7 @@ protected list> criticalPath, criticalPathWoC; Boolean visualizeTaskStartAndFinishTime; Boolean visualizeTaskCalcTime; - Boolean isPartOfODESystem, isPartOfEventSystem, isRemovedComponent; + Boolean isPartOfODESystem, isPartOfZeroFuncSystem, isRemovedComponent; array compInformations; algorithm (tmpGraph,graphIdx) := iGraph; @@ -2658,7 +2794,7 @@ algorithm (criticalPath,criticalPathWoC,schedulerInfo,annotationInfo) := iSchedulerInfoCritPath; GRAPHDUMPOPTIONS(visualizeTaskStartAndFinishTime=visualizeTaskStartAndFinishTime, visualizeTaskCalcTime=visualizeTaskCalcTime) := iGraphDumpOptions; components := arrayGet(inComps,nodeIdx); - ((isPartOfODESystem, isPartOfEventSystem, isRemovedComponent)) := getNodeMembershipByComponents(components, compInformations); + ((isPartOfODESystem, isPartOfZeroFuncSystem, isRemovedComponent)) := getNodeMembershipByComponents(components, compInformations); if(intNe(listLength(components), 1)) then primalComp := List.last(components); @@ -2702,7 +2838,7 @@ algorithm { ((nameAttIdx,compText)),((calcTimeAttIdx,calcTimeString)),((opCountAttIdx, opCountString)),((taskIdAttIdx,componentsString)),((compsIdAttIdx,compsText)), ((yCoordAttIdx,yCoordString)),((simCodeEqAttIdx,simCodeEqString)),((threadIdAttIdx,threadIdxString)),((taskNumberAttIdx,taskNumberString)), - ((annotationAttIdx,annotationString)), ((partOfEventAttIdx, boolString(isPartOfODESystem))), ((partOfOdeAttIdx, boolString(isPartOfEventSystem))), ((removedCompAttIdx, boolString(isRemovedComponent))) + ((annotationAttIdx,annotationString)), ((partOfEventAttIdx, boolString(isPartOfODESystem))), ((partOfOdeAttIdx, boolString(isPartOfZeroFuncSystem))), ((removedCompAttIdx, boolString(isRemovedComponent))) }, graphIdx, tmpGraph); @@ -2798,9 +2934,9 @@ protected function getNodeMembershipByComponents "author: marcusw Get the information of a node was removed or belongs to the ode or event-system." input list iNodeComponents; input array iCompInformations; - output tuple oMembership; // + output tuple oMembership; // protected - Boolean isPartOfODESystem, isPartOfEventSystem, isRemovedComponent; + Boolean isPartOfODESystem, isPartOfZeroFuncSystem, isRemovedComponent; Integer compIdx; ComponentInfo tmpComponentInformation; algorithm @@ -2808,8 +2944,8 @@ algorithm for compIdx in iNodeComponents loop tmpComponentInformation := combineComponentInformations(arrayGet(iCompInformations, compIdx), tmpComponentInformation); end for; - COMPONENTINFO(isPartOfODESystem, isPartOfEventSystem, isRemovedComponent) := tmpComponentInformation; - oMembership := (isPartOfODESystem, isPartOfEventSystem, isRemovedComponent); + COMPONENTINFO(isPartOfODESystem, isPartOfZeroFuncSystem, isRemovedComponent) := tmpComponentInformation; + oMembership := (isPartOfODESystem, isPartOfZeroFuncSystem, isRemovedComponent); end getNodeMembershipByComponents; //----------------- @@ -3066,14 +3202,14 @@ public function printComponentInformations "function to print the component info protected Integer compIdx; Boolean isPartOfODESystem; - Boolean isPartOfEventSystem; + Boolean isPartOfZeroFuncSystem; Boolean isRemovedComponent; algorithm for compIdx in 1:arrayLength(iComponentInformations) loop - COMPONENTINFO(isPartOfODESystem=isPartOfODESystem,isPartOfEventSystem=isPartOfEventSystem,isRemovedComponent=isRemovedComponent) := arrayGet(iComponentInformations, compIdx); + COMPONENTINFO(isPartOfODESystem=isPartOfODESystem,isPartOfZeroFuncSystem=isPartOfZeroFuncSystem,isRemovedComponent=isRemovedComponent) := arrayGet(iComponentInformations, compIdx); print("component " + intString(compIdx) + " has component information:\n"); print(" Is part of ODE-System: " + boolString(isPartOfODESystem) + "\n"); - print(" Is part of Event-System: " + boolString(isPartOfEventSystem) + "\n"); + print(" Is part of Event-System: " + boolString(isPartOfZeroFuncSystem) + "\n"); print(" Is removed component: " + boolString(isRemovedComponent) + "\n"); end for; print("--------------------------------\n"); @@ -3449,7 +3585,7 @@ public function markSystemComponents "author: marcusw Mark all components that are part of the given Task Graph in the target task graph meta with (ComponentInfo OR iComponentInfo)" input TaskGraph iTaskGraph; input TaskGraphMeta iTaskGraphMeta; - input tuple iComponentMarks; // + input tuple iComponentMarks; // input TaskGraphMeta iTargetTaskGraphMeta; output TaskGraphMeta oTargetTaskGraphMeta; protected @@ -3474,6 +3610,7 @@ algorithm TASKGRAPHMETA(inComps,varCompMapping,eqCompMapping,compParamMapping,compNames,compDescs,exeCosts,commCosts,nodeMark,compInformations) := iTargetTaskGraphMeta; for nodeIdx in 1:arrayLength(iTaskGraph) loop nodeComps := arrayGet(odeInComps, nodeIdx); + //print("markSystemComponents: Marking components '" + stringDelimitList(List.map(nodeComps, intString), ",") + "'\n"); for compIdx in nodeComps loop componentInformation := combineComponentInformations(arrayGet(compInformations, compIdx), iComponentInformation); compInformations := arrayUpdate(compInformations, compIdx, componentInformation); @@ -3489,12 +3626,12 @@ protected function combineComponentInformations "author: marcusw output ComponentInfo oComponentInfo; protected Boolean isPartOfODESystem, iIsPartOfODESystem; - Boolean isPartOfEventSystem, iIsPartOfEventSystem; + Boolean isPartOfZeroFuncSystem, iisPartOfZeroFuncSystem; Boolean isRemovedComponent, iIsRemovedComponent; algorithm - COMPONENTINFO(isPartOfODESystem, isPartOfEventSystem, isRemovedComponent) := iComponentInfo; - COMPONENTINFO(iIsPartOfODESystem, iIsPartOfEventSystem, iIsRemovedComponent) := iComponentInfo2; - oComponentInfo := COMPONENTINFO(boolOr(isPartOfODESystem, iIsPartOfODESystem), boolOr(isPartOfEventSystem, iIsPartOfEventSystem), boolOr(isRemovedComponent, iIsRemovedComponent)); + COMPONENTINFO(isPartOfODESystem, isPartOfZeroFuncSystem, isRemovedComponent) := iComponentInfo; + COMPONENTINFO(iIsPartOfODESystem, iisPartOfZeroFuncSystem, iIsRemovedComponent) := iComponentInfo2; + oComponentInfo := COMPONENTINFO(boolOr(isPartOfODESystem, iIsPartOfODESystem), boolOr(isPartOfZeroFuncSystem, iisPartOfZeroFuncSystem), boolOr(isRemovedComponent, iIsRemovedComponent)); end combineComponentInformations; protected function addUpExeCosts @@ -3515,16 +3652,8 @@ public function getExeCostReqCycles"author: waurich input Integer iNodeIdx; input TaskGraphMeta iGraphData; output Real oExeCost; -protected - array> inComps; - list comps; - array> exeCosts; - tuple tmpExeCost; algorithm - TASKGRAPHMETA(inComps=inComps, exeCosts=exeCosts) := iGraphData; - tmpExeCost := (0,0.0); - comps := arrayGet(inComps, iNodeIdx); - ((_,oExeCost)) := List.fold1(comps, getExeCost0, exeCosts, tmpExeCost); + oExeCost := Util.tuple22(getExeCost(iNodeIdx, iGraphData)); end getExeCostReqCycles; public function getExeCost "author: marcusw @@ -3533,32 +3662,24 @@ public function getExeCost "author: marcusw input TaskGraphMeta iGraphData; output tuple oExeCost; protected + Integer comp, opCount, opCount1; + Real exeCost, exeCost1; array> inComps; list comps; array> exeCosts; - tuple tmpExeCost; algorithm TASKGRAPHMETA(inComps=inComps, exeCosts=exeCosts) := iGraphData; - tmpExeCost := (0,0.0); + exeCost := 0.0; + opCount := 0; comps := arrayGet(inComps, iNodeIdx); - oExeCost := List.fold1(comps, getExeCost0, exeCosts, tmpExeCost); + for comp in comps loop + ((opCount1,exeCost1)) := arrayGet(exeCosts, comp); + opCount := intAdd(opCount, opCount1); + exeCost := realAdd(exeCost, exeCost1); + end for; + oExeCost := ((opCount,exeCost)); end getExeCost; -protected function getExeCost0 "author: marcusw - Helper function of getExeCost." - input Integer iCompIdx; - input array> iExeCosts; - input tuple iExeCost; - output tuple oExeCost; -protected - Real exeCost, exeCost1; - Integer opCount, opCount1; -algorithm - ((opCount,exeCost)) := arrayGet(iExeCosts, iCompIdx); - (opCount1,exeCost1) := iExeCost; - oExeCost := ((opCount+opCount1,realAdd(exeCost,exeCost1))); -end getExeCost0; - protected function getHighestExecCost "function getHighestExecCost author: marcusw Get the communication with highest costs out of the given list." @@ -4315,8 +4436,8 @@ end checkParentNode; public function createCosts "author: marcusw Updates the given TaskGraphMeta-Structure with the calculated exec und communication costs." input BackendDAE.BackendDAE iDae; - input String benchFilePrefix; //The prefix of the xml or json profiling-file - input array simeqCompMapping; //Map each simEq to the scc + input String iBenchFilePrefix; //The prefix of the xml or json profiling-file + input array iSimEqCompMapping; //Map each simEq to the scc input TaskGraphMeta iTaskGraphMeta; output TaskGraphMeta oTaskGraphMeta; protected @@ -4333,20 +4454,20 @@ protected array> inComps; array commCosts; algorithm - oTaskGraphMeta := matchcontinue(iDae,benchFilePrefix,simeqCompMapping,iTaskGraphMeta) + oTaskGraphMeta := matchcontinue(iDae,iBenchFilePrefix,iSimEqCompMapping,iTaskGraphMeta) case(BackendDAE.DAE(shared=shared),_,_,TASKGRAPHMETA(inComps=inComps, commCosts=commCosts)) equation (comps,compMapping_withIdx) = getSystemComponents(iDae); compMapping = Array.map(compMapping_withIdx, Util.tuple21); ((_,reqTimeCom)) = HpcOmBenchmark.benchSystem(); - reqTimeOpLstSimCode = HpcOmBenchmark.readCalcTimesFromFile(benchFilePrefix); + reqTimeOpLstSimCode = HpcOmBenchmark.readCalcTimesFromFile(iBenchFilePrefix); //print("createCosts: read files\n"); //print("createCosts: read values: " + stringDelimitList(List.map(List.map(reqTimeOpLstSimCode, Util.tuple33), realString), ",") + "\n"); reqTimeOpSimCode = arrayCreate(listLength(reqTimeOpLstSimCode),(-1,-1.0)); reqTimeOpSimCode = List.fold(reqTimeOpLstSimCode, createCosts1, reqTimeOpSimCode); //print("createCosts: reqTimeOpSimCode created\n"); reqTimeOp = arrayCreate(listLength(comps),-1.0); - reqTimeOp = convertSimEqToSccCosts(reqTimeOpSimCode, simeqCompMapping, reqTimeOp); + reqTimeOp = convertSimEqToSccCosts(reqTimeOpSimCode, iSimEqCompMapping, reqTimeOp); //print("createCosts: scc costs converted\n"); commCosts = createCommCosts(commCosts,1,reqTimeCom); ((_,tmpTaskGraphMeta)) = Array.fold4(inComps,createCosts0,(comps,shared),compMapping, reqTimeOp, reqTimeCom, (1,iTaskGraphMeta)); @@ -4354,7 +4475,7 @@ algorithm else equation tmpTaskGraphMeta = estimateCosts(iDae,iTaskGraphMeta); - print("Warning: The costs have been estimated. Maybe " + benchFilePrefix + "-file is missing.\n"); + print("Warning: The costs have been estimated. Maybe " + iBenchFilePrefix + "-file is missing.\n"); then tmpTaskGraphMeta; end matchcontinue; end createCosts; @@ -4468,6 +4589,32 @@ algorithm end matchcontinue; end calculateCosts; +public function copyCosts "author: marcusw + Copy the execution costs from the source to the target task graph data. The communcation costs are recalculated." + input TaskGraphMeta iSourceTaskGraphData; + input TaskGraphMeta iTargetTaskGraphData; + output TaskGraphMeta oTaskGraphData; +protected + array> inCompsSource, inCompsTarget; + array> exeCostsSource, exeCostsTarget; + Integer compIdx, childIdx; + array commCostsTarget; + tuple reqTimeCom; +algorithm + TASKGRAPHMETA(inComps=inCompsSource, exeCosts=exeCostsSource) := iSourceTaskGraphData; + TASKGRAPHMETA(inComps=inCompsTarget, exeCosts=exeCostsTarget, commCosts=commCostsTarget) := iTargetTaskGraphData; + + compIdx := intMin(arrayLength(exeCostsSource), arrayLength(exeCostsTarget)); + while(intGt(compIdx, 0)) loop + exeCostsTarget := arrayUpdate(exeCostsTarget, compIdx, arrayGet(exeCostsSource, compIdx)); + compIdx := compIdx - 1; + end while; + + ((_,reqTimeCom)) := HpcOmBenchmark.benchSystem(); + commCostsTarget := createCommCosts(commCostsTarget,1,reqTimeCom); + oTaskGraphData := iTargetTaskGraphData; +end copyCosts; + protected function getCommCostsOnly "function to compute the communicationCosts author: Waurich TUD 2013-09" input array commCostsIn; diff --git a/Compiler/BackEnd/IndexReduction.mo b/Compiler/BackEnd/IndexReduction.mo index 4d1595370bd..4bba3b7d844 100644 --- a/Compiler/BackEnd/IndexReduction.mo +++ b/Compiler/BackEnd/IndexReduction.mo @@ -55,7 +55,6 @@ protected import BackendVarTransform; protected import BaseHashTable; protected import ComponentReference; protected import DAEUtil; -protected import Debug; protected import Differentiate; protected import FCore; protected import Error; @@ -64,7 +63,6 @@ protected import Expression; protected import ExpressionDump; protected import ExpressionSimplify; protected import Flags; -protected import GraphML; protected import HashTable2; protected import HashTable3; protected import HashTableCG; diff --git a/Compiler/BackEnd/Initialization.mo b/Compiler/BackEnd/Initialization.mo index 0336da3f589..91c3c00b69d 100644 --- a/Compiler/BackEnd/Initialization.mo +++ b/Compiler/BackEnd/Initialization.mo @@ -48,17 +48,15 @@ public import Util; protected import Array; protected import BackendDAEEXT; protected import BackendDAEOptimize; -protected import BackendDAETransform; protected import BackendDAEUtil; protected import BackendDump; protected import BackendEquation; -protected import BackendVariable; protected import BackendVarTransform; +protected import BackendVariable; protected import BaseHashSet; protected import CheckModel; protected import ComponentReference; protected import DAEUtil; -protected import Debug; protected import Error; protected import Expression; protected import ExpressionDump; @@ -67,7 +65,7 @@ protected import Flags; protected import List; protected import Matching; protected import Sorting; -protected import SimCodeUtil; +protected import SimCodeFunctionUtil; // ============================================================================= // section for all public functions @@ -85,28 +83,28 @@ public function solveInitialSystem "author: lochel output list outAllPrimaryParameters "already sorted"; protected BackendDAE.BackendDAE dae; - BackendDAE.Variables initVars; + BackendDAE.BackendDAE initdae; + BackendDAE.EqSystem initsyst; BackendDAE.EqSystems systs; + BackendDAE.EquationArray inieqns, eqns, emptyeqns, reeqns; + BackendDAE.ExtraInfo ei; BackendDAE.Shared shared; + BackendDAE.Variables initVars; BackendDAE.Variables knvars, vars, fixvars, evars, eavars, avars; - BackendDAE.EquationArray inieqns, eqns, emptyeqns, reeqns; - BackendDAE.EqSystem initsyst; - BackendDAE.BackendDAE initdae; + Boolean b, b1, b2; + Boolean useHomotopy; + DAE.FunctionTree functionTree; FCore.Cache cache; FCore.Graph graph; - DAE.FunctionTree functionTree; - list constraints; - list classAttrs; - list tempVar; - Boolean b, b1, b2; HashSet.HashSet hs "contains all pre variables"; + list removedEqns; + list dumpVars, dumpVars2; + list tempVar; + list classAttrs; + list constraints; list> pastOptModules; tuple daeHandler; tuple matchingAlgorithm; - Boolean useHomotopy; - list dumpVars, dumpVars2; - BackendDAE.ExtraInfo ei; - list removedEqns; algorithm try // TODO: remove this once the initialization is moved before post-optimization @@ -172,7 +170,7 @@ algorithm // generate initial system and pre-balance it initsyst := BackendDAEUtil.createEqSystem(vars, eqns); (initsyst, dumpVars) := preBalanceInitialSystem(initsyst); - SimCodeUtil.execStat("created initial system"); + SimCodeFunctionUtil.execStat("created initial system"); // split the initial system into independend subsystems initdae := BackendDAE.DAE({initsyst}, shared); @@ -183,7 +181,7 @@ algorithm (systs, shared) := BackendDAEOptimize.partitionIndependentBlocksHelper(initsyst, shared, Error.getNumErrorMessages(), true); initdae := BackendDAE.DAE(systs, shared); - SimCodeUtil.execStat("partitioned initial system"); + SimCodeFunctionUtil.execStat("partitioned initial system"); if Flags.isSet(Flags.OPT_DAE_DUMP) then print(stringAppendList({"\npartitioned initial system:\n\n"})); @@ -327,22 +325,16 @@ protected function inlineWhenForInitializationSystem "author: lochel" input BackendDAE.EqSystem inEqSystem; output BackendDAE.EqSystem outEqSystem; protected - BackendDAE.Variables orderedVars; - BackendDAE.EquationArray orderedEqs; BackendDAE.EquationArray eqns; - BackendDAE.StateSets stateSets; - BackendDAE.BaseClockPartitionKind partitionKind; list eqnlst; algorithm - BackendDAE.EQSYSTEM(orderedVars=orderedVars, orderedEqs=orderedEqs, stateSets=stateSets, partitionKind=partitionKind) := inEqSystem; - - eqnlst := BackendEquation.traverseEquationArray(orderedEqs, inlineWhenForInitializationEquation, {}); + BackendDAE.EQSYSTEM(orderedEqs=eqns) := inEqSystem; + eqnlst := BackendEquation.traverseEquationArray(eqns, inlineWhenForInitializationEquation, {}); //print("Before: " + intString(listLength(eqnlst)) + "\n"); eqnlst := List.uniqueOnTrue(eqnlst, BackendEquation.equationEqual) "hack for #3209"; //print("After: " + intString(listLength(eqnlst)) + "\n"); - eqns := BackendEquation.listEquation(eqnlst); - - outEqSystem := BackendDAEUtil.createEqSystem(orderedVars, eqns, stateSets, partitionKind); + outEqSystem := BackendDAEUtil.setEqSystEqs(inEqSystem, BackendEquation.listEquation(eqnlst)); + outEqSystem := BackendDAEUtil.clearEqSyst(outEqSystem); end inlineWhenForInitializationSystem; protected function inlineWhenForInitializationEquation "author: lochel" @@ -397,8 +389,6 @@ algorithm DAE.Exp condition, right, crexp; BackendDAE.Equation eqn; list eqns; - BackendDAE.WhenEquation weqn; - BackendDAE.Variables vars; // active when equation during initialization case BackendDAE.WHEN_EQ(condition=condition, left=left, right=right) equation @@ -425,12 +415,9 @@ protected function inlineWhenForInitializationWhenAlgorithm "author: lochel algorithm (outStmts, outLeftCrs) := matchcontinue(inStmts) local - DAE.Exp condition; - list< DAE.ComponentRef> crefLst; DAE.Statement stmt; - list< DAE.Statement> stmts, rest; + list stmts, rest; HashSet.HashSet leftCrs; - list> crintLst; case {} then (listReverse(inAcc), inLeftCrs); @@ -441,7 +428,7 @@ algorithm // -> take care that for each left hand side an assigment is generated (stmts, leftCrs) = inlineWhenForInitializationWhenStmt(stmt, inLeftCrs, inAcc); (stmts, leftCrs) = inlineWhenForInitializationWhenAlgorithm(rest, stmts, leftCrs); - then (stmts, leftCrs); + then (stmts, leftCrs); // no when statement case stmt::rest equation @@ -461,11 +448,10 @@ algorithm (outStmts, outLeftCrs) := matchcontinue(inWhenStatement) local DAE.Exp condition; - list< DAE.ComponentRef> crefLst; + list crefLst; DAE.Statement stmt; - list< DAE.Statement> stmts; + list stmts; HashSet.HashSet leftCrs; - list> crintLst; // active when equation during initialization case DAE.STMT_WHEN(exp=condition, statementLst=stmts) equation @@ -491,7 +477,6 @@ algorithm else equation Error.addInternalError("function inlineWhenForInitializationWhenStmt failed", sourceInfo()); then fail(); - end matchcontinue; end inlineWhenForInitializationWhenStmt; @@ -547,58 +532,51 @@ public function collectPreVariablesEqSystem output HashSet.HashSet outHS; protected BackendDAE.EquationArray orderedEqs; - BackendDAE.EquationArray eqns; algorithm BackendDAE.EQSYSTEM(orderedEqs=orderedEqs) := inEqSystem; - ((_,outHS)) := BackendDAEUtil.traverseBackendDAEExpsEqns(orderedEqs, Expression.traverseSubexpressionsHelper, (collectPreVariablesTraverseExp, inHS)); + ((_, outHS)) := BackendDAEUtil.traverseBackendDAEExpsEqns(orderedEqs, Expression.traverseSubexpressionsHelper, (collectPreVariablesTraverseExp, inHS)); end collectPreVariablesEqSystem; public function collectPreVariablesTraverseExp - input DAE.Exp e; - input HashSet.HashSet hs; - output DAE.Exp outExp; - output HashSet.HashSet ohs; + input DAE.Exp inExp; + input HashSet.HashSet inHS; + output DAE.Exp outExp = inExp; + output HashSet.HashSet outHS; algorithm - (outExp,ohs) := match (e,hs) - local - list explst; - case (DAE.CALL(path=Absyn.IDENT(name="pre")), _) - equation - (_, ohs) = Expression.traverseExpBottomUp(e, collectPreVariablesTraverseExp2, hs); - then (e, ohs); - - case (DAE.CALL(path=Absyn.IDENT(name="change")), _) - equation - (_, ohs) = Expression.traverseExpBottomUp(e, collectPreVariablesTraverseExp2, hs); - then (e, ohs); - - case (DAE.CALL(path=Absyn.IDENT(name="edge")), _) - equation - (_, ohs) = Expression.traverseExpBottomUp(e, collectPreVariablesTraverseExp2, hs); - then (e, ohs); - - else (e,hs); + outHS := match (inExp) + case DAE.CALL(path=Absyn.IDENT(name="pre")) equation + (_, outHS) = Expression.traverseExpBottomUp(inExp, collectPreVariablesTraverseExp2, inHS); + then outHS; + + case DAE.CALL(path=Absyn.IDENT(name="change")) equation + (_, outHS) = Expression.traverseExpBottomUp(inExp, collectPreVariablesTraverseExp2, inHS); + then outHS; + + case DAE.CALL(path=Absyn.IDENT(name="edge")) equation + (_, outHS) = Expression.traverseExpBottomUp(inExp, collectPreVariablesTraverseExp2, inHS); + then outHS; + + else inHS; end match; end collectPreVariablesTraverseExp; protected function collectPreVariablesTraverseExp2 "author: lochel" - input DAE.Exp e; - input HashSet.HashSet hs; - output DAE.Exp outExp; - output HashSet.HashSet ohs; + input DAE.Exp inExp; + input HashSet.HashSet inHS; + output DAE.Exp outExp = inExp; + output HashSet.HashSet outHS; algorithm - (outExp,ohs) := match (e,hs) + outHS := match inExp local list crefs; DAE.ComponentRef cr; - case (DAE.CREF(componentRef=cr), _) - equation - crefs = ComponentReference.expandCref(cr, true); - ohs = List.fold(crefs, BaseHashSet.add, hs); - then (e, ohs); + case DAE.CREF(componentRef=cr) equation + crefs = ComponentReference.expandCref(cr, true); + outHS = List.fold(crefs, BaseHashSet.add, inHS); + then outHS; - else (e,hs); + else inHS; end match; end collectPreVariablesTraverseExp2; @@ -1041,19 +1019,25 @@ protected function preBalanceInitialSystem "author: lochel" input BackendDAE.EqSystem inSystem; output BackendDAE.EqSystem outSystem; output list outDumpVars; -protected - BackendDAE.Variables orderedVars; - BackendDAE.EquationArray orderedEqs; - BackendDAE.Matching matching; - BackendDAE.StateSets stateSets; - BackendDAE.BaseClockPartitionKind partitionKind; - Boolean b; - BackendDAE.IncidenceMatrix mt; algorithm - (_, mt) := BackendDAEUtil.incidenceMatrix(inSystem, BackendDAE.NORMAL(), NONE()); - BackendDAE.EQSYSTEM(orderedVars=orderedVars, orderedEqs=orderedEqs, stateSets=stateSets, partitionKind=partitionKind) := inSystem; - (orderedVars, orderedEqs, b, outDumpVars) := preBalanceInitialSystem1(arrayLength(mt), mt, orderedVars, orderedEqs, false, {}); - outSystem := if b then BackendDAEUtil.createEqSystem(orderedVars, orderedEqs, stateSets, partitionKind) else inSystem; + outSystem := match inSystem + local + BackendDAE.EqSystem syst; + BackendDAE.Variables orderedVars; + BackendDAE.EquationArray orderedEqs; + Boolean b; + BackendDAE.IncidenceMatrix mt; + case syst as BackendDAE.EQSYSTEM(orderedVars=orderedVars, orderedEqs=orderedEqs) + algorithm + (_, mt) := BackendDAEUtil.incidenceMatrix(syst, BackendDAE.NORMAL(), NONE()); + (orderedVars, orderedEqs, b, outDumpVars) := + preBalanceInitialSystem1(arrayLength(mt), mt, orderedVars, orderedEqs, false, {}); + if b then + syst.orderedEqs := orderedEqs; syst.orderedVars := orderedVars; + syst := BackendDAEUtil.clearEqSyst(syst); + end if; + then syst; + end match; end preBalanceInitialSystem; protected function preBalanceInitialSystem1 "author: lochel" @@ -1204,7 +1188,7 @@ protected function analyzeInitialSystem2 "author: lochel" output BackendDAE.Shared outShared = inShared; output tuple, list> outTpl; algorithm - (osyst, outTpl) := matchcontinue(isyst, inTpl) + (osyst, outTpl) := matchcontinue (isyst, inTpl) local BackendDAE.BackendDAE inDAE; BackendDAE.EqSystem system, sys; @@ -1233,7 +1217,7 @@ algorithm // add dummy var + dummy eqn dumpVars = listAppend(dumpVars, dumpVars2); removedEqns = listAppend(removedEqns, removedEqns2); - system = BackendDAEUtil.createEqSystem(vars, eqns2); + system = BackendDAEUtil.setEqSystEqs(isyst, eqns2); then (system, (inDAE, initVars, dumpVars, removedEqns)); // (index-1) mixed-determined system @@ -1245,7 +1229,7 @@ algorithm // add dummy var + dummy eqn dumpVars = listAppend(dumpVars, dumpVars2); removedEqns = listAppend(removedEqns, removedEqns2); - system = BackendDAEUtil.createEqSystem(vars, eqns2); + system = BackendDAEUtil.setEqSystEqs(isyst, eqns2); then (system, (inDAE, initVars, dumpVars, removedEqns)); // (index-2) mixed-determined system @@ -1257,7 +1241,7 @@ algorithm // add dummy var + dummy eqn dumpVars = listAppend(dumpVars, dumpVars2); removedEqns = listAppend(removedEqns, removedEqns2); - system = BackendDAEUtil.createEqSystem(vars, eqns2); + system = BackendDAEUtil.setEqSystEqs(isyst, eqns2); then (system, (inDAE, initVars, dumpVars, removedEqns)); // (index-3) mixed-determined system @@ -1269,7 +1253,7 @@ algorithm // add dummy var + dummy eqn dumpVars = listAppend(dumpVars, dumpVars2); removedEqns = listAppend(removedEqns, removedEqns2); - system = BackendDAEUtil.createEqSystem(vars, eqns2); + system = BackendDAEUtil.setEqSystEqs(isyst, eqns2); then (system, (inDAE, initVars, dumpVars, removedEqns)); else fail(); @@ -1850,19 +1834,11 @@ protected function getConsistentEquation "author: mwenzler" algorithm (outUnassignedEqns, outConsistent, outRemovedEqns) := matchcontinue(inUnassignedEqn) local - Integer currEqID, currVarID, currID, nVars, nEqns; - list unassignedEqns, unassignedEqns2, listVar, removedEqns; - list eqns_list; - list eqns_list_new; - list eqns_list2; + Integer nVars, nEqns; + list listVar; BackendDAE.EquationArray eqns; BackendDAE.Equation eqn, eqn2; - DAE.Exp lhs, rhs, exp, x; - String eqStr; - BackendDAE.Var var; - DAE.ComponentRef cref; - BackendDAE.Type type_; - Boolean consistent; + DAE.Exp lhs, rhs, exp; list listParameter; BackendDAE.IncidenceMatrix m; BackendDAE.EqSystem system; @@ -1903,7 +1879,7 @@ algorithm (exp, _) = ExpressionSimplify.simplify(exp); false = Expression.isZero(exp); - ((_, listParameter))=parameterCheck((exp, {})); + ((_, listParameter)) = parameterCheck((exp, {})); true = listEmpty(listParameter); eqn2 = BackendEquation.equationNth1(inEqnsOrig, inUnassignedEqn); @@ -1923,13 +1899,13 @@ algorithm ((_, listParameter))=parameterCheck((exp, {})); false = listEmpty(listParameter); - list_inEqns=BackendEquation.equationList(inEqns); + list_inEqns = BackendEquation.equationList(inEqns); list_inEqns = List.set(list_inEqns, inUnassignedEqn, eqn); eqns = BackendEquation.listEquation(list_inEqns); funcs = BackendDAEUtil.getFunctions(shared); system = BackendDAEUtil.createEqSystem(vars, eqns); (m, _) = BackendDAEUtil.incidenceMatrix(system, BackendDAE.NORMAL(), SOME(funcs)); - listVar=m[inUnassignedEqn]; + listVar = m[inUnassignedEqn]; false = listEmpty(listVar); _ = BackendEquation.equationNth1(inEqnsOrig, inUnassignedEqn); @@ -1947,7 +1923,7 @@ algorithm (exp, _) = ExpressionSimplify.simplify(exp); false = Expression.isZero(exp); - ((_, listParameter))=parameterCheck((exp, {})); + ((_, listParameter)) = parameterCheck((exp, {})); false = listEmpty(listParameter); eqn2 = BackendEquation.equationNth1(inEqnsOrig, inUnassignedEqn); @@ -1974,25 +1950,21 @@ protected function parameterCheck2 output DAE.Exp outExp; output list listParameter; algorithm - (outExp,listParameter) := match (exp,inParams) + (outExp, listParameter) := match (exp, inParams) local - DAE.Type ty; String Para; - case (DAE.CREF(componentRef=DAE.CREF_QUAL(ident=Para)), listParameter) - equation - listParameter=listAppend({Para}, listParameter); - then (exp, listParameter); + case (DAE.CREF(componentRef=DAE.CREF_QUAL(ident=Para)), listParameter) equation + listParameter=listAppend({Para}, listParameter); + then (exp, listParameter); - case (DAE.CREF(componentRef=DAE.CREF_IDENT(ident=Para)), listParameter) - equation - listParameter=listAppend({Para}, listParameter); - then (exp, listParameter); + case (DAE.CREF(componentRef=DAE.CREF_IDENT(ident=Para)), listParameter) equation + listParameter=listAppend({Para}, listParameter); + then (exp, listParameter); - case (DAE.CREF(componentRef=DAE.CREF_ITER(ident=Para)), listParameter) - equation - listParameter=listAppend({Para}, listParameter); - then (exp, listParameter); + case (DAE.CREF(componentRef=DAE.CREF_ITER(ident=Para)), listParameter) equation + listParameter=listAppend({Para}, listParameter); + then (exp, listParameter); else (exp, inParams); end match; @@ -2100,7 +2072,7 @@ protected function collectInitialVars "author: lochel output BackendDAE.Var outVar; output tuple outTpl; algorithm - (outVar,outTpl) := matchcontinue (inVar,inTpl) + (outVar, outTpl) := matchcontinue (inVar, inTpl) local BackendDAE.Var var, preVar, derVar; BackendDAE.Variables vars, fixvars; @@ -2356,7 +2328,7 @@ end collectInitialVars; protected function collectInitialEqns "author: lochel" input BackendDAE.Equation inEq; input tuple inTpl; - output BackendDAE.Equation eqn; + output BackendDAE.Equation outEq = inEq; output tuple outTpl; protected BackendDAE.Equation eqn1; @@ -2364,11 +2336,10 @@ protected Integer size; Boolean b; algorithm - eqn := inEq; (eqns, reeqns) := inTpl; // replace der(x) with $DER.x and replace pre(x) with $PRE.x - (eqn1, _) := BackendEquation.traverseExpsOfEquation(eqn, Expression.traverseSubexpressionsDummyHelper, replaceDerPreCref); + (eqn1, _) := BackendEquation.traverseExpsOfEquation(inEq, Expression.traverseSubexpressionsDummyHelper, replaceDerPreCref); // add it, if size is zero (terminate, assert, noretcall) move to removed equations size := BackendEquation.equationSize(eqn1); @@ -2387,17 +2358,14 @@ algorithm local DAE.ComponentRef dummyder, cr; DAE.Type ty; - Integer i; - case DAE.CALL(path = Absyn.IDENT(name = "der"), expLst = {DAE.CREF(componentRef = cr)}, attr=DAE.CALL_ATTR(ty=ty)) - equation - dummyder = ComponentReference.crefPrefixDer(cr); - then DAE.CREF(dummyder, ty); + case DAE.CALL(path = Absyn.IDENT(name="der"), expLst = {DAE.CREF(componentRef=cr)}, attr=DAE.CALL_ATTR(ty=ty)) equation + dummyder = ComponentReference.crefPrefixDer(cr); + then DAE.CREF(dummyder, ty); - case DAE.CALL(path = Absyn.IDENT(name = "pre"), expLst = {DAE.CREF(componentRef = cr)}, attr=DAE.CALL_ATTR(ty=ty)) - equation - dummyder = ComponentReference.crefPrefixPre(cr); - then DAE.CREF(dummyder, ty); + case DAE.CALL(path = Absyn.IDENT(name="pre"), expLst = {DAE.CREF(componentRef=cr)}, attr=DAE.CALL_ATTR(ty=ty)) equation + dummyder = ComponentReference.crefPrefixPre(cr); + then DAE.CREF(dummyder, ty); else inExp; end match; @@ -2415,7 +2383,7 @@ protected function collectInitialBindings "author: lochel output BackendDAE.Var outVar; output tuple outTpl; algorithm - (outVar,outTpl) := match (inVar,inTpl) + (outVar,outTpl) := match (inVar, inTpl) local BackendDAE.Var var; DAE.ComponentRef cr; @@ -2436,11 +2404,9 @@ algorithm eqns = BackendEquation.addEquation(eqn, eqns); then (var, (eqns, reeqns)); - else - equation - Error.addInternalError("function collectInitialBindings failed for: " + BackendDump.varString(inVar), sourceInfo()); - then fail(); - + else equation + Error.addInternalError("function collectInitialBindings failed for: " + BackendDump.varString(inVar), sourceInfo()); + then fail(); end match; end collectInitialBindings; diff --git a/Compiler/BackEnd/InlineArrayEquations.mo b/Compiler/BackEnd/InlineArrayEquations.mo index 529179bcac1..3dd70e89bc3 100644 --- a/Compiler/BackEnd/InlineArrayEquations.mo +++ b/Compiler/BackEnd/InlineArrayEquations.mo @@ -75,7 +75,7 @@ protected function inlineArrayEqn1 output BackendDAE.Shared outShared = inShared "unused"; output Boolean outOptimized; algorithm - (outEqSystem, outOptimized) := matchcontinue(inEqSystem) + (outEqSystem, outOptimized) := matchcontinue inEqSystem local BackendDAE.Variables orderedVars; BackendDAE.EquationArray orderedEqs; @@ -84,11 +84,11 @@ algorithm BackendDAE.StateSets stateSets; BackendDAE.BaseClockPartitionKind partitionKind; - case BackendDAE.EQSYSTEM(orderedVars=orderedVars, orderedEqs=orderedEqs, stateSets=stateSets, partitionKind=partitionKind) equation + case BackendDAE.EQSYSTEM(orderedEqs=orderedEqs) equation eqnLst = BackendEquation.equationList(orderedEqs); (eqnLst, true) = getScalarArrayEqns(eqnLst); orderedEqs = BackendEquation.listEquation(eqnLst); - then (BackendDAEUtil.createEqSystem(orderedVars, orderedEqs, stateSets, partitionKind), true); + then (BackendDAEUtil.clearEqSyst(BackendDAEUtil.setEqSystEqs(inEqSystem, orderedEqs)), true); else (inEqSystem, inOptimized); end matchcontinue; diff --git a/Compiler/BackEnd/Matching.mo b/Compiler/BackEnd/Matching.mo index 4b9695d4320..c9084b93b49 100644 --- a/Compiler/BackEnd/Matching.mo +++ b/Compiler/BackEnd/Matching.mo @@ -37,7 +37,6 @@ encapsulated package Matching RCS: $Id: Matching.mo 11428 2012-03-14 17:38:09Z Frenkel TUD $" -public import Absyn; public import BackendDAE; public import BackendDAEFunc; public import DAE; @@ -6341,19 +6340,15 @@ protected function randSortSystem input BackendDAE.Shared ishared; output BackendDAE.EqSystem osyst; algorithm - osyst := match(isyst,ishared) - local - Integer ne,nv; - array randarr,randarr1; - BackendDAE.Variables vars,vars1; - BackendDAE.EquationArray eqns,eqns1; - BackendDAE.IncidenceMatrix m; - BackendDAE.IncidenceMatrixT mT; - BackendDAE.EqSystem syst; - BackendDAE.StateSets stateSets; - BackendDAE.BaseClockPartitionKind partitionKind; - - case (BackendDAE.EQSYSTEM(orderedVars=vars, orderedEqs=eqns, stateSets=stateSets, partitionKind=partitionKind),_) + osyst := match isyst + local + Integer ne, nv; + array randarr, randarr1; + BackendDAE.Variables vars; + BackendDAE.EquationArray eqns; + BackendDAE.EqSystem syst; + + case syst as BackendDAE.EQSYSTEM(orderedVars=vars, orderedEqs=eqns) equation ne = BackendDAEUtil.systemSize(isyst); nv = BackendVariable.daenumVariables(isyst); @@ -6361,10 +6356,11 @@ algorithm setrandArray(ne, randarr); randarr1 = listArray(List.intRange(nv)); setrandArray(nv, randarr1); - eqns1 = randSortSystem1(ne, 0, randarr, eqns, BackendEquation.listEquation({}), BackendEquation.equationNth1, BackendEquation.addEquation); - vars1 = randSortSystem1(nv, 0, randarr1, vars, BackendVariable.emptyVars(), BackendVariable.getVarAt, BackendVariable.addVar); - (syst, _, _) = BackendDAEUtil.getIncidenceMatrix( BackendDAEUtil.createEqSystem(vars1, eqns1, stateSets, partitionKind), - BackendDAE.NORMAL(), NONE() ); + syst.orderedEqs = randSortSystem1( ne, 0, randarr, eqns, BackendEquation.listEquation({}), + BackendEquation.equationNth1, BackendEquation.addEquation ); + syst.orderedVars = randSortSystem1( nv, 0, randarr1, vars, BackendVariable.emptyVars(), + BackendVariable.getVarAt, BackendVariable.addVar ); + (syst, _, _) = BackendDAEUtil.getIncidenceMatrix( BackendDAEUtil.clearEqSyst(syst), BackendDAE.NORMAL(), NONE() ); then syst; end match; diff --git a/Compiler/BackEnd/MathematicaDump.mo b/Compiler/BackEnd/MathematicaDump.mo index 61c7cbd4b6c..9ad7e46cce4 100644 --- a/Compiler/BackEnd/MathematicaDump.mo +++ b/Compiler/BackEnd/MathematicaDump.mo @@ -38,7 +38,6 @@ encapsulated package MathematicaDump import Util; import List; import Absyn; - import Expression; import System; import ExpressionDump; import IOStream; diff --git a/Compiler/BackEnd/OnRelaxation.mo b/Compiler/BackEnd/OnRelaxation.mo index 613b9850602..b601feb5de4 100644 --- a/Compiler/BackEnd/OnRelaxation.mo +++ b/Compiler/BackEnd/OnRelaxation.mo @@ -48,7 +48,6 @@ protected import BackendVariable; protected import BackendDAETransform; protected import BaseHashSet; protected import ComponentReference; -protected import Debug; protected import Differentiate; protected import DumpGraphML; protected import Expression; diff --git a/Compiler/BackEnd/OpenTURNS.mo b/Compiler/BackEnd/OpenTURNS.mo index 52efaf198f2..cf7bf6fc43d 100644 --- a/Compiler/BackEnd/OpenTURNS.mo +++ b/Compiler/BackEnd/OpenTURNS.mo @@ -54,6 +54,7 @@ import BackendEquation; import BackendVariable; import ClockIndexes; import CevalScript; +import CevalScriptBackend; import ComponentReference; import DAEUtil; import Expression; @@ -96,8 +97,8 @@ algorithm cname_last_str := Absyn.pathLastIdent(inPath); fileNamePrefix := cname_str; - simSettings := CevalScript.convertSimulationOptionsToSimCode( - CevalScript.buildSimulationOptionsFromModelExperimentAnnotation( + simSettings := CevalScriptBackend.convertSimulationOptionsToSimCode( + CevalScriptBackend.buildSimulationOptionsFromModelExperimentAnnotation( GlobalScriptUtil.setSymbolTableAST(GlobalScript.emptySymboltable,inProgram),inPath,fileNamePrefix,NONE()) ); // correlation matrix form (vector of records) currently not supported by OpenModelica backend, remove it . @@ -517,13 +518,12 @@ protected function stripCorrelationVarsAndEqns " help function " protected BackendDAE.Variables vars; BackendDAE.EquationArray eqns; - BackendDAE.StateSets stateSets; - BackendDAE.BaseClockPartitionKind partitionKind; algorithm - BackendDAE.EQSYSTEM(orderedVars=vars, orderedEqs = eqns, stateSets = stateSets, partitionKind=partitionKind) := eqsys; + BackendDAE.EQSYSTEM(orderedVars=vars, orderedEqs = eqns) := eqsys; vars := stripCorrelationVars(vars); eqns := stripCorrelationEqns(eqns); - outEqsys := BackendDAEUtil.createEqSystem(vars, eqns, stateSets, partitionKind); + outEqsys := BackendDAEUtil.setEqSystVars(BackendDAEUtil.setEqSystEqs(eqsys, eqns), vars); + outEqsys := BackendDAEUtil.clearEqSyst(outEqsys); end stripCorrelationVarsAndEqns; protected function stripCorrelationEqns "help function " diff --git a/Compiler/BackEnd/RemoveSimpleEquations.mo b/Compiler/BackEnd/RemoveSimpleEquations.mo index 17b51089752..86a22664895 100644 --- a/Compiler/BackEnd/RemoveSimpleEquations.mo +++ b/Compiler/BackEnd/RemoveSimpleEquations.mo @@ -57,7 +57,6 @@ protected import BackendDump; protected import BackendEquation; protected import BackendVariable; protected import BackendVarTransform; -protected import BackendDAETransform; protected import BaseHashSet; protected import BaseHashTable; protected import Ceval; @@ -79,15 +78,9 @@ protected import Types; protected import Util; protected import HashTableCrToCrEqLst; protected import HashTableCrToExp; -protected import HashTableExpToExp; protected import HashTableExpToIndex; -protected import Array; -protected import HpcOmEqSystems; -protected import HpcOmTaskGraph; -protected import ResolveLoops; -protected import Differentiate; protected type EquationSourceAndAttributes = tuple "eqnAttributes(source,EquationAttributes)"; @@ -361,22 +354,23 @@ protected list simpleeqnslst; BackendDAE.Variables vars; BackendDAE.EquationArray eqns; - BackendDAE.StateSets stateSets; array> mT; Boolean foundSimple, globalFindSimple, b; Integer traversals; - BackendDAE.BaseClockPartitionKind partitionKind; algorithm try - BackendDAE.EQSYSTEM(orderedVars=vars, orderedEqs=eqns, stateSets=stateSets, partitionKind=partitionKind) := outSystem; + BackendDAE.EQSYSTEM(orderedVars=vars, orderedEqs=eqns) := outSystem; ((repl, globalFindSimple, unReplaceable, traversals)) := inTpl; // transform to list, this is later not neccesary because the acausal system should save the equations as list eqnslst := BackendEquation.equationList(eqns); mT := arrayCreate(BackendVariable.varsSize(vars), {}); // check equations - ((_, _, eqnslst, simpleeqnslst, _, _, foundSimple)) := List.fold(eqnslst, simpleEquationsFinder, (vars, inShared, {}, {}, 1, mT, false)); - ((_, vars, outShared, repl, unReplaceable, _, eqnslst, b)) := causalFinder(foundSimple, simpleeqnslst, eqnslst, 1, traversals, vars, inShared, repl, unReplaceable, mT, {}, globalFindSimple); - outSystem := updateSystem(b, eqnslst, vars, stateSets, partitionKind, repl, outSystem); + ((_, _, eqnslst, simpleeqnslst, _, _, foundSimple)) := List.fold( eqnslst, simpleEquationsFinder, + (vars, inShared, {}, {}, 1, mT, false) ); + ((_, vars, outShared, repl, unReplaceable, _, eqnslst, b)) := + causalFinder( foundSimple, simpleeqnslst, eqnslst, 1, traversals, vars, inShared, + repl, unReplaceable, mT, {}, globalFindSimple ); + outSystem := updateSystem(b, eqnslst, vars, repl, outSystem); outTpl := ((repl, b, unReplaceable, traversals)); else //Error.addCompilerWarning("The module removeSimpleEquations failed for a subsystem. The relevant subsystem get skipped and the transformation is proceeded."); @@ -505,10 +499,8 @@ protected array> mT; list eqnslst; BackendDAE.EqSystem syst; - BackendDAE.StateSets stateSets; - BackendDAE.BaseClockPartitionKind partitionKind; algorithm - BackendDAE.EQSYSTEM(orderedVars=vars, orderedEqs=eqns, stateSets=stateSets, partitionKind=partitionKind) := isyst; + BackendDAE.EQSYSTEM(orderedVars=vars, orderedEqs=eqns) := isyst; ((repl, unReplaceable, b1)) := inTpl; // transform to list, this is later not neccesary because the acausal system should save the equations as list @@ -517,7 +509,7 @@ algorithm // check equations ((vars, outShared, repl, unReplaceable, _, eqnslst, b)) := allCausalFinder(eqnslst, (vars, inShared, repl, unReplaceable, mT, {}, false)); - osyst := updateSystem(b, eqnslst, vars, stateSets, partitionKind, repl, isyst); + osyst := updateSystem(b, eqnslst, vars, repl, isyst); outTpl := ((repl, unReplaceable, b or b1)); end allAcausal1; @@ -574,17 +566,15 @@ protected array> mT; list eqnslst; BackendDAE.EqSystem syst; - BackendDAE.StateSets stateSets; - BackendDAE.BaseClockPartitionKind partitionKind; algorithm - BackendDAE.EQSYSTEM(orderedVars=vars, orderedEqs=eqns, matching=BackendDAE.MATCHING(comps=comps), stateSets=stateSets, partitionKind=partitionKind) := isyst; + BackendDAE.EQSYSTEM(orderedVars=vars, orderedEqs=eqns, matching=BackendDAE.MATCHING(comps=comps)) := isyst; ((repl, unReplaceable, b1)) := inTpl; mT := arrayCreate(BackendVariable.varsSize(vars), {}); // check equations ((vars, outShared, repl, unReplaceable, _, eqnslst, b)) := traverseComponents(comps, eqns, allCausalFinder, (vars, inShared, repl, unReplaceable, mT, {}, false)); - osyst := updateSystem(b, eqnslst, vars, stateSets, partitionKind, repl, isyst); + osyst := updateSystem(b, eqnslst, vars, repl, isyst); outTpl := ((repl, unReplaceable, b or b1)); end causal1; @@ -3475,28 +3465,27 @@ protected function updateSystem "author: Frenkel TUD 2012-12 input Boolean foundSimple; input list iEqnslst; input BackendDAE.Variables iVars; - input BackendDAE.StateSets stateSets; - input BackendDAE.BaseClockPartitionKind inPartitionKind; input BackendVarTransform.VariableReplacements repl; input BackendDAE.EqSystem isyst; output BackendDAE.EqSystem osyst; algorithm osyst:= - match (foundSimple, iEqnslst, iVars, stateSets, inPartitionKind, repl, isyst) + match (foundSimple, isyst) local BackendDAE.Variables vars; BackendDAE.EquationArray eqns; - case (false, _, _, _, _, _, _) then isyst; - case (true, _, _, _, _, _, _) + BackendDAE.EqSystem syst; + case (false, _) then isyst; + case (true, syst as BackendDAE.EQSYSTEM()) equation // remove empty entries from vars and update stateorder - vars = BackendVariable.emptyVars(); - ((vars, _)) = BackendVariable.traverseBackendDAEVars(iVars, updateVar, (vars, repl)); + ((vars, _)) = BackendVariable.traverseBackendDAEVars(iVars, updateVar, (BackendVariable.emptyVars(), repl)); // replace unoptimized equations with optimized eqns = BackendEquation.listEquation(listReverse(iEqnslst)); + syst.orderedEqs = eqns; syst.orderedVars = vars; then - BackendDAEUtil.createEqSystem(vars, eqns, stateSets, inPartitionKind); + BackendDAEUtil.clearEqSyst(syst); end match; end updateSystem; @@ -3714,17 +3703,19 @@ algorithm Boolean b, b1; BackendDAE.EqSystem syst; BackendDAE.StateSets stateSets; - BackendDAE.BaseClockPartitionKind partitionKind; Option statesetrepl1; case ({}, _, _, _, _) then inSysts1; - case ((syst as BackendDAE.EQSYSTEM(orderedVars=v, orderedEqs=eqns, stateSets=stateSets, partitionKind=partitionKind))::rest, _, _, _, _) - equation - ((_, eqnslst, b)) = BackendEquation.traverseEquationArray(eqns, replaceEquationTraverser, (repl, {}, false)); - eqnslst = if b then listReverse(eqnslst) else eqnslst; - eqns = if b then BackendEquation.listEquation(eqnslst) else eqns; - (stateSets, b1, statesetrepl1) = removeAliasVarsStateSets(stateSets, statesetrepl, v, aliasVars, {}, false); - syst = if b or b1 then BackendDAEUtil.createEqSystem(v, eqns, stateSets, partitionKind) else syst; + case ((syst as BackendDAE.EQSYSTEM(orderedVars=v, orderedEqs=eqns, stateSets=stateSets))::rest, _, _, _, _) + algorithm + ((_, eqnslst, b)) := BackendEquation.traverseEquationArray(eqns, replaceEquationTraverser, (repl, {}, false)); + (stateSets, b1, statesetrepl1) := removeAliasVarsStateSets(stateSets, statesetrepl, v, aliasVars, {}, false); + if b or b1 then + eqns := BackendEquation.listEquation(listReverse(eqnslst)); + syst.stateSets := stateSets; + syst.orderedEqs := eqns; + syst := BackendDAEUtil.clearEqSyst(syst); + end if; then removeSimpleEquationsShared1(rest, syst::inSysts1, repl, statesetrepl1, aliasVars); end match; @@ -4358,7 +4349,9 @@ algorithm Integer countAliasEquations, countSimpleEquations, size; Boolean b; - + BackendDAE.EqSystem syst; + BackendDAE.Shared shared; + BackendDAE.EventInfo eventInfo; BackendDAE.Variables knvars, exobj, knvars1; BackendDAE.Variables aliasVars; BackendDAE.EquationArray remeqns, inieqns, remeqns1; @@ -4370,22 +4363,16 @@ algorithm BackendDAE.ExternalObjectClasses eoc; BackendDAE.SymbolicJacobians symjacs; list whenClauseLst, whenClauseLst1; - list zeroCrossingLst, relationsLst, sampleLst; - Integer numMathFunctions; - BackendDAE.BackendDAEType btp; BackendDAE.EqSystems systs, systs1; list eqnslst; list varlst; Boolean b1; - list timeEvents; - BackendDAE.ExtraInfo ei; - array clocks; BackendVarTransform.VariableReplacements repl; - case (BackendDAE.EQSYSTEM(orderedVars, orderedEqs, _, _, _, stateSets,partitionKind), - BackendDAE.SHARED( knvars, exobj, aliasVars, inieqns, remeqns, constraintsLst, clsAttrsLst, cache, graph, funcTree, - BackendDAE.EVENT_INFO(timeEvents, whenClauseLst, zeroCrossingLst, sampleLst, relationsLst, numMathFunctions, clocks), - eoc, btp, symjacs, ei )) equation + case ( syst as BackendDAE.EQSYSTEM(orderedVars=orderedVars, orderedEqs=orderedEqs), + shared as BackendDAE.SHARED( knownVars=knvars, aliasVars=aliasVars, initialEqs=inieqns, removedEqs=remeqns, + eventInfo=eventInfo as BackendDAE.EVENT_INFO(whenClauseLst=whenClauseLst )) ) + equation // sizes of Hash tables are system dependent!!!! size = BackendVariable.varsSize(orderedVars); @@ -4466,12 +4453,18 @@ algorithm end if; //SimCodeUtil.execStat("FINDSIMPLE6: "); - outSystem = BackendDAE.EQSYSTEM(orderedVars, orderedEqs, NONE(), NONE(), BackendDAE.NO_MATCHING(), stateSets, partitionKind); - outShared = BackendDAE.SHARED( knvars, exobj, aliasVars, inieqns, remeqns, constraintsLst, clsAttrsLst, cache, graph, funcTree, - BackendDAE.EVENT_INFO(timeEvents, whenClauseLst, zeroCrossingLst, sampleLst, relationsLst, numMathFunctions, clocks), - eoc, btp, symjacs, ei); - then (outSystem,outShared); - else (inSystem,inShared); + syst.orderedVars = orderedVars; + syst.orderedEqs = orderedEqs; + + eventInfo.whenClauseLst = whenClauseLst; + shared.eventInfo = eventInfo; + shared.knownVars = knvars; + shared.aliasVars = aliasVars; + shared.initialEqs = inieqns; + shared.removedEqs = remeqns; + + then (BackendDAEUtil.clearEqSyst(syst), shared); + else (inSystem, inShared); end matchcontinue; end eliminateTrivialEquations; diff --git a/Compiler/BackEnd/ResolveLoops.mo b/Compiler/BackEnd/ResolveLoops.mo index 79e55c1cbbe..fbb392c770c 100644 --- a/Compiler/BackEnd/ResolveLoops.mo +++ b/Compiler/BackEnd/ResolveLoops.mo @@ -45,9 +45,7 @@ protected import BackendDAEUtil; protected import BackendEquation; protected import BackendVariable; protected import BackendDump; -protected import BackendDAEOptimize; protected import ComponentReference; -protected import Debug; protected import Expression; protected import ExpressionSimplify; protected import ExpressionSolve; @@ -111,10 +109,10 @@ algorithm list crefs; list eqLst,simpEqLst,resolvedEqs; list varLst,simpVarLst; - BackendDAE.BaseClockPartitionKind partitionKind; + BackendDAE.EqSystem syst; - case(_) equation - BackendDAE.EQSYSTEM(orderedVars=vars, orderedEqs=eqs, stateSets=stateSets, partitionKind=partitionKind) = inEqSys; + case syst as BackendDAE.EQSYSTEM(orderedVars=vars, orderedEqs=eqs) + equation eqLst = BackendEquation.equationList(eqs); varLst = BackendVariable.varList(vars); @@ -161,7 +159,7 @@ algorithm // handle the partitions separately, resolve the loops in the partitions, insert the resolved equation eqLst = resolveLoops_resolvePartitions(partitions,m_cut,mT_cut,m,mT,eqMapping,varMapping,eqLst,varLst,nonLoopEqIdcs); - eqs = BackendEquation.listEquation(eqLst); + syst.orderedEqs = BackendEquation.listEquation(eqLst); //BackendDump.dumpEquationList(eqLst,"the complete DAE after resolving"); // get the graphML for the resolved System @@ -175,7 +173,7 @@ algorithm eqAtts = List.threadMap(List.fill(false,numSimpEqs),List.fill("",numSimpEqs),Util.makeTuple); HpcOmEqSystems.dumpEquationSystemBipartiteGraph2(simpVars,simpEqs,m_after,varAtts,eqAtts,"rL_after_"+intString(inSysIdx)); - eqSys = BackendDAEUtil.createEqSystem(vars, eqs, stateSets, partitionKind); + eqSys = BackendDAEUtil.clearEqSyst(syst); then (eqSys, inSysIdx+1); else (inEqSys, inSysIdx+1); @@ -2120,20 +2118,19 @@ algorithm outTpl := (runMatching, offset,maxSize); if runMatching then - osyst := match(osyst) + osyst := match osyst local BackendDAE.Variables vars; BackendDAE.EquationArray eqns; - BackendDAE.StateSets stateSets; - BackendDAE.BaseClockPartitionKind partitionKind; - case (BackendDAE.EQSYSTEM(orderedVars=vars,orderedEqs=eqns,stateSets=stateSets,partitionKind=partitionKind)) + BackendDAE.EqSystem syst; + case syst as BackendDAE.EQSYSTEM(orderedVars=vars, orderedEqs=eqns) equation // remove empty entries from vars/eqns eqns = List.fold(ii,BackendEquation.equationRemove,eqns); - vars = BackendVariable.listVar1(BackendVariable.varList(vars)); - eqns = BackendEquation.listEquation(BackendEquation.equationList(eqns)); + syst.orderedVars = BackendVariable.listVar1(BackendVariable.varList(vars)); + syst.orderedEqs = BackendEquation.listEquation(BackendEquation.equationList(eqns)); then - BackendDAEUtil.createEqSystem(vars, eqns, stateSets, partitionKind); + BackendDAEUtil.clearEqSyst(syst); end match; end if; end solveLinearSystem1; @@ -2181,7 +2178,7 @@ algorithm end solveLinearSystem2; protected function solveLinearSystem3 - input BackendDAE.EqSystem syst; + input BackendDAE.EqSystem inSyst; input BackendDAE.Shared ishared; input list eqn_lst; input list eqn_indxs; @@ -2194,10 +2191,10 @@ protected function solveLinearSystem3 output Integer offset_; algorithm (osyst,oshared, offset_):= - match (syst, ishared) + match (inSyst, ishared) local - BackendDAE.Variables vars,v; - BackendDAE.EquationArray eqns, eqns1; + BackendDAE.Variables vars; + BackendDAE.EquationArray eqns; list beqs; list sources; Integer linInfo; @@ -2205,23 +2202,23 @@ algorithm BackendDAE.Matching matching; DAE.FunctionTree funcs; BackendDAE.Shared shared; - BackendDAE.StateSets stateSets; - BackendDAE.BaseClockPartitionKind partitionKind; + BackendDAE.EqSystem syst; Integer n; - case ( BackendDAE.EQSYSTEM(orderedVars=vars, orderedEqs=eqns, matching=matching, stateSets=stateSets, partitionKind=partitionKind), + case ( syst as BackendDAE.EQSYSTEM(orderedVars=vars, orderedEqs=eqns), shared as BackendDAE.SHARED(functionTree=funcs) ) - equation - v = BackendVariable.listVar1(var_lst); - eqns1 = BackendEquation.listEquation(eqn_lst); - (beqs,_) = BackendDAEUtil.getEqnSysRhs(eqns1,v,SOME(funcs)); - beqs = listReverse(beqs); - n = listLength(beqs); - names = List.map(var_lst,BackendVariable.varCref); - (eqns,vars, n, shared) = solveLinearSystem4(beqs, jac, names, var_lst, n, eqns, vars, offset, shared); + algorithm + (beqs, _) := BackendDAEUtil.getEqnSysRhs( BackendEquation.listEquation(eqn_lst), + BackendVariable.listVar1(var_lst), SOME(funcs) ); + beqs := listReverse(beqs); + n := listLength(beqs); + names := List.map(var_lst, BackendVariable.varCref); + (eqns, vars, n, shared) := solveLinearSystem4(beqs, jac, names, var_lst, n, eqns, vars, offset, shared); + syst.orderedVars := vars; syst.orderedEqs := eqns; + syst := BackendDAEUtil.setEqSystMatrices(syst); //eqns = List.fold(eqn_indxs,BackendEquation.equationRemove,eqns); then - (BackendDAE.EQSYSTEM(vars, eqns, NONE(), NONE(), matching, stateSets, partitionKind), shared, n); + (syst, shared, n); end match; end solveLinearSystem3; diff --git a/Compiler/BackEnd/Sorting.mo b/Compiler/BackEnd/Sorting.mo index 38b8fa53d20..1ec524b1bb9 100644 --- a/Compiler/BackEnd/Sorting.mo +++ b/Compiler/BackEnd/Sorting.mo @@ -39,11 +39,7 @@ encapsulated package Sorting public import BackendDAE; protected import BackendDump; -protected import Debug; -protected import Error; -protected import List; protected import Matching; -protected import Util; public function Tarjan "author: lochel This sorting algorithm only considers equations e that have a matched variable v with e = ass1[v]." diff --git a/Compiler/BackEnd/StateMachineFeatures.mo b/Compiler/BackEnd/StateMachineFeatures.mo index 21b0bdc2a9b..e9c7856a458 100644 --- a/Compiler/BackEnd/StateMachineFeatures.mo +++ b/Compiler/BackEnd/StateMachineFeatures.mo @@ -47,9 +47,6 @@ protected import BackendEquation; protected import BackendVariable; protected import ComponentReference; protected import DAEUtil; -protected import Debug; -protected import Error; -protected import Flags; protected import List; protected import Util; protected import HashSet; diff --git a/Compiler/BackEnd/SymbolicJacobian.mo b/Compiler/BackEnd/SymbolicJacobian.mo index b68d0cdf175..513c6ed9d3b 100644 --- a/Compiler/BackEnd/SymbolicJacobian.mo +++ b/Compiler/BackEnd/SymbolicJacobian.mo @@ -62,7 +62,6 @@ protected import DynamicOptimization; protected import Expression; protected import ExpressionDump; protected import ExpressionSimplify; -protected import ExpressionSolve; protected import Error; protected import Flags; protected import Global; @@ -70,7 +69,7 @@ protected import Graph; protected import HashSet; protected import IndexReduction; protected import List; -protected import SimCodeUtil; +protected import SimCodeFunctionUtil; protected import System; protected import Util; protected import Values; @@ -1699,14 +1698,14 @@ algorithm seedlst = List.map1(comref_vars, createSeedVars, inName); s1 = intString(listLength(inVars)); - //SimCodeUtil.execStat("analytical Jacobians -> starting to generate the jacobian. DiffVars:" + s + " diffed equations: " + s1); + //SimCodeFunctionUtil.execStat("analytical Jacobians -> starting to generate the jacobian. DiffVars:" + s + " diffed equations: " + s1); // Differentiate the ODE system w.r.t states for jacobian (backendDAE as BackendDAE.DAE(shared=shared), funcs) = generateSymbolicJacobian(reduceDAE, inDiffVars, inDifferentiatedVars, BackendVariable.listVar1(seedlst), inStateVars, inInputVars, inParameterVars, inName); if Flags.isSet(Flags.JAC_DUMP2) then print("analytical Jacobians -> generated equations for Jacobian " + inName + " time: " + realString(clock()) + "\n"); end if; - //SimCodeUtil.execStat("analytical Jacobians -> generated jacobian equations"); + //SimCodeFunctionUtil.execStat("analytical Jacobians -> generated jacobian equations"); knvars1 = BackendVariable.daeKnVars(shared); knvarsTmp = BackendVariable.varList(knvars1); @@ -1730,11 +1729,11 @@ algorithm end if; knvars = BackendVariable.listVar1(knvarsTmp); backendDAE = BackendDAEUtil.setKnownVars(backendDAE, knvars); - SimCodeUtil.execStat("analytical Jacobians -> generated optimized jacobians"); + SimCodeFunctionUtil.execStat("analytical Jacobians -> generated optimized jacobians"); // generate sparse pattern (sparsepattern,colsColors) = generateSparsePattern(reduceDAE, inDiffVars, diffedVars); - //SimCodeUtil.execStat("analytical Jacobians -> generated generateSparsePattern"); + //SimCodeFunctionUtil.execStat("analytical Jacobians -> generated generateSparsePattern"); then ((backendDAE, inName, inDiffVars, diffedVars, inVars), sparsepattern, colsColors, funcs); else diff --git a/Compiler/BackEnd/SynchronousFeatures.mo b/Compiler/BackEnd/SynchronousFeatures.mo index 51bc4771468..1733355b84e 100644 --- a/Compiler/BackEnd/SynchronousFeatures.mo +++ b/Compiler/BackEnd/SynchronousFeatures.mo @@ -50,7 +50,6 @@ protected import BackendEquation; protected import BackendVariable; protected import ComponentReference; protected import DAEUtil; -protected import Debug; protected import Error; protected import Flags; protected import List; @@ -216,25 +215,28 @@ protected function removeHoldExpsSyst input list inSysts; output list outSysts = {}; output list outHoldComps = {}; -protected - BackendDAE.EquationArray eqs; - BackendDAE.Variables vars; - BackendDAE.Equation eq; - list lstEqs; - Integer i; - BackendDAE.EqSystem syst; - BackendDAE.BaseClockPartitionKind partitionKind; algorithm - for syst in inSysts loop - lstEqs := {}; - BackendDAE.EQSYSTEM(orderedVars = vars, orderedEqs = eqs, partitionKind = partitionKind) := syst; - for i in 1:BackendDAEUtil.equationArraySize(eqs) loop - eq := BackendEquation.equationNth1(eqs, i); - (eq, outHoldComps) := BackendEquation.traverseExpsOfEquation(eq, removeHoldExp1, outHoldComps); - lstEqs := eq::lstEqs; - end for; - outSysts := BackendDAEUtil.createEqSystem( vars, BackendEquation.listEquation(listReverse(lstEqs)), - {}, partitionKind ) :: outSysts; + for syst1 in inSysts loop + syst1 := match syst1 + local + BackendDAE.EquationArray eqs; + BackendDAE.Variables vars; + BackendDAE.EqSystem syst; + list lstEqs; + Integer i; + BackendDAE.Equation eq; + case syst as BackendDAE.EQSYSTEM(orderedVars = vars, orderedEqs = eqs) + algorithm + lstEqs := {}; + for i in 1:BackendDAEUtil.equationArraySize(eqs) loop + eq := BackendEquation.equationNth1(eqs, i); + (eq, outHoldComps) := BackendEquation.traverseExpsOfEquation(eq, removeHoldExp1, outHoldComps); + lstEqs := eq::lstEqs; + end for; + syst.orderedEqs := BackendEquation.listEquation(listReverse(lstEqs)); + then syst; + end match; + outSysts := BackendDAEUtil.clearEqSyst(syst1) :: outSysts; end for; end removeHoldExpsSyst; @@ -1000,27 +1002,28 @@ protected function substituteParitionOpExps and the equation $var_i = expr_i is added to the equation set." input BackendDAE.EqSystem inSyst; output BackendDAE.EqSystem outSyst; -protected - BackendDAE.Variables vars; - BackendDAE.EquationArray eqs; - list newEqs = {}; - list newVars = {}; - Integer cnt = 1; - BackendDAE.StateSets stateSets; - BackendDAE.Equation eq; - Integer eqSize; algorithm - BackendDAE.EQSYSTEM(orderedVars=vars, orderedEqs=eqs) := inSyst; - eqSize := BackendDAEUtil.equationArraySize(eqs); - for i in 1:eqSize loop - eq := BackendEquation.equationNth1(eqs, i); - (eq, (newEqs, newVars, cnt)) := - BackendEquation.traverseExpsOfEquation(eq, substituteParitionOpExp, (newEqs, newVars, cnt)); - newEqs := eq::newEqs; - end for; - eqs := BackendEquation.listEquation(listReverse(newEqs)); - vars := BackendVariable.addVars(newVars, vars); - outSyst := BackendDAEUtil.createEqSystem(vars, eqs); + outSyst := match inSyst + local + BackendDAE.Variables vars; + BackendDAE.EquationArray eqs; + BackendDAE.EqSystem syst; + list newEqs = {}; + list newVars = {}; + Integer cnt = 1; + BackendDAE.Equation eq; + case syst as BackendDAE.EQSYSTEM(orderedVars=vars, orderedEqs=eqs) + algorithm + for i in 1:BackendDAEUtil.equationArraySize(eqs) loop + eq := BackendEquation.equationNth1(eqs, i); + (eq, (newEqs, newVars, cnt)) := + BackendEquation.traverseExpsOfEquation(eq, substituteParitionOpExp, (newEqs, newVars, cnt)); + newEqs := eq::newEqs; + end for; + syst.orderedEqs := BackendEquation.listEquation(listReverse(newEqs)); + syst.orderedVars := BackendVariable.addVars(newVars, vars); + then BackendDAEUtil.clearEqSyst(syst); + end match; end substituteParitionOpExps; protected function substituteParitionOpExp @@ -1483,18 +1486,15 @@ protected function setSystPartition input BackendDAE.EqSystem inSyst; input BackendDAE.BaseClockPartitionKind inPartitionKind; output BackendDAE.EqSystem outSyst; -protected - BackendDAE.Variables orderedVars; - BackendDAE.EquationArray orderedEqs; - Option m; - Option mT; - BackendDAE.Matching matching; - BackendDAE.StateSets stateSets; - BackendDAE.EquationArray removedEqs; - BackendDAE.EventInfo eventInfo; algorithm - BackendDAE.EQSYSTEM( orderedVars=orderedVars, orderedEqs=orderedEqs, stateSets=stateSets) := inSyst; - outSyst := BackendDAEUtil.createEqSystem(orderedVars, orderedEqs, stateSets, inPartitionKind); + outSyst := match inSyst + local + BackendDAE.EqSystem syst; + case syst as BackendDAE.EQSYSTEM() + algorithm + syst.partitionKind := inPartitionKind; + then syst; + end match; end setSystPartition; protected function getPartitionConflictError diff --git a/Compiler/BackEnd/Tearing.mo b/Compiler/BackEnd/Tearing.mo index 61c0f6c6116..d996aeb243e 100644 --- a/Compiler/BackEnd/Tearing.mo +++ b/Compiler/BackEnd/Tearing.mo @@ -46,13 +46,10 @@ protected import Array; protected import BackendDAEEXT; protected import BackendDAEOptimize; protected import BackendDAEUtil; -protected import BackendDAETransform; protected import BackendDump; protected import BackendEquation; protected import BackendVariable; protected import Config; -protected import Debug; -protected import Differentiate; protected import DumpGraphML; protected import Error; protected import Expression; @@ -63,8 +60,6 @@ protected import Flags; protected import List; protected import Matching; protected import Util; -protected import SCode; -protected import SCodeDump; protected import Sorting; // ============================================================================= diff --git a/Compiler/BackEnd/Uncertainties.mo b/Compiler/BackEnd/Uncertainties.mo index a788c619ab6..a33de7f691a 100644 --- a/Compiler/BackEnd/Uncertainties.mo +++ b/Compiler/BackEnd/Uncertainties.mo @@ -43,7 +43,6 @@ public import Values; protected import Algorithm; protected import BackendDAECreate; protected import BackendDAEEXT; -protected import BackendDAETransform; protected import BackendDAEUtil; protected import BackendEquation; protected import BackendVariable; diff --git a/Compiler/BackEnd/UnitCheck.mo b/Compiler/BackEnd/UnitCheck.mo index c0301fb3ce4..34cd946655c 100644 --- a/Compiler/BackEnd/UnitCheck.mo +++ b/Compiler/BackEnd/UnitCheck.mo @@ -51,11 +51,9 @@ protected import BackendVariable; protected import BackendDAEUtil; protected import BaseHashTable; protected import ComponentReference; -protected import Debug; protected import Error; protected import Expression; protected import ExpressionDump; -protected import FCore; protected import Flags; protected import HashTableCrToUnit; protected import HashTableStringToUnit; diff --git a/Compiler/BackEnd/Vectorization.mo b/Compiler/BackEnd/Vectorization.mo index b5f1b8f710c..9993aa5abd2 100644 --- a/Compiler/BackEnd/Vectorization.mo +++ b/Compiler/BackEnd/Vectorization.mo @@ -50,8 +50,6 @@ protected import Dump; protected import ExpressionDump; protected import ExpressionSimplify; protected import List; -protected import SCode; -protected import SCodeDump; protected import SimCode; protected import SimCodeVar; protected import Util; @@ -1405,53 +1403,42 @@ public function prepareVectorizedDAE0 input BackendDAE.Shared sharedIn; output BackendDAE.EqSystem sysOut; output BackendDAE.Shared sharedOut; -protected - array ass1, ass2; - BackendDAE.Variables vars, aliasVars,knownVars; - list varLst, addAlias, aliasLst, knownLst; - list eqLst; - BackendDAE.EquationArray eqs; - Option m; - Option mT; - BackendDAE.Matching matching; - BackendDAE.StrongComponents compsIn, comps; - BackendDAE.StateSets stateSets "the statesets of the system"; - BackendDAE.BaseClockPartitionKind partitionKind; - BackendDAE.Shared shared; algorithm - BackendDAE.EQSYSTEM(orderedVars=vars, orderedEqs=eqs, m=m, mT=mT, matching=matching, stateSets=stateSets, partitionKind=partitionKind) := sysIn; - BackendDAE.SHARED(aliasVars=aliasVars, knownVars=knownVars) := sharedIn; - - - eqLst := BackendEquation.equationList(eqs); - //BackendDump.dumpEquationList(eqLst,"eqsIn"); - //remove partly unrolled for-equations - // occasionally, there is a constantly indexed var in the for-equation - (eqLst,_) := updateIterCrefs(eqLst,({},{})); - // (eqLst,_) := List.fold(eqLst,markUnrolledForEqs,({},{})); - - // set subscripts at end of equation crefs - eqLst := List.map(listReverse(eqLst),setSubscriptsAtEndForEquation); - - // set subscripts at end of vars - varLst := BackendVariable.varList(vars); - aliasLst := BackendVariable.varList(aliasVars); - knownLst := BackendVariable.varList(knownVars); - varLst := List.map(varLst,appendSubscriptsInVar); - aliasLst := List.map(aliasLst,appendSubscriptsInVar); - knownLst := List.map(knownLst,appendSubscriptsInVar); - vars := BackendVariable.listVar1(varLst); - aliasVars := BackendVariable.listVar1(aliasLst); - knownVars := BackendVariable.listVar1(knownLst); - - eqs := BackendEquation.listEquation(eqLst); - //BackendDump.dumpEquationList(eqLst,"eqsOut"); - //BackendDump.dumpVariables(vars,"VARSOUT"); - - sysOut := BackendDAE.EQSYSTEM(vars, eqs, m, mT, matching, stateSets, partitionKind); - shared := BackendDAEUtil.setSharedRemovedEqns(sharedIn, BackendEquation.listEquation({})); - shared := BackendDAEUtil.setSharedAliasVars(shared, aliasVars); - sharedOut := BackendDAEUtil.setSharedKnVars(shared,knownVars); + (sysOut, sharedOut) := match (sysIn, sharedIn) + local + BackendDAE.Shared shared; + BackendDAE.EqSystem syst; + list varLst, addAlias, aliasLst, knownLst; + list eqLst; + case ( syst as BackendDAE.EQSYSTEM(), + shared as BackendDAE.SHARED() ) + algorithm + eqLst := BackendEquation.equationList(syst.orderedEqs); + //BackendDump.dumpEquationList(eqLst,"eqsIn"); + //remove partly unrolled for-equations + // occasionally, there is a constantly indexed var in the for-equation + (eqLst,_) := updateIterCrefs(eqLst,({},{})); + // (eqLst,_) := List.fold(eqLst,markUnrolledForEqs,({},{})); + + // set subscripts at end of equation crefs + eqLst := List.map(listReverse(eqLst),setSubscriptsAtEndForEquation); + + // set subscripts at end of vars + varLst := BackendVariable.varList(syst.orderedVars); + aliasLst := BackendVariable.varList(shared.aliasVars); + knownLst := BackendVariable.varList(shared.knownVars); + varLst := List.map(varLst,appendSubscriptsInVar); + aliasLst := List.map(aliasLst,appendSubscriptsInVar); + knownLst := List.map(knownLst,appendSubscriptsInVar); + syst.orderedVars := BackendVariable.listVar1(varLst); + shared.aliasVars := BackendVariable.listVar1(aliasLst); + shared.knownVars := BackendVariable.listVar1(knownLst); + shared.removedEqs := BackendEquation.listEquation({}); + syst.orderedEqs := BackendEquation.listEquation(eqLst); + //BackendDump.dumpEquationList(eqLst,"eqsOut"); + //BackendDump.dumpVariables(vars,"VARSOUT"); + then (syst, shared); + end match; end prepareVectorizedDAE0; protected function setSubscriptsAtEndForEquation @@ -1586,29 +1573,29 @@ protected BackendDAE.StateSets stateSets; BackendDAE.BaseClockPartitionKind partitionKind; algorithm - BackendDAE.EQSYSTEM(orderedVars=vars, orderedEqs=eqs, m=m, mT=mT, matching=matching, stateSets=stateSets, partitionKind=partitionKind) := sysIn; - BackendDAE.SHARED(aliasVars=aliasVars, knownVars=knownVars) := sharedIn; - - varLst := BackendVariable.varList(vars); - aliasLst := BackendVariable.varList(aliasVars); - knownLst := BackendVariable.varList(knownVars); - //BackendDump.dumpVarList(varLst,"varLst0"); - //BackendDump.dumpVarList(aliasLst,"aliasVars0"); - //BackendDump.dumpVarList(knownLst,"knownLst0"); - //BackendDump.dumpVarList(aliasLst,"aliasVars0"); - - (varLst,aliasLst) := enlargeIteratedArrayVars1(varLst,aliasLst,{},{}); - (knownLst,knownLst2) := enlargeIteratedArrayVars1(knownLst,{},{},{}); - - //BackendDump.dumpVarList(varLst,"varLst1"); - //BackendDump.dumpVarList(aliasLst,"aliasVars1"); - //BackendDump.dumpVarList(knownLst,"knownLst1"); - - vars := BackendVariable.listVar1(varLst); - aliasVars := BackendVariable.listVar1(aliasLst); - sysOut := BackendDAE.EQSYSTEM(vars,eqs,m,mT,matching,stateSets,partitionKind); - sharedOut := BackendDAEUtil.setSharedAliasVars(sharedIn,aliasVars); - sharedOut := BackendDAEUtil.setSharedKnVars(sharedOut,BackendVariable.listVar1(knownLst)); + (sysOut, sharedOut) := match (sysIn, sharedIn) + local + BackendDAE.EqSystem syst; + BackendDAE.Shared shared; + case (syst as BackendDAE.EQSYSTEM(), shared as BackendDAE.SHARED()) + algorithm + varLst := BackendVariable.varList(syst.orderedVars); + aliasLst := BackendVariable.varList(shared.aliasVars); + knownLst := BackendVariable.varList(shared.knownVars); + (varLst, aliasLst) := enlargeIteratedArrayVars1(varLst, aliasLst, {}, {}); + (knownLst, knownLst2) := enlargeIteratedArrayVars1(knownLst, {}, {}, {}); + syst.orderedVars := BackendVariable.listVar1(varLst); + shared.aliasVars := BackendVariable.listVar1(aliasLst); + shared.knownVars := BackendVariable.listVar1(knownLst); + //BackendDump.dumpVarList(varLst,"varLst0"); + //BackendDump.dumpVarList(aliasLst,"aliasVars0"); + //BackendDump.dumpVarList(knownLst,"knownLst0"); + //BackendDump.dumpVarList(aliasLst,"aliasVars0"); + //BackendDump.dumpVarList(varLst,"varLst1"); + //BackendDump.dumpVarList(aliasLst,"aliasVars1"); + //BackendDump.dumpVarList(knownLst,"knownLst1"); + then (syst, shared); + end match; end enlargeIteratedArrayVars; diff --git a/Compiler/FFrontEnd/FGraphStream.mo b/Compiler/FFrontEnd/FGraphStream.mo index 7e4679210cd..7c0d0287520 100644 --- a/Compiler/FFrontEnd/FGraphStream.mo +++ b/Compiler/FFrontEnd/FGraphStream.mo @@ -70,38 +70,20 @@ type Visited = FCore.Visited; public function start algorithm - _ := matchcontinue() - - case () - equation - true = Flags.isSet(Flags.GRAPH_INST_SHOW_GRAPH); - _ = GraphStream.startExternalViewer("localhost", 2001); - GraphStream.newStream("default", "localhost", 2001, false); - GraphStream.addGraphAttribute("default", "omc", -1, "stylesheet", Values.STRING("node{fill-mode:plain;fill-color:#567;size:6px;}")); - // GraphStream.addGraphAttribute("default", "omc", -1, "ui.antialias", Values.BOOL(true)); - // GraphStream.addGraphAttribute("default", "omc", -1, "layout.stabilization-limit", Values.INTEGER(0)); - then - (); - - else (); - - end matchcontinue; + if Flags.isSet(Flags.GRAPH_INST_SHOW_GRAPH) then + GraphStream.startExternalViewer("localhost", 2001); + GraphStream.newStream("default", "localhost", 2001, false); + GraphStream.addGraphAttribute("default", "omc", -1, "stylesheet", Values.STRING("node{fill-mode:plain;fill-color:#567;size:6px;}")); + // GraphStream.addGraphAttribute("default", "omc", -1, "ui.antialias", Values.BOOL(true)); + // GraphStream.addGraphAttribute("default", "omc", -1, "layout.stabilization-limit", Values.INTEGER(0)); + end if; end start; public function finish algorithm - _ := matchcontinue() - - case () - equation - true = Flags.isSet(Flags.GRAPH_INST_SHOW_GRAPH); - GraphStream.cleanup(); - then - (); - - else (); - - end matchcontinue; + if Flags.isSet(Flags.GRAPH_INST_SHOW_GRAPH) then + GraphStream.cleanup(); + end if; end finish; diff --git a/Compiler/FFrontEnd/FMod.mo b/Compiler/FFrontEnd/FMod.mo index ba6edd1003c..c3f07d8e8f3 100644 --- a/Compiler/FFrontEnd/FMod.mo +++ b/Compiler/FFrontEnd/FMod.mo @@ -49,7 +49,6 @@ import FCore; protected import List; import Error; -import System; public type Name = FCore.Name; diff --git a/Compiler/FFrontEnd/FResolve.mo b/Compiler/FFrontEnd/FResolve.mo index 5fbbf6d1ef1..60540c06607 100644 --- a/Compiler/FFrontEnd/FResolve.mo +++ b/Compiler/FFrontEnd/FResolve.mo @@ -43,7 +43,6 @@ public import Absyn; import FCore; import FNode; -import FGraph; import FLookup; protected diff --git a/Compiler/FrontEnd/BackendInterface.mo b/Compiler/FrontEnd/BackendInterface.mo index f8b19770080..ac6e6f3db7d 100644 --- a/Compiler/FrontEnd/BackendInterface.mo +++ b/Compiler/FrontEnd/BackendInterface.mo @@ -40,15 +40,11 @@ public import Absyn; public import DAE; public import FCore; public import GlobalScript; -public import GraphML; public import Prefix; public import Values; protected import CevalScript; -protected import GraphMLDumpTpl; protected import StaticScript; -protected import RewriteRules; -protected import Tpl; public function cevalInteractiveFunctions input FCore.Cache inCache; diff --git a/Compiler/FrontEnd/Ceval.mo b/Compiler/FrontEnd/Ceval.mo index 18a3b0214c3..f9a73c2ae0e 100644 --- a/Compiler/FrontEnd/Ceval.mo +++ b/Compiler/FrontEnd/Ceval.mo @@ -75,11 +75,9 @@ protected import ExpressionDump; protected import ExpressionSimplify; protected import Flags; protected import HashTable; -protected import Inst; protected import InstBinding; protected import InstUtil; protected import List; -protected import Mod; protected import ModelicaExternalC; protected import Prefix; protected import Print; diff --git a/Compiler/FrontEnd/ClassInf.mo b/Compiler/FrontEnd/ClassInf.mo index b114a73828b..25e616756c1 100644 --- a/Compiler/FrontEnd/ClassInf.mo +++ b/Compiler/FrontEnd/ClassInf.mo @@ -53,7 +53,6 @@ public import Absyn; protected import Debug; protected import Error; protected import Flags; -protected import List; protected import Print; protected import SCodeDump; diff --git a/Compiler/FrontEnd/ClassLoader.mo b/Compiler/FrontEnd/ClassLoader.mo index 82192d224af..19ec8686dbf 100644 --- a/Compiler/FrontEnd/ClassLoader.mo +++ b/Compiler/FrontEnd/ClassLoader.mo @@ -44,7 +44,6 @@ encapsulated package ClassLoader import Absyn; protected -import BackendInterface; import BaseHashTable; import Config; import Debug; diff --git a/Compiler/FrontEnd/ConnectionGraph.mo b/Compiler/FrontEnd/ConnectionGraph.mo index 7ae299ee7bd..717a814777d 100644 --- a/Compiler/FrontEnd/ConnectionGraph.mo +++ b/Compiler/FrontEnd/ConnectionGraph.mo @@ -75,7 +75,6 @@ public import HashTable3; public import HashTableCG; public import Connect; -protected import Error; public type Edge = tuple "an edge is a tuple with two component references"; public type Edges = list "A list of edges"; @@ -348,7 +347,6 @@ protected import BaseHashTable; protected import ComponentReference; protected import ConnectUtil; protected import Debug; -protected import Expression; protected import ExpressionDump; protected import Flags; protected import List; diff --git a/Compiler/FrontEnd/DAEDump.mo b/Compiler/FrontEnd/DAEDump.mo index aaa4af981a4..4eb2e438771 100644 --- a/Compiler/FrontEnd/DAEDump.mo +++ b/Compiler/FrontEnd/DAEDump.mo @@ -48,7 +48,6 @@ public import SCode; protected import ComponentReference; protected import Config; protected import DAEUtil; -protected import Debug; protected import Error; protected import Print; protected import Util; diff --git a/Compiler/FrontEnd/DAEUtil.mo b/Compiler/FrontEnd/DAEUtil.mo index 63d340601c1..88795c95ba2 100644 --- a/Compiler/FrontEnd/DAEUtil.mo +++ b/Compiler/FrontEnd/DAEUtil.mo @@ -4190,6 +4190,34 @@ protected uniontype TraverseStatementsOptions end TRAVERSE_RHS_ONLY; end TraverseStatementsOptions; +public function traverseAlgorithmExps " + This function goes through the Algorithm structure and finds all the + expressions and performs the function on them +" + replaceable type Type_a subtypeof Any; + input DAE.Algorithm inAlgorithm; + input FuncExpType func; + input Type_a inTypeA; + output Type_a outTypeA; + partial function FuncExpType + input DAE.Exp inExp; + input Type_a inTypeA; + output DAE.Exp outExp; + output Type_a outA; + end FuncExpType; +algorithm + outTypeA := match (inAlgorithm,func,inTypeA) + local + list stmts; + Type_a ext_arg_1; + case (DAE.ALGORITHM_STMTS(statementLst = stmts),_,_) + equation + (_,ext_arg_1) = DAEUtil.traverseDAEEquationsStmts(stmts,func,inTypeA); + then + ext_arg_1; + end match; +end traverseAlgorithmExps; + public function traverseDAEEquationsStmts "Traversing of DAE.Statement." input list inStmts; input FuncExpType func; diff --git a/Compiler/FrontEnd/Inline.mo b/Compiler/FrontEnd/Inline.mo index 7cdb30f20c0..2a7f466419e 100644 --- a/Compiler/FrontEnd/Inline.mo +++ b/Compiler/FrontEnd/Inline.mo @@ -44,11 +44,9 @@ encapsulated package Inline public import Absyn; public import BaseHashTable; public import DAE; -public import FCore; public import HashTableCG; public import SCode; public import Util; -public import Values; public type Functiontuple = tuple,list>; diff --git a/Compiler/FrontEnd/InnerOuter.mo b/Compiler/FrontEnd/InnerOuter.mo index c4ef149603d..acbded5a2fa 100644 --- a/Compiler/FrontEnd/InnerOuter.mo +++ b/Compiler/FrontEnd/InnerOuter.mo @@ -56,7 +56,6 @@ protected import Error; protected import ErrorExt; protected import Expression; protected import Flags; -protected import Inst; protected import InstSection; protected import List; protected import Lookup; diff --git a/Compiler/FrontEnd/InstExtends.mo b/Compiler/FrontEnd/InstExtends.mo index 4ebed84954b..401092ff1db 100644 --- a/Compiler/FrontEnd/InstExtends.mo +++ b/Compiler/FrontEnd/InstExtends.mo @@ -53,7 +53,6 @@ public import Prefix; // protected imports protected import BaseHashTable; -protected import Builtin; protected import ComponentReference; protected import Debug; protected import Dump; diff --git a/Compiler/FrontEnd/InstFunction.mo b/Compiler/FrontEnd/InstFunction.mo index 4dc99b79051..8907b6b799f 100644 --- a/Compiler/FrontEnd/InstFunction.mo +++ b/Compiler/FrontEnd/InstFunction.mo @@ -54,10 +54,7 @@ public import SCode; public import UnitAbsyn; protected import Lookup; -protected import MetaUtil; protected import Inst; -protected import InstBinding; -protected import InstVar; protected import InstUtil; protected import UnitAbsynBuilder; protected import List; @@ -72,7 +69,6 @@ protected import Config; protected import DAEUtil; protected import PrefixUtil; protected import Error; -protected import Builtin; protected type Ident = DAE.Ident "an identifier"; protected type InstanceHierarchy = InnerOuter.InstHierarchy "an instance hierarchy"; diff --git a/Compiler/FrontEnd/InstUtil.mo b/Compiler/FrontEnd/InstUtil.mo index 25c7b3ae264..5b28af633a9 100644 --- a/Compiler/FrontEnd/InstUtil.mo +++ b/Compiler/FrontEnd/InstUtil.mo @@ -8526,8 +8526,6 @@ algorithm ((_,b,unbound)) = List.fold1(stmts, checkFunctionDefUseStmt, true, (false,false,unbound)); then ((b,b,unbound)); case (DAE.STMT_ASSERT(cond=DAE.BCONST(false),source=source),_,(_,_,_)) // TODO: Re-write these earlier from assert(false,msg) to terminate(msg) - equation - _ = DAEUtil.getElementSourceFileInfo(source); then ((true,true,{})); case (DAE.STMT_ASSERT(cond=exp1,msg=exp2,source=source),_,(_,_,unbound)) equation @@ -8540,6 +8538,8 @@ algorithm info = DAEUtil.getElementSourceFileInfo(source); (_,(unbound,_)) = Expression.traverseExpTopDown(exp,findUnboundVariableUse,(unbound,info)); then ((true,true,unbound)); + case (DAE.STMT_NORETCALL(exp=DAE.CALL(path=Absyn.IDENT("fail"),expLst={}),source=source),_,(_,_,unbound)) + then ((true,true,{})); case (DAE.STMT_NORETCALL(exp=exp,source=source),_,(_,_,unbound)) equation info = DAEUtil.getElementSourceFileInfo(source); diff --git a/Compiler/FrontEnd/MetaUtil.mo b/Compiler/FrontEnd/MetaUtil.mo index ac65c519359..b7150e0aa78 100644 --- a/Compiler/FrontEnd/MetaUtil.mo +++ b/Compiler/FrontEnd/MetaUtil.mo @@ -45,8 +45,6 @@ public import SCode; public import SCodeUtil; protected import Config; -protected import Dump; -protected import Error; protected import Flags; protected import List; protected import Types; diff --git a/Compiler/FrontEnd/NFConnect2.mo b/Compiler/FrontEnd/NFConnect2.mo index a0f519d1e9c..21b649d517f 100644 --- a/Compiler/FrontEnd/NFConnect2.mo +++ b/Compiler/FrontEnd/NFConnect2.mo @@ -37,7 +37,6 @@ encapsulated package NFConnect2 RCS: $Id$ " -public import Absyn; public import DAE; public uniontype Face diff --git a/Compiler/FrontEnd/NFEnvAvlTree.mo b/Compiler/FrontEnd/NFEnvAvlTree.mo index 3ee1af9ba1d..5283c2a1748 100644 --- a/Compiler/FrontEnd/NFEnvAvlTree.mo +++ b/Compiler/FrontEnd/NFEnvAvlTree.mo @@ -39,7 +39,6 @@ encapsulated package NFEnvAvlTree This package implements an AvlTree that's used by NFEnv. " -public import Absyn; public import NFInstTypes; protected import Error; diff --git a/Compiler/FrontEnd/NFFlatten.mo b/Compiler/FrontEnd/NFFlatten.mo index d6b530c6e62..2e56b312f45 100644 --- a/Compiler/FrontEnd/NFFlatten.mo +++ b/Compiler/FrontEnd/NFFlatten.mo @@ -41,7 +41,6 @@ encapsulated package NFFlatten public import NFInst.{Instance}; -protected import NFEnv; public function flattenClass input Instance inClass; diff --git a/Compiler/FrontEnd/OperatorOverloading.mo b/Compiler/FrontEnd/OperatorOverloading.mo index 4dc08c153a5..f65757996eb 100644 --- a/Compiler/FrontEnd/OperatorOverloading.mo +++ b/Compiler/FrontEnd/OperatorOverloading.mo @@ -53,7 +53,6 @@ import ExpressionDump; import ExpressionSimplify; import FGraph; import Flags; -import Global; import Inline; import List; import Lookup; diff --git a/Compiler/FrontEnd/Parser.mo b/Compiler/FrontEnd/Parser.mo index 01cf0392a80..299f7fe6d27 100644 --- a/Compiler/FrontEnd/Parser.mo +++ b/Compiler/FrontEnd/Parser.mo @@ -45,7 +45,6 @@ import HashTableStringToProgram; protected import Config; -import Error; import ErrorExt; import Flags; import ParserExt; diff --git a/Compiler/FrontEnd/Patternm.mo b/Compiler/FrontEnd/Patternm.mo index f00b591a567..e177e7953bb 100644 --- a/Compiler/FrontEnd/Patternm.mo +++ b/Compiler/FrontEnd/Patternm.mo @@ -60,7 +60,6 @@ protected import BaseHashTable; protected import ComponentReference; protected import Connect; protected import DAEUtil; -protected import Debug; protected import Expression; protected import ExpressionDump; protected import Error; diff --git a/Compiler/FrontEnd/ValuesUtil.mo b/Compiler/FrontEnd/ValuesUtil.mo index e5893455ba8..fe52de541b9 100644 --- a/Compiler/FrontEnd/ValuesUtil.mo +++ b/Compiler/FrontEnd/ValuesUtil.mo @@ -47,7 +47,6 @@ protected import Debug; protected import Dump; protected import Error; protected import Expression; -protected import ExpressionDump; protected import ExpressionSimplify; protected import ExpressionSimplifyTypes; protected import Flags; @@ -56,7 +55,6 @@ protected import Print; protected import System; protected import ClassInf; protected import Types; -protected import SimulationResults; public function typeConvert "Apply type conversion on a list of Values" input DAE.Type inType1; @@ -2488,22 +2486,6 @@ algorithm Absyn.C_TYPENAME(path) := code; end getPath; -public function readDataset - input String filename; - input list vars; - input Integer dimsize; - output Values.Value val; -protected - list> rvals; - list> vals; - list rows; -algorithm - rvals := SimulationResults.readDataset(filename,vars,dimsize); - vals := List.mapListReverse(rvals,makeReal); - rows := List.mapReverse(vals,makeArray); - val := makeArray(rows); -end readDataset; - public function printCodeVariableName input Values.Value val; output String str; diff --git a/Compiler/Main/Main.mo b/Compiler/Main/Main.mo index 4ef50b615e4..7e01f9ac8f8 100644 --- a/Compiler/Main/Main.mo +++ b/Compiler/Main/Main.mo @@ -47,14 +47,13 @@ import BackendDAE; import BackendDAECreate; import BackendDAEUtil; import CevalScript; -import ClassLoader; +import CevalScriptBackend; import ClockIndexes; import Config; import Corba; import DAE; import DAEDump; import DAEUtil; -//import Database; import Debug; import Dump; import DumpGraphviz; @@ -75,7 +74,7 @@ import Print; import Settings; import SimCode; import SimCodeMain; -import SimCodeUtil; +import SimCodeFunctionUtil; import Socket; import System; import TplMain; @@ -482,7 +481,7 @@ algorithm DumpGraphviz.dump(p); end if; - SimCodeUtil.execStat("Parsed file"); + SimCodeFunctionUtil.execStat("Parsed file"); // Instantiate the program. (cache, env, d, cname) = instantiate(p); @@ -492,14 +491,14 @@ algorithm funcs = FCore.getFunctionTree(cache); Print.clearBuf(); - SimCodeUtil.execStat("Transformations before Dump"); + SimCodeFunctionUtil.execStat("Transformations before Dump"); s = DAEDump.dumpStr(d, funcs); - SimCodeUtil.execStat("DAEDump done"); + SimCodeFunctionUtil.execStat("DAEDump done"); Print.printBuf(s); if Flags.isSet(Flags.DAE_DUMP_GRAPHV) then DAEDump.dumpGraphviz(d); end if; - SimCodeUtil.execStat("Misc Dump"); + SimCodeFunctionUtil.execStat("Misc Dump"); // Do any transformations required before going into code generation, e.g. if-equations to expressions. d = if boolNot(Flags.isSet(Flags.TRANSFORMS_BEFORE_DUMP)) then DAEUtil.transformationsBeforeBackend(cache,env,d) else d; @@ -507,7 +506,7 @@ algorithm if not Config.silent() then print(Print.getString()); end if; - SimCodeUtil.execStat("Transformations before backend"); + SimCodeFunctionUtil.execStat("Transformations before backend"); // Run the backend. optimizeDae(cache, env, d, p, cname); @@ -580,7 +579,7 @@ algorithm // program. Otherwise, instantiate the given class name. cname := if stringLength(cls) == 0 then Absyn.lastClassname(program) else Absyn.stringPath(cls); st := GlobalScriptUtil.setSymbolTableAST(GlobalScript.emptySymboltable, program); - (cache, env, dae) := CevalScript.runFrontEnd(FCore.emptyCache(), FGraph.empty(), cname, st, true); + (cache, env, dae) := CevalScriptBackend.runFrontEnd(FCore.emptyCache(), FGraph.empty(), cname, st, true); end instantiate; protected function optimizeDae @@ -627,7 +626,7 @@ algorithm System.realtimeTock(ClockIndexes.RT_CLOCK_BACKEND); // Is this necessary? SimCodeMain.generateModelCode(inBackendDAE, inProgram, inDAE, inClassName, cname, SOME(sim_settings), Absyn.FUNCTIONARGS({}, {})); - SimCodeUtil.execStat("Codegen Done"); + SimCodeFunctionUtil.execStat("Codegen Done"); end if; end simcodegen; diff --git a/Compiler/Script/BlockCallRewrite.mo b/Compiler/Script/BlockCallRewrite.mo index 2966fecec16..bb1392b8af9 100644 --- a/Compiler/Script/BlockCallRewrite.mo +++ b/Compiler/Script/BlockCallRewrite.mo @@ -7,11 +7,8 @@ encapsulated package BlockCallRewrite " public import Absyn; -public import SCode; protected import Dump; -protected import Parser; -protected import Print; public function rewriteBlockCall input Absyn.Program inPg "Model containing block calls"; diff --git a/Compiler/Script/CevalScript.mo b/Compiler/Script/CevalScript.mo index 54c688f9de0..812168d3bf8 100644 --- a/Compiler/Script/CevalScript.mo +++ b/Compiler/Script/CevalScript.mo @@ -51,7 +51,6 @@ encapsulated package CevalScript // public imports import Absyn; -import BackendDAE; import Ceval; import DAE; import FCore; @@ -60,618 +59,233 @@ import GlobalScript; import Interactive; import Values; import SimCode; -import UnitAbsyn; // protected imports protected -import BackendDump; -import BackendDAECreate; -import BackendDAEUtil; -import BackendDAEOptimize; -import BackendEquation; -import BackendVariable; import BaseHashSet; import Builtin; +import CevalScriptBackend; import CevalFunction; -import CheckModel; import ClassInf; import ClassLoader; -import ClockIndexes; -import CodegenC; +import CodegenCFunctions; import Config; import Corba; -import DAEQuery; import DAEUtil; -import DAEDump; import Debug; import Dump; import DynLoad; import Expression; import ExpressionDump; -import Figaro; -import FindZeroCrossings; import Flags; -import FInst; import FGraph; -import FGraphDump; import GC; import GenerateAPIFunctionsTpl; import Global; import GlobalScriptUtil; import Graph; import HashSetString; -import Inst; import InstFunction; -import InnerOuter; -import LexerModelicaDiff; -import DiffAlgorithm; import List; import Lookup; -import MetaUtil; import Mod; -import NFSCodeLookup; import Prefix; import Parser; import Print; -import Refactor; import SCodeDump; -import NFInst; -import NFSCodeEnv; -import NFSCodeFlatten; -import SimCodeMain; +import SimCodeFunction; import System; import Static; -import StaticScript; import SCode; import SCodeUtil; import Settings; -import SimulationResults; -import SymbolicJacobian; -import TaskGraphResults; import Tpl; -import CodegenFMU; import Types; import Unparsing; import Util; import ValuesUtil; -import XMLDump; import ComponentReference; -import Uncertainties; -import OpenTURNS; -import FMI; -import FMIExt; import ErrorExt; -import UnitAbsynBuilder; -import UnitParserExt; -import RewriteRules; -import BlockCallRewrite; - -protected constant DAE.Type simulationResultType_rtest = DAE.T_COMPLEX(ClassInf.RECORD(Absyn.IDENT("SimulationResult")),{ - DAE.TYPES_VAR("resultFile",DAE.dummyAttrVar,DAE.T_STRING_DEFAULT,DAE.UNBOUND(),NONE()), - DAE.TYPES_VAR("simulationOptions",DAE.dummyAttrVar,DAE.T_STRING_DEFAULT,DAE.UNBOUND(),NONE()), - DAE.TYPES_VAR("messages",DAE.dummyAttrVar,DAE.T_STRING_DEFAULT,DAE.UNBOUND(),NONE()) - },NONE(),DAE.emptyTypeSource); - -protected constant DAE.Type simulationResultType_full = DAE.T_COMPLEX(ClassInf.RECORD(Absyn.IDENT("SimulationResult")),{ - DAE.TYPES_VAR("resultFile",DAE.dummyAttrVar,DAE.T_STRING_DEFAULT,DAE.UNBOUND(),NONE()), - DAE.TYPES_VAR("simulationOptions",DAE.dummyAttrVar,DAE.T_STRING_DEFAULT,DAE.UNBOUND(),NONE()), - DAE.TYPES_VAR("messages",DAE.dummyAttrVar,DAE.T_STRING_DEFAULT,DAE.UNBOUND(),NONE()), - DAE.TYPES_VAR("timeFrontend",DAE.dummyAttrVar,DAE.T_REAL_DEFAULT,DAE.UNBOUND(),NONE()), - DAE.TYPES_VAR("timeBackend",DAE.dummyAttrVar,DAE.T_REAL_DEFAULT,DAE.UNBOUND(),NONE()), - DAE.TYPES_VAR("timeSimCode",DAE.dummyAttrVar,DAE.T_REAL_DEFAULT,DAE.UNBOUND(),NONE()), - DAE.TYPES_VAR("timeTemplates",DAE.dummyAttrVar,DAE.T_REAL_DEFAULT,DAE.UNBOUND(),NONE()), - DAE.TYPES_VAR("timeCompile",DAE.dummyAttrVar,DAE.T_REAL_DEFAULT,DAE.UNBOUND(),NONE()), - DAE.TYPES_VAR("timeSimulation",DAE.dummyAttrVar,DAE.T_REAL_DEFAULT,DAE.UNBOUND(),NONE()), - DAE.TYPES_VAR("timeTotal",DAE.dummyAttrVar,DAE.T_REAL_DEFAULT,DAE.UNBOUND(),NONE()) - },NONE(),DAE.emptyTypeSource); - -protected constant DAE.Type simulationResultType_drModelica = DAE.T_COMPLEX(ClassInf.RECORD(Absyn.IDENT("SimulationResult")),{ - DAE.TYPES_VAR("messages",DAE.dummyAttrVar,DAE.T_STRING_DEFAULT,DAE.UNBOUND(),NONE()), - DAE.TYPES_VAR("flatteningTime",DAE.dummyAttrVar,DAE.T_REAL_DEFAULT,DAE.UNBOUND(),NONE()), - DAE.TYPES_VAR("simulationTime",DAE.dummyAttrVar,DAE.T_REAL_DEFAULT,DAE.UNBOUND(),NONE()) - },NONE(),DAE.emptyTypeSource); - -//these are in reversed order than above -protected constant list> zeroAdditionalSimulationResultValues = - { ("timeTotal", Values.REAL(0.0)), - ("timeSimulation", Values.REAL(0.0)), - ("timeCompile", Values.REAL(0.0)), - ("timeTemplates", Values.REAL(0.0)), - ("timeSimCode", Values.REAL(0.0)), - ("timeBackend", Values.REAL(0.0)), - ("timeFrontend", Values.REAL(0.0)) - }; - -protected constant DAE.Exp defaultStartTime = DAE.RCONST(0.0) "default startTime"; -protected constant DAE.Exp defaultStopTime = DAE.RCONST(1.0) "default stopTime"; -protected constant DAE.Exp defaultNumberOfIntervals = DAE.ICONST(500) "default numberOfIntervals"; -protected constant DAE.Exp defaultStepSize = DAE.RCONST(0.002) "default stepSize"; -protected constant DAE.Exp defaultTolerance = DAE.RCONST(1e-6) "default tolerance"; -protected constant DAE.Exp defaultMethod = DAE.SCONST("dassl") "default method"; -protected constant DAE.Exp defaultFileNamePrefix = DAE.SCONST("") "default fileNamePrefix"; -protected constant DAE.Exp defaultOptions = DAE.SCONST("") "default options"; -protected constant DAE.Exp defaultOutputFormat = DAE.SCONST("mat") "default outputFormat"; -protected constant DAE.Exp defaultVariableFilter = DAE.SCONST(".*") "default variableFilter; does whole string matching, i.e. it becomes ^.*$ in the runtime"; -protected constant DAE.Exp defaultCflags = DAE.SCONST("") "default compiler flags"; -protected constant DAE.Exp defaultSimflags = DAE.SCONST("") "default simulation flags"; - -protected constant GlobalScript.SimulationOptions defaultSimulationOptions = - GlobalScript.SIMULATION_OPTIONS( - defaultStartTime, - defaultStopTime, - defaultNumberOfIntervals, - defaultStepSize, - defaultTolerance, - defaultMethod, - defaultFileNamePrefix, - defaultOptions, - defaultOutputFormat, - defaultVariableFilter, - defaultCflags, - defaultSimflags - ) "default simulation options"; - -protected constant list simulationOptionsNames = - { - "startTime", - "stopTime", - "numberOfIntervals", - "tolerance", - "method", - "fileNamePrefix", - "options", - "outputFormat", - "variableFilter", - "cflags", - "simflags" - } "names of simulation options"; - -public function getSimulationResultType - output DAE.Type t; -algorithm - t := if Config.getRunningTestsuite() then simulationResultType_rtest else simulationResultType_full; -end getSimulationResultType; - -public function getDrModelicaSimulationResultType - output DAE.Type t; -algorithm - t := if Config.getRunningTestsuite() then simulationResultType_rtest else simulationResultType_drModelica; -end getDrModelicaSimulationResultType; - -public function createSimulationResult - input String resultFile; - input String options; - input String message; - input list> inAddResultValues "additional values in reversed order; expected values see in CevalScript.simulationResultType_full"; - output Values.Value res; -protected - list> resultValues; - list vals; - list fields; - Boolean isTestType,notest; -algorithm - resultValues := listReverse(inAddResultValues); - //TODO: maybe we should test if the fields are the ones in simulationResultType_full - notest := not Config.getRunningTestsuite(); - fields := if notest then List.map(resultValues, Util.tuple21) else {}; - vals := if notest then List.map(resultValues, Util.tuple22) else {}; - res := Values.RECORD(Absyn.IDENT("SimulationResult"), - Values.STRING(resultFile)::Values.STRING(options)::Values.STRING(message)::vals, - "resultFile"::"simulationOptions"::"messages"::fields,-1); -end createSimulationResult; - -public function createDrModelicaSimulationResult - input String resultFile; - input String options; - input String message; - input list> inAddResultValues "additional values in reversed order; expected values see in CevalScript.simulationResultType_full"; - output Values.Value res; -protected - list> resultValues; - list vals; - list fields; - Boolean isTestType,notest; -algorithm - resultValues := listReverse(inAddResultValues); - //TODO: maybe we should test if the fields are the ones in simulationResultType_full - notest := not Config.getRunningTestsuite(); - fields := if notest then List.map(resultValues, Util.tuple21) else {}; - vals := if notest then List.map(resultValues, Util.tuple22) else {}; - res := Values.RECORD(Absyn.IDENT("SimulationResult"),Values.STRING(message):: - vals, "messages"::fields,-1); -end createDrModelicaSimulationResult; - -public function createSimulationResultFailure - input String message; - input String options; - output Values.Value res; -protected - list vals; - list fields; -algorithm - res := createSimulationResult("", options, message, zeroAdditionalSimulationResultValues); -end createSimulationResultFailure; - -public function createDrModelicaSimulationResultFailure - input String message; - input String options; - output Values.Value res; -protected - list vals; - list fields; -algorithm - res := createDrModelicaSimulationResult("", options, message, {}); -end createDrModelicaSimulationResultFailure; -protected function buildCurrentSimulationResultExp - output DAE.Exp outExp; -protected - DAE.ComponentRef cref; -algorithm - cref := ComponentReference.makeCrefIdent("currentSimulationResult",DAE.T_UNKNOWN_DEFAULT,{}); - outExp := Expression.makeCrefExp(cref,DAE.T_UNKNOWN_DEFAULT); -end buildCurrentSimulationResultExp; +public -protected function cevalCurrentSimulationResultExp +function ceval " + This is a wrapper funtion to Ceval.ceval. The purpose of this + function is to concetrate all the calls to Ceval.ceval made from + the Script files. This will simplify the separation of the scripting + environment from the FrontEnd" input FCore.Cache inCache; - input FCore.Graph env; - input String inputFilename; - input GlobalScript.SymbolTable st; - input Absyn.Msg msg; + input FCore.Graph inEnv; + input DAE.Exp inExp; + input Boolean inBoolean "impl"; + input Option inST; + input Absyn.Msg inMsg; + input Integer numIter; output FCore.Cache outCache; - output String filename; -algorithm - (outCache,filename) := match (inCache,env,inputFilename,st,msg) - local FCore.Cache cache; - case (cache,_,"",_,_) - equation - (cache,Values.STRING(filename),_) = Ceval.ceval(cache,env,buildCurrentSimulationResultExp(),true,SOME(st),msg,0); - then (cache,filename); - else (inCache,inputFilename); - end match; -end cevalCurrentSimulationResultExp; + output Values.Value outValue; + output Option outST; -public function convertSimulationOptionsToSimCode "converts SimulationOptions to SimCode.SimulationSettings" - input GlobalScript.SimulationOptions opts; - output SimCode.SimulationSettings settings; -algorithm - settings := match(opts) - local - Real startTime,stopTime,stepSize,tolerance; - Integer nIntervals; - String method,format,varFilter,cflags,options; - - case(GlobalScript.SIMULATION_OPTIONS( - DAE.RCONST(startTime), - DAE.RCONST(stopTime), - DAE.ICONST(nIntervals), - DAE.RCONST(stepSize), - DAE.RCONST(tolerance), - DAE.SCONST(method), - _, /* fileNamePrefix*/ - _, /* options */ - DAE.SCONST(format), - DAE.SCONST(varFilter), - DAE.SCONST(cflags), - _)) equation - options = ""; - - then SimCode.SIMULATION_SETTINGS(startTime,stopTime,nIntervals,stepSize,tolerance,method,options,format,varFilter,cflags); - end match; -end convertSimulationOptionsToSimCode; - -public function buildSimulationOptions -"@author: adrpo - builds a SimulationOptions record from the given input" - input DAE.Exp startTime "start time, default 0.0"; - input DAE.Exp stopTime "stop time, default 1.0"; - input DAE.Exp numberOfIntervals "number of intervals, default 500"; - input DAE.Exp stepSize "stepSize, default (stopTime-startTime)/numberOfIntervals"; - input DAE.Exp tolerance "tolerance, default 1e-6"; - input DAE.Exp method "method, default 'dassl'"; - input DAE.Exp fileNamePrefix "file name prefix, default ''"; - input DAE.Exp options "options, default ''"; - input DAE.Exp outputFormat "output format, default 'plt'"; - input DAE.Exp variableFilter; - input DAE.Exp cflags; - input DAE.Exp simflags; - output GlobalScript.SimulationOptions outSimulationOptions; -algorithm - outSimulationOptions := - GlobalScript.SIMULATION_OPTIONS( - startTime, - stopTime, - numberOfIntervals, - stepSize, - tolerance, - method, - fileNamePrefix, - options, - outputFormat, - variableFilter, - cflags, - simflags - ); -end buildSimulationOptions; - -public function getSimulationOption -"@author: adrpo - get the value from simulation option" - input GlobalScript.SimulationOptions inSimOpt; - input String optionName; - output DAE.Exp outOptionValue; + partial function ReductionOperator + input Values.Value v1; + input Values.Value v2; + output Values.Value res; + end ReductionOperator; algorithm - outOptionValue := match(inSimOpt, optionName) + (outCache,outValue,outST):= + matchcontinue (inCache,inEnv,inExp,inBoolean,inST,inMsg,numIter) local + Option stOpt; + Boolean impl; + FCore.Graph env; + Absyn.Msg msg; + list vallst; + list expl; + Values.Value newval,value; DAE.Exp e; - String name, msg; - - case (GlobalScript.SIMULATION_OPTIONS(startTime = e), "startTime") then e; - case (GlobalScript.SIMULATION_OPTIONS(stopTime = e), "stopTime") then e; - case (GlobalScript.SIMULATION_OPTIONS(numberOfIntervals = e), "numberOfIntervals") then e; - case (GlobalScript.SIMULATION_OPTIONS(stepSize = e), "stepSize") then e; - case (GlobalScript.SIMULATION_OPTIONS(tolerance = e), "tolerance") then e; - case (GlobalScript.SIMULATION_OPTIONS(method = e), "method") then e; - case (GlobalScript.SIMULATION_OPTIONS(fileNamePrefix = e), "fileNamePrefix") then e; - case (GlobalScript.SIMULATION_OPTIONS(options = e), "options") then e; - case (GlobalScript.SIMULATION_OPTIONS(outputFormat = e), "outputFormat") then e; - case (GlobalScript.SIMULATION_OPTIONS(variableFilter = e), "variableFilter") then e; - case (GlobalScript.SIMULATION_OPTIONS(cflags = e), "cflags") then e; - case (GlobalScript.SIMULATION_OPTIONS(simflags = e), "simflags") then e; - case (_, name) - equation - msg = "Unknown simulation option: " + name; - Error.addCompilerWarning(msg); - then - fail(); - end match; -end getSimulationOption; - -public function buildSimulationOptionsFromModelExperimentAnnotation -"@author: adrpo - retrieve annotation(experiment(....)) values and build a SimulationOptions object to return" - input GlobalScript.SymbolTable inSymTab; - input Absyn.Path inModelPath; - input String inFileNamePrefix; - input Option defaultOption; - output GlobalScript.SimulationOptions outSimOpt; -algorithm - outSimOpt := matchcontinue (inSymTab, inModelPath, inFileNamePrefix, defaultOption) - local - GlobalScript.SimulationOptions defaults, simOpt; - String experimentAnnotationStr; - list named; - - // search inside annotation(experiment(...)) - case (_, _, _, _) - equation - defaults = Util.getOptionOrDefault(defaultOption, setFileNamePrefixInSimulationOptions(defaultSimulationOptions, inFileNamePrefix)); - - experimentAnnotationStr = - Interactive.getNamedAnnotation( - inModelPath, - GlobalScriptUtil.getSymbolTableAST(inSymTab), - Absyn.IDENT("experiment"), - SOME("{}"), - Interactive.getExperimentAnnotationString); - // parse the string we get back, either {} or {StopTime=5, Tolerance = 0.10}; - - // jump to next case if the annotation is empty - false = stringEq(experimentAnnotationStr, "{}"); - - // get rid of '{' and '}' - experimentAnnotationStr = System.stringReplace(experimentAnnotationStr, "{", ""); - experimentAnnotationStr = System.stringReplace(experimentAnnotationStr, "}", ""); - - GlobalScript.ISTMTS({GlobalScript.IEXP(exp = Absyn.CALL(functionArgs = Absyn.FUNCTIONARGS(_, named)))}, _) - = Parser.parsestringexp("experiment(" + experimentAnnotationStr + ");\n", ""); - - simOpt = populateSimulationOptions(defaults, named); - then - simOpt; + Absyn.Path funcpath; + FCore.Cache cache; + GlobalScript.SymbolTable st; - // if we fail, just use the defaults - else + // adrpo: TODO! this needs more work as if we don't have a symtab we run into unloading of dlls problem + case (cache,env,(e as DAE.CALL(path = funcpath,expLst = expl)),impl,stOpt,msg,_) equation - defaults = setFileNamePrefixInSimulationOptions(defaultSimulationOptions, inFileNamePrefix); - then defaults; - end matchcontinue; -end buildSimulationOptionsFromModelExperimentAnnotation; - -protected function setFileNamePrefixInSimulationOptions - input GlobalScript.SimulationOptions inSimOpt; - input String inFileNamePrefix; - output GlobalScript.SimulationOptions outSimOpt; -protected - DAE.Exp startTime, stopTime, numberOfIntervals, stepSize, tolerance, method, fileNamePrefix, options, outputFormat, variableFilter, cflags, simflags; - Boolean UseOtimica; -algorithm - UseOtimica := Config.acceptOptimicaGrammar() or Flags.getConfigBool(Flags.GENERATE_DYN_OPTIMIZATION_PROBLEM); - GlobalScript.SIMULATION_OPTIONS(startTime, stopTime, numberOfIntervals, stepSize, tolerance, method, _, options, outputFormat, variableFilter, cflags, simflags) := inSimOpt; - method := if UseOtimica then DAE.SCONST("optimization") else method; - numberOfIntervals := if UseOtimica then DAE.ICONST(50) else numberOfIntervals; - outSimOpt := GlobalScript.SIMULATION_OPTIONS(startTime, stopTime, numberOfIntervals, stepSize, tolerance, method, DAE.SCONST(inFileNamePrefix), options, outputFormat, variableFilter, cflags, simflags); -end setFileNamePrefixInSimulationOptions; - -protected function getConst -"@author: adrpo - Tranform a literal Absyn.Exp to DAE.Exp with the given DAE.Type" - input Absyn.Exp inAbsynExp; - input DAE.Type inExpType; - output DAE.Exp outExp; -algorithm - outExp := matchcontinue(inAbsynExp, inExpType) - local - Integer i; - Real r; - Absyn.Exp exp; - String str; + // do not handle Connection.isRoot here! + false = stringEq("Connection.isRoot", Absyn.pathString(funcpath)); + // do not roll back errors generated by evaluating the arguments + (cache,vallst,stOpt) = Ceval.cevalList(cache,env, expl, impl, stOpt, msg, numIter); - case (Absyn.UNARY(Absyn.UMINUS(),exp), _) - equation - DAE.ICONST(i) = getConst(exp, inExpType); - i = intNeg(i); + (cache,newval,stOpt)= cevalCallFunction(cache, env, e, vallst, impl, stOpt, msg, numIter+1); then - DAE.ICONST(i); + (cache,newval,stOpt); - case (Absyn.UNARY(Absyn.UMINUS(),exp), _) + // Try Interactive functions last + case (cache,env,(e as DAE.CALL()),(true),SOME(st),msg,_) equation - DAE.RCONST(r) = getConst(exp, inExpType); - r = realNeg(r); + (cache,value,st) = cevalInteractiveFunctions(cache, env, e, st, msg, numIter+1); then - DAE.RCONST(r); - - case (Absyn.INTEGER(i), DAE.T_INTEGER()) then DAE.ICONST(i); - case (Absyn.REAL(str), DAE.T_REAL()) equation r = System.stringReal(str); then DAE.RCONST(r); - case (Absyn.INTEGER(i), DAE.T_REAL()) equation r = intReal(i); then DAE.RCONST(r); - - else + (cache,value,SOME(st)); + case (cache,env,e,impl,stOpt,msg,_) equation - str = "CevalScript.getConst: experiment annotation contains unsupported expression: " + Dump.printExpStr(inAbsynExp) + " of type " + Types.unparseType(inExpType) + "\n"; - Error.addCompilerError(str); + (cache,value,stOpt) = Ceval.ceval(cache,env,e,impl,stOpt,msg,numIter+1); then - fail(); + (cache,value,stOpt); end matchcontinue; -end getConst; - -protected function populateSimulationOptions -"@auhtor: adrpo - populate simulation options" - input GlobalScript.SimulationOptions inSimOpt; - input list inExperimentSettings; - output GlobalScript.SimulationOptions outSimOpt; -algorithm - outSimOpt := matchcontinue(inSimOpt, inExperimentSettings) - local - Absyn.Exp exp; - list rest; - GlobalScript.SimulationOptions simOpt; - DAE.Exp startTime; - DAE.Exp stopTime; - DAE.Exp numberOfIntervals; - DAE.Exp stepSize; - DAE.Exp tolerance; - DAE.Exp method; - DAE.Exp fileNamePrefix; - DAE.Exp options; - DAE.Exp outputFormat; - DAE.Exp variableFilter, cflags, simflags; - Real rStepSize, rStopTime, rStartTime; - Integer iNumberOfIntervals; - String name,msg; - - case (_, {}) then inSimOpt; - - case (GlobalScript.SIMULATION_OPTIONS(startTime, stopTime, numberOfIntervals, stepSize, tolerance, method, fileNamePrefix, options, outputFormat, variableFilter, cflags, simflags), - Absyn.NAMEDARG(argName = "Tolerance", argValue = exp)::rest) - equation - tolerance = getConst(exp, DAE.T_REAL_DEFAULT); - simOpt = populateSimulationOptions( - GlobalScript.SIMULATION_OPTIONS(startTime,stopTime,numberOfIntervals,stepSize,tolerance,method, - fileNamePrefix,options,outputFormat,variableFilter,cflags,simflags), - rest); - then - simOpt; - - case (GlobalScript.SIMULATION_OPTIONS(startTime, stopTime, numberOfIntervals, stepSize, tolerance, method, fileNamePrefix, options, outputFormat, variableFilter, cflags, simflags), - Absyn.NAMEDARG(argName = "StartTime", argValue = exp)::rest) - equation - startTime = getConst(exp, DAE.T_REAL_DEFAULT); - simOpt = populateSimulationOptions( - GlobalScript.SIMULATION_OPTIONS(startTime,stopTime,numberOfIntervals,stepSize,tolerance,method, - fileNamePrefix,options,outputFormat,variableFilter,cflags,simflags), - rest); - then - simOpt; - - case (GlobalScript.SIMULATION_OPTIONS(startTime, stopTime, numberOfIntervals, stepSize, tolerance, method, fileNamePrefix, options, outputFormat, variableFilter, cflags, simflags), - Absyn.NAMEDARG(argName = "StopTime", argValue = exp)::rest) - equation - stopTime = getConst(exp, DAE.T_REAL_DEFAULT); - simOpt = populateSimulationOptions( - GlobalScript.SIMULATION_OPTIONS(startTime,stopTime,numberOfIntervals,stepSize,tolerance,method, - fileNamePrefix,options,outputFormat,variableFilter,cflags,simflags), - rest); - then - simOpt; +end ceval; - case (GlobalScript.SIMULATION_OPTIONS(startTime, stopTime, numberOfIntervals, stepSize, tolerance, method, fileNamePrefix, options, outputFormat, variableFilter, cflags, simflags), - Absyn.NAMEDARG(argName = "NumberOfIntervals", argValue = exp)::rest) - equation - numberOfIntervals = getConst(exp, DAE.T_INTEGER_DEFAULT); - simOpt = populateSimulationOptions( - GlobalScript.SIMULATION_OPTIONS(startTime,stopTime,numberOfIntervals,stepSize,tolerance,method, - fileNamePrefix,options,outputFormat,variableFilter,cflags,simflags), - rest); - then - simOpt; +public 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 FCore.Cache inCache; + input FCore.Graph inEnv; + input Absyn.Path inFuncPath; + output Boolean isComplete; +algorithm + isComplete := matchcontinue(inCache, inEnv, inFuncPath) + local + FCore.Cache cache; + FCore.Graph env; + Absyn.Path fpath; - case (GlobalScript.SIMULATION_OPTIONS(startTime, stopTime, numberOfIntervals, stepSize, tolerance, method, fileNamePrefix, options, outputFormat, variableFilter, cflags, simflags), - Absyn.NAMEDARG(argName = "Interval", argValue = exp)::rest) - equation - DAE.RCONST(rStepSize) = getConst(exp, DAE.T_REAL_DEFAULT); - // a bit different for Interval, handle it LAST!!!! - GlobalScript.SIMULATION_OPTIONS(startTime,stopTime,numberOfIntervals,stepSize,tolerance,method, - fileNamePrefix,options,outputFormat,variableFilter,cflags,simflags) = - populateSimulationOptions(inSimOpt, rest); + // external functions are complete :) + case (cache, env, fpath) + equation + (_, SCode.CLASS(classDef = SCode.PARTS(externalDecl = SOME(_))), _) = Lookup.lookupClass(cache, env, fpath, false); + then + true; - DAE.RCONST(rStartTime) = startTime; - DAE.RCONST(rStopTime) = stopTime; - iNumberOfIntervals = realInt(realDiv(realSub(rStopTime, rStartTime), rStepSize)); + // if is partial instantiation no function evaluation/generation + case (_, _, _) + equation + true = System.getPartialInstantiation(); + then + false; - numberOfIntervals = DAE.ICONST(iNumberOfIntervals); - stepSize = DAE.RCONST(rStepSize); + // partial functions are not complete! + case (cache, env, fpath) + equation + (_, SCode.CLASS(partialPrefix = SCode.PARTIAL()), _) = Lookup.lookupClass(cache, env, fpath, false); + then + false; - simOpt = GlobalScript.SIMULATION_OPTIONS(startTime,stopTime,numberOfIntervals,stepSize,tolerance,method, - fileNamePrefix,options,outputFormat,variableFilter,cflags,simflags); - then - simOpt; + else true; - case (_,Absyn.NAMEDARG(argName = name, argValue = exp)::rest) - equation - msg = "Ignoring unknown experiment annotation option: " + name + " = " + Dump.printExpStr(exp); - Error.addCompilerWarning(msg); - simOpt = populateSimulationOptions(inSimOpt, rest); - then - simOpt; end matchcontinue; -end populateSimulationOptions; +end isCompleteFunction; -protected function simOptionsAsString -"@author: adrpo - Gets the simulation options as string" - input list vals; - output String str; +public function compileModel "Compiles a model given a file-prefix, helper function to buildModel." + input String fileprefix; + input list libs; +protected + String omhome = Settings.getInstallationDirectoryPath(),omhome_1 = System.stringReplace(omhome, "\"", ""); + String pd = System.pathDelimiter(); + String libsfilename,libs_str,s_call,filename,winCompileMode; + String fileDLL = fileprefix + System.getDllExt(),fileEXE = fileprefix + System.getExeExt(),fileLOG = fileprefix + ".log"; + Integer numParallel,res; + Boolean isWindows = System.os() == "Windows_NT"; algorithm - str := matchcontinue vals - local - list simOptsValues; - list lst; + libsfilename := fileprefix + ".libs"; + libs_str := stringDelimitList(libs, " "); - case _::lst - equation - // build a list with the values - simOptsValues = List.map(lst, ValuesUtil.valString); - // trim " from strings! - simOptsValues = List.map2(simOptsValues, System.stringReplace, "\"", "\'"); + System.writeFile(libsfilename, libs_str); + if isWindows then + // We only need to set OPENMODELICAHOME on Windows, and set doesn't work in bash shells anyway + // adrpo: 2010-10-05: + // whatever you do, DO NOT add a space before the && otherwise + // OPENMODELICAHOME that we set will contain a SPACE at the end! + // set OPENMODELICAHOME=DIR && actually adds the space between the DIR and && + // to the environment variable! Don't ask me why, ask Microsoft. + omhome := "set OPENMODELICAHOME=\"" + System.stringReplace(omhome_1, "/", "\\") + "\"&& "; + winCompileMode := if Config.getRunningTestsuite() then "serial" else "parallel"; + s_call := stringAppendList({omhome,"\"",omhome_1,pd,"share",pd,"omc",pd,"scripts",pd,"Compile","\""," ",fileprefix," ",Config.simulationCodeTarget()," ", winCompileMode}); + else + numParallel := if Config.getRunningTestsuite() then 1 else Config.noProc(); + s_call := stringAppendList({System.getMakeCommand()," -j",intString(numParallel)," -f ",fileprefix,".makefile"}); + end if; + if Flags.isSet(Flags.DYN_LOAD) then + Debug.traceln("compileModel: running " + s_call); + end if; - str = Util.buildMapStr(simulationOptionsNames, simOptsValues, " = ", ", "); - then - str; + // remove .exe .dll .log! + if System.regularFileExists(fileEXE) then + 0 := System.removeFile(fileEXE); + end if; + if System.regularFileExists(fileDLL) then + 0 := System.removeFile(fileDLL); + end if; + if System.regularFileExists(fileLOG) then + 0 := System.removeFile(fileLOG); + end if; - // on failure - case (_::lst) - equation - // build a list with the values - simOptsValues = List.map(lst, ValuesUtil.valString); - // trim " from strings! - simOptsValues = List.map2(simOptsValues, System.stringReplace, "\"", "\'"); + if Config.getRunningTestsuite() then + System.appendFile(Config.getRunningTestsuiteFile(), + fileEXE + "\n" + fileDLL + "\n" + fileLOG + "\n" + fileprefix + ".o\n" + fileprefix + ".libs\n" + + fileprefix + "_records.o\n" + fileprefix + "_res.mat\n"); + end if; - str = stringDelimitList(simOptsValues, ", "); - then - str; - end matchcontinue; -end simOptionsAsString; + // call the system command to compile the model! + if System.systemCall(s_call,if isWindows then "" else fileLOG) <> 0 then + // We failed, print error + if System.regularFileExists(fileLOG) then + Error.addMessage(Error.SIMULATOR_BUILD_ERROR, {System.readFile(fileLOG)}); + elseif isWindows then + // Check that it is a correct OPENMODELICAHOME, on Windows only + s_call := stringAppendList({omhome_1,pd,"share",pd,"omc",pd,"scripts",pd,"Compile.bat"}); + if not System.regularFileExists(s_call) then + Error.addMessage(Error.SIMULATOR_BUILD_ERROR, {stringAppendList({"command ",s_call," not found. Check $OPENMODELICAHOME"})}); + end if; + end if; + if Flags.isSet(Flags.DYN_LOAD) then + Debug.trace("compileModel: failed!\n"); + end if; + fail(); + end if; + + if Flags.isSet(Flags.DYN_LOAD) then + Debug.trace("compileModel: successful!\n"); + end if; +end compileModel; protected function loadFile "load the file or the directory structure if the file is named package.mo" input String name; @@ -880,9 +494,6 @@ public function cevalInteractiveFunctions2 output FCore.Cache outCache; output Values.Value outValue; output GlobalScript.SymbolTable outInteractiveSymbolTable; -protected - import LexerModelicaDiff.{Token,TokenId,tokenContent,scanString,filterModelicaDiff,modelicaDiffTokenEq}; - import DiffAlgorithm.{Diff,diff,printActual,printDiffTerminalColor,printDiffXml}; algorithm (outCache,outValue,outInteractiveSymbolTable) := matchcontinue (inCache,inEnv,inFunctionName,inVals,inSt,msg) local @@ -914,21 +525,11 @@ algorithm Absyn.ClassDef cdef; Absyn.Exp aexp; DAE.DAElist dae; - BackendDAE.BackendDAE daelow,optdae; - BackendDAE.Variables vars; - BackendDAE.EquationArray eqnarr; array> m,mt; - Option>> jac; Values.Value ret_val,simValue,value,v,cvar,cvar2,v1,v2,v3; Absyn.ComponentRef cr,cr_1; Integer size,resI,i,i1,i2,i3,n,curveStyle,numberOfIntervals, status; - Option fmiContext, fmiInstance, fmiModelVariablesInstance; /* void* implementation: DO NOT UNBOX THE POINTER AS THAT MIGHT CHANGE IT. Just treat this as an opaque type. */ - Integer fmiLogLevel; list is; - list fmiTypeDefinitionsList; - list fmiModelVariablesList; - FMI.ExperimentAnnotation fmiExperimentAnnotation; - FMI.Info fmiInfo; list vars_1,args,strings,strs,strs1,strs2,visvars,postOptModStrings,postOptModStringsOrg,mps,files,dirs; Real timeTotal,timeSimulation,timeStamp,val,x1,x2,y1,y2,r,r1,r2,linearizeTime,curveWidth,offset,offset1,offset2,scaleFactor,scaleFactor1,scaleFactor2; GlobalScript.Statements istmts; @@ -946,8 +547,6 @@ algorithm list nargs; list classes; Absyn.Within within_; - BackendDAE.EqSystem syst; - BackendDAE.Shared shared; GlobalScript.SimulationOptions defaulSimOpt; SimCode.SimulationSettings simSettings; Boolean dumpExtractionSteps, requireExactVersion; @@ -959,7 +558,6 @@ algorithm HashSetString.HashSet hashSetString; list blst; list messages; - UnitAbsyn.Unit u1,u2; Real stoptime,starttime,tol,stepsize,interval; String stoptime_str,stepsize_str,starttime_str,tol_str,num_intervalls_str,description,prefix; list interfaceType; @@ -967,8 +565,6 @@ algorithm SCode.Encapsulated encflag; SCode.Restriction restr; list> valsLst; - list tokens1, tokens2; - list>> diffs; case (cache,_,"parseString",{Values.STRING(str1),Values.STRING(str2)},st,_) equation Absyn.PROGRAM(classes=classes,within_=within_) = Parser.parsestring(str1,str2); @@ -1018,123 +614,29 @@ algorithm then (cache,Values.BOOL(b),st); - case (cache,_,"setClassComment",{Values.CODE(Absyn.C_TYPENAME(path)),Values.STRING(str)},st as GlobalScript.SYMBOLTABLE(ast=p),_) + case (cache,_,"basename",{Values.STRING(str)},st,_) equation - (p,b) = Interactive.setClassComment(path, str, p); - st = GlobalScriptUtil.setSymbolTableAST(st, p); - then - (cache,Values.BOOL(b),st); + str = System.basename(str); + then (cache,Values.STRING(str),st); - case (cache, _, "isShortDefinition", {Values.CODE(Absyn.C_TYPENAME(path))}, st as GlobalScript.SYMBOLTABLE(ast = p), _) + case (cache,_,"dirname",{Values.STRING(str)},st,_) equation - b = isShortDefinition(path, p); - then - (cache,Values.BOOL(b),st); + str = System.dirname(str); + then (cache,Values.STRING(str),st); - case (cache,_,"getClassNames",{Values.CODE(Absyn.C_TYPENAME(Absyn.IDENT("AllLoadedClasses"))),Values.BOOL(false),_,Values.BOOL(sort),Values.BOOL(builtin),Values.BOOL(_)},st as GlobalScript.SYMBOLTABLE(ast = p),_) + case (cache,_,"codeToString",{Values.CODE(codeNode)},st,_) equation - (ip,_) = Builtin.getInitialFunctions(); - p = if builtin then Interactive.updateProgram(p,ip) else p; - paths = Interactive.getTopClassnames(p); - paths = if sort then List.sort(paths, Absyn.pathGe) else paths; - vals = List.map(paths,ValuesUtil.makeCodeTypeName); + str = Dump.printCodeStr(codeNode); + then (cache,Values.STRING(str),st); + + case (cache,_,"typeOf",{Values.CODE(Absyn.C_VARIABLENAME(Absyn.CREF_IDENT(name = varid)))},(st as GlobalScript.SYMBOLTABLE(lstVarVal = iv)),_) + equation + tp = Interactive.getTypeOfVariable(varid, iv); + str = Types.unparseType(tp); then - (cache,ValuesUtil.makeArray(vals),st); + (cache,Values.STRING(str),st); - case (cache,_,"getClassNames",{Values.CODE(Absyn.C_TYPENAME(path)),Values.BOOL(false),Values.BOOL(b),Values.BOOL(sort),Values.BOOL(builtin),Values.BOOL(showProtected)},st as GlobalScript.SYMBOLTABLE(ast = p),_) - equation - (ip,_) = Builtin.getInitialFunctions(); - p = if builtin then Interactive.updateProgram(p,ip) else p; - paths = Interactive.getClassnamesInPath(path, p, showProtected); - paths = if b then List.map1r(paths,Absyn.joinPaths,path) else paths; - paths = if sort then List.sort(paths, Absyn.pathGe) else paths; - vals = List.map(paths,ValuesUtil.makeCodeTypeName); - then - (cache,ValuesUtil.makeArray(vals),st); - - case (cache,_,"getClassNames",{Values.CODE(Absyn.C_TYPENAME(Absyn.IDENT("AllLoadedClasses"))),Values.BOOL(true),_,Values.BOOL(sort),Values.BOOL(builtin),Values.BOOL(showProtected)},st as GlobalScript.SYMBOLTABLE(ast = p),_) - equation - (ip,_) = Builtin.getInitialFunctions(); - p = if builtin then Interactive.updateProgram(p,ip) else p; - (_,paths) = Interactive.getClassNamesRecursive(NONE(),p,showProtected,{}); - paths = listReverse(paths); - paths = if sort then List.sort(paths, Absyn.pathGe) else paths; - vals = List.map(paths,ValuesUtil.makeCodeTypeName); - then - (cache,ValuesUtil.makeArray(vals),st); - - case (cache,_,"getClassNames",{Values.CODE(Absyn.C_TYPENAME(path)),Values.BOOL(true),_,Values.BOOL(sort),Values.BOOL(builtin),Values.BOOL(showProtected)},st as GlobalScript.SYMBOLTABLE(ast = p),_) - equation - (ip,_) = Builtin.getInitialFunctions(); - p = if builtin then Interactive.updateProgram(p,ip) else p; - (_,paths) = Interactive.getClassNamesRecursive(SOME(path),p,showProtected,{}); - paths = listReverse(paths); - paths = if sort then List.sort(paths, Absyn.pathGe) else paths; - vals = List.map(paths,ValuesUtil.makeCodeTypeName); - then - (cache,ValuesUtil.makeArray(vals),st); - - case (cache,_,"getUsedClassNames",{Values.CODE(Absyn.C_TYPENAME(path))},st as GlobalScript.SYMBOLTABLE(),_) - equation - (sp, st) = GlobalScriptUtil.symbolTableToSCode(st); - (sp, _) = NFSCodeFlatten.flattenClassInProgram(path, sp); - sp = SCode.removeBuiltinsFromTopScope(sp); - paths = Interactive.getSCodeClassNamesRecursive(sp); - // paths = bcallret2(sort, List.sort, paths, Absyn.pathGe, paths); - vals = List.map(paths,ValuesUtil.makeCodeTypeName); - then (cache,ValuesUtil.makeArray(vals),st); - - case (cache,_,"getUsedClassNames",_,st as GlobalScript.SYMBOLTABLE(),_) - then (cache,ValuesUtil.makeArray({}),st); - - case (cache,_,"getClassComment",{Values.CODE(Absyn.C_TYPENAME(path))},st as GlobalScript.SYMBOLTABLE(ast = p),_) - equation - Absyn.CLASS(_,_,_,_,_,cdef,_) = Interactive.getPathedClassInProgram(path, p); - str = System.unescapedString(getClassComment(cdef)); - then - (cache,Values.STRING(str),st); - - case (cache,_,"getClassComment",{Values.CODE(Absyn.C_TYPENAME(_))},st as GlobalScript.SYMBOLTABLE(),_) - then - (cache,Values.STRING(""),st); - - case (cache,_,"getPackages",{Values.CODE(Absyn.C_TYPENAME(Absyn.IDENT("AllLoadedClasses")))},st as GlobalScript.SYMBOLTABLE(ast = p),_) - equation - paths = Interactive.getTopPackages(p); - vals = List.map(paths,ValuesUtil.makeCodeTypeName); - then - (cache,ValuesUtil.makeArray(vals),st); - - case (cache,_,"getPackages",{Values.CODE(Absyn.C_TYPENAME(path))},st as GlobalScript.SYMBOLTABLE(ast = p),_) - equation - paths = Interactive.getPackagesInPath(path, p); - vals = List.map(paths,ValuesUtil.makeCodeTypeName); - then - (cache,ValuesUtil.makeArray(vals),st); - - case (cache,_,"basename",{Values.STRING(str)},st,_) - equation - str = System.basename(str); - then (cache,Values.STRING(str),st); - - case (cache,_,"dirname",{Values.STRING(str)},st,_) - equation - str = System.dirname(str); - then (cache,Values.STRING(str),st); - - case (cache,_,"codeToString",{Values.CODE(codeNode)},st,_) - equation - str = Dump.printCodeStr(codeNode); - then (cache,Values.STRING(str),st); - - case (cache,_,"typeOf",{Values.CODE(Absyn.C_VARIABLENAME(Absyn.CREF_IDENT(name = varid)))},(st as GlobalScript.SYMBOLTABLE(lstVarVal = iv)),_) - equation - tp = Interactive.getTypeOfVariable(varid, iv); - str = Types.unparseType(tp); - then - (cache,Values.STRING(str),st); - - case (cache,_,"GC_gcollect_and_unmap",{},st,_) + case (cache,_,"GC_gcollect_and_unmap",{},st,_) equation GC.gcollectAndUnmap(); then (cache,Values.BOOL(true),st); @@ -1180,32 +682,6 @@ algorithm then (cache,Values.BOOL(true),newst); - case (cache,_,"convertUnits",{Values.STRING(str1),Values.STRING(str2)},st,_) - equation - UnitParserExt.initSIUnits(); - (u1,scaleFactor1,offset1) = UnitAbsynBuilder.str2unitWithScaleFactor(str1,NONE()); - (u2,scaleFactor2,offset2) = UnitAbsynBuilder.str2unitWithScaleFactor(str2,NONE()); - b = valueEq(u1,u2); - /* How to calculate the final scale factor and offset? - ºF = (ºK - 273.15)* 1.8000 + 32.00 = (ºK - 255.37)* 1.8000 - ºC = (ºK - 273.15) - - ºF = (ºC - (255.37 - 273.15))*(1.8/1.0) - */ - scaleFactor = realDiv(scaleFactor2, scaleFactor1); - offset = realSub(offset2,offset1); - then - (cache,Values.TUPLE({Values.BOOL(b),Values.REAL(scaleFactor),Values.REAL(offset)}),st); - - case (cache,_,"getClassInformation",{Values.CODE(Absyn.C_TYPENAME(className))},st as GlobalScript.SYMBOLTABLE(),_) - equation - v = getClassInformation(className, st.ast); - then (cache,v,st); - - case (cache,_,"getClassInformation",_,st,_) - then (cache,Values.TUPLE({Values.STRING(""),Values.STRING(""),Values.BOOL(false),Values.BOOL(false),Values.BOOL(false),Values.STRING(""), - Values.BOOL(false),Values.INTEGER(0),Values.INTEGER(0),Values.INTEGER(0),Values.INTEGER(0),Values.ARRAY({},{0})}),st); - case (cache,_,"list",{Values.CODE(Absyn.C_TYPENAME(Absyn.IDENT("AllLoadedClasses"))),Values.BOOL(false),Values.BOOL(false),Values.ENUM_LITERAL(name=path)},(st as GlobalScript.SYMBOLTABLE(ast = p)),_) equation (scodeP,st) = GlobalScriptUtil.symbolTableToSCode(st); @@ -1255,33 +731,6 @@ algorithm case (cache,_,"listFile",_,st,_) then (cache,Values.STRING(""),st); - case (cache,_,"diffModelicaFileListings",{Values.STRING(s1),Values.STRING(s2),Values.ENUM_LITERAL(name=path)},(st as GlobalScript.SYMBOLTABLE(ast = p)),_) - algorithm - tokens1 := scanString(s1); - tokens2 := scanString(s2); - diffs := diff(tokens1, tokens2, modelicaDiffTokenEq); - // print("Before filtering:\n"+printDiffTerminalColor(diffs, tokenContent)+"\n"); - diffs := filterModelicaDiff(diffs,removeWhitespace=false); - // Scan a second time, with comments filtered into place - str := printActual(diffs, tokenContent); - // print("Intermediate string:\n"+printDiffTerminalColor(diffs, tokenContent)+"\n"); - tokens2 := scanString(str); - diffs := diff(tokens1, tokens2, modelicaDiffTokenEq); - // print("Before filtering (2):\n"+printDiffTerminalColor(diffs, tokenContent)+"\n"); - diffs := filterModelicaDiff(diffs); - str := match Absyn.pathLastIdent(path) - case "plain" then printActual(diffs, tokenContent); - case "color" then printDiffTerminalColor(diffs, tokenContent); - case "xml" then printDiffXml(diffs, tokenContent); - else - algorithm - Error.addInternalError("Unknown diffModelicaFileListings choice", sourceInfo()); - then fail(); - end match; - then (cache,Values.STRING(str),st); - - case (cache,_,"diffModelicaFileListings",_,st,_) then (cache,Values.STRING(""),st); - case (cache,_,"sortStrings",{Values.ARRAY(valueLst=vals)},(st as GlobalScript.SYMBOLTABLE()),_) equation strs = List.map(vals, ValuesUtil.extractValueString); @@ -1290,153 +739,12 @@ algorithm then (cache,v,st); - - // exportToFigaro cases added by Alexander Carlqvist - case (cache, _, "exportToFigaro", {Values.CODE(Absyn.C_TYPENAME(path)), Values.STRING(s1), Values.STRING(str), Values.STRING(str1), Values.STRING(str2), Values.STRING(str3)}, st as GlobalScript.SYMBOLTABLE(ast = p), _) - equation - (scodeP, _) = GlobalScriptUtil.symbolTableToSCode(st); - /* The following line of code should be commented out when building from trunk. - Uncomment when bootstrapping. */ - Figaro.run(scodeP, path, s1, str, str1, str2, str3); - then (cache, Values.BOOL(true), st); - - case (cache, _, "exportToFigaro", _, st, _) - then (cache, Values.BOOL(false), st); - - case (_,_, "rewriteBlockCall",{Values.CODE(Absyn.C_TYPENAME(classpath)), Values.CODE(Absyn.C_TYPENAME(path))}, - (st as GlobalScript.SYMBOLTABLE(p as Absyn.PROGRAM())),_) - equation - absynClass = Interactive.getPathedClassInProgram(path, p); - classes = {absynClass}; - absynClass = Interactive.getPathedClassInProgram(classpath, p); - within_ = Interactive.buildWithin(classpath); - pnew = BlockCallRewrite.rewriteBlockCall(Absyn.PROGRAM({absynClass}, within_), Absyn.PROGRAM(classes, within_)); - pnew = Interactive.updateProgram(pnew, p); - newst = GlobalScriptUtil.setSymbolTableAST(st, pnew); - then - (FCore.emptyCache(),Values.BOOL(true), newst); - - case (cache, _, "rewriteBlockCall", _, st, _) - then (cache, Values.BOOL(false), st); - case (cache,_,"listVariables",{},st as GlobalScript.SYMBOLTABLE(lstVarVal = iv),_) equation v = ValuesUtil.makeArray(getVariableNames(iv,{})); then (cache,v,st); - - case (cache,env,"jacobian",{Values.CODE(Absyn.C_TYPENAME(path))}, - (GlobalScript.SYMBOLTABLE( - ast = p,explodedAst = fp,instClsLst = ic, - lstVarVal = iv,compiledFunctions = cf, - loadedFiles = lf)),_) - equation - scodeP = SCodeUtil.translateAbsyn2SCode(p); - (cache, env, _, dae) = Inst.instantiateClass(cache, InnerOuter.emptyInstHierarchy, scodeP, path); - dae = DAEUtil.transformationsBeforeBackend(cache,env,dae); - ic_1 = Interactive.addInstantiatedClass(ic, GlobalScript.INSTCLASS(path,dae,env)); - filenameprefix = Absyn.pathString(path); - description = DAEUtil.daeDescription(dae); - daelow = BackendDAECreate.lower(dae,cache,env,BackendDAE.EXTRA_INFO(description,filenameprefix)); - (BackendDAE.DAE({syst},shared)) = BackendDAEUtil.preOptimizeBackendDAE(daelow,NONE()); - (syst,m,_) = BackendDAEUtil.getIncidenceMatrixfromOption(syst,BackendDAE.NORMAL(),NONE()); - vars = BackendVariable.daeVars(syst); - eqnarr = BackendEquation.getEqnsFromEqSystem(syst); - (jac, _) = SymbolicJacobian.calculateJacobian(vars, eqnarr, m, false,shared); - res = BackendDump.dumpJacobianStr(jac); - then - (cache,Values.STRING(res),GlobalScript.SYMBOLTABLE(p,fp,ic_1,iv,cf,lf)); - - case (cache,env,"translateModel",vals as {Values.CODE(Absyn.C_TYPENAME(className)),_,_,_,_,_,Values.STRING(filenameprefix),_,_,_,_,_},st,_) - equation - (cache,simSettings) = calculateSimulationSettings(cache,env,vals,st,msg); - (cache,st_1,_,_,_,_) = translateModel(cache, env, className, st, filenameprefix, true, SOME(simSettings)); - then - (cache,Values.BOOL(true),st_1); - - case (cache,_,"translateModel",_,st,_) - then (cache,Values.BOOL(false),st); - - case (cache,env,"modelEquationsUC",{Values.CODE(Absyn.C_TYPENAME(className)),Values.STRING(outputFile),Values.BOOL(dumpExtractionSteps)},st,_) - equation - (cache,ret_val,st_1) = Uncertainties.modelEquationsUC(cache, env, className, st, outputFile,dumpExtractionSteps); - then - (cache,ret_val,st_1); - - case (cache,_,"modelEquationsUC",_,st,_) - then (cache,Values.STRING("There were errors during extraction of uncertainty equations. Use getErrorString() to see them."),st); - - /*case (cache,env,"translateModelCPP",{Values.CODE(Absyn.C_TYPENAME(className)),Values.STRING(filenameprefix)},st,msg) - equation - (cache,ret_val,st_1,_,_,_,_) = translateModelCPP(cache,env, className, st, filenameprefix,true,NONE()); - then - (cache,ret_val,st_1);*/ - - 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 == "" 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, str2, filenameprefix, true, SOME(simSettings)); - then - (cache,ret_val,st_1); - - 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); - - case (cache,env,"translateModelXML",{Values.CODE(Absyn.C_TYPENAME(className)),Values.STRING(filenameprefix)},st,_) - equation - filenameprefix = Util.stringReplaceChar(filenameprefix,".","_"); - (cache,ret_val,st_1) = translateModelXML(cache, env, className, st, filenameprefix, true, NONE()); - then - (cache,ret_val,st_1); - - case (cache,env,"exportDAEtoMatlab",{Values.CODE(Absyn.C_TYPENAME(className)),Values.STRING(filenameprefix)},st,_) - equation - (cache,ret_val,st_1,_) = getIncidenceMatrix(cache,env, className, st, msg, filenameprefix); - then - (cache,ret_val,st_1); - - case (cache,env,"checkModel",{Values.CODE(Absyn.C_TYPENAME(className))},st,_) - equation - Flags.setConfigBool(Flags.CHECK_MODEL, true); - (cache,ret_val,st_1) = checkModel(cache, env, className, st, msg); - Flags.setConfigBool(Flags.CHECK_MODEL, false); - then - (cache,ret_val,st_1); - - case (cache,env,"checkAllModelsRecursive",{Values.CODE(Absyn.C_TYPENAME(className)),Values.BOOL(showProtected)},st,_) - equation - (cache,ret_val,st_1) = checkAllModelsRecursive(cache, env, className, showProtected, st, msg); - then - (cache,ret_val,st_1); - - case (cache,env,"translateGraphics",{Values.CODE(Absyn.C_TYPENAME(className))},st,_) - equation - (cache,ret_val,st_1) = translateGraphics(cache,env, className, st, msg); - then - (cache,ret_val,st_1); - case (cache,_,"setCompileCommand",{Values.STRING(cmd)},st,_) equation // cmd = Util.rawStringToInputString(cmd); @@ -1450,10 +758,6 @@ algorithm then (cache,Values.STRING(res),st); - case (cache,_,"setPlotCommand",{Values.STRING(_)},st,_) - then - (cache,Values.BOOL(false),st); - case (cache,_,"setTempDirectoryPath",{Values.STRING(cmd)},st,_) equation // cmd = Util.rawStringToInputString(cmd); @@ -1509,349 +813,18 @@ algorithm then (cache,Values.BOOL(false),st); - case (cache,_,"getAnnotationVersion",{},st,_) - equation - res = Config.getAnnotationVersion(); - then - (cache,Values.STRING(res),st); - - case (cache,_,"getNoSimplify",{},st,_) - equation - b = Config.getNoSimplify(); - then - (cache,Values.BOOL(b),st); - - case (cache,_,"setNoSimplify",{Values.BOOL(b)},st,_) - equation - Config.setNoSimplify(b); - then - (cache,Values.BOOL(true),st); - - case (cache,_,"getShowAnnotations",{},st,_) - equation - b = Config.showAnnotations(); - then - (cache,Values.BOOL(b),st); - - case (cache,_,"setShowAnnotations",{Values.BOOL(b)},st,_) - equation - Config.setShowAnnotations(b); - then - (cache,Values.BOOL(true),st); - - case (cache,_,"getVectorizationLimit",{},st,_) - equation - i = Config.vectorizationLimit(); - then - (cache,Values.INTEGER(i),st); - - case (cache,_,"getOrderConnections",{},st,_) - equation - b = Config.orderConnections(); - then - (cache,Values.BOOL(b),st); - case (cache,_,"getLanguageStandard",{},st,_) equation res = Config.languageStandardString(Config.getLanguageStandard()); then (cache,Values.STRING(res),st); - case (cache,env,"buildModel",vals,st,_) - equation - List.map_0(ClockIndexes.buildModelClocks,System.realtimeClear); - System.realtimeTick(ClockIndexes.RT_CLOCK_SIMULATE_TOTAL); - (cache,st,compileDir,executable,_,_,initfilename,_,_) = buildModel(cache,env, vals, st, msg); - executable = if not Config.getRunningTestsuite() then compileDir + executable else executable; - then - (cache,ValuesUtil.makeArray({Values.STRING(executable),Values.STRING(initfilename)}),st); - - case(cache,env,"buildOpenTURNSInterface",vals,st,_) - equation - (cache,scriptFile,st) = buildOpenTURNSInterface(cache,env,vals,st,msg); - then - (cache,Values.STRING(scriptFile),st); - case(_,_,"buildOpenTURNSInterface",_,_,_) - equation - Error.addMessage(Error.INTERNAL_ERROR,{"buildOpenTURNSInterface failed. Use getErrorString() to see why."}); - then - fail(); - - case(cache,env,"runOpenTURNSPythonScript",vals,st,_) - equation - (cache,logFile,st) = runOpenTURNSPythonScript(cache,env,vals,st,msg); - then - (cache,Values.STRING(logFile),st); - case(_,_,"runOpenTURNSPythonScript",_,_,_) - equation - Error.addMessage(Error.INTERNAL_ERROR,{"runOpenTURNSPythonScript failed. Use getErrorString() to see why"}); - then - fail(); - - case (cache,_,"buildModel",_,st,_) /* failing build_model */ - then (cache,ValuesUtil.makeArray({Values.STRING(""),Values.STRING("")}),st); - - case (cache,env,"buildModelBeast",vals,st,_) - equation - (cache,st,compileDir,executable,_,initfilename) = buildModelBeast(cache,env,vals,st,msg); - executable = if not Config.getRunningTestsuite() then compileDir + executable else executable; - then - (cache,ValuesUtil.makeArray({Values.STRING(executable),Values.STRING(initfilename)}),st); - - // adrpo: see if the model exists before simulation! - case (cache,_,"simulate",vals as Values.CODE(Absyn.C_TYPENAME(className))::_,st as GlobalScript.SYMBOLTABLE(ast = p),_) - equation - crefCName = Absyn.pathToCref(className); - false = Interactive.existClass(crefCName, p); - errMsg = "Simulation Failed. Model: " + Absyn.pathString(className) + " does not exist! Please load it first before simulation."; - simValue = createSimulationResultFailure(errMsg, simOptionsAsString(vals)); - then - (cache,simValue,st); - - case (cache,env,"simulate",vals as Values.CODE(Absyn.C_TYPENAME(className))::_,st_1,_) - equation - System.realtimeTick(ClockIndexes.RT_CLOCK_SIMULATE_TOTAL); - (cache,st,compileDir,executable,_,outputFormat_str,_,simflags,resultValues) = buildModel(cache,env,vals,st_1,msg); - - exeDir=compileDir; - (cache,simSettings) = calculateSimulationSettings(cache,env,vals,st_1,msg); - SimCode.SIMULATION_SETTINGS(outputFormat = outputFormat_str) - = simSettings; - result_file = stringAppendList(List.consOnTrue(not Config.getRunningTestsuite(),compileDir,{executable,"_res.",outputFormat_str})); - executableSuffixedExe = stringAppend(executable, getSimulationExtension(Config.simCodeTarget(),System.platform())); - logFile = stringAppend(executable,".log"); - // adrpo: log file is deleted by buildModel! do NOT DELETE IT AGAIN! - // we should really have different log files for simulation/compilation! - // as the buildModel log file will be deleted here and that gives less information to the user! - if System.regularFileExists(logFile) then - 0 = System.removeFile(logFile); - end if; - sim_call = stringAppendList({"\"",exeDir,executableSuffixedExe,"\""," ",simflags}); - System.realtimeTick(ClockIndexes.RT_CLOCK_SIMULATE_SIMULATION); - SimulationResults.close() "Windows cannot handle reading and writing to the same file from different processes like any real OS :("; - resI = System.systemCall(sim_call,logFile); - timeSimulation = System.realtimeTock(ClockIndexes.RT_CLOCK_SIMULATE_SIMULATION); - timeTotal = System.realtimeTock(ClockIndexes.RT_CLOCK_SIMULATE_TOTAL); - (cache,simValue,newst) = createSimulationResultFromcallModelExecutable(resI,timeTotal,timeSimulation,resultValues,cache,className,vals,st,result_file,logFile); - then - (cache,simValue,newst); - - case (cache,_,"simulate",vals as Values.CODE(Absyn.C_TYPENAME(className))::_,st,_) - equation - _ = Settings.getInstallationDirectoryPath() "simulation fail for some other reason than OPENMODELICAHOME not being set." ; - str = Absyn.pathString(className); - res = "Failed to build model: " + str; - simValue = createSimulationResultFailure(res, simOptionsAsString(vals)); - then - (cache,simValue,st); - - case (cache,_,"simulate",vals as Values.CODE(Absyn.C_TYPENAME(className))::_,st,_) - equation - str = Absyn.pathString(className); - simValue = createSimulationResultFailure( - "Simulation failed for model: " + str + - "\nEnvironment variable OPENMODELICAHOME not set.", - simOptionsAsString(vals)); - then - (cache,simValue,st); - - // adrpo: see if the model exists before moving! - case (cache,_,"moveClass",{Values.CODE(Absyn.C_TYPENAME(className)), - Values.STRING(_)}, - st as GlobalScript.SYMBOLTABLE(ast = p),_) - equation - crefCName = Absyn.pathToCref(className); - false = Interactive.existClass(crefCName, p); - simValue = Values.BOOL(false); - then - (cache,simValue,st); - - // everything should work fine here - case (cache,_,"moveClass",{Values.CODE(Absyn.C_TYPENAME(className)), - Values.STRING(direction)}, - st as GlobalScript.SYMBOLTABLE(ast = p),_) - equation - crefCName = Absyn.pathToCref(className); - true = Interactive.existClass(crefCName, p); - p = moveClass(className, direction, p); - st = GlobalScriptUtil.setSymbolTableAST(st, p); - simValue = Values.BOOL(true); - then - (cache,simValue,st); - - // adrpo: some error happened! - case (cache,_,"moveClass",{Values.CODE(Absyn.C_TYPENAME(className)), - Values.STRING(_)}, - st as GlobalScript.SYMBOLTABLE(ast = p),_) - equation - crefCName = Absyn.pathToCref(className); - true = Interactive.existClass(crefCName, p); - errMsg = "moveClass Error: Could not move the model " + Absyn.pathString(className) + ". Unknown error."; - Error.addMessage(Error.INTERNAL_ERROR, {errMsg}); - simValue = Values.BOOL(false); - then - (cache,simValue,st); - - case (cache,_,"copyClass",{Values.CODE(Absyn.C_TYPENAME(classpath)), Values.STRING(name), Values.CODE(Absyn.C_TYPENAME(Absyn.IDENT("TopLevel")))}, - st as GlobalScript.SYMBOLTABLE(ast = p),_) - equation - absynClass = Interactive.getPathedClassInProgram(classpath, p); - p = copyClass(absynClass, name, Absyn.TOP(), p); - st = GlobalScriptUtil.setSymbolTableAST(st, p); - ret_val = Values.BOOL(true); - then - (cache,ret_val,st); - - case (cache,_,"copyClass",{Values.CODE(Absyn.C_TYPENAME(classpath)), Values.STRING(name), Values.CODE(Absyn.C_TYPENAME(path))}, - st as GlobalScript.SYMBOLTABLE(ast = p),_) - equation - absynClass = Interactive.getPathedClassInProgram(classpath, p); - p = copyClass(absynClass, name, Absyn.WITHIN(path), p); - st = GlobalScriptUtil.setSymbolTableAST(st, p); - ret_val = Values.BOOL(true); - then - (cache,ret_val,st); - - case (cache,env,"linearize",(vals as Values.CODE(Absyn.C_TYPENAME(_))::_),st_1,_) - equation - - System.realtimeTick(ClockIndexes.RT_CLOCK_SIMULATE_TOTAL); - - b = Flags.getConfigBool(Flags.GENERATE_SYMBOLIC_LINEARIZATION); - Flags.setConfigBool(Flags.GENERATE_SYMBOLIC_LINEARIZATION, true); - - (cache,st,compileDir,executable,_,outputFormat_str,_,simflags,resultValues) = buildModel(cache,env,vals,st_1,msg); - Values.REAL(linearizeTime) = getListNthShowError(vals,"try to get stop time",0,2); - executableSuffixedExe = stringAppend(executable, System.getExeExt()); - logFile = stringAppend(executable,".log"); - if System.regularFileExists(logFile) then - 0 = System.removeFile(logFile); - end if; - strlinearizeTime = realString(linearizeTime); - sim_call = stringAppendList({"\"",compileDir,executableSuffixedExe,"\""," ","-l=",strlinearizeTime," ",simflags}); - System.realtimeTick(ClockIndexes.RT_CLOCK_SIMULATE_SIMULATION); - SimulationResults.close() "Windows cannot handle reading and writing to the same file from different processes like any real OS :("; - 0 = System.systemCall(sim_call,logFile); - - result_file = stringAppendList(List.consOnTrue(not Config.getRunningTestsuite(),compileDir,{executable,"_res.",outputFormat_str})); - timeSimulation = System.realtimeTock(ClockIndexes.RT_CLOCK_SIMULATE_SIMULATION); - timeTotal = System.realtimeTock(ClockIndexes.RT_CLOCK_SIMULATE_TOTAL); - simValue = createSimulationResult( - result_file, - simOptionsAsString(vals), - System.readFile(logFile), - ("timeTotal", Values.REAL(timeTotal)) :: - ("timeSimulation", Values.REAL(timeSimulation)) :: - resultValues); - newst = GlobalScriptUtil.addVarToSymboltable( - DAE.CREF_IDENT("currentSimulationResult", DAE.T_STRING_DEFAULT, {}), - Values.STRING(result_file), FGraph.empty(), st); - //reset config flag - Flags.setConfigBool(Flags.GENERATE_SYMBOLIC_LINEARIZATION, b); - then - (cache,simValue,newst); - - case (cache,env,"optimize",(vals as Values.CODE(Absyn.C_TYPENAME(className))::_),st_1,_) - equation - - System.realtimeTick(ClockIndexes.RT_CLOCK_SIMULATE_TOTAL); - - Flags.setConfigBool(Flags.GENERATE_SYMBOLIC_LINEARIZATION,true); - Flags.setConfigEnum(Flags.GRAMMAR, Flags.OPTIMICA); - Flags.setConfigBool(Flags.GENERATE_DYN_OPTIMIZATION_PROBLEM,true); - - (cache,st,compileDir,executable,_,outputFormat_str,_,simflags,resultValues) = buildModel(cache,env,vals,st_1,msg); - exeDir=compileDir; - (cache,simSettings) = calculateSimulationSettings(cache,env,vals,st_1,msg); - SimCode.SIMULATION_SETTINGS(outputFormat = outputFormat_str) = simSettings; - result_file = stringAppendList(List.consOnTrue(not Config.getRunningTestsuite(),compileDir,{executable,"_res.",outputFormat_str})); - executableSuffixedExe = stringAppend(executable, getSimulationExtension(Config.simCodeTarget(),System.platform())); - logFile = stringAppend(executable,".log"); - // adrpo: log file is deleted by buildModel! do NOT DELTE IT AGAIN! - // we should really have different log files for simulation/compilation! - // as the buildModel log file will be deleted here and that gives less information to the user! - if System.regularFileExists(logFile) then - 0 = System.removeFile(logFile); - end if; - sim_call = stringAppendList({"\"",exeDir,executableSuffixedExe,"\""," ",simflags}); - System.realtimeTick(ClockIndexes.RT_CLOCK_SIMULATE_SIMULATION); - SimulationResults.close() "Windows cannot handle reading and writing to the same file from different processes like any real OS :("; - resI = System.systemCall(sim_call,logFile); - timeSimulation = System.realtimeTock(ClockIndexes.RT_CLOCK_SIMULATE_SIMULATION); - timeTotal = System.realtimeTock(ClockIndexes.RT_CLOCK_SIMULATE_TOTAL); - (cache,simValue,newst) = createSimulationResultFromcallModelExecutable(resI,timeTotal,timeSimulation,resultValues,cache,className,vals,st,result_file,logFile); - then - (cache,simValue,newst); - - case (cache,env,"instantiateModel",{Values.CODE(Absyn.C_TYPENAME(className))},st,_) - equation - (cache,env,dae,st) = runFrontEnd(cache,env,className,st,true); - str = DAEDump.dumpStr(dae,FCore.getFunctionTree(cache)); - then - (cache,Values.STRING(str),st); - - case (cache,_,"instantiateModel",{Values.CODE(Absyn.C_TYPENAME(path))},st as GlobalScript.SYMBOLTABLE(ast=p),_) - equation - cr_1 = Absyn.pathToCref(path); - false = Interactive.existClass(cr_1, p); - str = Absyn.pathString(path); - Error.addMessage(Error.LOOKUP_ERROR, {str,""}); - then - (cache,Values.STRING(""),st); - - case (cache,_,"instantiateModel",{Values.CODE(Absyn.C_TYPENAME(path))},st,_) - equation - b = Error.getNumMessages() == 0; - str = Absyn.pathString(path); - str = "Instantiation of " + str + " failed with no error message"; - if b then - Error.addMessage(Error.INTERNAL_ERROR, {str,""}); - end if; - then - (cache,Values.STRING(""),st); - case (cache,_,"reopenStandardStream",{Values.ENUM_LITERAL(index=i),Values.STRING(filename)},st,_) equation b = System.reopenStandardStream(i-1,filename); then (cache,Values.BOOL(b),st); - case (cache,_,"importFMU",{Values.STRING(filename),Values.STRING(workdir),Values.INTEGER(fmiLogLevel),Values.BOOL(b1), Values.BOOL(b2), Values.BOOL(inputConnectors), Values.BOOL(outputConnectors)},st,_) - equation - Error.clearMessages() "Clear messages"; - true = System.regularFileExists(filename); - workdir = if System.directoryExists(workdir) then workdir else System.pwd(); - /* Initialize FMI objects */ - (b, fmiContext, fmiInstance, fmiInfo, fmiTypeDefinitionsList, fmiExperimentAnnotation, fmiModelVariablesInstance, fmiModelVariablesList) = FMIExt.initializeFMIImport(filename, workdir, fmiLogLevel, inputConnectors, outputConnectors); - true = b; /* if something goes wrong while initializing */ - fmiTypeDefinitionsList = listReverse(fmiTypeDefinitionsList); - fmiModelVariablesList = listReverse(fmiModelVariablesList); - s1 = System.tolower(System.platform()); - str = Tpl.tplString(CodegenFMU.importFMUModelica, FMI.FMIIMPORT(s1, filename, workdir, fmiLogLevel, b2, fmiContext, fmiInstance, fmiInfo, fmiTypeDefinitionsList, fmiExperimentAnnotation, fmiModelVariablesInstance, fmiModelVariablesList, inputConnectors, outputConnectors)); - pd = System.pathDelimiter(); - str1 = FMI.getFMIModelIdentifier(fmiInfo); - str2 = FMI.getFMIType(fmiInfo); - str3 = FMI.getFMIVersion(fmiInfo); - outputFile = stringAppendList({workdir,pd,str1,"_",str2,"_FMU.mo"}); - filename_1 = if b1 then stringAppendList({workdir,pd,str1,"_",str2,"_FMU.mo"}) else stringAppendList({str1,"_",str2,"_FMU.mo"}); - System.writeFile(outputFile, str); - /* Release FMI objects */ - FMIExt.releaseFMIImport(fmiModelVariablesInstance, fmiInstance, fmiContext, str3); - then - (cache,Values.STRING(filename_1),st); - - case (cache,_,"importFMU",{Values.STRING(filename),Values.STRING(_),Values.INTEGER(_),Values.BOOL(_), Values.BOOL(_), Values.BOOL(_), Values.BOOL(_)},st,_) - equation - false = System.regularFileExists(filename); - Error.clearMessages() "Clear messages"; - Error.addMessage(Error.FILE_NOT_FOUND_ERROR, {filename}); - then - (cache,Values.STRING(""),st); - - case (cache,_,"importFMU",{Values.STRING(_),Values.STRING(_),Values.INTEGER(_),Values.BOOL(_), Values.BOOL(_), Values.BOOL(_), Values.BOOL(_)},st,_) - then - (cache,Values.STRING(""),st); - case (cache,_,"iconv",{Values.STRING(str),Values.STRING(from),Values.STRING(to)},st,_) equation str = System.iconv(str,from,to); @@ -2148,46 +1121,7 @@ algorithm then (cache,v,st); - case (cache,_,"getIndexReductionMethod",_,st,_) - equation - str = Config.getIndexReductionMethod(); - then (cache,Values.STRING(str),st); - - case (cache,_,"getAvailableIndexReductionMethods",_,st,_) - equation - (strs1,strs2) = Flags.getConfigOptionsStringList(Flags.INDEX_REDUCTION_METHOD); - v1 = ValuesUtil.makeArray(List.map(strs1, ValuesUtil.makeString)); - v2 = ValuesUtil.makeArray(List.map(strs2, ValuesUtil.makeString)); - v = Values.TUPLE({v1,v2}); - then (cache,v,st); - - case (cache,_,"getMatchingAlgorithm",_,st,_) - equation - str = Config.getMatchingAlgorithm(); - then (cache,Values.STRING(str),st); - - case (cache,_,"getAvailableMatchingAlgorithms",_,st,_) - equation - (strs1,strs2) = Flags.getConfigOptionsStringList(Flags.MATCHING_ALGORITHM); - v1 = ValuesUtil.makeArray(List.map(strs1, ValuesUtil.makeString)); - v2 = ValuesUtil.makeArray(List.map(strs2, ValuesUtil.makeString)); - v = Values.TUPLE({v1,v2}); - then (cache,v,st); - - case (cache,_,"getTearingMethod",_,st,_) - equation - str = Config.getTearingMethod(); - then (cache,Values.STRING(str),st); - - case (cache,_,"getAvailableTearingMethods",_,st,_) - equation - (strs1,strs2) = Flags.getConfigOptionsStringList(Flags.TEARING_METHOD); - v1 = ValuesUtil.makeArray(List.map(strs1, ValuesUtil.makeString)); - v2 = ValuesUtil.makeArray(List.map(strs2, ValuesUtil.makeString)); - v = Values.TUPLE({v1,v2}); - then (cache,v,st); - - case (cache,_,"stringTypeName",{Values.STRING(str)},st,_) + case (cache,_,"stringTypeName",{Values.STRING(str)},st,_) equation path = Parser.stringPath(str); then (cache,Values.CODE(Absyn.C_TYPENAME(path)),st); @@ -2259,7 +1193,7 @@ algorithm case (cache,_,"generateEntryPoint",{Values.STRING(filename),Values.CODE(Absyn.C_TYPENAME(path)),Values.STRING(str)},st as GlobalScript.SYMBOLTABLE(),_) equation - str = Tpl.tplString2(CodegenC.generateEntryPoint, path, str); + str = Tpl.tplString2(CodegenCFunctions.generateEntryPoint, path, str); System.writeFile(filename,str); then (cache,Values.BOOL(true),st); @@ -2419,6 +1353,49 @@ algorithm i = System.alarm(i); then (cache,Values.INTEGER(i),st); + case (cache,_,"getClassNames",{Values.CODE(Absyn.C_TYPENAME(Absyn.IDENT("AllLoadedClasses"))),Values.BOOL(false),_,Values.BOOL(sort),Values.BOOL(builtin),Values.BOOL(_)},st as GlobalScript.SYMBOLTABLE(ast = p),_) + equation + (ip,_) = Builtin.getInitialFunctions(); + p = if builtin then Interactive.updateProgram(p,ip) else p; + paths = Interactive.getTopClassnames(p); + paths = if sort then List.sort(paths, Absyn.pathGe) else paths; + vals = List.map(paths,ValuesUtil.makeCodeTypeName); + then + (cache,ValuesUtil.makeArray(vals),st); + + case (cache,_,"getClassNames",{Values.CODE(Absyn.C_TYPENAME(path)),Values.BOOL(false),Values.BOOL(b),Values.BOOL(sort),Values.BOOL(builtin),Values.BOOL(showProtected)},st as GlobalScript.SYMBOLTABLE(ast = p),_) + equation + (ip,_) = Builtin.getInitialFunctions(); + p = if builtin then Interactive.updateProgram(p,ip) else p; + paths = Interactive.getClassnamesInPath(path, p, showProtected); + paths = if b then List.map1r(paths,Absyn.joinPaths,path) else paths; + paths = if sort then List.sort(paths, Absyn.pathGe) else paths; + vals = List.map(paths,ValuesUtil.makeCodeTypeName); + then + (cache,ValuesUtil.makeArray(vals),st); + + case (cache,_,"getClassNames",{Values.CODE(Absyn.C_TYPENAME(Absyn.IDENT("AllLoadedClasses"))),Values.BOOL(true),_,Values.BOOL(sort),Values.BOOL(builtin),Values.BOOL(showProtected)},st as GlobalScript.SYMBOLTABLE(ast = p),_) + equation + (ip,_) = Builtin.getInitialFunctions(); + p = if builtin then Interactive.updateProgram(p,ip) else p; + (_,paths) = Interactive.getClassNamesRecursive(NONE(),p,showProtected,{}); + paths = listReverse(paths); + paths = if sort then List.sort(paths, Absyn.pathGe) else paths; + vals = List.map(paths,ValuesUtil.makeCodeTypeName); + then + (cache,ValuesUtil.makeArray(vals),st); + + case (cache,_,"getClassNames",{Values.CODE(Absyn.C_TYPENAME(path)),Values.BOOL(true),_,Values.BOOL(sort),Values.BOOL(builtin),Values.BOOL(showProtected)},st as GlobalScript.SYMBOLTABLE(ast = p),_) + equation + (ip,_) = Builtin.getInitialFunctions(); + p = if builtin then Interactive.updateProgram(p,ip) else p; + (_,paths) = Interactive.getClassNamesRecursive(SOME(path),p,showProtected,{}); + paths = listReverse(paths); + paths = if sort then List.sort(paths, Absyn.pathGe) else paths; + vals = List.map(paths,ValuesUtil.makeCodeTypeName); + then + (cache,ValuesUtil.makeArray(vals),st); + case (cache,_,"reloadClass",{Values.CODE(Absyn.C_TYPENAME(classpath)),Values.STRING(encoding)},st as GlobalScript.SYMBOLTABLE(ast = p),_) equation Absyn.CLASS(info=SOURCEINFO(fileName=filename,lastModification=r2)) = Interactive.getPathedClassInProgram(classpath, p); @@ -2452,32 +1429,6 @@ algorithm case (cache,_,"loadString",_,st,_) then (cache,Values.BOOL(false),st); - case (cache,_,"saveModel",{Values.STRING(filename),Values.CODE(Absyn.C_TYPENAME(classpath))},(st as GlobalScript.SYMBOLTABLE(ast = p)),_) - equation - absynClass = Interactive.getPathedClassInProgram(classpath, p); - str = Dump.unparseStr(Absyn.PROGRAM({absynClass},Absyn.TOP()),true); - System.writeFile(filename, str); - then - (cache,Values.BOOL(true),st); - - case (cache,_,"save",{Values.CODE(Absyn.C_TYPENAME(className))},(st as GlobalScript.SYMBOLTABLE(ast = p)),_) - equation - (newp,filename) = Interactive.getContainedClassAndFile(className, p); - str = Dump.unparseStr(newp,true); - System.writeFile(filename, str); - then - (cache,Values.BOOL(true),st); - - case (cache,_,"save",{Values.CODE(Absyn.C_TYPENAME(_))},st,_) - then (cache,Values.BOOL(false),st); - - case (cache,_,"saveAll",{Values.STRING(filename)},st as GlobalScript.SYMBOLTABLE(ast=p),_) - equation - str = Dump.unparseStr(p,true); - System.writeFile(filename, str); - then - (cache,Values.BOOL(true),st); - case (cache,_,"help",{Values.STRING("")},st as GlobalScript.SYMBOLTABLE(),_) equation str = Flags.printUsage(); @@ -2490,59 +1441,6 @@ algorithm then (cache,Values.STRING(str),st); - case (cache,_,"saveModel",{Values.STRING(name),Values.CODE(Absyn.C_TYPENAME(classpath))}, - (st as GlobalScript.SYMBOLTABLE(ast = p)),_) - equation - _ = Interactive.getPathedClassInProgram(classpath, p); - Error.addMessage(Error.WRITING_FILE_ERROR, {name}); - then - (cache,Values.BOOL(false),st); - - case (cache,_,"saveModel",{Values.STRING(_),Values.CODE(Absyn.C_TYPENAME(classpath))},st,_) - equation - cname = Absyn.pathString(classpath); - Error.addMessage(Error.LOOKUP_ERROR, {cname,"global"}); - then - (cache,Values.BOOL(false),st); - - case (cache,_,"saveTotalModel",{Values.STRING(filename),Values.CODE(Absyn.C_TYPENAME(classpath))},st,_) - equation - st = saveTotalModel(filename,classpath,st); - then - (cache, Values.BOOL(true), st); - - case (cache,_,"saveTotalModel",{Values.STRING(_),Values.CODE(Absyn.C_TYPENAME(_))},(st as GlobalScript.SYMBOLTABLE()),_) - then (cache, Values.BOOL(false), st); - - case (cache,_,"getDocumentationAnnotation",{Values.CODE(Absyn.C_TYPENAME(classpath))},st as GlobalScript.SYMBOLTABLE(ast=p),_) - equation - ((str1,str2)) = Interactive.getNamedAnnotation(classpath, p, Absyn.IDENT("Documentation"), SOME(("","")),Interactive.getDocumentationAnnotationString); - then - (cache,ValuesUtil.makeArray({Values.STRING(str1),Values.STRING(str2)}),st); - - case (cache,_,"addClassAnnotation",{Values.CODE(Absyn.C_TYPENAME(classpath)),Values.CODE(Absyn.C_EXPRESSION(aexp))},GlobalScript.SYMBOLTABLE(p,_,ic,iv,cf,lf),_) - equation - p = Interactive.addClassAnnotation(Absyn.pathToCref(classpath), Absyn.NAMEDARG("annotate",aexp)::{}, p); - then - (cache,Values.BOOL(true),GlobalScript.SYMBOLTABLE(p,NONE(),ic,iv,cf,lf)); - - case (cache,_,"addClassAnnotation",_,st as GlobalScript.SYMBOLTABLE(),_) - then - (cache,Values.BOOL(false),st); - - case (cache,_,"setDocumentationAnnotation",{Values.CODE(Absyn.C_TYPENAME(classpath)),Values.STRING(str1),Values.STRING(str2)},GlobalScript.SYMBOLTABLE(p,_,ic,iv,cf,lf),_) - equation - nargs = List.consOnTrue(not stringEq(str1,""), Absyn.NAMEDARG("info",Absyn.STRING(str1)), {}); - nargs = List.consOnTrue(not stringEq(str2,""), Absyn.NAMEDARG("revisions",Absyn.STRING(str2)), nargs); - aexp = Absyn.CALL(Absyn.CREF_IDENT("Documentation",{}),Absyn.FUNCTIONARGS({},nargs)); - p = Interactive.addClassAnnotation(Absyn.pathToCref(classpath), Absyn.NAMEDARG("annotate",aexp)::{}, p); - then - (cache,Values.BOOL(true),GlobalScript.SYMBOLTABLE(p,NONE(),ic,iv,cf,lf)); - - case (cache,_,"setDocumentationAnnotation",_,st as GlobalScript.SYMBOLTABLE(),_) - then - (cache,Values.BOOL(false),st); - case (cache,_,"getTimeStamp",{Values.CODE(Absyn.C_TYPENAME(classpath))},st as GlobalScript.SYMBOLTABLE(ast=p),_) equation Absyn.CLASS(info=SOURCEINFO(lastModification=r)) = Interactive.getPathedClassInProgram(classpath,p); @@ -2559,169 +1457,6 @@ algorithm then (cache,Values.STRING(str),st); - case (cache,_,"isType",{Values.CODE(Absyn.C_TYPENAME(classpath))},st as GlobalScript.SYMBOLTABLE(ast=p),_) - equation - b = Interactive.isType(classpath, p); - then - (cache,Values.BOOL(b),st); - - case (cache,_,"isPackage",{Values.CODE(Absyn.C_TYPENAME(classpath))},st as GlobalScript.SYMBOLTABLE(ast=p),_) - equation - b = Interactive.isPackage(classpath, p); - then - (cache,Values.BOOL(b),st); - - case (cache,_,"isClass",{Values.CODE(Absyn.C_TYPENAME(classpath))},st as GlobalScript.SYMBOLTABLE(ast=p),_) - equation - b = Interactive.isClass(classpath, p); - then - (cache,Values.BOOL(b),st); - - case (cache,_,"isRecord",{Values.CODE(Absyn.C_TYPENAME(classpath))},st as GlobalScript.SYMBOLTABLE(ast=p),_) - equation - b = Interactive.isRecord(classpath, p); - then - (cache,Values.BOOL(b),st); - - case (cache,_,"isBlock",{Values.CODE(Absyn.C_TYPENAME(classpath))},st as GlobalScript.SYMBOLTABLE(ast=p),_) - equation - b = Interactive.isBlock(classpath, p); - then - (cache,Values.BOOL(b),st); - - case (cache,_,"isFunction",{Values.CODE(Absyn.C_TYPENAME(classpath))},st as GlobalScript.SYMBOLTABLE(ast=p),_) - equation - b = Interactive.isFunction(classpath, p); - then - (cache,Values.BOOL(b),st); - - case (cache,_,"isPartial",{Values.CODE(Absyn.C_TYPENAME(classpath))},st as GlobalScript.SYMBOLTABLE(ast=p),_) - equation - b = Interactive.isPartial(classpath, p); - then - (cache,Values.BOOL(b),st); - - case (cache,_,"isModel",{Values.CODE(Absyn.C_TYPENAME(classpath))},st as GlobalScript.SYMBOLTABLE(ast=p),_) - equation - b = Interactive.isModel(classpath, p); - then - (cache,Values.BOOL(b),st); - - case (cache,_,"isConnector",{Values.CODE(Absyn.C_TYPENAME(classpath))},st as GlobalScript.SYMBOLTABLE(ast=p),_) - equation - b = Interactive.isConnector(classpath, p); - then - (cache,Values.BOOL(b),st); - - case (cache,_,"isOptimization",{Values.CODE(Absyn.C_TYPENAME(classpath))},st as GlobalScript.SYMBOLTABLE(ast=p),_) - equation - b = Interactive.isOptimization(classpath, p); - then - (cache,Values.BOOL(b),st); - - case (cache,_,"isEnumeration",{Values.CODE(Absyn.C_TYPENAME(classpath))},st as GlobalScript.SYMBOLTABLE(ast=p),_) - equation - b = Interactive.isEnumeration(classpath, p); - then - (cache,Values.BOOL(b),st); - - case (cache,_,"isOperator",{Values.CODE(Absyn.C_TYPENAME(classpath))},st as GlobalScript.SYMBOLTABLE(ast=p),_) - equation - b = Interactive.isOperator(classpath, p); - then - (cache,Values.BOOL(b),st); - - case (cache,_,"isOperatorRecord",{Values.CODE(Absyn.C_TYPENAME(classpath))},st as GlobalScript.SYMBOLTABLE(ast=p),_) - equation - b = Interactive.isOperatorRecord(classpath, p); - then - (cache,Values.BOOL(b),st); - - case (cache,_,"isOperatorFunction",{Values.CODE(Absyn.C_TYPENAME(classpath))},st as GlobalScript.SYMBOLTABLE(ast=p),_) - equation - b = Interactive.isOperatorFunction(classpath, p); - then - (cache,Values.BOOL(b),st); - - case (cache,_,"isProtectedClass",{Values.CODE(Absyn.C_TYPENAME(classpath)), Values.STRING(name)},st as GlobalScript.SYMBOLTABLE(ast=p),_) - equation - b = Interactive.isProtectedClass(classpath, name, p); - then - (cache,Values.BOOL(b),st); - - case (cache,env,"getBuiltinType",{Values.CODE(Absyn.C_TYPENAME(classpath))},st as GlobalScript.SYMBOLTABLE(),_) - equation - (_, tp, _) = Lookup.lookupType(cache, env, classpath, SOME(Absyn.dummyInfo)); - str = Types.unparseType(tp); - then - (cache,Values.STRING(str),st); - - // if the lookup fails - case (cache,_,"getBuiltinType",{Values.CODE(Absyn.C_TYPENAME(_))},st as GlobalScript.SYMBOLTABLE(ast=_),_) - then - (cache,Values.STRING(""),st); - - case (cache,_,"extendsFrom", - {Values.CODE(Absyn.C_TYPENAME(classpath)), - Values.CODE(Absyn.C_TYPENAME(baseClassPath))},st as GlobalScript.SYMBOLTABLE(ast=p),_) - equation - paths = Interactive.getAllInheritedClasses(classpath, p); - b = List.applyAndFold1(paths, boolOr, Absyn.pathSuffixOfr, baseClassPath, false); - then - (cache,Values.BOOL(b),st); - - case (cache,_,"extendsFrom",_,st as GlobalScript.SYMBOLTABLE(),_) - then - (cache,Values.BOOL(false),st); - - case (cache,_,"isExperiment",{Values.CODE(Absyn.C_TYPENAME(classpath))},st as GlobalScript.SYMBOLTABLE(ast=p),_) - equation - b = Interactive.getNamedAnnotation(classpath, p, Absyn.IDENT("experiment"), SOME(false), hasStopTime); - then - (cache,Values.BOOL(b),st); - - case (cache,_,"isExperiment",_,st as GlobalScript.SYMBOLTABLE(),_) - then - (cache,Values.BOOL(false),st); - - case (cache,_,"getComponentsTest",{Values.CODE(Absyn.C_TYPENAME(classpath))},st as GlobalScript.SYMBOLTABLE(ast=p),_) - equation - absynClass = Interactive.getPathedClassInProgram(classpath, p); - (sp, st) = GlobalScriptUtil.symbolTableToSCode(st); - (cache, env) = Inst.makeEnvFromProgram(FCore.emptyCache(), sp, Absyn.IDENT("")); - (cache,(cl as SCode.CLASS(name=name,encapsulatedPrefix=encflag,restriction=restr)),env) = Lookup.lookupClass(cache, env, classpath, false); - env = FGraph.openScope(env, encflag, SOME(name), FGraph.restrictionToScopeType(restr)); - (_, env) = Inst.partialInstClassIn(cache, env, InnerOuter.emptyInstHierarchy, DAE.NOMOD(), Prefix.NOPRE(), - ClassInf.start(restr, FGraph.getGraphName(env)), cl, SCode.PUBLIC(), {}, 0); - valsLst = list(getComponentInfo(c, env, isProtected=false) for c in Interactive.getPublicComponentsInClass(absynClass)); - valsLst = listAppend(list(getComponentInfo(c, env, isProtected=true) for c in Interactive.getProtectedComponentsInClass(absynClass)), valsLst); - then (cache,ValuesUtil.makeArray(List.flatten(valsLst)),st); - - case (cache,_,"getComponentsTest",{Values.CODE(Absyn.C_TYPENAME(_))},st as GlobalScript.SYMBOLTABLE(),_) - then - (cache,Values.ARRAY({},{}),st); - - - case (cache,_,"getSimulationOptions",{Values.CODE(Absyn.C_TYPENAME(classpath)),Values.REAL(startTime),Values.REAL(stopTime),Values.REAL(tolerance),Values.INTEGER(numberOfIntervals),Values.REAL(interval)},st as GlobalScript.SYMBOLTABLE(),_) - equation - cr_1 = Absyn.pathToCref(classpath); - // ignore the name of the model - ErrorExt.setCheckpoint("getSimulationOptions"); - simOpt = GlobalScript.SIMULATION_OPTIONS(DAE.RCONST(startTime),DAE.RCONST(stopTime),DAE.ICONST(numberOfIntervals),DAE.RCONST(0.0),DAE.RCONST(tolerance),DAE.SCONST(""),DAE.SCONST(""),DAE.SCONST(""),DAE.SCONST(""),DAE.SCONST(""),DAE.SCONST(""),DAE.SCONST("")); - ErrorExt.rollBack("getSimulationOptions"); - (_, _::startTimeExp::stopTimeExp::intervalExp::toleranceExp::_) = StaticScript.getSimulationArguments(FCore.emptyCache(), FGraph.empty(), {Absyn.CREF(cr_1)},{},false,SOME(st),Prefix.NOPRE(),Absyn.dummyInfo,SOME(simOpt)); - startTime = ValuesUtil.valueReal(Util.makeValueOrDefault(Ceval.cevalSimple,startTimeExp,Values.REAL(startTime))); - stopTime = ValuesUtil.valueReal(Util.makeValueOrDefault(Ceval.cevalSimple,stopTimeExp,Values.REAL(stopTime))); - tolerance = ValuesUtil.valueReal(Util.makeValueOrDefault(Ceval.cevalSimple,toleranceExp,Values.REAL(tolerance))); - Values.INTEGER(numberOfIntervals) = Util.makeValueOrDefault(Ceval.cevalSimple,intervalExp,Values.INTEGER(numberOfIntervals)); // number of intervals - if numberOfIntervals == 0 then - numberOfIntervals = if interval > 0.0 then integer(ceil((stopTime - startTime)/interval)) else 0; - else - interval = (stopTime-startTime) / max(numberOfIntervals,1); - end if; - then - (cache,Values.TUPLE({Values.REAL(startTime),Values.REAL(stopTime),Values.REAL(tolerance),Values.INTEGER(numberOfIntervals),Values.REAL(interval)}),st); - case (cache,_,"classAnnotationExists",{Values.CODE(Absyn.C_TYPENAME(classpath)),Values.CODE(Absyn.C_TYPENAME(path))},st as GlobalScript.SYMBOLTABLE(ast=p),_) equation b = Interactive.getNamedAnnotation(classpath, p, path, SOME(false), Util.isSome); @@ -2741,81 +1476,6 @@ algorithm Error.addMessage(Error.CLASS_ANNOTATION_DOES_NOT_EXIST, {str1,str2}); then fail(); - case (cache,_,"searchClassNames",{Values.STRING(str), Values.BOOL(b)},st as GlobalScript.SYMBOLTABLE(ast=p),_) - equation - (_,paths) = Interactive.getClassNamesRecursive(NONE(),p,false,{}); - paths = listReverse(paths); - vals = List.map(paths,ValuesUtil.makeCodeTypeName); - vals = searchClassNames(vals, str, b, p); - then - (cache,ValuesUtil.makeArray(vals),st); - - case (cache,_,"getAvailableLibraries",{},st,_) - equation - mp = Settings.getModelicaPath(Config.getRunningTestsuite()); - gd = System.groupDelimiter(); - mps = System.strtok(mp, gd); - files = List.flatten(List.map(mps, System.moFiles)); - dirs = List.flatten(List.map(mps, System.subDirectories)); - files = List.map(List.map1(listAppend(files,dirs), System.strtok, ". "), listHead); - (str, status) = System.popen("impact search '' | perl -pe 's/\\e\\[?.*?[\\@-~]//g' | grep '[^ :]*:' | cut -d: -f1 2>&1"); - if 0==status then - files = listAppend(files, System.strtok(str,"\n")); - end if; - files = List.sort(files,Util.strcmpBool); - files = List.sortedUnique(files, stringEqual); - v = ValuesUtil.makeArray(List.map(files, ValuesUtil.makeString)); - then - (cache,v,st); - - case (cache,_,"getUses",{Values.CODE(Absyn.C_TYPENAME(classpath))},st as GlobalScript.SYMBOLTABLE(ast=p),_) - equation - (absynClass as Absyn.CLASS()) = Interactive.getPathedClassInProgram(classpath, p); - uses = Interactive.getUsesAnnotation(Absyn.PROGRAM({absynClass},Absyn.TOP())); - v = ValuesUtil.makeArray(List.map(uses,makeUsesArray)); - then - (cache,v,st); - - case (cache,_,"getDerivedClassModifierNames",{Values.CODE(Absyn.C_TYPENAME(classpath))},st as GlobalScript.SYMBOLTABLE(ast=p),_) - equation - absynClass = Interactive.getPathedClassInProgram(classpath, p); - args = Interactive.getDerivedClassModifierNames(absynClass); - vals = List.map(args, ValuesUtil.makeString); - v = ValuesUtil.makeArray(vals); - then - (cache,v,st); - - case (cache,_,"getDerivedClassModifierValue",{Values.CODE(Absyn.C_TYPENAME(classpath)), Values.CODE(Absyn.C_TYPENAME(className))},st as GlobalScript.SYMBOLTABLE(ast=p),_) - equation - absynClass = Interactive.getPathedClassInProgram(classpath, p); - str = Interactive.getDerivedClassModifierValue(absynClass, className); - then - (cache,Values.STRING(str),st); - - case (cache,_,"getAstAsCorbaString",{Values.STRING("")},st as GlobalScript.SYMBOLTABLE(ast=p),_) - equation - Print.clearBuf(); - Dump.getAstAsCorbaString(p); - res = Print.getString(); - Print.clearBuf(); - then - (cache,Values.STRING(res),st); - - case (cache,_,"getAstAsCorbaString",{Values.STRING(str)},st as GlobalScript.SYMBOLTABLE(ast=p),_) - equation - Print.clearBuf(); - Dump.getAstAsCorbaString(p); - Print.writeBuf(str); - Print.clearBuf(); - str = "Wrote result to file: " + str; - then - (cache,Values.STRING(str),st); - - case (cache,_,"getAstAsCorbaString",_,st,_) - equation - Error.addMessage(Error.INTERNAL_ERROR,{"getAstAsCorbaString failed"}); - then (cache,Values.STRING(""),st); - case (cache,_,"strtok",{Values.STRING(str),Values.STRING(token)},st,_) equation vals = List.map(System.strtok(str,token), ValuesUtil.makeString); @@ -2897,579 +1557,28 @@ algorithm Values.STRING(confcmd)}; then (cache,Values.RECORD(Absyn.IDENT("OpenModelica.Scripting.CheckSettingsResult"),vals,vars_1,-1),st); - case (cache,_,"readSimulationResult",{Values.STRING(filename),Values.ARRAY(valueLst=cvars),Values.INTEGER(size)},st,_) + case (cache,_,"echo",{v as Values.BOOL(bval)},st,_) equation - vars_1 = List.map(cvars, ValuesUtil.printCodeVariableName); - filename_1 = Util.absoluteOrRelative(filename); - value = ValuesUtil.readDataset(filename_1, vars_1, size); - then - (cache,value,st); + Settings.setEcho(if bval then 1 else 0); + then (cache,v,st); - case (cache,_,"readSimulationResult",_,st,_) + case (cache,_,"numProcessors",{},st,_) equation - Error.addMessage(Error.SCRIPT_READ_SIM_RES_ERROR, {}); - then (cache,Values.META_FAIL(),st); + i = Config.noProc(); + then (cache,Values.INTEGER(i),st); - case (cache,_,"readSimulationResultSize",{Values.STRING(filename)},st,_) + case (cache,_,"runScript",{Values.STRING(str)},st,_) equation - filename_1 = Util.absoluteOrRelative(filename); - i = SimulationResults.readSimulationResultSize(filename_1); + str = Util.testsuiteFriendlyPath(str); + istmts = Parser.parseexp(str); + (res,newst) = Interactive.evaluate(istmts, st, true); then - (cache,Values.INTEGER(i),st); + (cache,Values.STRING(res),newst); - case (cache,_,"readSimulationResultVars",{Values.STRING(filename),Values.BOOL(b1),Values.BOOL(b2)},st,_) - equation - filename_1 = Util.absoluteOrRelative(filename); - args = SimulationResults.readVariables(filename_1, b1, b2); - vals = List.map(args, ValuesUtil.makeString); - v = ValuesUtil.makeArray(vals); - then - (cache,v,st); + case (cache,_,"runScript",_,st,_) + then (cache,Values.STRING("Failed"),st); - case (cache,_,"compareSimulationResults",{Values.STRING(filename),Values.STRING(filename_1),Values.STRING(filename2),Values.REAL(x1),Values.REAL(x2),Values.ARRAY(valueLst=cvars)},st,_) - equation - filename = Util.absoluteOrRelative(filename); - filename_1 = Util.testsuiteFriendlyPath(filename_1); - filename_1 = Util.absoluteOrRelative(filename_1); - filename2 = Util.absoluteOrRelative(filename2); - vars_1 = List.map(cvars, ValuesUtil.extractValueString); - strings = SimulationResults.cmpSimulationResults(Config.getRunningTestsuite(),filename,filename_1,filename2,x1,x2,vars_1); - cvars = List.map(strings,ValuesUtil.makeString); - v = ValuesUtil.makeArray(cvars); - then - (cache,v,st); - - case (cache,_,"compareSimulationResults",_,st,_) - then (cache,Values.STRING("Error in compareSimulationResults"),st); - - case (cache,_,"filterSimulationResults",{Values.STRING(filename),Values.STRING(filename_1),Values.ARRAY(valueLst=cvars),Values.INTEGER(numberOfIntervals)},st,_) - equation - vars_1 = List.map(cvars, ValuesUtil.extractValueString); - b = SimulationResults.filterSimulationResults(filename,filename_1,vars_1,numberOfIntervals); - then - (cache,Values.BOOL(b),st); - - case (cache,_,"filterSimulationResults",_,st,_) - then (cache,Values.BOOL(false),st); - - case (cache,_,"diffSimulationResults",{Values.STRING(filename),Values.STRING(filename_1),Values.STRING(filename2),Values.REAL(reltol),Values.REAL(reltolDiffMinMax),Values.REAL(rangeDelta),Values.ARRAY(valueLst=cvars),Values.BOOL(b)},st,_) - equation - pwd = System.pwd(); - pd = System.pathDelimiter(); - filename = Util.absoluteOrRelative(filename); - filename_1 = Util.testsuiteFriendlyPath(filename_1); - filename_1 = Util.absoluteOrRelative(filename_1); - filename2 = Util.absoluteOrRelative(filename2); - vars_1 = List.map(cvars, ValuesUtil.extractValueString); - (b,strings) = SimulationResults.diffSimulationResults(Config.getRunningTestsuite(),filename,filename_1,filename2,reltol,reltolDiffMinMax,rangeDelta,vars_1,b); - cvars = List.map(strings,ValuesUtil.makeString); - v1 = ValuesUtil.makeArray(cvars); - then - (cache,Values.TUPLE({Values.BOOL(b),v1}),st); - - case (cache,_,"diffSimulationResults",_,st,_) - equation - v = ValuesUtil.makeArray({}); - then (cache,Values.TUPLE({Values.BOOL(false),v}),st); - - case (cache,_,"diffSimulationResultsHtml",{Values.STRING(str),Values.STRING(filename),Values.STRING(filename_1),Values.REAL(reltol),Values.REAL(reltolDiffMinMax),Values.REAL(rangeDelta)},st,_) - equation - filename = Util.absoluteOrRelative(filename); - filename_1 = Util.testsuiteFriendlyPath(filename_1); - filename_1 = Util.absoluteOrRelative(filename_1); - str = SimulationResults.diffSimulationResultsHtml(Config.getRunningTestsuite(),filename,filename_1,reltol,reltolDiffMinMax,rangeDelta,str); - then - (cache,Values.STRING(str),st); - - case (cache,_,"diffSimulationResultsHtml",_,st,_) - then (cache,Values.STRING(""),st); - - case (cache,_,"checkTaskGraph",{Values.STRING(filename),Values.STRING(filename_1)},st,_) - equation - pwd = System.pwd(); - pd = System.pathDelimiter(); - filename = if System.substring(filename,1,1) == "/" then filename else stringAppendList({pwd,pd,filename}); - filename_1 = if System.substring(filename_1,1,1) == "/" then filename_1 else stringAppendList({pwd,pd,filename_1}); - strings = TaskGraphResults.checkTaskGraph(filename, filename_1); - cvars = List.map(strings,ValuesUtil.makeString); - v = ValuesUtil.makeArray(cvars); - then (cache,v,st); - - case (cache,_,"checkTaskGraph",_,st,_) - then (cache,Values.STRING("Error in checkTaskGraph"),st); - - case (cache,_,"checkCodeGraph",{Values.STRING(filename),Values.STRING(filename_1)},st,_) - equation - pwd = System.pwd(); - pd = System.pathDelimiter(); - filename = if System.substring(filename,1,1) == "/" then filename else stringAppendList({pwd,pd,filename}); - filename_1 = if System.substring(filename_1,1,1) == "/" then filename_1 else stringAppendList({pwd,pd,filename_1}); - strings = TaskGraphResults.checkCodeGraph(filename, filename_1); - cvars = List.map(strings,ValuesUtil.makeString); - v = ValuesUtil.makeArray(cvars); - then (cache,v,st); - - case (cache,_,"checkCodeGraph",_,st,_) - then (cache,Values.STRING("Error in checkCodeGraph"),st); - - //plotAll(model) - case (cache,env,"plotAll", - { - Values.BOOL(externalWindow), - Values.STRING(filename), - Values.STRING(title), - Values.STRING(gridStr), - Values.BOOL(logX), - Values.BOOL(logY), - Values.STRING(xLabel), - Values.STRING(yLabel), - Values.ARRAY(valueLst={Values.REAL(x1),Values.REAL(x2)}), - Values.ARRAY(valueLst={Values.REAL(y1),Values.REAL(y2)}), - Values.REAL(curveWidth), - Values.INTEGER(curveStyle), - Values.STRING(legendPosition), - Values.STRING(footer), - Values.BOOL(autoScale), - Values.BOOL(forceOMPlot) - }, - st, - _) - equation - // get OPENMODELICAHOME - omhome = Settings.getInstallationDirectoryPath(); - // get the simulation filename - (cache,filename) = cevalCurrentSimulationResultExp(cache,env,filename,st,msg); - pd = System.pathDelimiter(); - // create absolute path of simulation result file - str1 = System.pwd() + pd + filename; - s1 = if System.os() == "Windows_NT" then ".exe" else ""; - filename = if System.regularFileExists(str1) then str1 else filename; - // check if plot callback is defined - b = System.plotCallBackDefined(); - if boolOr(forceOMPlot, boolNot(b)) then - // create the path till OMPlot - str2 = stringAppendList({omhome,pd,"bin",pd,"OMPlot",s1}); - // create the list of arguments for OMPlot - str3 = "--filename=\"" + filename + "\" --title=\"" + title + "\" --grid=" + gridStr + " --plotAll --logx=" + boolString(logX) + " --logy=" + boolString(logY) + " --xlabel=\"" + xLabel + "\" --ylabel=\"" + yLabel + "\" --xrange=" + realString(x1) + ":" + realString(x2) + " --yrange=" + realString(y1) + ":" + realString(y2) + " --new-window=" + boolString(externalWindow) + " --curve-width=" + realString(curveWidth) + " --curve-style=" + intString(curveStyle) + " --legend-position=\"" + legendPosition + "\" --footer=\"" + footer + "\" --auto-scale=" + boolString(autoScale); - call = stringAppendList({"\"",str2,"\""," ",str3}); - 0 = System.spawnCall(str2, call); - elseif b then - logXStr = boolString(logX); - logYStr = boolString(logY); - x1Str = realString(x1); - x2Str = realString(x2); - y1Str = realString(y1); - y2Str = realString(y2); - curveWidthStr = realString(curveWidth); - curveStyleStr = intString(curveStyle); - autoScaleStr = boolString(autoScale); - System.plotCallBack(externalWindow,filename,title,gridStr,"plotall",logXStr,logYStr,xLabel,yLabel,x1Str,x2Str,y1Str,y2Str,curveWidthStr,curveStyleStr,legendPosition,footer,autoScaleStr,""); - end if; - then - (cache,Values.BOOL(true),st); - - case (cache,_,"plotAll",_,st,_) - then (cache,Values.BOOL(false),st); - - // plot(x, model) - case (cache,env,"plot", - { - Values.ARRAY(valueLst = cvars), - Values.BOOL(externalWindow), - Values.STRING(filename), - Values.STRING(title), - Values.STRING(gridStr), - Values.BOOL(logX), - Values.BOOL(logY), - Values.STRING(xLabel), - Values.STRING(yLabel), - Values.ARRAY(valueLst={Values.REAL(x1),Values.REAL(x2)}), - Values.ARRAY(valueLst={Values.REAL(y1),Values.REAL(y2)}), - Values.REAL(curveWidth), - Values.INTEGER(curveStyle), - Values.STRING(legendPosition), - Values.STRING(footer), - Values.BOOL(autoScale), - Values.BOOL(forceOMPlot) - }, - st,_) - equation - // get the variables list - vars_1 = List.map(cvars, ValuesUtil.printCodeVariableName); - // get OPENMODELICAHOME - omhome = Settings.getInstallationDirectoryPath(); - // get the simulation filename - (cache,filename) = cevalCurrentSimulationResultExp(cache,env,filename,st,msg); - pd = System.pathDelimiter(); - // create absolute path of simulation result file - str1 = System.pwd() + pd + filename; - s1 = if System.os() == "Windows_NT" then ".exe" else ""; - filename = if System.regularFileExists(str1) then str1 else filename; - // check if plot callback is defined - b = System.plotCallBackDefined(); - if boolOr(forceOMPlot, boolNot(b)) then - // seperate the variables - str = stringDelimitList(vars_1,"\" \""); - // create the path till OMPlot - str2 = stringAppendList({omhome,pd,"bin",pd,"OMPlot",s1}); - // create the list of arguments for OMPlot - str3 = "--filename=\"" + filename + "\" --title=\"" + title + "\" --grid=" + gridStr + " --plot --logx=" + boolString(logX) + " --logy=" + boolString(logY) + " --xlabel=\"" + xLabel + "\" --ylabel=\"" + yLabel + "\" --xrange=" + realString(x1) + ":" + realString(x2) + " --yrange=" + realString(y1) + ":" + realString(y2) + " --new-window=" + boolString(externalWindow) + " --curve-width=" + realString(curveWidth) + " --curve-style=" + intString(curveStyle) + " --legend-position=\"" + legendPosition + "\" --footer=\"" + footer + "\" --auto-scale=" + boolString(autoScale) + " \"" + str + "\""; - call = stringAppendList({"\"",str2,"\""," ",str3}); - 0 = System.spawnCall(str2, call); - elseif b then - logXStr = boolString(logX); - logYStr = boolString(logY); - x1Str = realString(x1); - x2Str = realString(x2); - y1Str = realString(y1); - y2Str = realString(y2); - curveWidthStr = realString(curveWidth); - curveStyleStr = intString(curveStyle); - autoScaleStr = boolString(autoScale); - // seperate the variables - str = stringDelimitList(vars_1, " "); - System.plotCallBack(externalWindow,filename,title,gridStr,"plot",logXStr,logYStr,xLabel,yLabel,x1Str,x2Str,y1Str,y2Str,curveWidthStr,curveStyleStr,legendPosition,footer,autoScaleStr,str); - end if; - then - (cache,Values.BOOL(true),st); - - case (cache,_,"plot",_,st,_) - then - (cache,Values.BOOL(false),st); - - case (cache,env,"val",{cvar,Values.REAL(timeStamp),Values.STRING("")},st,_) - equation - (cache,Values.STRING(filename),_) = Ceval.ceval(cache,env,buildCurrentSimulationResultExp(), true, SOME(st),msg, 0); - varNameStr = ValuesUtil.printCodeVariableName(cvar); - val = SimulationResults.val(filename,varNameStr,timeStamp); - then (cache,Values.REAL(val),st); - - case (cache,_,"val",{cvar,Values.REAL(timeStamp),Values.STRING(filename)},st,_) - equation - false = stringEq(filename,""); - varNameStr = ValuesUtil.printCodeVariableName(cvar); - val = SimulationResults.val(filename,varNameStr,timeStamp); - then (cache,Values.REAL(val),st); - - case (cache,_,"closeSimulationResultFile",_,st,_) - equation - SimulationResults.close(); - then - (cache,Values.BOOL(true),st); - - case (cache,_,"getParameterNames",{Values.CODE(Absyn.C_TYPENAME(path))},(st as GlobalScript.SYMBOLTABLE(ast = p)),_) - equation - strings = Interactive.getParameterNames(path, p); - vals = List.map(strings, ValuesUtil.makeString); - v = ValuesUtil.makeArray(vals); - then - (cache,v,st); - - case (cache,_,"getParameterValue",{Values.CODE(Absyn.C_TYPENAME(path)),Values.STRING(str1)},(st as GlobalScript.SYMBOLTABLE(ast = p)),_) - equation - str2 = Interactive.getComponentBinding(path, str1, p); - then - (cache,Values.STRING(str2),st); - - case (cache,_,"getComponentModifierNames",{Values.CODE(Absyn.C_TYPENAME(path)),Values.STRING(str1)},(st as GlobalScript.SYMBOLTABLE(ast = p)),_) - equation - strings = Interactive.getComponentModifierNames(path, str1, p); - vals = List.map(strings, ValuesUtil.makeString); - v = ValuesUtil.makeArray(vals); - then - (cache,v,st); - - case (cache,_,"getAlgorithmCount",{Values.CODE(Absyn.C_TYPENAME(path))},(st as GlobalScript.SYMBOLTABLE(ast = p)),_) - equation - absynClass = Interactive.getPathedClassInProgram(path, p); - n = listLength(getAlgorithms(absynClass)); - then - (cache,Values.INTEGER(n),st); - - case (cache,_,"getAlgorithmCount",_,st,_) then (cache,Values.INTEGER(0),st); - - case (cache,_,"getNthAlgorithm",{Values.CODE(Absyn.C_TYPENAME(path)),Values.INTEGER(n)},(st as GlobalScript.SYMBOLTABLE(ast = p)),_) - equation - absynClass = Interactive.getPathedClassInProgram(path, p); - str = getNthAlgorithm(absynClass, n); - then - (cache,Values.STRING(str),st); - - case (cache,_,"getNthAlgorithm",_,st,_) then (cache,Values.STRING(""),st); - - case (cache,_,"getInitialAlgorithmCount",{Values.CODE(Absyn.C_TYPENAME(path))},(st as GlobalScript.SYMBOLTABLE(ast = p)),_) - equation - absynClass = Interactive.getPathedClassInProgram(path, p); - n = listLength(getInitialAlgorithms(absynClass)); - then - (cache,Values.INTEGER(n),st); - - case (cache,_,"getInitialAlgorithmCount",_,st,_) then (cache,Values.INTEGER(0),st); - - case (cache,_,"getNthInitialAlgorithm",{Values.CODE(Absyn.C_TYPENAME(path)),Values.INTEGER(n)},(st as GlobalScript.SYMBOLTABLE(ast = p)),_) - equation - absynClass = Interactive.getPathedClassInProgram(path, p); - str = getNthInitialAlgorithm(absynClass, n); - then - (cache,Values.STRING(str),st); - - case (cache,_,"getNthInitialAlgorithm",_,st,_) then (cache,Values.STRING(""),st); - - case (cache,_,"getAlgorithmItemsCount",{Values.CODE(Absyn.C_TYPENAME(path))},(st as GlobalScript.SYMBOLTABLE(ast = p)),_) - equation - absynClass = Interactive.getPathedClassInProgram(path, p); - n = getAlgorithmItemsCount(absynClass); - then - (cache,Values.INTEGER(n),st); - - case (cache,_,"getAlgorithmItemsCount",_,st,_) then (cache,Values.INTEGER(0),st); - - case (cache,_,"getNthAlgorithmItem",{Values.CODE(Absyn.C_TYPENAME(path)),Values.INTEGER(n)},(st as GlobalScript.SYMBOLTABLE(ast = p)),_) - equation - absynClass = Interactive.getPathedClassInProgram(path, p); - str = getNthAlgorithmItem(absynClass, n); - then - (cache,Values.STRING(str),st); - - case (cache,_,"getNthAlgorithmItem",_,st,_) then (cache,Values.STRING(""),st); - - case (cache,_,"getInitialAlgorithmItemsCount",{Values.CODE(Absyn.C_TYPENAME(path))},(st as GlobalScript.SYMBOLTABLE(ast = p)),_) - equation - absynClass = Interactive.getPathedClassInProgram(path, p); - n = getInitialAlgorithmItemsCount(absynClass); - then - (cache,Values.INTEGER(n),st); - - case (cache,_,"getInitialAlgorithmItemsCount",_,st,_) then (cache,Values.INTEGER(0),st); - - case (cache,_,"getNthInitialAlgorithmItem",{Values.CODE(Absyn.C_TYPENAME(path)),Values.INTEGER(n)},(st as GlobalScript.SYMBOLTABLE(ast = p)),_) - equation - absynClass = Interactive.getPathedClassInProgram(path, p); - str = getNthInitialAlgorithmItem(absynClass, n); - then - (cache,Values.STRING(str),st); - - case (cache,_,"getNthInitialAlgorithmItem",_,st,_) then (cache,Values.STRING(""),st); - - case (cache,_,"getEquationCount",{Values.CODE(Absyn.C_TYPENAME(path))},(st as GlobalScript.SYMBOLTABLE(ast = p)),_) - equation - absynClass = Interactive.getPathedClassInProgram(path, p); - n = listLength(getEquations(absynClass)); - then - (cache,Values.INTEGER(n),st); - - case (cache,_,"getEquationCount",_,st,_) then (cache,Values.INTEGER(0),st); - - case (cache,_,"getNthEquation",{Values.CODE(Absyn.C_TYPENAME(path)),Values.INTEGER(n)},(st as GlobalScript.SYMBOLTABLE(ast = p)),_) - equation - absynClass = Interactive.getPathedClassInProgram(path, p); - str = getNthEquation(absynClass, n); - then - (cache,Values.STRING(str),st); - - case (cache,_,"getNthEquation",_,st,_) then (cache,Values.STRING(""),st); - - case (cache,_,"getInitialEquationCount",{Values.CODE(Absyn.C_TYPENAME(path))},(st as GlobalScript.SYMBOLTABLE(ast = p)),_) - equation - absynClass = Interactive.getPathedClassInProgram(path, p); - n = listLength(getInitialEquations(absynClass)); - then - (cache,Values.INTEGER(n),st); - - case (cache,_,"getInitialEquationCount",_,st,_) then (cache,Values.INTEGER(0),st); - - case (cache,_,"getNthInitialEquation",{Values.CODE(Absyn.C_TYPENAME(path)),Values.INTEGER(n)},(st as GlobalScript.SYMBOLTABLE(ast = p)),_) - equation - absynClass = Interactive.getPathedClassInProgram(path, p); - str = getNthInitialEquation(absynClass, n); - then - (cache,Values.STRING(str),st); - - case (cache,_,"getNthInitialEquation",_,st,_) then (cache,Values.STRING(""),st); - - case (cache,_,"getEquationItemsCount",{Values.CODE(Absyn.C_TYPENAME(path))},(st as GlobalScript.SYMBOLTABLE(ast = p)),_) - equation - absynClass = Interactive.getPathedClassInProgram(path, p); - n = getEquationItemsCount(absynClass); - then - (cache,Values.INTEGER(n),st); - - case (cache,_,"getEquationItemsCount",_,st,_) then (cache,Values.INTEGER(0),st); - - case (cache,_,"getNthEquationItem",{Values.CODE(Absyn.C_TYPENAME(path)),Values.INTEGER(n)},(st as GlobalScript.SYMBOLTABLE(ast = p)),_) - equation - absynClass = Interactive.getPathedClassInProgram(path, p); - str = getNthEquationItem(absynClass, n); - then - (cache,Values.STRING(str),st); - - case (cache,_,"getNthEquationItem",_,st,_) then (cache,Values.STRING(""),st); - - case (cache,_,"getInitialEquationItemsCount",{Values.CODE(Absyn.C_TYPENAME(path))},(st as GlobalScript.SYMBOLTABLE(ast = p)),_) - equation - absynClass = Interactive.getPathedClassInProgram(path, p); - n = getInitialEquationItemsCount(absynClass); - then - (cache,Values.INTEGER(n),st); - - case (cache,_,"getInitialEquationItemsCount",_,st,_) then (cache,Values.INTEGER(0),st); - - case (cache,_,"getNthInitialEquationItem",{Values.CODE(Absyn.C_TYPENAME(path)),Values.INTEGER(n)},(st as GlobalScript.SYMBOLTABLE(ast = p)),_) - equation - absynClass = Interactive.getPathedClassInProgram(path, p); - str = getNthInitialEquationItem(absynClass, n); - then - (cache,Values.STRING(str),st); - - case (cache,_,"getNthInitialEquationItem",_,st,_) then (cache,Values.STRING(""),st); - - case (cache,_,"getAnnotationCount",{Values.CODE(Absyn.C_TYPENAME(path))},(st as GlobalScript.SYMBOLTABLE(ast = p)),_) - equation - absynClass = Interactive.getPathedClassInProgram(path, p); - n = getAnnotationCount(absynClass); - then - (cache,Values.INTEGER(n),st); - - case (cache,_,"getAnnotationCount",_,st,_) then (cache,Values.INTEGER(0),st); - - case (cache,_,"getNthAnnotationString",{Values.CODE(Absyn.C_TYPENAME(path)),Values.INTEGER(n)},(st as GlobalScript.SYMBOLTABLE(ast = p)),_) - equation - absynClass = Interactive.getPathedClassInProgram(path, p); - str = getNthAnnotationString(absynClass, n); - then - (cache,Values.STRING(str),st); - - case (cache,_,"getNthAnnotationString",_,st,_) then (cache,Values.STRING(""),st); - - case (cache,_,"getImportCount",{Values.CODE(Absyn.C_TYPENAME(path))},(st as GlobalScript.SYMBOLTABLE(ast = p)),_) - equation - absynClass = Interactive.getPathedClassInProgram(path, p); - n = getImportCount(absynClass); - then - (cache,Values.INTEGER(n),st); - - case (cache,_,"getImportCount",_,st,_) then (cache,Values.INTEGER(0),st); - - case (cache,_,"getNthImport",{Values.CODE(Absyn.C_TYPENAME(path)),Values.INTEGER(n)},(st as GlobalScript.SYMBOLTABLE(ast = p)),_) - equation - absynClass = Interactive.getPathedClassInProgram(path, p); - vals = getNthImport(absynClass, n); - then - (cache,ValuesUtil.makeArray(vals),st); - - case (cache,_,"getNthImport",_,st,_) then (cache,ValuesUtil.makeArray({}),st); - - // plotParametric - case (cache,env,"plotParametric", - { - cvar, - cvar2, - Values.BOOL(externalWindow), - Values.STRING(filename), - Values.STRING(title), - Values.STRING(gridStr), - Values.BOOL(logX), - Values.BOOL(logY), - Values.STRING(xLabel), - Values.STRING(yLabel), - Values.ARRAY(valueLst={Values.REAL(x1),Values.REAL(x2)}), - Values.ARRAY(valueLst={Values.REAL(y1),Values.REAL(y2)}), - Values.REAL(curveWidth), - Values.INTEGER(curveStyle), - Values.STRING(legendPosition), - Values.STRING(footer), - Values.BOOL(autoScale), - Values.BOOL(forceOMPlot) - }, - st,_) - equation - // get the variables - str = ValuesUtil.printCodeVariableName(cvar) + "\" \"" + ValuesUtil.printCodeVariableName(cvar2); - // get OPENMODELICAHOME - omhome = Settings.getInstallationDirectoryPath(); - // get the simulation filename - (cache,filename) = cevalCurrentSimulationResultExp(cache,env,filename,st,msg); - pd = System.pathDelimiter(); - // create absolute path of simulation result file - str1 = System.pwd() + pd + filename; - s1 = if System.os() == "Windows_NT" then ".exe" else ""; - filename = if System.regularFileExists(str1) then str1 else filename; - // check if plot callback is defined - b = System.plotCallBackDefined(); - if boolOr(forceOMPlot, boolNot(b)) then - // create the path till OMPlot - str2 = stringAppendList({omhome,pd,"bin",pd,"OMPlot",s1}); - // create the list of arguments for OMPlot - str3 = "--filename=\"" + filename + "\" --title=\"" + title + "\" --grid=" + gridStr + " --plotParametric --logx=" + boolString(logX) + " --logy=" + boolString(logY) + " --xlabel=\"" + xLabel + "\" --ylabel=\"" + yLabel + "\" --xrange=" + realString(x1) + ":" + realString(x2) + " --yrange=" + realString(y1) + ":" + realString(y2) + " --new-window=" + boolString(externalWindow) + " --curve-width=" + realString(curveWidth) + " --curve-style=" + intString(curveStyle) + " --legend-position=\"" + legendPosition + "\" --footer=\"" + footer + "\" --auto-scale=" + boolString(autoScale) + " \"" + str + "\""; - call = stringAppendList({"\"",str2,"\""," ",str3}); - 0 = System.spawnCall(str2, call); - elseif b then - logXStr = boolString(logX); - logYStr = boolString(logY); - x1Str = realString(x1); - x2Str = realString(x2); - y1Str = realString(y1); - y2Str = realString(y2); - curveWidthStr = realString(curveWidth); - curveStyleStr = intString(curveStyle); - autoScaleStr = boolString(autoScale); - System.plotCallBack(externalWindow,filename,title,gridStr,"plotparametric",logXStr,logYStr,xLabel,yLabel,x1Str,x2Str,y1Str,y2Str,curveWidthStr,curveStyleStr,legendPosition,footer,autoScaleStr,str); - end if; - then - (cache,Values.BOOL(true),st); - - case (cache,_,"plotParametric",_,st,_) - then (cache,Values.BOOL(false),st); - - case (cache,_,"echo",{v as Values.BOOL(bval)},st,_) - equation - setEcho(bval); - then (cache,v,st); - - case (cache,env,"dumpXMLDAE",vals,st,_) - equation - (cache,st,xml_filename) = dumpXMLDAE(cache,env,vals,st, msg); - then - (cache,ValuesUtil.makeTuple({Values.BOOL(true),Values.STRING(xml_filename)}),st); - - case (cache,_,"dumpXMLDAE",_,st,_) - then - (cache,ValuesUtil.makeTuple({Values.BOOL(false),Values.STRING("")}),st); - - case (cache,_,"solveLinearSystem",{Values.ARRAY(valueLst=vals),v,Values.ENUM_LITERAL(index=1 /*dgesv*/),Values.ARRAY(valueLst={Values.INTEGER(-1)})},st,_) - equation - (realVals,i) = System.dgesv(List.map(vals,ValuesUtil.arrayValueReals),ValuesUtil.arrayValueReals(v)); - v = ValuesUtil.makeArray(List.map(realVals,ValuesUtil.makeReal)); - then (cache,Values.TUPLE({v,Values.INTEGER(i)}),st); - - case (cache,_,"solveLinearSystem",{Values.ARRAY(valueLst=vals),v,Values.ENUM_LITERAL(index=2 /*lpsolve55*/),Values.ARRAY(valueLst=vals2)},st,_) - equation - (realVals,i) = System.lpsolve55(List.map(vals,ValuesUtil.arrayValueReals),ValuesUtil.arrayValueReals(v),List.map(vals2,ValuesUtil.valueInteger)); - v = ValuesUtil.makeArray(List.map(realVals,ValuesUtil.makeReal)); - then (cache,Values.TUPLE({v,Values.INTEGER(i)}),st); - - case (cache,_,"solveLinearSystem",{_,v,_,_},st,_) - equation - Error.addMessage(Error.INTERNAL_ERROR,{"Unknown input to solveLinearSystem scripting function"}); - then (cache,Values.TUPLE({v,Values.INTEGER(-1)}),st); - - case (cache,_,"numProcessors",{},st,_) - equation - i = Config.noProc(); - then (cache,Values.INTEGER(i),st); - - case (cache,_,"runScript",{Values.STRING(str)},st,_) - equation - str = Util.testsuiteFriendlyPath(str); - istmts = Parser.parseexp(str); - (res,newst) = Interactive.evaluate(istmts, st, true); - then - (cache,Values.STRING(res),newst); - - case (cache,_,"runScript",_,st,_) - then (cache,Values.STRING("Failed"),st); - - case (cache,_,"runScriptParallel",{Values.ARRAY(valueLst=vals),Values.INTEGER(i),Values.BOOL(true)},st,_) + case (cache,_,"runScriptParallel",{Values.ARRAY(valueLst=vals),Values.INTEGER(i),Values.BOOL(true)},st,_) equation strs = List.map(vals,ValuesUtil.extractValueString); blst = System.launchParallelTasks(i, List.map1(strs, Util.makeTuple, st), Interactive.evaluateFork); @@ -3501,3693 +1610,895 @@ algorithm v = Values.REAL(r); then (cache,v,st); + else + algorithm + (cache,v,st) := CevalScriptBackend.cevalInteractiveFunctions3(inCache,inEnv,inFunctionName,inVals,inSt,msg); + then (cache,v,st); + end matchcontinue; end cevalInteractiveFunctions2; - -protected function getSimulationExtension -input String inString; -input String inString2; -output String outString; -algorithm - outString:=match(inString,inString2) - local - case ("Cpp","WIN32") - then ".bat"; - case ("Cpp","WIN64") - then ".bat"; - else System.getExeExt(); - end match; - end getSimulationExtension; - - -protected function sconstToString -"@author: adrpo - Transform an DAE.SCONST into a string. - Fails if the given DAE.Exp is not a DAE.SCONST." - input DAE.Exp exp; - output String str; -algorithm - DAE.SCONST(str) := exp; -end sconstToString; - -protected function setEcho - input Boolean echo; +public function evalCodeTypeName + input Values.Value val; + input FCore.Graph env; + output Values.Value res; algorithm - _ := match (echo) + res := matchcontinue (val,env) local - case (true) - equation - Settings.setEcho(1); - then - (); - case (false) + Absyn.Path path; + case (Values.CODE(Absyn.C_TYPENAME(path as Absyn.IDENT(_) /* We only want to lookup idents in the symboltable; also speeds up e.g. simulate(Modelica.A.B.C) so we do not instantiate all classes */)),_) equation - Settings.setEcho(0); - then - (); - end match; -end setEcho; + (_,_,_,DAE.VALBOUND(valBound=res as Values.CODE(A=Absyn.C_TYPENAME())),_,_,_,_,_) = Lookup.lookupVar(FCore.emptyCache(), env, ComponentReference.pathToCref(path)); + then res; + else val; + end matchcontinue; +end evalCodeTypeName; -public function getIncidenceMatrix " author: adrpo - translates a model and returns the incidence matrix" - input FCore.Cache inCache; - input FCore.Graph inEnv; - input Absyn.Path className "path for the model"; - input GlobalScript.SymbolTable inInteractiveSymbolTable; - input Absyn.Msg inMsg; - input String filenameprefix; - output FCore.Cache outCache; - output Values.Value outValue; - output GlobalScript.SymbolTable outInteractiveSymbolTable; - output String outString; +protected function getVariableNames + input list vars; + input list acc; + output list ovars; algorithm - (outCache,outValue,outInteractiveSymbolTable,outString):= - match (inCache,inEnv,className,inInteractiveSymbolTable,inMsg,filenameprefix) + ovars := match (vars,acc) local - String filename,file_dir, str; - list p_1; - DAE.DAElist dae_1,dae; - FCore.Graph env; - list ic_1,ic; - BackendDAE.BackendDAE dlow; - Absyn.ComponentRef a_cref; - GlobalScript.SymbolTable st; - Absyn.Program p; - list iv; - list cf; - Absyn.Msg msg; - FCore.Cache cache; - String flatModelicaStr,description; - - case (cache,env,_,(st as GlobalScript.SYMBOLTABLE(ast = p,instClsLst = ic)),_,_) /* mo file directory */ - equation - p_1 = SCodeUtil.translateAbsyn2SCode(p); - (cache,env,_,dae_1) = - Inst.instantiateClass(cache,InnerOuter.emptyInstHierarchy,p_1,className); - dae = DAEUtil.transformationsBeforeBackend(cache,env,dae_1); - description = DAEUtil.daeDescription(dae); - _ = Interactive.addInstantiatedClass(ic, GlobalScript.INSTCLASS(className,dae,env)); - a_cref = Absyn.pathToCref(className); - file_dir = getFileDir(a_cref, p); - dlow = BackendDAECreate.lower(dae,cache,env,BackendDAE.EXTRA_INFO(description,filenameprefix)); - dlow = FindZeroCrossings.findZeroCrossings(dlow); - flatModelicaStr = DAEDump.dumpStr(dae,FCore.getFunctionTree(cache)); - flatModelicaStr = stringAppend("OldEqStr={'", flatModelicaStr); - flatModelicaStr = System.stringReplace(flatModelicaStr, "\n", "%##%"); - flatModelicaStr = System.stringReplace(flatModelicaStr, "%##%", "','"); - flatModelicaStr = stringAppend(flatModelicaStr,"'};"); - filename = DAEQuery.writeIncidenceMatrix(dlow, filenameprefix, flatModelicaStr); - str = stringAppend("The equation system was dumped to Matlab file:", filename); - then - (cache,Values.STRING(str),st,file_dir); + list vs; + String p; + case ({},_) then listReverse(acc); + case (GlobalScript.IVAR(varIdent = "$echo") :: vs,_) + then getVariableNames(vs,acc); + case (GlobalScript.IVAR(varIdent = p) :: vs,_) + then getVariableNames(vs,Values.CODE(Absyn.C_VARIABLENAME(Absyn.CREF_IDENT(p,{})))::acc); end match; -end getIncidenceMatrix; - -public function runFrontEnd - input FCore.Cache inCache; - input FCore.Graph inEnv; - input Absyn.Path className; - input GlobalScript.SymbolTable inInteractiveSymbolTable; - input Boolean relaxedFrontEnd "Do not check for illegal simulation models, so we allow instantation of packages, etc"; - output FCore.Cache cache; - output FCore.Graph env; - output DAE.DAElist dae; - output GlobalScript.SymbolTable st; -algorithm - // add program to the cache so it can be used to lookup modelica:// - // URIs in external functions IncludeDirectory/LibraryDirectory - st := runFrontEndLoadProgram(className, inInteractiveSymbolTable); - cache := FCore.setProgramInCache(inCache, GlobalScriptUtil.getSymbolTableAST(st)); - if Flags.isSet(Flags.GC_PROF) then - print(GC.profStatsStr(GC.getProfStats(), head="GC stats before front-end:") + "\n"); - end if; - (cache,env,dae,st) := runFrontEndWork(cache,inEnv,className,st,relaxedFrontEnd,Error.getNumErrorMessages()); - if Flags.isSet(Flags.GC_PROF) then - print(GC.profStatsStr(GC.getProfStats(), head="GC stats after front-end:") + "\n"); - end if; -end runFrontEnd; +end getVariableNames; -protected function runFrontEndLoadProgram - input Absyn.Path className; - input GlobalScript.SymbolTable inSt; - output GlobalScript.SymbolTable st; +protected function getPackageVersion + input Absyn.Path path; + input Absyn.Program p; + output String version; algorithm - st := matchcontinue (className, inSt) - local - Absyn.Restriction restriction; - Absyn.Class absynClass; - String str,re; - Option fp; - SCode.Program scodeP, scodePNew, scode_builtin; - list ic,ic_1; - Absyn.Program p,ptot,p_builtin; - list iv; - list cf; - list lf; - DAE.FunctionTree funcs; - Boolean b; - case (_, GlobalScript.SYMBOLTABLE(ast=p)) - equation - _ = Interactive.getPathedClassInProgram(className, p); - then inSt; - case (_, GlobalScript.SYMBOLTABLE(p,fp,ic,iv,cf,lf)) - equation - str = Absyn.pathFirstIdent(className); - (p,b) = loadModel({(Absyn.IDENT(str),{"default"})},Settings.getModelicaPath(Config.getRunningTestsuite()),p,true,true,true,false); - Error.assertionOrAddSourceMessage(not b,Error.NOTIFY_NOT_LOADED,{str,"default"},Absyn.dummyInfo); - // print(stringDelimitList(list(Absyn.pathString(path) for path in Interactive.getTopClassnames(p)), ",") + "\n"); - then GlobalScript.SYMBOLTABLE(p,fp,ic,iv,cf,lf); + version := matchcontinue (path,p) + case (_,_) + equation + Config.setEvaluateParametersInAnnotations(true); + Absyn.STRING(version) = Interactive.getNamedAnnotation(path, p, Absyn.IDENT("version"), SOME(Absyn.STRING("")), Interactive.getAnnotationExp); + Config.setEvaluateParametersInAnnotations(false); + then version; + else ""; end matchcontinue; -end runFrontEndLoadProgram; +end getPackageVersion; -protected function runFrontEndWork - input FCore.Cache inCache; - input FCore.Graph inEnv; - input Absyn.Path className; - input GlobalScript.SymbolTable inInteractiveSymbolTable; - input Boolean relaxedFrontEnd "Do not check for illegal simulation models, so we allow instantation of packages, etc"; - input Integer numError; - output FCore.Cache cache; - output FCore.Graph env; - output DAE.DAElist dae; - output GlobalScript.SymbolTable st; +protected function errorToValue + input Error.TotalMessage err; + output Values.Value val; algorithm - (cache,env,dae,st) := matchcontinue (inCache,inEnv,className,inInteractiveSymbolTable,relaxedFrontEnd,numError) + val := match err local - Absyn.Restriction restriction; - Absyn.Class absynClass; - String str,re; - Option fp; - SCode.Program scodeP, scodePNew, scode_builtin; - list ic,ic_1; - Absyn.Program p,ptot,p_builtin; - list iv; - list cf; - list lf; - DAE.FunctionTree funcs; - - case (cache,env,_,GlobalScript.SYMBOLTABLE(p,fp,ic,iv,cf,lf),_,_) - equation - true = Flags.isSet(Flags.GRAPH_INST); - false = Flags.isSet(Flags.SCODE_INST); - - System.realtimeTick(ClockIndexes.RT_CLOCK_FINST); - str = Absyn.pathString(className); - (absynClass as Absyn.CLASS(restriction = restriction)) = Interactive.getPathedClassInProgram(className, p); - re = Absyn.restrString(restriction); - Error.assertionOrAddSourceMessage(relaxedFrontEnd or not (Absyn.isFunctionRestriction(restriction) or Absyn.isPackageRestriction(restriction)), - Error.INST_INVALID_RESTRICTION,{str,re},Absyn.dummyInfo); - (p,true) = loadModel(Interactive.getUsesAnnotationOrDefault(Absyn.PROGRAM({absynClass},Absyn.TOP()), false),Settings.getModelicaPath(Config.getRunningTestsuite()),p,false,true,true,false); - print("Load deps: " + realString(System.realtimeTock(ClockIndexes.RT_CLOCK_FINST)) + "\n"); - - System.realtimeTick(ClockIndexes.RT_CLOCK_FINST); - scodeP = SCodeUtil.translateAbsyn2SCode(p); - print("Absyn->SCode: " + realString(System.realtimeTock(ClockIndexes.RT_CLOCK_FINST)) + "\n"); - - dae = FInst.instPath(className, scodeP); - ic_1 = ic; - then - (cache,env,dae,GlobalScript.SYMBOLTABLE(p,fp,ic_1,iv,cf,lf)); - - case (_, _, _, GlobalScript.SYMBOLTABLE(p, fp, ic, iv, cf, lf), _, _) + Absyn.Path msgpath; + Values.Value tyVal,severityVal,infoVal; + list values; + Util.TranslatableContent message; + String msg_str; + Integer id; + Error.Severity severity; + Error.MessageType ty; + SourceInfo info; + case Error.TOTALMESSAGE(Error.MESSAGE(id,ty,severity,message),info) equation - false = Flags.isSet(Flags.GRAPH_INST); - true = Flags.isSet(Flags.SCODE_INST); - scodeP = SCodeUtil.translateAbsyn2SCode(p); - // remove extends Modelica.Icons.* - //scodeP = SCodeSimplify.simplifyProgram(scodeP); - - // (_,scode_builtin) = Builtin.getInitialFunctions(); - - // nfenv = NFEnv.buildInitialEnv(scodeP, scode_builtin); - // (dae, funcs) = NFInst.instClass(className, nfenv); - - // cache = FCore.emptyCache(); - // cache = FCore.setCachedFunctionTree(cache, funcs); - // env = FGraph.empty(); - // ic_1 = Interactive.addInstantiatedClass(ic, - // GlobalScript.INSTCLASS(className, dae, env)); - // st = GlobalScript.SYMBOLTABLE(p, fp, ic_1, iv, cf, lf); - _ = NFInst.instClassInProgram(className, scodeP); - - cache = FCore.emptyCache(); - env = FGraph.empty(); - dae = DAE.DAE({}); - st = inInteractiveSymbolTable; - then - (cache, env, dae, st); + msg_str = Util.translateContent(message); + msgpath = Absyn.FULLYQUALIFIED(Absyn.QUALIFIED("OpenModelica",Absyn.QUALIFIED("Scripting",Absyn.IDENT("ErrorMessage")))); + tyVal = errorTypeToValue(ty); + severityVal = errorLevelToValue(severity); + infoVal = infoToValue(info); + values = {infoVal,Values.STRING(msg_str),tyVal,severityVal,Values.INTEGER(id)}; + then Values.RECORD(msgpath,values,{"info","message","kind","level","id"},-1); + end match; +end errorToValue; - case (cache,env,_,GlobalScript.SYMBOLTABLE(p,fp,ic,iv,cf,lf),_,_) +protected function infoToValue + input SourceInfo info; + output Values.Value val; +algorithm + val := match info + local + list values; + Absyn.Path infopath; + Integer ls,cs,le,ce; + String filename; + Boolean readonly; + case SOURCEINFO(filename,readonly,ls,cs,le,ce,_) equation - false = Flags.isSet(Flags.GRAPH_INST); - false = Flags.isSet(Flags.SCODE_INST); - str = Absyn.pathString(className); - (absynClass as Absyn.CLASS(restriction = restriction)) = Interactive.getPathedClassInProgram(className, p); - re = Absyn.restrString(restriction); - Error.assertionOrAddSourceMessage(relaxedFrontEnd or not (Absyn.isFunctionRestriction(restriction) or Absyn.isPackageRestriction(restriction)), - Error.INST_INVALID_RESTRICTION,{str,re},Absyn.dummyInfo); - (p,true) = loadModel(Interactive.getUsesAnnotationOrDefault(Absyn.PROGRAM({absynClass},Absyn.TOP()), false),Settings.getModelicaPath(Config.getRunningTestsuite()),p,false,true,true,false); - - //System.stopTimer(); - //print("\nExists+Dependency: " + realString(System.getTimerIntervalTime())); - - //System.startTimer(); - //print("\nAbsyn->SCode"); - - scodeP = SCodeUtil.translateAbsyn2SCode(p); - - // TODO: Why not simply get the whole thing from the cached SCode? It's faster, just need to stop doing the silly Dependency stuff. - - //System.stopTimer(); - //print("\nAbsyn->SCode: " + realString(System.getTimerIntervalTime())); - - //System.startTimer(); - //print("\nInst.instantiateClass"); - (cache,env,_,dae) = Inst.instantiateClass(cache,InnerOuter.emptyInstHierarchy,scodeP,className); - - FGraphDump.dumpGraph(env, "F:\\dev\\" + Absyn.pathString(className) + ".graph.graphml"); - - //System.stopTimer(); - //print("\nInst.instantiateClass: " + realString(System.getTimerIntervalTime())); + infopath = Absyn.FULLYQUALIFIED(Absyn.QUALIFIED("OpenModelica",Absyn.QUALIFIED("Scripting",Absyn.IDENT("SourceInfo")))); + values = {Values.STRING(filename),Values.BOOL(readonly),Values.INTEGER(ls),Values.INTEGER(cs),Values.INTEGER(le),Values.INTEGER(ce)}; + then Values.RECORD(infopath,values,{"filename","readonly","lineStart","columnStart","lineEnd","columnEnd"},-1); + end match; +end infoToValue; - // adrpo: do not add it to the instantiated classes, it just consumes memory for nothing. - ic_1 = ic; - // ic_1 = Interactive.addInstantiatedClass(ic, GlobalScript.INSTCLASS(className,dae,env)); - _ = DAEUtil.getFunctionList(FCore.getFunctionTree(cache)); // Make sure that the functions are valid before returning success - then (cache,env,dae,GlobalScript.SYMBOLTABLE(p,fp,ic_1,iv,cf,lf)); +protected function makeErrorEnumLiteral + input String enumName; + input String enumField; + input Integer index; + output Values.Value val; + annotation(__OpenModelica_EarlyInline=true); +algorithm + val := Values.ENUM_LITERAL(Absyn.FULLYQUALIFIED(Absyn.QUALIFIED("OpenModelica",Absyn.QUALIFIED("Scripting",Absyn.QUALIFIED(enumName,Absyn.IDENT(enumField))))),index); +end makeErrorEnumLiteral; - case (cache,env,_,st as GlobalScript.SYMBOLTABLE(ast=p),_,_) +protected function errorTypeToValue + input Error.MessageType ty; + output Values.Value val; +algorithm + val := match ty + case Error.SYNTAX() then makeErrorEnumLiteral("ErrorKind","syntax",1); + case Error.GRAMMAR() then makeErrorEnumLiteral("ErrorKind","grammar",2); + case Error.TRANSLATION() then makeErrorEnumLiteral("ErrorKind","translation",3); + case Error.SYMBOLIC() then makeErrorEnumLiteral("ErrorKind","symbolic",4); + case Error.SIMULATION() then makeErrorEnumLiteral("ErrorKind","runtime",5); + case Error.SCRIPTING() then makeErrorEnumLiteral("ErrorKind","scripting",6); + else equation - str = Absyn.pathString(className); - failure(_ = Interactive.getPathedClassInProgram(className, p)); - Error.addMessage(Error.LOOKUP_ERROR, {str,""}); + print("errorTypeToValue failed\n"); then fail(); + end match; +end errorTypeToValue; +protected function errorLevelToValue + input Error.Severity severity; + output Values.Value val; +algorithm + val := match severity + case Error.ERROR() then makeErrorEnumLiteral("ErrorLevel","error",1); + case Error.WARNING() then makeErrorEnumLiteral("ErrorLevel","warning",2); + case Error.NOTIFICATION() then makeErrorEnumLiteral("ErrorLevel","notification",3); else equation - str = Absyn.pathString(className); - true = Error.getNumErrorMessages() == numError; - str = "Instantiation of " + str + " failed with no error message."; - Error.addMessage(Error.INTERNAL_ERROR, {str}); + print("errorLevelToValue failed\n"); then fail(); - end matchcontinue; -end runFrontEndWork; + end match; +end errorLevelToValue; -protected function translateModel " author: x02lucpo - translates a model into cpp code and writes also a makefile" - input FCore.Cache inCache; - input FCore.Graph inEnv; - input Absyn.Path className "path for the model"; - input GlobalScript.SymbolTable inInteractiveSymbolTable; - input String inFileNamePrefix; - input Boolean addDummy "if true, add a dummy state"; - input Option inSimSettingsOpt; - output FCore.Cache outCache; - output GlobalScript.SymbolTable outInteractiveSymbolTable; - output BackendDAE.BackendDAE outBackendDAE; - output list outStringLst; - output String outFileDir; - output list> resultValues; +protected function generateFunctionName +"@author adrpo: + generate the function name from a path." + input Absyn.Path functionPath; + output String functionName; algorithm - (outCache,outInteractiveSymbolTable,outBackendDAE,outStringLst,outFileDir,resultValues):= - match (inCache,inEnv,className,inInteractiveSymbolTable,inFileNamePrefix,addDummy,inSimSettingsOpt) - local - FCore.Cache cache; - FCore.Graph env; - BackendDAE.BackendDAE indexed_dlow; - GlobalScript.SymbolTable st; - list libs; - String file_dir, fileNamePrefix; - Absyn.Program p; + functionName := Absyn.pathStringUnquoteReplaceDot(functionPath, "_"); +end generateFunctionName; - case (cache,env,_,st as GlobalScript.SYMBOLTABLE(),fileNamePrefix,_,_) +protected function generateFunctionFileName +"@author adrpo: + generate the function name from a path." + input Absyn.Path functionPath; + output String functionName; +algorithm + functionName := matchcontinue(functionPath) + local String name, n1, n2; Integer len; + case (_) + equation + name = Absyn.pathStringUnquoteReplaceDot(functionPath, "_"); + len = stringLength(name); + // not bigger than + true = len > Global.maxFunctionFileLength; + n1 = Absyn.pathFirstIdent(functionPath); + n2 = Absyn.pathLastIdent(functionPath); + name = System.unquoteIdentifier(n1 + "_" + n2); + name = name + "_" + intString(tick()); + then + name; + else equation - (cache, st, indexed_dlow, libs, file_dir, resultValues) = - SimCodeMain.translateModel(cache,env,className,st,fileNamePrefix,addDummy,inSimSettingsOpt,Absyn.FUNCTIONARGS({},{})); + name = Absyn.pathStringUnquoteReplaceDot(functionPath, "_"); then - (cache,st,indexed_dlow,libs,file_dir,resultValues); + name; + end matchcontinue; +end generateFunctionFileName; - end match; -end translateModel; +public function getFunctionDependencies +"returns all function dependencies as paths, also the main function and the function tree" + input FCore.Cache cache; + input Absyn.Path functionName; + output DAE.Function mainFunction "the main function"; + output list dependencies "the dependencies as paths"; + output DAE.FunctionTree funcs "the function tree"; +algorithm + funcs := FCore.getFunctionTree(cache); + // First check if the main function exists... If it does not it might be an interactive function... + mainFunction := DAEUtil.getNamedFunction(functionName, funcs); + dependencies := SimCodeFunction.getCalledFunctionsInFunction(functionName,funcs); +end getFunctionDependencies; -/*protected function translateModelCPP " author: x02lucpo - translates a model into cpp code and writes also a makefile" +public function collectDependencies +"collects all function dependencies, also the main function, uniontypes, metarecords" input FCore.Cache inCache; - input FCore.Graph inEnv; - input Absyn.Path className "path for the model"; - input GlobalScript.SymbolTable inInteractiveSymbolTable; - input String inFileNamePrefix; - input Boolean addDummy "if true, add a dummy state"; - input Option inSimSettingsOpt; + input FCore.Graph env; + input Absyn.Path functionName; output FCore.Cache outCache; - output Values.Value outValue; - output GlobalScript.SymbolTable outInteractiveSymbolTable; - output BackendDAE.BackendDAE outBackendDAE; - output list outStringLst; - output String outFileDir; - output list> resultValues; + output DAE.Function mainFunction; + output list dependencies; + output list metarecordTypes; +protected + list uniontypePaths,paths; + DAE.FunctionTree funcs; algorithm - (outCache,outValue,outInteractiveSymbolTable,outBackendDAE,outStringLst,outFileDir,resultValues):= - match (inCache,inEnv,className,inInteractiveSymbolTable,inFileNamePrefix,addDummy,inSimSettingsOpt) - local - FCore.Cache cache; - FCore.Graph env; - BackendDAE.BackendDAE indexed_dlow; - GlobalScript.SymbolTable st; - list libs; - Values.Value outValMsg; - String file_dir, fileNamePrefix; - - case (cache,env,className,st,fileNamePrefix,addDummy,inSimSettingsOpt) - equation - (cache, outValMsg, st, indexed_dlow, libs, file_dir, resultValues) = - SimCodeUtil.translateModelCPP(cache,env,className,st,fileNamePrefix,addDummy,inSimSettingsOpt); - then - (cache,outValMsg,st,indexed_dlow,libs,file_dir,resultValues); - end match; -end translateModelCPP;*/ + (mainFunction, paths, funcs) := getFunctionDependencies(inCache, functionName); + // The list of functions is not ordered, so we need to filter out the main function... + dependencies := List.map1(paths, DAEUtil.getNamedFunction, funcs); + dependencies := List.setDifference(dependencies, {mainFunction}); + uniontypePaths := DAEUtil.getUniontypePaths(dependencies,{}); + (outCache,metarecordTypes) := Lookup.lookupMetarecordsRecursive(inCache, env, uniontypePaths); +end collectDependencies; -protected function translateModelFMU " author: Frenkel TUD - translates a model into cpp code and writes also a makefile" +public function cevalGenerateFunction "Generates code for a given function name." input FCore.Cache inCache; input FCore.Graph inEnv; - 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 inSimSettingsOpt; + input Absyn.Program program; + input Absyn.Path inPath; output FCore.Cache outCache; - output Values.Value outValue; - output GlobalScript.SymbolTable outInteractiveSymbolTable; + output String functionName; + output String functionFileName; algorithm - (outCache,outValue,outInteractiveSymbolTable):= - match (inCache,inEnv,className,inInteractiveSymbolTable,inFMUVersion,inFMUType,inFileNamePrefix,addDummy,inSimSettingsOpt) + (outCache,functionName,functionFileName) := matchcontinue (inCache,inEnv,program,inPath) local - FCore.Cache cache; + String pathstr, fileName; FCore.Graph env; - BackendDAE.BackendDAE indexed_dlow; - GlobalScript.SymbolTable st; - list libs; - Values.Value outValMsg; - String file_dir, FMUVersion, FMUType, fileNamePrefix, str; - case (cache,env,_,st,FMUVersion,FMUType,fileNamePrefix,_,_) /* mo file directory */ + Absyn.Path path; + FCore.Cache cache; + DAE.Function mainFunction; + list d; + list metarecordTypes; + DAE.FunctionTree funcs; + // template based translation + case (cache, env, _, path) equation - (cache, outValMsg, st,_, libs,_, _) = - SimCodeMain.translateModelFMU(cache,env,className,st,FMUVersion,FMUType,fileNamePrefix,addDummy,inSimSettingsOpt); + true = Flags.isSet(Flags.GEN); + false = Flags.isSet(Flags.GENERATE_CODE_CHEAT); - // compile - fileNamePrefix = stringAppend(fileNamePrefix,"_FMU"); - compileModel(fileNamePrefix , libs); + (cache, mainFunction, d, metarecordTypes) = collectDependencies(cache, env, path); + pathstr = generateFunctionName(path); + fileName = generateFunctionFileName(path); + SimCodeFunction.translateFunctions(program, fileName, SOME(mainFunction), d, metarecordTypes, {}); + compileModel(fileName, {}); then - (cache,outValMsg,st); - else /* mo file directory */ + (cache, pathstr, fileName); + + // Cheat if we want to generate code for Main.main + // * Don't do dependency analysis of what functions to generate; just generate all of them + // * Don't generate extra code for unreferenced MetaRecord types (for external functions) + // This could be an annotation instead anyway. + // * Don't compile the generated files + case (cache, _, _, path) equation - str = Error.printMessagesStr(false); + true = Flags.isSet(Flags.GEN); + true = Flags.isSet(Flags.GENERATE_CODE_CHEAT); + funcs = FCore.getFunctionTree(cache); + // First check if the main function exists... If it does not it might be an interactive function... + pathstr = generateFunctionName(path); + fileName = generateFunctionFileName(path); + // The list of functions is not ordered, so we need to filter out the main function... + d = DAEUtil.getFunctionList(funcs); + SimCodeFunction.translateFunctions(program, fileName, NONE(), d, {}, {}); then - (inCache,ValuesUtil.makeArray({Values.STRING("translateModelFMU error."),Values.STRING(str)}),inInteractiveSymbolTable); - end match; -end translateModelFMU; - + (cache, pathstr, fileName); -protected function translateModelXML " author: Alachew - translates a model into XML code " - input FCore.Cache inCache; - input FCore.Graph inEnv; - input Absyn.Path className "path for the model"; - input GlobalScript.SymbolTable inInteractiveSymbolTable; - input String inFileNamePrefix; - input Boolean addDummy "if true, add a dummy state"; - input Option inSimSettingsOpt; - output FCore.Cache outCache; - output Values.Value outValue; - output GlobalScript.SymbolTable outInteractiveSymbolTable; -algorithm - (outCache,outValue,outInteractiveSymbolTable):= - match (inCache,inEnv,className,inInteractiveSymbolTable,inFileNamePrefix,addDummy,inSimSettingsOpt) - local - FCore.Cache cache; - FCore.Graph env; - BackendDAE.BackendDAE indexed_dlow; - GlobalScript.SymbolTable st; - list libs; - Values.Value outValMsg; - String file_dir, fileNamePrefix, str; - case (cache,env,_,st,fileNamePrefix,_,_) /* mo file directory */ - equation - (cache, outValMsg, st,_,_,_, _) = - SimCodeMain.translateModelXML(cache,env,className,st,fileNamePrefix,addDummy,inSimSettingsOpt); - then - (cache,outValMsg,st); - else /* mo file directory */ + case (cache, env, _, path) equation - str = Error.printMessagesStr(false); + true = Flags.isSet(Flags.GEN); + true = Flags.isSet(Flags.FAILTRACE); + (cache,false) = Static.isExternalObjectFunction(cache,env,path); + pathstr = generateFunctionName(path); + fileName = generateFunctionFileName(path); + Debug.trace("CevalScript.cevalGenerateFunction failed:\nfunction: " + pathstr + "\nfile: " + fileName + "\n"); then - (inCache,ValuesUtil.makeArray({Values.STRING("translateModelXML error."),Values.STRING(str)}),inInteractiveSymbolTable); - end match; -end translateModelXML; - + fail(); + end matchcontinue; +end cevalGenerateFunction; -public function translateGraphics "function: translates the graphical annotations from old to new version" - input FCore.Cache inCache; - input FCore.Graph inEnv; - input Absyn.Path className; - input GlobalScript.SymbolTable inInteractiveSymbolTable; - input Absyn.Msg inMsg; - output FCore.Cache outCache; - output Values.Value outValue; - output GlobalScript.SymbolTable outInteractiveSymbolTable; +protected function matchQualifiedCalls +"Collects the packages used by the functions" + input DAE.Exp e; + input list acc; + output DAE.Exp outExp; + output list outAcc; algorithm - (outCache,outValue,outInteractiveSymbolTable) := - matchcontinue (inCache,inEnv,className,inInteractiveSymbolTable,inMsg) + (outExp,outAcc) := match (e,acc) local - FCore.Graph env; - list ic; - GlobalScript.SymbolTable st; - Absyn.Program p; - list iv; - list cf; - Absyn.Msg msg; - FCore.Cache cache; - list lf; - String errorMsg,retStr,s1; - Absyn.Class cls, refactoredClass; - Absyn.Within within_; - Absyn.Program p1; - Boolean strEmpty; - - case (cache,_,_,(GlobalScript.SYMBOLTABLE(p as Absyn.PROGRAM(),_,ic,iv,cf,lf)),_) + String name; + DAE.ComponentRef cr; + case (DAE.CALL(path = Absyn.FULLYQUALIFIED(Absyn.QUALIFIED(name=name)), attr = DAE.CALL_ATTR(builtin = false)),_) equation - cls = Interactive.getPathedClassInProgram(className, p); - refactoredClass = Refactor.refactorGraphicalAnnotation(p, cls); - within_ = Interactive.buildWithin(className); - p1 = Interactive.updateProgram(Absyn.PROGRAM({refactoredClass}, within_), p); - s1 = Absyn.pathString(className); - retStr=stringAppendList({"Translation of ",s1," successful.\n"}); - then - (cache,Values.STRING(retStr),GlobalScript.SYMBOLTABLE(p1,NONE(),ic,iv,cf,lf)); - - case (cache,_,_,st,_) + outAcc = List.consOnTrue(not listMember(name,acc),name,acc); + then (e,outAcc); + case (DAE.CREF(componentRef=cr,ty=DAE.T_FUNCTION_REFERENCE_FUNC(builtin=false)),_) equation - errorMsg = Error.printMessagesStr(false); - strEmpty = (stringCompare("",errorMsg)==0); - errorMsg = if strEmpty then "Internal error, translating graphics to new version" else errorMsg; - then - (cache,Values.STRING(errorMsg),st); - end matchcontinue; -end translateGraphics; - + Absyn.QUALIFIED(name,Absyn.IDENT(_)) = ComponentReference.crefToPath(cr); + outAcc = List.consOnTrue(not listMember(name,acc),name,acc); + then (e,outAcc); + else (e,acc); + end match; +end matchQualifiedCalls; -protected function calculateSimulationSettings " author: x02lucpo - calculates the start,end,interval,stepsize, method and initFileName" - input FCore.Cache inCache; - input FCore.Graph inEnv; - input list vals; - input GlobalScript.SymbolTable inInteractiveSymbolTable; - input Absyn.Msg inMsg; +protected function instantiateDaeFunctions + input FCore.Cache icache; + input FCore.Graph ienv; + input list ipaths; output FCore.Cache outCache; - output SimCode.SimulationSettings outSimSettings; algorithm - (outCache,outSimSettings):= - match (inCache,inEnv,vals,inInteractiveSymbolTable,inMsg) + outCache := match (icache,ienv,ipaths) local - String method_str,options_str,outputFormat_str,variableFilter_str,s; - GlobalScript.SymbolTable st; - Values.Value starttime_v,stoptime_v,tolerance_v; - Integer interval_i; - Real starttime_r,stoptime_r,tolerance_r; - FCore.Graph env; - Absyn.Msg msg; - FCore.Cache cache; - String cflags,simflags; - case (cache,_,{Values.CODE(Absyn.C_TYPENAME(_)),starttime_v,stoptime_v,Values.INTEGER(interval_i),tolerance_v,Values.STRING(method_str),_,Values.STRING(options_str),Values.STRING(outputFormat_str),Values.STRING(variableFilter_str),Values.STRING(cflags),Values.STRING(_)}, - (GlobalScript.SYMBOLTABLE()),_) - equation - starttime_r = ValuesUtil.valueReal(starttime_v); - stoptime_r = ValuesUtil.valueReal(stoptime_v); - tolerance_r = ValuesUtil.valueReal(tolerance_v); - outSimSettings = SimCodeMain.createSimulationSettings(starttime_r,stoptime_r,interval_i,tolerance_r,method_str,options_str,outputFormat_str,variableFilter_str,cflags); - then - (cache, outSimSettings); - else + Absyn.Path path; + FCore.Cache cache; FCore.Graph env; + list paths; + case (cache,_,{}) then cache; + case (cache,env,path::paths) equation - s = "CevalScript.calculateSimulationSettings failed: " + ValuesUtil.valString(Values.TUPLE(vals)); - Error.addMessage(Error.INTERNAL_ERROR, {s}); - then - fail(); + // print("force inst: " + Absyn.pathString(path)); + (cache,Util.SUCCESS()) = Static.instantiateDaeFunctionForceInst(cache,env,path,false,NONE(),true); + // print(" ok\n"); + cache = instantiateDaeFunctions(cache,env,paths); + then cache; end match; -end calculateSimulationSettings; - -protected function getListFirstShowError -"@author: adrpo - return the first element in the list and the rest of values. - if the list is empty display the errorMessage!" - input list inValues; - input String errorMessage; - output Values.Value outValue; - output list restValues; +end instantiateDaeFunctions; + +protected function generateFunctions + input FCore.Cache icache; + input FCore.Graph ienv; + input Absyn.Program p; + input list isp; + input Boolean cleanCache; + output FCore.Cache cache; + output FCore.Graph env; algorithm - (outValue, restValues) := match(inValues, errorMessage) + (cache,env) := match (icache,ienv,p,isp,cleanCache) local - Values.Value v; - list rest; - - // everything is fine and dandy - case (v::rest, _) then (v, rest); + String name; + list names,dependencies; + list paths; + list elementLst; + DAE.FunctionTree funcs; + list d; + list>> acc; + list sp; + String file,nameHeader,str; + Integer n; + SourceInfo info; + SCode.Element cl; - // ups, we're missing an argument - case ({}, _) + case (cache,env,_,{},_) then (cache,env); + case (cache,env,_,(cl as SCode.CLASS(name=name,encapsulatedPrefix=SCode.ENCAPSULATED(),restriction=SCode.R_PACKAGE(),classDef=SCode.PARTS(elementLst=elementLst),info=info))::sp,_) equation - Error.addMessage(Error.INTERNAL_ERROR, {errorMessage}); - then - fail(); + (cache,env) = generateFunctions2(cache,env,p,cl,name,elementLst,info,cleanCache); + (cache,env) = generateFunctions(cache,env,p,sp,cleanCache); + then (cache,env); + case (cache,env,_,SCode.CLASS(encapsulatedPrefix=SCode.NOT_ENCAPSULATED(),name=name,info=info as SOURCEINFO(fileName=file))::_,_) + equation + (n,_) = System.regex(file, "ModelicaBuiltin.mo$", 1, false, false); + Error.assertion(n > 0, "Not an encapsulated class (required for separate compilation): " + name, info); + then fail(); end match; -end getListFirstShowError; - -protected function getListNthShowError -"@author: adrpo - return the N-th element in the list and the rest of values. - if the list is empty display the errorMessage!" - input list inValues; - input String errorMessage; - input Integer currentElement; - input Integer nthElement; - output Values.Value outValue; +end generateFunctions; + +protected function generateFunctions2 + input FCore.Cache icache; + input FCore.Graph ienv; + input Absyn.Program p; + input SCode.Element cl; + input String name; + input list elementLst; + input SourceInfo info; + input Boolean cleanCache; + output FCore.Cache cache; + output FCore.Graph env; algorithm - outValue := matchcontinue(inValues, errorMessage, currentElement, nthElement) + (cache,env) := matchcontinue (icache,ienv,p,cl,name,elementLst,info,cleanCache) local - Values.Value v; - list lst,rest; - Integer i,n; + list names,dependencies,strs; + list paths; + DAE.FunctionTree funcs; + list d; + list>> acc; + list sp; + String file,nameHeader,str; + Integer n; - // everything is fine and dandy - case (lst, _, i, n) + case (cache,env,_,_,_,_,SOURCEINFO(fileName=file),_) equation - true = i < n; - (_,rest) = getListFirstShowError(lst,errorMessage); - v = getListNthShowError(rest,errorMessage, i+1, n); - then v; + (1,_) = System.regex(file, "ModelicaBuiltin.mo$", 1, false, false); + then (cache,env); - // everything is fine and dandy - case (lst, _, _, _) + case (cache,env,_,_,_,_,_,_) equation - (v, _) = getListFirstShowError(lst,errorMessage); - then v; - + cache = if cleanCache then FCore.emptyCache() else cache; + paths = List.fold1(elementLst, findFunctionsToCompile, Absyn.FULLYQUALIFIED(Absyn.IDENT(name)), {}); + cache = instantiateDaeFunctions(cache, env, paths); + funcs = FCore.getFunctionTree(cache); + d = List.map2(paths, DAEUtil.getNamedFunctionWithError, funcs, info); + (_,(_,dependencies)) = DAEUtil.traverseDAEFunctions(d,Expression.traverseSubexpressionsHelper,(matchQualifiedCalls,{}),{}); + // print(name + " has dependencies: " + stringDelimitList(dependencies,",") + "\n"); + dependencies = List.sort(dependencies,Util.strcmpBool); + dependencies = List.map1(dependencies,stringAppend,".h"); + nameHeader = name + ".h"; + strs = List.map1r(nameHeader::dependencies, stringAppend, "$(GEN_DIR)"); + System.writeFile(name + ".deps", "$(GEN_DIR)" + name + ".o: $(GEN_DIR)" + name + ".c" + " " + stringDelimitList(strs," ")); + dependencies = List.map1(dependencies,stringAppend,"\""); + dependencies = List.map1r(dependencies,stringAppend,"#include \""); + SimCodeFunction.translateFunctions(p, name, NONE(), d, {}, dependencies); + str = Tpl.tplString(Unparsing.programExternalHeader, {cl}); + System.writeFile(name + "_records.c","#include \n" + str); + cache = if cleanCache then icache else cache; + then (cache,env); + else + equation + Error.addSourceMessage(Error.SEPARATE_COMPILATION_PACKAGE_FAILED,{name},info); + then fail(); end matchcontinue; -end getListNthShowError; +end generateFunctions2; -protected function moveClass - input Absyn.Path inClassName; - input String inDirection; - input Absyn.Program inProg; - output Absyn.Program outProg; +protected function findFunctionsToCompile + input SCode.Element elt; + input Absyn.Path pathPrefix; + input list acc; + output list paths; algorithm - outProg := match(inClassName, inDirection, inProg) + paths := match (elt,pathPrefix,acc) local - Absyn.Path c, parent; - Absyn.Program p; - list cls; - Absyn.Within w; + Absyn.Path p; String name; - Absyn.Class parentparentClass; - - case (Absyn.FULLYQUALIFIED(c), _, _) + list elts; + case (SCode.CLASS(name=name, partialPrefix=SCode.NOT_PARTIAL(), restriction=SCode.R_FUNCTION(_), classDef=SCode.PARTS(elementLst=elts)),_,_) equation - p = moveClass(c, inDirection, inProg); - then - p; - - case (Absyn.IDENT(name), _, p as Absyn.PROGRAM()) + p = Absyn.joinPaths(pathPrefix,Absyn.IDENT(name)); + paths = List.fold1(elts,findFunctionsToCompile,Absyn.joinPaths(pathPrefix,Absyn.IDENT(name)),acc); + then p::paths; + case (SCode.CLASS(name=name, partialPrefix=SCode.NOT_PARTIAL(), classDef=SCode.PARTS(elementLst=elts)),_,_) equation - p.classes = moveClassInList(name, p.classes, inDirection); - then p; - - case (Absyn.QUALIFIED(_, _), _, p) + paths = List.fold1(elts,findFunctionsToCompile,Absyn.joinPaths(pathPrefix,Absyn.IDENT(name)),acc); + then paths; + // Derived classes, class extends + case (SCode.CLASS(name=name, partialPrefix=SCode.NOT_PARTIAL(), restriction=SCode.R_FUNCTION(_)),_,_) equation - parent = Absyn.stripLast(inClassName); - _ = Interactive.getPathedClassInProgram(parent, p); - then - p; - - end match; -end moveClass; - -protected function moveClassInList - input String inClassName; - input list inCls; - input String inDirection; - output list outCls; -algorithm - outCls := inCls; -end moveClassInList; - -protected function copyClass - input Absyn.Class inClass; - input String inName; - input Absyn.Within inWithin; - input Absyn.Program inProg; - output Absyn.Program outProg; -algorithm - outProg := match(inClass, inName, inWithin, inProg) - local - Absyn.Within within_; - Absyn.Program p, newp; - String name, newName; - Boolean partialPrefix,finalPrefix,encapsulatedPrefix; - Absyn.Restriction restriction; - Absyn.ClassDef classDef; - case (Absyn.CLASS(partialPrefix = partialPrefix,finalPrefix = finalPrefix,encapsulatedPrefix = encapsulatedPrefix,restriction = restriction, - body = classDef), newName, within_, p) - equation - newp = Interactive.updateProgram(Absyn.PROGRAM({Absyn.CLASS(newName, partialPrefix, finalPrefix, encapsulatedPrefix, restriction, classDef, Absyn.dummyInfo)}, - within_), p); - then newp; + p = Absyn.joinPaths(pathPrefix,Absyn.IDENT(name)); + then p::acc; + else acc; end match; -end copyClass; +end findFunctionsToCompile; -protected function buildModel "translates and builds the model by running compiler script on the generated makefile" +public function cevalCallFunction "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 FCore.Cache inCache; input FCore.Graph inEnv; - input list inValues; - input GlobalScript.SymbolTable inInteractiveSymbolTable; + input DAE.Exp inExp; + input list inValuesValueLst; + input Boolean impl; + input Option inSymTab; input Absyn.Msg inMsg; + input Integer numIter; output FCore.Cache outCache; - output GlobalScript.SymbolTable outInteractiveSymbolTable3; - output String compileDir; - output String outString1 "className"; - output String outString2 "method"; - output String outputFormat_str; - output String outInitFileName "initFileName"; - output String outSimFlags; - output list> resultValues; + output Values.Value outValue; + output Option outSymTab; algorithm - (outCache,outInteractiveSymbolTable3,compileDir,outString1,outString2,outputFormat_str,outInitFileName,outSimFlags,resultValues):= - matchcontinue (inCache,inEnv,inValues,inInteractiveSymbolTable,inMsg) + (outCache,outValue,outSymTab) := matchcontinue (inCache,inEnv,inExp,inValuesValueLst,impl,inSymTab,inMsg,numIter) local - GlobalScript.SymbolTable st,st_1,st2; - BackendDAE.BackendDAE indexed_dlow_1; - list libs; - String file_dir,init_filename,method_str,filenameprefix,exeFile,s3,simflags; - Absyn.Path classname; - Absyn.Program p; - Absyn.Class cdef; - Real edit,build,globalEdit,globalBuild,timeCompile; + Values.Value newval; FCore.Graph env; - SimCode.SimulationSettings simSettings; - Values.Value starttime,stoptime,interval,tolerance,method,options,outputFormat,variableFilter; - list vals, values; + DAE.Exp e; + Absyn.Path funcpath; + list expl; + list vallst, pubVallst, proVallst; Absyn.Msg msg; FCore.Cache cache; - Boolean existFile; - - // compile the model - case (cache,env,vals,st,msg) - equation - // buildModel expects these arguments: - // className, startTime, stopTime, numberOfIntervals, tolerance, method, fileNamePrefix, - // options, outputFormat, variableFilter, cflags, simflags - values = vals; - (Values.CODE(Absyn.C_TYPENAME(classname)),vals) = getListFirstShowError(vals, "while retreaving the className (1 arg) from the buildModel arguments"); - (_,vals) = getListFirstShowError(vals, "while retreaving the startTime (2 arg) from the buildModel arguments"); - (_,vals) = getListFirstShowError(vals, "while retreaving the stopTime (3 arg) from the buildModel arguments"); - (_,vals) = getListFirstShowError(vals, "while retreaving the numberOfIntervals (4 arg) from the buildModel arguments"); - (_,vals) = getListFirstShowError(vals, "while retreaving the tolerance (5 arg) from the buildModel arguments"); - (_,vals) = getListFirstShowError(vals, "while retreaving the method (6 arg) from the buildModel arguments"); - (Values.STRING(filenameprefix),vals) = getListFirstShowError(vals, "while retreaving the fileNamePrefix (7 arg) from the buildModel arguments"); - (_,vals) = getListFirstShowError(vals, "while retreaving the options (8 arg) from the buildModel arguments"); - (_,vals) = getListFirstShowError(vals, "while retreaving the outputFormat (9 arg) from the buildModel arguments"); - (_,vals) = getListFirstShowError(vals, "while retreaving the variableFilter (10 arg) from the buildModel arguments"); - (_,vals) = getListFirstShowError(vals, "while retreaving the cflags (11 arg) from the buildModel arguments"); - (Values.STRING(simflags),vals) = getListFirstShowError(vals, "while retreaving the simflags (12 arg) from the buildModel arguments"); - - Error.clearMessages() "Clear messages"; - compileDir = System.pwd() + System.pathDelimiter(); - (cache,simSettings) = calculateSimulationSettings(cache, env, values, st, msg); - SimCode.SIMULATION_SETTINGS(method = method_str, outputFormat = outputFormat_str) - = simSettings; - - (cache,st as GlobalScript.SYMBOLTABLE(),_,libs,file_dir,resultValues) = translateModel(cache,env, classname, st, filenameprefix,true, SOME(simSettings)); - //cname_str = Absyn.pathString(classname); - //SimCodeUtil.generateInitData(indexed_dlow_1, classname, filenameprefix, init_filename, - // starttime_r, stoptime_r, interval_r, tolerance_r, method_str,options_str,outputFormat_str); + Option st; + Absyn.Path complexName; + list pubVarLst, proVarLst, varLst; + list pubVarNames, proVarNames, varNames; + DAE.Type ty; + SourceInfo info; + String str; + Boolean bIsCompleteFunction; - System.realtimeTick(ClockIndexes.RT_CLOCK_BUILD_MODEL); - init_filename = filenameprefix + "_init.xml"; //a hack ? should be at one place somewhere - //win1 = getWithinStatement(classname); + // External functions that are "known" should be evaluated without compilation, e.g. all math functions + case (cache,env,(DAE.CALL(path = funcpath)),vallst,_,st,msg,_) + equation + (cache,newval) = Ceval.cevalKnownExternalFuncs(cache,env, funcpath, vallst, msg); + then + (cache,newval,st); - if Flags.isSet(Flags.DYN_LOAD) then - Debug.traceln("buildModel: about to compile model " + filenameprefix + ", " + file_dir); - end if; - compileModel(filenameprefix, libs); - if Flags.isSet(Flags.DYN_LOAD) then - Debug.trace("buildModel: Compiling done.\n"); - end if; - // p = setBuildTime(p,classname); - st2 = st;// Interactive.replaceSymbolTableProgram(st,p); - timeCompile = System.realtimeTock(ClockIndexes.RT_CLOCK_BUILD_MODEL); - resultValues = ("timeCompile",Values.REAL(timeCompile)) :: resultValues; + // This case prevents the constructor call of external objects of being evaluated + case (cache,env,(DAE.CALL(path = funcpath)),_,_,_,msg,_) + equation + true = FGraph.isNotEmpty(env); + cevalIsExternalObjectConstructor(cache,funcpath,env,msg); then - (cache,st2,compileDir,filenameprefix,method_str,outputFormat_str,init_filename,simflags,resultValues); + fail(); - // failure - else + // Record constructors + case(cache,env,(DAE.CALL(path = funcpath,attr = DAE.CALL_ATTR(ty = DAE.T_COMPLEX(complexClassType = ClassInf.RECORD(complexName), varLst=varLst)))),pubVallst,_,st,msg,_) equation - Error.assertion(listLength(inValues) == 12, "buildModel failure, length = " + intString(listLength(inValues)), Absyn.dummyInfo); - then fail(); - end matchcontinue; -end buildModel; - -protected function createSimulationResultFromcallModelExecutable -"This function calls the compiled simulation executable." - input Integer callRet; - input Real timeTotal; - input Real timeSimulation; - input list> resultValues; - input FCore.Cache inCache; - input Absyn.Path className; - input list inVals; - input GlobalScript.SymbolTable inSt; - input String result_file; - input String logFile; - output FCore.Cache outCache; - output Values.Value outValue; - output GlobalScript.SymbolTable outInteractiveSymbolTable; -algorithm - (outCache,outValue,outInteractiveSymbolTable) := matchcontinue (callRet,timeTotal,timeSimulation,resultValues,inCache,className,inVals,inSt,result_file,logFile) - local - GlobalScript.SymbolTable newst; - String res,str; - Values.Value simValue; - - case (0,_,_,_,_,_,_,_,_,_) - equation - simValue = createSimulationResult( - result_file, - simOptionsAsString(inVals), - System.readFile(logFile), - ("timeTotal", Values.REAL(timeTotal)) :: - ("timeSimulation", Values.REAL(timeSimulation)) :: - resultValues); - newst = GlobalScriptUtil.addVarToSymboltable( - DAE.CREF_IDENT("currentSimulationResult", DAE.T_STRING_DEFAULT, {}), - Values.STRING(result_file), FGraph.empty(), inSt); + if Flags.isSet(Flags.DYN_LOAD) then + Debug.traceln("CALL: record constructor: func: " + Absyn.pathString(funcpath) + " type path: " + Absyn.pathString(complexName)); + end if; + true = Absyn.pathEqual(funcpath,complexName); + (pubVarLst,proVarLst) = List.splitOnTrue(varLst,Types.isPublicVar); + expl = List.map1(proVarLst, Types.getBindingExp, funcpath); + (cache,proVallst,st) = Ceval.cevalList(cache, env, expl, impl, st, msg, numIter); + pubVarNames = List.map(pubVarLst,Expression.varName); + proVarNames = List.map(proVarLst,Expression.varName); + varNames = listAppend(pubVarNames, proVarNames); + vallst = listAppend(pubVallst, proVallst); + // fprintln(Flags.DYN_LOAD, "CALL: record constructor: [success] func: " + Absyn.pathString(funcpath)); then - (inCache,simValue,newst); - else + (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(ty = ty, builtin = false)), _, _, _, msg, _) equation - true = System.regularFileExists(logFile); - res = System.readFile(logFile); - str = Absyn.pathString(className); - res = stringAppendList({"Simulation execution failed for model: ", str, "\n", res}); - simValue = createSimulationResult("", simOptionsAsString(inVals), res, resultValues); - then - (inCache,simValue,inSt); - end matchcontinue; -end createSimulationResultFromcallModelExecutable; + failure(cevalIsExternalObjectConstructor(cache, funcpath, env, msg)); + if Flags.isSet(Flags.DYN_LOAD) then + Debug.traceln("CALL: try to evaluate or generate function: " + Absyn.pathString(funcpath)); + end if; -protected function buildOpenTURNSInterface "builds the OpenTURNS interface by calling the OpenTURNS module" - input FCore.Cache inCache; - input FCore.Graph inEnv; - input list vals; - input GlobalScript.SymbolTable inSt; - input Absyn.Msg inMsg; - output FCore.Cache outCache; - output String scriptFile; - output GlobalScript.SymbolTable outSt; -algorithm - (outCache,scriptFile,outSt):= match(inCache,inEnv,vals,inSt,inMsg) - local - String templateFile, str; - Absyn.Program p; - Absyn.Path className; - FCore.Cache cache; - DAE.DAElist dae; - FCore.Graph env; - BackendDAE.BackendDAE dlow; - DAE.FunctionTree funcs; - GlobalScript.SymbolTable st; - Boolean showFlatModelica; - String filenameprefix,description; + bIsCompleteFunction = isCompleteFunction(cache, env, funcpath); + false = Types.hasMetaArray(ty); - case(cache,_,{Values.CODE(Absyn.C_TYPENAME(className)),Values.STRING(templateFile),Values.BOOL(showFlatModelica)},GlobalScript.SYMBOLTABLE(ast=p),_) - equation - (cache,env,dae,_) = runFrontEnd(cache,inEnv,className,inSt,false); - //print("instantiated class\n"); - dae = DAEUtil.transformationsBeforeBackend(cache,env,dae); - funcs = FCore.getFunctionTree(cache); - if showFlatModelica then - print(DAEDump.dumpStr(dae, funcs)); + if Flags.isSet(Flags.DYN_LOAD) then + Debug.traceln("CALL: is complete function: " + Absyn.pathString(funcpath) + " " + (if bIsCompleteFunction then "[true]" else "[false]")); end if; - // get all the variable names with a distribution - // TODO FIXME - // sort all variable names in the distribution order - // TODO FIXME - filenameprefix = Absyn.pathString(className); - description = DAEUtil.daeDescription(dae); - dlow = BackendDAECreate.lower(dae,cache,env,BackendDAE.EXTRA_INFO(description,filenameprefix)); - //print("lowered class\n"); - //print("calling generateOpenTurnsInterface\n"); - scriptFile = OpenTURNS.generateOpenTURNSInterface(cache,inEnv,dlow,funcs,className,p,dae,templateFile); - then - (cache,scriptFile,inSt); + (cache, newval, st) = cevalCallFunctionEvaluateOrGenerate(inCache,inEnv,inExp,inValuesValueLst,impl,inSymTab,inMsg,bIsCompleteFunction); - end match; -end buildOpenTURNSInterface; + // Debug.fprintln(Flags.DYN_LOAD, "CALL: constant evaluation success: " + Absyn.pathString(funcpath)); + then + (cache, newval, st); -protected function runOpenTURNSPythonScript -"runs OpenTURNS with the given python script returning the log file" - input FCore.Cache inCache; - input FCore.Graph inEnv; - input list vals; - input GlobalScript.SymbolTable inSt; - input Absyn.Msg inMsg; - output FCore.Cache outCache; - output String outLogFile; - output GlobalScript.SymbolTable outSt; -algorithm - (outCache,outLogFile,outSt):= match(inCache,inEnv,vals,inSt,inMsg) - local - String pythonScriptFile, logFile; - FCore.Cache cache; - case(cache,_,{Values.STRING(pythonScriptFile)},_,_) + // partial and replaceable functions should not be evaluated! + case (cache,env, DAE.CALL(path = funcpath, attr = DAE.CALL_ATTR( builtin = false)), _, _, _, msg, _) equation - logFile = OpenTURNS.runPythonScript(pythonScriptFile); - then - (cache,logFile,inSt); - end match; -end runOpenTURNSPythonScript; - -public function getFileDir "author: x02lucpo - returns the dir where class file (.mo) was saved or - $OPENMODELICAHOME/work if the file was not saved yet" - input Absyn.ComponentRef inComponentRef "class"; - input Absyn.Program inProgram; - output String outString; -algorithm - outString:= - matchcontinue (inComponentRef,inProgram) - local - Absyn.Path p_class; - Absyn.Class cdef; - String filename,pd,dir_1,omhome,omhome_1; - String pd_1; - list filename_1,dir; - Absyn.ComponentRef class_; - Absyn.Program p; - case (class_,p) - equation - p_class = Absyn.crefToPath(class_) "change to the saved files directory" ; - cdef = Interactive.getPathedClassInProgram(p_class, p); - filename = Absyn.classFilename(cdef); - pd = System.pathDelimiter(); - (pd_1 :: _) = stringListStringChar(pd); - filename_1 = Util.stringSplitAtChar(filename, pd_1); - dir = List.stripLast(filename_1); - dir_1 = stringDelimitList(dir, pd); + failure(cevalIsExternalObjectConstructor(cache, funcpath, env, msg)); + false = isCompleteFunction(cache, env, funcpath); + + if Flags.isSet(Flags.DYN_LOAD) then + Debug.traceln("CALL: constant evaluation failed (not complete function): " + Absyn.pathString(funcpath)); + end if; then - dir_1; - case (_,_) + fail(); + + case (cache,env, DAE.CALL(path = funcpath, attr = DAE.CALL_ATTR(ty = ty, builtin = false)), _, _, _, msg as Absyn.MSG(info), _) equation - omhome = Settings.getInstallationDirectoryPath() "model not yet saved! change to $OPENMODELICAHOME/work" ; - omhome_1 = System.trim(omhome, "\""); - pd = System.pathDelimiter(); - dir_1 = stringAppendList({"\"",omhome_1,pd,"work","\""}); - then - dir_1; - else ""; /* this function should never fail */ + failure(cevalIsExternalObjectConstructor(cache, funcpath, env, msg)); + true = isCompleteFunction(cache, env, funcpath); + true = Types.hasMetaArray(ty); + str = ExpressionDump.printExpStr(inExp); + Error.addSourceMessage(Error.FUNCTION_RETURNS_META_ARRAY, {str}, info); + then fail(); + end matchcontinue; -end getFileDir; +end cevalCallFunction; -public function compileModel "Compiles a model given a file-prefix, helper function to buildModel." - input String fileprefix; - input list libs; protected - String omhome = Settings.getInstallationDirectoryPath(),omhome_1 = System.stringReplace(omhome, "\"", ""); - String pd = System.pathDelimiter(); - String libsfilename,libs_str,s_call,filename,winCompileMode; - String fileDLL = fileprefix + System.getDllExt(),fileEXE = fileprefix + System.getExeExt(),fileLOG = fileprefix + ".log"; - Integer numParallel,res; - Boolean isWindows = System.os() == "Windows_NT"; -algorithm - libsfilename := fileprefix + ".libs"; - libs_str := stringDelimitList(libs, " "); - - System.writeFile(libsfilename, libs_str); - if isWindows then - // We only need to set OPENMODELICAHOME on Windows, and set doesn't work in bash shells anyway - // adrpo: 2010-10-05: - // whatever you do, DO NOT add a space before the && otherwise - // OPENMODELICAHOME that we set will contain a SPACE at the end! - // set OPENMODELICAHOME=DIR && actually adds the space between the DIR and && - // to the environment variable! Don't ask me why, ask Microsoft. - omhome := "set OPENMODELICAHOME=\"" + System.stringReplace(omhome_1, "/", "\\") + "\"&& "; - winCompileMode := if Config.getRunningTestsuite() then "serial" else "parallel"; - s_call := stringAppendList({omhome,"\"",omhome_1,pd,"share",pd,"omc",pd,"scripts",pd,"Compile","\""," ",fileprefix," ",Config.simulationCodeTarget()," ", winCompileMode}); - else - numParallel := if Config.getRunningTestsuite() then 1 else Config.noProc(); - s_call := stringAppendList({System.getMakeCommand()," -j",intString(numParallel)," -f ",fileprefix,".makefile"}); - end if; - if Flags.isSet(Flags.DYN_LOAD) then - Debug.traceln("compileModel: running " + s_call); - end if; - - // remove .exe .dll .log! - if System.regularFileExists(fileEXE) then - 0 := System.removeFile(fileEXE); - end if; - if System.regularFileExists(fileDLL) then - 0 := System.removeFile(fileDLL); - end if; - if System.regularFileExists(fileLOG) then - 0 := System.removeFile(fileLOG); - end if; - - if Config.getRunningTestsuite() then - System.appendFile(Config.getRunningTestsuiteFile(), - fileEXE + "\n" + fileDLL + "\n" + fileLOG + "\n" + fileprefix + ".o\n" + fileprefix + ".libs\n" + - fileprefix + "_records.o\n" + fileprefix + "_res.mat\n"); - end if; - - // call the system command to compile the model! - if System.systemCall(s_call,if isWindows then "" else fileLOG) <> 0 then - // We failed, print error - if System.regularFileExists(fileLOG) then - Error.addMessage(Error.SIMULATOR_BUILD_ERROR, {System.readFile(fileLOG)}); - elseif isWindows then - // Check that it is a correct OPENMODELICAHOME, on Windows only - s_call := stringAppendList({omhome_1,pd,"share",pd,"omc",pd,"scripts",pd,"Compile.bat"}); - if not System.regularFileExists(s_call) then - Error.addMessage(Error.SIMULATOR_BUILD_ERROR, {stringAppendList({"command ",s_call," not found. Check $OPENMODELICAHOME"})}); - end if; - end if; - if Flags.isSet(Flags.DYN_LOAD) then - Debug.trace("compileModel: failed!\n"); - end if; - fail(); - end if; - - if Flags.isSet(Flags.DYN_LOAD) then - Debug.trace("compileModel: successful!\n"); - end if; -end compileModel; -public function checkModel " checks a model and returns number of variables and equations" +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 FCore.Cache inCache; input FCore.Graph inEnv; - input Absyn.Path className; - input GlobalScript.SymbolTable inInteractiveSymbolTable; + input DAE.Exp inExp; + input list inValuesValueLst; + input Boolean impl; + input Option inSymTab; input Absyn.Msg inMsg; + input Boolean bIsCompleteFunction; output FCore.Cache outCache; output Values.Value outValue; - output GlobalScript.SymbolTable outInteractiveSymbolTable; + output Option outSymTab; algorithm - (outCache,outValue,outInteractiveSymbolTable) := - matchcontinue (inCache,inEnv,className,inInteractiveSymbolTable,inMsg) + (outCache,outValue,outSymTab) := matchcontinue (inCache,inEnv,inExp,inValuesValueLst,impl,inSymTab,inMsg,bIsCompleteFunction) local - DAE.DAElist dae; + Values.Value newval; FCore.Graph env; - GlobalScript.SymbolTable st; - Absyn.Program p; + DAE.Exp e; + Absyn.Path funcpath; + list expl; + Boolean print_debug; + list vallst; Absyn.Msg msg; FCore.Cache cache; - Integer eqnSize,varSize,simpleEqnSize; - String errorMsg,eqnSizeStr,varSizeStr,retStr,classNameStr,simpleEqnSizeStr; - Boolean strEmpty; - Absyn.Restriction restriction; - Absyn.Class c; + list cflist; + Option st; + Absyn.Program p; + Integer libHandle, funcHandle; + String fNew,fOld; + Real buildTime, edit, build; + Option> a; + list b; + list c; + list cf; + list lf; + String funcstr,f,fileName; + list newCF; + String name; + Boolean ppref, fpref, epref; + Absyn.ClassDef body; + SourceInfo info; + Absyn.Within w; + list functionDependencies; + SCode.Element sc; + SCode.ClassDef cdef; + String error_Str; + DAE.Function func; + SCode.Restriction res; + GlobalScript.SymbolTable syt; + Absyn.FunctionRestriction funcRest; + DAE.Type ty; - // handle normal models - case (cache,env,_,(st as GlobalScript.SYMBOLTABLE()),_) + // try function interpretation + case (cache,env, DAE.CALL(path = funcpath, attr = DAE.CALL_ATTR(builtin = false)), vallst, _, st, msg, _) equation - (cache,env,dae,st) = runFrontEnd(cache,env,className,st,false); - - (varSize,eqnSize,simpleEqnSize) = CheckModel.checkModel(dae); - eqnSizeStr = intString(eqnSize); - varSizeStr = intString(varSize); - simpleEqnSizeStr = intString(simpleEqnSize); - - classNameStr = Absyn.pathString(className); - retStr = stringAppendList({"Check of ",classNameStr," completed successfully.","\nClass ",classNameStr," has ",eqnSizeStr," equation(s) and ", - varSizeStr," variable(s).\n",simpleEqnSizeStr," of these are trivial equation(s)."}); + true = Flags.isSet(Flags.EVAL_FUNC); + failure(cevalIsExternalObjectConstructor(cache, funcpath, env, msg)); + // bcall1(Flags.isSet(Flags.DYN_LOAD), print,"[dynload]: try constant evaluation: " + Absyn.pathString(funcpath) + "\n"); + (cache, + sc as SCode.CLASS(partialPrefix = SCode.NOT_PARTIAL()), + env) = Lookup.lookupClass(cache, env, funcpath, false); + isCevaluableFunction(sc); + (cache, env, _) = InstFunction.implicitFunctionInstantiation( + cache, + env, + InnerOuter.emptyInstHierarchy, + DAE.NOMOD(), + Prefix.NOPRE(), + sc, + {}); + func = FCore.getCachedInstFunc(cache, funcpath); + (cache, newval, st) = CevalFunction.evaluate(cache, env, func, vallst, st); + // bcall1(Flags.isSet(Flags.DYN_LOAD), print, "[dynload]: constant evaluation SUCCESS: " + Absyn.pathString(funcpath) + "\n"); then - (cache,Values.STRING(retStr),st); + (cache, newval, st); - // handle functions - case (cache,env,_,(st as GlobalScript.SYMBOLTABLE(ast = p)),_) + // see if function is in CF list and the build time is less than the edit time + case (cache,env,(DAE.CALL(path = funcpath, attr = DAE.CALL_ATTR(builtin = false))),vallst,_,// (impl as true) + (st as SOME(GlobalScript.SYMBOLTABLE(ast=p as Absyn.PROGRAM(),compiledFunctions=cflist))),msg, _) equation - (Absyn.CLASS(restriction=restriction)) = Interactive.getPathedClassInProgram(className, p); - true = Absyn.isFunctionRestriction(restriction) or Absyn.isPackageRestriction(restriction); - (cache,env,_,st) = runFrontEnd(cache,env,className,st,true); - classNameStr = Absyn.pathString(className); - then - (cache,Values.STRING(""),st); + true = bIsCompleteFunction; + true = Flags.isSet(Flags.GEN); + failure(cevalIsExternalObjectConstructor(cache,funcpath,env,msg)); + if Flags.isSet(Flags.DYN_LOAD) then + Debug.traceln("[dynload]: [func from file] check if is in CF list: " + Absyn.pathString(funcpath)); + end if; - case (cache,_,_,st as GlobalScript.SYMBOLTABLE(ast=p), _) - equation - classNameStr = Absyn.pathString(className); - false = Interactive.existClass(Absyn.pathToCref(className), p); - Error.addMessage(Error.LOOKUP_ERROR, {classNameStr,""}); - then - (cache,Values.STRING(""),st); + (true, funcHandle, buildTime, fOld) = Static.isFunctionInCflist(cflist, funcpath); + Absyn.CLASS(_,_,_,_,Absyn.R_FUNCTION(_),_,SOURCEINFO(fileName = fNew)) = Interactive.getPathedClassInProgram(funcpath, p); + // see if the build time from the class is the same as the build time from the compiled functions list + false = stringEq(fNew,""); // see if the WE have a file or not! + false = Static.needToRebuild(fNew,fOld,buildTime); // we don't need to rebuild! - // errors - case (cache,_,_,st,_) - equation - classNameStr = Absyn.pathString(className); - strEmpty = Error.getNumMessages() == 0; - errorMsg = "Check of " + classNameStr + " failed with no error message"; - if strEmpty then - Error.addMessage(Error.INTERNAL_ERROR, {errorMsg,""}); + if Flags.isSet(Flags.DYN_LOAD) then + print("[dynload]: [func from file] About to execute function present in CF list: " + Absyn.pathString(funcpath) + "\n"); end if; - then - (cache,Values.STRING(""),st); - - end matchcontinue; -end checkModel; -protected function selectIfNotEmpty - input String inString; - input String selector " "; - output String outString; -algorithm - outString := match(inString, selector) - local - String s; - - case (_, "") then ""; - - else - equation - s = inString + selector; - then s; - end match; -end selectIfNotEmpty; - -protected function getWithinStatement "To get a correct Within-path with unknown input-path." - input Absyn.Path ip; - output Absyn.Within op; -algorithm op := matchcontinue(ip) - local Absyn.Path path; - case(path) equation path = Absyn.stripLast(path); then Absyn.WITHIN(path); - else Absyn.TOP(); - end matchcontinue; -end getWithinStatement; - -public function subtractDummy -"if $dummy is present in Variables, subtract 1 from equation and variable size, otherwise not" - input BackendDAE.Variables vars; - input Integer eqnSize; - input Integer varSize; - output Integer outEqnSize; - output Integer outVarSize; -algorithm - (outEqnSize,outVarSize) := matchcontinue(vars,eqnSize,varSize) - case(_,_,_) - equation - (_,_) = BackendVariable.getVar(ComponentReference.makeCrefIdent("$dummy",DAE.T_UNKNOWN_DEFAULT,{}),vars); - then (eqnSize-1,varSize-1); - else (eqnSize,varSize); - end matchcontinue; -end subtractDummy; - -protected function dumpXMLDAEFrontEnd -"@author: adrpo - this function runs the front-end for the dumpXMLDAE function" - input FCore.Cache inCache; - input FCore.Graph inEnv; - input Absyn.Path inClassName; - input GlobalScript.SymbolTable inInteractiveSymbolTable; - output FCore.Cache outCache; - output FCore.Graph outEnv; - output DAE.DAElist outDae; -algorithm - (outCache, outEnv, outDae) := match(inCache, inEnv, inClassName, inInteractiveSymbolTable) - local - Absyn.Program p; - SCode.Program scode; - - case (_, _, _, _) - equation - GlobalScript.SYMBOLTABLE(ast = p) = inInteractiveSymbolTable; - scode = SCodeUtil.translateAbsyn2SCode(p); - (outCache, outEnv, _, outDae) = Inst.instantiateClass(inCache, InnerOuter.emptyInstHierarchy, scode, inClassName); - outDae = DAEUtil.transformationsBeforeBackend(outCache,outEnv,outDae); - then - (outCache, outEnv, outDae); - - end match; -end dumpXMLDAEFrontEnd; - -protected function dumpXMLDAE " author: fildo - This function outputs the DAE system corresponding to a specific model." - input FCore.Cache inCache; - input FCore.Graph inEnv; - input list vals; - input GlobalScript.SymbolTable inInteractiveSymbolTable; - input Absyn.Msg inMsg; - output FCore.Cache outCache; - output GlobalScript.SymbolTable outInteractiveSymbolTable3; - output String xml_filename; -algorithm - (outCache,outInteractiveSymbolTable3,xml_filename) := - matchcontinue (inCache,inEnv,vals,inInteractiveSymbolTable,inMsg) - local - String cname_str,filenameprefix,compileDir,rewriteRulesFile,description; - FCore.Graph env; - Absyn.Path classname; - Absyn.Program p; - BackendDAE.BackendDAE dlow,dlow_1,indexed_dlow; - FCore.Cache cache; - Boolean addOriginalIncidenceMatrix,addSolvingInfo,addMathMLCode,dumpResiduals; - GlobalScript.SymbolTable st; - Absyn.Msg msg; - DAE.DAElist dae_1,dae; - list p_1; + print_debug = Flags.isSet(Flags.DYN_LOAD); + newval = DynLoad.executeFunction(funcHandle, vallst, print_debug); + //print("CALL: [func from file] CF LIST:\n\t" + stringDelimitList(List.map(cflist, Interactive.dumpCompiledFunction), "\n\t") + "\n"); + then + (cache,newval,st); - case (cache,env,{Values.CODE(Absyn.C_TYPENAME(classname)),Values.STRING(string="flat"), - Values.BOOL(addOriginalIncidenceMatrix),Values.BOOL(addSolvingInfo), - Values.BOOL(addMathMLCode),Values.BOOL(dumpResiduals), - Values.STRING(filenameprefix),Values.STRING(rewriteRulesFile)},st,_) + // see if function is in CF list and the build time is less than the edit time + case (cache,env,(DAE.CALL(path = funcpath, attr = DAE.CALL_ATTR(builtin = false))),vallst,_,// impl as true + (st as SOME(GlobalScript.SYMBOLTABLE(ast=p as Absyn.PROGRAM(),compiledFunctions=cflist))), msg, _) equation - Error.clearMessages() "Clear messages"; - - // set the rewrite rules flag - Flags.setConfigString(Flags.REWRITE_RULES_FILE, rewriteRulesFile); - // load the rewrite rules - RewriteRules.loadRules(); - - (cache, env, dae) = dumpXMLDAEFrontEnd(cache, env, classname, st); - description = DAEUtil.daeDescription(dae); + true = bIsCompleteFunction; + true = Flags.isSet(Flags.GEN); + failure(cevalIsExternalObjectConstructor(cache,funcpath,env,msg)); - compileDir = System.pwd() + System.pathDelimiter(); - cname_str = Absyn.pathString(classname); - filenameprefix = if filenameprefix == "" then cname_str else filenameprefix; + if Flags.isSet(Flags.DYN_LOAD) then + print("[dynload]: [func from buffer] check if is in CF list: " + Absyn.pathString(funcpath) + "\n"); + end if; - dlow = BackendDAECreate.lower(dae,cache,env,BackendDAE.EXTRA_INFO(description,filenameprefix)); //Verificare cosa fa - dlow_1 = BackendDAEUtil.preOptimizeBackendDAE(dlow,NONE()); - dlow_1 = FindZeroCrossings.findZeroCrossings(dlow_1); - xml_filename = stringAppendList({filenameprefix,".xml"}); + (true, funcHandle, buildTime, _) = Static.isFunctionInCflist(cflist, funcpath); + Absyn.CLASS(restriction=Absyn.R_FUNCTION(_),info=SOURCEINFO(fileName = fNew, lastModification = edit)) = Interactive.getPathedClassInProgram(funcpath, p); + // note, this should only work for classes that have no file name! + true = stringEq(fNew,""); // see that we don't have a file! - // apply rewrite rules to the back-end - dlow_1 = applyRewriteRulesOnBackend(dlow_1); + // see if the build time from the class is the same as the build time from the compiled functions list + true = buildTime > edit; - Print.clearBuf(); - XMLDump.dumpBackendDAE(dlow_1,addOriginalIncidenceMatrix,addSolvingInfo,addMathMLCode,dumpResiduals,false); - Print.writeBuf(xml_filename); - Print.clearBuf(); - compileDir = if Config.getRunningTestsuite() then "" else compileDir; + if Flags.isSet(Flags.DYN_LOAD) then + print("[dynload]: [func from buffer] About to execute function present in CF list: " + Absyn.pathString(funcpath) + "\n"); + end if; - // clear the rewrite rules! - Flags.setConfigString(Flags.REWRITE_RULES_FILE, ""); - RewriteRules.clearRules(); + newval = DynLoad.executeFunction(funcHandle, vallst, Flags.isSet(Flags.DYN_LOAD)); then - (cache,st,stringAppendList({compileDir,xml_filename})); + (cache,newval,st); - case (cache,env,{Values.CODE(Absyn.C_TYPENAME(classname)),Values.STRING(string="optimiser"), - Values.BOOL(addOriginalIncidenceMatrix),Values.BOOL(addSolvingInfo), - Values.BOOL(addMathMLCode),Values.BOOL(dumpResiduals), - Values.STRING(filenameprefix),Values.STRING(rewriteRulesFile)},(st as GlobalScript.SYMBOLTABLE()),_) + // not in CF list, we have a symbol table, generate function and update symtab + case (cache,env,(DAE.CALL(path = funcpath,attr = DAE.CALL_ATTR(builtin = false))),vallst,_, + SOME(syt as GlobalScript.SYMBOLTABLE(p as Absyn.PROGRAM(),a,b,c,cf,lf)), msg, _) // yeha! we have a symboltable! equation - //asInSimulationCode==false => it's NOT necessary to do all the translation's steps before dumping with xml - Error.clearMessages() "Clear messages"; - - // set the rewrite rules flag - Flags.setConfigString(Flags.REWRITE_RULES_FILE, rewriteRulesFile); - // load the rewrite rules - RewriteRules.loadRules(); - - (cache, env, dae) = dumpXMLDAEFrontEnd(cache, env, classname, st); - description = DAEUtil.daeDescription(dae); - - compileDir = System.pwd() + System.pathDelimiter(); - cname_str = Absyn.pathString(classname); - filenameprefix = if filenameprefix == "" then cname_str else filenameprefix; - - dlow = BackendDAECreate.lower(dae,cache,env,BackendDAE.EXTRA_INFO(description,filenameprefix)); //Verificare cosa fa - dlow_1 = BackendDAEUtil.preOptimizeBackendDAE(dlow,NONE()); - dlow_1 = BackendDAEUtil.transformBackendDAE(dlow_1,NONE(),NONE(),NONE()); - dlow_1 = FindZeroCrossings.findZeroCrossings(dlow_1); - xml_filename = stringAppendList({filenameprefix,".xml"}); - - // apply rewrite rules to the back-end - dlow_1 = applyRewriteRulesOnBackend(dlow_1); - - Print.clearBuf(); - XMLDump.dumpBackendDAE(dlow_1,addOriginalIncidenceMatrix,addSolvingInfo,addMathMLCode,dumpResiduals,false); - Print.writeBuf(xml_filename); - Print.clearBuf(); - compileDir = if Config.getRunningTestsuite() then "" else compileDir; + true = bIsCompleteFunction; + true = Flags.isSet(Flags.GEN); + failure(cevalIsExternalObjectConstructor(cache,funcpath,env,msg)); - // clear the rewrite rules! - Flags.setConfigString(Flags.REWRITE_RULES_FILE, ""); - RewriteRules.clearRules(); - then - (cache,st,stringAppendList({compileDir,xml_filename})); + if Flags.isSet(Flags.DYN_LOAD) then + print("[dynload]: [SOME SYMTAB] not in in CF list: " + Absyn.pathString(funcpath) + "\n"); + end if; - case (cache,env,{Values.CODE(Absyn.C_TYPENAME(classname)),Values.STRING(string="backEnd"), - Values.BOOL(addOriginalIncidenceMatrix),Values.BOOL(addSolvingInfo), - Values.BOOL(addMathMLCode),Values.BOOL(dumpResiduals), - Values.STRING(filenameprefix),Values.STRING(rewriteRulesFile)},(st as GlobalScript.SYMBOLTABLE()),_) - equation - //asInSimulationCode==true => it's necessary to do all the translation's steps before dumping with xml - Error.clearMessages() "Clear messages"; + // remove it and all its dependencies as it might be there with an older build time. + // get dependencies! + (_, functionDependencies, _) = getFunctionDependencies(cache, funcpath); + //print("\nFunctions before:\n\t" + stringDelimitList(List.map(cf, Interactive.dumpCompiledFunction), "\n\t") + "\n"); + newCF = Interactive.removeCfAndDependencies(cf, funcpath::functionDependencies); + //print("\nFunctions after remove:\n\t" + stringDelimitList(List.map(newCF, Interactive.dumpCompiledFunction), "\n\t") + "\n"); - // set the rewrite rules flag - Flags.setConfigString(Flags.REWRITE_RULES_FILE, rewriteRulesFile); - // load the rewrite rules - RewriteRules.loadRules(); + if Flags.isSet(Flags.DYN_LOAD) then + print("[dynload]: [SOME SYMTAB] not in in CF list: removed deps:" + + stringDelimitList(List.map(functionDependencies, Absyn.pathString) ,", ") + "\n"); + end if; + //print("\nfunctions in SYMTAB: " + Interactive.dumpCompiledFunctions(syt) - (cache, env, dae) = dumpXMLDAEFrontEnd(cache, env, classname, st); - description = DAEUtil.daeDescription(dae); + // now is safe to generate code + (cache, funcstr, fileName) = cevalGenerateFunction(cache, env, p, funcpath); + print_debug = Flags.isSet(Flags.DYN_LOAD); + libHandle = System.loadLibrary(fileName, print_debug); + funcHandle = System.lookupFunction(libHandle, stringAppend("in_", funcstr)); + newval = DynLoad.executeFunction(funcHandle, vallst, print_debug); + System.freeLibrary(libHandle, print_debug); + buildTime = System.getCurrentTime(); + // update the build time in the class! + Absyn.CLASS(_,_,_,_,Absyn.R_FUNCTION(_),_,info) = Interactive.getPathedClassInProgram(funcpath, p); - compileDir = System.pwd() + System.pathDelimiter(); - cname_str = Absyn.pathString(classname); - filenameprefix = if filenameprefix == "" then cname_str else filenameprefix; + /* info = Absyn.setBuildTimeInInfo(buildTime,info); + ts = Absyn.setTimeStampBuild(ts, buildTime); */ + w = Interactive.buildWithin(funcpath); - dlow = BackendDAECreate.lower(dae,cache,env,BackendDAE.EXTRA_INFO(description,filenameprefix)); - indexed_dlow = BackendDAEUtil.getSolvedSystem(dlow,""); - xml_filename = stringAppendList({filenameprefix,".xml"}); + if Flags.isSet(Flags.DYN_LOAD) then + print("[dynload]: Updating build time for function path: " + Absyn.pathString(funcpath) + " within: " + Dump.unparseWithin(w) + "\n"); + end if; - // apply rewrite rules to the back-end - indexed_dlow = applyRewriteRulesOnBackend(indexed_dlow); + // p = Interactive.updateProgram(Absyn.PROGRAM({Absyn.CLASS(name,ppref,fpref,epref,Absyn.R_FUNCTION(funcRest),body,info)},w,ts), p); + f = Absyn.getFileNameFromInfo(info); - Print.clearBuf(); - XMLDump.dumpBackendDAE(indexed_dlow,addOriginalIncidenceMatrix,addSolvingInfo,addMathMLCode,dumpResiduals,false); - Print.writeBuf(xml_filename); - Print.clearBuf(); - compileDir = if Config.getRunningTestsuite() then "" else compileDir; + syt = GlobalScript.SYMBOLTABLE( + p, a, b, c, + GlobalScript.CFunction(funcpath,DAE.T_UNKNOWN({funcpath}),funcHandle,buildTime,f)::newCF, + lf); - // clear the rewrite rules! - Flags.setConfigString(Flags.REWRITE_RULES_FILE, ""); - RewriteRules.clearRules(); + if Flags.isSet(Flags.DYN_LOAD) then + print("[dynload]: [SOME SYMTAB] not in in CF list [finished]: " + + Absyn.pathString(funcpath) + "\n"); + end if; + //print("\nfunctions in SYMTAB: " + Interactive.dumpCompiledFunctions(syt)); then - (cache,st,stringAppendList({compileDir,xml_filename})); + (cache,newval,SOME(syt)); - case (cache,env,{Values.CODE(Absyn.C_TYPENAME(classname)),Values.STRING(string="stateSpace"), - Values.BOOL(addOriginalIncidenceMatrix),Values.BOOL(addSolvingInfo), - Values.BOOL(addMathMLCode),Values.BOOL(dumpResiduals), - Values.STRING(filenameprefix),Values.STRING(rewriteRulesFile)},(st as GlobalScript.SYMBOLTABLE()),_) + // no symtab, WE SHOULD NOT EVALUATE! but we do anyway with suppressed error messages! + case (cache,env,(DAE.CALL(path = funcpath,attr = DAE.CALL_ATTR(builtin = false))),vallst,_,NONE(), msg, _) // crap! we have no symboltable! equation - //asInSimulationCode==true => it's necessary to do all the translation's steps before dumping with xml - Error.clearMessages() "Clear messages"; - - // set the rewrite rules flag - Flags.setConfigString(Flags.REWRITE_RULES_FILE, rewriteRulesFile); - // load the rewrite rules - RewriteRules.loadRules(); - - (cache, env, dae) = dumpXMLDAEFrontEnd(cache, env, classname, st); - description = DAEUtil.daeDescription(dae); - - compileDir = System.pwd() + System.pathDelimiter(); - cname_str = Absyn.pathString(classname); - filenameprefix = if filenameprefix == "" then cname_str else filenameprefix; - - dlow = BackendDAECreate.lower(dae,cache,env,BackendDAE.EXTRA_INFO(description,filenameprefix)); - indexed_dlow = BackendDAEUtil.getSolvedSystem(dlow,""); - xml_filename = stringAppendList({filenameprefix,".xml"}); + true = bIsCompleteFunction; + true = Flags.isSet(Flags.GEN); + failure(cevalIsExternalObjectConstructor(cache,funcpath,env,msg)); + ErrorExt.setCheckpoint("cevalCallFunctionEvaluateOrGenerate_NO_SYMTAB"); - // apply rewrite rules to the back-end - indexed_dlow = applyRewriteRulesOnBackend(indexed_dlow); + if Flags.isSet(Flags.DYN_LOAD) then + print("[dynload]: [NO SYMTAB] not in in CF list: " + Absyn.pathString(funcpath) + "\n"); + end if; - Print.clearBuf(); - XMLDump.dumpBackendDAE(indexed_dlow,addOriginalIncidenceMatrix,addSolvingInfo,addMathMLCode,dumpResiduals,true); - Print.writeBuf(xml_filename); - Print.clearBuf(); - compileDir = if Config.getRunningTestsuite() then "" else compileDir; + // we might actually have a function loaded here already! + // we need to unload all functions to not get conflicts! + p = FCore.getProgramFromCache(cache); + (cache,funcstr,fileName) = cevalGenerateFunction(cache, env, p, funcpath); + // generate a uniquely named dll! + if Flags.isSet(Flags.DYN_LOAD) then + print("[dynload]: cevalCallFunction: about to execute " + funcstr + "\n"); + end if; + print_debug = Flags.isSet(Flags.DYN_LOAD); + libHandle = System.loadLibrary(fileName, print_debug); + funcHandle = System.lookupFunction(libHandle, stringAppend("in_", funcstr)); + newval = DynLoad.executeFunction(funcHandle, vallst, print_debug); + System.freeFunction(funcHandle, print_debug); + System.freeLibrary(libHandle, print_debug); - // clear the rewrite rules! - Flags.setConfigString(Flags.REWRITE_RULES_FILE, ""); - RewriteRules.clearRules(); + if Flags.isSet(Flags.DYN_LOAD) then + Debug.traceln("CALL: [NO SYMTAB] not in in CF list [finished]: " + Absyn.pathString(funcpath)); + end if; + ErrorExt.rollBack("cevalCallFunctionEvaluateOrGenerate_NO_SYMTAB"); then - (cache,st,stringAppendList({compileDir,xml_filename})); - - else - equation - // clear the rewrite rules if we fail! - Flags.setConfigString(Flags.REWRITE_RULES_FILE, ""); - RewriteRules.clearRules(); - then fail(); - - end matchcontinue; -end dumpXMLDAE; - -protected function applyRewriteRulesOnBackend - input BackendDAE.BackendDAE inBackendDAE; - output BackendDAE.BackendDAE outBackendDAE; -algorithm - outBackendDAE := matchcontinue(inBackendDAE) - local - list vars,knvars,extvars,aliasvars; - BackendDAE.Variables vars_knownVars; - BackendDAE.Variables vars_externalObject; - BackendDAE.VariableArray varArr_externalObject; - BackendDAE.Variables vars_aliasVars; - BackendDAE.VariableArray varArr_aliasVars; - BackendDAE.ExternalObjectClasses extObjCls; - BackendDAE.EquationArray reqns,ieqns; - list constrs; - list clsAttrs; - list functionsElems; - BackendDAE.BackendDAEType btp; - list systs; - BackendDAE.SymbolicJacobians symjacs; - DAE.FunctionTree funcs; - BackendDAE.EventInfo eventInfo; - BackendDAE.ExtraInfo extraInfo; - FCore.Cache cache; - FCore.Graph env; + (cache,newval,NONE()); - // no rewrites! - case _ + // cleanup the case below when we failed. we should delete generated files too + case (cache,env,(DAE.CALL(path = funcpath,attr = DAE.CALL_ATTR(builtin = false))),_,_,NONE(),msg, _) // crap! we have no symboltable! equation - true = RewriteRules.noRewriteRulesBackEnd(); + true = bIsCompleteFunction; + true = Flags.isSet(Flags.GEN); + failure(cevalIsExternalObjectConstructor(cache,funcpath,env,msg)); + ErrorExt.rollBack("cevalCallFunctionEvaluateOrGenerate_NO_SYMTAB"); then - inBackendDAE; + fail(); - // some rewrites - case _ + case (_,_,(DAE.CALL(path = funcpath)),_,_,_, _, _) equation - false = RewriteRules.noRewriteRulesBackEnd(); - outBackendDAE = BackendDAEOptimize.applyRewriteRulesBackend(inBackendDAE); + if Flags.isSet(Flags.DYN_LOAD) then + print("[dynload]: FAILED to constant evaluate function: " + Absyn.pathString(funcpath) + "\n"); + end if; + //TODO: readd this when testsuite is okay. + //Error.addMessage(Error.FAILED_TO_EVALUATE_FUNCTION, {error_Str}); + false = Flags.isSet(Flags.GEN); + true = Flags.isSet(Flags.FAILTRACE); + Debug.trace("- codegeneration is turned off. switch \"nogen\" flag off\n"); then - outBackendDAE; + fail(); end matchcontinue; -end applyRewriteRulesOnBackend; +end cevalCallFunctionEvaluateOrGenerate; -protected function getClassnamesInClassList - input Absyn.Path inPath; - input Absyn.Program inProgram; - input Absyn.Class inClass; - input Boolean inShowProtected; - output list outStrings; +function cevalIsExternalObjectConstructor + input FCore.Cache cache; + input Absyn.Path funcpath; + input FCore.Graph env; + input Absyn.Msg msg; +protected + Absyn.Path funcpath2; + DAE.Type tp; + Option info; algorithm - outStrings := - match (inPath,inProgram,inClass,inShowProtected) - local - list strlist; - list parts; - Absyn.Path inmodel,path; - Absyn.Program p; - String baseClassName; - Boolean b; - case (_,_,Absyn.CLASS(body = Absyn.PARTS(classParts = parts)),b) + _ := match(cache, funcpath, env, msg) + case (_, _, FCore.EG(_), Absyn.NO_MSG()) then fail(); + case (_, _, _, Absyn.NO_MSG()) equation - strlist = Interactive.getClassnamesInParts(parts,b); + (funcpath2, Absyn.IDENT("constructor")) = Absyn.splitQualAndIdentPath(funcpath); + info = if valueEq(msg, Absyn.NO_MSG()) then NONE() else SOME(Absyn.dummyInfo); + (_, tp, _) = Lookup.lookupType(cache, env, funcpath2, info); + Types.externalObjectConstructorType(tp); then - strlist; + (); + end match; +end cevalIsExternalObjectConstructor; - case (_,_,Absyn.CLASS(body = Absyn.DERIVED(typeSpec=Absyn.TPATH())),_) - equation - then - {}; +protected function checkLibraryUsage + input String inLibrary; + input Absyn.Exp inExp; + output Boolean isUsed; +algorithm + isUsed := match(inLibrary, inExp) + local + String s; + list exps; - case (_,_,Absyn.CLASS(body = Absyn.OVERLOAD(_, _)),_) - equation - then {}; + case (_, Absyn.STRING(s)) then stringEq(s, inLibrary); + case (_, Absyn.ARRAY(exps)) + then List.isMemberOnTrue(inLibrary, exps, checkLibraryUsage); + end match; +end checkLibraryUsage; - case (_,_,Absyn.CLASS(body = Absyn.ENUMERATION(_, _)),_) - equation - then {}; +function isCevaluableFunction + "Checks if an element is a function or external function that can be evaluated + by CevalFunction." + input SCode.Element inElement; +algorithm + _ := match(inElement) + local + String fid; + SCode.Mod mod; + Absyn.Exp lib; - case (_,_,Absyn.CLASS(body = Absyn.CLASS_EXTENDS(parts=parts)),b) + //only some external functions. + case (SCode.CLASS(restriction = SCode.R_FUNCTION(SCode.FR_EXTERNAL_FUNCTION(_)), + classDef = SCode.PARTS(externalDecl = SOME(SCode.EXTERNALDECL( + funcName = SOME(fid), + annotation_ = SOME(SCode.ANNOTATION(mod))))))) equation - strlist = Interactive.getClassnamesInParts(parts,b); - then strlist; + SCode.MOD(binding = SOME(lib)) = Mod.getUnelabedSubMod(mod, "Library"); + true = checkLibraryUsage("Lapack", lib) or checkLibraryUsage("lapack", lib); + isCevaluableFunction2(fid); + then + (); - case (_,_,Absyn.CLASS(body = Absyn.PDER(_,_,_)),_) - equation - then {}; + // All other functions can be evaluated. + case (SCode.CLASS(restriction = SCode.R_FUNCTION(_))) then (); end match; -end getClassnamesInClassList; +end isCevaluableFunction; -protected function joinPaths - input String child; - input Absyn.Path parent; - output Absyn.Path outPath; -algorithm - outPath := match (child, parent) - local - Absyn.Path r, res; - String c; - case (c, r) - equation - res = Absyn.joinPaths(r, Absyn.IDENT(c)); - then res; - end match; -end joinPaths; - -protected function getAllClassPathsRecursive -"@author adrpo - Returns all paths of the classes recursively defined in a given class with the specified path." - input Absyn.Path inPath "the given class path"; - input Boolean inCheckProtected; - input Absyn.Program inProgram "the program"; - output list outPaths; -algorithm - outPaths := - matchcontinue (inPath,inCheckProtected,inProgram) - local - Absyn.Class cdef; - String parent_string, s; - list strlst; - Absyn.Program p; - list result_path_lst, result; - Boolean b; - case (_, b, p) - equation - cdef = Interactive.getPathedClassInProgram(inPath, p); - strlst = getClassnamesInClassList(inPath, p, cdef, b); - result_path_lst = List.map1(strlst, joinPaths, inPath); - result = List.flatten(List.map2(result_path_lst, getAllClassPathsRecursive, b, p)); - then - inPath::result; - else - equation - parent_string = Absyn.pathString(inPath); - s = Error.printMessagesStr(false); - s = stringAppendList({parent_string,"->","PROBLEM GETTING CLASS PATHS: ", s, "\n"}); - print(s); - then {}; - end matchcontinue; -end getAllClassPathsRecursive; - -public function checkAllModelsRecursive -"@author adrpo - checks all models and returns number of variables and equations" - input FCore.Cache inCache; - input FCore.Graph inEnv; - input Absyn.Path className; - input Boolean inCheckProtected; - input GlobalScript.SymbolTable inInteractiveSymbolTable; - input Absyn.Msg inMsg; - output FCore.Cache outCache; - output Values.Value outValue; - output GlobalScript.SymbolTable outInteractiveSymbolTable; -algorithm - (outCache,outValue,outInteractiveSymbolTable):= - matchcontinue (inCache,inEnv,className,inCheckProtected,inInteractiveSymbolTable,inMsg) - local - list allClassPaths; - GlobalScript.SymbolTable st; - Absyn.Program p; - Absyn.Msg msg; - FCore.Cache cache; - String ret; - FCore.Graph env; - Boolean b; - - case (cache,env,_,b,(st as GlobalScript.SYMBOLTABLE(ast = p)),msg) - equation - allClassPaths = getAllClassPathsRecursive(className, b, p); - print("Number of classes to check: " + intString(listLength(allClassPaths)) + "\n"); - // print ("All paths: \n" + stringDelimitList(List.map(allClassPaths, Absyn.pathString), "\n") + "\n"); - checkAll(cache, env, allClassPaths, st, msg); - ret = "Number of classes checked: " + intString(listLength(allClassPaths)); - then - (cache,Values.STRING(ret),st); - - case (cache,_,_,_,(st as GlobalScript.SYMBOLTABLE()),_) - equation - ret = stringAppend("Error checking: ", Absyn.pathString(className)); - then - (cache,Values.STRING(ret),st); - end matchcontinue; -end checkAllModelsRecursive; - -function failOrSuccess -"@author adrpo" - input String inStr; - output String outStr; -algorithm - outStr := matchcontinue(inStr) - local Integer res; - case _ - equation - res = System.stringFind(inStr, "successfully"); - true = (res >= 0); - then "OK"; - else "FAILED!"; - end matchcontinue; -end failOrSuccess; - -function checkAll -"@author adrpo - checks all models and returns number of variables and equations" - input FCore.Cache inCache; - input FCore.Graph inEnv; - input list allClasses; - input GlobalScript.SymbolTable inInteractiveSymbolTable; - input Absyn.Msg inMsg; -algorithm - _ := matchcontinue (inCache,inEnv,allClasses,inInteractiveSymbolTable,inMsg) - local - list rest; - Absyn.Path className; - GlobalScript.SymbolTable st; - Absyn.Program p; - Absyn.Msg msg; - FCore.Cache cache; - String str, s; - FCore.Graph env; - Real t1, t2, elapsedTime; - Absyn.ComponentRef cr; - Absyn.Class c; - case (_,_,{},_,_) then (); - - case (cache,env,className::rest,(st as GlobalScript.SYMBOLTABLE(ast = p)),msg) - equation - c = Interactive.getPathedClassInProgram(className, p); - // filter out partial classes - // Absyn.CLASS(partialPrefix = false) = c; // do not filter partial classes - // filter out packages - false = Interactive.isPackage(className, p); - // filter out functions - // false = Interactive.isFunction(cr, p); - // filter out types - false = Interactive.isType(className, p); - print("Checking: " + Dump.unparseClassAttributesStr(c) + " " + Absyn.pathString(className) + "... "); - t1 = clock(); - Flags.setConfigBool(Flags.CHECK_MODEL, true); - (_,Values.STRING(str),_) = checkModel(FCore.emptyCache(), env, className, st, msg); - Flags.setConfigBool(Flags.CHECK_MODEL, false); - (_,Values.STRING(str),_) = checkModel(FCore.emptyCache(), env, className, st, msg); - t2 = clock(); - elapsedTime = t2 - t1; - s = realString(elapsedTime); - print (s + " seconds -> " + failOrSuccess(str) + "\n\t"); - print (System.stringReplace(str, "\n", "\n\t")); - print ("\n"); - checkAll(cache, env, rest, st, msg); - then - (); - - case (cache,env,className::rest,(st as GlobalScript.SYMBOLTABLE(ast = p)),msg) - equation - c = Interactive.getPathedClassInProgram(className, p); - print("Checking skipped: " + Dump.unparseClassAttributesStr(c) + " " + Absyn.pathString(className) + "... \n"); - checkAll(cache, env, rest, st, msg); - then - (); - end matchcontinue; -end checkAll; - -public function buildModelBeast " copy & pasted by: Otto - translates and builds the model by running compiler script on the generated makefile" - input FCore.Cache inCache; - input FCore.Graph inEnv; - input list vals; - input GlobalScript.SymbolTable inInteractiveSymbolTable; - input Absyn.Msg inMsg; - output FCore.Cache outCache; - output GlobalScript.SymbolTable outInteractiveSymbolTable; - output String compileDir; - output String outString1 "className"; - output String outString2 "method"; - output String outString4 "initFileName"; -algorithm - (outCache,outInteractiveSymbolTable,compileDir,outString1,outString2,outString4):= - match (inCache,inEnv,vals,inInteractiveSymbolTable,inMsg) - local - GlobalScript.SymbolTable st,st2; - BackendDAE.BackendDAE indexed_dlow_1; - list libs; - String file_dir,method_str,filenameprefix,s3; - Absyn.Path classname; - Absyn.Program p,p2; - Absyn.Class cdef; - FCore.Graph env; - Values.Value starttime,stoptime,interval,method,tolerance,options; - Absyn.Msg msg; - Absyn.Within win1; - FCore.Cache cache; - SimCode.SimulationSettings simSettings; - - // normal call - case (cache,env,{Values.CODE(Absyn.C_TYPENAME(classname)),_,_,_,_, _,Values.STRING(filenameprefix),_},(st as GlobalScript.SYMBOLTABLE(ast = p as Absyn.PROGRAM())),msg) - equation - _ = Interactive.getPathedClassInProgram(classname,p); - Error.clearMessages() "Clear messages"; - compileDir = System.pwd() + System.pathDelimiter(); - (cache,simSettings) = calculateSimulationSettings(cache,env,vals,st,msg); - (cache,st,_,libs,file_dir,_) - = translateModel(cache,env, classname, st, filenameprefix,true,SOME(simSettings)); - SimCode.SIMULATION_SETTINGS() = simSettings; - //cname_str = Absyn.pathString(classname); - //(cache,init_filename,starttime_r,stoptime_r,interval_r,tolerance_r,method_str,options_str,outputFormat_str) - //= calculateSimulationSettings(cache,env, exp, st, msg, cname_str); - //SimCodeUtil.generateInitData(indexed_dlow_1, classname, filenameprefix, init_filename, starttime_r, stoptime_r, interval_r,tolerance_r,method_str,options_str,outputFormat_str); - if Flags.isSet(Flags.DYN_LOAD) then - Debug.traceln("buildModel: about to compile model " + filenameprefix + ", " + file_dir); - end if; - compileModel(filenameprefix, libs); - if Flags.isSet(Flags.DYN_LOAD) then - Debug.trace("buildModel: Compiling done.\n"); - end if; - // SimCodegen.generateMakefileBeast(makefilename, filenameprefix, libs, file_dir); - _ = getWithinStatement(classname); - compileModel(filenameprefix, libs); - // (p as Absyn.PROGRAM(globalBuildTimes=Absyn.TIMESTAMP(r1,r2))) = Interactive.updateProgram2(p2,p,false); - st2 = st; // Interactive.replaceSymbolTableProgram(st,p); - then - (cache,st2,compileDir,filenameprefix,"",""); - - // failure - else - then - fail(); - end match; -end buildModelBeast; - -protected function generateFunctionName -"@author adrpo: - generate the function name from a path." - input Absyn.Path functionPath; - output String functionName; -algorithm - functionName := Absyn.pathStringUnquoteReplaceDot(functionPath, "_"); -end generateFunctionName; - -protected function generateFunctionFileName -"@author adrpo: - generate the function name from a path." - input Absyn.Path functionPath; - output String functionName; -algorithm - functionName := matchcontinue(functionPath) - local String name, n1, n2; Integer len; - case (_) - equation - name = Absyn.pathStringUnquoteReplaceDot(functionPath, "_"); - len = stringLength(name); - // not bigger than - true = len > Global.maxFunctionFileLength; - n1 = Absyn.pathFirstIdent(functionPath); - n2 = Absyn.pathLastIdent(functionPath); - name = System.unquoteIdentifier(n1 + "_" + n2); - name = name + "_" + intString(tick()); - then - name; - else - equation - name = Absyn.pathStringUnquoteReplaceDot(functionPath, "_"); - then - name; - end matchcontinue; -end generateFunctionFileName; - -public function getFunctionDependencies -"returns all function dependencies as paths, also the main function and the function tree" - input FCore.Cache cache; - input Absyn.Path functionName; - output DAE.Function mainFunction "the main function"; - output list dependencies "the dependencies as paths"; - output DAE.FunctionTree funcs "the function tree"; -algorithm - funcs := FCore.getFunctionTree(cache); - // First check if the main function exists... If it does not it might be an interactive function... - mainFunction := DAEUtil.getNamedFunction(functionName, funcs); - dependencies := SimCodeMain.getCalledFunctionsInFunction(functionName,funcs); -end getFunctionDependencies; - -public function collectDependencies -"collects all function dependencies, also the main function, uniontypes, metarecords" - input FCore.Cache inCache; - input FCore.Graph env; - input Absyn.Path functionName; - output FCore.Cache outCache; - output DAE.Function mainFunction; - output list dependencies; - output list metarecordTypes; -protected - list uniontypePaths,paths; - DAE.FunctionTree funcs; -algorithm - (mainFunction, paths, funcs) := getFunctionDependencies(inCache, functionName); - // The list of functions is not ordered, so we need to filter out the main function... - dependencies := List.map1(paths, DAEUtil.getNamedFunction, funcs); - dependencies := List.setDifference(dependencies, {mainFunction}); - uniontypePaths := DAEUtil.getUniontypePaths(dependencies,{}); - (outCache,metarecordTypes) := Lookup.lookupMetarecordsRecursive(inCache, env, uniontypePaths); -end collectDependencies; - -public function cevalGenerateFunction "Generates code for a given function name." - input FCore.Cache inCache; - input FCore.Graph inEnv; - input Absyn.Program program; - input Absyn.Path inPath; - output FCore.Cache outCache; - output String functionName; - output String functionFileName; -algorithm - (outCache,functionName,functionFileName) := matchcontinue (inCache,inEnv,program,inPath) - local - String pathstr, fileName; - FCore.Graph env; - Absyn.Path path; - FCore.Cache cache; - DAE.Function mainFunction; - list d; - list metarecordTypes; - DAE.FunctionTree funcs; - // template based translation - case (cache, env, _, path) - equation - true = Flags.isSet(Flags.GEN); - false = Flags.isSet(Flags.GENERATE_CODE_CHEAT); - - (cache, mainFunction, d, metarecordTypes) = collectDependencies(cache, env, path); - - pathstr = generateFunctionName(path); - fileName = generateFunctionFileName(path); - SimCodeMain.translateFunctions(program, fileName, SOME(mainFunction), d, metarecordTypes, {}); - compileModel(fileName, {}); - then - (cache, pathstr, fileName); - - // Cheat if we want to generate code for Main.main - // * Don't do dependency analysis of what functions to generate; just generate all of them - // * Don't generate extra code for unreferenced MetaRecord types (for external functions) - // This could be an annotation instead anyway. - // * Don't compile the generated files - case (cache, _, _, path) - equation - true = Flags.isSet(Flags.GEN); - true = Flags.isSet(Flags.GENERATE_CODE_CHEAT); - funcs = FCore.getFunctionTree(cache); - // First check if the main function exists... If it does not it might be an interactive function... - pathstr = generateFunctionName(path); - fileName = generateFunctionFileName(path); - // The list of functions is not ordered, so we need to filter out the main function... - d = DAEUtil.getFunctionList(funcs); - SimCodeMain.translateFunctions(program, fileName, NONE(), d, {}, {}); - then - (cache, pathstr, fileName); - - case (cache, env, _, path) - equation - true = Flags.isSet(Flags.GEN); - true = Flags.isSet(Flags.FAILTRACE); - (cache,false) = Static.isExternalObjectFunction(cache,env,path); - pathstr = generateFunctionName(path); - fileName = generateFunctionFileName(path); - Debug.trace("CevalScript.cevalGenerateFunction failed:\nfunction: " + pathstr + "\nfile: " + fileName + "\n"); - then - fail(); - end matchcontinue; -end cevalGenerateFunction; - -protected function generateFunctions - input FCore.Cache icache; - input FCore.Graph ienv; - input Absyn.Program p; - input list isp; - input Boolean cleanCache; - output FCore.Cache cache; - output FCore.Graph env; -algorithm - (cache,env) := match (icache,ienv,p,isp,cleanCache) - local - String name; - list names,dependencies; - list paths; - list elementLst; - DAE.FunctionTree funcs; - list d; - list>> acc; - list sp; - String file,nameHeader,str; - Integer n; - SourceInfo info; - SCode.Element cl; - - case (cache,env,_,{},_) then (cache,env); - case (cache,env,_,(cl as SCode.CLASS(name=name,encapsulatedPrefix=SCode.ENCAPSULATED(),restriction=SCode.R_PACKAGE(),classDef=SCode.PARTS(elementLst=elementLst),info=info))::sp,_) - equation - (cache,env) = generateFunctions2(cache,env,p,cl,name,elementLst,info,cleanCache); - (cache,env) = generateFunctions(cache,env,p,sp,cleanCache); - then (cache,env); - case (cache,env,_,SCode.CLASS(encapsulatedPrefix=SCode.NOT_ENCAPSULATED(),name=name,info=info as SOURCEINFO(fileName=file))::_,_) - equation - (n,_) = System.regex(file, "ModelicaBuiltin.mo$", 1, false, false); - Error.assertion(n > 0, "Not an encapsulated class (required for separate compilation): " + name, info); - then fail(); - end match; -end generateFunctions; - -protected function generateFunctions2 - input FCore.Cache icache; - input FCore.Graph ienv; - input Absyn.Program p; - input SCode.Element cl; - input String name; - input list elementLst; - input SourceInfo info; - input Boolean cleanCache; - output FCore.Cache cache; - output FCore.Graph env; -algorithm - (cache,env) := matchcontinue (icache,ienv,p,cl,name,elementLst,info,cleanCache) - local - list names,dependencies,strs; - list paths; - DAE.FunctionTree funcs; - list d; - list>> acc; - list sp; - String file,nameHeader,str; - Integer n; - - case (cache,env,_,_,_,_,SOURCEINFO(fileName=file),_) - equation - (1,_) = System.regex(file, "ModelicaBuiltin.mo$", 1, false, false); - then (cache,env); - - case (cache,env,_,_,_,_,_,_) - equation - cache = if cleanCache then FCore.emptyCache() else cache; - paths = List.fold1(elementLst, findFunctionsToCompile, Absyn.FULLYQUALIFIED(Absyn.IDENT(name)), {}); - cache = instantiateDaeFunctions(cache, env, paths); - funcs = FCore.getFunctionTree(cache); - d = List.map2(paths, DAEUtil.getNamedFunctionWithError, funcs, info); - (_,(_,dependencies)) = DAEUtil.traverseDAEFunctions(d,Expression.traverseSubexpressionsHelper,(matchQualifiedCalls,{}),{}); - // print(name + " has dependencies: " + stringDelimitList(dependencies,",") + "\n"); - dependencies = List.sort(dependencies,Util.strcmpBool); - dependencies = List.map1(dependencies,stringAppend,".h"); - nameHeader = name + ".h"; - strs = List.map1r(nameHeader::dependencies, stringAppend, "$(GEN_DIR)"); - System.writeFile(name + ".deps", "$(GEN_DIR)" + name + ".o: $(GEN_DIR)" + name + ".c" + " " + stringDelimitList(strs," ")); - dependencies = List.map1(dependencies,stringAppend,"\""); - dependencies = List.map1r(dependencies,stringAppend,"#include \""); - SimCodeMain.translateFunctions(p, name, NONE(), d, {}, dependencies); - str = Tpl.tplString(Unparsing.programExternalHeader, {cl}); - System.writeFile(name + "_records.c","#include \n" + str); - cache = if cleanCache then icache else cache; - then (cache,env); - else - equation - Error.addSourceMessage(Error.SEPARATE_COMPILATION_PACKAGE_FAILED,{name},info); - then fail(); - end matchcontinue; -end generateFunctions2; - -protected function matchQualifiedCalls -"Collects the packages used by the functions" - input DAE.Exp e; - input list acc; - output DAE.Exp outExp; - output list outAcc; -algorithm - (outExp,outAcc) := match (e,acc) - local - String name; - DAE.ComponentRef cr; - case (DAE.CALL(path = Absyn.FULLYQUALIFIED(Absyn.QUALIFIED(name=name)), attr = DAE.CALL_ATTR(builtin = false)),_) - equation - outAcc = List.consOnTrue(not listMember(name,acc),name,acc); - then (e,outAcc); - case (DAE.CREF(componentRef=cr,ty=DAE.T_FUNCTION_REFERENCE_FUNC(builtin=false)),_) - equation - Absyn.QUALIFIED(name,Absyn.IDENT(_)) = ComponentReference.crefToPath(cr); - outAcc = List.consOnTrue(not listMember(name,acc),name,acc); - then (e,outAcc); - else (e,acc); - end match; -end matchQualifiedCalls; - -protected function instantiateDaeFunctions - input FCore.Cache icache; - input FCore.Graph ienv; - input list ipaths; - output FCore.Cache outCache; -algorithm - outCache := match (icache,ienv,ipaths) - local - Absyn.Path path; - FCore.Cache cache; FCore.Graph env; - list paths; - case (cache,_,{}) then cache; - case (cache,env,path::paths) - equation - // print("force inst: " + Absyn.pathString(path)); - (cache,Util.SUCCESS()) = Static.instantiateDaeFunctionForceInst(cache,env,path,false,NONE(),true); - // print(" ok\n"); - cache = instantiateDaeFunctions(cache,env,paths); - then cache; - end match; -end instantiateDaeFunctions; - -protected function getBasePathFromUri "Handle modelica:// URIs" - input String scheme; - input String iname; - input Absyn.Program program; - input String modelicaPath; - input Boolean printError; - output String basePath; -algorithm - basePath := matchcontinue (scheme,iname,program,modelicaPath,printError) - local - Boolean isDir; - list mps,names; - String gd,mp,bp,str,name,version,fileName; - case ("modelica://",name,_,mp,_) - equation - (name::names) = System.strtok(name,"."); - Absyn.CLASS(info=SOURCEINFO(fileName=fileName)) = Interactive.getPathedClassInProgram(Absyn.IDENT(name),program); - mp = System.dirname(fileName); - bp = findModelicaPath2(mp,names,"",true); - then bp; - case ("modelica://",name,_,mp,_) - equation - (name::names) = System.strtok(name,"."); - failure(_ = Interactive.getPathedClassInProgram(Absyn.IDENT(name),program)); - gd = System.groupDelimiter(); - mps = System.strtok(mp, gd); - (mp,name,isDir) = System.getLoadModelPath(name, {"default"}, mps); - mp = if isDir then mp + name else mp; - bp = findModelicaPath2(mp,names,"",true); - then bp; - case ("file://",_,_,_,_) then ""; - case ("modelica://",name,_,mp,true) - equation - name::_ = System.strtok(name,"."); - str = "Could not resolve modelica://" + name + " with MODELICAPATH: " + mp; - Error.addMessage(Error.COMPILER_ERROR,{str}); - then fail(); - end matchcontinue; -end getBasePathFromUri; - -protected function findModelicaPath "Handle modelica:// URIs" - input list imps; - input list names; - input String version; - output String basePath; -algorithm - basePath := matchcontinue (imps,names,version) - local - String mp; - list mps; - - case (mp::_,_,_) - then findModelicaPath2(mp,names,version,false); - case (_::mps,_,_) - then findModelicaPath(mps,names,version); - end matchcontinue; -end findModelicaPath; - -protected function findModelicaPath2 "Handle modelica:// URIs" - input String mp; - input list inames; - input String version; - input Boolean b; - output String basePath; -algorithm - basePath := matchcontinue (mp,inames,version,b) - local - list names; - String name,file; - - case (_,name::names,_,_) - equation - false = stringEq(version,""); - file = mp + "/" + name + " " + version; - true = System.directoryExists(file); - // print("Found file 1: " + file + "\n"); - then findModelicaPath2(file,names,"",true); - case (_,name::_,_,_) - equation - false = stringEq(version,""); - file = mp + "/" + name + " " + version + ".mo"; - true = System.regularFileExists(file); - // print("Found file 2: " + file + "\n"); - then mp; - - case (_,name::names,_,_) - equation - file = mp + "/" + name; - true = System.directoryExists(file); - // print("Found file 3: " + file + "\n"); - then findModelicaPath2(file,names,"",true); - case (_,name::_,_,_) - equation - file = mp + "/" + name + ".mo"; - true = System.regularFileExists(file); - // print("Found file 4: " + file + "\n"); - then mp; - - // This class is part of the current package.mo, or whatever... - case (_,_,_,true) - equation - // print("Did not find file 5: " + mp + " - " + name + "\n"); - then mp; - end matchcontinue; -end findModelicaPath2; - -public function getFullPathFromUri - input Absyn.Program program; - input String uri; - input Boolean printError; - output String path; -protected - String str1,str2,str3; -algorithm - (str1,str2,str3) := System.uriToClassAndPath(uri); - path := getBasePathFromUri(str1,str2,program,Settings.getModelicaPath(Config.getRunningTestsuite()),printError) + str3; -end getFullPathFromUri; - -protected function errorToValue - input Error.TotalMessage err; - output Values.Value val; -algorithm - val := match err - local - Absyn.Path msgpath; - Values.Value tyVal,severityVal,infoVal; - list values; - Util.TranslatableContent message; - String msg_str; - Integer id; - Error.Severity severity; - Error.MessageType ty; - SourceInfo info; - case Error.TOTALMESSAGE(Error.MESSAGE(id,ty,severity,message),info) - equation - msg_str = Util.translateContent(message); - msgpath = Absyn.FULLYQUALIFIED(Absyn.QUALIFIED("OpenModelica",Absyn.QUALIFIED("Scripting",Absyn.IDENT("ErrorMessage")))); - tyVal = errorTypeToValue(ty); - severityVal = errorLevelToValue(severity); - infoVal = infoToValue(info); - values = {infoVal,Values.STRING(msg_str),tyVal,severityVal,Values.INTEGER(id)}; - then Values.RECORD(msgpath,values,{"info","message","kind","level","id"},-1); - end match; -end errorToValue; - -protected function infoToValue - input SourceInfo info; - output Values.Value val; -algorithm - val := match info - local - list values; - Absyn.Path infopath; - Integer ls,cs,le,ce; - String filename; - Boolean readonly; - case SOURCEINFO(filename,readonly,ls,cs,le,ce,_) - equation - infopath = Absyn.FULLYQUALIFIED(Absyn.QUALIFIED("OpenModelica",Absyn.QUALIFIED("Scripting",Absyn.IDENT("SourceInfo")))); - values = {Values.STRING(filename),Values.BOOL(readonly),Values.INTEGER(ls),Values.INTEGER(cs),Values.INTEGER(le),Values.INTEGER(ce)}; - then Values.RECORD(infopath,values,{"filename","readonly","lineStart","columnStart","lineEnd","columnEnd"},-1); - end match; -end infoToValue; - -protected function makeErrorEnumLiteral - input String enumName; - input String enumField; - input Integer index; - output Values.Value val; - annotation(__OpenModelica_EarlyInline=true); -algorithm - val := Values.ENUM_LITERAL(Absyn.FULLYQUALIFIED(Absyn.QUALIFIED("OpenModelica",Absyn.QUALIFIED("Scripting",Absyn.QUALIFIED(enumName,Absyn.IDENT(enumField))))),index); -end makeErrorEnumLiteral; - -protected function errorTypeToValue - input Error.MessageType ty; - output Values.Value val; -algorithm - val := match ty - case Error.SYNTAX() then makeErrorEnumLiteral("ErrorKind","syntax",1); - case Error.GRAMMAR() then makeErrorEnumLiteral("ErrorKind","grammar",2); - case Error.TRANSLATION() then makeErrorEnumLiteral("ErrorKind","translation",3); - case Error.SYMBOLIC() then makeErrorEnumLiteral("ErrorKind","symbolic",4); - case Error.SIMULATION() then makeErrorEnumLiteral("ErrorKind","runtime",5); - case Error.SCRIPTING() then makeErrorEnumLiteral("ErrorKind","scripting",6); - else - equation - print("errorTypeToValue failed\n"); - then fail(); - end match; -end errorTypeToValue; - -protected function errorLevelToValue - input Error.Severity severity; - output Values.Value val; -algorithm - val := match severity - case Error.ERROR() then makeErrorEnumLiteral("ErrorLevel","error",1); - case Error.WARNING() then makeErrorEnumLiteral("ErrorLevel","warning",2); - case Error.NOTIFICATION() then makeErrorEnumLiteral("ErrorLevel","notification",3); - else - equation - print("errorLevelToValue failed\n"); - then fail(); - end match; -end errorLevelToValue; - -protected function getVariableNames - input list vars; - input list acc; - output list ovars; -algorithm - ovars := match (vars,acc) - local - list vs; - String p; - case ({},_) then listReverse(acc); - case (GlobalScript.IVAR(varIdent = "$echo") :: vs,_) - then getVariableNames(vs,acc); - case (GlobalScript.IVAR(varIdent = p) :: vs,_) - then getVariableNames(vs,Values.CODE(Absyn.C_VARIABLENAME(Absyn.CREF_IDENT(p,{})))::acc); - end match; -end getVariableNames; - -protected function getAlgorithms -"Counts the number of Algorithm sections in a class." - input Absyn.Class inClass; - output list outList; -algorithm - outList := match (inClass) - local - list algsList; - list parts; - case Absyn.CLASS(body = Absyn.PARTS(classParts = parts)) - equation - algsList = getAlgorithmsInClassParts(parts); - then - algsList; - // check also the case model extends X end X; - case Absyn.CLASS(body = Absyn.CLASS_EXTENDS(parts = parts)) - equation - algsList = getAlgorithmsInClassParts(parts); - then - algsList; - case Absyn.CLASS(body = Absyn.DERIVED()) then {}; - end match; -end getAlgorithms; - -protected function getAlgorithmsInClassParts -"Helper function to getAlgorithms" - input list inAbsynClassPartLst; - output list outList; -algorithm - outList := matchcontinue (inAbsynClassPartLst) - local - list algsList; - list algs; - list xs; - Absyn.ClassPart cp; - case ((cp as Absyn.ALGORITHMS()) :: xs) - equation - algsList = getAlgorithmsInClassParts(xs); - then - cp::algsList; - case ((_ :: xs)) - equation - algsList = getAlgorithmsInClassParts(xs); - then - algsList; - case ({}) then {}; - end matchcontinue; -end getAlgorithmsInClassParts; - -protected function getNthAlgorithm -"Returns the Nth Algorithm section from a class." - input Absyn.Class inClass; - input Integer inInteger; - output String outString; - protected list algsList; -algorithm - algsList := getAlgorithms(inClass); - outString := getNthAlgorithmInClass(listGet(algsList, inInteger)); -end getNthAlgorithm; - -protected function getNthAlgorithmInClass -"Helper function to getNthAlgorithm." - input Absyn.ClassPart inClassPart; - output String outString; -algorithm - outString := match (inClassPart) - local - String str; - list algs; - case (Absyn.ALGORITHMS(contents = algs)) - equation - str = Dump.unparseAlgorithmStrLst(algs, "\n"); - then - str; - end match; -end getNthAlgorithmInClass; - -protected function getInitialAlgorithms -"Counts the number of Initial Algorithm sections in a class." - input Absyn.Class inClass; - output list outList; -algorithm - outList := match (inClass) - local - list algsList; - list parts; - case Absyn.CLASS(body = Absyn.PARTS(classParts = parts)) - equation - algsList = getInitialAlgorithmsInClassParts(parts); - then - algsList; - // check also the case model extends X end X; - case Absyn.CLASS(body = Absyn.CLASS_EXTENDS(parts = parts)) - equation - algsList = getInitialAlgorithmsInClassParts(parts); - then - algsList; - case Absyn.CLASS(body = Absyn.DERIVED()) then {}; - end match; -end getInitialAlgorithms; - -protected function getInitialAlgorithmsInClassParts -"Helper function to getInitialAlgorithms" - input list inAbsynClassPartLst; - output list outList; -algorithm - outList := matchcontinue (inAbsynClassPartLst) - local - list algsList; - list algs; - list xs; - Absyn.ClassPart cp; - case ((cp as Absyn.INITIALALGORITHMS()) :: xs) - equation - algsList = getInitialAlgorithmsInClassParts(xs); - then - cp::algsList; - case ((_ :: xs)) - equation - algsList = getInitialAlgorithmsInClassParts(xs); - then - algsList; - case ({}) then {}; - end matchcontinue; -end getInitialAlgorithmsInClassParts; - -protected function getNthInitialAlgorithm -"Returns the Nth Initial Algorithm section from a class." - input Absyn.Class inClass; - input Integer inInteger; - output String outString; - protected list algsList; -algorithm - algsList := getInitialAlgorithms(inClass); - outString := getNthInitialAlgorithmInClass(listGet(algsList, inInteger)); -end getNthInitialAlgorithm; - -protected function getNthInitialAlgorithmInClass -"Helper function to getNthInitialAlgorithm." - input Absyn.ClassPart inClassPart; - output String outString; -algorithm - outString := match (inClassPart) - local - String str; - list algs; - case (Absyn.INITIALALGORITHMS(contents = algs)) - equation - str = Dump.unparseAlgorithmStrLst(algs, "\n"); - then - str; - end match; -end getNthInitialAlgorithmInClass; - -protected function getAlgorithmItemsCount -"Counts the number of Algorithm items in a class." - input Absyn.Class inClass; - output Integer outInteger; -algorithm - outInteger := match (inClass) - local - list parts; - Integer count; - case Absyn.CLASS(body = Absyn.PARTS(classParts = parts)) - equation - count = getAlgorithmItemsCountInClassParts(parts); - then - count; - // check also the case model extends X end X; - case Absyn.CLASS(body = Absyn.CLASS_EXTENDS(parts = parts)) - equation - count = getAlgorithmItemsCountInClassParts(parts); - then - count; - case Absyn.CLASS(body = Absyn.DERIVED()) then 0; - end match; -end getAlgorithmItemsCount; - -protected function getAlgorithmItemsCountInClassParts -"Helper function to getAlgorithmItemsCount" - input list inAbsynClassPartLst; - output Integer outInteger; -algorithm - outInteger := matchcontinue (inAbsynClassPartLst) - local - list algs; - list xs; - Integer c1, c2, res; - case (Absyn.ALGORITHMS(contents = algs) :: xs) - equation - c1 = getAlgorithmItemsCountInAlgorithmItems(algs); - c2 = getAlgorithmItemsCountInClassParts(xs); - then - c1 + c2; - case ((_ :: xs)) - equation - res = getAlgorithmItemsCountInClassParts(xs); - then - res; - case ({}) then 0; - end matchcontinue; -end getAlgorithmItemsCountInClassParts; - -protected function getAlgorithmItemsCountInAlgorithmItems -"Helper function to getAlgorithmItemsCountInClassParts" - input list inAbsynAlgorithmItemLst; - output Integer outInteger; -algorithm - outInteger := matchcontinue (inAbsynAlgorithmItemLst) - local - list xs; - Absyn.Algorithm alg; - Integer c1, res; - case (Absyn.ALGORITHMITEM() :: xs) - equation - c1 = getAlgorithmItemsCountInAlgorithmItems(xs); - then - c1 + 1; - case ((_ :: xs)) - equation - res = getAlgorithmItemsCountInAlgorithmItems(xs); - then - res; - case ({}) then 0; - end matchcontinue; -end getAlgorithmItemsCountInAlgorithmItems; - -protected function getNthAlgorithmItem -"Returns the Nth Algorithm Item from a class." - input Absyn.Class inClass; - input Integer inInteger; - output String outString; -algorithm - outString := match (inClass,inInteger) - local - list parts; - String str; - Integer n; - case (Absyn.CLASS(body = Absyn.PARTS(classParts = parts)),n) - equation - str = getNthAlgorithmItemInClassParts(parts,n); - then - str; - // check also the case model extends X end X; - case (Absyn.CLASS(body = Absyn.CLASS_EXTENDS(parts = parts)),n) - equation - str = getNthAlgorithmItemInClassParts(parts,n); - then - str; - end match; -end getNthAlgorithmItem; - -protected function getNthAlgorithmItemInClassParts -"Helper function to getNthAlgorithmItem" - input list inAbsynClassPartLst; - input Integer inInteger; - output String outString; -algorithm - outString := matchcontinue (inAbsynClassPartLst,inInteger) - local - String str; - list algs; - list xs; - Integer n,c1,newn; - case ((Absyn.ALGORITHMS(contents = algs) :: _),n) - equation - str = getNthAlgorithmItemInAlgorithms(algs, n); - then - str; - case ((Absyn.ALGORITHMS(contents = algs) :: xs),n) /* The rule above failed, subtract the number of algorithms in the first section and try with the rest of the classparts */ - equation - c1 = getAlgorithmItemsCountInAlgorithmItems(algs); - newn = n - c1; - str = getNthAlgorithmItemInClassParts(xs, newn); - then - str; - case ((_ :: xs),n) - equation - str = getNthAlgorithmItemInClassParts(xs, n); - then - str; - end matchcontinue; -end getNthAlgorithmItemInClassParts; - -protected function getNthAlgorithmItemInAlgorithms -" This function takes an Algorithm list and an int - and returns the nth algorithm item as String. - If the number is larger than the number of algorithms - in the list, the function fails. Helper function to getNthAlgorithmItemInClassParts." - input list inAbsynAlgorithmItemLst; - input Integer inInteger; - output String outString; -algorithm - outString := matchcontinue (inAbsynAlgorithmItemLst,inInteger) - local - String str; - Absyn.Algorithm alg; - Option cmt; - SourceInfo inf; - list xs; - Integer newn,n; - case ((Absyn.ALGORITHMITEM(algorithm_ = alg, comment = cmt, info = inf) :: _), 1) - equation - str = Dump.unparseAlgorithmStr(Absyn.ALGORITHMITEM(alg, cmt, inf)); - then - str; - case ((_ :: xs),n) - equation - newn = n - 1; - str = getNthAlgorithmItemInAlgorithms(xs, newn); - then - str; - case ({},_) then fail(); - end matchcontinue; -end getNthAlgorithmItemInAlgorithms; - -protected function getInitialAlgorithmItemsCount -"Counts the number of Initial Algorithm items in a class." - input Absyn.Class inClass; - output Integer outInteger; -algorithm - outInteger := match (inClass) - local - list parts; - Integer count; - case Absyn.CLASS(body = Absyn.PARTS(classParts = parts)) - equation - count = getInitialAlgorithmItemsCountInClassParts(parts); - then - count; - // check also the case model extends X end X; - case Absyn.CLASS(body = Absyn.CLASS_EXTENDS(parts = parts)) - equation - count = getInitialAlgorithmItemsCountInClassParts(parts); - then - count; - case Absyn.CLASS(body = Absyn.DERIVED()) then 0; - end match; -end getInitialAlgorithmItemsCount; - -protected function getInitialAlgorithmItemsCountInClassParts -"Helper function to getInitialAlgorithmItemsCount" - input list inAbsynClassPartLst; - output Integer outInteger; -algorithm - outInteger := matchcontinue (inAbsynClassPartLst) - local - list algs; - list xs; - Integer c1, c2, res; - case (Absyn.INITIALALGORITHMS(contents = algs) :: xs) - equation - c1 = getAlgorithmItemsCountInAlgorithmItems(algs); - c2 = getInitialAlgorithmItemsCountInClassParts(xs); - then - c1 + c2; - case ((_ :: xs)) - equation - res = getInitialAlgorithmItemsCountInClassParts(xs); - then - res; - case ({}) then 0; - end matchcontinue; -end getInitialAlgorithmItemsCountInClassParts; - -protected function getNthInitialAlgorithmItem -"Returns the Nth Initial Algorithm Item from a class." - input Absyn.Class inClass; - input Integer inInteger; - output String outString; -algorithm - outString := match (inClass,inInteger) - local - list parts; - String str; - Integer n; - case (Absyn.CLASS(body = Absyn.PARTS(classParts = parts)),n) - equation - str = getNthInitialAlgorithmItemInClassParts(parts,n); - then - str; - // check also the case model extends X end X; - case (Absyn.CLASS(body = Absyn.CLASS_EXTENDS(parts = parts)),n) - equation - str = getNthInitialAlgorithmItemInClassParts(parts,n); - then - str; - end match; -end getNthInitialAlgorithmItem; - -protected function getNthInitialAlgorithmItemInClassParts -"Helper function to getNthInitialAlgorithmItem" - input list inAbsynClassPartLst; - input Integer inInteger; - output String outString; -algorithm - outString := matchcontinue (inAbsynClassPartLst,inInteger) - local - String str; - list algs; - list xs; - Integer n,c1,newn; - case ((Absyn.INITIALALGORITHMS(contents = algs) :: _),n) - equation - str = getNthAlgorithmItemInAlgorithms(algs, n); - then - str; - case ((Absyn.INITIALALGORITHMS(contents = algs) :: xs),n) /* The rule above failed, subtract the number of algorithms in the first section and try with the rest of the classparts */ - equation - c1 = getAlgorithmItemsCountInAlgorithmItems(algs); - newn = n - c1; - str = getNthInitialAlgorithmItemInClassParts(xs, newn); - then - str; - case ((_ :: xs),n) - equation - str = getNthInitialAlgorithmItemInClassParts(xs, n); - then - str; - end matchcontinue; -end getNthInitialAlgorithmItemInClassParts; - -protected function getEquations -"Counts the number of Equation sections in a class." - input Absyn.Class inClass; - output list outList; -algorithm - outList := match (inClass) - local - list eqsList; - list parts; - case Absyn.CLASS(body = Absyn.PARTS(classParts = parts)) - equation - eqsList = getEquationsInClassParts(parts); - then - eqsList; - // check also the case model extends X end X; - case Absyn.CLASS(body = Absyn.CLASS_EXTENDS(parts = parts)) - equation - eqsList = getEquationsInClassParts(parts); - then - eqsList; - case Absyn.CLASS(body = Absyn.DERIVED()) then {}; - end match; -end getEquations; - -protected function getEquationsInClassParts -"Helper function to getEquations" - input list inAbsynClassPartLst; - output list outList; -algorithm - outList := matchcontinue (inAbsynClassPartLst) - local - list eqsList; - list eqs; - list xs; - Absyn.ClassPart cp; - case ((cp as Absyn.EQUATIONS()) :: xs) - equation - eqsList = getEquationsInClassParts(xs); - then - cp::eqsList; - case ((_ :: xs)) - equation - eqsList = getEquationsInClassParts(xs); - then - eqsList; - case ({}) then {}; - end matchcontinue; -end getEquationsInClassParts; - -protected function getNthEquation -"Returns the Nth Equation section from a class." - input Absyn.Class inClass; - input Integer inInteger; - output String outString; - protected list eqsList; -algorithm - eqsList := getEquations(inClass); - outString := getNthEquationInClass(listGet(eqsList, inInteger)); -end getNthEquation; - -protected function getNthEquationInClass -"Helper function to getNthEquation" - input Absyn.ClassPart inClassPart; - output String outString; -algorithm - outString := match (inClassPart) - local - String str; - list eqs; - case (Absyn.EQUATIONS(contents = eqs)) - equation - str = Dump.unparseEquationItemStrLst(eqs, "\n"); - then - str; - end match; -end getNthEquationInClass; - -protected function getInitialEquations -"Counts the number of Initial Equation sections in a class." - input Absyn.Class inClass; - output list outList; -algorithm - outList := match (inClass) - local - list eqsList; - list parts; - case Absyn.CLASS(body = Absyn.PARTS(classParts = parts)) - equation - eqsList = getInitialEquationsInClassParts(parts); - then - eqsList; - // check also the case model extends X end X; - case Absyn.CLASS(body = Absyn.CLASS_EXTENDS(parts = parts)) - equation - eqsList = getInitialEquationsInClassParts(parts); - then - eqsList; - case Absyn.CLASS(body = Absyn.DERIVED()) then {}; - end match; -end getInitialEquations; - -protected function getInitialEquationsInClassParts -"Helper function to getInitialEquations" - input list inAbsynClassPartLst; - output list outList; -algorithm - outList := matchcontinue (inAbsynClassPartLst) - local - list eqsList; - list eqs; - list xs; - Absyn.ClassPart cp; - case ((cp as Absyn.INITIALEQUATIONS()) :: xs) - equation - eqsList = getInitialEquationsInClassParts(xs); - then - cp::eqsList; - case ((_ :: xs)) - equation - eqsList = getInitialEquationsInClassParts(xs); - then - eqsList; - case ({}) then {}; - end matchcontinue; -end getInitialEquationsInClassParts; - -protected function getNthInitialEquation -"Returns the Nth Initial Equation section from a class." - input Absyn.Class inClass; - input Integer inInteger; - output String outString; - protected list eqsList; -algorithm - eqsList := getInitialEquations(inClass); - outString := getNthInitialEquationInClass(listGet(eqsList, inInteger)); -end getNthInitialEquation; - -protected function getNthInitialEquationInClass -"Helper function to getNthInitialEquation." - input Absyn.ClassPart inClassPart; - output String outString; -algorithm - outString := match (inClassPart) - local - String str; - list eqs; - case (Absyn.INITIALEQUATIONS(contents = eqs)) - equation - str = Dump.unparseEquationItemStrLst(eqs, "\n"); - then - str; - end match; -end getNthInitialEquationInClass; - -protected function getEquationItemsCount -"Counts the number of Equation items in a class." - input Absyn.Class inClass; - output Integer outInteger; -algorithm - outInteger := match (inClass) - local - list parts; - Integer count; - case Absyn.CLASS(body = Absyn.PARTS(classParts = parts)) - equation - count = getEquationItemsCountInClassParts(parts); - then - count; - // check also the case model extends X end X; - case Absyn.CLASS(body = Absyn.CLASS_EXTENDS(parts = parts)) - equation - count = getEquationItemsCountInClassParts(parts); - then - count; - case Absyn.CLASS(body = Absyn.DERIVED()) then 0; - end match; -end getEquationItemsCount; - -protected function getEquationItemsCountInClassParts -"Helper function to getEquationItemsCount" - input list inAbsynClassPartLst; - output Integer outInteger; -algorithm - outInteger := matchcontinue (inAbsynClassPartLst) - local - list eqs; - list xs; - Integer c1, c2, res; - case (Absyn.EQUATIONS(contents = eqs) :: xs) - equation - c1 = getEquationItemsCountInEquationItems(eqs); - c2 = getEquationItemsCountInClassParts(xs); - then - c1 + c2; - case ((_ :: xs)) - equation - res = getEquationItemsCountInClassParts(xs); - then - res; - case ({}) then 0; - end matchcontinue; -end getEquationItemsCountInClassParts; - -protected function getEquationItemsCountInEquationItems -"Helper function to getEquationItemsCountInClassParts" - input list inAbsynEquationItemLst; - output Integer outInteger; -algorithm - outInteger := matchcontinue (inAbsynEquationItemLst) - local - list xs; - Absyn.Equation eq; - Integer c1, res; - case (Absyn.EQUATIONITEM() :: xs) - equation - c1 = getEquationItemsCountInEquationItems(xs); - then - c1 + 1; - case ((_ :: xs)) - equation - res = getEquationItemsCountInEquationItems(xs); - then - res; - case ({}) then 0; - end matchcontinue; -end getEquationItemsCountInEquationItems; - -protected function getNthEquationItem -"Returns the Nth Equation Item from a class." - input Absyn.Class inClass; - input Integer inInteger; - output String outString; -algorithm - outString := match (inClass,inInteger) - local - list parts; - String str; - Integer n; - case (Absyn.CLASS(body = Absyn.PARTS(classParts = parts)),n) - equation - str = getNthEquationItemInClassParts(parts,n); - then - str; - // check also the case model extends X end X; - case (Absyn.CLASS(body = Absyn.CLASS_EXTENDS(parts = parts)),n) - equation - str = getNthEquationItemInClassParts(parts,n); - then - str; - end match; -end getNthEquationItem; - -protected function getNthEquationItemInClassParts -"Helper function to getNthEquationItem" - input list inAbsynClassPartLst; - input Integer inInteger; - output String outString; -algorithm - outString := matchcontinue (inAbsynClassPartLst,inInteger) - local - String str; - list eqs; - list xs; - Integer n,c1,newn; - case ((Absyn.EQUATIONS(contents = eqs) :: _),n) - equation - str = getNthEquationItemInEquations(eqs, n); - then - str; - case ((Absyn.EQUATIONS(contents = eqs) :: xs),n) /* The rule above failed, subtract the number of equations in the first section and try with the rest of the classparts */ - equation - c1 = getEquationItemsCountInEquationItems(eqs); - newn = n - c1; - str = getNthEquationItemInClassParts(xs, newn); - then - str; - case ((_ :: xs),n) - equation - str = getNthEquationItemInClassParts(xs, n); - then - str; - end matchcontinue; -end getNthEquationItemInClassParts; - -protected function getNthEquationItemInEquations -" This function takes an Equation list and an int - and returns the nth Equation item as String. - If the number is larger than the number of algorithms - in the list, the function fails. Helper function to getNthEquationItemInClassParts." - input list inAbsynEquationItemLst; - input Integer inInteger; - output String outString; -algorithm - outString := matchcontinue (inAbsynEquationItemLst,inInteger) - local - String str; - Absyn.Equation eq; - list xs; - Integer newn,n; - case ((Absyn.EQUATIONITEM(equation_ = eq) :: _), 1) - equation - str = Dump.unparseEquationStr(eq); - str = stringAppend(str, ";"); - str = System.trim(str, " "); - then - str; - case ((_ :: xs),n) - equation - newn = n - 1; - str = getNthEquationItemInEquations(xs, newn); - then - str; - case ({},_) then fail(); - end matchcontinue; -end getNthEquationItemInEquations; - -protected function getInitialEquationItemsCount -"Counts the number of Initial Equation items in a class." - input Absyn.Class inClass; - output Integer outInteger; -algorithm - outInteger := match (inClass) - local - list parts; - Integer count; - case Absyn.CLASS(body = Absyn.PARTS(classParts = parts)) - equation - count = getInitialEquationItemsCountInClassParts(parts); - then - count; - // check also the case model extends X end X; - case Absyn.CLASS(body = Absyn.CLASS_EXTENDS(parts = parts)) - equation - count = getInitialEquationItemsCountInClassParts(parts); - then - count; - case Absyn.CLASS(body = Absyn.DERIVED()) then 0; - end match; -end getInitialEquationItemsCount; - -protected function getInitialEquationItemsCountInClassParts -"Helper function to getInitialEquationItemsCount" - input list inAbsynClassPartLst; - output Integer outInteger; -algorithm - outInteger := matchcontinue (inAbsynClassPartLst) - local - list eqs; - list xs; - Integer c1, c2, res; - case (Absyn.INITIALEQUATIONS(contents = eqs) :: xs) - equation - c1 = getEquationItemsCountInEquationItems(eqs); - c2 = getInitialEquationItemsCountInClassParts(xs); - then - c1 + c2; - case ((_ :: xs)) - equation - res = getInitialEquationItemsCountInClassParts(xs); - then - res; - case ({}) then 0; - end matchcontinue; -end getInitialEquationItemsCountInClassParts; - -protected function getNthInitialEquationItem -"Returns the Nth Initial Equation Item from a class." - input Absyn.Class inClass; - input Integer inInteger; - output String outString; -algorithm - outString := match (inClass,inInteger) - local - list parts; - String str; - Integer n; - case (Absyn.CLASS(body = Absyn.PARTS(classParts = parts)),n) - equation - str = getNthInitialEquationItemInClassParts(parts,n); - then - str; - // check also the case model extends X end X; - case (Absyn.CLASS(body = Absyn.CLASS_EXTENDS(parts = parts)),n) - equation - str = getNthInitialEquationItemInClassParts(parts,n); - then - str; - end match; -end getNthInitialEquationItem; - -protected function getNthInitialEquationItemInClassParts -"Helper function to getNthInitialEquationItem" - input list inAbsynClassPartLst; - input Integer inInteger; - output String outString; -algorithm - outString := matchcontinue (inAbsynClassPartLst,inInteger) - local - String str; - list eqs; - list xs; - Integer n,c1,newn; - case ((Absyn.INITIALEQUATIONS(contents = eqs) :: _),n) - equation - str = getNthEquationItemInEquations(eqs, n); - then - str; - case ((Absyn.INITIALEQUATIONS(contents = eqs) :: xs),n) /* The rule above failed, subtract the number of equations in the first section and try with the rest of the classparts */ - equation - c1 = getEquationItemsCountInEquationItems(eqs); - newn = n - c1; - str = getNthInitialEquationItemInClassParts(xs, newn); - then - str; - case ((_ :: xs),n) - equation - str = getNthInitialEquationItemInClassParts(xs, n); - then - str; - end matchcontinue; -end getNthInitialEquationItemInClassParts; - -protected function getAnnotationCount -"Counts the number of Annotation sections in a class." - input Absyn.Class inClass; - output Integer outInteger; -algorithm - outInteger := match (inClass) - local - list ann; - Integer count; - case Absyn.CLASS(body = Absyn.PARTS(ann = ann)) - then listLength(ann); - // check also the case model extends X end X; - case Absyn.CLASS(body = Absyn.CLASS_EXTENDS(ann = ann)) - then listLength(ann); - case Absyn.CLASS(body = Absyn.DERIVED()) then 0; - end match; -end getAnnotationCount; - -protected function getNthAnnotationString -"Returns the Nth Annotation String from a class." - input Absyn.Class inClass; - input Integer inInteger; - output String outString; -algorithm - outString := match (inClass,inInteger) - local - list anns; - Absyn.Annotation ann; - String str; - Integer n; - case (Absyn.CLASS(body = Absyn.PARTS(ann = anns)),n) - equation - ann = listGet(anns,n); - str = Dump.unparseAnnotation(ann); - str = stringAppend(str, ";"); - str = System.trim(str, " "); - then - str; - // check also the case model extends X end X; - case (Absyn.CLASS(body = Absyn.CLASS_EXTENDS(ann = anns)),n) - equation - ann = listGet(anns,n); - str = Dump.unparseAnnotation(ann); - str = stringAppend(str, ";"); - str = System.trim(str, " "); - then - str; - end match; -end getNthAnnotationString; - -protected function getImportCount -"Counts the number of Import sections in a class." - input Absyn.Class inClass; - output Integer outInteger; -algorithm - outInteger := match (inClass) - local - list parts; - Integer count; - case Absyn.CLASS(body = Absyn.PARTS(classParts = parts)) - equation - count = getImportsInClassParts(parts); - then - count; - // check also the case model extends X end X; - case Absyn.CLASS(body = Absyn.CLASS_EXTENDS(parts = parts)) - equation - count = getImportsInClassParts(parts); - then - count; - case Absyn.CLASS(body = Absyn.DERIVED()) then 0; - end match; -end getImportCount; - -protected function getImportsInClassParts -"Helper function to getImportCount" - input list inAbsynClassPartLst; - output Integer outInteger; -algorithm - outInteger := matchcontinue (inAbsynClassPartLst) - local - list els; - list xs; - Integer c1, c2, res; - case (Absyn.PUBLIC(contents = els) :: xs) - equation - c1 = getImportsInElementItems(els); - c2 = getImportsInClassParts(xs); - then - c1 + c2; - case (Absyn.PROTECTED(contents = els) :: xs) - equation - c1 = getImportsInElementItems(els); - c2 = getImportsInClassParts(xs); - then - c1 + c2; - case ((_ :: xs)) - equation - res = getImportsInClassParts(xs); - then - res; - case ({}) then 0; - end matchcontinue; -end getImportsInClassParts; - -protected function getImportsInElementItems -"Helper function to getImportCount" - input list inAbsynElementItemLst; - output Integer outInteger; -algorithm - outInteger := matchcontinue (inAbsynElementItemLst) - local - Absyn.Import import_; - list els; - Integer c1, res; - case (Absyn.ELEMENTITEM(element = Absyn.ELEMENT(specification = Absyn.IMPORT())) :: els) - equation - c1 = getImportsInElementItems(els); - then - c1 + 1; - case ((_ :: els)) - equation - res = getImportsInElementItems(els); - then - res; - case ({}) then 0; - end matchcontinue; -end getImportsInElementItems; - -protected function getNthImport -"Returns the Nth Import String from a class." - input Absyn.Class inClass; - input Integer inInteger; - output list outValue; -algorithm - outValue := match (inClass,inInteger) - local - list parts; - list vals; - Integer n; - case (Absyn.CLASS(body = Absyn.PARTS(classParts = parts)),n) - equation - vals = getNthImportInClassParts(parts,n); - then - vals; - // check also the case model extends X end X; - case (Absyn.CLASS(body = Absyn.CLASS_EXTENDS(parts = parts)),n) - equation - vals = getNthImportInClassParts(parts,n); - then - vals; - end match; -end getNthImport; - -protected function getNthImportInClassParts -"Helper function to getNthImport" - input list inAbsynClassPartLst; - input Integer inInteger; - output list outValue; -algorithm - outValue := matchcontinue (inAbsynClassPartLst,inInteger) - local - list vals; - list els; - list xs; - Integer n,c1,newn; - case ((Absyn.PUBLIC(contents = els) :: _),n) - equation - vals = getNthImportInElementItems(els, n); - then - vals; - case ((Absyn.PUBLIC(contents = els) :: xs),n) /* The rule above failed, subtract the number of imports in the first section and try with the rest of the classparts */ - equation - c1 = getImportsInElementItems(els); - newn = n - c1; - vals = getNthImportInClassParts(xs, newn); - then - vals; - case ((Absyn.PROTECTED(contents = els) :: _),n) - equation - vals = getNthImportInElementItems(els, n); - then - vals; - case ((Absyn.PROTECTED(contents = els) :: xs),n) /* The rule above failed, subtract the number of imports in the first section and try with the rest of the classparts */ - equation - c1 = getImportsInElementItems(els); - newn = n - c1; - vals = getNthImportInClassParts(xs, newn); - then - vals; - case ((_ :: xs),n) - equation - vals = getNthImportInClassParts(xs, n); - then - vals; - end matchcontinue; -end getNthImportInClassParts; - -protected function getNthImportInElementItems -" This function takes an Element list and an int - and returns the nth import as string. - If the number is larger than the number of annotations - in the list, the function fails. Helper function to getNthImport." - input list inAbsynElementItemLst; - input Integer inInteger; - output list outValue; -algorithm - outValue := matchcontinue (inAbsynElementItemLst,inInteger) - local - list vals; - Absyn.Import import_; - list els; - Integer newn,n; - case ((Absyn.ELEMENTITEM(element = Absyn.ELEMENT(specification = Absyn.IMPORT(import_ = import_))) :: _), 1) - equation - vals = unparseNthImport(import_); - then - vals; - case ((Absyn.ELEMENTITEM(element = Absyn.ELEMENT(specification = Absyn.IMPORT())) :: els), n) - equation - newn = n - 1; - vals = getNthImportInElementItems(els, newn); - then - vals; - case ((_ :: els),n) - equation - vals = getNthImportInElementItems(els, n); - then - vals; - case ({},_) then fail(); - end matchcontinue; -end getNthImportInElementItems; - -public function unparseNthImport -" helperfunction to getNthImport." - input Absyn.Import inImport; - output list outValue; -algorithm - outValue := match (inImport) - local - list vals; - list gi; - String path_str,id; - Absyn.Path path; - case (Absyn.NAMED_IMPORT(name = id,path = path)) - equation - path_str = Absyn.pathString(path); - vals = {Values.STRING(path_str),Values.STRING(id),Values.STRING("named")}; - then - vals; - case (Absyn.QUAL_IMPORT(path = path)) - equation - path_str = Absyn.pathString(path); - vals = {Values.STRING(path_str),Values.STRING(""),Values.STRING("qualified")}; - then - vals; - case (Absyn.UNQUAL_IMPORT(path = path)) - equation - path_str = Absyn.pathString(path); - path_str = stringAppendList({path_str, ".*"}); - vals = {Values.STRING(path_str),Values.STRING(""),Values.STRING("unqualified")}; - then - vals; - case (Absyn.GROUP_IMPORT(prefix = path, groups = gi)) - equation - path_str = Absyn.pathString(path); - id = stringDelimitList(unparseGroupImport(gi),","); - path_str = stringAppendList({path_str,".{",id,"}"}); - vals = {Values.STRING(path_str),Values.STRING(""),Values.STRING("multiple")}; - then - vals; - end match; -end unparseNthImport; - -protected function unparseGroupImport - input list inAbsynGroupImportLst; - output list outList; -algorithm - outList := matchcontinue (inAbsynGroupImportLst) - local - list rest; - list lst; - String str; - case {} then {}; - case (Absyn.GROUP_IMPORT_NAME(name = str) :: rest) - equation - lst = unparseGroupImport(rest); - then - (str::lst); - case ((_ :: rest)) - equation - lst = unparseGroupImport(rest); - then - lst; - end matchcontinue; -end unparseGroupImport; - -public function evalCodeTypeName - input Values.Value val; - input FCore.Graph env; - output Values.Value res; -algorithm - res := matchcontinue (val,env) - local - Absyn.Path path; - case (Values.CODE(Absyn.C_TYPENAME(path as Absyn.IDENT(_) /* We only want to lookup idents in the symboltable; also speeds up e.g. simulate(Modelica.A.B.C) so we do not instantiate all classes */)),_) - equation - (_,_,_,DAE.VALBOUND(valBound=res as Values.CODE(A=Absyn.C_TYPENAME())),_,_,_,_,_) = Lookup.lookupVar(FCore.emptyCache(), env, ComponentReference.pathToCref(path)); - then res; - else val; - end matchcontinue; -end evalCodeTypeName; - -public function isShortDefinition -"@auhtor:adrpo - returns true if the class is derived or false otherwise" - input Absyn.Path inPath; - input Absyn.Program inProgram; - output Boolean outBoolean; -algorithm - outBoolean:= - matchcontinue (inPath,inProgram) - local - Absyn.Path path; - Absyn.Program p; - case (path,p) - equation - Absyn.CLASS(body = Absyn.DERIVED()) = Interactive.getPathedClassInProgram(path, p); - then - true; - else false; - end matchcontinue; -end isShortDefinition; - -protected function getPackageVersion - input Absyn.Path path; - input Absyn.Program p; - output String version; -algorithm - version := matchcontinue (path,p) - case (_,_) - equation - Config.setEvaluateParametersInAnnotations(true); - Absyn.STRING(version) = Interactive.getNamedAnnotation(path, p, Absyn.IDENT("version"), SOME(Absyn.STRING("")), Interactive.getAnnotationExp); - Config.setEvaluateParametersInAnnotations(false); - then version; - else ""; - end matchcontinue; -end getPackageVersion; - -protected function hasStopTime "For use with getNamedAnnotation" - input Option mod; - output Boolean b; -algorithm - b := match (mod) - local - list arglst; - case (SOME(Absyn.CLASSMOD(elementArgLst = arglst))) - then List.exist(arglst,hasStopTime2); - - end match; -end hasStopTime; - -protected function hasStopTime2 "For use with getNamedAnnotation" - input Absyn.ElementArg arg; - output Boolean b; -algorithm - b := match (arg) - local - - case Absyn.MODIFICATION(path=Absyn.IDENT(name="StopTime")) then true; - else false; - - end match; -end hasStopTime2; - -public 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 FCore.Cache inCache; - input FCore.Graph inEnv; - input DAE.Exp inExp; - input list inValuesValueLst; - input Boolean impl; - input Option inSymTab; - input Absyn.Msg inMsg; - input Boolean bIsCompleteFunction; - output FCore.Cache outCache; - output Values.Value outValue; - output Option outSymTab; -algorithm - (outCache,outValue,outSymTab) := matchcontinue (inCache,inEnv,inExp,inValuesValueLst,impl,inSymTab,inMsg,bIsCompleteFunction) - local - Values.Value newval; - FCore.Graph env; - DAE.Exp e; - Absyn.Path funcpath; - list expl; - Boolean print_debug; - list vallst; - Absyn.Msg msg; - FCore.Cache cache; - list cflist; - Option st; - Absyn.Program p; - Integer libHandle, funcHandle; - String fNew,fOld; - Real buildTime, edit, build; - Option> a; - list b; - list c; - list cf; - list lf; - String funcstr,f,fileName; - list newCF; - String name; - Boolean ppref, fpref, epref; - Absyn.ClassDef body; - SourceInfo info; - Absyn.Within w; - list functionDependencies; - SCode.Element sc; - SCode.ClassDef cdef; - String error_Str; - DAE.Function func; - SCode.Restriction res; - GlobalScript.SymbolTable syt; - Absyn.FunctionRestriction funcRest; - DAE.Type ty; - - // try function interpretation - case (cache,env, DAE.CALL(path = funcpath, attr = DAE.CALL_ATTR(builtin = false)), vallst, _, st, msg, _) - equation - true = Flags.isSet(Flags.EVAL_FUNC); - failure(cevalIsExternalObjectConstructor(cache, funcpath, env, msg)); - // bcall1(Flags.isSet(Flags.DYN_LOAD), print,"[dynload]: try constant evaluation: " + Absyn.pathString(funcpath) + "\n"); - (cache, - sc as SCode.CLASS(partialPrefix = SCode.NOT_PARTIAL()), - env) = Lookup.lookupClass(cache, env, funcpath, false); - isCevaluableFunction(sc); - (cache, env, _) = InstFunction.implicitFunctionInstantiation( - cache, - env, - InnerOuter.emptyInstHierarchy, - DAE.NOMOD(), - Prefix.NOPRE(), - sc, - {}); - func = FCore.getCachedInstFunc(cache, funcpath); - (cache, newval, st) = CevalFunction.evaluate(cache, env, func, vallst, st); - // bcall1(Flags.isSet(Flags.DYN_LOAD), print, "[dynload]: constant evaluation SUCCESS: " + Absyn.pathString(funcpath) + "\n"); - then - (cache, newval, st); - - // see if function is in CF list and the build time is less than the edit time - case (cache,env,(DAE.CALL(path = funcpath, attr = DAE.CALL_ATTR(builtin = false))),vallst,_,// (impl as true) - (st as SOME(GlobalScript.SYMBOLTABLE(ast=p as Absyn.PROGRAM(),compiledFunctions=cflist))),msg, _) - equation - true = bIsCompleteFunction; - true = Flags.isSet(Flags.GEN); - failure(cevalIsExternalObjectConstructor(cache,funcpath,env,msg)); - if Flags.isSet(Flags.DYN_LOAD) then - Debug.traceln("[dynload]: [func from file] check if is in CF list: " + Absyn.pathString(funcpath)); - end if; - - (true, funcHandle, buildTime, fOld) = Static.isFunctionInCflist(cflist, funcpath); - Absyn.CLASS(_,_,_,_,Absyn.R_FUNCTION(_),_,SOURCEINFO(fileName = fNew)) = Interactive.getPathedClassInProgram(funcpath, p); - // see if the build time from the class is the same as the build time from the compiled functions list - false = stringEq(fNew,""); // see if the WE have a file or not! - false = Static.needToRebuild(fNew,fOld,buildTime); // we don't need to rebuild! - - if Flags.isSet(Flags.DYN_LOAD) then - print("[dynload]: [func from file] About to execute function present in CF list: " + Absyn.pathString(funcpath) + "\n"); - end if; - - print_debug = Flags.isSet(Flags.DYN_LOAD); - newval = DynLoad.executeFunction(funcHandle, vallst, print_debug); - //print("CALL: [func from file] CF LIST:\n\t" + stringDelimitList(List.map(cflist, Interactive.dumpCompiledFunction), "\n\t") + "\n"); - then - (cache,newval,st); - - // see if function is in CF list and the build time is less than the edit time - case (cache,env,(DAE.CALL(path = funcpath, attr = DAE.CALL_ATTR(builtin = false))),vallst,_,// impl as true - (st as SOME(GlobalScript.SYMBOLTABLE(ast=p as Absyn.PROGRAM(),compiledFunctions=cflist))), msg, _) - equation - true = bIsCompleteFunction; - true = Flags.isSet(Flags.GEN); - failure(cevalIsExternalObjectConstructor(cache,funcpath,env,msg)); - - if Flags.isSet(Flags.DYN_LOAD) then - print("[dynload]: [func from buffer] check if is in CF list: " + Absyn.pathString(funcpath) + "\n"); - end if; - - (true, funcHandle, buildTime, _) = Static.isFunctionInCflist(cflist, funcpath); - Absyn.CLASS(restriction=Absyn.R_FUNCTION(_),info=SOURCEINFO(fileName = fNew, lastModification = edit)) = Interactive.getPathedClassInProgram(funcpath, p); - // note, this should only work for classes that have no file name! - true = stringEq(fNew,""); // see that we don't have a file! - - // see if the build time from the class is the same as the build time from the compiled functions list - true = buildTime > edit; - - if Flags.isSet(Flags.DYN_LOAD) then - print("[dynload]: [func from buffer] About to execute function present in CF list: " + Absyn.pathString(funcpath) + "\n"); - end if; - - newval = DynLoad.executeFunction(funcHandle, vallst, Flags.isSet(Flags.DYN_LOAD)); - then - (cache,newval,st); - - // not in CF list, we have a symbol table, generate function and update symtab - case (cache,env,(DAE.CALL(path = funcpath,attr = DAE.CALL_ATTR(builtin = false))),vallst,_, - SOME(syt as GlobalScript.SYMBOLTABLE(p as Absyn.PROGRAM(),a,b,c,cf,lf)), msg, _) // yeha! we have a symboltable! - equation - true = bIsCompleteFunction; - true = Flags.isSet(Flags.GEN); - failure(cevalIsExternalObjectConstructor(cache,funcpath,env,msg)); - - if Flags.isSet(Flags.DYN_LOAD) then - print("[dynload]: [SOME SYMTAB] not in in CF list: " + Absyn.pathString(funcpath) + "\n"); - end if; - - // remove it and all its dependencies as it might be there with an older build time. - // get dependencies! - (_, functionDependencies, _) = getFunctionDependencies(cache, funcpath); - //print("\nFunctions before:\n\t" + stringDelimitList(List.map(cf, Interactive.dumpCompiledFunction), "\n\t") + "\n"); - newCF = Interactive.removeCfAndDependencies(cf, funcpath::functionDependencies); - //print("\nFunctions after remove:\n\t" + stringDelimitList(List.map(newCF, Interactive.dumpCompiledFunction), "\n\t") + "\n"); - - if Flags.isSet(Flags.DYN_LOAD) then - print("[dynload]: [SOME SYMTAB] not in in CF list: removed deps:" + - stringDelimitList(List.map(functionDependencies, Absyn.pathString) ,", ") + "\n"); - end if; - //print("\nfunctions in SYMTAB: " + Interactive.dumpCompiledFunctions(syt) - - // now is safe to generate code - (cache, funcstr, fileName) = cevalGenerateFunction(cache, env, p, funcpath); - print_debug = Flags.isSet(Flags.DYN_LOAD); - libHandle = System.loadLibrary(fileName, print_debug); - funcHandle = System.lookupFunction(libHandle, stringAppend("in_", funcstr)); - newval = DynLoad.executeFunction(funcHandle, vallst, print_debug); - System.freeLibrary(libHandle, print_debug); - buildTime = System.getCurrentTime(); - // update the build time in the class! - Absyn.CLASS(_,_,_,_,Absyn.R_FUNCTION(_),_,info) = Interactive.getPathedClassInProgram(funcpath, p); - - /* info = Absyn.setBuildTimeInInfo(buildTime,info); - ts = Absyn.setTimeStampBuild(ts, buildTime); */ - w = Interactive.buildWithin(funcpath); - - if Flags.isSet(Flags.DYN_LOAD) then - print("[dynload]: Updating build time for function path: " + Absyn.pathString(funcpath) + " within: " + Dump.unparseWithin(w) + "\n"); - end if; - - // p = Interactive.updateProgram(Absyn.PROGRAM({Absyn.CLASS(name,ppref,fpref,epref,Absyn.R_FUNCTION(funcRest),body,info)},w,ts), p); - f = Absyn.getFileNameFromInfo(info); - - syt = GlobalScript.SYMBOLTABLE( - p, a, b, c, - GlobalScript.CFunction(funcpath,DAE.T_UNKNOWN({funcpath}),funcHandle,buildTime,f)::newCF, - lf); - - if Flags.isSet(Flags.DYN_LOAD) then - print("[dynload]: [SOME SYMTAB] not in in CF list [finished]: " + - Absyn.pathString(funcpath) + "\n"); - end if; - //print("\nfunctions in SYMTAB: " + Interactive.dumpCompiledFunctions(syt)); - then - (cache,newval,SOME(syt)); - - // no symtab, WE SHOULD NOT EVALUATE! but we do anyway with suppressed error messages! - case (cache,env,(DAE.CALL(path = funcpath,attr = DAE.CALL_ATTR(builtin = false))),vallst,_,NONE(), msg, _) // crap! we have no symboltable! - equation - true = bIsCompleteFunction; - true = Flags.isSet(Flags.GEN); - failure(cevalIsExternalObjectConstructor(cache,funcpath,env,msg)); - ErrorExt.setCheckpoint("cevalCallFunctionEvaluateOrGenerate_NO_SYMTAB"); - - if Flags.isSet(Flags.DYN_LOAD) then - print("[dynload]: [NO SYMTAB] not in in CF list: " + Absyn.pathString(funcpath) + "\n"); - end if; - - // we might actually have a function loaded here already! - // we need to unload all functions to not get conflicts! - p = FCore.getProgramFromCache(cache); - (cache,funcstr,fileName) = cevalGenerateFunction(cache, env, p, funcpath); - // generate a uniquely named dll! - if Flags.isSet(Flags.DYN_LOAD) then - print("[dynload]: cevalCallFunction: about to execute " + funcstr + "\n"); - end if; - print_debug = Flags.isSet(Flags.DYN_LOAD); - libHandle = System.loadLibrary(fileName, print_debug); - funcHandle = System.lookupFunction(libHandle, stringAppend("in_", funcstr)); - newval = DynLoad.executeFunction(funcHandle, vallst, print_debug); - System.freeFunction(funcHandle, print_debug); - System.freeLibrary(libHandle, print_debug); - - if Flags.isSet(Flags.DYN_LOAD) then - Debug.traceln("CALL: [NO SYMTAB] not in in CF list [finished]: " + Absyn.pathString(funcpath)); - end if; - ErrorExt.rollBack("cevalCallFunctionEvaluateOrGenerate_NO_SYMTAB"); - then - (cache,newval,NONE()); - - // cleanup the case below when we failed. we should delete generated files too - case (cache,env,(DAE.CALL(path = funcpath,attr = DAE.CALL_ATTR(builtin = false))),_,_,NONE(),msg, _) // crap! we have no symboltable! - equation - true = bIsCompleteFunction; - true = Flags.isSet(Flags.GEN); - failure(cevalIsExternalObjectConstructor(cache,funcpath,env,msg)); - ErrorExt.rollBack("cevalCallFunctionEvaluateOrGenerate_NO_SYMTAB"); - then - fail(); - - case (_,_,(DAE.CALL(path = funcpath)),_,_,_, _, _) - equation - if Flags.isSet(Flags.DYN_LOAD) then - print("[dynload]: FAILED to constant evaluate function: " + Absyn.pathString(funcpath) + "\n"); - end if; - //TODO: readd this when testsuite is okay. - //Error.addMessage(Error.FAILED_TO_EVALUATE_FUNCTION, {error_Str}); - false = Flags.isSet(Flags.GEN); - true = Flags.isSet(Flags.FAILTRACE); - Debug.trace("- codegeneration is turned off. switch \"nogen\" flag off\n"); - then - fail(); - - end matchcontinue; -end cevalCallFunctionEvaluateOrGenerate; - -protected function checkLibraryUsage - input String inLibrary; - input Absyn.Exp inExp; - output Boolean isUsed; -algorithm - isUsed := match(inLibrary, inExp) - local - String s; - list exps; - - case (_, Absyn.STRING(s)) then stringEq(s, inLibrary); - case (_, Absyn.ARRAY(exps)) - then List.isMemberOnTrue(inLibrary, exps, checkLibraryUsage); - end match; -end checkLibraryUsage; - - -protected function isCevaluableFunction - "Checks if an element is a function or external function that can be evaluated - by CevalFunction." - input SCode.Element inElement; -algorithm - _ := match(inElement) - local - String fid; - SCode.Mod mod; - Absyn.Exp lib; - - //only some external functions. - case (SCode.CLASS(restriction = SCode.R_FUNCTION(SCode.FR_EXTERNAL_FUNCTION(_)), - classDef = SCode.PARTS(externalDecl = SOME(SCode.EXTERNALDECL( - funcName = SOME(fid), - annotation_ = SOME(SCode.ANNOTATION(mod))))))) - equation - SCode.MOD(binding = SOME(lib)) = Mod.getUnelabedSubMod(mod, "Library"); - true = checkLibraryUsage("Lapack", lib) or checkLibraryUsage("lapack", lib); - isCevaluableFunction2(fid); - then - (); - - // All other functions can be evaluated. - case (SCode.CLASS(restriction = SCode.R_FUNCTION(_))) then (); - - end match; -end isCevaluableFunction; - -protected function isCevaluableFunction2 +function isCevaluableFunction2 "Checks if a function name belongs to a known external function that we can constant evaluate." input String inFuncName; @@ -7212,318 +2523,99 @@ algorithm end match; end isCevaluableFunction2; -public function cevalCallFunction "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 FCore.Cache inCache; - input FCore.Graph inEnv; - input DAE.Exp inExp; - input list inValuesValueLst; - input Boolean impl; - input Option inSymTab; - input Absyn.Msg inMsg; - input Integer numIter; - output FCore.Cache outCache; - output Values.Value outValue; - output Option outSymTab; -algorithm - (outCache,outValue,outSymTab) := matchcontinue (inCache,inEnv,inExp,inValuesValueLst,impl,inSymTab,inMsg,numIter) - local - Values.Value newval; - FCore.Graph env; - DAE.Exp e; - Absyn.Path funcpath; - list expl; - list vallst, pubVallst, proVallst; - Absyn.Msg msg; - FCore.Cache cache; - Option st; - Absyn.Path complexName; - list pubVarLst, proVarLst, varLst; - list pubVarNames, proVarNames, varNames; - DAE.Type ty; - SourceInfo info; - String str; - Boolean bIsCompleteFunction; - - // External functions that are "known" should be evaluated without compilation, e.g. all math functions - case (cache,env,(DAE.CALL(path = funcpath)),vallst,_,st,msg,_) - equation - (cache,newval) = Ceval.cevalKnownExternalFuncs(cache,env, funcpath, vallst, msg); - then - (cache,newval,st); - - // This case prevents the constructor call of external objects of being evaluated - case (cache,env,(DAE.CALL(path = funcpath)),_,_,_,msg,_) - equation - true = FGraph.isNotEmpty(env); - cevalIsExternalObjectConstructor(cache,funcpath,env,msg); - then - fail(); - - // Record constructors - case(cache,env,(DAE.CALL(path = funcpath,attr = DAE.CALL_ATTR(ty = DAE.T_COMPLEX(complexClassType = ClassInf.RECORD(complexName), varLst=varLst)))),pubVallst,_,st,msg,_) - equation - if Flags.isSet(Flags.DYN_LOAD) then - Debug.traceln("CALL: record constructor: func: " + Absyn.pathString(funcpath) + " type path: " + Absyn.pathString(complexName)); - end if; - true = Absyn.pathEqual(funcpath,complexName); - (pubVarLst,proVarLst) = List.splitOnTrue(varLst,Types.isPublicVar); - expl = List.map1(proVarLst, Types.getBindingExp, funcpath); - (cache,proVallst,st) = Ceval.cevalList(cache, env, expl, impl, st, msg, numIter); - pubVarNames = List.map(pubVarLst,Expression.varName); - proVarNames = List.map(proVarLst,Expression.varName); - varNames = listAppend(pubVarNames, proVarNames); - vallst = listAppend(pubVallst, proVallst); - // fprintln(Flags.DYN_LOAD, "CALL: record constructor: [success] func: " + Absyn.pathString(funcpath)); - 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(ty = ty, builtin = false)), _, _, _, msg, _) - equation - failure(cevalIsExternalObjectConstructor(cache, funcpath, env, msg)); - if Flags.isSet(Flags.DYN_LOAD) then - Debug.traceln("CALL: try to evaluate or generate function: " + Absyn.pathString(funcpath)); - end if; - - bIsCompleteFunction = isCompleteFunction(cache, env, funcpath); - false = Types.hasMetaArray(ty); - - if Flags.isSet(Flags.DYN_LOAD) then - Debug.traceln("CALL: is complete function: " + Absyn.pathString(funcpath) + " " + (if bIsCompleteFunction then "[true]" else "[false]")); - end if; - (cache, newval, st) = cevalCallFunctionEvaluateOrGenerate(inCache,inEnv,inExp,inValuesValueLst,impl,inSymTab,inMsg,bIsCompleteFunction); - - // Debug.fprintln(Flags.DYN_LOAD, "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)), _, _, _, msg, _) - equation - failure(cevalIsExternalObjectConstructor(cache, funcpath, env, msg)); - false = isCompleteFunction(cache, env, funcpath); - - if Flags.isSet(Flags.DYN_LOAD) then - Debug.traceln("CALL: constant evaluation failed (not complete function): " + Absyn.pathString(funcpath)); - end if; - then - fail(); - - case (cache,env, DAE.CALL(path = funcpath, attr = DAE.CALL_ATTR(ty = ty, builtin = false)), _, _, _, msg as Absyn.MSG(info), _) - equation - failure(cevalIsExternalObjectConstructor(cache, funcpath, env, msg)); - true = isCompleteFunction(cache, env, funcpath); - true = Types.hasMetaArray(ty); - str = ExpressionDump.printExpStr(inExp); - Error.addSourceMessage(Error.FUNCTION_RETURNS_META_ARRAY, {str}, info); - then fail(); - - end matchcontinue; -end cevalCallFunction; - -public 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 FCore.Cache inCache; - input FCore.Graph inEnv; - input Absyn.Path inFuncPath; - output Boolean isComplete; +function isSimpleAPIFunction + input DAE.Type ty; + output Boolean b; algorithm - isComplete := matchcontinue(inCache, inEnv, inFuncPath) - local - FCore.Cache cache; - FCore.Graph env; - Absyn.Path fpath; - - // external functions are complete :) - case (cache, env, fpath) - equation - (_, SCode.CLASS(classDef = SCode.PARTS(externalDecl = SOME(_))), _) = Lookup.lookupClass(cache, env, fpath, false); - then - true; - - // if is partial instantiation no function evaluation/generation - case (_, _, _) - 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, false); - then - false; - - else true; - - end matchcontinue; -end isCompleteFunction; + b := match ty + case DAE.T_FUNCTION(functionAttributes=DAE.FUNCTION_ATTRIBUTES(isBuiltin=DAE.FUNCTION_BUILTIN())) then + isSimpleAPIFunctionArg(ty.funcResultType) and + min(match fa case DAE.FUNCARG() then isSimpleAPIFunctionArg(fa.ty); end match for fa in ty.funcArg); + else false; + end match; +end isSimpleAPIFunction; -public function cevalIsExternalObjectConstructor - input FCore.Cache cache; - input Absyn.Path funcpath; - input FCore.Graph env; - input Absyn.Msg msg; -protected - Absyn.Path funcpath2; - DAE.Type tp; - Option info; +function isSimpleAPIFunctionArg + input DAE.Type ty; + output Boolean b; algorithm - _ := match(cache, funcpath, env, msg) - case (_, _, FCore.EG(_), Absyn.NO_MSG()) then fail(); - case (_, _, _, Absyn.NO_MSG()) - equation - (funcpath2, Absyn.IDENT("constructor")) = Absyn.splitQualAndIdentPath(funcpath); - info = if valueEq(msg, Absyn.NO_MSG()) then NONE() else SOME(Absyn.dummyInfo); - (_, tp, _) = Lookup.lookupType(cache, env, funcpath2, info); - Types.externalObjectConstructorType(tp); - then - (); + b := match ty + case DAE.T_INTEGER() then true; + case DAE.T_REAL() then true; + case DAE.T_BOOL() then true; + case DAE.T_STRING() then true; + case DAE.T_NORETCALL() then true; + case DAE.T_ARRAY() then isSimpleAPIFunctionArg(ty.ty); + case DAE.T_CODE(ty=DAE.C_TYPENAME()) then true; + case DAE.T_TUPLE() then min(isSimpleAPIFunctionArg(t) for t in ty.types); + else false; end match; -end cevalIsExternalObjectConstructor; - - - -public function ceval " - This is a wrapper funtion to Ceval.ceval. The purpose of this - function is to concetrate all the calls to Ceval.ceval made from - the Script files. This will simplify the separation of the scripting - environment from the FrontEnd" - input FCore.Cache inCache; - input FCore.Graph inEnv; - input DAE.Exp inExp; - input Boolean inBoolean "impl"; - input Option inST; - input Absyn.Msg inMsg; - input Integer numIter; - output FCore.Cache outCache; - output Values.Value outValue; - output Option outST; +end isSimpleAPIFunctionArg; - partial function ReductionOperator - input Values.Value v1; - input Values.Value v2; - output Values.Value res; - end ReductionOperator; +function verifyInterfaceType + input SCode.Element elt; + input list expected; algorithm - (outCache,outValue,outST):= - matchcontinue (inCache,inEnv,inExp,inBoolean,inST,inMsg,numIter) + _ := matchcontinue (elt,expected) local - Option stOpt; - Boolean impl; - FCore.Graph env; - Absyn.Msg msg; - list vallst; - list expl; - Values.Value newval,value; - DAE.Exp e; - Absyn.Path funcpath; - FCore.Cache cache; - GlobalScript.SymbolTable st; - - // adrpo: TODO! this needs more work as if we don't have a symtab we run into unloading of dlls problem - case (cache,env,(e as DAE.CALL(path = funcpath,expLst = expl)),impl,stOpt,msg,_) - equation - // do not handle Connection.isRoot here! - false = stringEq("Connection.isRoot", Absyn.pathString(funcpath)); - // do not roll back errors generated by evaluating the arguments - (cache,vallst,stOpt) = Ceval.cevalList(cache,env, expl, impl, stOpt, msg, numIter); - - (cache,newval,stOpt)= cevalCallFunction(cache, env, e, vallst, impl, stOpt, msg, numIter+1); - then - (cache,newval,stOpt); - - // Try Interactive functions last - case (cache,env,(e as DAE.CALL()),(true),SOME(st),msg,_) + String str,name; + SCode.Annotation ann; + SourceInfo info; + case (SCode.CLASS(cmt=SCode.COMMENT(annotation_=SOME(ann))),name::_) equation - (cache,value,st) = cevalInteractiveFunctions(cache, env, e, st, msg, numIter+1); - then - (cache,value,SOME(st)); - case (cache,env,e,impl,stOpt,msg,_) + (Absyn.STRING(str),info) = SCode.getNamedAnnotation(ann,"__OpenModelica_Interface"); + Error.assertionOrAddSourceMessage(listMember(str, expected), Error.MISMATCHING_INTERFACE_TYPE, {str,name}, info); + then (); + else equation - (cache,value,stOpt) = Ceval.ceval(cache,env,e,impl,stOpt,msg,numIter+1); - then - (cache,value,stOpt); + Error.addSourceMessage(Error.MISSING_INTERFACE_TYPE,{},SCode.elementInfo(elt)); + then fail(); end matchcontinue; -end ceval; +end verifyInterfaceType; -protected function searchClassNames - input list inVals; - input String inSearchText; - input Boolean inFindInText; - input Absyn.Program inProgram; - output list outVals; +function getInterfaceType + input SCode.Element elt; + input list>> assoc; + output list it; algorithm - outVals := matchcontinue (inVals, inSearchText, inFindInText, inProgram) + it := matchcontinue (elt,assoc) local - list valsList; - String str, str1; - Boolean b; - Absyn.Program p, p1; - Absyn.Class absynClass; - Integer position; - list xs; - Values.Value val; - case ((val as Values.CODE(_)) :: xs, str1, true, p) - equation - absynClass = Interactive.getPathedClassInProgram(ValuesUtil.getPath(val), p); - p1 = Absyn.PROGRAM({absynClass},Absyn.TOP()); - /* Don't consider packages for FindInText search */ - false = Interactive.isPackage(ValuesUtil.getPath(val), inProgram); - str = Dump.unparseStr(p1, false); - position = System.stringFind(System.tolower(str), System.tolower(str1)); - true = (position > -1); - valsList = searchClassNames(xs, str1, true, p); - then - val::valsList; - case ((val as Values.CODE(_)) :: xs, str1, b, p) + String name; + SCode.Annotation ann; + String str; + SourceInfo info; + case (SCode.CLASS(cmt=SCode.COMMENT(annotation_=SOME(ann))),_) equation - str = ValuesUtil.valString(val); - position = System.stringFind(System.tolower(str), System.tolower(str1)); - true = (position > -1); - valsList = searchClassNames(xs, str1, b, p); - then - val::valsList; - case ((_ :: xs), str1, b, p) + (Absyn.STRING(str),_) = SCode.getNamedAnnotation(ann,"__OpenModelica_Interface"); + it = Util.assoc(str,assoc); + then it; + else equation - valsList = searchClassNames(xs, str1, b, p); - then - valsList; - case ({}, _, _, _) then {}; + Error.addSourceMessage(Error.MISSING_INTERFACE_TYPE,{},SCode.elementInfo(elt)); + then fail(); end matchcontinue; -end searchClassNames; +end getInterfaceType; -protected function makeUsesArray - input tuple> inTpl; - output Values.Value v; +function getInterfaceTypeAssocElt + input Values.Value val; + input SourceInfo info; + output tuple> assoc; algorithm - v := match inTpl + assoc := match (val,info) local - Absyn.Path p; - String pstr,ver; - case ((p,{ver})) - equation - pstr = Absyn.pathString(p); - then ValuesUtil.makeArray({Values.STRING(pstr),Values.STRING(ver)}); - else + String str; + list strs; + list vals; + case (Values.ARRAY(valueLst=Values.STRING("")::_),_) equation - Error.addMessage(Error.INTERNAL_ERROR,{"makeUsesArray failed"}); + Error.addSourceMessage(Error.MISSING_INTERFACE_TYPE,{},info); then fail(); + case (Values.ARRAY(valueLst=Values.STRING(str)::vals),_) + equation + strs = List.select(List.map(vals,ValuesUtil.extractValueString), Util.isNotEmptyString); + then ((str,str::strs)); end match; -end makeUsesArray; - -protected function getTypeNameIdent - input Values.Value val; - output String str; -algorithm - Values.CODE(Absyn.C_TYPENAME(Absyn.IDENT(str))) := val; -end getTypeNameIdent; +end getInterfaceTypeAssocElt; protected function buildDependencyGraph input String name; @@ -7722,472 +2814,236 @@ protected function printInterfaceString input SCode.Element elt; protected String str; -algorithm - SCode.CLASS(name=str) := elt; - print(str + ": " + boolString(containsPublicInterface(elt)) + "\n"); -end printInterfaceString; - -protected function getChangedClass - input SCode.Element elt; - input String suffix; - output String name; -algorithm - name := matchcontinue (elt,suffix) - local - String fileName; - case (SCode.CLASS(name=name,info=SOURCEINFO()),_) - equation - false = System.regularFileExists(name + suffix); - then name; - case (SCode.CLASS(name=name,info=SOURCEINFO(fileName=fileName)),_) - equation - true = System.fileIsNewerThan(fileName, name + suffix); - then name; - end matchcontinue; -end getChangedClass; - -protected function isChanged - input tuple> node; - input HashSetString.HashSet hs; - output Boolean b; -protected - String str; - list strs; -algorithm - (str,strs) := node; - b := List.exist1(str::strs,BaseHashSet.has,hs); - // print(str + ": " + boolString(b) + "\n"); -end isChanged; - -protected function reloadClass - input String filename; - input String encoding; - input GlobalScript.SymbolTable inST; - output GlobalScript.SymbolTable outST; -protected - Absyn.Program p,newp; -algorithm - GlobalScript.SYMBOLTABLE(ast=p) := inST; - newp := Parser.parse(filename,encoding); /* Don't use the classloader since that can pull in entire directory structures. We only want to reload one single file. */ - newp := Interactive.updateProgram(newp, p); - outST := GlobalScriptUtil.setSymbolTableAST(inST, newp); -end reloadClass; - -protected function writeModuleDepends - input SCode.Element cl; - input String prefix; - input String suffix; - input list>> deps; - output String str; -algorithm - str := matchcontinue (cl,prefix,suffix,deps) - local - String name,fileName; - list allDepends,protectedDepends; - list elts; - SourceInfo info; - case (SCode.CLASS(name=name, classDef=SCode.PARTS(elementLst=elts), info = SOURCEINFO()),_,_,_) - equation - protectedDepends = List.map(List.select(elts,SCode.elementIsProtectedImport),importDepenency); - protectedDepends = List.select(protectedDepends, isNotBuiltinImport); - _::allDepends = Graph.allReachableNodes((name::protectedDepends,{}),deps,stringEq); - allDepends = List.map1r(allDepends, stringAppend, prefix); - allDepends = List.map1(allDepends, stringAppend, ".interface.mo"); - str = prefix + name + suffix + ": $(RELPATH_" + name + ") " + stringDelimitList(allDepends," "); - then str; - case (SCode.CLASS(name=name,info=info),_,_,_) - equation - Error.addSourceMessage(Error.GENERATE_SEPARATE_CODE_DEPENDENCIES_FAILED, {name}, info); - then fail(); - end matchcontinue; -end writeModuleDepends; - -protected function isNotBuiltinImport - input String module; - output Boolean b = module <> "MetaModelica"; -end isNotBuiltinImport; - -protected function findFunctionsToCompile - input SCode.Element elt; - input Absyn.Path pathPrefix; - input list acc; - output list paths; -algorithm - paths := match (elt,pathPrefix,acc) - local - Absyn.Path p; - String name; - list elts; - case (SCode.CLASS(name=name, partialPrefix=SCode.NOT_PARTIAL(), restriction=SCode.R_FUNCTION(_), classDef=SCode.PARTS(elementLst=elts)),_,_) - equation - p = Absyn.joinPaths(pathPrefix,Absyn.IDENT(name)); - paths = List.fold1(elts,findFunctionsToCompile,Absyn.joinPaths(pathPrefix,Absyn.IDENT(name)),acc); - then p::paths; - case (SCode.CLASS(name=name, partialPrefix=SCode.NOT_PARTIAL(), classDef=SCode.PARTS(elementLst=elts)),_,_) - equation - paths = List.fold1(elts,findFunctionsToCompile,Absyn.joinPaths(pathPrefix,Absyn.IDENT(name)),acc); - then paths; - // Derived classes, class extends - case (SCode.CLASS(name=name, partialPrefix=SCode.NOT_PARTIAL(), restriction=SCode.R_FUNCTION(_)),_,_) - equation - p = Absyn.joinPaths(pathPrefix,Absyn.IDENT(name)); - then p::acc; - else acc; - end match; -end findFunctionsToCompile; - -protected function saveTotalModel - input String filename; - input Absyn.Path classpath; - input GlobalScript.SymbolTable st; - output GlobalScript.SymbolTable outSt; -protected - SCode.Program scodeP; - String str,str1,str2,str3; - NFSCodeEnv.Env env; - SCode.Comment cmt; -algorithm - (scodeP, outSt) := GlobalScriptUtil.symbolTableToSCode(st); - (scodeP, env) := NFSCodeFlatten.flattenClassInProgram(classpath, scodeP); - (NFSCodeEnv.CLASS(cls=SCode.CLASS(cmt=cmt)),_,_) := NFSCodeLookup.lookupClassName(classpath, env, Absyn.dummyInfo); - scodeP := SCode.removeBuiltinsFromTopScope(scodeP); - str := SCodeDump.programStr(scodeP,SCodeDump.defaultOptions); - str1 := Absyn.pathLastIdent(classpath) + "_total"; - str2 := SCodeDump.printCommentStr(cmt); - str2 := if stringEq(str2,"") then "" else (" " + str2); - str3 := SCodeDump.printAnnotationStr(cmt,SCodeDump.defaultOptions); - str3 := if stringEq(str3,"") then "" else (str3 + ";\n"); - str1 := "\nmodel " + str1 + str2 + "\n extends " + Absyn.pathString(classpath) + ";\n" + str3 + "end " + str1 + ";\n"; - System.writeFile(filename, str + str1); -end saveTotalModel; - -protected function verifyInterfaceType - input SCode.Element elt; - input list expected; -algorithm - _ := matchcontinue (elt,expected) - local - String str,name; - SCode.Annotation ann; - SourceInfo info; - case (SCode.CLASS(cmt=SCode.COMMENT(annotation_=SOME(ann))),name::_) - equation - (Absyn.STRING(str),info) = SCode.getNamedAnnotation(ann,"__OpenModelica_Interface"); - Error.assertionOrAddSourceMessage(listMember(str, expected), Error.MISMATCHING_INTERFACE_TYPE, {str,name}, info); - then (); - else - equation - Error.addSourceMessage(Error.MISSING_INTERFACE_TYPE,{},SCode.elementInfo(elt)); - then fail(); - end matchcontinue; -end verifyInterfaceType; +algorithm + SCode.CLASS(name=str) := elt; + print(str + ": " + boolString(containsPublicInterface(elt)) + "\n"); +end printInterfaceString; -protected function getInterfaceType - input SCode.Element elt; - input list>> assoc; - output list it; +protected function writeModuleDepends + input SCode.Element cl; + input String prefix; + input String suffix; + input list>> deps; + output String str; algorithm - it := matchcontinue (elt,assoc) + str := matchcontinue (cl,prefix,suffix,deps) local - String name; - SCode.Annotation ann; - String str; + String name,fileName,tmp1; + list allDepends,protectedDepends,tmp2; + list elts; SourceInfo info; - case (SCode.CLASS(cmt=SCode.COMMENT(annotation_=SOME(ann))),_) + case (SCode.CLASS(name=name, classDef=SCode.PARTS(elementLst=elts), info = SOURCEINFO()),_,_,_) equation - (Absyn.STRING(str),_) = SCode.getNamedAnnotation(ann,"__OpenModelica_Interface"); - it = Util.assoc(str,assoc); - then it; - else + protectedDepends = List.map(List.select(elts,SCode.elementIsProtectedImport),importDepenency); + protectedDepends = List.select(protectedDepends, isNotBuiltinImport); + _::allDepends = Graph.allReachableNodes((name::protectedDepends,{}),deps,stringEq); + allDepends = List.map1r(allDepends, stringAppend, prefix); + allDepends = List.map1(allDepends, stringAppend, ".interface.mo"); + str = prefix + name + suffix + ": $(RELPATH_" + name + ") " + stringDelimitList(allDepends," "); + then str; + case (SCode.CLASS(name=name, classDef=SCode.PARTS(elementLst=elts), info=info),_,_,_) + algorithm + protectedDepends := List.map(List.select(elts,SCode.elementIsProtectedImport),importDepenency); + protectedDepends := List.select(protectedDepends, isNotBuiltinImport); + allDepends := list(Util.tuple21(e) for e in deps); + for d in protectedDepends loop + if not listMember(d, allDepends) then + Error.addSourceMessage(Error.GENERATE_SEPARATE_CODE_DEPENDENCIES_FAILED_UNKNOWN_PACKAGE, {name,name,d}, info); + fail(); + end if; + end for; + for dep in deps loop + (tmp1,tmp2) := dep; + for d in tmp2 loop + if not listMember(d, allDepends) then + Error.addSourceMessage(Error.GENERATE_SEPARATE_CODE_DEPENDENCIES_FAILED_UNKNOWN_PACKAGE, {name,tmp1,d}, info); + fail(); + end if; + end for; + end for; + then fail(); + case (SCode.CLASS(name=name,info=info),_,_,_) equation - Error.addSourceMessage(Error.MISSING_INTERFACE_TYPE,{},SCode.elementInfo(elt)); + Error.addSourceMessage(Error.GENERATE_SEPARATE_CODE_DEPENDENCIES_FAILED, {name}, info); then fail(); end matchcontinue; -end getInterfaceType; +end writeModuleDepends; + +protected function isNotBuiltinImport + input String module; + output Boolean b = module <> "MetaModelica"; +end isNotBuiltinImport; -protected function getInterfaceTypeAssocElt +protected function getTypeNameIdent input Values.Value val; - input SourceInfo info; - output tuple> assoc; + output String str; algorithm - assoc := match (val,info) + Values.CODE(Absyn.C_TYPENAME(Absyn.IDENT(str))) := val; +end getTypeNameIdent; + +protected function getChangedClass + input SCode.Element elt; + input String suffix; + output String name; +algorithm + name := matchcontinue (elt,suffix) local - String str; - list strs; - list vals; - case (Values.ARRAY(valueLst=Values.STRING("")::_),_) + String fileName; + case (SCode.CLASS(name=name,info=SOURCEINFO()),_) equation - Error.addSourceMessage(Error.MISSING_INTERFACE_TYPE,{},info); - then fail(); - case (Values.ARRAY(valueLst=Values.STRING(str)::vals),_) + false = System.regularFileExists(name + suffix); + then name; + case (SCode.CLASS(name=name,info=SOURCEINFO(fileName=fileName)),_) equation - strs = List.select(List.map(vals,ValuesUtil.extractValueString), Util.isNotEmptyString); - then ((str,str::strs)); - end match; -end getInterfaceTypeAssocElt; + true = System.fileIsNewerThan(fileName, name + suffix); + then name; + end matchcontinue; +end getChangedClass; -protected function getClassInformation -"author: PA - Returns all the possible class information. - changed by adrpo 2006-02-24 (latest 2006-03-14) to return more info and in a different format: - {\"restriction\",\"comment\",\"filename.mo\",{bool,bool,bool},{\"readonly|writable\",int,int,int,int}} - if you like more named attributes, use getClassAttributes API which uses get_class_attributes function - change by sjoelund.se 2014-11-14 to actually be sane. Using the typed API. - " - input Absyn.Path path; - input Absyn.Program p; - output Values.Value res_1; +protected function isChanged + input tuple> node; + input HashSetString.HashSet hs; + output Boolean b; protected - String name,file,strPartial,strFinal,strEncapsulated,res,cmt,str_readonly,str_sline,str_scol,str_eline,str_ecol; - String dim_str; - Boolean partialPrefix,finalPrefix,encapsulatedPrefix,isReadOnly; - Absyn.Restriction restr; - Absyn.ClassDef cdef; - Absyn.Class c; - Integer sl,sc,el,ec; -algorithm - Absyn.CLASS(name,partialPrefix,finalPrefix,encapsulatedPrefix,restr,cdef,SOURCEINFO(file,isReadOnly,sl,sc,el,ec,_)) := Interactive.getPathedClassInProgram(path, p); - res := Dump.unparseRestrictionStr(restr); - cmt := getClassComment(cdef); - file := Util.testsuiteFriendly(file); - res_1 := Values.TUPLE({ - Values.STRING(res), - Values.STRING(cmt), - Values.BOOL(partialPrefix), - Values.BOOL(finalPrefix), - Values.BOOL(encapsulatedPrefix), - Values.STRING(file), - Values.BOOL(isReadOnly), - Values.INTEGER(sl), - Values.INTEGER(sc), - Values.INTEGER(el), - Values.INTEGER(ec), - getClassDimensions(cdef) - }); -end getClassInformation; - -function getClassDimensions -"return the dimensions of a class - as vector of dimension sizes in a string. - Note: A class can only have dimensions if it is a short class definition." - input Absyn.ClassDef cdef; - output Values.Value v; + String str; + list strs; algorithm - v := match cdef - local - Absyn.ArrayDim ad; - case(Absyn.DERIVED(typeSpec=Absyn.TPATH(arrayDim=SOME(ad)))) - then ValuesUtil.makeArray(list(Values.STRING(Dump.printSubscriptStr(d)) for d in ad)); - else ValuesUtil.makeArray({}); - end match; -end getClassDimensions; + (str,strs) := node; + b := List.exist1(str::strs,BaseHashSet.has,hs); + // print(str + ": " + boolString(b) + "\n"); +end isChanged; -function getClassComment "Returns the class comment of a Absyn.ClassDef" - input Absyn.ClassDef inClassDef; - output String outString; +protected function reloadClass + input String filename; + input String encoding; + input GlobalScript.SymbolTable inST; + output GlobalScript.SymbolTable outST; +protected + Absyn.Program p,newp; algorithm - outString:= - matchcontinue (inClassDef) - local - String str,res; - Option cmt; - case (Absyn.PARTS(comment = SOME(str))) then str; - case (Absyn.DERIVED(comment = cmt)) - then Interactive.getStringComment2(cmt); - case (Absyn.ENUMERATION(comment = cmt)) - then Interactive.getStringComment2(cmt); - case (Absyn.ENUMERATION(comment = cmt)) - then Interactive.getStringComment2(cmt); - case (Absyn.OVERLOAD(comment = cmt)) - then Interactive.getStringComment2(cmt); - case (Absyn.CLASS_EXTENDS(comment = SOME(str))) then str; - else ""; - end matchcontinue; -end getClassComment; + GlobalScript.SYMBOLTABLE(ast=p) := inST; + newp := Parser.parse(filename,encoding); /* Don't use the classloader since that can pull in entire directory structures. We only want to reload one single file. */ + newp := Interactive.updateProgram(newp, p); + outST := GlobalScriptUtil.setSymbolTableAST(inST, newp); +end reloadClass; -function isSimpleAPIFunction - input DAE.Type ty; - output Boolean b; +public function getFullPathFromUri + input Absyn.Program program; + input String uri; + input Boolean printError; + output String path; +protected + String str1,str2,str3; algorithm - b := match ty - case DAE.T_FUNCTION(functionAttributes=DAE.FUNCTION_ATTRIBUTES(isBuiltin=DAE.FUNCTION_BUILTIN())) then - isSimpleAPIFunctionArg(ty.funcResultType) and - min(match fa case DAE.FUNCARG() then isSimpleAPIFunctionArg(fa.ty); end match for fa in ty.funcArg); - else false; - end match; -end isSimpleAPIFunction; + (str1,str2,str3) := System.uriToClassAndPath(uri); + path := getBasePathFromUri(str1,str2,program,Settings.getModelicaPath(Config.getRunningTestsuite()),printError) + str3; +end getFullPathFromUri; -function isSimpleAPIFunctionArg - input DAE.Type ty; - output Boolean b; +protected function getBasePathFromUri "Handle modelica:// URIs" + input String scheme; + input String iname; + input Absyn.Program program; + input String modelicaPath; + input Boolean printError; + output String basePath; algorithm - b := match ty - case DAE.T_INTEGER() then true; - case DAE.T_REAL() then true; - case DAE.T_BOOL() then true; - case DAE.T_STRING() then true; - case DAE.T_NORETCALL() then true; - case DAE.T_ARRAY() then isSimpleAPIFunctionArg(ty.ty); - case DAE.T_CODE(ty=DAE.C_TYPENAME()) then true; - case DAE.T_TUPLE() then min(isSimpleAPIFunctionArg(t) for t in ty.types); - else false; - end match; -end isSimpleAPIFunctionArg; + basePath := matchcontinue (scheme,iname,program,modelicaPath,printError) + local + Boolean isDir; + list mps,names; + String gd,mp,bp,str,name,version,fileName; + case ("modelica://",name,_,mp,_) + equation + (name::names) = System.strtok(name,"."); + Absyn.CLASS(info=SOURCEINFO(fileName=fileName)) = Interactive.getPathedClassInProgram(Absyn.IDENT(name),program); + mp = System.dirname(fileName); + bp = findModelicaPath2(mp,names,"",true); + then bp; + case ("modelica://",name,_,mp,_) + equation + (name::names) = System.strtok(name,"."); + failure(_ = Interactive.getPathedClassInProgram(Absyn.IDENT(name),program)); + gd = System.groupDelimiter(); + mps = System.strtok(mp, gd); + (mp,name,isDir) = System.getLoadModelPath(name, {"default"}, mps); + mp = if isDir then mp + name else mp; + bp = findModelicaPath2(mp,names,"",true); + then bp; + case ("file://",_,_,_,_) then ""; + case ("modelica://",name,_,mp,true) + equation + name::_ = System.strtok(name,"."); + str = "Could not resolve modelica://" + name + " with MODELICAPATH: " + mp; + Error.addMessage(Error.COMPILER_ERROR,{str}); + then fail(); + end matchcontinue; +end getBasePathFromUri; -function getComponentInfo - input Absyn.Element comp; - input FCore.Graph inEnv; - input Boolean isProtected; - output list vs; +protected function findModelicaPath "Handle modelica:// URIs" + input list imps; + input list names; + input String version; + output String basePath; algorithm - vs := match comp + basePath := matchcontinue (imps,names,version) local - SCode.Element c; - Absyn.Path envpath, p_1, p; - String tpname, typename, inout_str, variability_str, dir_str, access, name, comment; - String typeAdStr; - Boolean r_1, b; - Option r; - Absyn.ElementAttributes attr; - Option typeAd; - FCore.Graph env; - list dims, dims1; - Absyn.ArrayDim subs; - Absyn.ElementSpec spec; + String mp; + list mps; - case Absyn.ELEMENT(specification = spec as Absyn.COMPONENTS(attributes = attr as Absyn.ATTR(),typeSpec = Absyn.TPATH(p, _))) - algorithm - typename := matchcontinue () - case () - equation - (_,_,env) = Lookup.lookupClass(FCore.emptyCache(), inEnv, p, false); - SOME(envpath) = FGraph.getScopePath(env); - tpname = Absyn.pathLastIdent(p); - p_1 = Absyn.joinPaths(envpath, Absyn.IDENT(tpname)); - then Absyn.pathString(p_1); - else Absyn.pathString(p); - end matchcontinue; - vs := {}; - - dims1 := list(Dump.printSubscriptStr(sub) for sub in attr.arrayDim); - r_1 := Interactive.keywordReplaceable(comp.redeclareKeywords); - - inout_str := innerOuterStr(comp.innerOuter); - - variability_str := attrVariabilityStr(attr); - dir_str := attrDirectionStr(attr); - - for ci in spec.components loop - (name, comment) := getComponentitemsName(ci); - - dims := match ci - case Absyn.COMPONENTITEM(component=Absyn.COMPONENT(arrayDim=subs)) - then listAppend(list(Dump.printSubscriptStr(sub) for sub in subs), dims1); - end match; - - vs := makeGetComponentsRecord( - className = typename, name = name, comment = comment, - isProtected=isProtected, isReplaceable=r_1, isFinal=comp.finalPrefix, innerOuter=inout_str, isFlow=attr.flowPrefix, - isStream=attr.streamPrefix, variability=variability_str, inputOutput=dir_str, dimensions=dims) :: vs; - end for; - then vs; - end match; -end getComponentInfo; + case (mp::_,_,_) + then findModelicaPath2(mp,names,version,false); + case (_::mps,_,_) + then findModelicaPath(mps,names,version); + end matchcontinue; +end findModelicaPath; -function makeGetComponentsRecord - input String className; - input String name; - input String comment; - input Boolean isProtected; - input Boolean isFinal; - input Boolean isFlow; - input Boolean isStream; - input Boolean isReplaceable; - input String variability; - input String innerOuter; - input String inputOutput; - input list dimensions; - output Values.Value v; -algorithm - v := Values.RECORD( - Absyn.QUALIFIED("OpenModelica", Absyn.QUALIFIED("Scripting", Absyn.QUALIFIED("getComponentsTest", Absyn.IDENT("Component")))), - { - Values.STRING(className), - Values.STRING(name), - Values.STRING(comment), - Values.BOOL(isProtected), - Values.BOOL(isFinal), - Values.BOOL(isFlow), - Values.BOOL(isStream), - Values.BOOL(isReplaceable), - Values.STRING(variability), - Values.STRING(innerOuter), - Values.STRING(inputOutput), - ValuesUtil.makeArray(list(Values.STRING(s) for s in dimensions)) - }, - {"className","name","comment","isProtected","isFinal","isFlow","isStream","isReplaceable","variability","innerOuter","inputOutput","dimensions"}, - -1 - ); -end makeGetComponentsRecord; - -function innerOuterStr -"Helper function to getComponentInfo, retrieve the inner outer string." - input Absyn.InnerOuter inInnerOuter; - output String outString; +protected function findModelicaPath2 "Handle modelica:// URIs" + input String mp; + input list inames; + input String version; + input Boolean b; + output String basePath; algorithm - outString:= - match (inInnerOuter) - case Absyn.INNER() then "inner"; - case Absyn.OUTER() then "outer"; - case Absyn.NOT_INNER_OUTER() then ""; - case Absyn.INNER_OUTER() then "inner outer"; - end match; -end innerOuterStr; - + basePath := matchcontinue (mp,inames,version,b) + local + list names; + String name,file; -function attrVariabilityStr -"Helper function to get_component_info, - retrieve variability as a string." - input Absyn.ElementAttributes inElementAttributes; - output String outString; -algorithm - outString:= - match (inElementAttributes) - case (Absyn.ATTR(variability = Absyn.VAR())) then ""; - case (Absyn.ATTR(variability = Absyn.DISCRETE())) then "discrete"; - case (Absyn.ATTR(variability = Absyn.PARAM())) then "parameter"; - case (Absyn.ATTR(variability = Absyn.CONST())) then "constant"; - end match; -end attrVariabilityStr; + case (_,name::names,_,_) + equation + false = stringEq(version,""); + file = mp + "/" + name + " " + version; + true = System.directoryExists(file); + // print("Found file 1: " + file + "\n"); + then findModelicaPath2(file,names,"",true); + case (_,name::_,_,_) + equation + false = stringEq(version,""); + file = mp + "/" + name + " " + version + ".mo"; + true = System.regularFileExists(file); + // print("Found file 2: " + file + "\n"); + then mp; -function attrDirectionStr -"Helper function to get_component_info, - retrieve direction as a string." - input Absyn.ElementAttributes inElementAttributes; - output String outString; -algorithm - outString:= - match (inElementAttributes) - case (Absyn.ATTR(direction = Absyn.INPUT())) then "input"; - case (Absyn.ATTR(direction = Absyn.OUTPUT())) then "output"; - case (Absyn.ATTR(direction = Absyn.BIDIR())) then ""; - end match; -end attrDirectionStr; + case (_,name::names,_,_) + equation + file = mp + "/" + name; + true = System.directoryExists(file); + // print("Found file 3: " + file + "\n"); + then findModelicaPath2(file,names,"",true); + case (_,name::_,_,_) + equation + file = mp + "/" + name + ".mo"; + true = System.regularFileExists(file); + // print("Found file 4: " + file + "\n"); + then mp; -function getComponentitemsName - " separated list of all component names and comments (if any)." - input Absyn.ComponentItem ci; - output String name, comment; -algorithm - (name, comment) := match ci - local - String c1,s2; - case Absyn.COMPONENTITEM(component = Absyn.COMPONENT(name = c1),comment = SOME(Absyn.COMMENT(_,SOME(s2)))) - then (c1, s2); - case Absyn.COMPONENTITEM(component = Absyn.COMPONENT(name = c1),comment = NONE()) - then (c1, ""); - end match; -end getComponentitemsName; + // This class is part of the current package.mo, or whatever... + case (_,_,_,true) + equation + // print("Did not find file 5: " + mp + " - " + name + "\n"); + then mp; + end matchcontinue; +end findModelicaPath2; annotation(__OpenModelica_Interface="backend"); end CevalScript; diff --git a/Compiler/Script/CevalScriptBackend.mo b/Compiler/Script/CevalScriptBackend.mo new file mode 100644 index 00000000000..57be6d873a3 --- /dev/null +++ b/Compiler/Script/CevalScriptBackend.mo @@ -0,0 +1,5322 @@ +/* + * This file is part of OpenModelica. + * + * Copyright (c) 1998-2014, Open Source Modelica Consortium (OSMC), + * c/o Linköpings universitet, Department of Computer and Information Science, + * SE-58183 Linköping, Sweden. + * + * All rights reserved. + * + * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF GPL VERSION 3 LICENSE OR + * THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.2. + * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES + * RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GPL VERSION 3, + * ACCORDING TO RECIPIENTS CHOICE. + * + * The OpenModelica software and the Open Source Modelica + * Consortium (OSMC) Public License (OSMC-PL) are obtained + * from OSMC, either from the above address, + * from the URLs: http://www.ida.liu.se/projects/OpenModelica or + * http://www.openmodelica.org, and in the OpenModelica distribution. + * GNU version 3 is obtained from: http://www.gnu.org/copyleft/gpl.html. + * + * This program is distributed WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH + * IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL. + * + * See the full OSMC Public License conditions for more details. + * + */ + +encapsulated package CevalScriptBackend +" + This module handles constant propagation of expressions for scripting + functions. This module contains the parts not needed for the + bootstrapping. +" + +// public imports +import Absyn; +import BackendDAE; +import Ceval; +import DAE; +import FCore; +import Error; +import GlobalScript; +import Interactive; +import Values; +import SimCode; +import UnitAbsyn; + +// protected imports +protected +import BackendDump; +import BackendDAECreate; +import BackendDAEUtil; +import BackendDAEOptimize; +import BackendEquation; +import BackendVariable; +import Builtin; +import CevalScript; +import CheckModel; +import ClassInf; +import ClockIndexes; +import Config; +import DAEQuery; +import DAEUtil; +import DAEDump; +import Debug; +import Dump; +import Expression; +import Figaro; +import FindZeroCrossings; +import Flags; +import FInst; +import FGraph; +import FGraphDump; +import GC; +import GlobalScriptUtil; +import Graph; +import HashSetString; +import Inst; +import InnerOuter; +import LexerModelicaDiff; +import DiffAlgorithm; +import List; +import Lookup; +import NFSCodeLookup; +import Prefix; +import Parser; +import Print; +import Refactor; +import SCodeDump; +import NFInst; +import NFSCodeEnv; +import NFSCodeFlatten; +import SimCodeMain; +import System; +import StaticScript; +import SCode; +import SCodeUtil; +import Settings; +import SimulationResults; +import SymbolicJacobian; +import TaskGraphResults; +import Tpl; +import CodegenFMU; +import Types; +import Util; +import ValuesUtil; +import XMLDump; +import ComponentReference; +import Uncertainties; +import OpenTURNS; +import FMI; +import FMIExt; +import ErrorExt; +import UnitAbsynBuilder; +import UnitParserExt; +import RewriteRules; +import BlockCallRewrite; + +protected constant DAE.Type simulationResultType_rtest = DAE.T_COMPLEX(ClassInf.RECORD(Absyn.IDENT("SimulationResult")),{ + DAE.TYPES_VAR("resultFile",DAE.dummyAttrVar,DAE.T_STRING_DEFAULT,DAE.UNBOUND(),NONE()), + DAE.TYPES_VAR("simulationOptions",DAE.dummyAttrVar,DAE.T_STRING_DEFAULT,DAE.UNBOUND(),NONE()), + DAE.TYPES_VAR("messages",DAE.dummyAttrVar,DAE.T_STRING_DEFAULT,DAE.UNBOUND(),NONE()) + },NONE(),DAE.emptyTypeSource); + +protected constant DAE.Type simulationResultType_full = DAE.T_COMPLEX(ClassInf.RECORD(Absyn.IDENT("SimulationResult")),{ + DAE.TYPES_VAR("resultFile",DAE.dummyAttrVar,DAE.T_STRING_DEFAULT,DAE.UNBOUND(),NONE()), + DAE.TYPES_VAR("simulationOptions",DAE.dummyAttrVar,DAE.T_STRING_DEFAULT,DAE.UNBOUND(),NONE()), + DAE.TYPES_VAR("messages",DAE.dummyAttrVar,DAE.T_STRING_DEFAULT,DAE.UNBOUND(),NONE()), + DAE.TYPES_VAR("timeFrontend",DAE.dummyAttrVar,DAE.T_REAL_DEFAULT,DAE.UNBOUND(),NONE()), + DAE.TYPES_VAR("timeBackend",DAE.dummyAttrVar,DAE.T_REAL_DEFAULT,DAE.UNBOUND(),NONE()), + DAE.TYPES_VAR("timeSimCode",DAE.dummyAttrVar,DAE.T_REAL_DEFAULT,DAE.UNBOUND(),NONE()), + DAE.TYPES_VAR("timeTemplates",DAE.dummyAttrVar,DAE.T_REAL_DEFAULT,DAE.UNBOUND(),NONE()), + DAE.TYPES_VAR("timeCompile",DAE.dummyAttrVar,DAE.T_REAL_DEFAULT,DAE.UNBOUND(),NONE()), + DAE.TYPES_VAR("timeSimulation",DAE.dummyAttrVar,DAE.T_REAL_DEFAULT,DAE.UNBOUND(),NONE()), + DAE.TYPES_VAR("timeTotal",DAE.dummyAttrVar,DAE.T_REAL_DEFAULT,DAE.UNBOUND(),NONE()) + },NONE(),DAE.emptyTypeSource); + +protected constant DAE.Type simulationResultType_drModelica = DAE.T_COMPLEX(ClassInf.RECORD(Absyn.IDENT("SimulationResult")),{ + DAE.TYPES_VAR("messages",DAE.dummyAttrVar,DAE.T_STRING_DEFAULT,DAE.UNBOUND(),NONE()), + DAE.TYPES_VAR("flatteningTime",DAE.dummyAttrVar,DAE.T_REAL_DEFAULT,DAE.UNBOUND(),NONE()), + DAE.TYPES_VAR("simulationTime",DAE.dummyAttrVar,DAE.T_REAL_DEFAULT,DAE.UNBOUND(),NONE()) + },NONE(),DAE.emptyTypeSource); + +//these are in reversed order than above +protected constant list> zeroAdditionalSimulationResultValues = + { ("timeTotal", Values.REAL(0.0)), + ("timeSimulation", Values.REAL(0.0)), + ("timeCompile", Values.REAL(0.0)), + ("timeTemplates", Values.REAL(0.0)), + ("timeSimCode", Values.REAL(0.0)), + ("timeBackend", Values.REAL(0.0)), + ("timeFrontend", Values.REAL(0.0)) + }; + +protected constant DAE.Exp defaultStartTime = DAE.RCONST(0.0) "default startTime"; +protected constant DAE.Exp defaultStopTime = DAE.RCONST(1.0) "default stopTime"; +protected constant DAE.Exp defaultNumberOfIntervals = DAE.ICONST(500) "default numberOfIntervals"; +protected constant DAE.Exp defaultStepSize = DAE.RCONST(0.002) "default stepSize"; +protected constant DAE.Exp defaultTolerance = DAE.RCONST(1e-6) "default tolerance"; +protected constant DAE.Exp defaultMethod = DAE.SCONST("dassl") "default method"; +protected constant DAE.Exp defaultFileNamePrefix = DAE.SCONST("") "default fileNamePrefix"; +protected constant DAE.Exp defaultOptions = DAE.SCONST("") "default options"; +protected constant DAE.Exp defaultOutputFormat = DAE.SCONST("mat") "default outputFormat"; +protected constant DAE.Exp defaultVariableFilter = DAE.SCONST(".*") "default variableFilter; does whole string matching, i.e. it becomes ^.*$ in the runtime"; +protected constant DAE.Exp defaultCflags = DAE.SCONST("") "default compiler flags"; +protected constant DAE.Exp defaultSimflags = DAE.SCONST("") "default simulation flags"; + +protected constant GlobalScript.SimulationOptions defaultSimulationOptions = + GlobalScript.SIMULATION_OPTIONS( + defaultStartTime, + defaultStopTime, + defaultNumberOfIntervals, + defaultStepSize, + defaultTolerance, + defaultMethod, + defaultFileNamePrefix, + defaultOptions, + defaultOutputFormat, + defaultVariableFilter, + defaultCflags, + defaultSimflags + ) "default simulation options"; + +protected constant list simulationOptionsNames = + { + "startTime", + "stopTime", + "numberOfIntervals", + "tolerance", + "method", + "fileNamePrefix", + "options", + "outputFormat", + "variableFilter", + "cflags", + "simflags" + } "names of simulation options"; + +public function getSimulationResultType + output DAE.Type t; +algorithm + t := if Config.getRunningTestsuite() then simulationResultType_rtest else simulationResultType_full; +end getSimulationResultType; + +public function getDrModelicaSimulationResultType + output DAE.Type t; +algorithm + t := if Config.getRunningTestsuite() then simulationResultType_rtest else simulationResultType_drModelica; +end getDrModelicaSimulationResultType; + +public function createSimulationResult + input String resultFile; + input String options; + input String message; + input list> inAddResultValues "additional values in reversed order; expected values see in CevalScript.simulationResultType_full"; + output Values.Value res; +protected + list> resultValues; + list vals; + list fields; + Boolean isTestType,notest; +algorithm + resultValues := listReverse(inAddResultValues); + //TODO: maybe we should test if the fields are the ones in simulationResultType_full + notest := not Config.getRunningTestsuite(); + fields := if notest then List.map(resultValues, Util.tuple21) else {}; + vals := if notest then List.map(resultValues, Util.tuple22) else {}; + res := Values.RECORD(Absyn.IDENT("SimulationResult"), + Values.STRING(resultFile)::Values.STRING(options)::Values.STRING(message)::vals, + "resultFile"::"simulationOptions"::"messages"::fields,-1); +end createSimulationResult; + +public function createDrModelicaSimulationResult + input String resultFile; + input String options; + input String message; + input list> inAddResultValues "additional values in reversed order; expected values see in CevalScript.simulationResultType_full"; + output Values.Value res; +protected + list> resultValues; + list vals; + list fields; + Boolean isTestType,notest; +algorithm + resultValues := listReverse(inAddResultValues); + //TODO: maybe we should test if the fields are the ones in simulationResultType_full + notest := not Config.getRunningTestsuite(); + fields := if notest then List.map(resultValues, Util.tuple21) else {}; + vals := if notest then List.map(resultValues, Util.tuple22) else {}; + res := Values.RECORD(Absyn.IDENT("SimulationResult"),Values.STRING(message):: + vals, "messages"::fields,-1); +end createDrModelicaSimulationResult; + +public function createSimulationResultFailure + input String message; + input String options; + output Values.Value res; +protected + list vals; + list fields; +algorithm + res := createSimulationResult("", options, message, zeroAdditionalSimulationResultValues); +end createSimulationResultFailure; + +public function createDrModelicaSimulationResultFailure + input String message; + input String options; + output Values.Value res; +protected + list vals; + list fields; +algorithm + res := createDrModelicaSimulationResult("", options, message, {}); +end createDrModelicaSimulationResultFailure; + +protected function buildCurrentSimulationResultExp + output DAE.Exp outExp; +protected + DAE.ComponentRef cref; +algorithm + cref := ComponentReference.makeCrefIdent("currentSimulationResult",DAE.T_UNKNOWN_DEFAULT,{}); + outExp := Expression.makeCrefExp(cref,DAE.T_UNKNOWN_DEFAULT); +end buildCurrentSimulationResultExp; + +protected function cevalCurrentSimulationResultExp + input FCore.Cache inCache; + input FCore.Graph env; + input String inputFilename; + input GlobalScript.SymbolTable st; + input Absyn.Msg msg; + output FCore.Cache outCache; + output String filename; +algorithm + (outCache,filename) := match (inCache,env,inputFilename,st,msg) + local FCore.Cache cache; + case (cache,_,"",_,_) + equation + (cache,Values.STRING(filename),_) = Ceval.ceval(cache,env,buildCurrentSimulationResultExp(),true,SOME(st),msg,0); + then (cache,filename); + else (inCache,inputFilename); + end match; +end cevalCurrentSimulationResultExp; + +public function convertSimulationOptionsToSimCode "converts SimulationOptions to SimCode.SimulationSettings" + input GlobalScript.SimulationOptions opts; + output SimCode.SimulationSettings settings; +algorithm + settings := match(opts) + local + Real startTime,stopTime,stepSize,tolerance; + Integer nIntervals; + String method,format,varFilter,cflags,options; + + case(GlobalScript.SIMULATION_OPTIONS( + DAE.RCONST(startTime), + DAE.RCONST(stopTime), + DAE.ICONST(nIntervals), + DAE.RCONST(stepSize), + DAE.RCONST(tolerance), + DAE.SCONST(method), + _, /* fileNamePrefix*/ + _, /* options */ + DAE.SCONST(format), + DAE.SCONST(varFilter), + DAE.SCONST(cflags), + _)) equation + options = ""; + + then SimCode.SIMULATION_SETTINGS(startTime,stopTime,nIntervals,stepSize,tolerance,method,options,format,varFilter,cflags); + end match; +end convertSimulationOptionsToSimCode; + +public function buildSimulationOptions +"@author: adrpo + builds a SimulationOptions record from the given input" + input DAE.Exp startTime "start time, default 0.0"; + input DAE.Exp stopTime "stop time, default 1.0"; + input DAE.Exp numberOfIntervals "number of intervals, default 500"; + input DAE.Exp stepSize "stepSize, default (stopTime-startTime)/numberOfIntervals"; + input DAE.Exp tolerance "tolerance, default 1e-6"; + input DAE.Exp method "method, default 'dassl'"; + input DAE.Exp fileNamePrefix "file name prefix, default ''"; + input DAE.Exp options "options, default ''"; + input DAE.Exp outputFormat "output format, default 'plt'"; + input DAE.Exp variableFilter; + input DAE.Exp cflags; + input DAE.Exp simflags; + output GlobalScript.SimulationOptions outSimulationOptions; +algorithm + outSimulationOptions := + GlobalScript.SIMULATION_OPTIONS( + startTime, + stopTime, + numberOfIntervals, + stepSize, + tolerance, + method, + fileNamePrefix, + options, + outputFormat, + variableFilter, + cflags, + simflags + ); +end buildSimulationOptions; + +public function getSimulationOption +"@author: adrpo + get the value from simulation option" + input GlobalScript.SimulationOptions inSimOpt; + input String optionName; + output DAE.Exp outOptionValue; +algorithm + outOptionValue := match(inSimOpt, optionName) + local + DAE.Exp e; + String name, msg; + + case (GlobalScript.SIMULATION_OPTIONS(startTime = e), "startTime") then e; + case (GlobalScript.SIMULATION_OPTIONS(stopTime = e), "stopTime") then e; + case (GlobalScript.SIMULATION_OPTIONS(numberOfIntervals = e), "numberOfIntervals") then e; + case (GlobalScript.SIMULATION_OPTIONS(stepSize = e), "stepSize") then e; + case (GlobalScript.SIMULATION_OPTIONS(tolerance = e), "tolerance") then e; + case (GlobalScript.SIMULATION_OPTIONS(method = e), "method") then e; + case (GlobalScript.SIMULATION_OPTIONS(fileNamePrefix = e), "fileNamePrefix") then e; + case (GlobalScript.SIMULATION_OPTIONS(options = e), "options") then e; + case (GlobalScript.SIMULATION_OPTIONS(outputFormat = e), "outputFormat") then e; + case (GlobalScript.SIMULATION_OPTIONS(variableFilter = e), "variableFilter") then e; + case (GlobalScript.SIMULATION_OPTIONS(cflags = e), "cflags") then e; + case (GlobalScript.SIMULATION_OPTIONS(simflags = e), "simflags") then e; + case (_, name) + equation + msg = "Unknown simulation option: " + name; + Error.addCompilerWarning(msg); + then + fail(); + end match; +end getSimulationOption; + +public function buildSimulationOptionsFromModelExperimentAnnotation +"@author: adrpo + retrieve annotation(experiment(....)) values and build a SimulationOptions object to return" + input GlobalScript.SymbolTable inSymTab; + input Absyn.Path inModelPath; + input String inFileNamePrefix; + input Option defaultOption; + output GlobalScript.SimulationOptions outSimOpt; +algorithm + outSimOpt := matchcontinue (inSymTab, inModelPath, inFileNamePrefix, defaultOption) + local + GlobalScript.SimulationOptions defaults, simOpt; + String experimentAnnotationStr; + list named; + + // search inside annotation(experiment(...)) + case (_, _, _, _) + equation + defaults = Util.getOptionOrDefault(defaultOption, setFileNamePrefixInSimulationOptions(defaultSimulationOptions, inFileNamePrefix)); + + experimentAnnotationStr = + Interactive.getNamedAnnotation( + inModelPath, + GlobalScriptUtil.getSymbolTableAST(inSymTab), + Absyn.IDENT("experiment"), + SOME("{}"), + Interactive.getExperimentAnnotationString); + // parse the string we get back, either {} or {StopTime=5, Tolerance = 0.10}; + + // jump to next case if the annotation is empty + false = stringEq(experimentAnnotationStr, "{}"); + + // get rid of '{' and '}' + experimentAnnotationStr = System.stringReplace(experimentAnnotationStr, "{", ""); + experimentAnnotationStr = System.stringReplace(experimentAnnotationStr, "}", ""); + + GlobalScript.ISTMTS({GlobalScript.IEXP(exp = Absyn.CALL(functionArgs = Absyn.FUNCTIONARGS(_, named)))}, _) + = Parser.parsestringexp("experiment(" + experimentAnnotationStr + ");\n", ""); + + simOpt = populateSimulationOptions(defaults, named); + then + simOpt; + + // if we fail, just use the defaults + else + equation + defaults = setFileNamePrefixInSimulationOptions(defaultSimulationOptions, inFileNamePrefix); + then defaults; + end matchcontinue; +end buildSimulationOptionsFromModelExperimentAnnotation; + +protected function setFileNamePrefixInSimulationOptions + input GlobalScript.SimulationOptions inSimOpt; + input String inFileNamePrefix; + output GlobalScript.SimulationOptions outSimOpt; +protected + DAE.Exp startTime, stopTime, numberOfIntervals, stepSize, tolerance, method, fileNamePrefix, options, outputFormat, variableFilter, cflags, simflags; + Boolean UseOtimica; +algorithm + UseOtimica := Config.acceptOptimicaGrammar() or Flags.getConfigBool(Flags.GENERATE_DYN_OPTIMIZATION_PROBLEM); + GlobalScript.SIMULATION_OPTIONS(startTime, stopTime, numberOfIntervals, stepSize, tolerance, method, _, options, outputFormat, variableFilter, cflags, simflags) := inSimOpt; + method := if UseOtimica then DAE.SCONST("optimization") else method; + numberOfIntervals := if UseOtimica then DAE.ICONST(50) else numberOfIntervals; + outSimOpt := GlobalScript.SIMULATION_OPTIONS(startTime, stopTime, numberOfIntervals, stepSize, tolerance, method, DAE.SCONST(inFileNamePrefix), options, outputFormat, variableFilter, cflags, simflags); +end setFileNamePrefixInSimulationOptions; + +protected function getConst +"@author: adrpo + Tranform a literal Absyn.Exp to DAE.Exp with the given DAE.Type" + input Absyn.Exp inAbsynExp; + input DAE.Type inExpType; + output DAE.Exp outExp; +algorithm + outExp := matchcontinue(inAbsynExp, inExpType) + local + Integer i; + Real r; + Absyn.Exp exp; + String str; + + case (Absyn.UNARY(Absyn.UMINUS(),exp), _) + equation + DAE.ICONST(i) = getConst(exp, inExpType); + i = intNeg(i); + then + DAE.ICONST(i); + + case (Absyn.UNARY(Absyn.UMINUS(),exp), _) + equation + DAE.RCONST(r) = getConst(exp, inExpType); + r = realNeg(r); + then + DAE.RCONST(r); + + case (Absyn.INTEGER(i), DAE.T_INTEGER()) then DAE.ICONST(i); + case (Absyn.REAL(str), DAE.T_REAL()) equation r = System.stringReal(str); then DAE.RCONST(r); + case (Absyn.INTEGER(i), DAE.T_REAL()) equation r = intReal(i); then DAE.RCONST(r); + + else + equation + str = "CevalScript.getConst: experiment annotation contains unsupported expression: " + Dump.printExpStr(inAbsynExp) + " of type " + Types.unparseType(inExpType) + "\n"; + Error.addCompilerError(str); + then + fail(); + end matchcontinue; +end getConst; + +protected function populateSimulationOptions +"@auhtor: adrpo + populate simulation options" + input GlobalScript.SimulationOptions inSimOpt; + input list inExperimentSettings; + output GlobalScript.SimulationOptions outSimOpt; +algorithm + outSimOpt := matchcontinue(inSimOpt, inExperimentSettings) + local + Absyn.Exp exp; + list rest; + GlobalScript.SimulationOptions simOpt; + DAE.Exp startTime; + DAE.Exp stopTime; + DAE.Exp numberOfIntervals; + DAE.Exp stepSize; + DAE.Exp tolerance; + DAE.Exp method; + DAE.Exp fileNamePrefix; + DAE.Exp options; + DAE.Exp outputFormat; + DAE.Exp variableFilter, cflags, simflags; + Real rStepSize, rStopTime, rStartTime; + Integer iNumberOfIntervals; + String name,msg; + + case (_, {}) then inSimOpt; + + case (GlobalScript.SIMULATION_OPTIONS(startTime, stopTime, numberOfIntervals, stepSize, tolerance, method, fileNamePrefix, options, outputFormat, variableFilter, cflags, simflags), + Absyn.NAMEDARG(argName = "Tolerance", argValue = exp)::rest) + equation + tolerance = getConst(exp, DAE.T_REAL_DEFAULT); + simOpt = populateSimulationOptions( + GlobalScript.SIMULATION_OPTIONS(startTime,stopTime,numberOfIntervals,stepSize,tolerance,method, + fileNamePrefix,options,outputFormat,variableFilter,cflags,simflags), + rest); + then + simOpt; + + case (GlobalScript.SIMULATION_OPTIONS(startTime, stopTime, numberOfIntervals, stepSize, tolerance, method, fileNamePrefix, options, outputFormat, variableFilter, cflags, simflags), + Absyn.NAMEDARG(argName = "StartTime", argValue = exp)::rest) + equation + startTime = getConst(exp, DAE.T_REAL_DEFAULT); + simOpt = populateSimulationOptions( + GlobalScript.SIMULATION_OPTIONS(startTime,stopTime,numberOfIntervals,stepSize,tolerance,method, + fileNamePrefix,options,outputFormat,variableFilter,cflags,simflags), + rest); + then + simOpt; + + case (GlobalScript.SIMULATION_OPTIONS(startTime, stopTime, numberOfIntervals, stepSize, tolerance, method, fileNamePrefix, options, outputFormat, variableFilter, cflags, simflags), + Absyn.NAMEDARG(argName = "StopTime", argValue = exp)::rest) + equation + stopTime = getConst(exp, DAE.T_REAL_DEFAULT); + simOpt = populateSimulationOptions( + GlobalScript.SIMULATION_OPTIONS(startTime,stopTime,numberOfIntervals,stepSize,tolerance,method, + fileNamePrefix,options,outputFormat,variableFilter,cflags,simflags), + rest); + then + simOpt; + + case (GlobalScript.SIMULATION_OPTIONS(startTime, stopTime, numberOfIntervals, stepSize, tolerance, method, fileNamePrefix, options, outputFormat, variableFilter, cflags, simflags), + Absyn.NAMEDARG(argName = "NumberOfIntervals", argValue = exp)::rest) + equation + numberOfIntervals = getConst(exp, DAE.T_INTEGER_DEFAULT); + simOpt = populateSimulationOptions( + GlobalScript.SIMULATION_OPTIONS(startTime,stopTime,numberOfIntervals,stepSize,tolerance,method, + fileNamePrefix,options,outputFormat,variableFilter,cflags,simflags), + rest); + then + simOpt; + + case (GlobalScript.SIMULATION_OPTIONS(startTime, stopTime, numberOfIntervals, stepSize, tolerance, method, fileNamePrefix, options, outputFormat, variableFilter, cflags, simflags), + Absyn.NAMEDARG(argName = "Interval", argValue = exp)::rest) + equation + DAE.RCONST(rStepSize) = getConst(exp, DAE.T_REAL_DEFAULT); + // a bit different for Interval, handle it LAST!!!! + GlobalScript.SIMULATION_OPTIONS(startTime,stopTime,numberOfIntervals,stepSize,tolerance,method, + fileNamePrefix,options,outputFormat,variableFilter,cflags,simflags) = + populateSimulationOptions(inSimOpt, rest); + + DAE.RCONST(rStartTime) = startTime; + DAE.RCONST(rStopTime) = stopTime; + iNumberOfIntervals = realInt(realDiv(realSub(rStopTime, rStartTime), rStepSize)); + + numberOfIntervals = DAE.ICONST(iNumberOfIntervals); + stepSize = DAE.RCONST(rStepSize); + + simOpt = GlobalScript.SIMULATION_OPTIONS(startTime,stopTime,numberOfIntervals,stepSize,tolerance,method, + fileNamePrefix,options,outputFormat,variableFilter,cflags,simflags); + then + simOpt; + + case (_,Absyn.NAMEDARG(argName = name, argValue = exp)::rest) + equation + msg = "Ignoring unknown experiment annotation option: " + name + " = " + Dump.printExpStr(exp); + Error.addCompilerWarning(msg); + simOpt = populateSimulationOptions(inSimOpt, rest); + then + simOpt; + end matchcontinue; +end populateSimulationOptions; + +protected function simOptionsAsString +"@author: adrpo + Gets the simulation options as string" + input list vals; + output String str; +algorithm + str := matchcontinue vals + local + list simOptsValues; + list lst; + + case _::lst + equation + // build a list with the values + simOptsValues = List.map(lst, ValuesUtil.valString); + // trim " from strings! + simOptsValues = List.map2(simOptsValues, System.stringReplace, "\"", "\'"); + + str = Util.buildMapStr(simulationOptionsNames, simOptsValues, " = ", ", "); + then + str; + + // on failure + case (_::lst) + equation + // build a list with the values + simOptsValues = List.map(lst, ValuesUtil.valString); + // trim " from strings! + simOptsValues = List.map2(simOptsValues, System.stringReplace, "\"", "\'"); + + str = stringDelimitList(simOptsValues, ", "); + then + str; + end matchcontinue; +end simOptionsAsString; + +public function cevalInteractiveFunctions3 +"defined in the interactive environment." + input FCore.Cache inCache; + input FCore.Graph inEnv; + input String inFunctionName; + input list inVals; + input GlobalScript.SymbolTable inSt; + input Absyn.Msg msg; + output FCore.Cache outCache; + output Values.Value outValue; + output GlobalScript.SymbolTable outInteractiveSymbolTable; +protected + import LexerModelicaDiff.{Token,TokenId,tokenContent,scanString,filterModelicaDiff,modelicaDiffTokenEq}; + import DiffAlgorithm.{Diff,diff,printActual,printDiffTerminalColor,printDiffXml}; +algorithm + (outCache,outValue,outInteractiveSymbolTable) := matchcontinue (inCache,inEnv,inFunctionName,inVals,inSt,msg) + local + String omdev,simflags,s1,s2,s3,str,str1,str2,str3,token,varid,cmd,executable,executable1,encoding,method_str, + outputFormat_str,initfilename,pd,executableSuffixedExe,sim_call,result_file,filename_1,filename, + call,str_1,mp,pathstr,name,cname,errMsg,errorStr, + title,xLabel,yLabel,filename2,varNameStr,xml_filename,xml_contents,visvar_str,pwd,omhome,omlib,omcpath,os, + platform,usercflags,senddata,res,workdir,gcc,confcmd,touch_file,uname,filenameprefix,compileDir,libDir,exeDir,configDir,from,to, + gridStr, logXStr, logYStr, x1Str, x2Str, y1Str, y2Str, curveWidthStr, curveStyleStr, legendPosition, footer, autoScaleStr,scriptFile,logFile, simflags2, outputFile, + systemPath, gccVersion, gd, strlinearizeTime, direction, suffix; + list simOptions; + list vals; + Absyn.Path path,classpath,className,baseClassPath; + SCode.Program scodeP,sp; + Option> fp; + FCore.Graph env; + GlobalScript.SymbolTable newst,st_1,st; + Absyn.Program p,ip,pnew,newp,ptot; + list newps; + list ic,ic_1; + list iv; + list cf; + GlobalScript.SimulationOptions simOpt; + Real startTime,stopTime,tolerance,reltol,reltolDiffMinMax,rangeDelta; + DAE.Exp startTimeExp,stopTimeExp,toleranceExp,intervalExp; + DAE.Type tp, ty; + list tys; + Absyn.Class absynClass; + Absyn.ClassDef cdef; + Absyn.Exp aexp; + DAE.DAElist dae; + BackendDAE.BackendDAE daelow,optdae; + BackendDAE.Variables vars; + BackendDAE.EquationArray eqnarr; + array> m,mt; + Option>> jac; + Values.Value ret_val,simValue,value,v,cvar,cvar2,v1,v2,v3; + Absyn.ComponentRef cr,cr_1; + Integer size,resI,i,i1,i2,i3,n,curveStyle,numberOfIntervals, status; + Option fmiContext, fmiInstance, fmiModelVariablesInstance; /* void* implementation: DO NOT UNBOX THE POINTER AS THAT MIGHT CHANGE IT. Just treat this as an opaque type. */ + Integer fmiLogLevel; + list is; + list fmiTypeDefinitionsList; + list fmiModelVariablesList; + FMI.ExperimentAnnotation fmiExperimentAnnotation; + FMI.Info fmiInfo; + list vars_1,args,strings,strs,strs1,strs2,visvars,postOptModStrings,postOptModStringsOrg,mps,files,dirs; + Real timeTotal,timeSimulation,timeStamp,val,x1,x2,y1,y2,r,r1,r2,linearizeTime,curveWidth,offset,offset1,offset2,scaleFactor,scaleFactor1,scaleFactor2; + GlobalScript.Statements istmts; + list istmtss; + Boolean have_corba, bval, anyCode, b, b1, b2, externalWindow, logX, logY, autoScale, forceOMPlot, gcc_res, omcfound, rm_res, touch_res, uname_res, ifcpp, ifmsvc,sort, builtin, showProtected, inputConnectors, outputConnectors; + FCore.Cache cache; + list lf; + Absyn.ComponentRef crefCName; + list> resultValues; + list realVals; + list>> deps,depstransitive,depstransposed,depstransposedtransitive,depsmerged,depschanged; + Absyn.CodeNode codeNode; + list cvars,vals2; + list paths; + list nargs; + list classes; + Absyn.Within within_; + BackendDAE.EqSystem syst; + BackendDAE.Shared shared; + GlobalScript.SimulationOptions defaulSimOpt; + SimCode.SimulationSettings simSettings; + Boolean dumpExtractionSteps, requireExactVersion; + list>> uses; + Config.LanguageStandard oldLanguageStd; + SCode.Element cl; + list cls, elts; + list names, namesPublic, namesProtected, namesChanged, fileNames; + HashSetString.HashSet hashSetString; + list blst; + list messages; + UnitAbsyn.Unit u1,u2; + Real stoptime,starttime,tol,stepsize,interval; + String stoptime_str,stepsize_str,starttime_str,tol_str,num_intervalls_str,description,prefix; + list interfaceType; + list>> interfaceTypeAssoc; + SCode.Encapsulated encflag; + SCode.Restriction restr; + list> valsLst; + list tokens1, tokens2; + list>> diffs; + + case (cache,_,"setClassComment",{Values.CODE(Absyn.C_TYPENAME(path)),Values.STRING(str)},st as GlobalScript.SYMBOLTABLE(ast=p),_) + equation + (p,b) = Interactive.setClassComment(path, str, p); + st = GlobalScriptUtil.setSymbolTableAST(st, p); + then + (cache,Values.BOOL(b),st); + + case (cache, _, "isShortDefinition", {Values.CODE(Absyn.C_TYPENAME(path))}, st as GlobalScript.SYMBOLTABLE(ast = p), _) + equation + b = isShortDefinition(path, p); + then + (cache,Values.BOOL(b),st); + + case (cache,_,"getUsedClassNames",{Values.CODE(Absyn.C_TYPENAME(path))},st as GlobalScript.SYMBOLTABLE(),_) + equation + (sp, st) = GlobalScriptUtil.symbolTableToSCode(st); + (sp, _) = NFSCodeFlatten.flattenClassInProgram(path, sp); + sp = SCode.removeBuiltinsFromTopScope(sp); + paths = Interactive.getSCodeClassNamesRecursive(sp); + // paths = bcallret2(sort, List.sort, paths, Absyn.pathGe, paths); + vals = List.map(paths,ValuesUtil.makeCodeTypeName); + then (cache,ValuesUtil.makeArray(vals),st); + + case (cache,_,"getUsedClassNames",_,st as GlobalScript.SYMBOLTABLE(),_) + then (cache,ValuesUtil.makeArray({}),st); + + case (cache,_,"getClassComment",{Values.CODE(Absyn.C_TYPENAME(path))},st as GlobalScript.SYMBOLTABLE(ast = p),_) + equation + Absyn.CLASS(_,_,_,_,_,cdef,_) = Interactive.getPathedClassInProgram(path, p); + str = System.unescapedString(getClassComment(cdef)); + then + (cache,Values.STRING(str),st); + + case (cache,_,"getClassComment",{Values.CODE(Absyn.C_TYPENAME(_))},st as GlobalScript.SYMBOLTABLE(),_) + then + (cache,Values.STRING(""),st); + + case (cache,_,"getPackages",{Values.CODE(Absyn.C_TYPENAME(Absyn.IDENT("AllLoadedClasses")))},st as GlobalScript.SYMBOLTABLE(ast = p),_) + equation + paths = Interactive.getTopPackages(p); + vals = List.map(paths,ValuesUtil.makeCodeTypeName); + then + (cache,ValuesUtil.makeArray(vals),st); + + case (cache,_,"getPackages",{Values.CODE(Absyn.C_TYPENAME(path))},st as GlobalScript.SYMBOLTABLE(ast = p),_) + equation + paths = Interactive.getPackagesInPath(path, p); + vals = List.map(paths,ValuesUtil.makeCodeTypeName); + then + (cache,ValuesUtil.makeArray(vals),st); + + case (cache,_,"convertUnits",{Values.STRING(str1),Values.STRING(str2)},st,_) + equation + UnitParserExt.initSIUnits(); + (u1,scaleFactor1,offset1) = UnitAbsynBuilder.str2unitWithScaleFactor(str1,NONE()); + (u2,scaleFactor2,offset2) = UnitAbsynBuilder.str2unitWithScaleFactor(str2,NONE()); + b = valueEq(u1,u2); + /* How to calculate the final scale factor and offset? + ºF = (ºK - 273.15)* 1.8000 + 32.00 = (ºK - 255.37)* 1.8000 + ºC = (ºK - 273.15) + + ºF = (ºC - (255.37 - 273.15))*(1.8/1.0) + */ + scaleFactor = realDiv(scaleFactor2, scaleFactor1); + offset = realSub(offset2,offset1); + then + (cache,Values.TUPLE({Values.BOOL(b),Values.REAL(scaleFactor),Values.REAL(offset)}),st); + + case (cache,_,"getClassInformation",{Values.CODE(Absyn.C_TYPENAME(className))},st as GlobalScript.SYMBOLTABLE(),_) + equation + v = getClassInformation(className, st.ast); + then (cache,v,st); + + case (cache,_,"getClassInformation",_,st,_) + then (cache,Values.TUPLE({Values.STRING(""),Values.STRING(""),Values.BOOL(false),Values.BOOL(false),Values.BOOL(false),Values.STRING(""), + Values.BOOL(false),Values.INTEGER(0),Values.INTEGER(0),Values.INTEGER(0),Values.INTEGER(0),Values.ARRAY({},{0})}),st); + + case (cache,_,"diffModelicaFileListings",{Values.STRING(s1),Values.STRING(s2),Values.ENUM_LITERAL(name=path)},(st as GlobalScript.SYMBOLTABLE(ast = p)),_) + algorithm + tokens1 := scanString(s1); + tokens2 := scanString(s2); + diffs := diff(tokens1, tokens2, modelicaDiffTokenEq); + // print("Before filtering:\n"+printDiffTerminalColor(diffs, tokenContent)+"\n"); + diffs := filterModelicaDiff(diffs,removeWhitespace=false); + // Scan a second time, with comments filtered into place + str := printActual(diffs, tokenContent); + // print("Intermediate string:\n"+printDiffTerminalColor(diffs, tokenContent)+"\n"); + tokens2 := scanString(str); + diffs := diff(tokens1, tokens2, modelicaDiffTokenEq); + // print("Before filtering (2):\n"+printDiffTerminalColor(diffs, tokenContent)+"\n"); + diffs := filterModelicaDiff(diffs); + str := match Absyn.pathLastIdent(path) + case "plain" then printActual(diffs, tokenContent); + case "color" then printDiffTerminalColor(diffs, tokenContent); + case "xml" then printDiffXml(diffs, tokenContent); + else + algorithm + Error.addInternalError("Unknown diffModelicaFileListings choice", sourceInfo()); + then fail(); + end match; + then (cache,Values.STRING(str),st); + + case (cache,_,"diffModelicaFileListings",_,st,_) then (cache,Values.STRING(""),st); + + // exportToFigaro cases added by Alexander Carlqvist + case (cache, _, "exportToFigaro", {Values.CODE(Absyn.C_TYPENAME(path)), Values.STRING(s1), Values.STRING(str), Values.STRING(str1), Values.STRING(str2), Values.STRING(str3)}, st as GlobalScript.SYMBOLTABLE(ast = p), _) + equation + (scodeP, _) = GlobalScriptUtil.symbolTableToSCode(st); + /* The following line of code should be commented out when building from trunk. + Uncomment when bootstrapping. */ + Figaro.run(scodeP, path, s1, str, str1, str2, str3); + then (cache, Values.BOOL(true), st); + + case (cache, _, "exportToFigaro", _, st, _) + then (cache, Values.BOOL(false), st); + + case (_,_, "rewriteBlockCall",{Values.CODE(Absyn.C_TYPENAME(classpath)), Values.CODE(Absyn.C_TYPENAME(path))}, + (st as GlobalScript.SYMBOLTABLE(p as Absyn.PROGRAM())),_) + equation + absynClass = Interactive.getPathedClassInProgram(path, p); + classes = {absynClass}; + absynClass = Interactive.getPathedClassInProgram(classpath, p); + within_ = Interactive.buildWithin(classpath); + pnew = BlockCallRewrite.rewriteBlockCall(Absyn.PROGRAM({absynClass}, within_), Absyn.PROGRAM(classes, within_)); + pnew = Interactive.updateProgram(pnew, p); + newst = GlobalScriptUtil.setSymbolTableAST(st, pnew); + then + (FCore.emptyCache(),Values.BOOL(true), newst); + + case (cache, _, "rewriteBlockCall", _, st, _) + then (cache, Values.BOOL(false), st); + + case (cache,env,"jacobian",{Values.CODE(Absyn.C_TYPENAME(path))}, + (GlobalScript.SYMBOLTABLE( + ast = p,explodedAst = fp,instClsLst = ic, + lstVarVal = iv,compiledFunctions = cf, + loadedFiles = lf)),_) + equation + scodeP = SCodeUtil.translateAbsyn2SCode(p); + (cache, env, _, dae) = Inst.instantiateClass(cache, InnerOuter.emptyInstHierarchy, scodeP, path); + dae = DAEUtil.transformationsBeforeBackend(cache,env,dae); + ic_1 = Interactive.addInstantiatedClass(ic, GlobalScript.INSTCLASS(path,dae,env)); + filenameprefix = Absyn.pathString(path); + description = DAEUtil.daeDescription(dae); + daelow = BackendDAECreate.lower(dae,cache,env,BackendDAE.EXTRA_INFO(description,filenameprefix)); + (BackendDAE.DAE({syst},shared)) = BackendDAEUtil.preOptimizeBackendDAE(daelow,NONE()); + (syst,m,_) = BackendDAEUtil.getIncidenceMatrixfromOption(syst,BackendDAE.NORMAL(),NONE()); + vars = BackendVariable.daeVars(syst); + eqnarr = BackendEquation.getEqnsFromEqSystem(syst); + (jac, _) = SymbolicJacobian.calculateJacobian(vars, eqnarr, m, false,shared); + res = BackendDump.dumpJacobianStr(jac); + then + (cache,Values.STRING(res),GlobalScript.SYMBOLTABLE(p,fp,ic_1,iv,cf,lf)); + + case (cache,env,"translateModel",vals as {Values.CODE(Absyn.C_TYPENAME(className)),_,_,_,_,_,Values.STRING(filenameprefix),_,_,_,_,_},st,_) + equation + (cache,simSettings) = calculateSimulationSettings(cache,env,vals,st,msg); + (cache,st_1,_,_,_,_) = translateModel(cache, env, className, st, filenameprefix, true, SOME(simSettings)); + then + (cache,Values.BOOL(true),st_1); + + case (cache,_,"translateModel",_,st,_) + then (cache,Values.BOOL(false),st); + + case (cache,env,"modelEquationsUC",{Values.CODE(Absyn.C_TYPENAME(className)),Values.STRING(outputFile),Values.BOOL(dumpExtractionSteps)},st,_) + equation + (cache,ret_val,st_1) = Uncertainties.modelEquationsUC(cache, env, className, st, outputFile,dumpExtractionSteps); + then + (cache,ret_val,st_1); + + case (cache,_,"modelEquationsUC",_,st,_) + then (cache,Values.STRING("There were errors during extraction of uncertainty equations. Use getErrorString() to see them."),st); + + /*case (cache,env,"translateModelCPP",{Values.CODE(Absyn.C_TYPENAME(className)),Values.STRING(filenameprefix)},st,msg) + equation + (cache,ret_val,st_1,_,_,_,_) = translateModelCPP(cache,env, className, st, filenameprefix,true,NONE()); + then + (cache,ret_val,st_1);*/ + + 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 == "" 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, str2, filenameprefix, true, SOME(simSettings)); + then + (cache,ret_val,st_1); + + 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); + + case (cache,env,"translateModelXML",{Values.CODE(Absyn.C_TYPENAME(className)),Values.STRING(filenameprefix)},st,_) + equation + filenameprefix = Util.stringReplaceChar(filenameprefix,".","_"); + (cache,ret_val,st_1) = translateModelXML(cache, env, className, st, filenameprefix, true, NONE()); + then + (cache,ret_val,st_1); + + case (cache,env,"exportDAEtoMatlab",{Values.CODE(Absyn.C_TYPENAME(className)),Values.STRING(filenameprefix)},st,_) + equation + (cache,ret_val,st_1,_) = getIncidenceMatrix(cache,env, className, st, msg, filenameprefix); + then + (cache,ret_val,st_1); + + case (cache,env,"checkModel",{Values.CODE(Absyn.C_TYPENAME(className))},st,_) + equation + Flags.setConfigBool(Flags.CHECK_MODEL, true); + (cache,ret_val,st_1) = checkModel(cache, env, className, st, msg); + Flags.setConfigBool(Flags.CHECK_MODEL, false); + then + (cache,ret_val,st_1); + + case (cache,env,"checkAllModelsRecursive",{Values.CODE(Absyn.C_TYPENAME(className)),Values.BOOL(showProtected)},st,_) + equation + (cache,ret_val,st_1) = checkAllModelsRecursive(cache, env, className, showProtected, st, msg); + then + (cache,ret_val,st_1); + + case (cache,env,"translateGraphics",{Values.CODE(Absyn.C_TYPENAME(className))},st,_) + equation + (cache,ret_val,st_1) = translateGraphics(cache,env, className, st, msg); + then + (cache,ret_val,st_1); + + case (cache,_,"setPlotCommand",{Values.STRING(_)},st,_) + then + (cache,Values.BOOL(false),st); + + case (cache,_,"getAnnotationVersion",{},st,_) + equation + res = Config.getAnnotationVersion(); + then + (cache,Values.STRING(res),st); + + case (cache,_,"getNoSimplify",{},st,_) + equation + b = Config.getNoSimplify(); + then + (cache,Values.BOOL(b),st); + + case (cache,_,"setNoSimplify",{Values.BOOL(b)},st,_) + equation + Config.setNoSimplify(b); + then + (cache,Values.BOOL(true),st); + + case (cache,_,"getShowAnnotations",{},st,_) + equation + b = Config.showAnnotations(); + then + (cache,Values.BOOL(b),st); + + case (cache,_,"setShowAnnotations",{Values.BOOL(b)},st,_) + equation + Config.setShowAnnotations(b); + then + (cache,Values.BOOL(true),st); + + case (cache,_,"getVectorizationLimit",{},st,_) + equation + i = Config.vectorizationLimit(); + then + (cache,Values.INTEGER(i),st); + + case (cache,_,"getOrderConnections",{},st,_) + equation + b = Config.orderConnections(); + then + (cache,Values.BOOL(b),st); + + case (cache,env,"buildModel",vals,st,_) + equation + List.map_0(ClockIndexes.buildModelClocks,System.realtimeClear); + System.realtimeTick(ClockIndexes.RT_CLOCK_SIMULATE_TOTAL); + (cache,st,compileDir,executable,_,_,initfilename,_,_) = buildModel(cache,env, vals, st, msg); + executable = if not Config.getRunningTestsuite() then compileDir + executable else executable; + then + (cache,ValuesUtil.makeArray({Values.STRING(executable),Values.STRING(initfilename)}),st); + + case(cache,env,"buildOpenTURNSInterface",vals,st,_) + equation + (cache,scriptFile,st) = buildOpenTURNSInterface(cache,env,vals,st,msg); + then + (cache,Values.STRING(scriptFile),st); + case(_,_,"buildOpenTURNSInterface",_,_,_) + equation + Error.addMessage(Error.INTERNAL_ERROR,{"buildOpenTURNSInterface failed. Use getErrorString() to see why."}); + then + fail(); + + case(cache,env,"runOpenTURNSPythonScript",vals,st,_) + equation + (cache,logFile,st) = runOpenTURNSPythonScript(cache,env,vals,st,msg); + then + (cache,Values.STRING(logFile),st); + case(_,_,"runOpenTURNSPythonScript",_,_,_) + equation + Error.addMessage(Error.INTERNAL_ERROR,{"runOpenTURNSPythonScript failed. Use getErrorString() to see why"}); + then + fail(); + + case (cache,_,"buildModel",_,st,_) /* failing build_model */ + then (cache,ValuesUtil.makeArray({Values.STRING(""),Values.STRING("")}),st); + + case (cache,env,"buildModelBeast",vals,st,_) + equation + (cache,st,compileDir,executable,_,initfilename) = buildModelBeast(cache,env,vals,st,msg); + executable = if not Config.getRunningTestsuite() then compileDir + executable else executable; + then + (cache,ValuesUtil.makeArray({Values.STRING(executable),Values.STRING(initfilename)}),st); + + // adrpo: see if the model exists before simulation! + case (cache,_,"simulate",vals as Values.CODE(Absyn.C_TYPENAME(className))::_,st as GlobalScript.SYMBOLTABLE(ast = p),_) + equation + crefCName = Absyn.pathToCref(className); + false = Interactive.existClass(crefCName, p); + errMsg = "Simulation Failed. Model: " + Absyn.pathString(className) + " does not exist! Please load it first before simulation."; + simValue = createSimulationResultFailure(errMsg, simOptionsAsString(vals)); + then + (cache,simValue,st); + + case (cache,env,"simulate",vals as Values.CODE(Absyn.C_TYPENAME(className))::_,st_1,_) + equation + System.realtimeTick(ClockIndexes.RT_CLOCK_SIMULATE_TOTAL); + (cache,st,compileDir,executable,_,outputFormat_str,_,simflags,resultValues) = buildModel(cache,env,vals,st_1,msg); + + exeDir=compileDir; + (cache,simSettings) = calculateSimulationSettings(cache,env,vals,st_1,msg); + SimCode.SIMULATION_SETTINGS(outputFormat = outputFormat_str) + = simSettings; + result_file = stringAppendList(List.consOnTrue(not Config.getRunningTestsuite(),compileDir,{executable,"_res.",outputFormat_str})); + executableSuffixedExe = stringAppend(executable, getSimulationExtension(Config.simCodeTarget(),System.platform())); + logFile = stringAppend(executable,".log"); + // adrpo: log file is deleted by buildModel! do NOT DELETE IT AGAIN! + // we should really have different log files for simulation/compilation! + // as the buildModel log file will be deleted here and that gives less information to the user! + if System.regularFileExists(logFile) then + 0 = System.removeFile(logFile); + end if; + sim_call = stringAppendList({"\"",exeDir,executableSuffixedExe,"\""," ",simflags}); + System.realtimeTick(ClockIndexes.RT_CLOCK_SIMULATE_SIMULATION); + SimulationResults.close() "Windows cannot handle reading and writing to the same file from different processes like any real OS :("; + resI = System.systemCall(sim_call,logFile); + timeSimulation = System.realtimeTock(ClockIndexes.RT_CLOCK_SIMULATE_SIMULATION); + timeTotal = System.realtimeTock(ClockIndexes.RT_CLOCK_SIMULATE_TOTAL); + (cache,simValue,newst) = createSimulationResultFromcallModelExecutable(resI,timeTotal,timeSimulation,resultValues,cache,className,vals,st,result_file,logFile); + then + (cache,simValue,newst); + + case (cache,_,"simulate",vals as Values.CODE(Absyn.C_TYPENAME(className))::_,st,_) + equation + _ = Settings.getInstallationDirectoryPath() "simulation fail for some other reason than OPENMODELICAHOME not being set." ; + str = Absyn.pathString(className); + res = "Failed to build model: " + str; + simValue = createSimulationResultFailure(res, simOptionsAsString(vals)); + then + (cache,simValue,st); + + case (cache,_,"simulate",vals as Values.CODE(Absyn.C_TYPENAME(className))::_,st,_) + equation + str = Absyn.pathString(className); + simValue = createSimulationResultFailure( + "Simulation failed for model: " + str + + "\nEnvironment variable OPENMODELICAHOME not set.", + simOptionsAsString(vals)); + then + (cache,simValue,st); + + // adrpo: see if the model exists before moving! + case (cache,_,"moveClass",{Values.CODE(Absyn.C_TYPENAME(className)), + Values.STRING(_)}, + st as GlobalScript.SYMBOLTABLE(ast = p),_) + equation + crefCName = Absyn.pathToCref(className); + false = Interactive.existClass(crefCName, p); + simValue = Values.BOOL(false); + then + (cache,simValue,st); + + // everything should work fine here + case (cache,_,"moveClass",{Values.CODE(Absyn.C_TYPENAME(className)), + Values.STRING(direction)}, + st as GlobalScript.SYMBOLTABLE(ast = p),_) + equation + crefCName = Absyn.pathToCref(className); + true = Interactive.existClass(crefCName, p); + p = moveClass(className, direction, p); + st = GlobalScriptUtil.setSymbolTableAST(st, p); + simValue = Values.BOOL(true); + then + (cache,simValue,st); + + // adrpo: some error happened! + case (cache,_,"moveClass",{Values.CODE(Absyn.C_TYPENAME(className)), + Values.STRING(_)}, + st as GlobalScript.SYMBOLTABLE(ast = p),_) + equation + crefCName = Absyn.pathToCref(className); + true = Interactive.existClass(crefCName, p); + errMsg = "moveClass Error: Could not move the model " + Absyn.pathString(className) + ". Unknown error."; + Error.addMessage(Error.INTERNAL_ERROR, {errMsg}); + simValue = Values.BOOL(false); + then + (cache,simValue,st); + + case (cache,_,"copyClass",{Values.CODE(Absyn.C_TYPENAME(classpath)), Values.STRING(name), Values.CODE(Absyn.C_TYPENAME(Absyn.IDENT("TopLevel")))}, + st as GlobalScript.SYMBOLTABLE(ast = p),_) + equation + absynClass = Interactive.getPathedClassInProgram(classpath, p); + p = copyClass(absynClass, name, Absyn.TOP(), p); + st = GlobalScriptUtil.setSymbolTableAST(st, p); + ret_val = Values.BOOL(true); + then + (cache,ret_val,st); + + case (cache,_,"copyClass",{Values.CODE(Absyn.C_TYPENAME(classpath)), Values.STRING(name), Values.CODE(Absyn.C_TYPENAME(path))}, + st as GlobalScript.SYMBOLTABLE(ast = p),_) + equation + absynClass = Interactive.getPathedClassInProgram(classpath, p); + p = copyClass(absynClass, name, Absyn.WITHIN(path), p); + st = GlobalScriptUtil.setSymbolTableAST(st, p); + ret_val = Values.BOOL(true); + then + (cache,ret_val,st); + + case (cache,env,"linearize",(vals as Values.CODE(Absyn.C_TYPENAME(_))::_),st_1,_) + equation + + System.realtimeTick(ClockIndexes.RT_CLOCK_SIMULATE_TOTAL); + + b = Flags.getConfigBool(Flags.GENERATE_SYMBOLIC_LINEARIZATION); + Flags.setConfigBool(Flags.GENERATE_SYMBOLIC_LINEARIZATION, true); + + (cache,st,compileDir,executable,_,outputFormat_str,_,simflags,resultValues) = buildModel(cache,env,vals,st_1,msg); + Values.REAL(linearizeTime) = getListNthShowError(vals,"try to get stop time",0,2); + executableSuffixedExe = stringAppend(executable, System.getExeExt()); + logFile = stringAppend(executable,".log"); + if System.regularFileExists(logFile) then + 0 = System.removeFile(logFile); + end if; + strlinearizeTime = realString(linearizeTime); + sim_call = stringAppendList({"\"",compileDir,executableSuffixedExe,"\""," ","-l=",strlinearizeTime," ",simflags}); + System.realtimeTick(ClockIndexes.RT_CLOCK_SIMULATE_SIMULATION); + SimulationResults.close() "Windows cannot handle reading and writing to the same file from different processes like any real OS :("; + 0 = System.systemCall(sim_call,logFile); + + result_file = stringAppendList(List.consOnTrue(not Config.getRunningTestsuite(),compileDir,{executable,"_res.",outputFormat_str})); + timeSimulation = System.realtimeTock(ClockIndexes.RT_CLOCK_SIMULATE_SIMULATION); + timeTotal = System.realtimeTock(ClockIndexes.RT_CLOCK_SIMULATE_TOTAL); + simValue = createSimulationResult( + result_file, + simOptionsAsString(vals), + System.readFile(logFile), + ("timeTotal", Values.REAL(timeTotal)) :: + ("timeSimulation", Values.REAL(timeSimulation)) :: + resultValues); + newst = GlobalScriptUtil.addVarToSymboltable( + DAE.CREF_IDENT("currentSimulationResult", DAE.T_STRING_DEFAULT, {}), + Values.STRING(result_file), FGraph.empty(), st); + //reset config flag + Flags.setConfigBool(Flags.GENERATE_SYMBOLIC_LINEARIZATION, b); + then + (cache,simValue,newst); + + case (cache,env,"optimize",(vals as Values.CODE(Absyn.C_TYPENAME(className))::_),st_1,_) + equation + + System.realtimeTick(ClockIndexes.RT_CLOCK_SIMULATE_TOTAL); + + Flags.setConfigBool(Flags.GENERATE_SYMBOLIC_LINEARIZATION,true); + Flags.setConfigEnum(Flags.GRAMMAR, Flags.OPTIMICA); + Flags.setConfigBool(Flags.GENERATE_DYN_OPTIMIZATION_PROBLEM,true); + + (cache,st,compileDir,executable,_,outputFormat_str,_,simflags,resultValues) = buildModel(cache,env,vals,st_1,msg); + exeDir=compileDir; + (cache,simSettings) = calculateSimulationSettings(cache,env,vals,st_1,msg); + SimCode.SIMULATION_SETTINGS(outputFormat = outputFormat_str) = simSettings; + result_file = stringAppendList(List.consOnTrue(not Config.getRunningTestsuite(),compileDir,{executable,"_res.",outputFormat_str})); + executableSuffixedExe = stringAppend(executable, getSimulationExtension(Config.simCodeTarget(),System.platform())); + logFile = stringAppend(executable,".log"); + // adrpo: log file is deleted by buildModel! do NOT DELTE IT AGAIN! + // we should really have different log files for simulation/compilation! + // as the buildModel log file will be deleted here and that gives less information to the user! + if System.regularFileExists(logFile) then + 0 = System.removeFile(logFile); + end if; + sim_call = stringAppendList({"\"",exeDir,executableSuffixedExe,"\""," ",simflags}); + System.realtimeTick(ClockIndexes.RT_CLOCK_SIMULATE_SIMULATION); + SimulationResults.close() "Windows cannot handle reading and writing to the same file from different processes like any real OS :("; + resI = System.systemCall(sim_call,logFile); + timeSimulation = System.realtimeTock(ClockIndexes.RT_CLOCK_SIMULATE_SIMULATION); + timeTotal = System.realtimeTock(ClockIndexes.RT_CLOCK_SIMULATE_TOTAL); + (cache,simValue,newst) = createSimulationResultFromcallModelExecutable(resI,timeTotal,timeSimulation,resultValues,cache,className,vals,st,result_file,logFile); + then + (cache,simValue,newst); + + case (cache,env,"instantiateModel",{Values.CODE(Absyn.C_TYPENAME(className))},st,_) + equation + (cache,env,dae,st) = runFrontEnd(cache,env,className,st,true); + str = DAEDump.dumpStr(dae,FCore.getFunctionTree(cache)); + then + (cache,Values.STRING(str),st); + + case (cache,_,"instantiateModel",{Values.CODE(Absyn.C_TYPENAME(path))},st as GlobalScript.SYMBOLTABLE(ast=p),_) + equation + cr_1 = Absyn.pathToCref(path); + false = Interactive.existClass(cr_1, p); + str = Absyn.pathString(path); + Error.addMessage(Error.LOOKUP_ERROR, {str,""}); + then + (cache,Values.STRING(""),st); + + case (cache,_,"instantiateModel",{Values.CODE(Absyn.C_TYPENAME(path))},st,_) + equation + b = Error.getNumMessages() == 0; + str = Absyn.pathString(path); + str = "Instantiation of " + str + " failed with no error message"; + if b then + Error.addMessage(Error.INTERNAL_ERROR, {str,""}); + end if; + then + (cache,Values.STRING(""),st); + + case (cache,_,"importFMU",{Values.STRING(filename),Values.STRING(workdir),Values.INTEGER(fmiLogLevel),Values.BOOL(b1), Values.BOOL(b2), Values.BOOL(inputConnectors), Values.BOOL(outputConnectors)},st,_) + equation + Error.clearMessages() "Clear messages"; + true = System.regularFileExists(filename); + workdir = if System.directoryExists(workdir) then workdir else System.pwd(); + /* Initialize FMI objects */ + (b, fmiContext, fmiInstance, fmiInfo, fmiTypeDefinitionsList, fmiExperimentAnnotation, fmiModelVariablesInstance, fmiModelVariablesList) = FMIExt.initializeFMIImport(filename, workdir, fmiLogLevel, inputConnectors, outputConnectors); + true = b; /* if something goes wrong while initializing */ + fmiTypeDefinitionsList = listReverse(fmiTypeDefinitionsList); + fmiModelVariablesList = listReverse(fmiModelVariablesList); + s1 = System.tolower(System.platform()); + str = Tpl.tplString(CodegenFMU.importFMUModelica, FMI.FMIIMPORT(s1, filename, workdir, fmiLogLevel, b2, fmiContext, fmiInstance, fmiInfo, fmiTypeDefinitionsList, fmiExperimentAnnotation, fmiModelVariablesInstance, fmiModelVariablesList, inputConnectors, outputConnectors)); + pd = System.pathDelimiter(); + str1 = FMI.getFMIModelIdentifier(fmiInfo); + str2 = FMI.getFMIType(fmiInfo); + str3 = FMI.getFMIVersion(fmiInfo); + outputFile = stringAppendList({workdir,pd,str1,"_",str2,"_FMU.mo"}); + filename_1 = if b1 then stringAppendList({workdir,pd,str1,"_",str2,"_FMU.mo"}) else stringAppendList({str1,"_",str2,"_FMU.mo"}); + System.writeFile(outputFile, str); + /* Release FMI objects */ + FMIExt.releaseFMIImport(fmiModelVariablesInstance, fmiInstance, fmiContext, str3); + then + (cache,Values.STRING(filename_1),st); + + case (cache,_,"importFMU",{Values.STRING(filename),Values.STRING(_),Values.INTEGER(_),Values.BOOL(_), Values.BOOL(_), Values.BOOL(_), Values.BOOL(_)},st,_) + equation + false = System.regularFileExists(filename); + Error.clearMessages() "Clear messages"; + Error.addMessage(Error.FILE_NOT_FOUND_ERROR, {filename}); + then + (cache,Values.STRING(""),st); + + case (cache,_,"importFMU",{Values.STRING(_),Values.STRING(_),Values.INTEGER(_),Values.BOOL(_), Values.BOOL(_), Values.BOOL(_), Values.BOOL(_)},st,_) + then + (cache,Values.STRING(""),st); + + case (cache,_,"getIndexReductionMethod",_,st,_) + equation + str = Config.getIndexReductionMethod(); + then (cache,Values.STRING(str),st); + + case (cache,_,"getAvailableIndexReductionMethods",_,st,_) + equation + (strs1,strs2) = Flags.getConfigOptionsStringList(Flags.INDEX_REDUCTION_METHOD); + v1 = ValuesUtil.makeArray(List.map(strs1, ValuesUtil.makeString)); + v2 = ValuesUtil.makeArray(List.map(strs2, ValuesUtil.makeString)); + v = Values.TUPLE({v1,v2}); + then (cache,v,st); + + case (cache,_,"getMatchingAlgorithm",_,st,_) + equation + str = Config.getMatchingAlgorithm(); + then (cache,Values.STRING(str),st); + + case (cache,_,"getAvailableMatchingAlgorithms",_,st,_) + equation + (strs1,strs2) = Flags.getConfigOptionsStringList(Flags.MATCHING_ALGORITHM); + v1 = ValuesUtil.makeArray(List.map(strs1, ValuesUtil.makeString)); + v2 = ValuesUtil.makeArray(List.map(strs2, ValuesUtil.makeString)); + v = Values.TUPLE({v1,v2}); + then (cache,v,st); + + case (cache,_,"getTearingMethod",_,st,_) + equation + str = Config.getTearingMethod(); + then (cache,Values.STRING(str),st); + + case (cache,_,"getAvailableTearingMethods",_,st,_) + equation + (strs1,strs2) = Flags.getConfigOptionsStringList(Flags.TEARING_METHOD); + v1 = ValuesUtil.makeArray(List.map(strs1, ValuesUtil.makeString)); + v2 = ValuesUtil.makeArray(List.map(strs2, ValuesUtil.makeString)); + v = Values.TUPLE({v1,v2}); + then (cache,v,st); + + case (cache,_,"saveModel",{Values.STRING(filename),Values.CODE(Absyn.C_TYPENAME(classpath))},(st as GlobalScript.SYMBOLTABLE(ast = p)),_) + equation + absynClass = Interactive.getPathedClassInProgram(classpath, p); + str = Dump.unparseStr(Absyn.PROGRAM({absynClass},Absyn.TOP()),true); + System.writeFile(filename, str); + then + (cache,Values.BOOL(true),st); + + case (cache,_,"save",{Values.CODE(Absyn.C_TYPENAME(className))},(st as GlobalScript.SYMBOLTABLE(ast = p)),_) + equation + (newp,filename) = Interactive.getContainedClassAndFile(className, p); + str = Dump.unparseStr(newp,true); + System.writeFile(filename, str); + then + (cache,Values.BOOL(true),st); + + case (cache,_,"save",{Values.CODE(Absyn.C_TYPENAME(_))},st,_) + then (cache,Values.BOOL(false),st); + + case (cache,_,"saveAll",{Values.STRING(filename)},st as GlobalScript.SYMBOLTABLE(ast=p),_) + equation + str = Dump.unparseStr(p,true); + System.writeFile(filename, str); + then + (cache,Values.BOOL(true),st); + + case (cache,_,"saveModel",{Values.STRING(name),Values.CODE(Absyn.C_TYPENAME(classpath))}, + (st as GlobalScript.SYMBOLTABLE(ast = p)),_) + equation + _ = Interactive.getPathedClassInProgram(classpath, p); + Error.addMessage(Error.WRITING_FILE_ERROR, {name}); + then + (cache,Values.BOOL(false),st); + + case (cache,_,"saveModel",{Values.STRING(_),Values.CODE(Absyn.C_TYPENAME(classpath))},st,_) + equation + cname = Absyn.pathString(classpath); + Error.addMessage(Error.LOOKUP_ERROR, {cname,"global"}); + then + (cache,Values.BOOL(false),st); + + case (cache,_,"saveTotalModel",{Values.STRING(filename),Values.CODE(Absyn.C_TYPENAME(classpath))},st,_) + equation + st = saveTotalModel(filename,classpath,st); + then + (cache, Values.BOOL(true), st); + + case (cache,_,"saveTotalModel",{Values.STRING(_),Values.CODE(Absyn.C_TYPENAME(_))},(st as GlobalScript.SYMBOLTABLE()),_) + then (cache, Values.BOOL(false), st); + + case (cache,_,"getDocumentationAnnotation",{Values.CODE(Absyn.C_TYPENAME(classpath))},st as GlobalScript.SYMBOLTABLE(ast=p),_) + equation + ((str1,str2)) = Interactive.getNamedAnnotation(classpath, p, Absyn.IDENT("Documentation"), SOME(("","")),Interactive.getDocumentationAnnotationString); + then + (cache,ValuesUtil.makeArray({Values.STRING(str1),Values.STRING(str2)}),st); + + case (cache,_,"addClassAnnotation",{Values.CODE(Absyn.C_TYPENAME(classpath)),Values.CODE(Absyn.C_EXPRESSION(aexp))},GlobalScript.SYMBOLTABLE(p,_,ic,iv,cf,lf),_) + equation + p = Interactive.addClassAnnotation(Absyn.pathToCref(classpath), Absyn.NAMEDARG("annotate",aexp)::{}, p); + then + (cache,Values.BOOL(true),GlobalScript.SYMBOLTABLE(p,NONE(),ic,iv,cf,lf)); + + case (cache,_,"addClassAnnotation",_,st as GlobalScript.SYMBOLTABLE(),_) + then + (cache,Values.BOOL(false),st); + + case (cache,_,"setDocumentationAnnotation",{Values.CODE(Absyn.C_TYPENAME(classpath)),Values.STRING(str1),Values.STRING(str2)},GlobalScript.SYMBOLTABLE(p,_,ic,iv,cf,lf),_) + equation + nargs = List.consOnTrue(not stringEq(str1,""), Absyn.NAMEDARG("info",Absyn.STRING(str1)), {}); + nargs = List.consOnTrue(not stringEq(str2,""), Absyn.NAMEDARG("revisions",Absyn.STRING(str2)), nargs); + aexp = Absyn.CALL(Absyn.CREF_IDENT("Documentation",{}),Absyn.FUNCTIONARGS({},nargs)); + p = Interactive.addClassAnnotation(Absyn.pathToCref(classpath), Absyn.NAMEDARG("annotate",aexp)::{}, p); + then + (cache,Values.BOOL(true),GlobalScript.SYMBOLTABLE(p,NONE(),ic,iv,cf,lf)); + + case (cache,_,"setDocumentationAnnotation",_,st as GlobalScript.SYMBOLTABLE(),_) + then + (cache,Values.BOOL(false),st); + + case (cache,_,"isType",{Values.CODE(Absyn.C_TYPENAME(classpath))},st as GlobalScript.SYMBOLTABLE(ast=p),_) + equation + b = Interactive.isType(classpath, p); + then + (cache,Values.BOOL(b),st); + + case (cache,_,"isPackage",{Values.CODE(Absyn.C_TYPENAME(classpath))},st as GlobalScript.SYMBOLTABLE(ast=p),_) + equation + b = Interactive.isPackage(classpath, p); + then + (cache,Values.BOOL(b),st); + + case (cache,_,"isClass",{Values.CODE(Absyn.C_TYPENAME(classpath))},st as GlobalScript.SYMBOLTABLE(ast=p),_) + equation + b = Interactive.isClass(classpath, p); + then + (cache,Values.BOOL(b),st); + + case (cache,_,"isRecord",{Values.CODE(Absyn.C_TYPENAME(classpath))},st as GlobalScript.SYMBOLTABLE(ast=p),_) + equation + b = Interactive.isRecord(classpath, p); + then + (cache,Values.BOOL(b),st); + + case (cache,_,"isBlock",{Values.CODE(Absyn.C_TYPENAME(classpath))},st as GlobalScript.SYMBOLTABLE(ast=p),_) + equation + b = Interactive.isBlock(classpath, p); + then + (cache,Values.BOOL(b),st); + + case (cache,_,"isFunction",{Values.CODE(Absyn.C_TYPENAME(classpath))},st as GlobalScript.SYMBOLTABLE(ast=p),_) + equation + b = Interactive.isFunction(classpath, p); + then + (cache,Values.BOOL(b),st); + + case (cache,_,"isPartial",{Values.CODE(Absyn.C_TYPENAME(classpath))},st as GlobalScript.SYMBOLTABLE(ast=p),_) + equation + b = Interactive.isPartial(classpath, p); + then + (cache,Values.BOOL(b),st); + + case (cache,_,"isModel",{Values.CODE(Absyn.C_TYPENAME(classpath))},st as GlobalScript.SYMBOLTABLE(ast=p),_) + equation + b = Interactive.isModel(classpath, p); + then + (cache,Values.BOOL(b),st); + + case (cache,_,"isConnector",{Values.CODE(Absyn.C_TYPENAME(classpath))},st as GlobalScript.SYMBOLTABLE(ast=p),_) + equation + b = Interactive.isConnector(classpath, p); + then + (cache,Values.BOOL(b),st); + + case (cache,_,"isOptimization",{Values.CODE(Absyn.C_TYPENAME(classpath))},st as GlobalScript.SYMBOLTABLE(ast=p),_) + equation + b = Interactive.isOptimization(classpath, p); + then + (cache,Values.BOOL(b),st); + + case (cache,_,"isEnumeration",{Values.CODE(Absyn.C_TYPENAME(classpath))},st as GlobalScript.SYMBOLTABLE(ast=p),_) + equation + b = Interactive.isEnumeration(classpath, p); + then + (cache,Values.BOOL(b),st); + + case (cache,_,"isOperator",{Values.CODE(Absyn.C_TYPENAME(classpath))},st as GlobalScript.SYMBOLTABLE(ast=p),_) + equation + b = Interactive.isOperator(classpath, p); + then + (cache,Values.BOOL(b),st); + + case (cache,_,"isOperatorRecord",{Values.CODE(Absyn.C_TYPENAME(classpath))},st as GlobalScript.SYMBOLTABLE(ast=p),_) + equation + b = Interactive.isOperatorRecord(classpath, p); + then + (cache,Values.BOOL(b),st); + + case (cache,_,"isOperatorFunction",{Values.CODE(Absyn.C_TYPENAME(classpath))},st as GlobalScript.SYMBOLTABLE(ast=p),_) + equation + b = Interactive.isOperatorFunction(classpath, p); + then + (cache,Values.BOOL(b),st); + + case (cache,_,"isProtectedClass",{Values.CODE(Absyn.C_TYPENAME(classpath)), Values.STRING(name)},st as GlobalScript.SYMBOLTABLE(ast=p),_) + equation + b = Interactive.isProtectedClass(classpath, name, p); + then + (cache,Values.BOOL(b),st); + + case (cache,env,"getBuiltinType",{Values.CODE(Absyn.C_TYPENAME(classpath))},st as GlobalScript.SYMBOLTABLE(),_) + equation + (_, tp, _) = Lookup.lookupType(cache, env, classpath, SOME(Absyn.dummyInfo)); + str = Types.unparseType(tp); + then + (cache,Values.STRING(str),st); + + // if the lookup fails + case (cache,_,"getBuiltinType",{Values.CODE(Absyn.C_TYPENAME(_))},st as GlobalScript.SYMBOLTABLE(ast=_),_) + then + (cache,Values.STRING(""),st); + + case (cache,_,"extendsFrom", + {Values.CODE(Absyn.C_TYPENAME(classpath)), + Values.CODE(Absyn.C_TYPENAME(baseClassPath))},st as GlobalScript.SYMBOLTABLE(ast=p),_) + equation + paths = Interactive.getAllInheritedClasses(classpath, p); + b = List.applyAndFold1(paths, boolOr, Absyn.pathSuffixOfr, baseClassPath, false); + then + (cache,Values.BOOL(b),st); + + case (cache,_,"extendsFrom",_,st as GlobalScript.SYMBOLTABLE(),_) + then + (cache,Values.BOOL(false),st); + + case (cache,_,"isExperiment",{Values.CODE(Absyn.C_TYPENAME(classpath))},st as GlobalScript.SYMBOLTABLE(ast=p),_) + equation + b = Interactive.getNamedAnnotation(classpath, p, Absyn.IDENT("experiment"), SOME(false), hasStopTime); + then + (cache,Values.BOOL(b),st); + + case (cache,_,"isExperiment",_,st as GlobalScript.SYMBOLTABLE(),_) + then + (cache,Values.BOOL(false),st); + + case (cache,_,"getComponentsTest",{Values.CODE(Absyn.C_TYPENAME(classpath))},st as GlobalScript.SYMBOLTABLE(ast=p),_) + equation + absynClass = Interactive.getPathedClassInProgram(classpath, p); + (sp, st) = GlobalScriptUtil.symbolTableToSCode(st); + (cache, env) = Inst.makeEnvFromProgram(FCore.emptyCache(), sp, Absyn.IDENT("")); + (cache,(cl as SCode.CLASS(name=name,encapsulatedPrefix=encflag,restriction=restr)),env) = Lookup.lookupClass(cache, env, classpath, false); + env = FGraph.openScope(env, encflag, SOME(name), FGraph.restrictionToScopeType(restr)); + (_, env) = Inst.partialInstClassIn(cache, env, InnerOuter.emptyInstHierarchy, DAE.NOMOD(), Prefix.NOPRE(), + ClassInf.start(restr, FGraph.getGraphName(env)), cl, SCode.PUBLIC(), {}, 0); + valsLst = list(getComponentInfo(c, env, isProtected=false) for c in Interactive.getPublicComponentsInClass(absynClass)); + valsLst = listAppend(list(getComponentInfo(c, env, isProtected=true) for c in Interactive.getProtectedComponentsInClass(absynClass)), valsLst); + then (cache,ValuesUtil.makeArray(List.flatten(valsLst)),st); + + case (cache,_,"getComponentsTest",{Values.CODE(Absyn.C_TYPENAME(_))},st as GlobalScript.SYMBOLTABLE(),_) + then + (cache,Values.ARRAY({},{}),st); + + + case (cache,_,"getSimulationOptions",{Values.CODE(Absyn.C_TYPENAME(classpath)),Values.REAL(startTime),Values.REAL(stopTime),Values.REAL(tolerance),Values.INTEGER(numberOfIntervals),Values.REAL(interval)},st as GlobalScript.SYMBOLTABLE(),_) + equation + cr_1 = Absyn.pathToCref(classpath); + // ignore the name of the model + ErrorExt.setCheckpoint("getSimulationOptions"); + simOpt = GlobalScript.SIMULATION_OPTIONS(DAE.RCONST(startTime),DAE.RCONST(stopTime),DAE.ICONST(numberOfIntervals),DAE.RCONST(0.0),DAE.RCONST(tolerance),DAE.SCONST(""),DAE.SCONST(""),DAE.SCONST(""),DAE.SCONST(""),DAE.SCONST(""),DAE.SCONST(""),DAE.SCONST("")); + ErrorExt.rollBack("getSimulationOptions"); + (_, _::startTimeExp::stopTimeExp::intervalExp::toleranceExp::_) = StaticScript.getSimulationArguments(FCore.emptyCache(), FGraph.empty(), {Absyn.CREF(cr_1)},{},false,SOME(st),Prefix.NOPRE(),Absyn.dummyInfo,SOME(simOpt)); + startTime = ValuesUtil.valueReal(Util.makeValueOrDefault(Ceval.cevalSimple,startTimeExp,Values.REAL(startTime))); + stopTime = ValuesUtil.valueReal(Util.makeValueOrDefault(Ceval.cevalSimple,stopTimeExp,Values.REAL(stopTime))); + tolerance = ValuesUtil.valueReal(Util.makeValueOrDefault(Ceval.cevalSimple,toleranceExp,Values.REAL(tolerance))); + Values.INTEGER(numberOfIntervals) = Util.makeValueOrDefault(Ceval.cevalSimple,intervalExp,Values.INTEGER(numberOfIntervals)); // number of intervals + if numberOfIntervals == 0 then + numberOfIntervals = if interval > 0.0 then integer(ceil((stopTime - startTime)/interval)) else 0; + else + interval = (stopTime-startTime) / max(numberOfIntervals,1); + end if; + then + (cache,Values.TUPLE({Values.REAL(startTime),Values.REAL(stopTime),Values.REAL(tolerance),Values.INTEGER(numberOfIntervals),Values.REAL(interval)}),st); + + case (cache,_,"searchClassNames",{Values.STRING(str), Values.BOOL(b)},st as GlobalScript.SYMBOLTABLE(ast=p),_) + equation + (_,paths) = Interactive.getClassNamesRecursive(NONE(),p,false,{}); + paths = listReverse(paths); + vals = List.map(paths,ValuesUtil.makeCodeTypeName); + vals = searchClassNames(vals, str, b, p); + then + (cache,ValuesUtil.makeArray(vals),st); + + case (cache,_,"getAvailableLibraries",{},st,_) + equation + mp = Settings.getModelicaPath(Config.getRunningTestsuite()); + gd = System.groupDelimiter(); + mps = System.strtok(mp, gd); + files = List.flatten(List.map(mps, System.moFiles)); + dirs = List.flatten(List.map(mps, System.subDirectories)); + files = List.map(List.map1(listAppend(files,dirs), System.strtok, ". "), listHead); + (str, status) = System.popen("impact search '' | perl -pe 's/\\e\\[?.*?[\\@-~]//g' | grep '[^ :]*:' | cut -d: -f1 2>&1"); + if 0==status then + files = listAppend(files, System.strtok(str,"\n")); + end if; + files = List.sort(files,Util.strcmpBool); + files = List.sortedUnique(files, stringEqual); + v = ValuesUtil.makeArray(List.map(files, ValuesUtil.makeString)); + then + (cache,v,st); + + case (cache,_,"getUses",{Values.CODE(Absyn.C_TYPENAME(classpath))},st as GlobalScript.SYMBOLTABLE(ast=p),_) + equation + (absynClass as Absyn.CLASS()) = Interactive.getPathedClassInProgram(classpath, p); + uses = Interactive.getUsesAnnotation(Absyn.PROGRAM({absynClass},Absyn.TOP())); + v = ValuesUtil.makeArray(List.map(uses,makeUsesArray)); + then + (cache,v,st); + + case (cache,_,"getDerivedClassModifierNames",{Values.CODE(Absyn.C_TYPENAME(classpath))},st as GlobalScript.SYMBOLTABLE(ast=p),_) + equation + absynClass = Interactive.getPathedClassInProgram(classpath, p); + args = Interactive.getDerivedClassModifierNames(absynClass); + vals = List.map(args, ValuesUtil.makeString); + v = ValuesUtil.makeArray(vals); + then + (cache,v,st); + + case (cache,_,"getDerivedClassModifierValue",{Values.CODE(Absyn.C_TYPENAME(classpath)), Values.CODE(Absyn.C_TYPENAME(className))},st as GlobalScript.SYMBOLTABLE(ast=p),_) + equation + absynClass = Interactive.getPathedClassInProgram(classpath, p); + str = Interactive.getDerivedClassModifierValue(absynClass, className); + then + (cache,Values.STRING(str),st); + + case (cache,_,"getAstAsCorbaString",{Values.STRING("")},st as GlobalScript.SYMBOLTABLE(ast=p),_) + equation + Print.clearBuf(); + Dump.getAstAsCorbaString(p); + res = Print.getString(); + Print.clearBuf(); + then + (cache,Values.STRING(res),st); + + case (cache,_,"getAstAsCorbaString",{Values.STRING(str)},st as GlobalScript.SYMBOLTABLE(ast=p),_) + equation + Print.clearBuf(); + Dump.getAstAsCorbaString(p); + Print.writeBuf(str); + Print.clearBuf(); + str = "Wrote result to file: " + str; + then + (cache,Values.STRING(str),st); + + case (cache,_,"getAstAsCorbaString",_,st,_) + equation + Error.addMessage(Error.INTERNAL_ERROR,{"getAstAsCorbaString failed"}); + then (cache,Values.STRING(""),st); + + case (cache,_,"readSimulationResult",{Values.STRING(filename),Values.ARRAY(valueLst=cvars),Values.INTEGER(size)},st,_) + equation + vars_1 = List.map(cvars, ValuesUtil.printCodeVariableName); + filename_1 = Util.absoluteOrRelative(filename); + value = SimulationResults.readDataset(filename_1, vars_1, size); + then + (cache,value,st); + + case (cache,_,"readSimulationResult",_,st,_) + equation + Error.addMessage(Error.SCRIPT_READ_SIM_RES_ERROR, {}); + then (cache,Values.META_FAIL(),st); + + case (cache,_,"readSimulationResultSize",{Values.STRING(filename)},st,_) + equation + filename_1 = Util.absoluteOrRelative(filename); + i = SimulationResults.readSimulationResultSize(filename_1); + then + (cache,Values.INTEGER(i),st); + + case (cache,_,"readSimulationResultVars",{Values.STRING(filename),Values.BOOL(b1),Values.BOOL(b2)},st,_) + equation + filename_1 = Util.absoluteOrRelative(filename); + args = SimulationResults.readVariables(filename_1, b1, b2); + vals = List.map(args, ValuesUtil.makeString); + v = ValuesUtil.makeArray(vals); + then + (cache,v,st); + + case (cache,_,"compareSimulationResults",{Values.STRING(filename),Values.STRING(filename_1),Values.STRING(filename2),Values.REAL(x1),Values.REAL(x2),Values.ARRAY(valueLst=cvars)},st,_) + equation + filename = Util.absoluteOrRelative(filename); + filename_1 = Util.testsuiteFriendlyPath(filename_1); + filename_1 = Util.absoluteOrRelative(filename_1); + filename2 = Util.absoluteOrRelative(filename2); + vars_1 = List.map(cvars, ValuesUtil.extractValueString); + strings = SimulationResults.cmpSimulationResults(Config.getRunningTestsuite(),filename,filename_1,filename2,x1,x2,vars_1); + cvars = List.map(strings,ValuesUtil.makeString); + v = ValuesUtil.makeArray(cvars); + then + (cache,v,st); + + case (cache,_,"compareSimulationResults",_,st,_) + then (cache,Values.STRING("Error in compareSimulationResults"),st); + + case (cache,_,"filterSimulationResults",{Values.STRING(filename),Values.STRING(filename_1),Values.ARRAY(valueLst=cvars),Values.INTEGER(numberOfIntervals)},st,_) + equation + vars_1 = List.map(cvars, ValuesUtil.extractValueString); + b = SimulationResults.filterSimulationResults(filename,filename_1,vars_1,numberOfIntervals); + then + (cache,Values.BOOL(b),st); + + case (cache,_,"filterSimulationResults",_,st,_) + then (cache,Values.BOOL(false),st); + + case (cache,_,"diffSimulationResults",{Values.STRING(filename),Values.STRING(filename_1),Values.STRING(filename2),Values.REAL(reltol),Values.REAL(reltolDiffMinMax),Values.REAL(rangeDelta),Values.ARRAY(valueLst=cvars),Values.BOOL(b)},st,_) + equation + pwd = System.pwd(); + pd = System.pathDelimiter(); + filename = Util.absoluteOrRelative(filename); + filename_1 = Util.testsuiteFriendlyPath(filename_1); + filename_1 = Util.absoluteOrRelative(filename_1); + filename2 = Util.absoluteOrRelative(filename2); + vars_1 = List.map(cvars, ValuesUtil.extractValueString); + (b,strings) = SimulationResults.diffSimulationResults(Config.getRunningTestsuite(),filename,filename_1,filename2,reltol,reltolDiffMinMax,rangeDelta,vars_1,b); + cvars = List.map(strings,ValuesUtil.makeString); + v1 = ValuesUtil.makeArray(cvars); + then + (cache,Values.TUPLE({Values.BOOL(b),v1}),st); + + case (cache,_,"diffSimulationResults",_,st,_) + equation + v = ValuesUtil.makeArray({}); + then (cache,Values.TUPLE({Values.BOOL(false),v}),st); + + case (cache,_,"diffSimulationResultsHtml",{Values.STRING(str),Values.STRING(filename),Values.STRING(filename_1),Values.REAL(reltol),Values.REAL(reltolDiffMinMax),Values.REAL(rangeDelta)},st,_) + equation + filename = Util.absoluteOrRelative(filename); + filename_1 = Util.testsuiteFriendlyPath(filename_1); + filename_1 = Util.absoluteOrRelative(filename_1); + str = SimulationResults.diffSimulationResultsHtml(Config.getRunningTestsuite(),filename,filename_1,reltol,reltolDiffMinMax,rangeDelta,str); + then + (cache,Values.STRING(str),st); + + case (cache,_,"diffSimulationResultsHtml",_,st,_) + then (cache,Values.STRING(""),st); + + case (cache,_,"checkTaskGraph",{Values.STRING(filename),Values.STRING(filename_1)},st,_) + equation + pwd = System.pwd(); + pd = System.pathDelimiter(); + filename = if System.substring(filename,1,1) == "/" then filename else stringAppendList({pwd,pd,filename}); + filename_1 = if System.substring(filename_1,1,1) == "/" then filename_1 else stringAppendList({pwd,pd,filename_1}); + strings = TaskGraphResults.checkTaskGraph(filename, filename_1); + cvars = List.map(strings,ValuesUtil.makeString); + v = ValuesUtil.makeArray(cvars); + then (cache,v,st); + + case (cache,_,"checkTaskGraph",_,st,_) + then (cache,Values.STRING("Error in checkTaskGraph"),st); + + case (cache,_,"checkCodeGraph",{Values.STRING(filename),Values.STRING(filename_1)},st,_) + equation + pwd = System.pwd(); + pd = System.pathDelimiter(); + filename = if System.substring(filename,1,1) == "/" then filename else stringAppendList({pwd,pd,filename}); + filename_1 = if System.substring(filename_1,1,1) == "/" then filename_1 else stringAppendList({pwd,pd,filename_1}); + strings = TaskGraphResults.checkCodeGraph(filename, filename_1); + cvars = List.map(strings,ValuesUtil.makeString); + v = ValuesUtil.makeArray(cvars); + then (cache,v,st); + + case (cache,_,"checkCodeGraph",_,st,_) + then (cache,Values.STRING("Error in checkCodeGraph"),st); + + //plotAll(model) + case (cache,env,"plotAll", + { + Values.BOOL(externalWindow), + Values.STRING(filename), + Values.STRING(title), + Values.STRING(gridStr), + Values.BOOL(logX), + Values.BOOL(logY), + Values.STRING(xLabel), + Values.STRING(yLabel), + Values.ARRAY(valueLst={Values.REAL(x1),Values.REAL(x2)}), + Values.ARRAY(valueLst={Values.REAL(y1),Values.REAL(y2)}), + Values.REAL(curveWidth), + Values.INTEGER(curveStyle), + Values.STRING(legendPosition), + Values.STRING(footer), + Values.BOOL(autoScale), + Values.BOOL(forceOMPlot) + }, + st, + _) + equation + // get OPENMODELICAHOME + omhome = Settings.getInstallationDirectoryPath(); + // get the simulation filename + (cache,filename) = cevalCurrentSimulationResultExp(cache,env,filename,st,msg); + pd = System.pathDelimiter(); + // create absolute path of simulation result file + str1 = System.pwd() + pd + filename; + s1 = if System.os() == "Windows_NT" then ".exe" else ""; + filename = if System.regularFileExists(str1) then str1 else filename; + // check if plot callback is defined + b = System.plotCallBackDefined(); + if boolOr(forceOMPlot, boolNot(b)) then + // create the path till OMPlot + str2 = stringAppendList({omhome,pd,"bin",pd,"OMPlot",s1}); + // create the list of arguments for OMPlot + str3 = "--filename=\"" + filename + "\" --title=\"" + title + "\" --grid=" + gridStr + " --plotAll --logx=" + boolString(logX) + " --logy=" + boolString(logY) + " --xlabel=\"" + xLabel + "\" --ylabel=\"" + yLabel + "\" --xrange=" + realString(x1) + ":" + realString(x2) + " --yrange=" + realString(y1) + ":" + realString(y2) + " --new-window=" + boolString(externalWindow) + " --curve-width=" + realString(curveWidth) + " --curve-style=" + intString(curveStyle) + " --legend-position=\"" + legendPosition + "\" --footer=\"" + footer + "\" --auto-scale=" + boolString(autoScale); + call = stringAppendList({"\"",str2,"\""," ",str3}); + 0 = System.spawnCall(str2, call); + elseif b then + logXStr = boolString(logX); + logYStr = boolString(logY); + x1Str = realString(x1); + x2Str = realString(x2); + y1Str = realString(y1); + y2Str = realString(y2); + curveWidthStr = realString(curveWidth); + curveStyleStr = intString(curveStyle); + autoScaleStr = boolString(autoScale); + System.plotCallBack(externalWindow,filename,title,gridStr,"plotall",logXStr,logYStr,xLabel,yLabel,x1Str,x2Str,y1Str,y2Str,curveWidthStr,curveStyleStr,legendPosition,footer,autoScaleStr,""); + end if; + then + (cache,Values.BOOL(true),st); + + case (cache,_,"plotAll",_,st,_) + then (cache,Values.BOOL(false),st); + + // plot(x, model) + case (cache,env,"plot", + { + Values.ARRAY(valueLst = cvars), + Values.BOOL(externalWindow), + Values.STRING(filename), + Values.STRING(title), + Values.STRING(gridStr), + Values.BOOL(logX), + Values.BOOL(logY), + Values.STRING(xLabel), + Values.STRING(yLabel), + Values.ARRAY(valueLst={Values.REAL(x1),Values.REAL(x2)}), + Values.ARRAY(valueLst={Values.REAL(y1),Values.REAL(y2)}), + Values.REAL(curveWidth), + Values.INTEGER(curveStyle), + Values.STRING(legendPosition), + Values.STRING(footer), + Values.BOOL(autoScale), + Values.BOOL(forceOMPlot) + }, + st,_) + equation + // get the variables list + vars_1 = List.map(cvars, ValuesUtil.printCodeVariableName); + // get OPENMODELICAHOME + omhome = Settings.getInstallationDirectoryPath(); + // get the simulation filename + (cache,filename) = cevalCurrentSimulationResultExp(cache,env,filename,st,msg); + pd = System.pathDelimiter(); + // create absolute path of simulation result file + str1 = System.pwd() + pd + filename; + s1 = if System.os() == "Windows_NT" then ".exe" else ""; + filename = if System.regularFileExists(str1) then str1 else filename; + // check if plot callback is defined + b = System.plotCallBackDefined(); + if boolOr(forceOMPlot, boolNot(b)) then + // seperate the variables + str = stringDelimitList(vars_1,"\" \""); + // create the path till OMPlot + str2 = stringAppendList({omhome,pd,"bin",pd,"OMPlot",s1}); + // create the list of arguments for OMPlot + str3 = "--filename=\"" + filename + "\" --title=\"" + title + "\" --grid=" + gridStr + " --plot --logx=" + boolString(logX) + " --logy=" + boolString(logY) + " --xlabel=\"" + xLabel + "\" --ylabel=\"" + yLabel + "\" --xrange=" + realString(x1) + ":" + realString(x2) + " --yrange=" + realString(y1) + ":" + realString(y2) + " --new-window=" + boolString(externalWindow) + " --curve-width=" + realString(curveWidth) + " --curve-style=" + intString(curveStyle) + " --legend-position=\"" + legendPosition + "\" --footer=\"" + footer + "\" --auto-scale=" + boolString(autoScale) + " \"" + str + "\""; + call = stringAppendList({"\"",str2,"\""," ",str3}); + 0 = System.spawnCall(str2, call); + elseif b then + logXStr = boolString(logX); + logYStr = boolString(logY); + x1Str = realString(x1); + x2Str = realString(x2); + y1Str = realString(y1); + y2Str = realString(y2); + curveWidthStr = realString(curveWidth); + curveStyleStr = intString(curveStyle); + autoScaleStr = boolString(autoScale); + // seperate the variables + str = stringDelimitList(vars_1, " "); + System.plotCallBack(externalWindow,filename,title,gridStr,"plot",logXStr,logYStr,xLabel,yLabel,x1Str,x2Str,y1Str,y2Str,curveWidthStr,curveStyleStr,legendPosition,footer,autoScaleStr,str); + end if; + then + (cache,Values.BOOL(true),st); + + case (cache,_,"plot",_,st,_) + then + (cache,Values.BOOL(false),st); + + case (cache,env,"val",{cvar,Values.REAL(timeStamp),Values.STRING("")},st,_) + equation + (cache,Values.STRING(filename),_) = Ceval.ceval(cache,env,buildCurrentSimulationResultExp(), true, SOME(st),msg, 0); + varNameStr = ValuesUtil.printCodeVariableName(cvar); + val = SimulationResults.val(filename,varNameStr,timeStamp); + then (cache,Values.REAL(val),st); + + case (cache,_,"val",{cvar,Values.REAL(timeStamp),Values.STRING(filename)},st,_) + equation + false = stringEq(filename,""); + varNameStr = ValuesUtil.printCodeVariableName(cvar); + val = SimulationResults.val(filename,varNameStr,timeStamp); + then (cache,Values.REAL(val),st); + + case (cache,_,"closeSimulationResultFile",_,st,_) + equation + SimulationResults.close(); + then + (cache,Values.BOOL(true),st); + + case (cache,_,"getParameterNames",{Values.CODE(Absyn.C_TYPENAME(path))},(st as GlobalScript.SYMBOLTABLE(ast = p)),_) + equation + strings = Interactive.getParameterNames(path, p); + vals = List.map(strings, ValuesUtil.makeString); + v = ValuesUtil.makeArray(vals); + then + (cache,v,st); + + case (cache,_,"getParameterValue",{Values.CODE(Absyn.C_TYPENAME(path)),Values.STRING(str1)},(st as GlobalScript.SYMBOLTABLE(ast = p)),_) + equation + str2 = Interactive.getComponentBinding(path, str1, p); + then + (cache,Values.STRING(str2),st); + + case (cache,_,"getComponentModifierNames",{Values.CODE(Absyn.C_TYPENAME(path)),Values.STRING(str1)},(st as GlobalScript.SYMBOLTABLE(ast = p)),_) + equation + strings = Interactive.getComponentModifierNames(path, str1, p); + vals = List.map(strings, ValuesUtil.makeString); + v = ValuesUtil.makeArray(vals); + then + (cache,v,st); + + case (cache,_,"getAlgorithmCount",{Values.CODE(Absyn.C_TYPENAME(path))},(st as GlobalScript.SYMBOLTABLE(ast = p)),_) + equation + absynClass = Interactive.getPathedClassInProgram(path, p); + n = listLength(getAlgorithms(absynClass)); + then + (cache,Values.INTEGER(n),st); + + case (cache,_,"getAlgorithmCount",_,st,_) then (cache,Values.INTEGER(0),st); + + case (cache,_,"getNthAlgorithm",{Values.CODE(Absyn.C_TYPENAME(path)),Values.INTEGER(n)},(st as GlobalScript.SYMBOLTABLE(ast = p)),_) + equation + absynClass = Interactive.getPathedClassInProgram(path, p); + str = getNthAlgorithm(absynClass, n); + then + (cache,Values.STRING(str),st); + + case (cache,_,"getNthAlgorithm",_,st,_) then (cache,Values.STRING(""),st); + + case (cache,_,"getInitialAlgorithmCount",{Values.CODE(Absyn.C_TYPENAME(path))},(st as GlobalScript.SYMBOLTABLE(ast = p)),_) + equation + absynClass = Interactive.getPathedClassInProgram(path, p); + n = listLength(getInitialAlgorithms(absynClass)); + then + (cache,Values.INTEGER(n),st); + + case (cache,_,"getInitialAlgorithmCount",_,st,_) then (cache,Values.INTEGER(0),st); + + case (cache,_,"getNthInitialAlgorithm",{Values.CODE(Absyn.C_TYPENAME(path)),Values.INTEGER(n)},(st as GlobalScript.SYMBOLTABLE(ast = p)),_) + equation + absynClass = Interactive.getPathedClassInProgram(path, p); + str = getNthInitialAlgorithm(absynClass, n); + then + (cache,Values.STRING(str),st); + + case (cache,_,"getNthInitialAlgorithm",_,st,_) then (cache,Values.STRING(""),st); + + case (cache,_,"getAlgorithmItemsCount",{Values.CODE(Absyn.C_TYPENAME(path))},(st as GlobalScript.SYMBOLTABLE(ast = p)),_) + equation + absynClass = Interactive.getPathedClassInProgram(path, p); + n = getAlgorithmItemsCount(absynClass); + then + (cache,Values.INTEGER(n),st); + + case (cache,_,"getAlgorithmItemsCount",_,st,_) then (cache,Values.INTEGER(0),st); + + case (cache,_,"getNthAlgorithmItem",{Values.CODE(Absyn.C_TYPENAME(path)),Values.INTEGER(n)},(st as GlobalScript.SYMBOLTABLE(ast = p)),_) + equation + absynClass = Interactive.getPathedClassInProgram(path, p); + str = getNthAlgorithmItem(absynClass, n); + then + (cache,Values.STRING(str),st); + + case (cache,_,"getNthAlgorithmItem",_,st,_) then (cache,Values.STRING(""),st); + + case (cache,_,"getInitialAlgorithmItemsCount",{Values.CODE(Absyn.C_TYPENAME(path))},(st as GlobalScript.SYMBOLTABLE(ast = p)),_) + equation + absynClass = Interactive.getPathedClassInProgram(path, p); + n = getInitialAlgorithmItemsCount(absynClass); + then + (cache,Values.INTEGER(n),st); + + case (cache,_,"getInitialAlgorithmItemsCount",_,st,_) then (cache,Values.INTEGER(0),st); + + case (cache,_,"getNthInitialAlgorithmItem",{Values.CODE(Absyn.C_TYPENAME(path)),Values.INTEGER(n)},(st as GlobalScript.SYMBOLTABLE(ast = p)),_) + equation + absynClass = Interactive.getPathedClassInProgram(path, p); + str = getNthInitialAlgorithmItem(absynClass, n); + then + (cache,Values.STRING(str),st); + + case (cache,_,"getNthInitialAlgorithmItem",_,st,_) then (cache,Values.STRING(""),st); + + case (cache,_,"getEquationCount",{Values.CODE(Absyn.C_TYPENAME(path))},(st as GlobalScript.SYMBOLTABLE(ast = p)),_) + equation + absynClass = Interactive.getPathedClassInProgram(path, p); + n = listLength(getEquations(absynClass)); + then + (cache,Values.INTEGER(n),st); + + case (cache,_,"getEquationCount",_,st,_) then (cache,Values.INTEGER(0),st); + + case (cache,_,"getNthEquation",{Values.CODE(Absyn.C_TYPENAME(path)),Values.INTEGER(n)},(st as GlobalScript.SYMBOLTABLE(ast = p)),_) + equation + absynClass = Interactive.getPathedClassInProgram(path, p); + str = getNthEquation(absynClass, n); + then + (cache,Values.STRING(str),st); + + case (cache,_,"getNthEquation",_,st,_) then (cache,Values.STRING(""),st); + + case (cache,_,"getInitialEquationCount",{Values.CODE(Absyn.C_TYPENAME(path))},(st as GlobalScript.SYMBOLTABLE(ast = p)),_) + equation + absynClass = Interactive.getPathedClassInProgram(path, p); + n = listLength(getInitialEquations(absynClass)); + then + (cache,Values.INTEGER(n),st); + + case (cache,_,"getInitialEquationCount",_,st,_) then (cache,Values.INTEGER(0),st); + + case (cache,_,"getNthInitialEquation",{Values.CODE(Absyn.C_TYPENAME(path)),Values.INTEGER(n)},(st as GlobalScript.SYMBOLTABLE(ast = p)),_) + equation + absynClass = Interactive.getPathedClassInProgram(path, p); + str = getNthInitialEquation(absynClass, n); + then + (cache,Values.STRING(str),st); + + case (cache,_,"getNthInitialEquation",_,st,_) then (cache,Values.STRING(""),st); + + case (cache,_,"getEquationItemsCount",{Values.CODE(Absyn.C_TYPENAME(path))},(st as GlobalScript.SYMBOLTABLE(ast = p)),_) + equation + absynClass = Interactive.getPathedClassInProgram(path, p); + n = getEquationItemsCount(absynClass); + then + (cache,Values.INTEGER(n),st); + + case (cache,_,"getEquationItemsCount",_,st,_) then (cache,Values.INTEGER(0),st); + + case (cache,_,"getNthEquationItem",{Values.CODE(Absyn.C_TYPENAME(path)),Values.INTEGER(n)},(st as GlobalScript.SYMBOLTABLE(ast = p)),_) + equation + absynClass = Interactive.getPathedClassInProgram(path, p); + str = getNthEquationItem(absynClass, n); + then + (cache,Values.STRING(str),st); + + case (cache,_,"getNthEquationItem",_,st,_) then (cache,Values.STRING(""),st); + + case (cache,_,"getInitialEquationItemsCount",{Values.CODE(Absyn.C_TYPENAME(path))},(st as GlobalScript.SYMBOLTABLE(ast = p)),_) + equation + absynClass = Interactive.getPathedClassInProgram(path, p); + n = getInitialEquationItemsCount(absynClass); + then + (cache,Values.INTEGER(n),st); + + case (cache,_,"getInitialEquationItemsCount",_,st,_) then (cache,Values.INTEGER(0),st); + + case (cache,_,"getNthInitialEquationItem",{Values.CODE(Absyn.C_TYPENAME(path)),Values.INTEGER(n)},(st as GlobalScript.SYMBOLTABLE(ast = p)),_) + equation + absynClass = Interactive.getPathedClassInProgram(path, p); + str = getNthInitialEquationItem(absynClass, n); + then + (cache,Values.STRING(str),st); + + case (cache,_,"getNthInitialEquationItem",_,st,_) then (cache,Values.STRING(""),st); + + case (cache,_,"getAnnotationCount",{Values.CODE(Absyn.C_TYPENAME(path))},(st as GlobalScript.SYMBOLTABLE(ast = p)),_) + equation + absynClass = Interactive.getPathedClassInProgram(path, p); + n = getAnnotationCount(absynClass); + then + (cache,Values.INTEGER(n),st); + + case (cache,_,"getAnnotationCount",_,st,_) then (cache,Values.INTEGER(0),st); + + case (cache,_,"getNthAnnotationString",{Values.CODE(Absyn.C_TYPENAME(path)),Values.INTEGER(n)},(st as GlobalScript.SYMBOLTABLE(ast = p)),_) + equation + absynClass = Interactive.getPathedClassInProgram(path, p); + str = getNthAnnotationString(absynClass, n); + then + (cache,Values.STRING(str),st); + + case (cache,_,"getNthAnnotationString",_,st,_) then (cache,Values.STRING(""),st); + + case (cache,_,"getImportCount",{Values.CODE(Absyn.C_TYPENAME(path))},(st as GlobalScript.SYMBOLTABLE(ast = p)),_) + equation + absynClass = Interactive.getPathedClassInProgram(path, p); + n = getImportCount(absynClass); + then + (cache,Values.INTEGER(n),st); + + case (cache,_,"getImportCount",_,st,_) then (cache,Values.INTEGER(0),st); + + case (cache,_,"getNthImport",{Values.CODE(Absyn.C_TYPENAME(path)),Values.INTEGER(n)},(st as GlobalScript.SYMBOLTABLE(ast = p)),_) + equation + absynClass = Interactive.getPathedClassInProgram(path, p); + vals = getNthImport(absynClass, n); + then + (cache,ValuesUtil.makeArray(vals),st); + + case (cache,_,"getNthImport",_,st,_) then (cache,ValuesUtil.makeArray({}),st); + + // plotParametric + case (cache,env,"plotParametric", + { + cvar, + cvar2, + Values.BOOL(externalWindow), + Values.STRING(filename), + Values.STRING(title), + Values.STRING(gridStr), + Values.BOOL(logX), + Values.BOOL(logY), + Values.STRING(xLabel), + Values.STRING(yLabel), + Values.ARRAY(valueLst={Values.REAL(x1),Values.REAL(x2)}), + Values.ARRAY(valueLst={Values.REAL(y1),Values.REAL(y2)}), + Values.REAL(curveWidth), + Values.INTEGER(curveStyle), + Values.STRING(legendPosition), + Values.STRING(footer), + Values.BOOL(autoScale), + Values.BOOL(forceOMPlot) + }, + st,_) + equation + // get the variables + str = ValuesUtil.printCodeVariableName(cvar) + "\" \"" + ValuesUtil.printCodeVariableName(cvar2); + // get OPENMODELICAHOME + omhome = Settings.getInstallationDirectoryPath(); + // get the simulation filename + (cache,filename) = cevalCurrentSimulationResultExp(cache,env,filename,st,msg); + pd = System.pathDelimiter(); + // create absolute path of simulation result file + str1 = System.pwd() + pd + filename; + s1 = if System.os() == "Windows_NT" then ".exe" else ""; + filename = if System.regularFileExists(str1) then str1 else filename; + // check if plot callback is defined + b = System.plotCallBackDefined(); + if boolOr(forceOMPlot, boolNot(b)) then + // create the path till OMPlot + str2 = stringAppendList({omhome,pd,"bin",pd,"OMPlot",s1}); + // create the list of arguments for OMPlot + str3 = "--filename=\"" + filename + "\" --title=\"" + title + "\" --grid=" + gridStr + " --plotParametric --logx=" + boolString(logX) + " --logy=" + boolString(logY) + " --xlabel=\"" + xLabel + "\" --ylabel=\"" + yLabel + "\" --xrange=" + realString(x1) + ":" + realString(x2) + " --yrange=" + realString(y1) + ":" + realString(y2) + " --new-window=" + boolString(externalWindow) + " --curve-width=" + realString(curveWidth) + " --curve-style=" + intString(curveStyle) + " --legend-position=\"" + legendPosition + "\" --footer=\"" + footer + "\" --auto-scale=" + boolString(autoScale) + " \"" + str + "\""; + call = stringAppendList({"\"",str2,"\""," ",str3}); + 0 = System.spawnCall(str2, call); + elseif b then + logXStr = boolString(logX); + logYStr = boolString(logY); + x1Str = realString(x1); + x2Str = realString(x2); + y1Str = realString(y1); + y2Str = realString(y2); + curveWidthStr = realString(curveWidth); + curveStyleStr = intString(curveStyle); + autoScaleStr = boolString(autoScale); + System.plotCallBack(externalWindow,filename,title,gridStr,"plotparametric",logXStr,logYStr,xLabel,yLabel,x1Str,x2Str,y1Str,y2Str,curveWidthStr,curveStyleStr,legendPosition,footer,autoScaleStr,str); + end if; + then + (cache,Values.BOOL(true),st); + + case (cache,_,"plotParametric",_,st,_) + then (cache,Values.BOOL(false),st); + + case (cache,env,"dumpXMLDAE",vals,st,_) + equation + (cache,st,xml_filename) = dumpXMLDAE(cache,env,vals,st, msg); + then + (cache,ValuesUtil.makeTuple({Values.BOOL(true),Values.STRING(xml_filename)}),st); + + case (cache,_,"dumpXMLDAE",_,st,_) + then + (cache,ValuesUtil.makeTuple({Values.BOOL(false),Values.STRING("")}),st); + + case (cache,_,"solveLinearSystem",{Values.ARRAY(valueLst=vals),v,Values.ENUM_LITERAL(index=1 /*dgesv*/),Values.ARRAY(valueLst={Values.INTEGER(-1)})},st,_) + equation + (realVals,i) = System.dgesv(List.map(vals,ValuesUtil.arrayValueReals),ValuesUtil.arrayValueReals(v)); + v = ValuesUtil.makeArray(List.map(realVals,ValuesUtil.makeReal)); + then (cache,Values.TUPLE({v,Values.INTEGER(i)}),st); + + case (cache,_,"solveLinearSystem",{Values.ARRAY(valueLst=vals),v,Values.ENUM_LITERAL(index=2 /*lpsolve55*/),Values.ARRAY(valueLst=vals2)},st,_) + equation + (realVals,i) = System.lpsolve55(List.map(vals,ValuesUtil.arrayValueReals),ValuesUtil.arrayValueReals(v),List.map(vals2,ValuesUtil.valueInteger)); + v = ValuesUtil.makeArray(List.map(realVals,ValuesUtil.makeReal)); + then (cache,Values.TUPLE({v,Values.INTEGER(i)}),st); + + case (cache,_,"solveLinearSystem",{_,v,_,_},st,_) + equation + Error.addMessage(Error.INTERNAL_ERROR,{"Unknown input to solveLinearSystem scripting function"}); + then (cache,Values.TUPLE({v,Values.INTEGER(-1)}),st); + + end matchcontinue; +end cevalInteractiveFunctions3; + + +protected function getSimulationExtension +input String inString; +input String inString2; +output String outString; +algorithm + outString:=match(inString,inString2) + local + case ("Cpp","WIN32") + then ".bat"; + case ("Cpp","WIN64") + then ".bat"; + else System.getExeExt(); + end match; + end getSimulationExtension; + + +protected function sconstToString +"@author: adrpo + Transform an DAE.SCONST into a string. + Fails if the given DAE.Exp is not a DAE.SCONST." + input DAE.Exp exp; + output String str; +algorithm + DAE.SCONST(str) := exp; +end sconstToString; + +public function getIncidenceMatrix " author: adrpo + translates a model and returns the incidence matrix" + input FCore.Cache inCache; + input FCore.Graph inEnv; + input Absyn.Path className "path for the model"; + input GlobalScript.SymbolTable inInteractiveSymbolTable; + input Absyn.Msg inMsg; + input String filenameprefix; + output FCore.Cache outCache; + output Values.Value outValue; + output GlobalScript.SymbolTable outInteractiveSymbolTable; + output String outString; +algorithm + (outCache,outValue,outInteractiveSymbolTable,outString):= + match (inCache,inEnv,className,inInteractiveSymbolTable,inMsg,filenameprefix) + local + String filename,file_dir, str; + list p_1; + DAE.DAElist dae_1,dae; + FCore.Graph env; + list ic_1,ic; + BackendDAE.BackendDAE dlow; + Absyn.ComponentRef a_cref; + GlobalScript.SymbolTable st; + Absyn.Program p; + list iv; + list cf; + Absyn.Msg msg; + FCore.Cache cache; + String flatModelicaStr,description; + + case (cache,env,_,(st as GlobalScript.SYMBOLTABLE(ast = p,instClsLst = ic)),_,_) /* mo file directory */ + equation + p_1 = SCodeUtil.translateAbsyn2SCode(p); + (cache,env,_,dae_1) = + Inst.instantiateClass(cache,InnerOuter.emptyInstHierarchy,p_1,className); + dae = DAEUtil.transformationsBeforeBackend(cache,env,dae_1); + description = DAEUtil.daeDescription(dae); + _ = Interactive.addInstantiatedClass(ic, GlobalScript.INSTCLASS(className,dae,env)); + a_cref = Absyn.pathToCref(className); + file_dir = getFileDir(a_cref, p); + dlow = BackendDAECreate.lower(dae,cache,env,BackendDAE.EXTRA_INFO(description,filenameprefix)); + dlow = FindZeroCrossings.findZeroCrossings(dlow); + flatModelicaStr = DAEDump.dumpStr(dae,FCore.getFunctionTree(cache)); + flatModelicaStr = stringAppend("OldEqStr={'", flatModelicaStr); + flatModelicaStr = System.stringReplace(flatModelicaStr, "\n", "%##%"); + flatModelicaStr = System.stringReplace(flatModelicaStr, "%##%", "','"); + flatModelicaStr = stringAppend(flatModelicaStr,"'};"); + filename = DAEQuery.writeIncidenceMatrix(dlow, filenameprefix, flatModelicaStr); + str = stringAppend("The equation system was dumped to Matlab file:", filename); + then + (cache,Values.STRING(str),st,file_dir); + end match; +end getIncidenceMatrix; + +public function runFrontEnd + input FCore.Cache inCache; + input FCore.Graph inEnv; + input Absyn.Path className; + input GlobalScript.SymbolTable inInteractiveSymbolTable; + input Boolean relaxedFrontEnd "Do not check for illegal simulation models, so we allow instantation of packages, etc"; + output FCore.Cache cache; + output FCore.Graph env; + output DAE.DAElist dae; + output GlobalScript.SymbolTable st; +algorithm + // add program to the cache so it can be used to lookup modelica:// + // URIs in external functions IncludeDirectory/LibraryDirectory + st := runFrontEndLoadProgram(className, inInteractiveSymbolTable); + cache := FCore.setProgramInCache(inCache, GlobalScriptUtil.getSymbolTableAST(st)); + if Flags.isSet(Flags.GC_PROF) then + print(GC.profStatsStr(GC.getProfStats(), head="GC stats before front-end:") + "\n"); + end if; + (cache,env,dae,st) := runFrontEndWork(cache,inEnv,className,st,relaxedFrontEnd,Error.getNumErrorMessages()); + if Flags.isSet(Flags.GC_PROF) then + print(GC.profStatsStr(GC.getProfStats(), head="GC stats after front-end:") + "\n"); + end if; +end runFrontEnd; + +protected function runFrontEndLoadProgram + input Absyn.Path className; + input GlobalScript.SymbolTable inSt; + output GlobalScript.SymbolTable st; +algorithm + st := matchcontinue (className, inSt) + local + Absyn.Restriction restriction; + Absyn.Class absynClass; + String str,re; + Option fp; + SCode.Program scodeP, scodePNew, scode_builtin; + list ic,ic_1; + Absyn.Program p,ptot,p_builtin; + list iv; + list cf; + list lf; + DAE.FunctionTree funcs; + Boolean b; + case (_, GlobalScript.SYMBOLTABLE(ast=p)) + equation + _ = Interactive.getPathedClassInProgram(className, p); + then inSt; + case (_, GlobalScript.SYMBOLTABLE(p,fp,ic,iv,cf,lf)) + equation + str = Absyn.pathFirstIdent(className); + (p,b) = CevalScript.loadModel({(Absyn.IDENT(str),{"default"})},Settings.getModelicaPath(Config.getRunningTestsuite()),p,true,true,true,false); + Error.assertionOrAddSourceMessage(not b,Error.NOTIFY_NOT_LOADED,{str,"default"},Absyn.dummyInfo); + // print(stringDelimitList(list(Absyn.pathString(path) for path in Interactive.getTopClassnames(p)), ",") + "\n"); + then GlobalScript.SYMBOLTABLE(p,fp,ic,iv,cf,lf); + end matchcontinue; +end runFrontEndLoadProgram; + +protected function runFrontEndWork + input FCore.Cache inCache; + input FCore.Graph inEnv; + input Absyn.Path className; + input GlobalScript.SymbolTable inInteractiveSymbolTable; + input Boolean relaxedFrontEnd "Do not check for illegal simulation models, so we allow instantation of packages, etc"; + input Integer numError; + output FCore.Cache cache; + output FCore.Graph env; + output DAE.DAElist dae; + output GlobalScript.SymbolTable st; +algorithm + (cache,env,dae,st) := matchcontinue (inCache,inEnv,className,inInteractiveSymbolTable,relaxedFrontEnd,numError) + local + Absyn.Restriction restriction; + Absyn.Class absynClass; + String str,re; + Option fp; + SCode.Program scodeP, scodePNew, scode_builtin; + list ic,ic_1; + Absyn.Program p,ptot,p_builtin; + list iv; + list cf; + list lf; + DAE.FunctionTree funcs; + + case (cache,env,_,GlobalScript.SYMBOLTABLE(p,fp,ic,iv,cf,lf),_,_) + equation + true = Flags.isSet(Flags.GRAPH_INST); + false = Flags.isSet(Flags.SCODE_INST); + + System.realtimeTick(ClockIndexes.RT_CLOCK_FINST); + str = Absyn.pathString(className); + (absynClass as Absyn.CLASS(restriction = restriction)) = Interactive.getPathedClassInProgram(className, p); + re = Absyn.restrString(restriction); + Error.assertionOrAddSourceMessage(relaxedFrontEnd or not (Absyn.isFunctionRestriction(restriction) or Absyn.isPackageRestriction(restriction)), + Error.INST_INVALID_RESTRICTION,{str,re},Absyn.dummyInfo); + (p,true) = CevalScript.loadModel(Interactive.getUsesAnnotationOrDefault(Absyn.PROGRAM({absynClass},Absyn.TOP()), false),Settings.getModelicaPath(Config.getRunningTestsuite()),p,false,true,true,false); + print("Load deps: " + realString(System.realtimeTock(ClockIndexes.RT_CLOCK_FINST)) + "\n"); + + System.realtimeTick(ClockIndexes.RT_CLOCK_FINST); + scodeP = SCodeUtil.translateAbsyn2SCode(p); + print("Absyn->SCode: " + realString(System.realtimeTock(ClockIndexes.RT_CLOCK_FINST)) + "\n"); + + dae = FInst.instPath(className, scodeP); + ic_1 = ic; + then + (cache,env,dae,GlobalScript.SYMBOLTABLE(p,fp,ic_1,iv,cf,lf)); + + case (_, _, _, GlobalScript.SYMBOLTABLE(p, fp, ic, iv, cf, lf), _, _) + equation + false = Flags.isSet(Flags.GRAPH_INST); + true = Flags.isSet(Flags.SCODE_INST); + scodeP = SCodeUtil.translateAbsyn2SCode(p); + // remove extends Modelica.Icons.* + //scodeP = SCodeSimplify.simplifyProgram(scodeP); + + // (_,scode_builtin) = Builtin.getInitialFunctions(); + + // nfenv = NFEnv.buildInitialEnv(scodeP, scode_builtin); + // (dae, funcs) = NFInst.instClass(className, nfenv); + + // cache = FCore.emptyCache(); + // cache = FCore.setCachedFunctionTree(cache, funcs); + // env = FGraph.empty(); + // ic_1 = Interactive.addInstantiatedClass(ic, + // GlobalScript.INSTCLASS(className, dae, env)); + // st = GlobalScript.SYMBOLTABLE(p, fp, ic_1, iv, cf, lf); + _ = NFInst.instClassInProgram(className, scodeP); + + cache = FCore.emptyCache(); + env = FGraph.empty(); + dae = DAE.DAE({}); + st = inInteractiveSymbolTable; + then + (cache, env, dae, st); + + case (cache,env,_,GlobalScript.SYMBOLTABLE(p,fp,ic,iv,cf,lf),_,_) + equation + false = Flags.isSet(Flags.GRAPH_INST); + false = Flags.isSet(Flags.SCODE_INST); + str = Absyn.pathString(className); + (absynClass as Absyn.CLASS(restriction = restriction)) = Interactive.getPathedClassInProgram(className, p); + re = Absyn.restrString(restriction); + Error.assertionOrAddSourceMessage(relaxedFrontEnd or not (Absyn.isFunctionRestriction(restriction) or Absyn.isPackageRestriction(restriction)), + Error.INST_INVALID_RESTRICTION,{str,re},Absyn.dummyInfo); + (p,true) = CevalScript.loadModel(Interactive.getUsesAnnotationOrDefault(Absyn.PROGRAM({absynClass},Absyn.TOP()), false),Settings.getModelicaPath(Config.getRunningTestsuite()),p,false,true,true,false); + + //System.stopTimer(); + //print("\nExists+Dependency: " + realString(System.getTimerIntervalTime())); + + //System.startTimer(); + //print("\nAbsyn->SCode"); + + scodeP = SCodeUtil.translateAbsyn2SCode(p); + + // TODO: Why not simply get the whole thing from the cached SCode? It's faster, just need to stop doing the silly Dependency stuff. + + //System.stopTimer(); + //print("\nAbsyn->SCode: " + realString(System.getTimerIntervalTime())); + + //System.startTimer(); + //print("\nInst.instantiateClass"); + (cache,env,_,dae) = Inst.instantiateClass(cache,InnerOuter.emptyInstHierarchy,scodeP,className); + + FGraphDump.dumpGraph(env, "F:\\dev\\" + Absyn.pathString(className) + ".graph.graphml"); + + //System.stopTimer(); + //print("\nInst.instantiateClass: " + realString(System.getTimerIntervalTime())); + + // adrpo: do not add it to the instantiated classes, it just consumes memory for nothing. + ic_1 = ic; + // ic_1 = Interactive.addInstantiatedClass(ic, GlobalScript.INSTCLASS(className,dae,env)); + _ = DAEUtil.getFunctionList(FCore.getFunctionTree(cache)); // Make sure that the functions are valid before returning success + then (cache,env,dae,GlobalScript.SYMBOLTABLE(p,fp,ic_1,iv,cf,lf)); + + case (cache,env,_,st as GlobalScript.SYMBOLTABLE(ast=p),_,_) + equation + str = Absyn.pathString(className); + failure(_ = Interactive.getPathedClassInProgram(className, p)); + Error.addMessage(Error.LOOKUP_ERROR, {str,""}); + then fail(); + + else + equation + str = Absyn.pathString(className); + true = Error.getNumErrorMessages() == numError; + str = "Instantiation of " + str + " failed with no error message."; + Error.addMessage(Error.INTERNAL_ERROR, {str}); + then fail(); + end matchcontinue; +end runFrontEndWork; + +protected function translateModel " author: x02lucpo + translates a model into cpp code and writes also a makefile" + input FCore.Cache inCache; + input FCore.Graph inEnv; + input Absyn.Path className "path for the model"; + input GlobalScript.SymbolTable inInteractiveSymbolTable; + input String inFileNamePrefix; + input Boolean addDummy "if true, add a dummy state"; + input Option inSimSettingsOpt; + output FCore.Cache outCache; + output GlobalScript.SymbolTable outInteractiveSymbolTable; + output BackendDAE.BackendDAE outBackendDAE; + output list outStringLst; + output String outFileDir; + output list> resultValues; +algorithm + (outCache,outInteractiveSymbolTable,outBackendDAE,outStringLst,outFileDir,resultValues):= + match (inCache,inEnv,className,inInteractiveSymbolTable,inFileNamePrefix,addDummy,inSimSettingsOpt) + local + FCore.Cache cache; + FCore.Graph env; + BackendDAE.BackendDAE indexed_dlow; + GlobalScript.SymbolTable st; + list libs; + String file_dir, fileNamePrefix; + Absyn.Program p; + + case (cache,env,_,st as GlobalScript.SYMBOLTABLE(),fileNamePrefix,_,_) + equation + (cache, st, indexed_dlow, libs, file_dir, resultValues) = + SimCodeMain.translateModel(cache,env,className,st,fileNamePrefix,addDummy,inSimSettingsOpt,Absyn.FUNCTIONARGS({},{})); + then + (cache,st,indexed_dlow,libs,file_dir,resultValues); + + end match; +end translateModel; + +/*protected function translateModelCPP " author: x02lucpo + translates a model into cpp code and writes also a makefile" + input FCore.Cache inCache; + input FCore.Graph inEnv; + input Absyn.Path className "path for the model"; + input GlobalScript.SymbolTable inInteractiveSymbolTable; + input String inFileNamePrefix; + input Boolean addDummy "if true, add a dummy state"; + input Option inSimSettingsOpt; + output FCore.Cache outCache; + output Values.Value outValue; + output GlobalScript.SymbolTable outInteractiveSymbolTable; + output BackendDAE.BackendDAE outBackendDAE; + output list outStringLst; + output String outFileDir; + output list> resultValues; +algorithm + (outCache,outValue,outInteractiveSymbolTable,outBackendDAE,outStringLst,outFileDir,resultValues):= + match (inCache,inEnv,className,inInteractiveSymbolTable,inFileNamePrefix,addDummy,inSimSettingsOpt) + local + FCore.Cache cache; + FCore.Graph env; + BackendDAE.BackendDAE indexed_dlow; + GlobalScript.SymbolTable st; + list libs; + Values.Value outValMsg; + String file_dir, fileNamePrefix; + + case (cache,env,className,st,fileNamePrefix,addDummy,inSimSettingsOpt) + equation + (cache, outValMsg, st, indexed_dlow, libs, file_dir, resultValues) = + SimCodeUtil.translateModelCPP(cache,env,className,st,fileNamePrefix,addDummy,inSimSettingsOpt); + then + (cache,outValMsg,st,indexed_dlow,libs,file_dir,resultValues); + end match; +end translateModelCPP;*/ + +protected function translateModelFMU " author: Frenkel TUD + translates a model into cpp code and writes also a makefile" + input FCore.Cache inCache; + input FCore.Graph inEnv; + 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 inSimSettingsOpt; + output FCore.Cache outCache; + output Values.Value outValue; + output GlobalScript.SymbolTable outInteractiveSymbolTable; +algorithm + (outCache,outValue,outInteractiveSymbolTable):= + 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 libs; + Values.Value outValMsg; + 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,FMUType,fileNamePrefix,addDummy,inSimSettingsOpt); + + // compile + fileNamePrefix = stringAppend(fileNamePrefix,"_FMU"); + CevalScript.compileModel(fileNamePrefix , libs); + + then + (cache,outValMsg,st); + else /* mo file directory */ + equation + str = Error.printMessagesStr(false); + then + (inCache,ValuesUtil.makeArray({Values.STRING("translateModelFMU error."),Values.STRING(str)}),inInteractiveSymbolTable); + end match; +end translateModelFMU; + + +protected function translateModelXML " author: Alachew + translates a model into XML code " + input FCore.Cache inCache; + input FCore.Graph inEnv; + input Absyn.Path className "path for the model"; + input GlobalScript.SymbolTable inInteractiveSymbolTable; + input String inFileNamePrefix; + input Boolean addDummy "if true, add a dummy state"; + input Option inSimSettingsOpt; + output FCore.Cache outCache; + output Values.Value outValue; + output GlobalScript.SymbolTable outInteractiveSymbolTable; +algorithm + (outCache,outValue,outInteractiveSymbolTable):= + match (inCache,inEnv,className,inInteractiveSymbolTable,inFileNamePrefix,addDummy,inSimSettingsOpt) + local + FCore.Cache cache; + FCore.Graph env; + BackendDAE.BackendDAE indexed_dlow; + GlobalScript.SymbolTable st; + list libs; + Values.Value outValMsg; + String file_dir, fileNamePrefix, str; + case (cache,env,_,st,fileNamePrefix,_,_) /* mo file directory */ + equation + (cache, outValMsg, st,_,_,_, _) = + SimCodeMain.translateModelXML(cache,env,className,st,fileNamePrefix,addDummy,inSimSettingsOpt); + then + (cache,outValMsg,st); + else /* mo file directory */ + equation + str = Error.printMessagesStr(false); + then + (inCache,ValuesUtil.makeArray({Values.STRING("translateModelXML error."),Values.STRING(str)}),inInteractiveSymbolTable); + end match; +end translateModelXML; + + +public function translateGraphics "function: translates the graphical annotations from old to new version" + input FCore.Cache inCache; + input FCore.Graph inEnv; + input Absyn.Path className; + input GlobalScript.SymbolTable inInteractiveSymbolTable; + input Absyn.Msg inMsg; + output FCore.Cache outCache; + output Values.Value outValue; + output GlobalScript.SymbolTable outInteractiveSymbolTable; +algorithm + (outCache,outValue,outInteractiveSymbolTable) := + matchcontinue (inCache,inEnv,className,inInteractiveSymbolTable,inMsg) + local + FCore.Graph env; + list ic; + GlobalScript.SymbolTable st; + Absyn.Program p; + list iv; + list cf; + Absyn.Msg msg; + FCore.Cache cache; + list lf; + String errorMsg,retStr,s1; + Absyn.Class cls, refactoredClass; + Absyn.Within within_; + Absyn.Program p1; + Boolean strEmpty; + + case (cache,_,_,(GlobalScript.SYMBOLTABLE(p as Absyn.PROGRAM(),_,ic,iv,cf,lf)),_) + equation + cls = Interactive.getPathedClassInProgram(className, p); + refactoredClass = Refactor.refactorGraphicalAnnotation(p, cls); + within_ = Interactive.buildWithin(className); + p1 = Interactive.updateProgram(Absyn.PROGRAM({refactoredClass}, within_), p); + s1 = Absyn.pathString(className); + retStr=stringAppendList({"Translation of ",s1," successful.\n"}); + then + (cache,Values.STRING(retStr),GlobalScript.SYMBOLTABLE(p1,NONE(),ic,iv,cf,lf)); + + case (cache,_,_,st,_) + equation + errorMsg = Error.printMessagesStr(false); + strEmpty = (stringCompare("",errorMsg)==0); + errorMsg = if strEmpty then "Internal error, translating graphics to new version" else errorMsg; + then + (cache,Values.STRING(errorMsg),st); + end matchcontinue; +end translateGraphics; + + +protected function calculateSimulationSettings " author: x02lucpo + calculates the start,end,interval,stepsize, method and initFileName" + input FCore.Cache inCache; + input FCore.Graph inEnv; + input list vals; + input GlobalScript.SymbolTable inInteractiveSymbolTable; + input Absyn.Msg inMsg; + output FCore.Cache outCache; + output SimCode.SimulationSettings outSimSettings; +algorithm + (outCache,outSimSettings):= + match (inCache,inEnv,vals,inInteractiveSymbolTable,inMsg) + local + String method_str,options_str,outputFormat_str,variableFilter_str,s; + GlobalScript.SymbolTable st; + Values.Value starttime_v,stoptime_v,tolerance_v; + Integer interval_i; + Real starttime_r,stoptime_r,tolerance_r; + FCore.Graph env; + Absyn.Msg msg; + FCore.Cache cache; + String cflags,simflags; + case (cache,_,{Values.CODE(Absyn.C_TYPENAME(_)),starttime_v,stoptime_v,Values.INTEGER(interval_i),tolerance_v,Values.STRING(method_str),_,Values.STRING(options_str),Values.STRING(outputFormat_str),Values.STRING(variableFilter_str),Values.STRING(cflags),Values.STRING(_)}, + (GlobalScript.SYMBOLTABLE()),_) + equation + starttime_r = ValuesUtil.valueReal(starttime_v); + stoptime_r = ValuesUtil.valueReal(stoptime_v); + tolerance_r = ValuesUtil.valueReal(tolerance_v); + outSimSettings = SimCodeMain.createSimulationSettings(starttime_r,stoptime_r,interval_i,tolerance_r,method_str,options_str,outputFormat_str,variableFilter_str,cflags); + then + (cache, outSimSettings); + else + equation + s = "CevalScript.calculateSimulationSettings failed: " + ValuesUtil.valString(Values.TUPLE(vals)); + Error.addMessage(Error.INTERNAL_ERROR, {s}); + then + fail(); + end match; +end calculateSimulationSettings; + +protected function getListFirstShowError +"@author: adrpo + return the first element in the list and the rest of values. + if the list is empty display the errorMessage!" + input list inValues; + input String errorMessage; + output Values.Value outValue; + output list restValues; +algorithm + (outValue, restValues) := match(inValues, errorMessage) + local + Values.Value v; + list rest; + + // everything is fine and dandy + case (v::rest, _) then (v, rest); + + // ups, we're missing an argument + case ({}, _) + equation + Error.addMessage(Error.INTERNAL_ERROR, {errorMessage}); + then + fail(); + end match; +end getListFirstShowError; + +protected function getListNthShowError +"@author: adrpo + return the N-th element in the list and the rest of values. + if the list is empty display the errorMessage!" + input list inValues; + input String errorMessage; + input Integer currentElement; + input Integer nthElement; + output Values.Value outValue; +algorithm + outValue := matchcontinue(inValues, errorMessage, currentElement, nthElement) + local + Values.Value v; + list lst,rest; + Integer i,n; + + // everything is fine and dandy + case (lst, _, i, n) + equation + true = i < n; + (_,rest) = getListFirstShowError(lst,errorMessage); + v = getListNthShowError(rest,errorMessage, i+1, n); + then v; + + // everything is fine and dandy + case (lst, _, _, _) + equation + (v, _) = getListFirstShowError(lst,errorMessage); + then v; + + end matchcontinue; +end getListNthShowError; + +protected function moveClass + input Absyn.Path inClassName; + input String inDirection; + input Absyn.Program inProg; + output Absyn.Program outProg; +algorithm + outProg := match(inClassName, inDirection, inProg) + local + Absyn.Path c, parent; + Absyn.Program p; + list cls; + Absyn.Within w; + String name; + Absyn.Class parentparentClass; + + case (Absyn.FULLYQUALIFIED(c), _, _) + equation + p = moveClass(c, inDirection, inProg); + then + p; + + case (Absyn.IDENT(name), _, p as Absyn.PROGRAM()) + equation + p.classes = moveClassInList(name, p.classes, inDirection); + then p; + + case (Absyn.QUALIFIED(_, _), _, p) + equation + parent = Absyn.stripLast(inClassName); + _ = Interactive.getPathedClassInProgram(parent, p); + then + p; + + end match; +end moveClass; + +protected function moveClassInList + input String inClassName; + input list inCls; + input String inDirection; + output list outCls; +algorithm + outCls := inCls; +end moveClassInList; + +protected function copyClass + input Absyn.Class inClass; + input String inName; + input Absyn.Within inWithin; + input Absyn.Program inProg; + output Absyn.Program outProg; +algorithm + outProg := match(inClass, inName, inWithin, inProg) + local + Absyn.Within within_; + Absyn.Program p, newp; + String name, newName; + Boolean partialPrefix,finalPrefix,encapsulatedPrefix; + Absyn.Restriction restriction; + Absyn.ClassDef classDef; + case (Absyn.CLASS(partialPrefix = partialPrefix,finalPrefix = finalPrefix,encapsulatedPrefix = encapsulatedPrefix,restriction = restriction, + body = classDef), newName, within_, p) + equation + newp = Interactive.updateProgram(Absyn.PROGRAM({Absyn.CLASS(newName, partialPrefix, finalPrefix, encapsulatedPrefix, restriction, classDef, Absyn.dummyInfo)}, + within_), p); + then newp; + end match; +end copyClass; + +protected function buildModel "translates and builds the model by running compiler script on the generated makefile" + input FCore.Cache inCache; + input FCore.Graph inEnv; + input list inValues; + input GlobalScript.SymbolTable inInteractiveSymbolTable; + input Absyn.Msg inMsg; + output FCore.Cache outCache; + output GlobalScript.SymbolTable outInteractiveSymbolTable3; + output String compileDir; + output String outString1 "className"; + output String outString2 "method"; + output String outputFormat_str; + output String outInitFileName "initFileName"; + output String outSimFlags; + output list> resultValues; +algorithm + (outCache,outInteractiveSymbolTable3,compileDir,outString1,outString2,outputFormat_str,outInitFileName,outSimFlags,resultValues):= + matchcontinue (inCache,inEnv,inValues,inInteractiveSymbolTable,inMsg) + local + GlobalScript.SymbolTable st,st_1,st2; + BackendDAE.BackendDAE indexed_dlow_1; + list libs; + String file_dir,init_filename,method_str,filenameprefix,exeFile,s3,simflags; + Absyn.Path classname; + Absyn.Program p; + Absyn.Class cdef; + Real edit,build,globalEdit,globalBuild,timeCompile; + FCore.Graph env; + SimCode.SimulationSettings simSettings; + Values.Value starttime,stoptime,interval,tolerance,method,options,outputFormat,variableFilter; + list vals, values; + Absyn.Msg msg; + FCore.Cache cache; + Boolean existFile; + + // compile the model + case (cache,env,vals,st,msg) + equation + // buildModel expects these arguments: + // className, startTime, stopTime, numberOfIntervals, tolerance, method, fileNamePrefix, + // options, outputFormat, variableFilter, cflags, simflags + values = vals; + (Values.CODE(Absyn.C_TYPENAME(classname)),vals) = getListFirstShowError(vals, "while retreaving the className (1 arg) from the buildModel arguments"); + (_,vals) = getListFirstShowError(vals, "while retreaving the startTime (2 arg) from the buildModel arguments"); + (_,vals) = getListFirstShowError(vals, "while retreaving the stopTime (3 arg) from the buildModel arguments"); + (_,vals) = getListFirstShowError(vals, "while retreaving the numberOfIntervals (4 arg) from the buildModel arguments"); + (_,vals) = getListFirstShowError(vals, "while retreaving the tolerance (5 arg) from the buildModel arguments"); + (_,vals) = getListFirstShowError(vals, "while retreaving the method (6 arg) from the buildModel arguments"); + (Values.STRING(filenameprefix),vals) = getListFirstShowError(vals, "while retreaving the fileNamePrefix (7 arg) from the buildModel arguments"); + (_,vals) = getListFirstShowError(vals, "while retreaving the options (8 arg) from the buildModel arguments"); + (_,vals) = getListFirstShowError(vals, "while retreaving the outputFormat (9 arg) from the buildModel arguments"); + (_,vals) = getListFirstShowError(vals, "while retreaving the variableFilter (10 arg) from the buildModel arguments"); + (_,vals) = getListFirstShowError(vals, "while retreaving the cflags (11 arg) from the buildModel arguments"); + (Values.STRING(simflags),vals) = getListFirstShowError(vals, "while retreaving the simflags (12 arg) from the buildModel arguments"); + + Error.clearMessages() "Clear messages"; + compileDir = System.pwd() + System.pathDelimiter(); + (cache,simSettings) = calculateSimulationSettings(cache, env, values, st, msg); + SimCode.SIMULATION_SETTINGS(method = method_str, outputFormat = outputFormat_str) + = simSettings; + + (cache,st as GlobalScript.SYMBOLTABLE(),_,libs,file_dir,resultValues) = translateModel(cache,env, classname, st, filenameprefix,true, SOME(simSettings)); + //cname_str = Absyn.pathString(classname); + //SimCodeUtil.generateInitData(indexed_dlow_1, classname, filenameprefix, init_filename, + // starttime_r, stoptime_r, interval_r, tolerance_r, method_str,options_str,outputFormat_str); + + System.realtimeTick(ClockIndexes.RT_CLOCK_BUILD_MODEL); + init_filename = filenameprefix + "_init.xml"; //a hack ? should be at one place somewhere + //win1 = getWithinStatement(classname); + + if Flags.isSet(Flags.DYN_LOAD) then + Debug.traceln("buildModel: about to compile model " + filenameprefix + ", " + file_dir); + end if; + CevalScript.compileModel(filenameprefix, libs); + if Flags.isSet(Flags.DYN_LOAD) then + Debug.trace("buildModel: Compiling done.\n"); + end if; + // p = setBuildTime(p,classname); + st2 = st;// Interactive.replaceSymbolTableProgram(st,p); + timeCompile = System.realtimeTock(ClockIndexes.RT_CLOCK_BUILD_MODEL); + resultValues = ("timeCompile",Values.REAL(timeCompile)) :: resultValues; + then + (cache,st2,compileDir,filenameprefix,method_str,outputFormat_str,init_filename,simflags,resultValues); + + // failure + else + equation + Error.assertion(listLength(inValues) == 12, "buildModel failure, length = " + intString(listLength(inValues)), Absyn.dummyInfo); + then fail(); + end matchcontinue; +end buildModel; + +protected function createSimulationResultFromcallModelExecutable +"This function calls the compiled simulation executable." + input Integer callRet; + input Real timeTotal; + input Real timeSimulation; + input list> resultValues; + input FCore.Cache inCache; + input Absyn.Path className; + input list inVals; + input GlobalScript.SymbolTable inSt; + input String result_file; + input String logFile; + output FCore.Cache outCache; + output Values.Value outValue; + output GlobalScript.SymbolTable outInteractiveSymbolTable; +algorithm + (outCache,outValue,outInteractiveSymbolTable) := matchcontinue (callRet,timeTotal,timeSimulation,resultValues,inCache,className,inVals,inSt,result_file,logFile) + local + GlobalScript.SymbolTable newst; + String res,str; + Values.Value simValue; + + case (0,_,_,_,_,_,_,_,_,_) + equation + simValue = createSimulationResult( + result_file, + simOptionsAsString(inVals), + System.readFile(logFile), + ("timeTotal", Values.REAL(timeTotal)) :: + ("timeSimulation", Values.REAL(timeSimulation)) :: + resultValues); + newst = GlobalScriptUtil.addVarToSymboltable( + DAE.CREF_IDENT("currentSimulationResult", DAE.T_STRING_DEFAULT, {}), + Values.STRING(result_file), FGraph.empty(), inSt); + then + (inCache,simValue,newst); + else + equation + true = System.regularFileExists(logFile); + res = System.readFile(logFile); + str = Absyn.pathString(className); + res = stringAppendList({"Simulation execution failed for model: ", str, "\n", res}); + simValue = createSimulationResult("", simOptionsAsString(inVals), res, resultValues); + then + (inCache,simValue,inSt); + end matchcontinue; +end createSimulationResultFromcallModelExecutable; + +protected function buildOpenTURNSInterface "builds the OpenTURNS interface by calling the OpenTURNS module" + input FCore.Cache inCache; + input FCore.Graph inEnv; + input list vals; + input GlobalScript.SymbolTable inSt; + input Absyn.Msg inMsg; + output FCore.Cache outCache; + output String scriptFile; + output GlobalScript.SymbolTable outSt; +algorithm + (outCache,scriptFile,outSt):= match(inCache,inEnv,vals,inSt,inMsg) + local + String templateFile, str; + Absyn.Program p; + Absyn.Path className; + FCore.Cache cache; + DAE.DAElist dae; + FCore.Graph env; + BackendDAE.BackendDAE dlow; + DAE.FunctionTree funcs; + GlobalScript.SymbolTable st; + Boolean showFlatModelica; + String filenameprefix,description; + + case(cache,_,{Values.CODE(Absyn.C_TYPENAME(className)),Values.STRING(templateFile),Values.BOOL(showFlatModelica)},GlobalScript.SYMBOLTABLE(ast=p),_) + equation + (cache,env,dae,_) = runFrontEnd(cache,inEnv,className,inSt,false); + //print("instantiated class\n"); + dae = DAEUtil.transformationsBeforeBackend(cache,env,dae); + funcs = FCore.getFunctionTree(cache); + if showFlatModelica then + print(DAEDump.dumpStr(dae, funcs)); + end if; + // get all the variable names with a distribution + // TODO FIXME + // sort all variable names in the distribution order + // TODO FIXME + filenameprefix = Absyn.pathString(className); + description = DAEUtil.daeDescription(dae); + dlow = BackendDAECreate.lower(dae,cache,env,BackendDAE.EXTRA_INFO(description,filenameprefix)); + //print("lowered class\n"); + //print("calling generateOpenTurnsInterface\n"); + scriptFile = OpenTURNS.generateOpenTURNSInterface(cache,inEnv,dlow,funcs,className,p,dae,templateFile); + then + (cache,scriptFile,inSt); + + end match; +end buildOpenTURNSInterface; + +protected function runOpenTURNSPythonScript +"runs OpenTURNS with the given python script returning the log file" + input FCore.Cache inCache; + input FCore.Graph inEnv; + input list vals; + input GlobalScript.SymbolTable inSt; + input Absyn.Msg inMsg; + output FCore.Cache outCache; + output String outLogFile; + output GlobalScript.SymbolTable outSt; +algorithm + (outCache,outLogFile,outSt):= match(inCache,inEnv,vals,inSt,inMsg) + local + String pythonScriptFile, logFile; + FCore.Cache cache; + case(cache,_,{Values.STRING(pythonScriptFile)},_,_) + equation + logFile = OpenTURNS.runPythonScript(pythonScriptFile); + then + (cache,logFile,inSt); + end match; +end runOpenTURNSPythonScript; + +public function getFileDir "author: x02lucpo + returns the dir where class file (.mo) was saved or + $OPENMODELICAHOME/work if the file was not saved yet" + input Absyn.ComponentRef inComponentRef "class"; + input Absyn.Program inProgram; + output String outString; +algorithm + outString:= + matchcontinue (inComponentRef,inProgram) + local + Absyn.Path p_class; + Absyn.Class cdef; + String filename,pd,dir_1,omhome,omhome_1; + String pd_1; + list filename_1,dir; + Absyn.ComponentRef class_; + Absyn.Program p; + case (class_,p) + equation + p_class = Absyn.crefToPath(class_) "change to the saved files directory" ; + cdef = Interactive.getPathedClassInProgram(p_class, p); + filename = Absyn.classFilename(cdef); + pd = System.pathDelimiter(); + (pd_1 :: _) = stringListStringChar(pd); + filename_1 = Util.stringSplitAtChar(filename, pd_1); + dir = List.stripLast(filename_1); + dir_1 = stringDelimitList(dir, pd); + then + dir_1; + case (_,_) + equation + omhome = Settings.getInstallationDirectoryPath() "model not yet saved! change to $OPENMODELICAHOME/work" ; + omhome_1 = System.trim(omhome, "\""); + pd = System.pathDelimiter(); + dir_1 = stringAppendList({"\"",omhome_1,pd,"work","\""}); + then + dir_1; + else ""; /* this function should never fail */ + end matchcontinue; +end getFileDir; + +public function checkModel " checks a model and returns number of variables and equations" + input FCore.Cache inCache; + input FCore.Graph inEnv; + input Absyn.Path className; + input GlobalScript.SymbolTable inInteractiveSymbolTable; + input Absyn.Msg inMsg; + output FCore.Cache outCache; + output Values.Value outValue; + output GlobalScript.SymbolTable outInteractiveSymbolTable; +algorithm + (outCache,outValue,outInteractiveSymbolTable) := + matchcontinue (inCache,inEnv,className,inInteractiveSymbolTable,inMsg) + local + DAE.DAElist dae; + FCore.Graph env; + GlobalScript.SymbolTable st; + Absyn.Program p; + Absyn.Msg msg; + FCore.Cache cache; + Integer eqnSize,varSize,simpleEqnSize; + String errorMsg,eqnSizeStr,varSizeStr,retStr,classNameStr,simpleEqnSizeStr; + Boolean strEmpty; + Absyn.Restriction restriction; + Absyn.Class c; + + // handle normal models + case (cache,env,_,(st as GlobalScript.SYMBOLTABLE()),_) + equation + (cache,env,dae,st) = runFrontEnd(cache,env,className,st,false); + + (varSize,eqnSize,simpleEqnSize) = CheckModel.checkModel(dae); + eqnSizeStr = intString(eqnSize); + varSizeStr = intString(varSize); + simpleEqnSizeStr = intString(simpleEqnSize); + + classNameStr = Absyn.pathString(className); + retStr = stringAppendList({"Check of ",classNameStr," completed successfully.","\nClass ",classNameStr," has ",eqnSizeStr," equation(s) and ", + varSizeStr," variable(s).\n",simpleEqnSizeStr," of these are trivial equation(s)."}); + then + (cache,Values.STRING(retStr),st); + + // handle functions + case (cache,env,_,(st as GlobalScript.SYMBOLTABLE(ast = p)),_) + equation + (Absyn.CLASS(restriction=restriction)) = Interactive.getPathedClassInProgram(className, p); + true = Absyn.isFunctionRestriction(restriction) or Absyn.isPackageRestriction(restriction); + (cache,env,_,st) = runFrontEnd(cache,env,className,st,true); + classNameStr = Absyn.pathString(className); + then + (cache,Values.STRING(""),st); + + case (cache,_,_,st as GlobalScript.SYMBOLTABLE(ast=p), _) + equation + classNameStr = Absyn.pathString(className); + false = Interactive.existClass(Absyn.pathToCref(className), p); + Error.addMessage(Error.LOOKUP_ERROR, {classNameStr,""}); + then + (cache,Values.STRING(""),st); + + // errors + case (cache,_,_,st,_) + equation + classNameStr = Absyn.pathString(className); + strEmpty = Error.getNumMessages() == 0; + errorMsg = "Check of " + classNameStr + " failed with no error message"; + if strEmpty then + Error.addMessage(Error.INTERNAL_ERROR, {errorMsg,""}); + end if; + then + (cache,Values.STRING(""),st); + + end matchcontinue; +end checkModel; + +protected function selectIfNotEmpty + input String inString; + input String selector " "; + output String outString; +algorithm + outString := match(inString, selector) + local + String s; + + case (_, "") then ""; + + else + equation + s = inString + selector; + then s; + end match; +end selectIfNotEmpty; + +protected function getWithinStatement "To get a correct Within-path with unknown input-path." + input Absyn.Path ip; + output Absyn.Within op; +algorithm op := matchcontinue(ip) + local Absyn.Path path; + case(path) equation path = Absyn.stripLast(path); then Absyn.WITHIN(path); + else Absyn.TOP(); + end matchcontinue; +end getWithinStatement; + +public function subtractDummy +"if $dummy is present in Variables, subtract 1 from equation and variable size, otherwise not" + input BackendDAE.Variables vars; + input Integer eqnSize; + input Integer varSize; + output Integer outEqnSize; + output Integer outVarSize; +algorithm + (outEqnSize,outVarSize) := matchcontinue(vars,eqnSize,varSize) + case(_,_,_) + equation + (_,_) = BackendVariable.getVar(ComponentReference.makeCrefIdent("$dummy",DAE.T_UNKNOWN_DEFAULT,{}),vars); + then (eqnSize-1,varSize-1); + else (eqnSize,varSize); + end matchcontinue; +end subtractDummy; + +protected function dumpXMLDAEFrontEnd +"@author: adrpo + this function runs the front-end for the dumpXMLDAE function" + input FCore.Cache inCache; + input FCore.Graph inEnv; + input Absyn.Path inClassName; + input GlobalScript.SymbolTable inInteractiveSymbolTable; + output FCore.Cache outCache; + output FCore.Graph outEnv; + output DAE.DAElist outDae; +algorithm + (outCache, outEnv, outDae) := match(inCache, inEnv, inClassName, inInteractiveSymbolTable) + local + Absyn.Program p; + SCode.Program scode; + + case (_, _, _, _) + equation + GlobalScript.SYMBOLTABLE(ast = p) = inInteractiveSymbolTable; + scode = SCodeUtil.translateAbsyn2SCode(p); + (outCache, outEnv, _, outDae) = Inst.instantiateClass(inCache, InnerOuter.emptyInstHierarchy, scode, inClassName); + outDae = DAEUtil.transformationsBeforeBackend(outCache,outEnv,outDae); + then + (outCache, outEnv, outDae); + + end match; +end dumpXMLDAEFrontEnd; + +protected function dumpXMLDAE " author: fildo + This function outputs the DAE system corresponding to a specific model." + input FCore.Cache inCache; + input FCore.Graph inEnv; + input list vals; + input GlobalScript.SymbolTable inInteractiveSymbolTable; + input Absyn.Msg inMsg; + output FCore.Cache outCache; + output GlobalScript.SymbolTable outInteractiveSymbolTable3; + output String xml_filename; +algorithm + (outCache,outInteractiveSymbolTable3,xml_filename) := + matchcontinue (inCache,inEnv,vals,inInteractiveSymbolTable,inMsg) + local + String cname_str,filenameprefix,compileDir,rewriteRulesFile,description; + FCore.Graph env; + Absyn.Path classname; + Absyn.Program p; + BackendDAE.BackendDAE dlow,dlow_1,indexed_dlow; + FCore.Cache cache; + Boolean addOriginalIncidenceMatrix,addSolvingInfo,addMathMLCode,dumpResiduals; + GlobalScript.SymbolTable st; + Absyn.Msg msg; + DAE.DAElist dae_1,dae; + list p_1; + + case (cache,env,{Values.CODE(Absyn.C_TYPENAME(classname)),Values.STRING(string="flat"), + Values.BOOL(addOriginalIncidenceMatrix),Values.BOOL(addSolvingInfo), + Values.BOOL(addMathMLCode),Values.BOOL(dumpResiduals), + Values.STRING(filenameprefix),Values.STRING(rewriteRulesFile)},st,_) + equation + Error.clearMessages() "Clear messages"; + + // set the rewrite rules flag + Flags.setConfigString(Flags.REWRITE_RULES_FILE, rewriteRulesFile); + // load the rewrite rules + RewriteRules.loadRules(); + + (cache, env, dae) = dumpXMLDAEFrontEnd(cache, env, classname, st); + description = DAEUtil.daeDescription(dae); + + compileDir = System.pwd() + System.pathDelimiter(); + cname_str = Absyn.pathString(classname); + filenameprefix = if filenameprefix == "" then cname_str else filenameprefix; + + dlow = BackendDAECreate.lower(dae,cache,env,BackendDAE.EXTRA_INFO(description,filenameprefix)); //Verificare cosa fa + dlow_1 = BackendDAEUtil.preOptimizeBackendDAE(dlow,NONE()); + dlow_1 = FindZeroCrossings.findZeroCrossings(dlow_1); + xml_filename = stringAppendList({filenameprefix,".xml"}); + + // apply rewrite rules to the back-end + dlow_1 = applyRewriteRulesOnBackend(dlow_1); + + Print.clearBuf(); + XMLDump.dumpBackendDAE(dlow_1,addOriginalIncidenceMatrix,addSolvingInfo,addMathMLCode,dumpResiduals,false); + Print.writeBuf(xml_filename); + Print.clearBuf(); + compileDir = if Config.getRunningTestsuite() then "" else compileDir; + + // clear the rewrite rules! + Flags.setConfigString(Flags.REWRITE_RULES_FILE, ""); + RewriteRules.clearRules(); + then + (cache,st,stringAppendList({compileDir,xml_filename})); + + case (cache,env,{Values.CODE(Absyn.C_TYPENAME(classname)),Values.STRING(string="optimiser"), + Values.BOOL(addOriginalIncidenceMatrix),Values.BOOL(addSolvingInfo), + Values.BOOL(addMathMLCode),Values.BOOL(dumpResiduals), + Values.STRING(filenameprefix),Values.STRING(rewriteRulesFile)},(st as GlobalScript.SYMBOLTABLE()),_) + equation + //asInSimulationCode==false => it's NOT necessary to do all the translation's steps before dumping with xml + Error.clearMessages() "Clear messages"; + + // set the rewrite rules flag + Flags.setConfigString(Flags.REWRITE_RULES_FILE, rewriteRulesFile); + // load the rewrite rules + RewriteRules.loadRules(); + + (cache, env, dae) = dumpXMLDAEFrontEnd(cache, env, classname, st); + description = DAEUtil.daeDescription(dae); + + compileDir = System.pwd() + System.pathDelimiter(); + cname_str = Absyn.pathString(classname); + filenameprefix = if filenameprefix == "" then cname_str else filenameprefix; + + dlow = BackendDAECreate.lower(dae,cache,env,BackendDAE.EXTRA_INFO(description,filenameprefix)); //Verificare cosa fa + dlow_1 = BackendDAEUtil.preOptimizeBackendDAE(dlow,NONE()); + dlow_1 = BackendDAEUtil.transformBackendDAE(dlow_1,NONE(),NONE(),NONE()); + dlow_1 = FindZeroCrossings.findZeroCrossings(dlow_1); + xml_filename = stringAppendList({filenameprefix,".xml"}); + + // apply rewrite rules to the back-end + dlow_1 = applyRewriteRulesOnBackend(dlow_1); + + Print.clearBuf(); + XMLDump.dumpBackendDAE(dlow_1,addOriginalIncidenceMatrix,addSolvingInfo,addMathMLCode,dumpResiduals,false); + Print.writeBuf(xml_filename); + Print.clearBuf(); + compileDir = if Config.getRunningTestsuite() then "" else compileDir; + + // clear the rewrite rules! + Flags.setConfigString(Flags.REWRITE_RULES_FILE, ""); + RewriteRules.clearRules(); + then + (cache,st,stringAppendList({compileDir,xml_filename})); + + case (cache,env,{Values.CODE(Absyn.C_TYPENAME(classname)),Values.STRING(string="backEnd"), + Values.BOOL(addOriginalIncidenceMatrix),Values.BOOL(addSolvingInfo), + Values.BOOL(addMathMLCode),Values.BOOL(dumpResiduals), + Values.STRING(filenameprefix),Values.STRING(rewriteRulesFile)},(st as GlobalScript.SYMBOLTABLE()),_) + equation + //asInSimulationCode==true => it's necessary to do all the translation's steps before dumping with xml + Error.clearMessages() "Clear messages"; + + // set the rewrite rules flag + Flags.setConfigString(Flags.REWRITE_RULES_FILE, rewriteRulesFile); + // load the rewrite rules + RewriteRules.loadRules(); + + (cache, env, dae) = dumpXMLDAEFrontEnd(cache, env, classname, st); + description = DAEUtil.daeDescription(dae); + + compileDir = System.pwd() + System.pathDelimiter(); + cname_str = Absyn.pathString(classname); + filenameprefix = if filenameprefix == "" then cname_str else filenameprefix; + + dlow = BackendDAECreate.lower(dae,cache,env,BackendDAE.EXTRA_INFO(description,filenameprefix)); + indexed_dlow = BackendDAEUtil.getSolvedSystem(dlow,""); + xml_filename = stringAppendList({filenameprefix,".xml"}); + + // apply rewrite rules to the back-end + indexed_dlow = applyRewriteRulesOnBackend(indexed_dlow); + + Print.clearBuf(); + XMLDump.dumpBackendDAE(indexed_dlow,addOriginalIncidenceMatrix,addSolvingInfo,addMathMLCode,dumpResiduals,false); + Print.writeBuf(xml_filename); + Print.clearBuf(); + compileDir = if Config.getRunningTestsuite() then "" else compileDir; + + // clear the rewrite rules! + Flags.setConfigString(Flags.REWRITE_RULES_FILE, ""); + RewriteRules.clearRules(); + then + (cache,st,stringAppendList({compileDir,xml_filename})); + + case (cache,env,{Values.CODE(Absyn.C_TYPENAME(classname)),Values.STRING(string="stateSpace"), + Values.BOOL(addOriginalIncidenceMatrix),Values.BOOL(addSolvingInfo), + Values.BOOL(addMathMLCode),Values.BOOL(dumpResiduals), + Values.STRING(filenameprefix),Values.STRING(rewriteRulesFile)},(st as GlobalScript.SYMBOLTABLE()),_) + equation + //asInSimulationCode==true => it's necessary to do all the translation's steps before dumping with xml + Error.clearMessages() "Clear messages"; + + // set the rewrite rules flag + Flags.setConfigString(Flags.REWRITE_RULES_FILE, rewriteRulesFile); + // load the rewrite rules + RewriteRules.loadRules(); + + (cache, env, dae) = dumpXMLDAEFrontEnd(cache, env, classname, st); + description = DAEUtil.daeDescription(dae); + + compileDir = System.pwd() + System.pathDelimiter(); + cname_str = Absyn.pathString(classname); + filenameprefix = if filenameprefix == "" then cname_str else filenameprefix; + + dlow = BackendDAECreate.lower(dae,cache,env,BackendDAE.EXTRA_INFO(description,filenameprefix)); + indexed_dlow = BackendDAEUtil.getSolvedSystem(dlow,""); + xml_filename = stringAppendList({filenameprefix,".xml"}); + + // apply rewrite rules to the back-end + indexed_dlow = applyRewriteRulesOnBackend(indexed_dlow); + + Print.clearBuf(); + XMLDump.dumpBackendDAE(indexed_dlow,addOriginalIncidenceMatrix,addSolvingInfo,addMathMLCode,dumpResiduals,true); + Print.writeBuf(xml_filename); + Print.clearBuf(); + compileDir = if Config.getRunningTestsuite() then "" else compileDir; + + // clear the rewrite rules! + Flags.setConfigString(Flags.REWRITE_RULES_FILE, ""); + RewriteRules.clearRules(); + then + (cache,st,stringAppendList({compileDir,xml_filename})); + + else + equation + // clear the rewrite rules if we fail! + Flags.setConfigString(Flags.REWRITE_RULES_FILE, ""); + RewriteRules.clearRules(); + then fail(); + + end matchcontinue; +end dumpXMLDAE; + +protected function applyRewriteRulesOnBackend + input BackendDAE.BackendDAE inBackendDAE; + output BackendDAE.BackendDAE outBackendDAE; +algorithm + outBackendDAE := matchcontinue(inBackendDAE) + local + list vars,knvars,extvars,aliasvars; + BackendDAE.Variables vars_knownVars; + BackendDAE.Variables vars_externalObject; + BackendDAE.VariableArray varArr_externalObject; + BackendDAE.Variables vars_aliasVars; + BackendDAE.VariableArray varArr_aliasVars; + BackendDAE.ExternalObjectClasses extObjCls; + BackendDAE.EquationArray reqns,ieqns; + list constrs; + list clsAttrs; + list functionsElems; + BackendDAE.BackendDAEType btp; + list systs; + BackendDAE.SymbolicJacobians symjacs; + DAE.FunctionTree funcs; + BackendDAE.EventInfo eventInfo; + BackendDAE.ExtraInfo extraInfo; + FCore.Cache cache; + FCore.Graph env; + + // no rewrites! + case _ + equation + true = RewriteRules.noRewriteRulesBackEnd(); + then + inBackendDAE; + + // some rewrites + case _ + equation + false = RewriteRules.noRewriteRulesBackEnd(); + outBackendDAE = BackendDAEOptimize.applyRewriteRulesBackend(inBackendDAE); + then + outBackendDAE; + + end matchcontinue; +end applyRewriteRulesOnBackend; + +protected function getClassnamesInClassList + input Absyn.Path inPath; + input Absyn.Program inProgram; + input Absyn.Class inClass; + input Boolean inShowProtected; + output list outStrings; +algorithm + outStrings := + match (inPath,inProgram,inClass,inShowProtected) + local + list strlist; + list parts; + Absyn.Path inmodel,path; + Absyn.Program p; + String baseClassName; + Boolean b; + case (_,_,Absyn.CLASS(body = Absyn.PARTS(classParts = parts)),b) + equation + strlist = Interactive.getClassnamesInParts(parts,b); + then + strlist; + + case (_,_,Absyn.CLASS(body = Absyn.DERIVED(typeSpec=Absyn.TPATH())),_) + equation + then + {}; + + case (_,_,Absyn.CLASS(body = Absyn.OVERLOAD(_, _)),_) + equation + then {}; + + case (_,_,Absyn.CLASS(body = Absyn.ENUMERATION(_, _)),_) + equation + then {}; + + case (_,_,Absyn.CLASS(body = Absyn.CLASS_EXTENDS(parts=parts)),b) + equation + strlist = Interactive.getClassnamesInParts(parts,b); + then strlist; + + case (_,_,Absyn.CLASS(body = Absyn.PDER(_,_,_)),_) + equation + then {}; + + end match; +end getClassnamesInClassList; + +protected function joinPaths + input String child; + input Absyn.Path parent; + output Absyn.Path outPath; +algorithm + outPath := match (child, parent) + local + Absyn.Path r, res; + String c; + case (c, r) + equation + res = Absyn.joinPaths(r, Absyn.IDENT(c)); + then res; + end match; +end joinPaths; + +protected function getAllClassPathsRecursive +"@author adrpo + Returns all paths of the classes recursively defined in a given class with the specified path." + input Absyn.Path inPath "the given class path"; + input Boolean inCheckProtected; + input Absyn.Program inProgram "the program"; + output list outPaths; +algorithm + outPaths := + matchcontinue (inPath,inCheckProtected,inProgram) + local + Absyn.Class cdef; + String parent_string, s; + list strlst; + Absyn.Program p; + list result_path_lst, result; + Boolean b; + case (_, b, p) + equation + cdef = Interactive.getPathedClassInProgram(inPath, p); + strlst = getClassnamesInClassList(inPath, p, cdef, b); + result_path_lst = List.map1(strlst, joinPaths, inPath); + result = List.flatten(List.map2(result_path_lst, getAllClassPathsRecursive, b, p)); + then + inPath::result; + else + equation + parent_string = Absyn.pathString(inPath); + s = Error.printMessagesStr(false); + s = stringAppendList({parent_string,"->","PROBLEM GETTING CLASS PATHS: ", s, "\n"}); + print(s); + then {}; + end matchcontinue; +end getAllClassPathsRecursive; + +public function checkAllModelsRecursive +"@author adrpo + checks all models and returns number of variables and equations" + input FCore.Cache inCache; + input FCore.Graph inEnv; + input Absyn.Path className; + input Boolean inCheckProtected; + input GlobalScript.SymbolTable inInteractiveSymbolTable; + input Absyn.Msg inMsg; + output FCore.Cache outCache; + output Values.Value outValue; + output GlobalScript.SymbolTable outInteractiveSymbolTable; +algorithm + (outCache,outValue,outInteractiveSymbolTable):= + matchcontinue (inCache,inEnv,className,inCheckProtected,inInteractiveSymbolTable,inMsg) + local + list allClassPaths; + GlobalScript.SymbolTable st; + Absyn.Program p; + Absyn.Msg msg; + FCore.Cache cache; + String ret; + FCore.Graph env; + Boolean b; + + case (cache,env,_,b,(st as GlobalScript.SYMBOLTABLE(ast = p)),msg) + equation + allClassPaths = getAllClassPathsRecursive(className, b, p); + print("Number of classes to check: " + intString(listLength(allClassPaths)) + "\n"); + // print ("All paths: \n" + stringDelimitList(List.map(allClassPaths, Absyn.pathString), "\n") + "\n"); + checkAll(cache, env, allClassPaths, st, msg); + ret = "Number of classes checked: " + intString(listLength(allClassPaths)); + then + (cache,Values.STRING(ret),st); + + case (cache,_,_,_,(st as GlobalScript.SYMBOLTABLE()),_) + equation + ret = stringAppend("Error checking: ", Absyn.pathString(className)); + then + (cache,Values.STRING(ret),st); + end matchcontinue; +end checkAllModelsRecursive; + +function failOrSuccess +"@author adrpo" + input String inStr; + output String outStr; +algorithm + outStr := matchcontinue(inStr) + local Integer res; + case _ + equation + res = System.stringFind(inStr, "successfully"); + true = (res >= 0); + then "OK"; + else "FAILED!"; + end matchcontinue; +end failOrSuccess; + +function checkAll +"@author adrpo + checks all models and returns number of variables and equations" + input FCore.Cache inCache; + input FCore.Graph inEnv; + input list allClasses; + input GlobalScript.SymbolTable inInteractiveSymbolTable; + input Absyn.Msg inMsg; +algorithm + _ := matchcontinue (inCache,inEnv,allClasses,inInteractiveSymbolTable,inMsg) + local + list rest; + Absyn.Path className; + GlobalScript.SymbolTable st; + Absyn.Program p; + Absyn.Msg msg; + FCore.Cache cache; + String str, s; + FCore.Graph env; + Real t1, t2, elapsedTime; + Absyn.ComponentRef cr; + Absyn.Class c; + case (_,_,{},_,_) then (); + + case (cache,env,className::rest,(st as GlobalScript.SYMBOLTABLE(ast = p)),msg) + equation + c = Interactive.getPathedClassInProgram(className, p); + // filter out partial classes + // Absyn.CLASS(partialPrefix = false) = c; // do not filter partial classes + // filter out packages + false = Interactive.isPackage(className, p); + // filter out functions + // false = Interactive.isFunction(cr, p); + // filter out types + false = Interactive.isType(className, p); + print("Checking: " + Dump.unparseClassAttributesStr(c) + " " + Absyn.pathString(className) + "... "); + t1 = clock(); + Flags.setConfigBool(Flags.CHECK_MODEL, true); + (_,Values.STRING(str),_) = checkModel(FCore.emptyCache(), env, className, st, msg); + Flags.setConfigBool(Flags.CHECK_MODEL, false); + (_,Values.STRING(str),_) = checkModel(FCore.emptyCache(), env, className, st, msg); + t2 = clock(); + elapsedTime = t2 - t1; + s = realString(elapsedTime); + print (s + " seconds -> " + failOrSuccess(str) + "\n\t"); + print (System.stringReplace(str, "\n", "\n\t")); + print ("\n"); + checkAll(cache, env, rest, st, msg); + then + (); + + case (cache,env,className::rest,(st as GlobalScript.SYMBOLTABLE(ast = p)),msg) + equation + c = Interactive.getPathedClassInProgram(className, p); + print("Checking skipped: " + Dump.unparseClassAttributesStr(c) + " " + Absyn.pathString(className) + "... \n"); + checkAll(cache, env, rest, st, msg); + then + (); + end matchcontinue; +end checkAll; + +public function buildModelBeast " copy & pasted by: Otto + translates and builds the model by running compiler script on the generated makefile" + input FCore.Cache inCache; + input FCore.Graph inEnv; + input list vals; + input GlobalScript.SymbolTable inInteractiveSymbolTable; + input Absyn.Msg inMsg; + output FCore.Cache outCache; + output GlobalScript.SymbolTable outInteractiveSymbolTable; + output String compileDir; + output String outString1 "className"; + output String outString2 "method"; + output String outString4 "initFileName"; +algorithm + (outCache,outInteractiveSymbolTable,compileDir,outString1,outString2,outString4):= + match (inCache,inEnv,vals,inInteractiveSymbolTable,inMsg) + local + GlobalScript.SymbolTable st,st2; + BackendDAE.BackendDAE indexed_dlow_1; + list libs; + String file_dir,method_str,filenameprefix,s3; + Absyn.Path classname; + Absyn.Program p,p2; + Absyn.Class cdef; + FCore.Graph env; + Values.Value starttime,stoptime,interval,method,tolerance,options; + Absyn.Msg msg; + Absyn.Within win1; + FCore.Cache cache; + SimCode.SimulationSettings simSettings; + + // normal call + case (cache,env,{Values.CODE(Absyn.C_TYPENAME(classname)),_,_,_,_, _,Values.STRING(filenameprefix),_},(st as GlobalScript.SYMBOLTABLE(ast = p as Absyn.PROGRAM())),msg) + equation + _ = Interactive.getPathedClassInProgram(classname,p); + Error.clearMessages() "Clear messages"; + compileDir = System.pwd() + System.pathDelimiter(); + (cache,simSettings) = calculateSimulationSettings(cache,env,vals,st,msg); + (cache,st,_,libs,file_dir,_) + = translateModel(cache,env, classname, st, filenameprefix,true,SOME(simSettings)); + SimCode.SIMULATION_SETTINGS() = simSettings; + //cname_str = Absyn.pathString(classname); + //(cache,init_filename,starttime_r,stoptime_r,interval_r,tolerance_r,method_str,options_str,outputFormat_str) + //= calculateSimulationSettings(cache,env, exp, st, msg, cname_str); + //SimCodeUtil.generateInitData(indexed_dlow_1, classname, filenameprefix, init_filename, starttime_r, stoptime_r, interval_r,tolerance_r,method_str,options_str,outputFormat_str); + if Flags.isSet(Flags.DYN_LOAD) then + Debug.traceln("buildModel: about to compile model " + filenameprefix + ", " + file_dir); + end if; + CevalScript.compileModel(filenameprefix, libs); + if Flags.isSet(Flags.DYN_LOAD) then + Debug.trace("buildModel: Compiling done.\n"); + end if; + // SimCodegen.generateMakefileBeast(makefilename, filenameprefix, libs, file_dir); + _ = getWithinStatement(classname); + CevalScript.compileModel(filenameprefix, libs); + // (p as Absyn.PROGRAM(globalBuildTimes=Absyn.TIMESTAMP(r1,r2))) = Interactive.updateProgram2(p2,p,false); + st2 = st; // Interactive.replaceSymbolTableProgram(st,p); + then + (cache,st2,compileDir,filenameprefix,"",""); + + // failure + else + then + fail(); + end match; +end buildModelBeast; + +protected function getAlgorithms +"Counts the number of Algorithm sections in a class." + input Absyn.Class inClass; + output list outList; +algorithm + outList := match (inClass) + local + list algsList; + list parts; + case Absyn.CLASS(body = Absyn.PARTS(classParts = parts)) + equation + algsList = getAlgorithmsInClassParts(parts); + then + algsList; + // check also the case model extends X end X; + case Absyn.CLASS(body = Absyn.CLASS_EXTENDS(parts = parts)) + equation + algsList = getAlgorithmsInClassParts(parts); + then + algsList; + case Absyn.CLASS(body = Absyn.DERIVED()) then {}; + end match; +end getAlgorithms; + +protected function getAlgorithmsInClassParts +"Helper function to getAlgorithms" + input list inAbsynClassPartLst; + output list outList; +algorithm + outList := matchcontinue (inAbsynClassPartLst) + local + list algsList; + list algs; + list xs; + Absyn.ClassPart cp; + case ((cp as Absyn.ALGORITHMS()) :: xs) + equation + algsList = getAlgorithmsInClassParts(xs); + then + cp::algsList; + case ((_ :: xs)) + equation + algsList = getAlgorithmsInClassParts(xs); + then + algsList; + case ({}) then {}; + end matchcontinue; +end getAlgorithmsInClassParts; + +protected function getNthAlgorithm +"Returns the Nth Algorithm section from a class." + input Absyn.Class inClass; + input Integer inInteger; + output String outString; + protected list algsList; +algorithm + algsList := getAlgorithms(inClass); + outString := getNthAlgorithmInClass(listGet(algsList, inInteger)); +end getNthAlgorithm; + +protected function getNthAlgorithmInClass +"Helper function to getNthAlgorithm." + input Absyn.ClassPart inClassPart; + output String outString; +algorithm + outString := match (inClassPart) + local + String str; + list algs; + case (Absyn.ALGORITHMS(contents = algs)) + equation + str = Dump.unparseAlgorithmStrLst(algs, "\n"); + then + str; + end match; +end getNthAlgorithmInClass; + +protected function getInitialAlgorithms +"Counts the number of Initial Algorithm sections in a class." + input Absyn.Class inClass; + output list outList; +algorithm + outList := match (inClass) + local + list algsList; + list parts; + case Absyn.CLASS(body = Absyn.PARTS(classParts = parts)) + equation + algsList = getInitialAlgorithmsInClassParts(parts); + then + algsList; + // check also the case model extends X end X; + case Absyn.CLASS(body = Absyn.CLASS_EXTENDS(parts = parts)) + equation + algsList = getInitialAlgorithmsInClassParts(parts); + then + algsList; + case Absyn.CLASS(body = Absyn.DERIVED()) then {}; + end match; +end getInitialAlgorithms; + +protected function getInitialAlgorithmsInClassParts +"Helper function to getInitialAlgorithms" + input list inAbsynClassPartLst; + output list outList; +algorithm + outList := matchcontinue (inAbsynClassPartLst) + local + list algsList; + list algs; + list xs; + Absyn.ClassPart cp; + case ((cp as Absyn.INITIALALGORITHMS()) :: xs) + equation + algsList = getInitialAlgorithmsInClassParts(xs); + then + cp::algsList; + case ((_ :: xs)) + equation + algsList = getInitialAlgorithmsInClassParts(xs); + then + algsList; + case ({}) then {}; + end matchcontinue; +end getInitialAlgorithmsInClassParts; + +protected function getNthInitialAlgorithm +"Returns the Nth Initial Algorithm section from a class." + input Absyn.Class inClass; + input Integer inInteger; + output String outString; + protected list algsList; +algorithm + algsList := getInitialAlgorithms(inClass); + outString := getNthInitialAlgorithmInClass(listGet(algsList, inInteger)); +end getNthInitialAlgorithm; + +protected function getNthInitialAlgorithmInClass +"Helper function to getNthInitialAlgorithm." + input Absyn.ClassPart inClassPart; + output String outString; +algorithm + outString := match (inClassPart) + local + String str; + list algs; + case (Absyn.INITIALALGORITHMS(contents = algs)) + equation + str = Dump.unparseAlgorithmStrLst(algs, "\n"); + then + str; + end match; +end getNthInitialAlgorithmInClass; + +protected function getAlgorithmItemsCount +"Counts the number of Algorithm items in a class." + input Absyn.Class inClass; + output Integer outInteger; +algorithm + outInteger := match (inClass) + local + list parts; + Integer count; + case Absyn.CLASS(body = Absyn.PARTS(classParts = parts)) + equation + count = getAlgorithmItemsCountInClassParts(parts); + then + count; + // check also the case model extends X end X; + case Absyn.CLASS(body = Absyn.CLASS_EXTENDS(parts = parts)) + equation + count = getAlgorithmItemsCountInClassParts(parts); + then + count; + case Absyn.CLASS(body = Absyn.DERIVED()) then 0; + end match; +end getAlgorithmItemsCount; + +protected function getAlgorithmItemsCountInClassParts +"Helper function to getAlgorithmItemsCount" + input list inAbsynClassPartLst; + output Integer outInteger; +algorithm + outInteger := matchcontinue (inAbsynClassPartLst) + local + list algs; + list xs; + Integer c1, c2, res; + case (Absyn.ALGORITHMS(contents = algs) :: xs) + equation + c1 = getAlgorithmItemsCountInAlgorithmItems(algs); + c2 = getAlgorithmItemsCountInClassParts(xs); + then + c1 + c2; + case ((_ :: xs)) + equation + res = getAlgorithmItemsCountInClassParts(xs); + then + res; + case ({}) then 0; + end matchcontinue; +end getAlgorithmItemsCountInClassParts; + +protected function getAlgorithmItemsCountInAlgorithmItems +"Helper function to getAlgorithmItemsCountInClassParts" + input list inAbsynAlgorithmItemLst; + output Integer outInteger; +algorithm + outInteger := matchcontinue (inAbsynAlgorithmItemLst) + local + list xs; + Absyn.Algorithm alg; + Integer c1, res; + case (Absyn.ALGORITHMITEM() :: xs) + equation + c1 = getAlgorithmItemsCountInAlgorithmItems(xs); + then + c1 + 1; + case ((_ :: xs)) + equation + res = getAlgorithmItemsCountInAlgorithmItems(xs); + then + res; + case ({}) then 0; + end matchcontinue; +end getAlgorithmItemsCountInAlgorithmItems; + +protected function getNthAlgorithmItem +"Returns the Nth Algorithm Item from a class." + input Absyn.Class inClass; + input Integer inInteger; + output String outString; +algorithm + outString := match (inClass,inInteger) + local + list parts; + String str; + Integer n; + case (Absyn.CLASS(body = Absyn.PARTS(classParts = parts)),n) + equation + str = getNthAlgorithmItemInClassParts(parts,n); + then + str; + // check also the case model extends X end X; + case (Absyn.CLASS(body = Absyn.CLASS_EXTENDS(parts = parts)),n) + equation + str = getNthAlgorithmItemInClassParts(parts,n); + then + str; + end match; +end getNthAlgorithmItem; + +protected function getNthAlgorithmItemInClassParts +"Helper function to getNthAlgorithmItem" + input list inAbsynClassPartLst; + input Integer inInteger; + output String outString; +algorithm + outString := matchcontinue (inAbsynClassPartLst,inInteger) + local + String str; + list algs; + list xs; + Integer n,c1,newn; + case ((Absyn.ALGORITHMS(contents = algs) :: _),n) + equation + str = getNthAlgorithmItemInAlgorithms(algs, n); + then + str; + case ((Absyn.ALGORITHMS(contents = algs) :: xs),n) /* The rule above failed, subtract the number of algorithms in the first section and try with the rest of the classparts */ + equation + c1 = getAlgorithmItemsCountInAlgorithmItems(algs); + newn = n - c1; + str = getNthAlgorithmItemInClassParts(xs, newn); + then + str; + case ((_ :: xs),n) + equation + str = getNthAlgorithmItemInClassParts(xs, n); + then + str; + end matchcontinue; +end getNthAlgorithmItemInClassParts; + +protected function getNthAlgorithmItemInAlgorithms +" This function takes an Algorithm list and an int + and returns the nth algorithm item as String. + If the number is larger than the number of algorithms + in the list, the function fails. Helper function to getNthAlgorithmItemInClassParts." + input list inAbsynAlgorithmItemLst; + input Integer inInteger; + output String outString; +algorithm + outString := matchcontinue (inAbsynAlgorithmItemLst,inInteger) + local + String str; + Absyn.Algorithm alg; + Option cmt; + SourceInfo inf; + list xs; + Integer newn,n; + case ((Absyn.ALGORITHMITEM(algorithm_ = alg, comment = cmt, info = inf) :: _), 1) + equation + str = Dump.unparseAlgorithmStr(Absyn.ALGORITHMITEM(alg, cmt, inf)); + then + str; + case ((_ :: xs),n) + equation + newn = n - 1; + str = getNthAlgorithmItemInAlgorithms(xs, newn); + then + str; + case ({},_) then fail(); + end matchcontinue; +end getNthAlgorithmItemInAlgorithms; + +protected function getInitialAlgorithmItemsCount +"Counts the number of Initial Algorithm items in a class." + input Absyn.Class inClass; + output Integer outInteger; +algorithm + outInteger := match (inClass) + local + list parts; + Integer count; + case Absyn.CLASS(body = Absyn.PARTS(classParts = parts)) + equation + count = getInitialAlgorithmItemsCountInClassParts(parts); + then + count; + // check also the case model extends X end X; + case Absyn.CLASS(body = Absyn.CLASS_EXTENDS(parts = parts)) + equation + count = getInitialAlgorithmItemsCountInClassParts(parts); + then + count; + case Absyn.CLASS(body = Absyn.DERIVED()) then 0; + end match; +end getInitialAlgorithmItemsCount; + +protected function getInitialAlgorithmItemsCountInClassParts +"Helper function to getInitialAlgorithmItemsCount" + input list inAbsynClassPartLst; + output Integer outInteger; +algorithm + outInteger := matchcontinue (inAbsynClassPartLst) + local + list algs; + list xs; + Integer c1, c2, res; + case (Absyn.INITIALALGORITHMS(contents = algs) :: xs) + equation + c1 = getAlgorithmItemsCountInAlgorithmItems(algs); + c2 = getInitialAlgorithmItemsCountInClassParts(xs); + then + c1 + c2; + case ((_ :: xs)) + equation + res = getInitialAlgorithmItemsCountInClassParts(xs); + then + res; + case ({}) then 0; + end matchcontinue; +end getInitialAlgorithmItemsCountInClassParts; + +protected function getNthInitialAlgorithmItem +"Returns the Nth Initial Algorithm Item from a class." + input Absyn.Class inClass; + input Integer inInteger; + output String outString; +algorithm + outString := match (inClass,inInteger) + local + list parts; + String str; + Integer n; + case (Absyn.CLASS(body = Absyn.PARTS(classParts = parts)),n) + equation + str = getNthInitialAlgorithmItemInClassParts(parts,n); + then + str; + // check also the case model extends X end X; + case (Absyn.CLASS(body = Absyn.CLASS_EXTENDS(parts = parts)),n) + equation + str = getNthInitialAlgorithmItemInClassParts(parts,n); + then + str; + end match; +end getNthInitialAlgorithmItem; + +protected function getNthInitialAlgorithmItemInClassParts +"Helper function to getNthInitialAlgorithmItem" + input list inAbsynClassPartLst; + input Integer inInteger; + output String outString; +algorithm + outString := matchcontinue (inAbsynClassPartLst,inInteger) + local + String str; + list algs; + list xs; + Integer n,c1,newn; + case ((Absyn.INITIALALGORITHMS(contents = algs) :: _),n) + equation + str = getNthAlgorithmItemInAlgorithms(algs, n); + then + str; + case ((Absyn.INITIALALGORITHMS(contents = algs) :: xs),n) /* The rule above failed, subtract the number of algorithms in the first section and try with the rest of the classparts */ + equation + c1 = getAlgorithmItemsCountInAlgorithmItems(algs); + newn = n - c1; + str = getNthInitialAlgorithmItemInClassParts(xs, newn); + then + str; + case ((_ :: xs),n) + equation + str = getNthInitialAlgorithmItemInClassParts(xs, n); + then + str; + end matchcontinue; +end getNthInitialAlgorithmItemInClassParts; + +protected function getEquations +"Counts the number of Equation sections in a class." + input Absyn.Class inClass; + output list outList; +algorithm + outList := match (inClass) + local + list eqsList; + list parts; + case Absyn.CLASS(body = Absyn.PARTS(classParts = parts)) + equation + eqsList = getEquationsInClassParts(parts); + then + eqsList; + // check also the case model extends X end X; + case Absyn.CLASS(body = Absyn.CLASS_EXTENDS(parts = parts)) + equation + eqsList = getEquationsInClassParts(parts); + then + eqsList; + case Absyn.CLASS(body = Absyn.DERIVED()) then {}; + end match; +end getEquations; + +protected function getEquationsInClassParts +"Helper function to getEquations" + input list inAbsynClassPartLst; + output list outList; +algorithm + outList := matchcontinue (inAbsynClassPartLst) + local + list eqsList; + list eqs; + list xs; + Absyn.ClassPart cp; + case ((cp as Absyn.EQUATIONS()) :: xs) + equation + eqsList = getEquationsInClassParts(xs); + then + cp::eqsList; + case ((_ :: xs)) + equation + eqsList = getEquationsInClassParts(xs); + then + eqsList; + case ({}) then {}; + end matchcontinue; +end getEquationsInClassParts; + +protected function getNthEquation +"Returns the Nth Equation section from a class." + input Absyn.Class inClass; + input Integer inInteger; + output String outString; + protected list eqsList; +algorithm + eqsList := getEquations(inClass); + outString := getNthEquationInClass(listGet(eqsList, inInteger)); +end getNthEquation; + +protected function getNthEquationInClass +"Helper function to getNthEquation" + input Absyn.ClassPart inClassPart; + output String outString; +algorithm + outString := match (inClassPart) + local + String str; + list eqs; + case (Absyn.EQUATIONS(contents = eqs)) + equation + str = Dump.unparseEquationItemStrLst(eqs, "\n"); + then + str; + end match; +end getNthEquationInClass; + +protected function getInitialEquations +"Counts the number of Initial Equation sections in a class." + input Absyn.Class inClass; + output list outList; +algorithm + outList := match (inClass) + local + list eqsList; + list parts; + case Absyn.CLASS(body = Absyn.PARTS(classParts = parts)) + equation + eqsList = getInitialEquationsInClassParts(parts); + then + eqsList; + // check also the case model extends X end X; + case Absyn.CLASS(body = Absyn.CLASS_EXTENDS(parts = parts)) + equation + eqsList = getInitialEquationsInClassParts(parts); + then + eqsList; + case Absyn.CLASS(body = Absyn.DERIVED()) then {}; + end match; +end getInitialEquations; + +protected function getInitialEquationsInClassParts +"Helper function to getInitialEquations" + input list inAbsynClassPartLst; + output list outList; +algorithm + outList := matchcontinue (inAbsynClassPartLst) + local + list eqsList; + list eqs; + list xs; + Absyn.ClassPart cp; + case ((cp as Absyn.INITIALEQUATIONS()) :: xs) + equation + eqsList = getInitialEquationsInClassParts(xs); + then + cp::eqsList; + case ((_ :: xs)) + equation + eqsList = getInitialEquationsInClassParts(xs); + then + eqsList; + case ({}) then {}; + end matchcontinue; +end getInitialEquationsInClassParts; + +protected function getNthInitialEquation +"Returns the Nth Initial Equation section from a class." + input Absyn.Class inClass; + input Integer inInteger; + output String outString; + protected list eqsList; +algorithm + eqsList := getInitialEquations(inClass); + outString := getNthInitialEquationInClass(listGet(eqsList, inInteger)); +end getNthInitialEquation; + +protected function getNthInitialEquationInClass +"Helper function to getNthInitialEquation." + input Absyn.ClassPart inClassPart; + output String outString; +algorithm + outString := match (inClassPart) + local + String str; + list eqs; + case (Absyn.INITIALEQUATIONS(contents = eqs)) + equation + str = Dump.unparseEquationItemStrLst(eqs, "\n"); + then + str; + end match; +end getNthInitialEquationInClass; + +protected function getEquationItemsCount +"Counts the number of Equation items in a class." + input Absyn.Class inClass; + output Integer outInteger; +algorithm + outInteger := match (inClass) + local + list parts; + Integer count; + case Absyn.CLASS(body = Absyn.PARTS(classParts = parts)) + equation + count = getEquationItemsCountInClassParts(parts); + then + count; + // check also the case model extends X end X; + case Absyn.CLASS(body = Absyn.CLASS_EXTENDS(parts = parts)) + equation + count = getEquationItemsCountInClassParts(parts); + then + count; + case Absyn.CLASS(body = Absyn.DERIVED()) then 0; + end match; +end getEquationItemsCount; + +protected function getEquationItemsCountInClassParts +"Helper function to getEquationItemsCount" + input list inAbsynClassPartLst; + output Integer outInteger; +algorithm + outInteger := matchcontinue (inAbsynClassPartLst) + local + list eqs; + list xs; + Integer c1, c2, res; + case (Absyn.EQUATIONS(contents = eqs) :: xs) + equation + c1 = getEquationItemsCountInEquationItems(eqs); + c2 = getEquationItemsCountInClassParts(xs); + then + c1 + c2; + case ((_ :: xs)) + equation + res = getEquationItemsCountInClassParts(xs); + then + res; + case ({}) then 0; + end matchcontinue; +end getEquationItemsCountInClassParts; + +protected function getEquationItemsCountInEquationItems +"Helper function to getEquationItemsCountInClassParts" + input list inAbsynEquationItemLst; + output Integer outInteger; +algorithm + outInteger := matchcontinue (inAbsynEquationItemLst) + local + list xs; + Absyn.Equation eq; + Integer c1, res; + case (Absyn.EQUATIONITEM() :: xs) + equation + c1 = getEquationItemsCountInEquationItems(xs); + then + c1 + 1; + case ((_ :: xs)) + equation + res = getEquationItemsCountInEquationItems(xs); + then + res; + case ({}) then 0; + end matchcontinue; +end getEquationItemsCountInEquationItems; + +protected function getNthEquationItem +"Returns the Nth Equation Item from a class." + input Absyn.Class inClass; + input Integer inInteger; + output String outString; +algorithm + outString := match (inClass,inInteger) + local + list parts; + String str; + Integer n; + case (Absyn.CLASS(body = Absyn.PARTS(classParts = parts)),n) + equation + str = getNthEquationItemInClassParts(parts,n); + then + str; + // check also the case model extends X end X; + case (Absyn.CLASS(body = Absyn.CLASS_EXTENDS(parts = parts)),n) + equation + str = getNthEquationItemInClassParts(parts,n); + then + str; + end match; +end getNthEquationItem; + +protected function getNthEquationItemInClassParts +"Helper function to getNthEquationItem" + input list inAbsynClassPartLst; + input Integer inInteger; + output String outString; +algorithm + outString := matchcontinue (inAbsynClassPartLst,inInteger) + local + String str; + list eqs; + list xs; + Integer n,c1,newn; + case ((Absyn.EQUATIONS(contents = eqs) :: _),n) + equation + str = getNthEquationItemInEquations(eqs, n); + then + str; + case ((Absyn.EQUATIONS(contents = eqs) :: xs),n) /* The rule above failed, subtract the number of equations in the first section and try with the rest of the classparts */ + equation + c1 = getEquationItemsCountInEquationItems(eqs); + newn = n - c1; + str = getNthEquationItemInClassParts(xs, newn); + then + str; + case ((_ :: xs),n) + equation + str = getNthEquationItemInClassParts(xs, n); + then + str; + end matchcontinue; +end getNthEquationItemInClassParts; + +protected function getNthEquationItemInEquations +" This function takes an Equation list and an int + and returns the nth Equation item as String. + If the number is larger than the number of algorithms + in the list, the function fails. Helper function to getNthEquationItemInClassParts." + input list inAbsynEquationItemLst; + input Integer inInteger; + output String outString; +algorithm + outString := matchcontinue (inAbsynEquationItemLst,inInteger) + local + String str; + Absyn.Equation eq; + list xs; + Integer newn,n; + case ((Absyn.EQUATIONITEM(equation_ = eq) :: _), 1) + equation + str = Dump.unparseEquationStr(eq); + str = stringAppend(str, ";"); + str = System.trim(str, " "); + then + str; + case ((_ :: xs),n) + equation + newn = n - 1; + str = getNthEquationItemInEquations(xs, newn); + then + str; + case ({},_) then fail(); + end matchcontinue; +end getNthEquationItemInEquations; + +protected function getInitialEquationItemsCount +"Counts the number of Initial Equation items in a class." + input Absyn.Class inClass; + output Integer outInteger; +algorithm + outInteger := match (inClass) + local + list parts; + Integer count; + case Absyn.CLASS(body = Absyn.PARTS(classParts = parts)) + equation + count = getInitialEquationItemsCountInClassParts(parts); + then + count; + // check also the case model extends X end X; + case Absyn.CLASS(body = Absyn.CLASS_EXTENDS(parts = parts)) + equation + count = getInitialEquationItemsCountInClassParts(parts); + then + count; + case Absyn.CLASS(body = Absyn.DERIVED()) then 0; + end match; +end getInitialEquationItemsCount; + +protected function getInitialEquationItemsCountInClassParts +"Helper function to getInitialEquationItemsCount" + input list inAbsynClassPartLst; + output Integer outInteger; +algorithm + outInteger := matchcontinue (inAbsynClassPartLst) + local + list eqs; + list xs; + Integer c1, c2, res; + case (Absyn.INITIALEQUATIONS(contents = eqs) :: xs) + equation + c1 = getEquationItemsCountInEquationItems(eqs); + c2 = getInitialEquationItemsCountInClassParts(xs); + then + c1 + c2; + case ((_ :: xs)) + equation + res = getInitialEquationItemsCountInClassParts(xs); + then + res; + case ({}) then 0; + end matchcontinue; +end getInitialEquationItemsCountInClassParts; + +protected function getNthInitialEquationItem +"Returns the Nth Initial Equation Item from a class." + input Absyn.Class inClass; + input Integer inInteger; + output String outString; +algorithm + outString := match (inClass,inInteger) + local + list parts; + String str; + Integer n; + case (Absyn.CLASS(body = Absyn.PARTS(classParts = parts)),n) + equation + str = getNthInitialEquationItemInClassParts(parts,n); + then + str; + // check also the case model extends X end X; + case (Absyn.CLASS(body = Absyn.CLASS_EXTENDS(parts = parts)),n) + equation + str = getNthInitialEquationItemInClassParts(parts,n); + then + str; + end match; +end getNthInitialEquationItem; + +protected function getNthInitialEquationItemInClassParts +"Helper function to getNthInitialEquationItem" + input list inAbsynClassPartLst; + input Integer inInteger; + output String outString; +algorithm + outString := matchcontinue (inAbsynClassPartLst,inInteger) + local + String str; + list eqs; + list xs; + Integer n,c1,newn; + case ((Absyn.INITIALEQUATIONS(contents = eqs) :: _),n) + equation + str = getNthEquationItemInEquations(eqs, n); + then + str; + case ((Absyn.INITIALEQUATIONS(contents = eqs) :: xs),n) /* The rule above failed, subtract the number of equations in the first section and try with the rest of the classparts */ + equation + c1 = getEquationItemsCountInEquationItems(eqs); + newn = n - c1; + str = getNthInitialEquationItemInClassParts(xs, newn); + then + str; + case ((_ :: xs),n) + equation + str = getNthInitialEquationItemInClassParts(xs, n); + then + str; + end matchcontinue; +end getNthInitialEquationItemInClassParts; + +protected function getAnnotationCount +"Counts the number of Annotation sections in a class." + input Absyn.Class inClass; + output Integer outInteger; +algorithm + outInteger := match (inClass) + local + list ann; + Integer count; + case Absyn.CLASS(body = Absyn.PARTS(ann = ann)) + then listLength(ann); + // check also the case model extends X end X; + case Absyn.CLASS(body = Absyn.CLASS_EXTENDS(ann = ann)) + then listLength(ann); + case Absyn.CLASS(body = Absyn.DERIVED()) then 0; + end match; +end getAnnotationCount; + +protected function getNthAnnotationString +"Returns the Nth Annotation String from a class." + input Absyn.Class inClass; + input Integer inInteger; + output String outString; +algorithm + outString := match (inClass,inInteger) + local + list anns; + Absyn.Annotation ann; + String str; + Integer n; + case (Absyn.CLASS(body = Absyn.PARTS(ann = anns)),n) + equation + ann = listGet(anns,n); + str = Dump.unparseAnnotation(ann); + str = stringAppend(str, ";"); + str = System.trim(str, " "); + then + str; + // check also the case model extends X end X; + case (Absyn.CLASS(body = Absyn.CLASS_EXTENDS(ann = anns)),n) + equation + ann = listGet(anns,n); + str = Dump.unparseAnnotation(ann); + str = stringAppend(str, ";"); + str = System.trim(str, " "); + then + str; + end match; +end getNthAnnotationString; + +protected function getImportCount +"Counts the number of Import sections in a class." + input Absyn.Class inClass; + output Integer outInteger; +algorithm + outInteger := match (inClass) + local + list parts; + Integer count; + case Absyn.CLASS(body = Absyn.PARTS(classParts = parts)) + equation + count = getImportsInClassParts(parts); + then + count; + // check also the case model extends X end X; + case Absyn.CLASS(body = Absyn.CLASS_EXTENDS(parts = parts)) + equation + count = getImportsInClassParts(parts); + then + count; + case Absyn.CLASS(body = Absyn.DERIVED()) then 0; + end match; +end getImportCount; + +protected function getImportsInClassParts +"Helper function to getImportCount" + input list inAbsynClassPartLst; + output Integer outInteger; +algorithm + outInteger := matchcontinue (inAbsynClassPartLst) + local + list els; + list xs; + Integer c1, c2, res; + case (Absyn.PUBLIC(contents = els) :: xs) + equation + c1 = getImportsInElementItems(els); + c2 = getImportsInClassParts(xs); + then + c1 + c2; + case (Absyn.PROTECTED(contents = els) :: xs) + equation + c1 = getImportsInElementItems(els); + c2 = getImportsInClassParts(xs); + then + c1 + c2; + case ((_ :: xs)) + equation + res = getImportsInClassParts(xs); + then + res; + case ({}) then 0; + end matchcontinue; +end getImportsInClassParts; + +protected function getImportsInElementItems +"Helper function to getImportCount" + input list inAbsynElementItemLst; + output Integer outInteger; +algorithm + outInteger := matchcontinue (inAbsynElementItemLst) + local + Absyn.Import import_; + list els; + Integer c1, res; + case (Absyn.ELEMENTITEM(element = Absyn.ELEMENT(specification = Absyn.IMPORT())) :: els) + equation + c1 = getImportsInElementItems(els); + then + c1 + 1; + case ((_ :: els)) + equation + res = getImportsInElementItems(els); + then + res; + case ({}) then 0; + end matchcontinue; +end getImportsInElementItems; + +protected function getNthImport +"Returns the Nth Import String from a class." + input Absyn.Class inClass; + input Integer inInteger; + output list outValue; +algorithm + outValue := match (inClass,inInteger) + local + list parts; + list vals; + Integer n; + case (Absyn.CLASS(body = Absyn.PARTS(classParts = parts)),n) + equation + vals = getNthImportInClassParts(parts,n); + then + vals; + // check also the case model extends X end X; + case (Absyn.CLASS(body = Absyn.CLASS_EXTENDS(parts = parts)),n) + equation + vals = getNthImportInClassParts(parts,n); + then + vals; + end match; +end getNthImport; + +protected function getNthImportInClassParts +"Helper function to getNthImport" + input list inAbsynClassPartLst; + input Integer inInteger; + output list outValue; +algorithm + outValue := matchcontinue (inAbsynClassPartLst,inInteger) + local + list vals; + list els; + list xs; + Integer n,c1,newn; + case ((Absyn.PUBLIC(contents = els) :: _),n) + equation + vals = getNthImportInElementItems(els, n); + then + vals; + case ((Absyn.PUBLIC(contents = els) :: xs),n) /* The rule above failed, subtract the number of imports in the first section and try with the rest of the classparts */ + equation + c1 = getImportsInElementItems(els); + newn = n - c1; + vals = getNthImportInClassParts(xs, newn); + then + vals; + case ((Absyn.PROTECTED(contents = els) :: _),n) + equation + vals = getNthImportInElementItems(els, n); + then + vals; + case ((Absyn.PROTECTED(contents = els) :: xs),n) /* The rule above failed, subtract the number of imports in the first section and try with the rest of the classparts */ + equation + c1 = getImportsInElementItems(els); + newn = n - c1; + vals = getNthImportInClassParts(xs, newn); + then + vals; + case ((_ :: xs),n) + equation + vals = getNthImportInClassParts(xs, n); + then + vals; + end matchcontinue; +end getNthImportInClassParts; + +protected function getNthImportInElementItems +" This function takes an Element list and an int + and returns the nth import as string. + If the number is larger than the number of annotations + in the list, the function fails. Helper function to getNthImport." + input list inAbsynElementItemLst; + input Integer inInteger; + output list outValue; +algorithm + outValue := matchcontinue (inAbsynElementItemLst,inInteger) + local + list vals; + Absyn.Import import_; + list els; + Integer newn,n; + case ((Absyn.ELEMENTITEM(element = Absyn.ELEMENT(specification = Absyn.IMPORT(import_ = import_))) :: _), 1) + equation + vals = unparseNthImport(import_); + then + vals; + case ((Absyn.ELEMENTITEM(element = Absyn.ELEMENT(specification = Absyn.IMPORT())) :: els), n) + equation + newn = n - 1; + vals = getNthImportInElementItems(els, newn); + then + vals; + case ((_ :: els),n) + equation + vals = getNthImportInElementItems(els, n); + then + vals; + case ({},_) then fail(); + end matchcontinue; +end getNthImportInElementItems; + +public function unparseNthImport +" helperfunction to getNthImport." + input Absyn.Import inImport; + output list outValue; +algorithm + outValue := match (inImport) + local + list vals; + list gi; + String path_str,id; + Absyn.Path path; + case (Absyn.NAMED_IMPORT(name = id,path = path)) + equation + path_str = Absyn.pathString(path); + vals = {Values.STRING(path_str),Values.STRING(id),Values.STRING("named")}; + then + vals; + case (Absyn.QUAL_IMPORT(path = path)) + equation + path_str = Absyn.pathString(path); + vals = {Values.STRING(path_str),Values.STRING(""),Values.STRING("qualified")}; + then + vals; + case (Absyn.UNQUAL_IMPORT(path = path)) + equation + path_str = Absyn.pathString(path); + path_str = stringAppendList({path_str, ".*"}); + vals = {Values.STRING(path_str),Values.STRING(""),Values.STRING("unqualified")}; + then + vals; + case (Absyn.GROUP_IMPORT(prefix = path, groups = gi)) + equation + path_str = Absyn.pathString(path); + id = stringDelimitList(unparseGroupImport(gi),","); + path_str = stringAppendList({path_str,".{",id,"}"}); + vals = {Values.STRING(path_str),Values.STRING(""),Values.STRING("multiple")}; + then + vals; + end match; +end unparseNthImport; + +protected function unparseGroupImport + input list inAbsynGroupImportLst; + output list outList; +algorithm + outList := matchcontinue (inAbsynGroupImportLst) + local + list rest; + list lst; + String str; + case {} then {}; + case (Absyn.GROUP_IMPORT_NAME(name = str) :: rest) + equation + lst = unparseGroupImport(rest); + then + (str::lst); + case ((_ :: rest)) + equation + lst = unparseGroupImport(rest); + then + lst; + end matchcontinue; +end unparseGroupImport; + +public function isShortDefinition +"@auhtor:adrpo + returns true if the class is derived or false otherwise" + input Absyn.Path inPath; + input Absyn.Program inProgram; + output Boolean outBoolean; +algorithm + outBoolean:= + matchcontinue (inPath,inProgram) + local + Absyn.Path path; + Absyn.Program p; + case (path,p) + equation + Absyn.CLASS(body = Absyn.DERIVED()) = Interactive.getPathedClassInProgram(path, p); + then + true; + else false; + end matchcontinue; +end isShortDefinition; + +protected function hasStopTime "For use with getNamedAnnotation" + input Option mod; + output Boolean b; +algorithm + b := match (mod) + local + list arglst; + case (SOME(Absyn.CLASSMOD(elementArgLst = arglst))) + then List.exist(arglst,hasStopTime2); + + end match; +end hasStopTime; + +protected function hasStopTime2 "For use with getNamedAnnotation" + input Absyn.ElementArg arg; + output Boolean b; +algorithm + b := match (arg) + local + + case Absyn.MODIFICATION(path=Absyn.IDENT(name="StopTime")) then true; + else false; + + end match; +end hasStopTime2; + +protected function searchClassNames + input list inVals; + input String inSearchText; + input Boolean inFindInText; + input Absyn.Program inProgram; + output list outVals; +algorithm + outVals := matchcontinue (inVals, inSearchText, inFindInText, inProgram) + local + list valsList; + String str, str1; + Boolean b; + Absyn.Program p, p1; + Absyn.Class absynClass; + Integer position; + list xs; + Values.Value val; + case ((val as Values.CODE(_)) :: xs, str1, true, p) + equation + absynClass = Interactive.getPathedClassInProgram(ValuesUtil.getPath(val), p); + p1 = Absyn.PROGRAM({absynClass},Absyn.TOP()); + /* Don't consider packages for FindInText search */ + false = Interactive.isPackage(ValuesUtil.getPath(val), inProgram); + str = Dump.unparseStr(p1, false); + position = System.stringFind(System.tolower(str), System.tolower(str1)); + true = (position > -1); + valsList = searchClassNames(xs, str1, true, p); + then + val::valsList; + case ((val as Values.CODE(_)) :: xs, str1, b, p) + equation + str = ValuesUtil.valString(val); + position = System.stringFind(System.tolower(str), System.tolower(str1)); + true = (position > -1); + valsList = searchClassNames(xs, str1, b, p); + then + val::valsList; + case ((_ :: xs), str1, b, p) + equation + valsList = searchClassNames(xs, str1, b, p); + then + valsList; + case ({}, _, _, _) then {}; + end matchcontinue; +end searchClassNames; + +protected function makeUsesArray + input tuple> inTpl; + output Values.Value v; +algorithm + v := match inTpl + local + Absyn.Path p; + String pstr,ver; + case ((p,{ver})) + equation + pstr = Absyn.pathString(p); + then ValuesUtil.makeArray({Values.STRING(pstr),Values.STRING(ver)}); + else + equation + Error.addMessage(Error.INTERNAL_ERROR,{"makeUsesArray failed"}); + then fail(); + end match; +end makeUsesArray; + +protected function saveTotalModel + input String filename; + input Absyn.Path classpath; + input GlobalScript.SymbolTable st; + output GlobalScript.SymbolTable outSt; +protected + SCode.Program scodeP; + String str,str1,str2,str3; + NFSCodeEnv.Env env; + SCode.Comment cmt; +algorithm + (scodeP, outSt) := GlobalScriptUtil.symbolTableToSCode(st); + (scodeP, env) := NFSCodeFlatten.flattenClassInProgram(classpath, scodeP); + (NFSCodeEnv.CLASS(cls=SCode.CLASS(cmt=cmt)),_,_) := NFSCodeLookup.lookupClassName(classpath, env, Absyn.dummyInfo); + scodeP := SCode.removeBuiltinsFromTopScope(scodeP); + str := SCodeDump.programStr(scodeP,SCodeDump.defaultOptions); + str1 := Absyn.pathLastIdent(classpath) + "_total"; + str2 := SCodeDump.printCommentStr(cmt); + str2 := if stringEq(str2,"") then "" else (" " + str2); + str3 := SCodeDump.printAnnotationStr(cmt,SCodeDump.defaultOptions); + str3 := if stringEq(str3,"") then "" else (str3 + ";\n"); + str1 := "\nmodel " + str1 + str2 + "\n extends " + Absyn.pathString(classpath) + ";\n" + str3 + "end " + str1 + ";\n"; + System.writeFile(filename, str + str1); +end saveTotalModel; + +protected function getClassInformation +"author: PA + Returns all the possible class information. + changed by adrpo 2006-02-24 (latest 2006-03-14) to return more info and in a different format: + {\"restriction\",\"comment\",\"filename.mo\",{bool,bool,bool},{\"readonly|writable\",int,int,int,int}} + if you like more named attributes, use getClassAttributes API which uses get_class_attributes function + change by sjoelund.se 2014-11-14 to actually be sane. Using the typed API. + " + input Absyn.Path path; + input Absyn.Program p; + output Values.Value res_1; +protected + String name,file,strPartial,strFinal,strEncapsulated,res,cmt,str_readonly,str_sline,str_scol,str_eline,str_ecol; + String dim_str; + Boolean partialPrefix,finalPrefix,encapsulatedPrefix,isReadOnly; + Absyn.Restriction restr; + Absyn.ClassDef cdef; + Absyn.Class c; + Integer sl,sc,el,ec; +algorithm + Absyn.CLASS(name,partialPrefix,finalPrefix,encapsulatedPrefix,restr,cdef,SOURCEINFO(file,isReadOnly,sl,sc,el,ec,_)) := Interactive.getPathedClassInProgram(path, p); + res := Dump.unparseRestrictionStr(restr); + cmt := getClassComment(cdef); + file := Util.testsuiteFriendly(file); + res_1 := Values.TUPLE({ + Values.STRING(res), + Values.STRING(cmt), + Values.BOOL(partialPrefix), + Values.BOOL(finalPrefix), + Values.BOOL(encapsulatedPrefix), + Values.STRING(file), + Values.BOOL(isReadOnly), + Values.INTEGER(sl), + Values.INTEGER(sc), + Values.INTEGER(el), + Values.INTEGER(ec), + getClassDimensions(cdef) + }); +end getClassInformation; + +function getClassDimensions +"return the dimensions of a class + as vector of dimension sizes in a string. + Note: A class can only have dimensions if it is a short class definition." + input Absyn.ClassDef cdef; + output Values.Value v; +algorithm + v := match cdef + local + Absyn.ArrayDim ad; + case(Absyn.DERIVED(typeSpec=Absyn.TPATH(arrayDim=SOME(ad)))) + then ValuesUtil.makeArray(list(Values.STRING(Dump.printSubscriptStr(d)) for d in ad)); + else ValuesUtil.makeArray({}); + end match; +end getClassDimensions; + +function getClassComment "Returns the class comment of a Absyn.ClassDef" + input Absyn.ClassDef inClassDef; + output String outString; +algorithm + outString:= + matchcontinue (inClassDef) + local + String str,res; + Option cmt; + case (Absyn.PARTS(comment = SOME(str))) then str; + case (Absyn.DERIVED(comment = cmt)) + then Interactive.getStringComment2(cmt); + case (Absyn.ENUMERATION(comment = cmt)) + then Interactive.getStringComment2(cmt); + case (Absyn.ENUMERATION(comment = cmt)) + then Interactive.getStringComment2(cmt); + case (Absyn.OVERLOAD(comment = cmt)) + then Interactive.getStringComment2(cmt); + case (Absyn.CLASS_EXTENDS(comment = SOME(str))) then str; + else ""; + end matchcontinue; +end getClassComment; + +function getComponentInfo + input Absyn.Element comp; + input FCore.Graph inEnv; + input Boolean isProtected; + output list vs; +algorithm + vs := match comp + local + SCode.Element c; + Absyn.Path envpath, p_1, p; + String tpname, typename, inout_str, variability_str, dir_str, access, name, comment; + String typeAdStr; + Boolean r_1, b; + Option r; + Absyn.ElementAttributes attr; + Option typeAd; + FCore.Graph env; + list dims, dims1; + Absyn.ArrayDim subs; + Absyn.ElementSpec spec; + + case Absyn.ELEMENT(specification = spec as Absyn.COMPONENTS(attributes = attr as Absyn.ATTR(),typeSpec = Absyn.TPATH(p, _))) + algorithm + typename := matchcontinue () + case () + equation + (_,_,env) = Lookup.lookupClass(FCore.emptyCache(), inEnv, p, false); + SOME(envpath) = FGraph.getScopePath(env); + tpname = Absyn.pathLastIdent(p); + p_1 = Absyn.joinPaths(envpath, Absyn.IDENT(tpname)); + then Absyn.pathString(p_1); + else Absyn.pathString(p); + end matchcontinue; + vs := {}; + + dims1 := list(Dump.printSubscriptStr(sub) for sub in attr.arrayDim); + r_1 := Interactive.keywordReplaceable(comp.redeclareKeywords); + + inout_str := innerOuterStr(comp.innerOuter); + + variability_str := attrVariabilityStr(attr); + dir_str := attrDirectionStr(attr); + + for ci in spec.components loop + (name, comment) := getComponentitemsName(ci); + + dims := match ci + case Absyn.COMPONENTITEM(component=Absyn.COMPONENT(arrayDim=subs)) + then listAppend(list(Dump.printSubscriptStr(sub) for sub in subs), dims1); + end match; + + vs := makeGetComponentsRecord( + className = typename, name = name, comment = comment, + isProtected=isProtected, isReplaceable=r_1, isFinal=comp.finalPrefix, innerOuter=inout_str, isFlow=attr.flowPrefix, + isStream=attr.streamPrefix, variability=variability_str, inputOutput=dir_str, dimensions=dims) :: vs; + end for; + then vs; + end match; +end getComponentInfo; + +function makeGetComponentsRecord + input String className; + input String name; + input String comment; + input Boolean isProtected; + input Boolean isFinal; + input Boolean isFlow; + input Boolean isStream; + input Boolean isReplaceable; + input String variability; + input String innerOuter; + input String inputOutput; + input list dimensions; + output Values.Value v; +algorithm + v := Values.RECORD( + Absyn.QUALIFIED("OpenModelica", Absyn.QUALIFIED("Scripting", Absyn.QUALIFIED("getComponentsTest", Absyn.IDENT("Component")))), + { + Values.STRING(className), + Values.STRING(name), + Values.STRING(comment), + Values.BOOL(isProtected), + Values.BOOL(isFinal), + Values.BOOL(isFlow), + Values.BOOL(isStream), + Values.BOOL(isReplaceable), + Values.STRING(variability), + Values.STRING(innerOuter), + Values.STRING(inputOutput), + ValuesUtil.makeArray(list(Values.STRING(s) for s in dimensions)) + }, + {"className","name","comment","isProtected","isFinal","isFlow","isStream","isReplaceable","variability","innerOuter","inputOutput","dimensions"}, + -1 + ); +end makeGetComponentsRecord; + +function innerOuterStr +"Helper function to getComponentInfo, retrieve the inner outer string." + input Absyn.InnerOuter inInnerOuter; + output String outString; +algorithm + outString:= + match (inInnerOuter) + case Absyn.INNER() then "inner"; + case Absyn.OUTER() then "outer"; + case Absyn.NOT_INNER_OUTER() then ""; + case Absyn.INNER_OUTER() then "inner outer"; + end match; +end innerOuterStr; + + +function attrVariabilityStr +"Helper function to get_component_info, + retrieve variability as a string." + input Absyn.ElementAttributes inElementAttributes; + output String outString; +algorithm + outString:= + match (inElementAttributes) + case (Absyn.ATTR(variability = Absyn.VAR())) then ""; + case (Absyn.ATTR(variability = Absyn.DISCRETE())) then "discrete"; + case (Absyn.ATTR(variability = Absyn.PARAM())) then "parameter"; + case (Absyn.ATTR(variability = Absyn.CONST())) then "constant"; + end match; +end attrVariabilityStr; + +function attrDirectionStr +"Helper function to get_component_info, + retrieve direction as a string." + input Absyn.ElementAttributes inElementAttributes; + output String outString; +algorithm + outString:= + match (inElementAttributes) + case (Absyn.ATTR(direction = Absyn.INPUT())) then "input"; + case (Absyn.ATTR(direction = Absyn.OUTPUT())) then "output"; + case (Absyn.ATTR(direction = Absyn.BIDIR())) then ""; + end match; +end attrDirectionStr; + +function getComponentitemsName + " separated list of all component names and comments (if any)." + input Absyn.ComponentItem ci; + output String name, comment; +algorithm + (name, comment) := match ci + local + String c1,s2; + case Absyn.COMPONENTITEM(component = Absyn.COMPONENT(name = c1),comment = SOME(Absyn.COMMENT(_,SOME(s2)))) + then (c1, s2); + case Absyn.COMPONENTITEM(component = Absyn.COMPONENT(name = c1),comment = NONE()) + then (c1, ""); + end match; +end getComponentitemsName; + +annotation(__OpenModelica_Interface="backend"); +end CevalScriptBackend; diff --git a/Compiler/Script/GlobalScript.mo b/Compiler/Script/GlobalScript.mo index 1a1f547e878..e1c84172bc1 100644 --- a/Compiler/Script/GlobalScript.mo +++ b/Compiler/Script/GlobalScript.mo @@ -40,7 +40,6 @@ encapsulated package GlobalScript public import Absyn; public import DAE; public import FCore; -public import Global; public import SCode; public import Values; diff --git a/Compiler/Script/Interactive.mo b/Compiler/Script/Interactive.mo index c0f3b9d638b..f3d97e73345 100644 --- a/Compiler/Script/Interactive.mo +++ b/Compiler/Script/Interactive.mo @@ -61,11 +61,9 @@ public import Values; // protected imports protected import Builtin; protected import Ceval; -protected import CevalFunction; protected import CevalScript; protected import ClassInf; protected import ClockIndexes; -protected import ComponentReference; protected import Config; protected import Connect; protected import Constants; diff --git a/Compiler/Script/StaticScript.mo b/Compiler/Script/StaticScript.mo index e960949d977..7a64c51ddc8 100644 --- a/Compiler/Script/StaticScript.mo +++ b/Compiler/Script/StaticScript.mo @@ -39,17 +39,20 @@ public import Prefix; protected type Ident = String; -protected import Ceval; -protected import CevalScript; -protected import ClassInf; -protected import ComponentReference; -protected import Error; -protected import ErrorExt; -protected import Expression; -protected import ExpressionSimplify; -protected import Static; -protected import Types; -protected import Values; +protected + +import Ceval; +import CevalScript; +import CevalScriptBackend; +import ClassInf; +import ComponentReference; +import Error; +import ErrorExt; +import Expression; +import ExpressionSimplify; +import Static; +import Types; +import Values; protected function calculateSimulationTimes @@ -95,12 +98,12 @@ algorithm (cache,startTime as DAE.RCONST(rstartTime)) = Static.getOptionalNamedArg(cache, env, SOME(st), impl, "startTime", DAE.T_REAL_DEFAULT, - args, CevalScript.getSimulationOption(inSimOpt, "startTime"), + args, CevalScriptBackend.getSimulationOption(inSimOpt, "startTime"), pre, info); (cache,stopTime as DAE.RCONST(rstopTime)) = Static.getOptionalNamedArg(cache, env, SOME(st), impl, "stopTime", DAE.T_REAL_DEFAULT, - args, CevalScript.getSimulationOption(inSimOpt, "stopTime"), + args, CevalScriptBackend.getSimulationOption(inSimOpt, "stopTime"), pre, info); intervals = realInt((rstopTime - rstartTime) / rstepTime); @@ -115,17 +118,17 @@ algorithm // fails if stepSize isn't given as argument to buildModel. (cache,startTime) = Static.getOptionalNamedArg(cache, env, SOME(st), impl, "startTime", DAE.T_REAL_DEFAULT, - args, CevalScript.getSimulationOption(inSimOpt, "startTime"), + args, CevalScriptBackend.getSimulationOption(inSimOpt, "startTime"), pre, info); (cache,stopTime) = Static.getOptionalNamedArg(cache, env, SOME(st), impl, "stopTime", DAE.T_REAL_DEFAULT, - args, CevalScript.getSimulationOption(inSimOpt, "stopTime"), + args, CevalScriptBackend.getSimulationOption(inSimOpt, "stopTime"), pre, info); (cache,numberOfIntervals) = Static.getOptionalNamedArg(cache, env, SOME(st), impl, "numberOfIntervals", DAE.T_INTEGER_DEFAULT, - args, CevalScript.getSimulationOption(inSimOpt, "numberOfIntervals"), + args, CevalScriptBackend.getSimulationOption(inSimOpt, "numberOfIntervals"), pre, info); then (cache, startTime, stopTime, numberOfIntervals); @@ -177,48 +180,48 @@ algorithm Values.CODE(Absyn.C_TYPENAME(className)) = CevalScript.evalCodeTypeName(v,env); cname_str = Absyn.pathString(Absyn.unqotePathIdents(className)) "easier than checking if the file system supports UTF-8..."; - defaulSimOpt = CevalScript.buildSimulationOptionsFromModelExperimentAnnotation(st, className, cname_str, defaultOption); + defaulSimOpt = CevalScriptBackend.buildSimulationOptionsFromModelExperimentAnnotation(st, className, cname_str, defaultOption); (cache, startTime, stopTime, numberOfIntervals) = calculateSimulationTimes(inCache, inEnv, inAbsynExpLst, inAbsynNamedArgLst, impl, inSymbolTable, inPrefix, inInfo, defaulSimOpt); (cache,tolerance) = Static.getOptionalNamedArg(cache, env, SOME(st), impl, "tolerance", DAE.T_REAL_DEFAULT, - args, CevalScript.getSimulationOption(defaulSimOpt, "tolerance"), + args, CevalScriptBackend.getSimulationOption(defaulSimOpt, "tolerance"), pre,info); (cache,method) = Static.getOptionalNamedArg(cache, env, SOME(st), impl, "method", DAE.T_STRING_DEFAULT, - args, CevalScript.getSimulationOption(defaulSimOpt, "method"), + args, CevalScriptBackend.getSimulationOption(defaulSimOpt, "method"), pre, info); (cache,fileNamePrefix) = Static.getOptionalNamedArg(cache,env, SOME(st), impl, "fileNamePrefix", DAE.T_STRING_DEFAULT, - args, CevalScript.getSimulationOption(defaulSimOpt, "fileNamePrefix"), + args, CevalScriptBackend.getSimulationOption(defaulSimOpt, "fileNamePrefix"), pre, info); (cache,options) = Static.getOptionalNamedArg(cache, env, SOME(st), impl, "options", DAE.T_STRING_DEFAULT, - args, CevalScript.getSimulationOption(defaulSimOpt, "options"), + args, CevalScriptBackend.getSimulationOption(defaulSimOpt, "options"), pre, info); (cache,outputFormat) = Static.getOptionalNamedArg(cache, env, SOME(st), impl, "outputFormat", DAE.T_STRING_DEFAULT, - args, CevalScript.getSimulationOption(defaulSimOpt, "outputFormat"), + args, CevalScriptBackend.getSimulationOption(defaulSimOpt, "outputFormat"), pre, info); (cache,variableFilter) = Static.getOptionalNamedArg(cache, env, SOME(st), impl, "variableFilter", DAE.T_STRING_DEFAULT, - args, CevalScript.getSimulationOption(defaulSimOpt, "variableFilter"), + args, CevalScriptBackend.getSimulationOption(defaulSimOpt, "variableFilter"), pre, info); (cache,cflags) = Static.getOptionalNamedArg(cache, env, SOME(st), impl, "cflags", DAE.T_STRING_DEFAULT, - args, CevalScript.getSimulationOption(defaulSimOpt, "cflags"), + args, CevalScriptBackend.getSimulationOption(defaulSimOpt, "cflags"), pre, info); (cache,simflags) = Static.getOptionalNamedArg(cache, env, SOME(st), impl, "simflags", DAE.T_STRING_DEFAULT, - args, CevalScript.getSimulationOption(defaulSimOpt, "simflags"), + args, CevalScriptBackend.getSimulationOption(defaulSimOpt, "simflags"), pre, info); then @@ -388,28 +391,28 @@ public function elabCallInteractive "This function elaborates the functions defi case (cache,env,Absyn.CREF_IDENT(name = "simulate"),{Absyn.CREF()},args,_,SOME(st),_,_) /* Fill in rest of defaults here */ equation (cache, simulationArgs) = getSimulationArguments(cache, env, inExps, args, inImplInst, inSymbolTable, inPrefix, info, NONE()); - recordtype = CevalScript.getSimulationResultType(); + recordtype = CevalScriptBackend.getSimulationResultType(); then (cache,Expression.makePureBuiltinCall("simulate",simulationArgs,DAE.T_UNKNOWN_DEFAULT),DAE.PROP(recordtype,DAE.C_VAR()),SOME(st)); case (cache,env,Absyn.CREF_IDENT(name = "simulation"),{Absyn.CREF()},args,_,SOME(st),_,_) /* Fill in rest of defaults here */ equation (cache, simulationArgs) = getSimulationArguments(cache, env, inExps, args, inImplInst, inSymbolTable, inPrefix, info, NONE()); - recordtype = CevalScript.getDrModelicaSimulationResultType(); + recordtype = CevalScriptBackend.getDrModelicaSimulationResultType(); then (cache,Expression.makePureBuiltinCall("simulation",simulationArgs,DAE.T_UNKNOWN_DEFAULT),DAE.PROP(recordtype,DAE.C_VAR()),SOME(st)); case (cache,env,Absyn.CREF_IDENT(name = "linearize"),{Absyn.CREF()},args,_,SOME(st),_,_) /* Fill in rest of defaults here */ equation (cache, simulationArgs) = getSimulationArguments(cache, env, inExps, args, inImplInst, inSymbolTable, inPrefix, info, NONE()); - recordtype = CevalScript.getSimulationResultType(); + recordtype = CevalScriptBackend.getSimulationResultType(); then (cache,Expression.makePureBuiltinCall("linearize",simulationArgs,DAE.T_UNKNOWN_DEFAULT),DAE.PROP(recordtype,DAE.C_VAR()),SOME(st)); case (cache,env,Absyn.CREF_IDENT(name = "optimize"),{Absyn.CREF()},args,_,SOME(st),_,_) /* Fill in rest of defaults here */ equation (cache, simulationArgs) = getSimulationArguments(cache, env, inExps, args, inImplInst, inSymbolTable, inPrefix, info, NONE()); - recordtype = CevalScript.getSimulationResultType(); + recordtype = CevalScriptBackend.getSimulationResultType(); then (cache,Expression.makePureBuiltinCall("optimize",simulationArgs,DAE.T_UNKNOWN_DEFAULT),DAE.PROP(recordtype,DAE.C_VAR()),SOME(st)); diff --git a/Compiler/SimCode/HpcOmSimCode.mo b/Compiler/SimCode/HpcOmSimCode.mo index 6a3052afd51..e84b5e03be0 100644 --- a/Compiler/SimCode/HpcOmSimCode.mo +++ b/Compiler/SimCode/HpcOmSimCode.mo @@ -31,99 +31,98 @@ encapsulated package HpcOmSimCode - public import HashTableCrILst; - public import SimCodeVar; +import SimCodeVar; - public constant HpcOmData emptyHpcomData = HPCOMDATA(NONE(), NONE()); +constant HpcOmData emptyHpcomData = HPCOMDATA(NONE(), NONE()); - public uniontype HpcOmData - record HPCOMDATA - Option> schedules; // - Option hpcOmMemory; - end HPCOMDATA; - end HpcOmData; +uniontype HpcOmData + record HPCOMDATA + Option> schedules; // + Option hpcOmMemory; + end HPCOMDATA; +end HpcOmData; - public uniontype MemoryMap //stores information to organize the memory for the parallel code in an efficient way - record MEMORYMAP_ARRAY - Integer floatArraySize; //array size including state, state der and other float variables that are necessary for code generation - Integer intArraySize; - Integer boolArraySize; - end MEMORYMAP_ARRAY; - record MEMORYMAP_UNIFORM - end MEMORYMAP_UNIFORM; - end MemoryMap; +uniontype MemoryMap //stores information to organize the memory for the parallel code in an efficient way + record MEMORYMAP_ARRAY + Integer floatArraySize; //array size including state, state der and other float variables that are necessary for code generation + Integer intArraySize; + Integer boolArraySize; + end MEMORYMAP_ARRAY; + record MEMORYMAP_UNIFORM + end MEMORYMAP_UNIFORM; +end MemoryMap; - public uniontype CommunicationInfo //stores more detailed information about a communication (edge) - record COMMUNICATION_INFO - list floatVars; //the float, int and boolean variables that have to be transfered - list intVars; - list boolVars; - end COMMUNICATION_INFO; - end CommunicationInfo; +uniontype CommunicationInfo //stores more detailed information about a communication (edge) + record COMMUNICATION_INFO + list floatVars; //the float, int and boolean variables that have to be transfered + list intVars; + list boolVars; + end COMMUNICATION_INFO; +end CommunicationInfo; - public uniontype Task - record SCHEDULED_TASK - Integer compIdx; - Integer numThreads; - Schedule taskSchedule; - end SCHEDULED_TASK; - record CALCTASK //Task which calculates something - Integer weighting; - Integer index; - Real calcTime; - Real timeFinished; - Integer threadIdx; - list eqIdc; - end CALCTASK; - record CALCTASK_LEVEL - list eqIdc; - list nodeIdc; //graph-node indices of same level nodes - Option threadIdx; //an advice which thread should calculate the task - end CALCTASK_LEVEL; - record DEPTASK - Task sourceTask; - Task targetTask; - Boolean outgoing; //true if the dependency is leading to the task of another thread - Integer id; - CommunicationInfo communicationInfo; - end DEPTASK; - record PREFETCHTASK //This task will load variables in the cache - list varIdc; - Integer varArrayidx; - end PREFETCHTASK; - record TASKEMPTY //Dummy Task - end TASKEMPTY; - end Task; +uniontype Task + record SCHEDULED_TASK + Integer compIdx; + Integer numThreads; + Schedule taskSchedule; + end SCHEDULED_TASK; + record CALCTASK //Task which calculates something + Integer weighting; + Integer index; + Real calcTime; + Real timeFinished; + Integer threadIdx; + list eqIdc; + end CALCTASK; + record CALCTASK_LEVEL + list eqIdc; + list nodeIdc; //graph-node indices of same level nodes + Option threadIdx; //an advice which thread should calculate the task + end CALCTASK_LEVEL; + record DEPTASK + Task sourceTask; + Task targetTask; + Boolean outgoing; //true if the dependency is leading to the task of another thread + Integer id; + CommunicationInfo communicationInfo; + end DEPTASK; + record PREFETCHTASK //This task will load variables in the cache + list varIdc; + Integer varArrayidx; + end PREFETCHTASK; + record TASKEMPTY //Dummy Task + end TASKEMPTY; +end Task; - public uniontype TaskList - record PARALLELTASKLIST - list tasks; - end PARALLELTASKLIST; - record SERIALTASKLIST - list tasks; - Boolean masterOnly; //Set to true if only the master thread should calculate the tasks in the list - end SERIALTASKLIST; - end TaskList; +uniontype TaskList + record PARALLELTASKLIST + list tasks; + end PARALLELTASKLIST; + record SERIALTASKLIST + list tasks; + Boolean masterOnly; //Set to true if only the master thread should calculate the tasks in the list + end SERIALTASKLIST; +end TaskList; - //TODO: Use the TaskList for the other schedulers, too - public uniontype Schedule // stores all scheduling-informations - record LEVELSCHEDULE - list tasksOfLevels; //List of tasks solved in the same level in parallel - Boolean useFixedAssignments; //true if the scheduling is fully static -> all tasks need to have a threadIdx - end LEVELSCHEDULE; - record THREADSCHEDULE - array> threadTasks; //List of tasks assigned to the thread <%idx%> - list outgoingDepTasks; //all outgoing dep-tasks -> can be used for example to initialize locks - list scheduledTasks; - array> allCalcTasks; //mapping task idx -> (calc task, reference counter) - end THREADSCHEDULE; - record TASKDEPSCHEDULE - list>> tasks; //topological sorted tasks with - end TASKDEPSCHEDULE; - record EMPTYSCHEDULE // a dummy schedule. used if there is no ODE-system or if the serial code should be produced - TaskList tasks; - end EMPTYSCHEDULE; - end Schedule; +//TODO: Use the TaskList for the other schedulers, too +uniontype Schedule // stores all scheduling-informations + record LEVELSCHEDULE + list tasksOfLevels; //List of tasks solved in the same level in parallel + Boolean useFixedAssignments; //true if the scheduling is fully static -> all tasks need to have a threadIdx + end LEVELSCHEDULE; + record THREADSCHEDULE + array> threadTasks; //List of tasks assigned to the thread <%idx%> + list outgoingDepTasks; //all outgoing dep-tasks -> can be used for example to initialize locks + list scheduledTasks; + array> allCalcTasks; //mapping task idx -> (calc task, reference counter) + end THREADSCHEDULE; + record TASKDEPSCHEDULE + list>> tasks; //topological sorted tasks with + end TASKDEPSCHEDULE; + record EMPTYSCHEDULE // a dummy schedule. used if there is no ODE-system or if the serial code should be produced + TaskList tasks; + end EMPTYSCHEDULE; +end Schedule; annotation(__OpenModelica_Interface="backend"); end HpcOmSimCode; diff --git a/Compiler/SimCode/HpcOmSimCodeMain.mo b/Compiler/SimCode/HpcOmSimCodeMain.mo index 373a8313466..164af6e321b 100644 --- a/Compiler/SimCode/HpcOmSimCodeMain.mo +++ b/Compiler/SimCode/HpcOmSimCodeMain.mo @@ -60,6 +60,7 @@ protected import HpcOmScheduler; protected import Initialization; protected import List; protected import SimCodeUtil; +protected import SimCodeFunctionUtil; protected import System; protected import Util; @@ -147,15 +148,16 @@ algorithm list timeEvents; BackendDAE.StrongComponents allComps, initComps; - HpcOmTaskGraph.TaskGraph taskGraph, taskGraphDae, taskGraphOde, taskGraphEvent, taskGraphOdeSimplified, taskGraphDaeSimplified, taskGraphOdeScheduled, taskGraphDaeScheduled, taskGraphInit; - HpcOmTaskGraph.TaskGraphMeta taskGraphData, taskGraphDataDae, taskGraphDataOde, taskGraphDataEvent, taskGraphDataOdeSimplified, taskGraphDataDaeSimplified, taskGraphDataOdeScheduled, taskGraphDataDaeScheduled, taskGraphDataInit; + HpcOmTaskGraph.TaskGraph taskGraph, taskGraphDae, taskGraphOde, taskGraphZeroFuncs, taskGraphOdeSimplified, taskGraphDaeSimplified, taskGraphZeroFuncSimplified, taskGraphOdeScheduled, taskGraphDaeScheduled, taskGraphZeroFuncScheduled, taskGraphInit; + HpcOmTaskGraph.TaskGraphMeta taskGraphData, taskGraphDataDae, taskGraphDataOde, taskGraphDataZeroFuncs, taskGraphDataOdeSimplified, taskGraphDataDaeSimplified, taskGraphDataZeroFuncSimplified, taskGraphDataOdeScheduled, taskGraphDataDaeScheduled, taskGraphDataZeroFuncScheduled, taskGraphDataInit; String fileName, fileNamePrefix; Integer numProc; list> parallelSets; list> criticalPaths, criticalPathsWoC; Real cpCosts, cpCostsWoC, serTime, parTime, speedUp, speedUpMax; - list scheduledTasksOde, scheduledTasksDae; + list scheduledTasksOde, scheduledTasksDae, scheduledTasksZeroFunc; list scheduledDAENodes; + list zeroFuncsSimEqIdc; //Additional informations to append SimCode list simCodeLiterals; @@ -165,16 +167,14 @@ algorithm list simCodeExternalFunctionIncludes; Boolean taskGraphMetaValid, numFixed; - String taskGraphMetaMessage, criticalPathInfo; + String criticalPathInfo; array> schedulerInfo; //maps each Task to - HpcOmSimCode.Schedule scheduleOde, scheduleDae; + HpcOmSimCode.Schedule scheduleOde, scheduleDae, scheduleZeroFunc; array> eqCompMapping, varCompMapping; Real graphCosts; Integer graphOps; Option backendMapping; Option optTmpMemoryMap; - list eventSystemTaskList; - list>> eventSystemTasks; list equationsForConditions; array> simEqIdxSimEqMapping; @@ -224,11 +224,14 @@ algorithm //dumpSimEqSCCMapping(simeqCompMapping); //dumpSccSimEqMapping(sccSimEqMapping); - SimCodeUtil.execStat("hpcom setup"); + SimCodeFunctionUtil.execStat("hpcom setup"); + + //Get small DAE System (without removed equations) + //------------------------------------------------ + (taskGraph,taskGraphData) = HpcOmTaskGraph.createTaskGraph(inBackendDAE); //Get complete DAE System //----------------------- - (taskGraph,taskGraphData) = HpcOmTaskGraph.createTaskGraph(inBackendDAE); //HpcOmTaskGraph.printTaskGraph(taskGraph); //HpcOmTaskGraph.printTaskGraphMeta(taskGraphData); @@ -236,39 +239,18 @@ algorithm taskGraphDataDae = HpcOmTaskGraph.copyTaskGraphMeta(taskGraphData); (taskGraphDae,taskGraphDataDae) = HpcOmTaskGraph.appendRemovedEquations(inBackendDAE,taskGraphDae,taskGraphDataDae); - fileName = ("taskGraph"+filenamePrefix+"DAE.graphml"); daeSccSimEqMapping = listArray(List.map(SimCodeUtil.getRemovedEquationSimEqSysIdxes(simCode),List.create)); daeSccSimEqMapping = arrayAppend(sccSimEqMapping,daeSccSimEqMapping); schedulerInfo = arrayCreate(arrayLength(taskGraphDae), (-1,-1,-1.0)); - HpcOmTaskGraph.dumpAsGraphMLSccLevel(taskGraphDae, taskGraphDataDae,inBackendDAE, fileName, "", {}, {}, daeSccSimEqMapping, schedulerInfo, HpcOmTaskGraph.GRAPHDUMPOPTIONS(false,false,true,true)); SimCodeUtil.execStat("hpcom create DAE TaskGraph"); - //print("DAE\n"); - //HpcOmTaskGraph.printTaskGraph(taskGraphDae); - //HpcOmTaskGraph.printTaskGraphMeta(taskGraphDataDae); - - - //Get Event System - //---------------- - taskGraphEvent = arrayCopy(taskGraph); - taskGraphDataEvent = HpcOmTaskGraph.copyTaskGraphMeta(taskGraphData); - (taskGraphEvent,taskGraphDataEvent) = HpcOmTaskGraph.getEventSystem(taskGraphEvent,taskGraphDataEvent,inBackendDAE, zeroCrossings, simeqCompMapping); - - fileName = ("taskGraph"+filenamePrefix+"_event.graphml"); - schedulerInfo = arrayCreate(arrayLength(taskGraphEvent), (-1,-1,-1.0)); - HpcOmTaskGraph.dumpAsGraphMLSccLevel(taskGraphEvent, taskGraphDataEvent,inBackendDAE, fileName, "", {}, {}, sccSimEqMapping, schedulerInfo, HpcOmTaskGraph.GRAPHDUMPOPTIONS(false,false,true,true)); - SimCodeUtil.execStat("hpcom create and dump event TaskGraph"); - - HpcOmSimCode.TASKDEPSCHEDULE(tasks=eventSystemTasks) = HpcOmScheduler.createTaskDepSchedule(taskGraphEvent, taskGraphDataEvent, sccSimEqMapping); - _ = List.map(eventSystemTasks, Util.tuple21); - - //Mark all event nodes in the DAE Task Graph - taskGraphData = HpcOmTaskGraph.markSystemComponents(taskGraphEvent, taskGraphDataEvent, (true, false, false), taskGraphData); + _ = checkTaskGraphMetaConsistency(taskGraphDae, taskGraphDataDae, "DAE system"); + SimCodeUtil.execStat("hpcom validate DAE TaskGraph"); //Create Costs //------------ - taskGraphDataDae = HpcOmTaskGraph.estimateCosts(inBackendDAE,taskGraphDataDae); - taskGraphData = HpcOmTaskGraph.createCosts(inBackendDAE, filenamePrefix + "_eqs_prof" , simeqCompMapping, taskGraphData); + taskGraphDataDae = HpcOmTaskGraph.createCosts(inBackendDAE, filenamePrefix + "_eqs_prof" , simeqCompMapping, taskGraphDataDae); + taskGraphData = HpcOmTaskGraph.copyCosts(taskGraphDataDae, taskGraphData); SimCodeUtil.execStat("hpcom create costs"); //print cost estimation infos //outputTimeBenchmark(taskGraphData,inBackendDAE); @@ -278,25 +260,48 @@ algorithm taskGraphOde = arrayCopy(taskGraph); taskGraphDataOde = HpcOmTaskGraph.copyTaskGraphMeta(taskGraphData); (taskGraphOde,taskGraphDataOde) = HpcOmTaskGraph.getOdeSystem(taskGraphOde,taskGraphDataOde,inBackendDAE); - SimCodeUtil.execStat("hpcom create ODE TaskGraph"); + SimCodeFunctionUtil.execStat("hpcom create ODE TaskGraph"); taskGraphMetaValid = HpcOmTaskGraph.validateTaskGraphMeta(taskGraphDataOde, inBackendDAE); - taskGraphMetaMessage = if taskGraphMetaValid then "TaskgraphMeta valid\n" else "TaskgraphMeta invalid\n"; - print(taskGraphMetaMessage); - SimCodeUtil.execStat("hpcom validate TaskGraph"); + if boolNot(taskGraphMetaValid) then + print("TaskgraphMeta ODE invalid\n"); + end if; + SimCodeUtil.execStat("hpcom validate ODE TaskGraph"); //print("ODE Task Graph Informations\n"); //HpcOmTaskGraph.printTaskGraph(taskGraphOde); //HpcOmTaskGraph.printTaskGraphMeta(taskGraphDataOde); //Mark all ODE nodes in the DAE Task Graph - taskGraphData = HpcOmTaskGraph.markSystemComponents(taskGraphOde, taskGraphDataOde, (false, true, false), taskGraphData); + taskGraphDataDae = HpcOmTaskGraph.markSystemComponents(taskGraphOde, taskGraphDataOde, (false, true, false), taskGraphDataDae); + + //Get Zero Funcs System + //--------------------- + taskGraphZeroFuncs = arrayCopy(taskGraphDae); + taskGraphDataZeroFuncs = HpcOmTaskGraph.copyTaskGraphMeta(taskGraphDataDae); + zeroFuncsSimEqIdc = List.map(zeroCrossingsEquations, SimCodeUtil.simEqSystemIndex); + (taskGraphZeroFuncs,taskGraphDataZeroFuncs) = HpcOmTaskGraph.getZeroFuncsSystem(taskGraphZeroFuncs,taskGraphDataZeroFuncs, inBackendDAE, arrayLength(daeSccSimEqMapping), zeroFuncsSimEqIdc, simeqCompMapping); + + fileName = ("taskGraph"+filenamePrefix+"_ZeroFuncs.graphml"); + schedulerInfo = arrayCreate(arrayLength(taskGraphZeroFuncs), (-1,-1,-1.0)); + HpcOmTaskGraph.dumpAsGraphMLSccLevel(taskGraphZeroFuncs, taskGraphDataZeroFuncs, fileName, "", {}, {}, daeSccSimEqMapping, schedulerInfo, HpcOmTaskGraph.GRAPHDUMPOPTIONS(false,false,true,true)); + SimCodeUtil.execStat("hpcom create and dump zeroFuncs TaskGraph"); + + //Mark all event nodes in the DAE Task Graph + taskGraphDataDae = HpcOmTaskGraph.markSystemComponents(taskGraphZeroFuncs, taskGraphDataZeroFuncs, (true, false, false), taskGraphDataDae); + + _ = checkTaskGraphMetaConsistency(taskGraphZeroFuncs, taskGraphDataZeroFuncs, "ZeroFunc system"); + _ = checkEquationCount(taskGraphDataZeroFuncs, "ZeroFunc system", listLength(zeroFuncsSimEqIdc), sccSimEqMapping); //Dump DAE Task Graph //------------------- - fileName = ("taskGraph"+filenamePrefix+".graphml"); - schedulerInfo = arrayCreate(arrayLength(taskGraph), (-1,-1,-1.0)); - HpcOmTaskGraph.dumpAsGraphMLSccLevel(taskGraph, taskGraphData, inBackendDAE, fileName, "", {}, {}, sccSimEqMapping, schedulerInfo, HpcOmTaskGraph.GRAPHDUMPOPTIONS(false,false,true,true)); + //print("DAE\n"); + //HpcOmTaskGraph.printTaskGraph(taskGraphDae); + //HpcOmTaskGraph.printTaskGraphMeta(taskGraphDataDae); + + fileName = ("taskGraph"+filenamePrefix+"DAE.graphml"); + schedulerInfo = arrayCreate(arrayLength(taskGraphDae), (-1,-1,-1.0)); + HpcOmTaskGraph.dumpAsGraphMLSccLevel(taskGraphDae, taskGraphDataDae, fileName, "", {}, {}, daeSccSimEqMapping, schedulerInfo, HpcOmTaskGraph.GRAPHDUMPOPTIONS(false,false,true,true)); SimCodeUtil.execStat("hpcom dump DAE TaskGraph"); //Get critical path @@ -309,7 +314,7 @@ algorithm fileName = ("taskGraph"+filenamePrefix+"ODE.graphml"); schedulerInfo = arrayCreate(arrayLength(taskGraphOde), (-1,-1,-1.0)); SimCodeUtil.execStat("hpcom assign levels / get crit. path"); - HpcOmTaskGraph.dumpAsGraphMLSccLevel(taskGraphOde, taskGraphDataOde,inBackendDAE, fileName, criticalPathInfo, HpcOmTaskGraph.convertNodeListToEdgeTuples(listHead(criticalPaths)), HpcOmTaskGraph.convertNodeListToEdgeTuples(listHead(criticalPathsWoC)), sccSimEqMapping, schedulerInfo, HpcOmTaskGraph.GRAPHDUMPOPTIONS(true,false,true,true)); + HpcOmTaskGraph.dumpAsGraphMLSccLevel(taskGraphOde, taskGraphDataOde, fileName, criticalPathInfo, HpcOmTaskGraph.convertNodeListToEdgeTuples(listHead(criticalPaths)), HpcOmTaskGraph.convertNodeListToEdgeTuples(listHead(criticalPathsWoC)), sccSimEqMapping, schedulerInfo, HpcOmTaskGraph.GRAPHDUMPOPTIONS(true,false,true,true)); SimCodeUtil.execStat("hpcom dump ODE TaskGraph"); if Flags.isSet(Flags.HPCOM_DUMP) then @@ -320,15 +325,17 @@ algorithm //----------------------------- scheduledTasksDae = {}; (scheduledTasksOde,_) = HpcOmEqSystems.parallelizeTornSystems(taskGraphOde,taskGraphDataOde,sccSimEqMapping,simVarMapping,inBackendDAE); + scheduledTasksZeroFunc = {}; //Apply filters //------------- (taskGraphDaeSimplified,taskGraphDataDaeSimplified) = (taskGraphDae,taskGraphDataDae); (taskGraphOdeSimplified,taskGraphDataOdeSimplified) = applyGRS(taskGraphOde,taskGraphDataOde, sccSimEqMapping, inBackendDAE); + (taskGraphZeroFuncSimplified,taskGraphDataZeroFuncSimplified) = (taskGraphZeroFuncs,taskGraphDataZeroFuncs); SimCodeUtil.execStat("hpcom GRS"); fileName = ("taskGraph"+filenamePrefix+"ODE_merged.graphml"); - HpcOmTaskGraph.dumpAsGraphMLSccLevel(taskGraphOdeSimplified, taskGraphDataOdeSimplified, inBackendDAE, fileName, criticalPathInfo, HpcOmTaskGraph.convertNodeListToEdgeTuples(listHead(criticalPaths)), HpcOmTaskGraph.convertNodeListToEdgeTuples(listHead(criticalPathsWoC)), sccSimEqMapping, schedulerInfo, HpcOmTaskGraph.GRAPHDUMPOPTIONS(true,false,true,true)); + HpcOmTaskGraph.dumpAsGraphMLSccLevel(taskGraphOdeSimplified, taskGraphDataOdeSimplified, fileName, criticalPathInfo, HpcOmTaskGraph.convertNodeListToEdgeTuples(listHead(criticalPaths)), HpcOmTaskGraph.convertNodeListToEdgeTuples(listHead(criticalPathsWoC)), sccSimEqMapping, schedulerInfo, HpcOmTaskGraph.GRAPHDUMPOPTIONS(true,false,true,true)); SimCodeUtil.execStat("hpcom dump simplified TaskGraph"); if Flags.isSet(Flags.HPCOM_DUMP) then @@ -340,8 +347,9 @@ algorithm numProc = Flags.getConfigInt(Flags.NUM_PROC); (numProc,_) = setNumProc(numProc,cpCostsWoC,taskGraphDataOde);//in case n-flag is not set - (scheduleDae,simCode,taskGraphDaeScheduled,taskGraphDataDaeScheduled,sccSimEqMapping) = createSchedule(taskGraphDaeSimplified,taskGraphDataDaeSimplified,daeSccSimEqMapping,simVarMapping,filenamePrefix,numProc,simCode,scheduledTasksDae,"DAE system"); - (scheduleOde,simCode,taskGraphOdeScheduled,taskGraphDataOdeScheduled,sccSimEqMapping) = createSchedule(taskGraphOdeSimplified,taskGraphDataOdeSimplified,sccSimEqMapping,simVarMapping,filenamePrefix,numProc,simCode,scheduledTasksOde,"ODE system"); + (scheduleDae,simCode,taskGraphDaeScheduled,taskGraphDataDaeScheduled,sccSimEqMapping) = createSchedule(taskGraphDaeSimplified,taskGraphDataDaeSimplified,daeSccSimEqMapping,simVarMapping,filenamePrefix,numProc,simCode,scheduledTasksDae,"DAE system",Flags.getConfigString(Flags.HPCOM_SCHEDULER)); + (scheduleOde,simCode,taskGraphOdeScheduled,taskGraphDataOdeScheduled,sccSimEqMapping) = createSchedule(taskGraphOdeSimplified,taskGraphDataOdeSimplified,sccSimEqMapping,simVarMapping,filenamePrefix,numProc,simCode,scheduledTasksOde,"ODE system",Flags.getConfigString(Flags.HPCOM_SCHEDULER)); + (scheduleZeroFunc,simCode,taskGraphZeroFuncScheduled,taskGraphDataZeroFuncScheduled,sccSimEqMapping) = createSchedule(taskGraphZeroFuncSimplified,taskGraphDataZeroFuncSimplified,daeSccSimEqMapping,simVarMapping,filenamePrefix,numProc,simCode,scheduledTasksZeroFunc,"ZeroFunc system",Flags.getConfigString(Flags.HPCOM_SCHEDULER)); SimCode.SIMCODE( modelInfo, simCodeLiterals, simCodeRecordDecls, simCodeExternalFunctionIncludes, allEquations, odeEquations, algebraicEquations, partitionsKind, baseClocks, useHomotopy, initialEquations, removedInitialEquations, startValueEquations, @@ -354,12 +362,11 @@ algorithm numProc = Flags.getConfigInt(Flags.NUM_PROC); criticalPathInfo = HpcOmScheduler.analyseScheduledTaskGraph(scheduleOde,numProc,taskGraphOdeScheduled,taskGraphDataOdeScheduled,"ODE system"); schedulerInfo = HpcOmScheduler.convertScheduleStrucToInfo(scheduleOde,arrayLength(taskGraphOdeScheduled)); - SimCodeUtil.execStat("hpcom create schedule"); + SimCodeFunctionUtil.execStat("hpcom create schedule"); fileName = ("taskGraph"+filenamePrefix+"ODE_schedule.graphml"); - HpcOmTaskGraph.dumpAsGraphMLSccLevel(taskGraphOdeScheduled, taskGraphDataOdeScheduled, inBackendDAE, fileName, criticalPathInfo, HpcOmTaskGraph.convertNodeListToEdgeTuples(listHead(criticalPaths)), HpcOmTaskGraph.convertNodeListToEdgeTuples(listHead(criticalPathsWoC)), sccSimEqMapping, schedulerInfo, HpcOmTaskGraph.GRAPHDUMPOPTIONS(true,false,true,true)); + HpcOmTaskGraph.dumpAsGraphMLSccLevel(taskGraphOdeScheduled, taskGraphDataOdeScheduled, fileName, criticalPathInfo, HpcOmTaskGraph.convertNodeListToEdgeTuples(listHead(criticalPaths)), HpcOmTaskGraph.convertNodeListToEdgeTuples(listHead(criticalPathsWoC)), sccSimEqMapping, schedulerInfo, HpcOmTaskGraph.GRAPHDUMPOPTIONS(true,false,true,true)); //HpcOmScheduler.printSchedule(scheduleOde); - SimCodeUtil.execStat("hpcom dump schedule TaskGraph"); if Flags.isSet(Flags.HPCOM_DUMP) then @@ -372,16 +379,16 @@ algorithm //HpcOmTaskGraph.printTaskGraphMeta(taskGraphDataScheduled); checkOdeSystemSize(taskGraphDataOdeScheduled,odeEquations); - SimCodeUtil.execStat("hpcom check ODE system size"); + SimCodeFunctionUtil.execStat("hpcom check ODE system size"); //Create Memory-Map and Sim-Code //------------------------------ (optTmpMemoryMap, varToArrayIndexMapping, varToIndexMapping) = HpcOmMemory.createMemoryMap(modelInfo, varToArrayIndexMapping, varToIndexMapping, taskGraphOdeSimplified, BackendDAEUtil.transposeMatrix(taskGraphOdeSimplified,arrayLength(taskGraphOdeSimplified)), taskGraphDataOdeSimplified, eqs, filenamePrefix, schedulerInfo, scheduleOde, sccSimEqMapping, criticalPaths, criticalPathsWoC, criticalPathInfo, numProc, allComps); //BaseHashTable.dumpHashTable(varToArrayIndexMapping); - SimCodeUtil.execStat("hpcom create memory map"); + SimCodeFunctionUtil.execStat("hpcom create memory map"); - hpcomData = HpcOmSimCode.HPCOMDATA(SOME((scheduleOde, scheduleDae)), optTmpMemoryMap); + hpcomData = HpcOmSimCode.HPCOMDATA(SOME((scheduleOde, scheduleDae, scheduleZeroFunc)), optTmpMemoryMap); simCode = SimCode.SIMCODE( modelInfo, simCodeLiterals, simCodeRecordDecls, simCodeExternalFunctionIncludes, allEquations, odeEquations, algebraicEquations, partitionsKind, baseClocks, useHomotopy, initialEquations, removedInitialEquations, startValueEquations, nominalValueEquations, minValueEquations, maxValueEquations, parameterEquations, removedEquations, algorithmAndEquationAsserts, @@ -391,7 +398,7 @@ algorithm //print("Number of literals post: " + intString(listLength(simCodeLiterals)) + "\n"); - SimCodeUtil.execStat("hpcom other"); + SimCodeFunctionUtil.execStat("hpcom other"); print("HpcOm is still under construction.\n"); then simCode; else equation @@ -419,7 +426,7 @@ algorithm fileName = ("taskGraph"+iFileNamePrefix+"_init.graphml"); schedulerInfo = arrayCreate(arrayLength(tmpTaskGraph), (-1,-1,-1.0)); sccSimEqMapping = arrayCreate(arrayLength(tmpTaskGraph), {}); - HpcOmTaskGraph.dumpAsGraphMLSccLevel(tmpTaskGraph, tmpTaskGraphMeta, initDAE, fileName, "", {}, {}, sccSimEqMapping ,schedulerInfo, HpcOmTaskGraph.GRAPHDUMPOPTIONS(false,false,true,true)); + HpcOmTaskGraph.dumpAsGraphMLSccLevel(tmpTaskGraph, tmpTaskGraphMeta, fileName, "", {}, {}, sccSimEqMapping ,schedulerInfo, HpcOmTaskGraph.GRAPHDUMPOPTIONS(false,false,true,true)); then (); else (); end match; @@ -500,7 +507,7 @@ protected taskGraphT := BackendDAEUtil.transposeMatrix(taskGraph1,arrayLength(taskGraph1)); fileName := ("taskGraphMergeDebug.graphml"); schedulerInfo := arrayCreate(arrayLength(taskGraph1), (-1,-1,-1.0)); - HpcOmTaskGraph.dumpAsGraphMLSccLevel(taskGraph1, taskGraphMeta1, iBackendDAE, fileName, "", {}, {}, iSccSimEqMapping, schedulerInfo, HpcOmTaskGraph.GRAPHDUMPOPTIONS(false,false,true,true)); + HpcOmTaskGraph.dumpAsGraphMLSccLevel(taskGraph1, taskGraphMeta1, fileName, "", {}, {}, iSccSimEqMapping, schedulerInfo, HpcOmTaskGraph.GRAPHDUMPOPTIONS(false,false,true,true)); contractedTasks := arrayCreate(arrayLength(taskGraph1),0); */ @@ -744,24 +751,52 @@ algorithm end GRS_newGraph2; -protected function createSchedule +protected function createSchedule "create a schedule for the given task graph and the given number of processors. +author: mwalther, Waurich TUD" input HpcOmTaskGraph.TaskGraph iTaskGraph; input HpcOmTaskGraph.TaskGraphMeta iTaskGraphMeta; input array> iSccSimEqMapping; input array> iSimVarMapping; input String iFilenamePrefix; - input Integer numProc; + input Integer iNumProc; input SimCode.SimCode iSimCode; input list iScheduledTasks; input String iSystemName; //e.g. "ODE system" or "DAE system" + input String iSchedulerName; + output HpcOmSimCode.Schedule oSchedule; + output SimCode.SimCode oSimCode; + output HpcOmTaskGraph.TaskGraph oTaskGraph; + output HpcOmTaskGraph.TaskGraphMeta oTaskGraphMeta; + output array> oSccSimEqMapping; +protected + list knownScheduler = {"none","level","levelfix","ext","metis","hmet","listr","rand","list","mcp","part","taskdep","tds","bls","sbs"}; + String schedulerName = iSchedulerName; +algorithm + if(boolNot(List.exist1(knownScheduler,stringEq,schedulerName))) then + print("HpcOmScheduler.createSchedule warning: The scheduler '" + iSchedulerName + "' is unknown. The list-scheduling algorithm is used instead for the " + iSystemName + ".\n"); + schedulerName := "list"; + end if; + (oSchedule,oSimCode,oTaskGraph,oTaskGraphMeta,oSccSimEqMapping) := createSchedule1(iTaskGraph, iTaskGraphMeta, iSccSimEqMapping, iSimVarMapping, iFilenamePrefix, iNumProc, iSimCode, iScheduledTasks, iSystemName, schedulerName); +end createSchedule; + +protected function createSchedule1 "check if the given scheduler is known and create it, otherwise fail +author: mwalther, Waurich TUD" + input HpcOmTaskGraph.TaskGraph iTaskGraph; + input HpcOmTaskGraph.TaskGraphMeta iTaskGraphMeta; + input array> iSccSimEqMapping; + input array> iSimVarMapping; + input String iFilenamePrefix; + input Integer iNumProc; + input SimCode.SimCode iSimCode; + input list iScheduledTasks; + input String iSystemName; //e.g. "ODE system" or "DAE system" + input String iSchedulerName; output HpcOmSimCode.Schedule oSchedule; output SimCode.SimCode oSimCode; output HpcOmTaskGraph.TaskGraph oTaskGraph; output HpcOmTaskGraph.TaskGraphMeta oTaskGraphMeta; output array> oSccSimEqMapping; protected - Boolean tried = false; - String flagValue; list lst; array> sccSimEqMap; HpcOmSimCode.Schedule schedule; @@ -769,149 +804,91 @@ protected HpcOmTaskGraph.TaskGraphMeta taskGraphMeta1; SimCode.SimCode simCode; algorithm - (oSchedule,oSimCode,oTaskGraph,oTaskGraphMeta,oSccSimEqMapping) := matchcontinue(iTaskGraph,iTaskGraphMeta,iSccSimEqMapping,iSimVarMapping,iFilenamePrefix,numProc,iSimCode,iScheduledTasks,iSystemName) - case(_,_,_,_,_,_,_,_,_) - equation - true = arrayLength(iTaskGraph) == 0; - tried = true; - print("There nothing to parallize in the " + iSystemName + "!\n"); - schedule = HpcOmScheduler.createEmptySchedule(iTaskGraph,iTaskGraphMeta,iSccSimEqMapping); - then - (schedule,iSimCode,iTaskGraph,iTaskGraphMeta,iSccSimEqMapping); - case(_,_,_,_,_,_,_,_,_) + (oSchedule,oSimCode,oTaskGraph,oTaskGraphMeta,oSccSimEqMapping) := matchcontinue(iTaskGraph,iTaskGraphMeta,iSccSimEqMapping,iSimVarMapping,iFilenamePrefix,iNumProc,iSimCode,iScheduledTasks,iSystemName,iSchedulerName) + case(_,_,_,_,_,_,_,_,_,"none") equation - flagValue = Flags.getConfigString(Flags.HPCOM_SCHEDULER); - true = stringEq(flagValue, "none"); - tried = true; print("Using serial code for the " + iSystemName + "\n"); schedule = HpcOmScheduler.createEmptySchedule(iTaskGraph,iTaskGraphMeta,iSccSimEqMapping); then (schedule,iSimCode,iTaskGraph,iTaskGraphMeta,iSccSimEqMapping); - case(_,_,_,_,_,_,_,_,_) + case(_,_,_,_,_,_,_,_,_,"level") equation - flagValue = Flags.getConfigString(Flags.HPCOM_SCHEDULER); - true = stringEq(flagValue, "level"); - tried = true; print("Using level Scheduler for the " + iSystemName + "\n"); (schedule,taskGraphMeta1) = HpcOmScheduler.createLevelSchedule(iTaskGraph,iTaskGraphMeta,iSccSimEqMapping); then (schedule,iSimCode,iTaskGraph,taskGraphMeta1,iSccSimEqMapping); - case(_,_,_,_,_,_,_,_,_) + case(_,_,_,_,_,_,_,_,_,"levelfix") equation - flagValue = Flags.getConfigString(Flags.HPCOM_SCHEDULER); - true = stringEq(flagValue, "levelfix"); - tried = true; print("Using fixed level Scheduler (experimental) for the " + iSystemName + "\n"); - (schedule,taskGraphMeta1) = HpcOmScheduler.createFixedLevelSchedule(iTaskGraph,iTaskGraphMeta,numProc,iSccSimEqMapping); + (schedule,taskGraphMeta1) = HpcOmScheduler.createFixedLevelSchedule(iTaskGraph,iTaskGraphMeta,iNumProc,iSccSimEqMapping); then (schedule,iSimCode,iTaskGraph,taskGraphMeta1,iSccSimEqMapping); - case(_,_,_,_,_,_,_,_,_) + case(_,_,_,_,_,_,_,_,_,"ext") equation - flagValue = Flags.getConfigString(Flags.HPCOM_SCHEDULER); - true = stringEq(flagValue, "ext"); - tried = true; print("Using external Scheduler for the " + iSystemName + "\n"); - schedule = HpcOmScheduler.createExtSchedule(iTaskGraph, iTaskGraphMeta, numProc, iSccSimEqMapping, iSimVarMapping, "taskGraph" + iFilenamePrefix + "_ext.graphml"); + schedule = HpcOmScheduler.createExtSchedule(iTaskGraph, iTaskGraphMeta, iNumProc, iSccSimEqMapping, iSimVarMapping, "taskGraph" + iFilenamePrefix + "_ext.graphml"); then (schedule,iSimCode,iTaskGraph,iTaskGraphMeta,iSccSimEqMapping); - case(_,_,_,_,_,_,_,_,_) + case(_,_,_,_,_,_,_,_,_,"metis") equation - flagValue = Flags.getConfigString(Flags.HPCOM_SCHEDULER); - true = stringEq(flagValue, "metis"); - tried = true; print("Using METIS Scheduler for the " + iSystemName + "\n"); - schedule = HpcOmScheduler.createMetisSchedule(iTaskGraph, iTaskGraphMeta, numProc, iSccSimEqMapping, iSimVarMapping); + schedule = HpcOmScheduler.createMetisSchedule(iTaskGraph, iTaskGraphMeta, iNumProc, iSccSimEqMapping, iSimVarMapping); then (schedule,iSimCode,iTaskGraph,iTaskGraphMeta,iSccSimEqMapping); - case(_,_,_,_,_,_,_,_,_) + case(_,_,_,_,_,_,_,_,_,"hmet") equation - flagValue = Flags.getConfigString(Flags.HPCOM_SCHEDULER); - true = stringEq(flagValue, "hmet"); - tried = true; print("Using hMETIS Scheduler for the " + iSystemName + "\n"); - schedule = HpcOmScheduler.createHMetisSchedule(iTaskGraph, iTaskGraphMeta, numProc, iSccSimEqMapping,iSimVarMapping); + schedule = HpcOmScheduler.createHMetisSchedule(iTaskGraph, iTaskGraphMeta, iNumProc, iSccSimEqMapping,iSimVarMapping); then (schedule,iSimCode,iTaskGraph,iTaskGraphMeta,iSccSimEqMapping); - case(_,_,_,_,_,_,_,_,_) + case(_,_,_,_,_,_,_,_,_,"listr") equation - flagValue = Flags.getConfigString(Flags.HPCOM_SCHEDULER); - true = stringEq(flagValue, "listr"); - tried = true; print("Using list reverse Scheduler for the " + iSystemName + "\n"); - schedule = HpcOmScheduler.createListScheduleReverse(iTaskGraph,iTaskGraphMeta,numProc,iSccSimEqMapping, iSimVarMapping); + schedule = HpcOmScheduler.createListScheduleReverse(iTaskGraph,iTaskGraphMeta,iNumProc,iSccSimEqMapping, iSimVarMapping); then (schedule,iSimCode,iTaskGraph,iTaskGraphMeta,iSccSimEqMapping); - case(_,_,_,_,_,_,_,_,_) + case(_,_,_,_,_,_,_,_,_,"rand") equation - flagValue = Flags.getConfigString(Flags.HPCOM_SCHEDULER); - true = stringEq(flagValue, "rand"); - tried = true; print("Using Random Scheduler for the " + iSystemName + "\n"); - schedule = HpcOmScheduler.createRandomSchedule(iTaskGraph, iTaskGraphMeta, numProc, iSccSimEqMapping, iSimVarMapping); - then (schedule, iSimCode, iTaskGraph, iTaskGraphMeta, iSccSimEqMapping); - case(_,_,_,_,_,_,_,_,_) + schedule = HpcOmScheduler.createRandomSchedule(iTaskGraph, iTaskGraphMeta, iNumProc, iSccSimEqMapping, iSimVarMapping); + then (schedule,iSimCode,iTaskGraph,iTaskGraphMeta,iSccSimEqMapping); + case(_,_,_,_,_,_,_,_,_,"list") equation - flagValue = Flags.getConfigString(Flags.HPCOM_SCHEDULER); - true = stringEq(flagValue, "list"); - tried = true; print("Using list Scheduler for the " + iSystemName + "\n"); - schedule = HpcOmScheduler.createListSchedule(iTaskGraph,iTaskGraphMeta,numProc,iSccSimEqMapping, iSimVarMapping); + schedule = HpcOmScheduler.createListSchedule(iTaskGraph,iTaskGraphMeta,iNumProc,iSccSimEqMapping, iSimVarMapping); then (schedule,iSimCode,iTaskGraph,iTaskGraphMeta,iSccSimEqMapping); - case(_,_,_,_,_,_,_,_,_) + case(_,_,_,_,_,_,_,_,_,"mcp") equation - flagValue = Flags.getConfigString(Flags.HPCOM_SCHEDULER); - true = stringEq(flagValue, "mcp"); - tried = true; print("Using Modified Critical Path Scheduler for the " + iSystemName + "\n"); - schedule = HpcOmScheduler.createMCPschedule(iTaskGraph,iTaskGraphMeta,numProc,iSccSimEqMapping,iSimVarMapping); + schedule = HpcOmScheduler.createMCPschedule(iTaskGraph,iTaskGraphMeta,iNumProc,iSccSimEqMapping,iSimVarMapping); then (schedule,iSimCode,iTaskGraph,iTaskGraphMeta,iSccSimEqMapping); - case(_,_,_,_,_,_,_,_,_) + case(_,_,_,_,_,_,_,_,_,"part") equation - flagValue = Flags.getConfigString(Flags.HPCOM_SCHEDULER); - true = stringEq(flagValue, "part"); - tried = true; print("Using partition Scheduler for the " + iSystemName + "\n"); - schedule = HpcOmScheduler.createPartSchedule(iTaskGraph,iTaskGraphMeta,numProc,iSccSimEqMapping,iSimVarMapping); + schedule = HpcOmScheduler.createPartSchedule(iTaskGraph,iTaskGraphMeta,iNumProc,iSccSimEqMapping,iSimVarMapping); then (schedule,iSimCode,iTaskGraph,iTaskGraphMeta,iSccSimEqMapping); - case(_,_,_,_,_,_,_,_,_) + case(_,_,_,_,_,_,_,_,_,"taskdep") equation - flagValue = Flags.getConfigString(Flags.HPCOM_SCHEDULER); - true = stringEq(flagValue, "taskdep"); - tried = true; print("Using dynamic task dependencies for the " + iSystemName + "\n"); schedule = HpcOmScheduler.createTaskDepSchedule(iTaskGraph,iTaskGraphMeta,iSccSimEqMapping); then (schedule,iSimCode,iTaskGraph,iTaskGraphMeta,iSccSimEqMapping); - case(_,_,_,_,_,_,_,_,_) + case(_,_,_,_,_,_,_,_,_,"tds") equation - flagValue = Flags.getConfigString(Flags.HPCOM_SCHEDULER); - true = stringEq(flagValue, "tds"); - tried = true; print("Using Task Duplication-based Scheduling for the " + iSystemName + "\n"); - (schedule,simCode,taskGraph1,taskGraphMeta1,sccSimEqMap) = HpcOmScheduler.TDS_schedule(iTaskGraph,iTaskGraphMeta,numProc,iSccSimEqMapping,iSimVarMapping,iSimCode); + (schedule,simCode,taskGraph1,taskGraphMeta1,sccSimEqMap) = HpcOmScheduler.TDS_schedule(iTaskGraph,iTaskGraphMeta,iNumProc,iSccSimEqMapping,iSimVarMapping,iSimCode); then (schedule,simCode,taskGraph1,taskGraphMeta1,sccSimEqMap); - case(_,_,_,_,_,_,_,_,_) + case(_,_,_,_,_,_,_,_,_,"bls") equation - flagValue = Flags.getConfigString(Flags.HPCOM_SCHEDULER); - true = stringEq(flagValue, "bls"); - tried = true; print("Using Balanced Level Scheduling for the " + iSystemName + "\n"); (schedule,taskGraphMeta1) = HpcOmScheduler.createBalancedLevelScheduling(iTaskGraph,iTaskGraphMeta,iSccSimEqMapping); then (schedule,iSimCode,iTaskGraph,taskGraphMeta1,iSccSimEqMapping); - case(_,_,_,_,_,_,_,_,_) + case(_,_,_,_,_,_,_,_,_,"sbs") equation - flagValue = Flags.getConfigString(Flags.HPCOM_SCHEDULER); - true = stringEq(flagValue, "sbs"); - tried = true; print("Using Single Block Scheduling for the " + iSystemName + "\n"); schedule = HpcOmEqSystems.createSingleBlockSchedule(iTaskGraph,iTaskGraphMeta,iScheduledTasks,iSccSimEqMapping); then (schedule,iSimCode,iTaskGraph,iTaskGraphMeta,iSccSimEqMapping); - case(_,_,_,_,_,_,_,_,_) - equation - flagValue = Flags.getConfigString(Flags.HPCOM_SCHEDULER); - false = tried; //we have to prevent that the ODE and DAE system are scheduled with different schedulers - print("HpcOmScheduler.createSchedule warning: The scheduler '" + flagValue + "' is unknown. The list-scheduling algorithm is used instead for the " + iSystemName + ".\n"); - schedule = HpcOmScheduler.createListSchedule(iTaskGraph,iTaskGraphMeta,numProc,iSccSimEqMapping,iSimVarMapping); - then (schedule,iSimCode,iTaskGraph,iTaskGraphMeta,iSccSimEqMapping); else equation print("HpcOmSimCode.createSchedule failed!\n"); - then fail(); + schedule = HpcOmScheduler.createEmptySchedule(iTaskGraph,iTaskGraphMeta,iSccSimEqMapping); + then (schedule,iSimCode,iTaskGraph,iTaskGraphMeta,iSccSimEqMapping); end matchcontinue; -end createSchedule; +end createSchedule1; + protected function convertToSccSimEqMapping "function convertToSccSimEqMapping author: marcusw @@ -1287,13 +1264,64 @@ algorithm targetSize := listLength(List.flatten(iOdeEqs)); oIsCorrect := intEq(targetSize,actualSize); if(oIsCorrect) then - print("the ODE-system size is correct("+intString(actualSize)+")\n"); + //print("the ODE-system size is correct("+intString(actualSize)+")\n"); else print("the size should be "+intString(targetSize)+" but it is "+intString(actualSize)+"!\n"); print("the ODE-system is NOT correct\n"); end if; end checkOdeSystemSize; +protected function checkTaskGraphMetaConsistency "Check if the number of nodes in task graph meta is equal to the number of nodes in the task graph. +author:marcusw" + input HpcOmTaskGraph.TaskGraph iTaskGraph; + input HpcOmTaskGraph.TaskGraphMeta iTaskGraphMeta; + input String iSystemName; + output Boolean oIsCorrect; +protected + Integer numberOfNodes; + array> inComps; +algorithm + numberOfNodes := arrayLength(iTaskGraph); + HpcOmTaskGraph.TASKGRAPHMETA(inComps=inComps) := iTaskGraphMeta; + if(boolNot(intEq(numberOfNodes, arrayLength(inComps)))) then + print("the number of nodes in the " + iSystemName + " task graph ("+intString(numberOfNodes)+") is distinguished from the number of nodes in task graph meta (" + intString(arrayLength(inComps)) + ")\n"); + oIsCorrect := false; + else + oIsCorrect := true; + end if; +end checkTaskGraphMetaConsistency; + +protected function checkEquationCount "Check if the number of equations in the nodes of the task graph is equal to the given expected number. +author:marcusw" + input HpcOmTaskGraph.TaskGraphMeta iTaskGraphMeta; + input String iSystemName; + input Integer iExpectedNumberOfEqs; + input array> iSccSimEqMapping; + output Boolean oIsCorrect; +protected + Integer inCompsIdx, eqCount; + array> inComps; + list comps; + list compEqs; +algorithm + HpcOmTaskGraph.TASKGRAPHMETA(inComps=inComps) := iTaskGraphMeta; + inCompsIdx := arrayLength(inComps); + eqCount := 0; + while intGt(inCompsIdx, 0) loop + comps := arrayGet(inComps, inCompsIdx); + for comp in comps loop + compEqs := arrayGet(iSccSimEqMapping, comp); + eqCount := eqCount + listLength(compEqs); + end for; + inCompsIdx := inCompsIdx - 1; + end while; + + oIsCorrect := intEq(iExpectedNumberOfEqs, eqCount); + if(boolNot(oIsCorrect)) then + print("the number of equations in the " + iSystemName + " task graph ("+intString(eqCount)+") is distinguished from the expected number of equations (" + intString(iExpectedNumberOfEqs) + ")\n"); + end if; +end checkEquationCount; + /* protected function repeatScheduleWithOtherNumProc"checks if the scheduling with the given numProc is fine. if n=auto, more cores are available and more speedup could be achieved repeat schedule with increased num of procs. diff --git a/Compiler/SimCode/SerializeModelInfo.mo b/Compiler/SimCode/SerializeModelInfo.mo index c38100be93b..a2273cf630a 100644 --- a/Compiler/SimCode/SerializeModelInfo.mo +++ b/Compiler/SimCode/SerializeModelInfo.mo @@ -54,6 +54,7 @@ import crefStr = ComponentReference.printComponentRefStrFixDollarDer; import expStr = ExpressionDump.printExpStr; import List; import SimCodeUtil; +import SimCodeFunctionUtil; import SCodeDump; import Util; @@ -778,7 +779,7 @@ algorithm File.write(file, ",\"section\":\""); File.write(file, section); File.write(file, "\",\"tag\":\"container\",\"display\":\"mixed\",\"defines\":["); - serializeUses(file,list(SimCodeUtil.varName(v) for v in eq.discVars)); + serializeUses(file,list(SimCodeFunctionUtil.varName(v) for v in eq.discVars)); File.write(file, "],\"equation\":["); serializeEquationIndex(file,eq.cont); list(match () case () equation File.write(file,","); serializeEquationIndex(file,e); then (); end match for e in eq.discEqs); diff --git a/Compiler/SimCode/SimCodeFunction.mo b/Compiler/SimCode/SimCodeFunction.mo new file mode 100644 index 00000000000..7b7ec69e590 --- /dev/null +++ b/Compiler/SimCode/SimCodeFunction.mo @@ -0,0 +1,182 @@ +/* + * This file is part of OpenModelica. + * + * Copyright (c) 1998-2014, Open Source Modelica Consortium (OSMC), + * c/o Linköpings universitet, Department of Computer and Information Science, + * SE-58183 Linköping, Sweden. + * + * All rights reserved. + * + * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF GPL VERSION 3 LICENSE OR + * THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.2. + * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES + * RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GPL VERSION 3, + * ACCORDING TO RECIPIENTS CHOICE. + * + * The OpenModelica software and the Open Source Modelica + * Consortium (OSMC) Public License (OSMC-PL) are obtained + * from OSMC, either from the above address, + * from the URLs: http://www.ida.liu.se/projects/OpenModelica or + * http://www.openmodelica.org, and in the OpenModelica distribution. + * GNU version 3 is obtained from: http://www.gnu.org/copyleft/gpl.html. + * + * This program is distributed WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH + * IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL. + * + * See the full OSMC Public License conditions for more details. + * + */ + +encapsulated package SimCodeFunction +"The entry points to this module is the translateFunctions fuction." + +// public imports +public +import Absyn; +import DAE; +import HashTableStringToPath; +import Tpl; +import SimCode; + +// protected imports +protected +import BaseHashTable; +import CodegenCFunctions; +import SimCodeFunctionUtil; + +public function translateFunctions " + Entry point to translate Modelica/MetaModelica functions to C functions. + Called from other places in the compiler." + input Absyn.Program program; + input String name; + input Option optMainFunction; + input list idaeElements; + input list metarecordTypes; + input list inIncludes; +algorithm + _ := match (program, name, optMainFunction, idaeElements, metarecordTypes, inIncludes) + local + DAE.Function daeMainFunction; + SimCode.Function mainFunction; + list fns; + list includes, libs, libPaths,includeDirs; + SimCode.MakefileParams makefileParams; + SimCode.FunctionCode fnCode; + list extraRecordDecls; + list literals; + list daeElements; + + case (_, _, SOME(daeMainFunction), daeElements, _, includes) + equation + // Create SimCode.FunctionCode + (daeElements,literals) = SimCodeFunctionUtil.findLiterals(daeMainFunction::daeElements); + (mainFunction::fns, extraRecordDecls, includes, includeDirs, libs,libPaths) = SimCodeFunctionUtil.elaborateFunctions(program, daeElements, metarecordTypes, literals, includes); + SimCodeFunctionUtil.checkValidMainFunction(name, mainFunction); + makefileParams = SimCodeFunctionUtil.createMakefileParams(includeDirs, libs,libPaths, true); + fnCode = SimCode.FUNCTIONCODE(name, SOME(mainFunction), fns, literals, includes, makefileParams, extraRecordDecls); + // Generate code + _ = Tpl.tplString(CodegenCFunctions.translateFunctions, fnCode); + then + (); + case (_, _, NONE(), daeElements, _, includes) + equation + // Create SimCode.FunctionCode + (daeElements,literals) = SimCodeFunctionUtil.findLiterals(daeElements); + (fns, extraRecordDecls, includes, includeDirs, libs,libPaths) = SimCodeFunctionUtil.elaborateFunctions(program, daeElements, metarecordTypes, literals, includes); + makefileParams = SimCodeFunctionUtil.createMakefileParams(includeDirs, libs,libPaths, true); + // remove OpenModelica.threadData.ThreadData + fns = removeThreadDataFunction(fns, {}); + extraRecordDecls = removeThreadDataRecord(extraRecordDecls, {}); + + fnCode = SimCode.FUNCTIONCODE(name, NONE(), fns, literals, includes, makefileParams, extraRecordDecls); + // Generate code + _ = Tpl.tplString(CodegenCFunctions.translateFunctions, fnCode); + then + (); + end match; +end translateFunctions; + +protected function removeThreadDataRecord +"remove OpenModelica.threadData.ThreadData + as is already defined in openmodelica.h" + input list inRecs; + input list inAcc; + output list outRecs; +algorithm + outRecs := match(inRecs, inAcc) + local + Absyn.Path p; + list acc, rest; + SimCode.RecordDeclaration r; + + case ({}, _) then listReverse(inAcc); + + case (SimCode.RECORD_DECL_FULL(name = "OpenModelica_threadData_ThreadData")::rest, _) + equation + acc = removeThreadDataRecord(rest, inAcc); + then + acc; + + case (SimCode.RECORD_DECL_DEF(path = Absyn.QUALIFIED("OpenModelica",Absyn.QUALIFIED("threadData",Absyn.IDENT("ThreadData"))))::rest, _) + equation + acc = removeThreadDataRecord(rest, inAcc); + then + acc; + + case (r::rest, _) + equation + acc = removeThreadDataRecord(rest, r::inAcc); + then + acc; + + end match; +end removeThreadDataRecord; + +protected function removeThreadDataFunction +"remove OpenModelica.threadData.ThreadData + as is already defined in openmodelica.h" + input list inFuncs; + input list inAcc; + output list outFuncs; +algorithm + outFuncs := match(inFuncs, inAcc) + local + Absyn.Path p; + list acc, rest; + SimCode.Function f; + + case ({}, _) then listReverse(inAcc); + + case (SimCode.RECORD_CONSTRUCTOR(name = Absyn.FULLYQUALIFIED(Absyn.QUALIFIED("OpenModelica",Absyn.QUALIFIED("threadData",Absyn.IDENT("ThreadData")))))::rest, _) + equation + acc = removeThreadDataFunction(rest, inAcc); + then + acc; + + case (f::rest, _) + equation + acc = removeThreadDataFunction(rest, f::inAcc); + then + acc; + + end match; +end removeThreadDataFunction; + +public function getCalledFunctionsInFunction +"Goes through the given DAE, finds the given function and collects + the names of the functions called from within those functions" + input Absyn.Path path; + input DAE.FunctionTree funcs; + output list outPaths; +protected + HashTableStringToPath.HashTable ht; +algorithm + ht := HashTableStringToPath.emptyHashTable(); + ht := SimCodeFunctionUtil.getCalledFunctionsInFunction2(path,Absyn.pathStringNoQual(path),ht,funcs); + outPaths := BaseHashTable.hashTableValueList(ht); +end getCalledFunctionsInFunction; + +annotation(__OpenModelica_Interface="backend"); +end SimCodeFunction; diff --git a/Compiler/SimCode/SimCodeFunctionUtil.mo b/Compiler/SimCode/SimCodeFunctionUtil.mo new file mode 100644 index 00000000000..d0aad49d880 --- /dev/null +++ b/Compiler/SimCode/SimCodeFunctionUtil.mo @@ -0,0 +1,2890 @@ +/* + * This file is part of OpenModelica. + * + * Copyright (c) 1998-2014, Open Source Modelica Consortium (OSMC), + * c/o Linköpings universitet, Department of Computer and Information Science, + * SE-58183 Linköping, Sweden. + * + * All rights reserved. + * + * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF GPL VERSION 3 LICENSE OR + * THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.2. + * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES + * RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GPL VERSION 3, + * ACCORDING TO RECIPIENTS CHOICE. + * + * The OpenModelica software and the Open Source Modelica + * Consortium (OSMC) Public License (OSMC-PL) are obtained + * from OSMC, either from the above address, + * from the URLs: http://www.ida.liu.se/projects/OpenModelica or + * http://www.openmodelica.org, and in the OpenModelica distribution. + * GNU version 3 is obtained from: http://www.gnu.org/copyleft/gpl.html. + * + * This program is distributed WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH + * IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL. + * + * See the full OSMC Public License conditions for more details. + * + */ + +encapsulated package SimCodeFunctionUtil "SimCode functions not related to equation systems" + +import DAE; +import HashTableExpToIndex; +import SimCode; + +protected + +import Array; +import BaseHashTable; +import CevalScript; +import ClockIndexes; +import ComponentReference; +import DAEDump; +import DAEUtil; +import Debug; +import Error; +import Expression; +import ExpressionSimplify; +import ExpressionDump; +import Flags; +import GC; +import Graph; +import List; +import Mod; +import SCode; + +public + +public function elementVars +"Used by templates to get a list of variables from a valueblock." + input list ild; + output list vars; +protected + list ld; +algorithm + ld := List.filter(ild, isVarQ); + vars := List.map(ld, daeInOutSimVar); +end elementVars; + +public function crefSubIsScalar +"Used by templates to determine if a component reference's subscripts are + scalar." + input DAE.ComponentRef cref; + output Boolean isScalar; +protected + list subs; +algorithm + subs := ComponentReference.crefSubs(cref); + isScalar := subsToScalar(subs); +end crefSubIsScalar; + +protected function subsToScalar "scalar expression." + input list inExpSubscriptLst; + output Boolean outBoolean; +algorithm + outBoolean := match (inExpSubscriptLst) + local + Boolean b; + list r; + case {} then true; + case (DAE.SLICE() :: _) then false; + case (DAE.WHOLEDIM() :: _) then false; + case (DAE.INDEX() :: r) + equation + b = subsToScalar(r); + then + b; + end match; +end subsToScalar; + +public function crefNoSub +"Used by templates to determine if a component reference has no subscripts." + input DAE.ComponentRef cref; + output Boolean noSub; +algorithm + noSub := not ComponentReference.crefHaveSubs(cref); +end crefNoSub; + +public function inFunctionContext + input SimCode.Context inContext; + output Boolean outInFunction; +algorithm + outInFunction := match inContext + case SimCode.FUNCTION_CONTEXT() then true; + case SimCode.PARALLEL_FUNCTION_CONTEXT() then true; + else false; + end match; +end inFunctionContext; + +public function crefIsScalar + "Whether a component reference is a scalar depends on what context we are in. + If we are generating code for a function, then only crefs without subscripts + are scalar. If we are generating code for simulation though, then crefs with + only constant subscripts are also scalars, since a variable is generated for + each element of an array in the model." + input DAE.ComponentRef cref; + input SimCode.Context context; + output Boolean isScalar; +algorithm + if inFunctionContext(context) then + isScalar := listEmpty(ComponentReference.crefLastSubs(cref)); + else + isScalar := ComponentReference.crefHasScalarSubscripts(cref); + end if; +end crefIsScalar; + +public function buildCrefExpFromAsub +"Used by templates to convert an ASUB expression to a component reference + with subscripts." + input DAE.Exp cref; + input list subs; + output DAE.Exp cRefOut; +algorithm + cRefOut := matchcontinue(cref, subs) + local + DAE.Exp crefExp; + DAE.Type ty; + DAE.ComponentRef crNew; + list indexes; + + case (_, {}) then cref; + case (DAE.CREF(componentRef=crNew, ty=ty), _) + equation + indexes = List.map(subs, Expression.makeIndexSubscript); + crNew = ComponentReference.subscriptCref(crNew, indexes); + crefExp = Expression.makeCrefExp(crNew, ty); + then + crefExp; + end matchcontinue; +end buildCrefExpFromAsub; + +public function incrementInt +"Used by templates to create new integers that are increments of another." + input Integer inInt; + input Integer increment; + output Integer outInt; +algorithm + outInt := inInt + increment; +end incrementInt; + +public function decrementInt +"Used by templates to create new integers that are increments of another." + input Integer inInt; + input Integer decrement; + output Integer outInt; +algorithm + outInt := inInt - decrement; +end decrementInt; + + +public function protectedVars + input list InSimVars; + output list OutSimVars; + algorithm + OutSimVars:= List.filterOnTrue(InSimVars,isNotProtected); +end protectedVars; + +protected function isNotProtected + input SimCodeVar.SimVar simVar; + output Boolean isProtected; +algorithm + SimCodeVar.SIMVAR(isProtected=isProtected) := simVar; + isProtected := not isProtected; +end isNotProtected; + + +public function makeCrefRecordExp +"Helper function to generate records." + input DAE.ComponentRef inCRefRecord; + input DAE.Var inVar; + output DAE.Exp outExp; +algorithm + outExp := match (inCRefRecord, inVar) + local + DAE.ComponentRef cr, cr1; + String name; + DAE.Type tp; + case (cr, DAE.TYPES_VAR(name=name, ty=tp)) + equation + cr1 = ComponentReference.crefPrependIdent(cr, name, {}, tp); + outExp = Expression.makeCrefExp(cr1, tp); + then + outExp; + end match; +end makeCrefRecordExp; + +public function cref2simvar +"Used by templates to find SIMVAR for given cref (to gain representaion index info mainly)." + input DAE.ComponentRef inCref; + input SimCode.SimCode simCode; + output SimCodeVar.SimVar outSimVar; +algorithm + outSimVar := matchcontinue(inCref, simCode) + local + DAE.ComponentRef cref, badcref; + SimCodeVar.SimVar sv; + SimCode.HashTableCrefToSimVar crefToSimVarHT; + String errstr; + + case (cref, SimCode.SIMCODE(crefToSimVarHT = crefToSimVarHT) ) + equation + sv = get(cref, crefToSimVarHT); + then sv; + + case (_, _) + equation + //print("cref2simvar: " + ComponentReference.printComponentRefStr(inCref) + " not found!\n"); + badcref = ComponentReference.makeCrefIdent("ERROR_cref2simvar_failed", DAE.T_REAL_DEFAULT, {}); + /* Todo: This also generates an error for example itearation variables, so i commented out + "Template did not find the simulation variable for "+ ComponentReference.printComponentRefStr(cref) + ". "; + Error.addInternalError(errstr, sourceInfo());*/ + then + SimCodeVar.SIMVAR(badcref, BackendDAE.VARIABLE(), "", "", "", -2, NONE(), NONE(), NONE(), NONE(), false, DAE.T_REAL_DEFAULT, false, NONE(), SimCodeVar.NOALIAS(), DAE.emptyElementSource, SimCodeVar.INTERNAL(), NONE(), {}, false, true); + end matchcontinue; +end cref2simvar; + +public function isModelTooBigForCSharpInOneFile +"Used by C# template to determine if the generated code should be split into several files + to make Visual Studio responsive when the file is opened (C# compiler is OK, + but VS does not scale well for big C# files)." + input SimCode.SimCode simCode; + output Boolean outIsTooBig; +algorithm + outIsTooBig := match(simCode) + local + Integer numAlgVars; + + case (SimCode.SIMCODE(modelInfo = SimCode.MODELINFO(varInfo = SimCode.VARINFO(numAlgVars = numAlgVars)))) + equation + outIsTooBig = numAlgVars > 1000; + then outIsTooBig; + + end match; +end isModelTooBigForCSharpInOneFile; + +public function derComponentRef +"Used by templates to derrive a cref in a der(cref) expression. + Particularly, this function is called for the C# code generator, + while for C/C++, it is solved by prefixing the cref with '$P$DER' in daeExpCall() template. + The prefixing technique is not usable for C#, because there is no macroprocessor in C#. + TODO: all der(cref) expressions should be eliminated before the expressions enter templates + to pull this logic (and this function) out of templates." + input DAE.ComponentRef inCref; + output DAE.ComponentRef derCref; +algorithm + derCref := ComponentReference.crefPrefixDer(inCref); +end derComponentRef; + +public function hackArrayReverseToCref +"This is a hack transformation of an expanded array back to its cref. +It is used in daeExpArray() (for C# yet) to optimize the generated code. +TODO: This function should not exist! +Rather the array should not be let expanded when SimCode is entering templates. +" + input DAE.Exp inExp; + input SimCode.Context context; + output DAE.Exp outExp; +algorithm + outExp := matchcontinue (inExp, context) + local + list aRest; + DAE.ComponentRef cr; + DAE.Type aty; + DAE.Exp crefExp; + + case(DAE.ARRAY(ty=aty, scalar=true, array =(DAE.CREF(componentRef=cr) ::aRest)), _) + equation + failure(SimCode.FUNCTION_CONTEXT()=context); // only in the function context + failure(SimCode.PARALLEL_FUNCTION_CONTEXT()=context); // only in the function context + { DAE.INDEX(DAE.ICONST(1)) } = ComponentReference.crefLastSubs(cr); + cr = ComponentReference.crefStripLastSubs(cr); + true = isArrayExpansion(aRest, cr, 2); + crefExp = Expression.makeCrefExp(cr, aty); + then + crefExp; + + else inExp; + + end matchcontinue; +end hackArrayReverseToCref; + +protected function isArrayExpansion +"Helper funtion to hackArrayReverseToCref." + input list inArrayElems; + input DAE.ComponentRef inCref; + input Integer index; + output Boolean isExpanded; +algorithm + isExpanded := matchcontinue(inArrayElems, inCref, index) + local + list aRest; + Integer i; + DAE.ComponentRef cr; + case({}, _, _) then true; + case (DAE.CREF(componentRef=cr) :: aRest, _, _) + equation + { DAE.INDEX(DAE.ICONST(i)) } = ComponentReference.crefLastSubs(cr); + true = (i == index); + cr = ComponentReference.crefStripLastSubs(cr); + true = ComponentReference.crefEqualNoStringCompare(inCref, cr); + then isArrayExpansion(aRest, inCref, index+1); + else false; + end matchcontinue; +end isArrayExpansion; + +public function hackMatrixReverseToCref +"This is a hack transformation of an expanded matrix back to its cref. +It is used in daeExpMatrix() (for C# yet) to optimize the generated code. +TODO: This function should not exist! +Rather the matrix should not be let expanded when SimCode is entering templates +" + input DAE.Exp inExp; + input SimCode.Context context; + output DAE.Exp outExp; +algorithm + outExp := matchcontinue (inExp, context) + local + DAE.ComponentRef cr; + DAE.Type aty; + list> rows; + DAE.Exp crefExp; + + case(DAE.MATRIX(ty=aty, matrix = rows as (((DAE.CREF(componentRef=cr))::_)::_) ), _) + equation + failure(SimCode.FUNCTION_CONTEXT()=context); + failure(SimCode.PARALLEL_FUNCTION_CONTEXT()=context); // only in the function context + { DAE.INDEX(DAE.ICONST(1)), DAE.INDEX(DAE.ICONST(1)) } = ComponentReference.crefLastSubs(cr); + cr = ComponentReference.crefStripLastSubs(cr); + true = isMatrixExpansion(rows, cr, 1, 1); + crefExp = Expression.makeCrefExp(cr, aty); + then + crefExp; + + else inExp; + + end matchcontinue; +end hackMatrixReverseToCref; + +protected function isMatrixExpansion +"Helper funtion to hackMatrixReverseToCref." + input list> rows; + input DAE.ComponentRef inCref; + input Integer rowIndex; + input Integer colIndex; + output Boolean isExpanded; +algorithm + isExpanded := matchcontinue(rows, inCref, rowIndex, colIndex) + local + list> restRows; + list restElems; + Integer r, c; + DAE.ComponentRef cr; + case({}, _, _, _) then true; + case({} :: restRows, _, _, _) then isMatrixExpansion(restRows, inCref, rowIndex+1, 1); + case ( (DAE.CREF(componentRef=cr) :: restElems) :: restRows, _, _, _) + equation + { DAE.INDEX(DAE.ICONST(r)), DAE.INDEX(DAE.ICONST(c)) } = ComponentReference.crefLastSubs(cr); + true = (r == rowIndex) and (c == colIndex); + cr = ComponentReference.crefStripLastSubs(cr); + true = ComponentReference.crefEqualNoStringCompare(inCref, cr); + then isMatrixExpansion(restElems :: restRows, inCref, rowIndex, colIndex+1); + else false; + end matchcontinue; +end isMatrixExpansion; + +public function hackGetFirstExternalFunctionLib +"This is a hack to get the original library name given to an external function. +TODO: redesign OMC and Modelica specification so they are not so C/C++ centric." + input list libs; + output String outFirstLib; +algorithm + outFirstLib := matchcontinue (libs) + local + String lib; + + case _ + equation + lib = List.last(libs); + lib = System.stringReplace(lib, "-l", ""); + then + lib; + + else "NO_LIB"; + + end matchcontinue; +end hackGetFirstExternalFunctionLib; + +public function createAssertforSqrt + input DAE.Exp inExp; + output DAE.Exp outExp; +algorithm + outExp := + match (inExp) + case(_) + equation + // Simplify things like abs(exp) >= 0 to exp + (outExp, _) = ExpressionSimplify.simplify(DAE.RELATION(inExp, DAE.GREATEREQ(DAE.T_REAL_DEFAULT), DAE.RCONST(0.0), -1, NONE())); + then outExp; + end match; +end createAssertforSqrt; + +public function createDAEString + input String inString; + output DAE.Exp outExp; + annotation(__OpenModelica_EarlyInline = true); +algorithm + outExp := DAE.SCONST(inString); +end createDAEString; + +/* end of TypeView published functions */ + +// ============================================================================= +// section to generate SimCode from functions +// +// Finds the called functions in BackendDAE and transforms them to a list of +// libraries and a list of SimCode.Function uniontypes. +// ============================================================================= + +protected function orderRecordDecls + input SimCode.RecordDeclaration decl1; + input SimCode.RecordDeclaration decl2; + output Boolean b; +algorithm + b := match (decl1,decl2) + local + Absyn.Path path1,path2; + case (SimCode.RECORD_DECL_DEF(path=path1),SimCode.RECORD_DECL_DEF(path=path2)) then Absyn.pathGe(path1,path2); + else true; + end match; +end orderRecordDecls; + +public function elaborateFunctions + input Absyn.Program program; + input list daeElements; + input list metarecordTypes; + input list literals; + input list includes; + output list functions; + output list extraRecordDecls; + output list outIncludes; + output list includeDirs; + output list libs; + output list libpaths; +protected + list fns; + list outRecordTypes; + HashTableStringToPath.HashTable ht; + list>> g; +algorithm + (extraRecordDecls, outRecordTypes) := elaborateRecordDeclarationsForMetarecords(literals, {}, {}); + (functions, outRecordTypes, extraRecordDecls, outIncludes, includeDirs, libs,libpaths) := elaborateFunctions2(program, daeElements, {}, outRecordTypes, extraRecordDecls, includes, {}, {},{}); + extraRecordDecls := List.unique(extraRecordDecls); + (extraRecordDecls, _) := elaborateRecordDeclarationsFromTypes(metarecordTypes, extraRecordDecls, outRecordTypes); + extraRecordDecls := List.sort(extraRecordDecls, orderRecordDecls); + ht := HashTableStringToPath.emptyHashTableSized(BaseHashTable.lowBucketSize); + (extraRecordDecls,_) := List.mapFold(extraRecordDecls, aliasRecordDeclarations, ht); + // Topological sort since we have no guarantees in the order of generated records + g := Graph.buildGraph(extraRecordDecls, getRecordDependencies, extraRecordDecls); + (extraRecordDecls, {}) := Graph.topologicalSort(g, isRecordDeclEqual); +end elaborateFunctions; + +protected function getRecordDependencies + input SimCode.RecordDeclaration decl; + input list allDecls; + output list dependencies; +algorithm + dependencies := match (decl,allDecls) + local + String name; + list vars; + list tys; + list> tyss; + case (SimCode.RECORD_DECL_FULL(aliasName=SOME(name)),_) + then List.select1(allDecls, isRecordDecl, name); + case (SimCode.RECORD_DECL_FULL(variables=vars),_) + equation + tys = list(getVarType(v) for v in vars); + tyss = List.map1(tys, Types.getAllInnerTypesOfType, Util.anyReturnTrue); + tys = List.flatten(tyss); + dependencies = List.filterMap1(tys, getRecordDependenciesFromType, allDecls); + then List.unique(dependencies); + else {}; + end match; +end getRecordDependencies; + +protected function getVarType + input SimCode.Variable var; + output DAE.Type ty; +algorithm + ty := match var + case SimCode.VARIABLE(ty=ty) then ty; + else DAE.T_ANYTYPE_DEFAULT; + end match; +end getVarType; + +protected function getRecordDependenciesFromType + input DAE.Type ty; + input list allDecls; + output SimCode.RecordDeclaration decl; +protected + Absyn.Path path; + String name; +algorithm + DAE.T_COMPLEX(complexClassType = ClassInf.RECORD(path)) := ty; + name := Absyn.pathStringUnquoteReplaceDot(path, "_"); + decl := List.selectFirst1(allDecls, isRecordDecl, name); +end getRecordDependenciesFromType; + +protected function isRecordDecl + input SimCode.RecordDeclaration decl; + input String name; + output Boolean b; +algorithm + b := match (decl,name) + local + String name1; + case (SimCode.RECORD_DECL_FULL(name=name1),_) then stringEq(name,name1); + else false; + end match; +end isRecordDecl; + +protected function isRecordDeclEqual + input SimCode.RecordDeclaration decl1; + input SimCode.RecordDeclaration decl2; + output Boolean b; +algorithm + b := match (decl1,decl2) + local + String name1,name2; + Absyn.Path path1,path2; + case (SimCode.RECORD_DECL_FULL(name=name1),SimCode.RECORD_DECL_FULL(name=name2)) then stringEq(name1,name2); + case (SimCode.RECORD_DECL_DEF(path=path1),SimCode.RECORD_DECL_DEF(path=path2)) then Absyn.pathEqual(path1,path2); + else false; + end match; +end isRecordDeclEqual; + +protected function elaborateFunctions2 + input Absyn.Program program; + input list daeElements; + input list inFunctions; + input list inRecordTypes; + input list inDecls; + input list inIncludes; + input list inIncludeDirs; + input list inLibs; + input list inPaths; + output list outFunctions; + output list outRecordTypes; + output list outDecls; + output list outIncludes; + output list outIncludeDirs; + output list outLibs; + output list outLibsPaths; +algorithm + (outFunctions, outRecordTypes, outDecls, outIncludes, outIncludeDirs, outLibs,outLibsPaths) := + match (program, daeElements, inFunctions, inRecordTypes, inDecls, inIncludes, inIncludeDirs, inLibs,inPaths) + local + Boolean b; + list accfns, fns; + SimCode.Function fn; + list rt, rt_1, rt_2, includes, libs,libPaths; + DAE.Function fel; + list rest; + list decls; + String name; + list includeDirs; + Absyn.Path path; + + case (_, {}, accfns, rt, decls, includes, includeDirs, libs,libPaths) + then (listReverse(accfns), rt, decls, includes, includeDirs, libs,libPaths); + case (_, (DAE.FUNCTION( type_ = DAE.T_FUNCTION(functionAttributes=DAE.FUNCTION_ATTRIBUTES(isBuiltin=DAE.FUNCTION_BUILTIN_PTR()))) :: rest), accfns, rt, decls, includes, includeDirs, libs,libPaths) + equation + // skip over builtin functions + (fns, rt_2, decls, includes, includeDirs, libs,libPaths) = elaborateFunctions2(program, rest, accfns, rt, decls, includes, includeDirs, libs,libPaths); + then + (fns, rt_2, decls, includes, includeDirs, libs,libPaths); + case (_, (DAE.FUNCTION(partialPrefix = true) :: rest), accfns, rt, decls, includes, includeDirs, libs,libPaths) + equation + // skip over partial functions + (fns, rt_2, decls, includes, includeDirs, libs,libPaths) = elaborateFunctions2(program, rest, accfns, rt, decls, includes, includeDirs, libs,libPaths); + then + (fns, rt_2, decls, includes, includeDirs, libs,libPaths); + case (_, DAE.FUNCTION(functions = DAE.FUNCTION_EXT(externalDecl = DAE.EXTERNALDECL(language="builtin"))::_)::rest, accfns, rt, decls, includes, includeDirs, libs,libPaths) + equation + // skip over builtin functions + (fns, rt_2, decls, includes, includeDirs, libs,libPaths) = elaborateFunctions2(program, rest, accfns, rt, decls, includes, includeDirs, libs,libPaths); + then + (fns, rt_2, decls, includes, includeDirs, libs,libPaths); + + case (_, (fel as DAE.FUNCTION(functions = DAE.FUNCTION_EXT(externalDecl = DAE.EXTERNALDECL(name=name, language="C"))::_))::rest, accfns, rt, decls, includes, includeDirs, libs,libPaths) + equation + // skip over builtin functions + b = listMember(name, SCode.knownExternalCFunctions); + (fn,_, decls, includes, includeDirs, libs,libPaths) = elaborateFunction(program, fel, rt, decls, includes, includeDirs, libs,libPaths); + (fns, rt_2, decls, includes, includeDirs, libs,libPaths) = elaborateFunctions2(program, rest, List.consOnTrue(not b, fn, accfns), rt, decls, includes, includeDirs, libs,libPaths); + then + (fns, rt_2, decls, includes, includeDirs, libs,libPaths); + + case (_, (fel :: rest), accfns, rt, decls, includes, includeDirs, libs,libPaths) + equation + (fn, rt_1, decls, includes, includeDirs, libs,libPaths) = elaborateFunction(program, fel, rt, decls, includes, includeDirs, libs,libPaths); + (fns, rt_2, decls, includes, includeDirs, libs,libPaths) = elaborateFunctions2(program, rest, (fn :: accfns), rt_1, decls, includes, includeDirs, libs,libPaths); + then + (fns, rt_2, decls, includes, includeDirs, libs,libPaths); + end match; +end elaborateFunctions2; + +/* Does the actual work of transforming a DAE.FUNCTION to a SimCode.Function. */ +protected function elaborateFunction + input Absyn.Program program; + input DAE.Function inElement; + input list inRecordTypes; + input list inRecordDecls; + input list inIncludes; + input list inIncludeDirs; + input list inLibs; + input list inLibPaths; + output SimCode.Function outFunction; + output list outRecordTypes; + output list outRecordDecls; + output list outIncludes; + output list outIncludeDirs; + output list outLibs; + output list outLibPaths; +algorithm + (outFunction, outRecordTypes, outRecordDecls, outIncludes, outIncludeDirs, outLibs,outLibPaths):= + matchcontinue (program, inElement, inRecordTypes, inRecordDecls, inIncludes, inIncludeDirs, inLibs,inLibPaths) + local + DAE.Function fn; + String extfnname, lang, str; + list algs, vars; // , bivars, invars, outvars; + list includes, libs, libPaths, fn_libs,fn_paths, fn_includes, fn_includeDirs, rt, rt_1; + Absyn.Path fpath; + list args; + DAE.Type restype, tp; + list extargs; + list simextargs; + SimCode.SimExtArg extReturn; + DAE.ExtArg extretarg; + Option ann; + DAE.ExternalDecl extdecl; + list outVars, inVars, biVars, funArgs, varDecls; + list recordDecls; + list bodyStmts; + list daeElts; + Absyn.Path name; + DAE.ElementSource source; + SourceInfo info; + Boolean dynamicLoad, hasIncludeAnnotation, hasLibraryAnnotation; + list includeDirs; + DAE.FunctionAttributes funAttrs; + list varlst; + DAE.VarKind kind; + SCode.Visibility visibility; + + // Modelica functions. + case (_, DAE.FUNCTION(path = fpath, source = source, visibility = visibility, + functions = DAE.FUNCTION_DEF(body = daeElts)::_, // might be followed by derivative maps + type_ = DAE.T_FUNCTION(funcArg=args, functionAttributes=funAttrs), + partialPrefix=false), rt, recordDecls, includes, includeDirs, libs,libPaths) + equation + + DAE.FUNCTION_ATTRIBUTES(functionParallelism=DAE.FP_NON_PARALLEL()) = funAttrs; + + outVars = List.map(DAEUtil.getOutputVars(daeElts), daeInOutSimVar); + funArgs = List.map1(args, typesSimFunctionArg, NONE()); + (recordDecls, rt_1) = elaborateRecordDeclarations(daeElts, recordDecls, rt); + vars = List.filter(daeElts, isVarQ); + varDecls = List.map(vars, daeInOutSimVar); + algs = List.filterOnTrue(daeElts, DAEUtil.isAlgorithm); + bodyStmts = List.map(algs, elaborateStatement); + info = DAEUtil.getElementSourceFileInfo(source); + then + (SimCode.FUNCTION(fpath, outVars, funArgs, varDecls, bodyStmts, visibility, info), rt_1, recordDecls, includes, includeDirs, libs,libPaths); + + + case (_, DAE.FUNCTION(path = fpath, source = source, + functions = DAE.FUNCTION_DEF(body = daeElts)::_, // might be followed by derivative maps + type_ = DAE.T_FUNCTION(funcArg=args, functionAttributes=funAttrs), + partialPrefix=false), rt, recordDecls, includes, includeDirs, libs,libPaths) + equation + + DAE.FUNCTION_ATTRIBUTES(functionParallelism=DAE.FP_KERNEL_FUNCTION()) = funAttrs; + + outVars = List.map(DAEUtil.getOutputVars(daeElts), daeInOutSimVar); + funArgs = List.map1(args, typesSimFunctionArg, NONE()); + (recordDecls, rt_1) = elaborateRecordDeclarations(daeElts, recordDecls, rt); + vars = List.filter(daeElts, isVarNotInputNotOutput); + varDecls = List.map(vars, daeInOutSimVar); + algs = List.filterOnTrue(daeElts, DAEUtil.isAlgorithm); + bodyStmts = List.map(algs, elaborateStatement); + info = DAEUtil.getElementSourceFileInfo(source); + then + (SimCode.KERNEL_FUNCTION(fpath, outVars, funArgs, varDecls, bodyStmts, info), rt_1, recordDecls, includes, includeDirs, libs,libPaths); + + + case (_, DAE.FUNCTION(path = fpath, source = source, + functions = DAE.FUNCTION_DEF(body = daeElts)::_, // might be followed by derivative maps + type_ = DAE.T_FUNCTION(funcArg=args, functionAttributes = funAttrs), + partialPrefix=false), rt, recordDecls, includes, includeDirs, libs,libPaths) + equation + + DAE.FUNCTION_ATTRIBUTES(functionParallelism=DAE.FP_PARALLEL_FUNCTION()) = funAttrs; + + outVars = List.map(DAEUtil.getOutputVars(daeElts), daeInOutSimVar); + funArgs = List.map1(args, typesSimFunctionArg, NONE()); + (recordDecls, rt_1) = elaborateRecordDeclarations(daeElts, recordDecls, rt); + vars = List.filter(daeElts, isVarQ); + varDecls = List.map(vars, daeInOutSimVar); + algs = List.filterOnTrue(daeElts, DAEUtil.isAlgorithm); + bodyStmts = List.map(algs, elaborateStatement); + info = DAEUtil.getElementSourceFileInfo(source); + then + (SimCode.PARALLEL_FUNCTION(fpath, outVars, funArgs, varDecls, bodyStmts, info), rt_1, recordDecls, includes, includeDirs, libs,libPaths); + + // External functions. + case (_, DAE.FUNCTION(path = fpath, source = source, visibility = visibility, + functions = DAE.FUNCTION_EXT(body = daeElts, externalDecl = extdecl)::_, // might be followed by derivative maps + type_ = (DAE.T_FUNCTION(funcArg = args))), rt, recordDecls, includes, includeDirs, libs,libPaths) + equation + DAE.EXTERNALDECL(name=extfnname, args=extargs, + returnArg=extretarg, language=lang, ann=ann) = extdecl; + // outvars = DAEUtil.getOutputVars(daeElts); + // invars = DAEUtil.getInputVars(daeElts); + // bivars = DAEUtil.getBidirVars(daeElts); + funArgs = List.map1(args, typesSimFunctionArg, NONE()); + outVars = List.map(DAEUtil.getOutputVars(daeElts), daeInOutSimVar); + inVars = List.map(DAEUtil.getInputVars(daeElts), daeInOutSimVar); + biVars = List.map(DAEUtil.getBidirVars(daeElts), daeInOutSimVar); + (recordDecls, rt_1) = elaborateRecordDeclarations(daeElts, recordDecls, rt); + info = DAEUtil.getElementSourceFileInfo(source); + (fn_includes, fn_includeDirs, fn_libs, fn_paths,dynamicLoad) = generateExtFunctionIncludes(program, fpath, ann, info); + includes = List.union(fn_includes, includes); + includeDirs = List.union(fn_includeDirs, includeDirs); + libs = List.union(fn_libs, libs); + libPaths = List.union(fn_paths, libPaths); + simextargs = List.map(extargs, extArgsToSimExtArgs); + extReturn = extArgsToSimExtArgs(extretarg); + (simextargs, extReturn) = fixOutputIndex(outVars, simextargs, extReturn); + // make lang to-upper as we have FORTRAN 77 and Fortran 77 in the Modelica Library! + lang = System.toupper(lang); + then + (SimCode.EXTERNAL_FUNCTION(fpath, extfnname, funArgs, simextargs, extReturn, + inVars, outVars, biVars, fn_includes, fn_libs, lang, visibility, info, dynamicLoad), + rt_1, recordDecls, includes, includeDirs, libs,libPaths); + + // Record constructor. + case (_, DAE.RECORD_CONSTRUCTOR(source = source, type_ = DAE.T_FUNCTION(funcArg = args, funcResultType = restype as DAE.T_COMPLEX(complexClassType = ClassInf.RECORD(name))),kind=kind), rt, recordDecls, includes, includeDirs, libs,libPaths) + equation + funArgs = List.map1(args, typesSimFunctionArg, NONE()); + (recordDecls, rt_1) = elaborateRecordDeclarationsForRecord(restype, recordDecls, rt); + DAE.T_COMPLEX(varLst = varlst) = restype; + varlst = List.filterOnTrue(varlst, Types.isProtectedVar); + varDecls = List.map(varlst, typesVar); + info = DAEUtil.getElementSourceFileInfo(source); + then + (SimCode.RECORD_CONSTRUCTOR(name, funArgs, varDecls, SCode.PUBLIC(), info, kind), rt_1, recordDecls, includes, includeDirs, libs,libPaths); + + // failure + case (_, fn, _, _, _, _, _,_) + equation + Error.addInternalError("function elaborateFunction failed for function: \n" + DAEDump.dumpFunctionStr(fn), sourceInfo()); + then + fail(); + end matchcontinue; +end elaborateFunction; + +protected function typesSimFunctionArg +"Generates code from a function argument." + input DAE.FuncArg inFuncArg; + input Option binding; + output SimCode.Variable outVar; +algorithm + outVar := matchcontinue (inFuncArg, binding) + local + DAE.Type tty; + String name; + DAE.ComponentRef cref_; + DAE.Const const; + list args; + DAE.Type res_ty; + list var_args; + list tys; + DAE.VarKind kind; + DAE.VarParallelism prl; + + case (DAE.FUNCARG(name=name, ty=DAE.T_FUNCTION(funcArg = args, funcResultType = DAE.T_TUPLE(types = tys))), _) + equation + var_args = List.map1(args, typesSimFunctionArg, NONE()); + tys = List.map(tys, Types.simplifyType); + then + SimCode.FUNCTION_PTR(name, tys, var_args, binding); + + case (DAE.FUNCARG(name=name, ty=DAE.T_FUNCTION(funcArg = args, funcResultType = DAE.T_NORETCALL())), _) + equation + var_args = List.map1(args, typesSimFunctionArg, NONE()); + then + SimCode.FUNCTION_PTR(name, {}, var_args, binding); + + case (DAE.FUNCARG(name=name, ty=DAE.T_FUNCTION(funcArg = args, funcResultType = res_ty)), _) + equation + res_ty = Types.simplifyType(res_ty); + var_args = List.map1(args, typesSimFunctionArg, NONE()); + then + SimCode.FUNCTION_PTR(name, {res_ty}, var_args, binding); + + case (DAE.FUNCARG(name=name, ty=tty, par=prl, const=const), _) + equation + tty = Types.simplifyType(tty); + cref_ = ComponentReference.makeCrefIdent(name, tty, {}); + kind = DAEUtil.const2VarKind(const); + then + SimCode.VARIABLE(cref_, tty, binding, {}, prl, kind); + end matchcontinue; +end typesSimFunctionArg; + +protected function daeInOutSimVar + input DAE.Element inElement; + output SimCode.Variable outVar; +algorithm + outVar := matchcontinue(inElement) + local + String name; + DAE.Type daeType; + DAE.ComponentRef id; + DAE.VarKind kind; + DAE.VarParallelism prl; + list inst_dims; + list inst_dims_exp; + Option binding; + SimCode.Variable var; + case (DAE.VAR(componentRef = DAE.CREF_IDENT(ident=name), ty = daeType as DAE.T_FUNCTION(), parallelism = prl, binding = binding)) + equation + var = typesSimFunctionArg(DAE.FUNCARG(name, daeType, DAE.C_VAR(), prl, NONE()), binding); + then var; + + case (DAE.VAR(componentRef = id, + parallelism = prl, + ty = daeType, + binding = binding, + dims = inst_dims, + kind = kind + )) + equation + daeType = Types.simplifyType(daeType); + inst_dims_exp = List.map(inst_dims, Expression.dimensionSizeExpHandleUnkown); + then SimCode.VARIABLE(id, daeType, binding, inst_dims_exp, prl, kind); + else + equation + // TODO: ArrayEqn fails here + Error.addInternalError("function daeInOutSimVar failed\n", sourceInfo()); + then + fail(); + end matchcontinue; +end daeInOutSimVar; + +protected function extArgsToSimExtArgs + input DAE.ExtArg extArg; + output SimCode.SimExtArg simExtArg; +algorithm + simExtArg := + match (extArg) + local + DAE.ComponentRef componentRef; + DAE.Attributes attributes; + DAE.Type type_; + Boolean isInput; + Boolean isOutput; + Boolean isArray; + DAE.Exp exp_; + Integer outputIndex; + + case DAE.EXTARG(componentRef, attributes, type_) + equation + isInput = Types.isInputAttr(attributes); + isOutput = Types.isOutputAttr(attributes); + outputIndex = if isOutput then -1 else 0; // correct output index is added later by fixOutputIndex + isArray = Types.isArray(type_); + type_ = Types.simplifyType(type_); + then SimCode.SIMEXTARG(componentRef, isInput, outputIndex, isArray, false /*fixed later*/, type_); + + case DAE.EXTARGEXP(exp_, type_) + equation + type_ = Types.simplifyType(type_); + then SimCode.SIMEXTARGEXP(exp_, type_); + + case DAE.EXTARGSIZE(componentRef, attributes, type_, exp_) + equation + isInput = Types.isInputAttr(attributes); + isOutput = Types.isOutputAttr(attributes); + outputIndex = if isOutput then -1 else 0; // correct output index is added later by fixOutputIndex + type_ = Types.simplifyType(type_); + then SimCode.SIMEXTARGSIZE(componentRef, isInput, outputIndex, type_, exp_); + + case DAE.NOEXTARG() then SimCode.SIMNOEXTARG(); + end match; +end extArgsToSimExtArgs; + +protected function fixOutputIndex + input list outVars; + input list simExtArgsIn; + input SimCode.SimExtArg extReturnIn; + output list simExtArgsOut; + output SimCode.SimExtArg extReturnOut; +algorithm + (simExtArgsOut, extReturnOut) := match (outVars, simExtArgsIn, extReturnIn) + local + case (_, _, _) + equation + simExtArgsOut = List.map1(simExtArgsIn, assignOutputIndex, outVars); + extReturnOut = assignOutputIndex(extReturnIn, outVars); + then + (simExtArgsOut, extReturnOut); + end match; +end fixOutputIndex; + +protected function assignOutputIndex + input SimCode.SimExtArg simExtArgIn; + input list outVars; + output SimCode.SimExtArg simExtArgOut; +algorithm + simExtArgOut := + matchcontinue (simExtArgIn, outVars) + local + DAE.ComponentRef cref, fcref; + Boolean isInput; + Integer outputIndex; // > 0 if output + Boolean isArray, hasBinding; + DAE.Type type_; + DAE.Exp exp; + Integer newOutputIndex; + + case (SimCode.SIMEXTARG(cref, isInput, outputIndex, isArray, _, type_), _) + equation + true = outputIndex == -1; + fcref = ComponentReference.crefFirstCref(cref); + (newOutputIndex, hasBinding) = findIndexInList(fcref, outVars, 1); + then + SimCode.SIMEXTARG(cref, isInput, newOutputIndex, isArray, hasBinding, type_); + + case (SimCode.SIMEXTARGSIZE(cref, isInput, outputIndex, type_, exp), _) + equation + true = outputIndex == -1; + (newOutputIndex, _) = findIndexInList(cref, outVars, 1); + then + SimCode.SIMEXTARGSIZE(cref, isInput, newOutputIndex, type_, exp); + + else + simExtArgIn; + end matchcontinue; +end assignOutputIndex; + +protected function findIndexInList + input DAE.ComponentRef cref; + input list outVars; + input Integer inCurrentIndex; + output Integer crefIndexInOutVars; + output Boolean hasBinding; +algorithm + (crefIndexInOutVars, hasBinding) := + matchcontinue (cref, outVars, inCurrentIndex) + local + DAE.ComponentRef name; + list restOutVars; + Option v; + Integer currentIndex; + + case (_, {}, _) then (-1, false); + case (_, SimCode.VARIABLE(name=name, value=v) :: _, currentIndex) + equation + true = ComponentReference.crefEqualNoStringCompare(cref, name); + then (currentIndex, Util.isSome(v)); + case (_, _ :: restOutVars, currentIndex) + equation + currentIndex = currentIndex + 1; + (currentIndex, hasBinding) = findIndexInList(cref, restOutVars, currentIndex); + then (currentIndex, hasBinding); + end matchcontinue; +end findIndexInList; + +protected function elaborateStatement + input DAE.Element inElement; + output SimCode.Statement outStatement; +algorithm + (outStatement):= + matchcontinue (inElement) + local + list stmts; + case (DAE.ALGORITHM(algorithm_ = DAE.ALGORITHM_STMTS(statementLst = stmts))) + then + SimCode.ALGORITHM(stmts); + else + equation + true = Flags.isSet(Flags.FAILTRACE); + Debug.trace("# SimCode.elaborateStatement failed\n"); + then + fail(); + end matchcontinue; +end elaborateStatement; + + +public function checkValidMainFunction +"Verifies that an in-function can be generated. +This is not the case if the input involves function-pointers." + input String name; + input SimCode.Function fn; +algorithm + _ := matchcontinue (name, fn) + local + list inVars; + case (_, SimCode.FUNCTION(functionArguments = inVars)) + equation + failure(_ = List.selectFirst(inVars, isFunctionPtr)); + then (); + case (_, SimCode.EXTERNAL_FUNCTION(inVars = inVars)) + equation + failure(_ = List.selectFirst(inVars, isFunctionPtr)); + then (); + else + equation + Error.addMessage(Error.GENERATECODE_INVARS_HAS_FUNCTION_PTR, {name}); + then fail(); + end matchcontinue; +end checkValidMainFunction; + +public function isBoxedFunction +"Verifies that an in-function can be generated. +This is not the case if the input involves function-pointers." + input SimCode.Function fn; + output Boolean b; +algorithm + b := matchcontinue fn + local + list inVars, outVars; + case (SimCode.FUNCTION(functionArguments = inVars, outVars = outVars)) + equation + List.map_0(inVars, isBoxedArg); + List.map_0(outVars, isBoxedArg); + then true; + case (SimCode.EXTERNAL_FUNCTION(inVars = inVars, outVars = outVars)) + equation + List.map_0(inVars, isBoxedArg); + List.map_0(outVars, isBoxedArg); + then true; + else false; + end matchcontinue; +end isBoxedFunction; + +protected function isFunctionPtr +"Checks if an input variable is a function pointer" + input SimCode.Variable var; + output Boolean b; +algorithm + b := match var + /* Yes, they are VARIABLE, not SimCode.FUNCTION_PTR. */ + case SimCode.FUNCTION_PTR() then true; + else false; + end match; +end isFunctionPtr; + +protected function isBoxedArg +"Checks if a variable is a boxed datatype" + input SimCode.Variable var; +algorithm + _ := match var + case SimCode.FUNCTION_PTR() then (); + case SimCode.VARIABLE(ty = DAE.T_METABOXED()) then (); + case SimCode.VARIABLE(ty = DAE.T_METATYPE()) then (); + case SimCode.VARIABLE(ty = DAE.T_STRING()) then (); + end match; +end isBoxedArg; + +public function findLiterals + "Finds all literal expressions in functions" + input list fns; + output list ofns; + output list literals; +algorithm + (ofns, (_, _, literals)) := DAEUtil.traverseDAEFunctions( + fns, findLiteralsHelper, + (0, HashTableExpToIndex.emptyHashTableSized(BaseHashTable.bigBucketSize), {}), {}); + literals := listReverse(literals); +end findLiterals; + +public + +function findLiteralsHelper + input DAE.Exp inExp; + input tuple> inTpl; + output DAE.Exp exp; + output tuple> tpl; +algorithm + exp := inExp; + tpl := inTpl; + (exp, tpl) := Expression.traverseExpBottomUp(exp, replaceLiteralExp, tpl); + (exp, tpl) := Expression.traverseExpTopDown(exp, replaceLiteralArrayExp, tpl); +end findLiteralsHelper; + +protected + +function replaceLiteralArrayExp + "The tuples contain: + * The expression to be replaced (or not) + * Index of next literal + * HashTable Exp->Index (Number of the literal) + * The list of literals + + Handles only array expressions (needs to be performed in a top-down fashion) + " + input DAE.Exp inExp; + input tuple> inTpl; + output DAE.Exp outExp; + output Boolean cont; + output tuple> outTpl; +algorithm + (outExp,cont,outTpl) := matchcontinue (inExp,inTpl) + local + DAE.Exp exp,exp2; + tuple> tpl; + case (DAE.ARRAY(), _) + equation + isLiteralArrayExp(inExp); + (exp2, tpl) = replaceLiteralExp2(inExp, inTpl); + then (exp2, false, tpl); + case (exp as DAE.ARRAY(), tpl) + equation + failure(isLiteralArrayExp(exp)); + then (exp, false, tpl); + case (exp as DAE.MATRIX(), _) + equation + isLiteralArrayExp(exp); + (exp2, tpl) = replaceLiteralExp2(inExp, inTpl); + then (exp2, false, tpl); + case (exp as DAE.MATRIX(), tpl) + equation + failure(isLiteralArrayExp(exp)); + then (exp, false, tpl); + else (inExp, true, inTpl); + end matchcontinue; +end replaceLiteralArrayExp; + +function replaceLiteralExp + "The tuples contain: + * The expression to be replaced (or not) + * Index of next literal + * HashTable Exp->Index (Number of the literal) + * The list of literals + " + input DAE.Exp inExp; + input tuple> inTpl; + output DAE.Exp outExp; + output tuple> outTpl; +algorithm + (outExp,outTpl) := matchcontinue (inExp,inTpl) + local + DAE.Exp exp; + String msg; + tuple> t; + list es; + case (exp, t) + equation + failure(isLiteralExp(exp)); + then (exp, t); + case (exp, t) + equation + isTrivialLiteralExp(exp); + then (exp, t); + case (DAE.LIST(valList=es), t) + equation + true = listLength(es) > 25; + (exp,t) = replaceLiteralExp2(inExp, t); + then (exp, t); // Too large list; causes performance issues to find all sublists... + case (exp, t) + equation + exp = listToCons(exp); + (exp, t) = Expression.traverseExpBottomUp(exp, replaceLiteralExp, t); + then (exp, t); // All sublists should also be added as literals... + case (exp, _) + equation + failure(_ = listToCons(exp)); + (exp,t) = replaceLiteralExp2(exp, inTpl); + then (exp, t); + case (exp, _) + equation + msg = "function replaceLiteralExp failed. Falling back to not replacing "+ExpressionDump.printExpStr(exp)+"."; + Error.addInternalError(msg, sourceInfo()); + then (inExp,inTpl); + end matchcontinue; +end replaceLiteralExp; + +function replaceLiteralExp2 + "The tuples contain: + * The expression to be replaced (or not) + * Index of next literal + * HashTable Exp->Index (Number of the literal) + * The list of literals + " + input DAE.Exp inExp; + input tuple> inTpl; + output DAE.Exp outExp; + output tuple> outTpl; +algorithm + (outExp,outTpl) := matchcontinue (inExp,inTpl) + local + DAE.Exp exp, nexp; + Integer i, ix; + list l; + DAE.Type et; + HashTableExpToIndex.HashTable ht; + case (exp, (i, ht, l)) + equation + ix = BaseHashTable.get(exp, ht); + nexp = DAE.SHARED_LITERAL(ix, exp); + then (nexp, (i, ht, l)); + case (exp, (i, ht, l)) + equation + ht = BaseHashTable.add((exp, i), ht); + nexp = DAE.SHARED_LITERAL(i, exp); + then (nexp, (i+1, ht, exp::l)); + end matchcontinue; +end replaceLiteralExp2; + +function listToCons +"Converts a DAE.LIST to a chain of DAE.CONS" + input DAE.Exp e; + output DAE.Exp o; +algorithm + o := match e + local + list es; + case DAE.LIST(es as _::_) then listToCons2(es); + end match; +end listToCons; + +function listToCons2 +"Converts a DAE.LIST to a chain of DAE.CONS" + input list ies; + output DAE.Exp o; +algorithm + o := match ies + local + DAE.Exp car, cdr; + list es; + case ({}) then DAE.LIST({}); + case (car::es) + equation + cdr = listToCons2(es); + then DAE.CONS(car, cdr); + end match; +end listToCons2; + +function isTrivialLiteralExp +"Succeeds if the expression should not be translated to a constant literal because it is too simple" + input DAE.Exp exp; +algorithm + _ := match exp + case DAE.BOX(DAE.SCONST(_)) then fail(); + case DAE.BOX(DAE.RCONST(_)) then fail(); + case DAE.BOX(_) then (); + case DAE.ICONST(_) then (); + case DAE.BCONST(_) then (); + case DAE.RCONST(_) then (); + case DAE.ENUM_LITERAL() then (); + case DAE.LIST(valList={}) then (); + case DAE.META_OPTION(NONE()) then (); + case DAE.SHARED_LITERAL() then (); + else fail(); + end match; +end isTrivialLiteralExp; + +function isLiteralArrayExp + input DAE.Exp iexp; +algorithm + _ := match iexp + local + DAE.Exp e1, e2, exp; + list expl; + list> expll; + + case DAE.SCONST(_) then (); + case DAE.ICONST(_) then (); + case DAE.RCONST(_) then (); + case DAE.BCONST(_) then (); + case DAE.ARRAY(array=expl) equation List.map_0(expl, isLiteralArrayExp); then (); + case DAE.MATRIX(matrix=expll) equation List.map_0(List.flatten(expll), isLiteralArrayExp); then (); + case DAE.ENUM_LITERAL() then (); + case DAE.META_OPTION(NONE()) then (); + case DAE.META_OPTION(SOME(exp)) equation isLiteralArrayExp(exp); then (); + case DAE.BOX(exp) equation isLiteralArrayExp(exp); then (); + case DAE.CONS(car = e1, cdr = e2) equation isLiteralArrayExp(e1); isLiteralArrayExp(e2); then (); + case DAE.LIST(valList = expl) equation List.map_0(expl, isLiteralArrayExp); then (); + case DAE.META_TUPLE(expl) equation List.map_0(expl, isLiteralArrayExp); then (); + case DAE.METARECORDCALL(args=expl) equation List.map_0(expl, isLiteralArrayExp); then (); + case DAE.SHARED_LITERAL() then (); + else fail(); + end match; +end isLiteralArrayExp; + +function isLiteralExp +"Returns if the expression may be replaced by a constant literal" + input DAE.Exp iexp; +algorithm + _ := match iexp + local + DAE.Exp e1, e2, exp; + list expl; + case DAE.SCONST(_) then (); + case DAE.ICONST(_) then (); + case DAE.RCONST(_) then (); + case DAE.BCONST(_) then (); + case DAE.ENUM_LITERAL() then (); + case DAE.META_OPTION(NONE()) then (); + case DAE.META_OPTION(SOME(exp)) equation isLiteralExp(exp); then (); + case DAE.BOX(exp) equation isLiteralExp(exp); then (); + case DAE.CONS(car = e1, cdr = e2) equation isLiteralExp(e1); isLiteralExp(e2); then (); + case DAE.LIST(valList = expl) equation List.map_0(expl, isLiteralExp); then (); + case DAE.META_TUPLE(expl) equation List.map_0(expl, isLiteralExp); then (); + case DAE.METARECORDCALL(args=expl) equation List.map_0(expl, isLiteralExp); then (); + case DAE.SHARED_LITERAL() then (); + else fail(); + end match; +end isLiteralExp; + +protected function elaborateRecordDeclarationsFromTypes + input list inTypes; + input list inAccRecordDecls; + input list inReturnTypes; + output list outRecordDecls; + output list outReturnTypes; +algorithm + (outRecordDecls, outReturnTypes) := + match (inTypes, inAccRecordDecls, inReturnTypes) + local + list accRecDecls; + DAE.Type firstType; + list restTypes; + list returnTypes; + + case ({}, accRecDecls, _) + then (accRecDecls, inReturnTypes); + case (firstType :: restTypes, accRecDecls, _) + equation + (accRecDecls, returnTypes) = + elaborateRecordDeclarationsForRecord(firstType, accRecDecls, inReturnTypes); + (accRecDecls, returnTypes) = + elaborateRecordDeclarationsFromTypes(restTypes, accRecDecls, returnTypes); + then (accRecDecls, returnTypes); + end match; +end elaborateRecordDeclarationsFromTypes; + +protected function elaborateRecordDeclarations +"Translate all records used by varlist to structs." + input list inVars; + input list inAccRecordDecls; + input list inReturnTypes; + output list outRecordDecls; + output list outReturnTypes; +algorithm + (outRecordDecls, outReturnTypes) := + matchcontinue (inVars, inAccRecordDecls, inReturnTypes) + local + DAE.Element var; + list rest; + DAE.Type ft; + list rt, rt_1, rt_2; + list accRecDecls; + DAE.Algorithm algorithm_; + list expl; + + case ({}, accRecDecls, rt) then (accRecDecls, rt); + + case (((DAE.VAR(ty = ft)) :: rest), accRecDecls, rt) + equation + (accRecDecls, rt_1) = elaborateRecordDeclarationsForRecord(ft, accRecDecls, rt); + (accRecDecls, rt_2) = elaborateRecordDeclarations(rest, accRecDecls, rt_1); + then + (accRecDecls, rt_2); + + case ((DAE.ALGORITHM(algorithm_ = algorithm_) :: rest), accRecDecls, rt) + equation + true = Config.acceptMetaModelicaGrammar(); + ((_, expl)) = DAEUtil.traverseAlgorithmExps(algorithm_, Expression.traverseSubexpressionsHelper, (matchMetarecordCalls, {})); + (accRecDecls, rt_2) = elaborateRecordDeclarationsForMetarecords(expl, accRecDecls, rt); + // TODO: ? what about rest ? , can be there something else after the ALGORITHM + (accRecDecls, rt_2) = elaborateRecordDeclarations(rest, accRecDecls, rt_2); + then + (accRecDecls, rt_2); + + case ((_ :: rest), accRecDecls, rt) + equation + (accRecDecls, rt_1) = elaborateRecordDeclarations(rest, accRecDecls, rt); + then + (accRecDecls, rt_1); + end matchcontinue; +end elaborateRecordDeclarations; + +protected function matchMetarecordCalls "Used together with getMatchingExps" + input DAE.Exp e; + input list acc; + output DAE.Exp outExp; + output list outExps; +algorithm + (outExp,outExps) := matchcontinue (e,acc) + local + Integer index; + case (DAE.METARECORDCALL(index = index), _) + equation + outExps = List.consOnTrue(-1 <> index, e, acc); + then (e, outExps); + else (e,acc); + end matchcontinue; +end matchMetarecordCalls; + +protected function isVarQ +"Succeeds if inElement is a variable or constant that is not input." + input DAE.Element inElement; +algorithm + _ := match (inElement) + local + DAE.VarKind vk; + DAE.VarDirection vd; + case DAE.VAR(kind=vk, direction=vd) + equation + isVarVarOrConstant(vk); + isDirectionNotInput(vd); + then (); + end match; +end isVarQ; + +protected function isVarNotInputNotOutput +"Succeeds if inElement is a variable or constant that is not input or output. +needed in kernel functions since they shouldn't have output vars." + input DAE.Element inElement; +algorithm + _ := match (inElement) + local + DAE.VarKind vk; + DAE.VarDirection vd; + case DAE.VAR(kind=vk, direction=vd) + equation + isVarVarOrConstant(vk); + isDirectionNotInputNotOutput(vd); + then (); + end match; +end isVarNotInputNotOutput; + +protected function isVarVarOrConstant + input DAE.VarKind inVarKind; +algorithm + _ := match (inVarKind) + case DAE.VARIABLE() then (); + case DAE.PARAM() then (); + case DAE.CONST() then (); + end match; +end isVarVarOrConstant; + +protected function isDirectionNotInput + input DAE.VarDirection inVarDirection; +algorithm + _ := match (inVarDirection) + case DAE.OUTPUT() then (); + case DAE.BIDIR() then (); + end match; +end isDirectionNotInput; + +protected function isDirectionNotInputNotOutput + input DAE.VarDirection inVarDirection; +algorithm + _ := match (inVarDirection) + case DAE.BIDIR() then (); + end match; +end isDirectionNotInputNotOutput; + +protected function filterNg "Sets the number of zero crossings to zero if events are disabled." + input Integer ng; + output Integer outInteger; +algorithm + outInteger := if useZerocrossing() then ng else 0; +end filterNg; + +protected function useZerocrossing + output Boolean res; +algorithm + res := Flags.isSet(Flags.EVENTS); +end useZerocrossing; + +protected function getCrefFromExp "Assume input Exp is CREF and return the ComponentRef, fail otherwise." + input DAE.Exp e; + output Absyn.ComponentRef c; +algorithm + c := match (e) + local + DAE.ComponentRef crefe; + Absyn.ComponentRef crefa; + + case(DAE.CREF(componentRef = crefe)) + equation + crefa = ComponentReference.unelabCref(crefe); + then + crefa; + + else + equation + Error.addInternalError("function getCrefFromExp failed: input was not of type DAE.CREF", sourceInfo()); + then + fail(); + end match; +end getCrefFromExp; + +protected function elaborateRecordDeclarationsForRecord +"Helper function to generateStructsForRecords." + input DAE.Type inRecordType; + input list inAccRecordDecls; + input list inReturnTypes; + output list outRecordDecls; + output list outReturnTypes; +algorithm + (outRecordDecls, outReturnTypes) := match (inRecordType, inAccRecordDecls, inReturnTypes) + local + Absyn.Path path, name; + list varlst; + String sname; + list rt, rt_1, rt_2, fieldNames; + list accRecDecls; + list vars; + Integer index; + SimCode.RecordDeclaration recDecl; + + case (DAE.T_COMPLEX(complexClassType = ClassInf.RECORD(name), varLst = varlst, source = {_}), accRecDecls, rt) + equation + sname = Absyn.pathStringUnquoteReplaceDot(name, "_"); + if not listMember(sname, rt) then + vars = List.map(varlst, typesVarNoBinding); + vars = List.sort(vars,compareVariable); + rt_1 = sname :: rt; + (accRecDecls, rt_2) = elaborateNestedRecordDeclarations(varlst, accRecDecls, rt_1); + recDecl = SimCode.RECORD_DECL_FULL(sname, NONE(), name, vars); + accRecDecls = List.appendElt(recDecl, accRecDecls); + else + rt_2 = rt; + end if; + then (accRecDecls, rt_2); + + case (DAE.T_COMPLEX(complexClassType = ClassInf.RECORD(_)), accRecDecls, rt) + then (accRecDecls, rt); + + case (DAE.T_METARECORD(source = {Absyn.QUALIFIED(name="SourceInfo")}), accRecDecls, rt) + then (accRecDecls, rt); + + case (DAE.T_METARECORD( fields = varlst, source = {path}), accRecDecls, rt) + equation + sname = Absyn.pathStringUnquoteReplaceDot(path, "_"); + if not listMember(sname, rt) then + fieldNames = List.map(varlst, generateVarName); + accRecDecls = SimCode.RECORD_DECL_DEF(path, fieldNames) :: accRecDecls; + rt_1 = sname::rt; + (accRecDecls, rt_2) = elaborateNestedRecordDeclarations(varlst, accRecDecls, rt_1); + else + rt_2 = rt; + end if; + then (accRecDecls, rt_2); + + case (_, accRecDecls, rt) + then (accRecDecls, rt); + + end match; +end elaborateRecordDeclarationsForRecord; + +protected function typesVarNoBinding + input DAE.Var inTypesVar; + output SimCode.Variable outVar; +algorithm + outVar := match (inTypesVar) + local + String name; + DAE.Type ty; + DAE.ComponentRef cref_; + DAE.Attributes attr; + SCode.Parallelism scPrl; + DAE.VarParallelism prl; + + case (DAE.TYPES_VAR(name=name, attributes = attr, ty=ty)) + equation + ty = Types.simplifyType(ty); + cref_ = ComponentReference.makeCrefIdent(name, ty, {}); + DAE.ATTR(parallelism = scPrl) = attr; + prl = scodeParallelismToDAEParallelism(scPrl); + then SimCode.VARIABLE(cref_, ty, NONE(), {}, prl,DAE.VARIABLE()); + end match; +end typesVarNoBinding; + +protected function typesVar + input DAE.Var inTypesVar; + output SimCode.Variable outVar; +algorithm + outVar := match (inTypesVar) + local + String name; + DAE.Type ty; + DAE.ComponentRef cref_; + DAE.Attributes attr; + SCode.Parallelism scPrl; + DAE.VarParallelism prl; + DAE.Exp bindExp; + + case (DAE.TYPES_VAR(name=name, attributes = attr, ty=ty)) + equation + ty = Types.simplifyType(ty); + cref_ = ComponentReference.makeCrefIdent(name, ty, {}); + DAE.ATTR(parallelism = scPrl) = attr; + prl = scodeParallelismToDAEParallelism(scPrl); + bindExp = Types.getBindingExp(inTypesVar, Absyn.IDENT(name)); + then SimCode.VARIABLE(cref_, ty, SOME(bindExp), {}, prl, DAE.VARIABLE()); + end match; +end typesVar; + +protected function scodeParallelismToDAEParallelism + input SCode.Parallelism inParallelism; + output DAE.VarParallelism outParallelism; +algorithm + outParallelism := match(inParallelism) + case(SCode.PARGLOBAL()) then DAE.PARGLOBAL(); + case(SCode.PARLOCAL()) then DAE.PARLOCAL(); + case(SCode.NON_PARALLEL()) then DAE.NON_PARALLEL(); + end match; +end scodeParallelismToDAEParallelism; + +protected function variableName + input SimCode.Variable v; + output String s; +algorithm + s := match v + case SimCode.VARIABLE(name=DAE.CREF_IDENT(ident=s)) then s; + case SimCode.FUNCTION_PTR(name=s) then s; + end match; +end variableName; + +protected function compareVariable + input SimCode.Variable v1; + input SimCode.Variable v2; + output Boolean b; +algorithm + b := stringCompare(variableName(v1),variableName(v2)) > 0; +end compareVariable; + +protected function generateVarName + input DAE.Var inVar; + output String outName; +algorithm + outName := + match (inVar) + local + DAE.Ident name; + case DAE.TYPES_VAR(name = name) then name; + else "NULL"; + end match; +end generateVarName; + +protected function elaborateNestedRecordDeclarations +"Helper function to elaborateRecordDeclarations." + input list inRecordTypes; + input list inAccRecordDecls; + input list inReturnTypes; + output list outRecordDecls; + output list outReturnTypes; +algorithm + (outRecordDecls, outReturnTypes) := matchcontinue (inRecordTypes, inAccRecordDecls, inReturnTypes) + local + DAE.Type ty; + list rest; + list rt, rt_1, rt_2; + list accRecDecls; + case ({}, accRecDecls, rt) + then (accRecDecls, rt); + case (DAE.TYPES_VAR(ty = ty as DAE.T_COMPLEX(complexClassType = ClassInf.RECORD(_)))::rest, accRecDecls, rt) + equation + (accRecDecls, rt_1) = elaborateRecordDeclarationsForRecord(ty, accRecDecls, rt); + (accRecDecls, rt_2) = elaborateNestedRecordDeclarations(rest, accRecDecls, rt_1); + then (accRecDecls, rt_2); + case (_::rest, accRecDecls, rt) + equation + (accRecDecls, rt_1) = elaborateNestedRecordDeclarations(rest, accRecDecls, rt); + then (accRecDecls, rt_1); + end matchcontinue; +end elaborateNestedRecordDeclarations; + +protected function elaborateRecordDeclarationsForMetarecords + input list inExpl; + input list inAccRecordDecls; + input list inReturnTypes; + output list outRecordDecls; + output list outReturnTypes; +algorithm + (outRecordDecls, outReturnTypes) := match (inExpl, inAccRecordDecls, inReturnTypes) + local + list rt, rt_1, rt_2, fieldNames; + list rest; + String name; + Absyn.Path path; + list accRecDecls; + Boolean b; + + case ({}, accRecDecls, rt) then (accRecDecls, rt); + case (DAE.METARECORDCALL(path=path, fieldNames=fieldNames)::rest, accRecDecls, rt) + equation + name = Absyn.pathStringUnquoteReplaceDot(path, "_"); + b = listMember(name, rt); + accRecDecls = List.consOnTrue(not b, SimCode.RECORD_DECL_DEF(path, fieldNames), accRecDecls); + rt_1 = List.consOnTrue(not b, name, rt); + (accRecDecls, rt_2) = elaborateRecordDeclarationsForMetarecords(rest, accRecDecls, rt_1); + then (accRecDecls, rt_2); + case (_::rest, accRecDecls, rt) + equation + (accRecDecls, rt_1) = elaborateRecordDeclarationsForMetarecords(rest, accRecDecls, rt); + then (accRecDecls, rt_1); + end match; +end elaborateRecordDeclarationsForMetarecords; + + +protected function generateExtFunctionIncludes "by investigating the annotation of an external function." + input Absyn.Program program; + input Absyn.Path path; + input Option inAbsynAnnotationOption; + input SourceInfo info; + output list includes; + output list includeDirs; + output list libs; + output list paths; + output Boolean dynamcLoad; +algorithm + (includes, includeDirs, libs,paths, dynamcLoad):= + match (program, path, inAbsynAnnotationOption) + local + SCode.Mod mod; + Boolean b; + String target; + Option odir, resources; + list libNames, fullLibNames, dirs; + + case (_, _, SOME(SCode.ANNOTATION(mod))) + algorithm + b := generateExtFunctionDynamicLoad(mod); + target := Flags.getConfigString(Flags.TARGET); + (libs, libNames) := generateExtFunctionIncludesLibstr(target,mod); + includes := generateExtFunctionIncludesIncludestr(mod); + (libs, dirs, resources) := generateExtFunctionLibraryDirectoryFlags(program, path, mod, libs); + for name in if Flags.isSet(Flags.CHECK_EXT_LIBS) then libNames else {} loop + if target=="msvc" or System.os()=="Windows_NT" then + fullLibNames := {name + System.getDllExt(), "lib" + name + ".a", "lib" + name + ".lib"}; + else + fullLibNames := {"lib" + name + ".a", "lib" + name + System.getDllExt()}; + end if; + lookForExtFunctionLibrary(fullLibNames, dirs, name, resources, path, info); + end for; + paths := generateExtFunctionLibraryDirectoryPaths(program, path, mod); + includeDirs := generateExtFunctionIncludeDirectoryFlags(program, path, mod, includes); + then + (includes, includeDirs, libs,paths, b); + case (_, _, NONE()) then ({}, {}, {},{}, false); + end match; +end generateExtFunctionIncludes; + +protected function lookForExtFunctionLibrary + input list names; + input list dirs; + input String name; + input Option resources; + input Absyn.Path path; + input SourceInfo info; +algorithm + if not max(System.regularFileExists(d+"/"+n) for d in dirs, n in names) then + _ := match resources + local + String resourcesStr, tmpdir, cmd, pwd, contents, found; + Integer status; + Boolean didFind; + case SOME(resourcesStr) + algorithm + if System.directoryExists(resourcesStr) then + didFind := false; + for dir in list(dir for dir guard System.regularFileExists(resourcesStr + "/BuildProjects/" + dir + "/autogen.sh") in System.subDirectories(resourcesStr + "/BuildProjects")) loop + tmpdir := System.createTemporaryDirectory(Settings.getTempDirectoryPath() + "/omc_compile_" + name + "_"); + Error.addSourceMessage(Error.COMPILER_NOTIFICATION, {"Created directory " + tmpdir}, info); + cmd := "cp -a \"" + resourcesStr + "\"/* \"" + tmpdir + "\""; + Error.addSourceMessage(Error.COMPILER_NOTIFICATION, {cmd}, info); + System.systemCall(cmd); + pwd := System.pwd(); + if 0==System.cd(tmpdir + "/BuildProjects/" + dir) then + Error.addSourceMessage(Error.COMPILER_NOTIFICATION, {"Changed directory to " + System.pwd()}, info); + // TODO: Add $(host) + cmd := "sh ./autogen.sh && ./configure --libdir='"+userCompiledBinariesDirectory(path)+"' && make && make install"; + status := System.systemCall(cmd, "log"); + contents := System.readFile("log"); + if status <> 0 then + Error.addSourceMessage(Error.COMPILER_WARNING, {"Failed to run "+cmd+": " + contents}, info); + else + Error.addSourceMessage(Error.COMPILER_NOTIFICATION, {"Succeeded with compilation and installation of the library using:\ncommand: "+cmd+"\n" + contents}, info); + if not max(System.regularFileExists(d+"/"+n) for d in dirs, n in names) then + Error.addSourceMessage(Error.EXT_LIBRARY_NOT_FOUND_DESPITE_COMPILATION_SUCCESS, {cmd, System.pwd()}, info); + else + found := listHead(list(x for x guard System.regularFileExists(x) in List.flatten(list(d+"/"+n for d in dirs, n in names)))); + Error.addSourceMessage(Error.COMPILER_NOTIFICATION, {"Compiled "+found+" by running build project " + resourcesStr + "/BuildProjects/" + dir}, info); + didFind := true; + end if; + end if; + else + Error.addSourceMessage(Error.COMPILER_WARNING, {"Failed to change directory to " + tmpdir + "/BuildProjects/" + dir}, info); + end if; + System.cd(pwd); + System.removeDirectory(tmpdir); + Error.addSourceMessage(Error.COMPILER_NOTIFICATION, {"Removed directory " + tmpdir}, info); + if didFind then + break; + end if; + end for; + end if; + then (); + else (); + end match; + if not max(System.regularFileExists(d+"/"+n) for d in dirs, n in names) then + // suppress this warning if we're running the testsuite + if not Config.getRunningTestsuite() then + Error.addSourceMessage(Error.EXT_LIBRARY_NOT_FOUND, {name, sum("\n " + d + "/" + n for d in dirs, n in names)}, info); + end if; + end if; + end if; +end lookForExtFunctionLibrary; + +protected function generateExtFunctionIncludeDirectoryFlags + "Process LibraryDirectory and IncludeDirectory" + input Absyn.Program program; + input Absyn.Path path; + input SCode.Mod inMod; + input list includes; + output list outDirs; +algorithm + outDirs := matchcontinue (program, path, inMod, includes) + local + String str,istr; + case (_, _, _, {}) then {}; + case (_, _, _, _) + equation + SCode.MOD(binding = SOME(Absyn.STRING(str))) = + Mod.getUnelabedSubMod(inMod, "IncludeDirectory"); + str = CevalScript.getFullPathFromUri(program, str, false); + istr = "\"-I"+str+"\""; + then if System.directoryExists(str) then {istr} else {}; + case (_, _, _, _) + equation + str = "modelica://" + Absyn.pathFirstIdent(path) + "/Resources/Include"; + str = CevalScript.getFullPathFromUri(program, str, false); + istr = "\"-I"+str+"\""; + then if System.directoryExists(str) then {istr} else {}; + // Read SourceInfo instead? + else {}; + end matchcontinue; +end generateExtFunctionIncludeDirectoryFlags; + +protected function generateExtFunctionLibraryDirectoryFlags + "Process LibraryDirectory and IncludeDirectory" + input Absyn.Program program; + input Absyn.Path path; + input SCode.Mod inMod; + input list inLibs; + output list outLibs; + output list installDirs; + output Option resources; +algorithm + (outLibs, installDirs, resources) := matchcontinue (program, path, inMod, inLibs) + local + String str, str1, str2, str3, platform1, platform2, target, dir, resourcesStr; + list libs, libs2; + Boolean isLinux; + case (_, _, _, {}) then ({}, {}, NONE()); + case (_, _, _, libs) + algorithm + str := matchcontinue inMod + case _ + equation + SCode.MOD(binding = SOME(Absyn.STRING(str))) = Mod.getUnelabedSubMod(inMod, "LibraryDirectory"); + then str; + else "modelica://" + Absyn.pathFirstIdent(path) + "/Resources/Library"; + end matchcontinue; + str := CevalScript.getFullPathFromUri(program, str, false); + resourcesStr := CevalScript.getFullPathFromUri(program, "modelica://" + Absyn.pathFirstIdent(path) + "/Resources", false); + platform1 := str + "/" + System.openModelicaPlatform(); + platform2 := str + "/" + System.modelicaPlatform(); + isLinux := stringEq("linux",System.os()); + target := Flags.getConfigString(Flags.TARGET); + // please, take care about ordering these libraries, the most specific should have the highest priority + libs2 := str::platform2::platform1::(Settings.getHomeDir(false)+"/.openmodelica/binaries/"+Absyn.pathFirstIdent(path))::(Settings.getInstallationDirectoryPath() + "/lib/" + System.getTriple() + "/omc")::(Settings.getInstallationDirectoryPath() + "/lib/")::{}; + libs := List.fold2(libs2, generateExtFunctionLibraryDirectoryFlags2, isLinux, target, libs); + then (libs, listReverse(libs2), SOME(resourcesStr)); + else (inLibs, {}, NONE()); + end matchcontinue; +end generateExtFunctionLibraryDirectoryFlags; + +protected function generateExtFunctionLibraryDirectoryFlags2 + input String dir; + input Boolean isLinux; + input String target; + input list inLibs; + output list libs; +algorithm + libs := if isLinux then "-Wl,-rpath=\"" + dir + "\""::inLibs else inLibs; + libs := (if target=="msvc" then "/LIBPATH:\"" + dir + "\"" else "\"-L" + dir + "\"")::libs; +end generateExtFunctionLibraryDirectoryFlags2; + +protected function userCompiledBinariesDirectory + input Absyn.Path path; + output String str = Settings.getHomeDir(false)+"/.openmodelica/binaries/"+Absyn.pathFirstIdent(path); +end userCompiledBinariesDirectory; + +protected function generateExtFunctionLibraryDirectoryPaths + "Process LibraryDirectory and IncludeDirectory" + input Absyn.Program program; + input Absyn.Path path; + input SCode.Mod inMod; + output list outLibs; +algorithm + outLibs := matchcontinue (program, path, inMod) + local + String str, str1, str2, str3, platform1, platform2,target; + list libs; + Boolean isLinux; + case (_, _, _) + equation + SCode.MOD(binding = SOME(Absyn.STRING(str))) = + Mod.getUnelabedSubMod(inMod, "LibraryDirectory"); + str = CevalScript.getFullPathFromUri(program, str, false); + platform1 = System.openModelicaPlatform(); + platform2 = System.modelicaPlatform(); + isLinux = stringEq("linux",System.os()); + // please, take care about ordering these libraries, the most specific should go first (in reverse here) + libs = generateExtFunctionLibraryDirectoryPaths2(true, str, isLinux, {} ); + libs = generateExtFunctionLibraryDirectoryPaths2(not stringEq(platform2,""), str + "/" + platform2, isLinux, libs); + libs = generateExtFunctionLibraryDirectoryPaths2(not stringEq(platform1,""), str + "/" + platform1, isLinux, libs); + then libs; + case (_, _, _) + equation + str = "modelica://" + Absyn.pathFirstIdent(path) + "/Resources/Library"; + str = CevalScript.getFullPathFromUri(program, str, false); + platform1 = System.openModelicaPlatform(); + platform2 = System.modelicaPlatform(); + isLinux = stringEq("linux",System.os()); + // please, take care about ordering these libraries, the most specific should go first (in reverse here) + libs = generateExtFunctionLibraryDirectoryPaths2(true, str, isLinux, {} ); + libs = generateExtFunctionLibraryDirectoryPaths2(not stringEq(platform2,""), str + "/" + platform2, isLinux, libs); + libs = generateExtFunctionLibraryDirectoryPaths2(not stringEq(platform1,""), str + "/" + platform1, isLinux, libs); + then libs; + else {}; + end matchcontinue; +end generateExtFunctionLibraryDirectoryPaths; + + +protected function generateExtFunctionLibraryDirectoryPaths2 + input Boolean add; + input String dir; + input Boolean isLinux; + input list inLibs; + output list libs; +algorithm + libs := match (add,dir,isLinux,inLibs) + local + Boolean b; + case (true,_,_,libs) + equation + b = System.directoryExists(dir); + libs = List.consOnTrue(b, dir , libs); + then libs; + else inLibs; + end match; +end generateExtFunctionLibraryDirectoryPaths2; + + +protected function getLibraryStringInMSVCFormat +"Takes an Absyn.STRING describing a library and outputs a list +of strings corresponding to it. +Note: Normally only outputs a single string, but Lapack on MinGW is special." + input Absyn.Exp exp; + output list strs; + output list names; +algorithm + (strs,names) := matchcontinue exp + local + String str; + + // seems lapack can show on Lapack form or lapack (different case) (MLS revision 6155) + // Lapack on MinGW/Windows is linked against f2c + case Absyn.STRING(str) guard str=="Lapack" or str=="lapack" + then ({"lapack_win32_MT.lib", "f2c.lib"}, {}); + + // omcruntime on windows needs linking with mico2313 and wsock and then some :) + case Absyn.STRING("omcruntime") + equation + true = "Windows_NT" == System.os(); + strs = {"f2c.lib", "initialization.lib", "libexpat.lib", "math-support.lib", "meta.lib", "ModelicaExternalC.lib", "results.lib", "simulation.lib", "solver.lib", "sundials_kinsol.lib", "sundials_nvecserial.lib", "util.lib", "lapack_win32_MT.lib"}; + then + (strs, {}); + + // Wonder if there may be issues if we have duplicates in the Corba libs + // and the other libs. Some other developer will probably swear over this + // hack some day, but at least I get an early weekend. + case Absyn.STRING("OpenModelicaCorba") + equation + str = System.getCorbaLibs(); + then ({str},{}); + + case Absyn.STRING("fmilib") + then ({"fmilib.lib","shlwapi.lib"},{}); + + // If the string starts with a -, it's probably -l or -L gcc flags + case Absyn.STRING(str) + equation + true = "-" == stringGetStringChar(str, 1); + then ({str},{}); + + case Absyn.STRING(str) + equation + str = str + ".lib"; + then ({str},{}); + + else + equation + Error.addInternalError("Failed to process Library annotation for external function", sourceInfo()); + then fail(); + end matchcontinue; +end getLibraryStringInMSVCFormat; + +protected function getLibraryStringInGccFormat +"Takes an Absyn.STRING describing a library and outputs a list +of strings corresponding to it. +Note: Normally only outputs a single string, but Lapack on MinGW is special." + input Absyn.Exp exp; + output list strs; + output list names; +algorithm + (strs,names) := matchcontinue exp + local + String str, fopenmp; + + // Lapack is always included + case Absyn.STRING("lapack") then ({},{}); + case Absyn.STRING("Lapack") then ({},{}); + + case Absyn.STRING(str as "omcruntime") + equation + if "Windows_NT" == System.os() then + // omcruntime on windows needs linking with mico2313 and wsock and then some :) + str = "-l" + str; + strs = str :: "-lintl" :: "-liconv" :: "-lexpat" :: "-lsqlite3" :: "-llpsolve55" :: "-lmico2313" :: "-lws2_32" :: "-lregex" :: {}; + else + strs = System.getRuntimeLibs(); + end if; + then (strs,{}); + + // Wonder if there may be issues if we have duplicates in the Corba libs + // and the other libs. Some other developer will probably swear over this + // hack some day, but at least I get an early weekend. + case Absyn.STRING("OpenModelicaCorba") + equation + str = System.getCorbaLibs(); + then ({str},{}); + + case Absyn.STRING("fmilib") + then (if System.os()=="Windows_NT" then {"-lfmilib","-lshlwapi"} else {"-lfmilib"},{}); + + case Absyn.STRING(str) + equation + // If the string is a file, return it as it is + // If the string starts with a -, it's probably -l or -L gcc flags + if System.regularFileExists(str) or "-" == stringGetStringChar(str, 1) then + strs = {str}; + names = {}; + else + strs = {"-l" + str}; + names = {str}; + end if; + + then (strs,names); + + else + equation + Error.addInternalError("Failed to process Library annotation for external function", sourceInfo()); + then fail(); + end matchcontinue; +end getLibraryStringInGccFormat; + +protected function generateExtFunctionIncludesLibstr + input String target; + input SCode.Mod inMod; + output list outStringLst; + output list names; +algorithm + (outStringLst, names) := matchcontinue (target,inMod) + local + list arr; + list libs; + list> libsList, namesList; + Absyn.Exp exp; + case ("msvc",_) + equation + SCode.MOD(binding = SOME(Absyn.ARRAY(arr))) = + Mod.getUnelabedSubMod(inMod, "Library"); + (libsList, namesList) = List.map_2(arr, getLibraryStringInMSVCFormat); + then + (List.flatten(libsList), List.flatten(namesList)); + case ("msvc",_) + equation + SCode.MOD(binding = SOME(exp)) = + Mod.getUnelabedSubMod(inMod, "Library"); + (libs,names) = getLibraryStringInMSVCFormat(exp); + then + (libs,names); + case (_,_) + equation + SCode.MOD(binding = SOME(Absyn.ARRAY(arr))) = + Mod.getUnelabedSubMod(inMod, "Library"); + (libsList, namesList) = List.map_2(arr, getLibraryStringInGccFormat); + then + (List.flatten(libsList), List.flatten(namesList)); + case (_,_) + equation + SCode.MOD(binding = SOME(exp)) = + Mod.getUnelabedSubMod(inMod, "Library"); + (libs,names) = getLibraryStringInGccFormat(exp); + then + (libs,names); + else ({},{}); + end matchcontinue; +end generateExtFunctionIncludesLibstr; + +protected function generateExtFunctionIncludesIncludestr + input SCode.Mod inMod; + output list includes; +algorithm + includes := matchcontinue (inMod) + local + String inc, inc_1; + Integer lineNumberStart; + String str,fileName; + case (_) + equation + SCode.MOD(binding = SOME(Absyn.STRING(inc)), info = SOURCEINFO(fileName=fileName,lineNumberStart=lineNumberStart)) = + Mod.getUnelabedSubMod(inMod, "Include"); + str = "#line "+intString(lineNumberStart)+" \""+fileName+"\""; + inc_1 = System.unescapedString(inc); + includes = if Config.acceptMetaModelicaGrammar() or Flags.isSet(Flags.GEN_DEBUG_SYMBOLS) then {str,inc_1} else {inc_1}; + then includes; + else {}; + end matchcontinue; +end generateExtFunctionIncludesIncludestr; + +protected function generateExtFunctionDynamicLoad + input SCode.Mod inMod; + output Boolean outDynamicLoad; +algorithm + outDynamicLoad:= matchcontinue (inMod) + local + Boolean b; + case (_) + equation + SCode.MOD(binding = SOME((Absyn.BOOL(b)))) = + Mod.getUnelabedSubMod(inMod, "DynamicLoad"); + then + b; + else false; + end matchcontinue; +end generateExtFunctionDynamicLoad; + +public function getImplicitRecordConstructors + "If a record instance is sent to a function we need to generate code for the + record constructor even if it's not explicitly called, because the constructor + is used by the generated code. This function checks the arguments of a + function for these implicit record constructor calls and returns a list of all + record constructors that are used." + input list inExpLst; + output list outExpLst; +algorithm + outExpLst := matchcontinue(inExpLst) + local + DAE.ComponentRef cref; + DAE.Type record_type; + Absyn.Path record_path; + list rest_expr; + DAE.Exp record_cref; + case ({}) then {}; + // A record component reference. + case (DAE.CREF( + componentRef = cref, + ty = (DAE.T_COMPLEX( + complexClassType = ClassInf.RECORD(path = record_path)))) :: rest_expr) + equation + // Make sure it has no subscripts, i.e. it's a component reference for + // an entire record instance. + {} = ComponentReference.crefLastSubs(cref); + // Build a DAE.CREF from the record path. + cref = ComponentReference.pathToCref(record_path); + record_cref = Expression.crefExp(cref); + rest_expr = getImplicitRecordConstructors(rest_expr); + then record_cref :: rest_expr; + case (_ :: rest_expr) + equation + rest_expr = getImplicitRecordConstructors(rest_expr); + then rest_expr; + end matchcontinue; +end getImplicitRecordConstructors; + +protected function getCalledFunctionsInFunctions "Goes through the given DAE, finds the given functions and collects + the names of the functions called from within those functions" + input list paths; + input HashTableStringToPath.HashTable inHt; + input DAE.FunctionTree funcs; + output HashTableStringToPath.HashTable outHt; +algorithm + outHt := match (paths, inHt, funcs) + local + list rest; + Absyn.Path path; + HashTableStringToPath.HashTable ht; + + case ({}, ht, _) then ht; + case (path::rest, ht, _) + equation + ht = getCalledFunctionsInFunction2(path, Absyn.pathStringNoQual(path), ht, funcs); + ht = getCalledFunctionsInFunctions(rest, ht, funcs); + then ht; + end match; +end getCalledFunctionsInFunctions; + +public function getCalledFunctionsInFunction2 "Goes through the given DAE, finds the given function and collects + the names of the functions called from within those functions" + input Absyn.Path inPath; + input String pathstr; + input HashTableStringToPath.HashTable inHt "paths to not add"; + input DAE.FunctionTree funcs; + output HashTableStringToPath.HashTable outHt "paths to not add"; +algorithm + outHt := matchcontinue (inPath, pathstr, inHt, funcs) + local + String str; + Absyn.Path path; + DAE.Function funcelem; + list calledfuncs, varfuncs; + list els; + HashTableStringToPath.HashTable ht; + + case (_, _, ht, _) + equation + BaseHashTable.get(pathstr, ht); + then ht; + + case (path, _, ht, _) + equation + funcelem = DAEUtil.getNamedFunction(path, funcs); + els = DAEUtil.getFunctionElements(funcelem); + // SimCode.Function reference variables are filtered out + varfuncs = List.fold(els, DAEUtil.collectFunctionRefVarPaths, {}); + (_, (_, varfuncs)) = DAEUtil.traverseDAE2(els, Expression.traverseSubexpressionsHelper, (DAEUtil.collectValueblockFunctionRefVars, varfuncs)); + (_, (_, (calledfuncs, _))) = DAEUtil.traverseDAE2(els, Expression.traverseSubexpressionsHelper, (matchNonBuiltinCallsAndFnRefPaths, ({}, varfuncs))); + ht = BaseHashTable.add((pathstr, path), ht); + ht = addDestructor(funcelem, ht); + ht = getCalledFunctionsInFunctions(calledfuncs, ht, funcs); + then ht; + + case (path, _, _, _) + equation + failure(_ = DAEUtil.getNamedFunction(path, funcs)); + str = "function getCalledFunctionsInFunction2: Class " + pathstr + " not found in global scope."; + Error.addInternalError(str, sourceInfo()); + then + fail(); + end matchcontinue; +end getCalledFunctionsInFunction2; + +protected function addDestructor + input DAE.Function func; + input HashTableStringToPath.HashTable inHt; + output HashTableStringToPath.HashTable outHt; +algorithm + outHt := match (func,inHt) + local + Absyn.Path path; + String pathstr; + case (DAE.FUNCTION(type_=DAE.T_FUNCTION(funcResultType=DAE.T_COMPLEX(complexClassType=ClassInf.EXTERNAL_OBJ(path=path)))),_) + equation + path = Absyn.joinPaths(path,Absyn.IDENT("destructor")); + then addDestructor2(path,Absyn.pathStringNoQual(path),inHt); + else inHt; + end match; +end addDestructor; + +protected function addDestructor2 + input Absyn.Path path; + input String pathstr; + input HashTableStringToPath.HashTable inHt; + output HashTableStringToPath.HashTable ht = inHt; +algorithm + if not BaseHashTable.hasKey(pathstr, ht) then + BaseHashTable.add((pathstr, path), ht); + end if; +end addDestructor2; + +protected function matchNonBuiltinCallsAndFnRefPaths "The extra argument is a tuple; the second list is the list of variable + names to filter out (so we don't add function references variables)" + input DAE.Exp inExp; + input tuple, list> itpl; + output DAE.Exp outExp; + output tuple, list> otpl; +algorithm + (outExp,otpl) := matchcontinue (inExp,itpl) + local + Absyn.Path path; + list acc, filter; + case (DAE.CALL(path = path, attr = DAE.CALL_ATTR(builtin = false)), (acc, filter)) + equation + path = Absyn.makeNotFullyQualified(path); + false = List.isMemberOnTrue(path, filter, Absyn.pathEqual); + then (inExp, (path::acc, filter)); + case (DAE.REDUCTION(reductionInfo = DAE.REDUCTIONINFO(path = path)), (acc, filter)) + equation + false = List.isMemberOnTrue(path, {Absyn.IDENT("list"),Absyn.IDENT("listReverse"),Absyn.IDENT("array"),Absyn.IDENT("min"),Absyn.IDENT("max"),Absyn.IDENT("sum"),Absyn.IDENT("product")}, Absyn.pathEqual); + false = List.isMemberOnTrue(path, filter, Absyn.pathEqual); + then (inExp, (path::acc, filter)); + case (DAE.PARTEVALFUNCTION(path = path), (acc, filter)) + equation + path = Absyn.makeNotFullyQualified(path); + false = List.isMemberOnTrue(path, filter, Absyn.pathEqual); + then (inExp, (path::acc, filter)); + case (DAE.CREF(ty = DAE.T_FUNCTION_REFERENCE_FUNC(builtin = false)), (acc, filter)) + equation + path = Absyn.crefToPath(getCrefFromExp(inExp)); + false = List.isMemberOnTrue(path, filter, Absyn.pathEqual); + then (inExp, (path::acc, filter)); + else (inExp,itpl); + end matchcontinue; +end matchNonBuiltinCallsAndFnRefPaths; +protected function aliasRecordDeclarations + input SimCode.RecordDeclaration inDecl; + input HashTableStringToPath.HashTable inHt; + output SimCode.RecordDeclaration decl; + output HashTableStringToPath.HashTable ht; +algorithm + (decl,ht) := match (inDecl,inHt) + local + list vars; + Absyn.Path name; + String str,sname; + Option alias; + case (SimCode.RECORD_DECL_FULL(sname, _, name, vars),_) + equation + str = stringDelimitList(List.map(vars, variableString), "\n"); + (alias,ht) = aliasRecordDeclarations2(str, name, inHt); + then (SimCode.RECORD_DECL_FULL(sname, alias, name, vars),ht); + else (inDecl,inHt); + end match; +end aliasRecordDeclarations; + +protected function aliasRecordDeclarations2 + input String str; + input Absyn.Path path; + input HashTableStringToPath.HashTable inHt; + output Option alias; + output HashTableStringToPath.HashTable ht; +algorithm + (alias,ht) := matchcontinue (str,path,inHt) + local + String aliasStr; + case (_,_,_) + equation + aliasStr = Absyn.pathStringUnquoteReplaceDot(BaseHashTable.get(str, inHt),"_"); + then (SOME(aliasStr),inHt); + else + equation + ht = BaseHashTable.add((str,path),inHt); + then (NONE(),ht); + end matchcontinue; +end aliasRecordDeclarations2; + +protected function variableString + input SimCode.Variable var; + output String str; +algorithm + str := match var + local + DAE.ComponentRef name; + DAE.Type ty; + case SimCode.VARIABLE(name=name, ty=ty) + then Types.unparseType(ty) + " " + ComponentReference.printComponentRefStr(name); + case SimCode.FUNCTION_PTR(name=str) + then "modelica_fnptr " + str; + end match; +end variableString; + +/****** HashTable ComponentRef -> SimCodeVar.SimVar ******/ +/* a workaround to enable "cross public import" */ + + +/* HashTable instance specific code */ + +protected function keyEqual + input SimCode.Key key1; + input SimCode.Key key2; + output Boolean res; +algorithm + res := ComponentReference.crefEqualNoStringCompare(key1, key2); +end keyEqual; + +/* end of HashTable instance specific code */ + +public function emptyHashTableSized " + author: PA + Returns an empty HashTable. + Using the bucketsize 100 and array size 10." + input Integer size; + output SimCode.HashTableCrefToSimVar hashTable; +protected + array>> arr; + list>> lst; + array>> emptyarr; + Integer szArr; +algorithm + arr := arrayCreate(size, {}); + emptyarr := arrayCreate(size, NONE()); + szArr:=realInt(realMul(intReal(size), 0.6)); + hashTable := SimCode.HASHTABLE(arr, SimCode.VALUE_ARRAY(0, szArr, emptyarr), size, 0); +end emptyHashTableSized; + +public function add " + author: PA + + Add a Key-Value tuple to hashtable. + If the Key-Value tuple already exists, the function updates the Value. +" + input tuple entry; + input SimCode.HashTableCrefToSimVar hashTable; + output SimCode.HashTableCrefToSimVar outHashTable; +algorithm + outHashTable := matchcontinue (entry, hashTable) + local + Integer indx, newpos, n, n_1, bsize, indx_1; + SimCode.ValueArray varr_1, varr; + list> indexes; + array>> hashvec_1, hashvec; + tuple v, newv; + SimCode.Key key; + SimCode.Value value; + /* Adding when not existing previously */ + case ((v as (key, _)), (SimCode.HASHTABLE(hashvec, varr, bsize, _))) + equation + failure((_) = get(key, hashTable)); + indx = ComponentReference.hashComponentRefMod(key,bsize); + newpos = valueArrayLength(varr); + varr_1 = valueArrayAdd(varr, v); + indexes = hashvec[indx + 1]; + hashvec_1 = arrayUpdate(hashvec, indx + 1, ((key, newpos) :: indexes)); + n_1 = valueArrayLength(varr_1); + then SimCode.HASHTABLE(hashvec_1, varr_1, bsize, n_1); + + /* adding when already present => Updating value */ + case ((newv as (key, _)), (SimCode.HASHTABLE(hashvec, varr, bsize, n))) + equation + (_, indx) = get1(key, hashTable); + // print("adding when present, indx =" );print(intString(indx));print("\n"); + varr_1 = valueArraySetnth(varr, indx, newv); + then SimCode.HASHTABLE(hashvec, varr_1, bsize, n); + case (_, _) + equation + print("- HashTableCrefToSimVar.add failed\n"); + then + fail(); + end matchcontinue; +end add; + +public function addNoUpdCheck " + author: PA + + Add a Key-Value tuple to hashtable. + If the Key-Value tuple already exists, the function updates the Value. +" + input tuple entry; + input SimCode.HashTableCrefToSimVar hashTable; + output SimCode.HashTableCrefToSimVar outHashTable; +algorithm + outHashTable := matchcontinue (entry, hashTable) + local + Integer hval, indx, newpos, n, n_1, bsize, indx_1; + SimCode.ValueArray varr_1, varr; + list> indexes; + array>> hashvec_1, hashvec; + String name_str; + tuple v, newv; + SimCode.Key key; + SimCode.Value value; + + // adding when not existing previously + case ((v as (key, _)), SimCode.HASHTABLE(hashvec, varr, bsize, _)) + equation + indx = ComponentReference.hashComponentRefMod(key,bsize); + newpos = valueArrayLength(varr); + varr_1 = valueArrayAdd(varr, v); + indexes = hashvec[indx + 1]; + hashvec_1 = arrayUpdate(hashvec, indx + 1, ((key, newpos) :: indexes)); + n_1 = valueArrayLength(varr_1); + then SimCode.HASHTABLE(hashvec_1, varr_1, bsize, n_1); + + // failure + else + equation + print("- HashTableCrefToSimVar.addNoUpdCheck failed\n"); + then + fail(); + end matchcontinue; +end addNoUpdCheck; + +public function get " +author: PA + + Returns a Value given a Key and a HashTable. +" + input SimCode.Key key; + input SimCode.HashTableCrefToSimVar hashTable; + output SimCode.Value value; +algorithm + (value, _):= get1(key, hashTable); +end get; + +protected function get1 "help function to get" + input SimCode.Key key; + input SimCode.HashTableCrefToSimVar hashTable; + output SimCode.Value value; + output Integer indx; +algorithm + (value, indx):= + match (key, hashTable) + local + Integer bsize, n; + list> indexes; + SimCode.Value v; + array>> hashvec; + SimCode.ValueArray varr; + SimCode.Key k; + case (_, (SimCode.HASHTABLE(hashvec, varr, bsize, _))) + equation + indx = ComponentReference.hashComponentRefMod(key,bsize); + indexes = hashvec[indx + 1]; + indx = get2(key, indexes); + (k, v) = valueArrayNth(varr, indx); + true = keyEqual(k, key); + then + (v, indx); + end match; +end get1; + +protected function get2 " + author: PA + + Helper function to get +" + input SimCode.Key key; + input list> keyIndices; + output Integer index; +algorithm + index := + matchcontinue (key, keyIndices) + local + SimCode.Key key2; + list> xs; + case (_, ((key2, index) :: _)) + equation + true = keyEqual(key, key2); + then + index; + case (_, (_ :: xs)) + equation + index = get2(key, xs); + then + index; + end matchcontinue; +end get2; + +public function valueArrayLength " + author: PA + + Returns the number of elements in the ValueArray +" + input SimCode.ValueArray valueArray; + output Integer size; +algorithm + size := match (valueArray) + case (SimCode.VALUE_ARRAY(numberOfElements = size)) then size; + end match; +end valueArrayLength; + +public function valueArrayAdd "author: PA + Adds an entry last to the ValueArray, increasing array size + if no space left by factor 1.4 +" + input SimCode.ValueArray valueArray; + input tuple entry; + output SimCode.ValueArray outValueArray; +algorithm + outValueArray:= + matchcontinue (valueArray, entry) + local + Integer n_1, n, size, expandsize, expandsize_1, newsize; + array>> arr_1, arr, arr_2; + Real rsize, rexpandsize; + case (SimCode.VALUE_ARRAY(numberOfElements = n, arrSize = size, valueArray = arr), _) + equation + (n < size) = true "Have space to add array elt."; + n_1 = n + 1; + arr_1 = arrayUpdate(arr, n + 1, SOME(entry)); + then + SimCode.VALUE_ARRAY(n_1, size, arr_1); + + case (SimCode.VALUE_ARRAY(numberOfElements = n, arrSize = size, valueArray = arr), _) + equation + (n < size) = false "Do NOT have splace to add array elt. Expand with factor 1.4"; + rsize = intReal(size); + rexpandsize = rsize * 0.4; + expandsize = realInt(rexpandsize); + expandsize_1 = intMax(expandsize, 1); + newsize = expandsize_1 + size; + arr_1 = Array.expand(expandsize_1, arr, NONE()); + n_1 = n + 1; + arr_2 = arrayUpdate(arr_1, n + 1, SOME(entry)); + then + SimCode.VALUE_ARRAY(n_1, newsize, arr_2); + case (_, _) + equation + print("-HashTableCrefToSimVar.valueArrayAdd failed\n"); + then + fail(); + end matchcontinue; +end valueArrayAdd; + +public function valueArraySetnth "author: PA + Set the n:th variable in the ValueArray to value. +" + input SimCode.ValueArray valueArray; + input Integer pos; + input tuple entry; + output SimCode.ValueArray outValueArray; +algorithm + outValueArray:= + matchcontinue (valueArray, pos, entry) + local + array>> arr_1, arr; + Integer n, size; + case (SimCode.VALUE_ARRAY(n, size, arr), _, _) + equation + (pos < size) = true; + arr_1 = arrayUpdate(arr, pos + 1, SOME(entry)); + then + SimCode.VALUE_ARRAY(n, size, arr_1); + case (_, _, _) + equation + print("-HashTableCrefToSimVar.valueArraySetnth failed\n"); + then + fail(); + end matchcontinue; +end valueArraySetnth; + +public function valueArrayNth "author: PA + + Retrieve the n:th Vale from ValueArray, index from 0..n-1. + " + input SimCode.ValueArray valueArray; + input Integer pos; + output SimCode.Key key; + output SimCode.Value value; +algorithm + (key, value) := + matchcontinue (valueArray, pos) + local + SimCode.Key k; + SimCode.Value v; + Integer n; + array>> arr; + case (SimCode.VALUE_ARRAY(numberOfElements = n, valueArray = arr), _) + equation + (pos < n) = true; + SOME((k, v)) = arr[pos + 1]; + then + (k, v); + case (SimCode.VALUE_ARRAY(numberOfElements = n, valueArray = arr), _) + equation + (pos < n) = true; + NONE() = arr[pos + 1]; + then + fail(); + end matchcontinue; +end valueArrayNth; + +/***** end of HashTable ComponentRef -> SimCodeVar.SimVar *******/ + +public function createMakefileParams + input list includes; + input list libs; + input list libPaths; + input Boolean isFunction; + output SimCode.MakefileParams makefileParams; +protected + String omhome, ccompiler, cxxcompiler, linker, exeext, dllext, cflags, ldflags, rtlibs, platform, fopenmp,compileDir; +algorithm + ccompiler := if stringEq(Config.simCodeTarget(),"JavaScript") then "emcc" else + (if Flags.isSet(Flags.HPCOM) then System.getOMPCCompiler() else System.getCCompiler()); + cxxcompiler := if stringEq(Config.simCodeTarget(),"JavaScript") then "emcc" else System.getCXXCompiler(); + linker := if stringEq(Config.simCodeTarget(),"JavaScript") then "emcc" else System.getLinker(); + exeext := if stringEq(Config.simCodeTarget(),"JavaScript") then ".js" else System.getExeExt(); + dllext := System.getDllExt(); + omhome := Settings.getInstallationDirectoryPath(); + omhome := System.trim(omhome, "\""); // Remove any quotation marks from omhome. + cflags := System.getCFlags() + " " + + (if Flags.isSet(Flags.HPCOM) then "-fopenmp" else ""); + cflags := if stringEq(Config.simCodeTarget(),"JavaScript") then "-Os -Wno-warn-absolute-paths" else cflags; + ldflags := System.getLDFlags(); + rtlibs := if isFunction then System.getRTLibs() else System.getRTLibsSim(); + platform := System.modelicaPlatform(); + compileDir := System.pwd() + System.pathDelimiter(); + makefileParams := SimCode.MAKEFILE_PARAMS(ccompiler, cxxcompiler, linker, exeext, dllext, + omhome, cflags, ldflags, rtlibs, includes, libs,libPaths, platform,compileDir); +end createMakefileParams; + +public + +function codegenResetTryThrowIndex +algorithm + setGlobalRoot(Global.codegenTryThrowIndex, {}); +end codegenResetTryThrowIndex; + +function codegenPushTryThrowIndex + input Integer i; +protected + list lst; +algorithm + lst := getGlobalRoot(Global.codegenTryThrowIndex); + setGlobalRoot(Global.codegenTryThrowIndex, i::lst); +end codegenPushTryThrowIndex; + +function codegenPopTryThrowIndex +protected + list lst; +algorithm + lst := getGlobalRoot(Global.codegenTryThrowIndex); + _::lst := lst; + setGlobalRoot(Global.codegenTryThrowIndex, lst); +end codegenPopTryThrowIndex; + +function codegenPeekTryThrowIndex + output Integer i; +protected + list lst; +algorithm + lst := getGlobalRoot(Global.codegenTryThrowIndex); + i := match lst + case i::_ then i; + else -1; + end match; +end codegenPeekTryThrowIndex; + +public function execStat + "Prints an execution stat on the format: + *** %name% -> time: %time%, memory %memory% + Where you provide name, and time is the time since the last call using this + index (the clock is reset after each call). The memory is the total memory + consumed by the compiler at this point in time. + " + input String name; +algorithm + execStat2(Flags.isSet(Flags.EXEC_STAT),name); +end execStat; + +protected function execStat2 + input Boolean cond; + input String name; +algorithm + _ := match (cond,name) + local + Real t,total,used,allocated; + String timeStr,totalTimeStr,gcStr; + case (false,_) then (); + else + equation + t = System.realtimeTock(ClockIndexes.RT_CLOCK_EXECSTAT); + total = System.realtimeTock(ClockIndexes.RT_CLOCK_EXECSTAT_CUMULATIVE); + gcStr = GC.profStatsStr(GC.getProfStats(), head=""); + timeStr = System.snprintff("%.4g",20,t); + totalTimeStr = System.snprintff("%.4g",20,total); + if Flags.isSet(Flags.GC_PROF) then + Error.addMessage(Error.EXEC_STAT_GC,{name,timeStr,totalTimeStr,gcStr}); + else + Error.addMessage(Error.EXEC_STAT,{name,timeStr,totalTimeStr}); + end if; + System.realtimeTick(ClockIndexes.RT_CLOCK_EXECSTAT); + then (); + end match; +end execStat2; + +public function varIndex + input SimCodeVar.SimVar var; + output Integer index; +algorithm + SimCodeVar.SIMVAR(index=index) := var; +end varIndex; + +public function varName + input SimCodeVar.SimVar var; + output DAE.ComponentRef name; +algorithm + SimCodeVar.SIMVAR(name=name) := var; +end varName; + +public function isParallelFunctionContext + input SimCode.Context context; + output Boolean outBool; +algorithm + outBool := match(context) + case (SimCode.PARALLEL_FUNCTION_CONTEXT()) then true; + else false; + end match; +end isParallelFunctionContext; + +function twodigit + input Integer i; + output String outS; +algorithm + outS := + matchcontinue (i) + local String s; + case _ + equation + (i < 10) = true; + s = intString(i); + s = stringAppend("0", s); + then + s; + else intString(i); + end matchcontinue; +end twodigit; + +public function generateSubPalceholders + input DAE.ComponentRef cr; + output String outdef; +protected + list dims; + Integer nrdims; + list idxstrlst; +algorithm + dims := ComponentReference.crefDims(cr); + nrdims := listLength(dims); + idxstrlst := List.map(List.intRange(nrdims),intString); + outdef := stringDelimitList(List.threadMap(List.fill("i_", nrdims), idxstrlst, stringAppend), ","); +end generateSubPalceholders; + +annotation(__OpenModelica_Interface="backend"); +end SimCodeFunctionUtil; diff --git a/Compiler/SimCode/SimCodeMain.mo b/Compiler/SimCode/SimCodeMain.mo index dbc2724483e..c36b225e843 100644 --- a/Compiler/SimCode/SimCodeMain.mo +++ b/Compiler/SimCode/SimCodeMain.mo @@ -49,7 +49,6 @@ import DAE; import FCore; import GlobalScript; import HashTableExpToIndex; -import HashTableStringToPath; import Tpl; import Values; import SimCode; @@ -58,9 +57,8 @@ import SimCode; protected import BackendDAECreate; import BackendQSS; -import BaseHashTable; import ClockIndexes; -import CevalScript; +import CevalScriptBackend; import CodegenC; import CodegenFMU; import CodegenFMUCpp; @@ -141,13 +139,13 @@ protected algorithm System.realtimeTick(ClockIndexes.RT_CLOCK_SIMCODE); a_cref := Absyn.pathToCref(className); - fileDir := CevalScript.getFileDir(a_cref, p); + fileDir := CevalScriptBackend.getFileDir(a_cref, p); (libs,libPaths,includes, includeDirs, recordDecls, functions, outIndexedBackendDAE, _, literals) := SimCodeUtil.createFunctions(p, dae, inBackendDAE, className); (simCode,_) := SimCodeUtil.createSimCode(outIndexedBackendDAE, className, filenamePrefix, fileDir, functions, includes, includeDirs, libs, libPaths,simSettingsOpt, recordDecls, literals,Absyn.FUNCTIONARGS({},{})); timeSimCode := System.realtimeTock(ClockIndexes.RT_CLOCK_SIMCODE); - SimCodeUtil.execStat("SimCode"); + SimCodeFunctionUtil.execStat("SimCode"); System.realtimeTick(ClockIndexes.RT_CLOCK_TEMPLATES); callTargetTemplatesFMU(simCode, Config.simCodeTarget(), FMUVersion, FMUType); @@ -182,13 +180,13 @@ protected algorithm System.realtimeTick(ClockIndexes.RT_CLOCK_SIMCODE); a_cref := Absyn.pathToCref(className); - fileDir := CevalScript.getFileDir(a_cref, p); + fileDir := CevalScriptBackend.getFileDir(a_cref, p); (libs, libPaths, includes, includeDirs, recordDecls, functions, outIndexedBackendDAE, _, literals) := SimCodeUtil.createFunctions(p, dae, inBackendDAE, className); (simCode,_) := SimCodeUtil.createSimCode(outIndexedBackendDAE, className, filenamePrefix, fileDir, functions, includes, includeDirs, libs,libPaths, simSettingsOpt, recordDecls, literals,Absyn.FUNCTIONARGS({},{})); timeSimCode := System.realtimeTock(ClockIndexes.RT_CLOCK_SIMCODE); - SimCodeUtil.execStat("SimCode"); + SimCodeFunctionUtil.execStat("SimCode"); System.realtimeTick(ClockIndexes.RT_CLOCK_TEMPLATES); callTargetTemplatesXML(simCode, Config.simCodeTarget()); @@ -240,7 +238,7 @@ algorithm /* calculate stuff that we need to create SimCode data structure */ System.realtimeTick(ClockIndexes.RT_CLOCK_FRONTEND); //(cache,Values.STRING(filenameprefix),SOME(_)) = Ceval.ceval(cache,graph, fileprefix, true, SOME(st),NONE(), msg); - (cache,graph,dae,st) = CevalScript.runFrontEnd(cache,graph,className,st,false); + (cache,graph,dae,st) = CevalScriptBackend.runFrontEnd(cache,graph,className,st,false); timeFrontend = System.realtimeTock(ClockIndexes.RT_CLOCK_FRONTEND); System.realtimeTick(ClockIndexes.RT_CLOCK_BACKEND); @@ -322,7 +320,7 @@ algorithm /* calculate stuff that we need to create SimCode data structure */ System.realtimeTick(ClockIndexes.RT_CLOCK_FRONTEND); //(cache,Values.STRING(filenameprefix),SOME(_)) = Ceval.ceval(cache,graph, fileprefix, true, SOME(st),NONE(), msg); - (cache,graph,dae,st) = CevalScript.runFrontEnd(cache,graph,className,st,false); + (cache,graph,dae,st) = CevalScriptBackend.runFrontEnd(cache,graph,className,st,false); timeFrontend = System.realtimeTock(ClockIndexes.RT_CLOCK_FRONTEND); System.realtimeTick(ClockIndexes.RT_CLOCK_BACKEND); _ = FCore.getFunctionTree(cache); @@ -384,16 +382,16 @@ algorithm end if; System.realtimeTick(ClockIndexes.RT_CLOCK_SIMCODE); a_cref := Absyn.pathToCref(className); - fileDir := CevalScript.getFileDir(a_cref, p); + fileDir := CevalScriptBackend.getFileDir(a_cref, p); (libs, libPaths,includes, includeDirs, recordDecls, functions, outIndexedBackendDAE, _, literals) := SimCodeUtil.createFunctions(p, dae, inBackendDAE, className); simCode := createSimCode(outIndexedBackendDAE, className, filenamePrefix, fileDir, functions, includes, includeDirs, libs,libPaths, simSettingsOpt, recordDecls, literals, args); timeSimCode := System.realtimeTock(ClockIndexes.RT_CLOCK_SIMCODE); - SimCodeUtil.execStat("SimCode"); + SimCodeFunctionUtil.execStat("SimCode"); System.realtimeTick(ClockIndexes.RT_CLOCK_TEMPLATES); callTargetTemplates(simCode, inBackendDAE, Config.simCodeTarget()); timeTemplates := System.realtimeTock(ClockIndexes.RT_CLOCK_TEMPLATES); - SimCodeUtil.execStat("Templates"); + SimCodeFunctionUtil.execStat("Templates"); end generateModelCode; protected function createSimCode " @@ -632,13 +630,13 @@ algorithm System.realtimeTick(ClockIndexes.RT_CLOCK_FRONTEND); System.realtimeTick(ClockIndexes.RT_CLOCK_EXECSTAT); System.realtimeTick(ClockIndexes.RT_CLOCK_EXECSTAT_CUMULATIVE); - (cache, graph, dae, st) = CevalScript.runFrontEnd(cache, graph, className, st, false); - SimCodeUtil.execStat("FrontEnd"); + (cache, graph, dae, st) = CevalScriptBackend.runFrontEnd(cache, graph, className, st, false); + SimCodeFunctionUtil.execStat("FrontEnd"); timeFrontend = System.realtimeTock(ClockIndexes.RT_CLOCK_FRONTEND); System.realtimeTick(ClockIndexes.RT_CLOCK_BACKEND); dae = DAEUtil.transformationsBeforeBackend(cache, graph, dae); - SimCodeUtil.execStat("Transformations before backend"); + SimCodeFunctionUtil.execStat("Transformations before backend"); description = DAEUtil.daeDescription(dae); dlow = BackendDAECreate.lower(dae, cache, graph, BackendDAE.EXTRA_INFO(description,filenameprefix)); //BackendDump.printBackendDAE(dlow); @@ -663,137 +661,5 @@ algorithm end matchcontinue; end translateModel; -public function translateFunctions " - Entry point to translate Modelica/MetaModelica functions to C functions. - Called from other places in the compiler." - input Absyn.Program program; - input String name; - input Option optMainFunction; - input list idaeElements; - input list metarecordTypes; - input list inIncludes; -algorithm - _ := match (program, name, optMainFunction, idaeElements, metarecordTypes, inIncludes) - local - DAE.Function daeMainFunction; - SimCode.Function mainFunction; - list fns; - list includes, libs, libPaths,includeDirs; - SimCode.MakefileParams makefileParams; - SimCode.FunctionCode fnCode; - list extraRecordDecls; - list literals; - list daeElements; - - case (_, _, SOME(daeMainFunction), daeElements, _, includes) - equation - // Create SimCode.FunctionCode - (daeElements,literals) = SimCodeUtil.findLiterals(daeMainFunction::daeElements); - (mainFunction::fns, extraRecordDecls, includes, includeDirs, libs,libPaths) = SimCodeUtil.elaborateFunctions(program, daeElements, metarecordTypes, literals, includes); - SimCodeUtil.checkValidMainFunction(name, mainFunction); - makefileParams = SimCodeUtil.createMakefileParams(includeDirs, libs,libPaths, true); - fnCode = SimCode.FUNCTIONCODE(name, SOME(mainFunction), fns, literals, includes, makefileParams, extraRecordDecls); - // Generate code - _ = Tpl.tplString(CodegenC.translateFunctions, fnCode); - then - (); - case (_, _, NONE(), daeElements, _, includes) - equation - // Create SimCode.FunctionCode - (daeElements,literals) = SimCodeUtil.findLiterals(daeElements); - (fns, extraRecordDecls, includes, includeDirs, libs,libPaths) = SimCodeUtil.elaborateFunctions(program, daeElements, metarecordTypes, literals, includes); - makefileParams = SimCodeUtil.createMakefileParams(includeDirs, libs,libPaths, true); - // remove OpenModelica.threadData.ThreadData - fns = removeThreadDataFunction(fns, {}); - extraRecordDecls = removeThreadDataRecord(extraRecordDecls, {}); - - fnCode = SimCode.FUNCTIONCODE(name, NONE(), fns, literals, includes, makefileParams, extraRecordDecls); - // Generate code - _ = Tpl.tplString(CodegenC.translateFunctions, fnCode); - then - (); - end match; -end translateFunctions; - -protected function removeThreadDataRecord -"remove OpenModelica.threadData.ThreadData - as is already defined in openmodelica.h" - input list inRecs; - input list inAcc; - output list outRecs; -algorithm - outRecs := match(inRecs, inAcc) - local - Absyn.Path p; - list acc, rest; - SimCode.RecordDeclaration r; - - case ({}, _) then listReverse(inAcc); - - case (SimCode.RECORD_DECL_FULL(name = "OpenModelica_threadData_ThreadData")::rest, _) - equation - acc = removeThreadDataRecord(rest, inAcc); - then - acc; - - case (SimCode.RECORD_DECL_DEF(path = Absyn.QUALIFIED("OpenModelica",Absyn.QUALIFIED("threadData",Absyn.IDENT("ThreadData"))))::rest, _) - equation - acc = removeThreadDataRecord(rest, inAcc); - then - acc; - - case (r::rest, _) - equation - acc = removeThreadDataRecord(rest, r::inAcc); - then - acc; - - end match; -end removeThreadDataRecord; - -protected function removeThreadDataFunction -"remove OpenModelica.threadData.ThreadData - as is already defined in openmodelica.h" - input list inFuncs; - input list inAcc; - output list outFuncs; -algorithm - outFuncs := match(inFuncs, inAcc) - local - Absyn.Path p; - list acc, rest; - SimCode.Function f; - - case ({}, _) then listReverse(inAcc); - - case (SimCode.RECORD_CONSTRUCTOR(name = Absyn.FULLYQUALIFIED(Absyn.QUALIFIED("OpenModelica",Absyn.QUALIFIED("threadData",Absyn.IDENT("ThreadData")))))::rest, _) - equation - acc = removeThreadDataFunction(rest, inAcc); - then - acc; - - case (f::rest, _) - equation - acc = removeThreadDataFunction(rest, f::inAcc); - then - acc; - - end match; -end removeThreadDataFunction; - -public function getCalledFunctionsInFunction -"Goes through the given DAE, finds the given function and collects - the names of the functions called from within those functions" - input Absyn.Path path; - input DAE.FunctionTree funcs; - output list outPaths; -protected - HashTableStringToPath.HashTable ht; -algorithm - ht := HashTableStringToPath.emptyHashTable(); - ht := SimCodeUtil.getCalledFunctionsInFunction2(path,Absyn.pathStringNoQual(path),ht,funcs); - outPaths := BaseHashTable.hashTableValueList(ht); -end getCalledFunctionsInFunction; - annotation(__OpenModelica_Interface="backend"); end SimCodeMain; diff --git a/Compiler/SimCode/SimCodeUtil.mo b/Compiler/SimCode/SimCodeUtil.mo index 5f8f92013c9..901b7d0ca01 100644 --- a/Compiler/SimCode/SimCodeUtil.mo +++ b/Compiler/SimCode/SimCodeUtil.mo @@ -50,7 +50,6 @@ import HashTable; import HashTableCrILst; import HashTableCrIListArray; import HashTableExpToIndex; -import HashTableStringToPath; import SCode; import Tpl; import Types; @@ -72,8 +71,6 @@ import BackendVarTransform; import BaseHashTable; import BaseHashSet; import Builtin; -import ClockIndexes; -import CevalScript; import CheckModel; import ClassInf; import ComponentReference; @@ -89,390 +86,22 @@ import ExpressionSimplify; import ExpressionSolve; import FindZeroCrossings; import Flags; -import GC; import Graph; import HashSet; import HpcOmSimCode; import Initialization; import Inline; import List; -import Mod; import PriorityQueue; -import Settings; import SimCodeDump; +import SimCodeFunctionUtil; +import SimCodeFunctionUtil.{execStat,varName}; import SymbolicJacobian; import System; import Util; import ValuesUtil; import VisualXML; -// ============================================================================= -// section for public function for SimCodeTV -// -// ============================================================================= - -public function elementVars -"Used by templates to get a list of variables from a valueblock." - input list ild; - output list vars; -protected - list ld; -algorithm - ld := List.filter(ild, isVarQ); - vars := List.map(ld, daeInOutSimVar); -end elementVars; - -public function crefSubIsScalar -"Used by templates to determine if a component reference's subscripts are - scalar." - input DAE.ComponentRef cref; - output Boolean isScalar; -protected - list subs; -algorithm - subs := ComponentReference.crefSubs(cref); - isScalar := subsToScalar(subs); -end crefSubIsScalar; - -public function crefNoSub -"Used by templates to determine if a component reference has no subscripts." - input DAE.ComponentRef cref; - output Boolean noSub; -algorithm - noSub := not ComponentReference.crefHaveSubs(cref); -end crefNoSub; - -public function inFunctionContext - input SimCode.Context inContext; - output Boolean outInFunction; -algorithm - outInFunction := match inContext - case SimCode.FUNCTION_CONTEXT() then true; - case SimCode.PARALLEL_FUNCTION_CONTEXT() then true; - else false; - end match; -end inFunctionContext; - -public function crefIsScalar - "Whether a component reference is a scalar depends on what context we are in. - If we are generating code for a function, then only crefs without subscripts - are scalar. If we are generating code for simulation though, then crefs with - only constant subscripts are also scalars, since a variable is generated for - each element of an array in the model." - input DAE.ComponentRef cref; - input SimCode.Context context; - output Boolean isScalar; -algorithm - if inFunctionContext(context) then - isScalar := listEmpty(ComponentReference.crefLastSubs(cref)); - else - isScalar := ComponentReference.crefHasScalarSubscripts(cref); - end if; -end crefIsScalar; - -public function buildCrefExpFromAsub -"Used by templates to convert an ASUB expression to a component reference - with subscripts." - input DAE.Exp cref; - input list subs; - output DAE.Exp cRefOut; -algorithm - cRefOut := matchcontinue(cref, subs) - local - DAE.Exp crefExp; - DAE.Type ty; - DAE.ComponentRef crNew; - list indexes; - - case (_, {}) then cref; - case (DAE.CREF(componentRef=crNew, ty=ty), _) - equation - indexes = List.map(subs, Expression.makeIndexSubscript); - crNew = ComponentReference.subscriptCref(crNew, indexes); - crefExp = Expression.makeCrefExp(crNew, ty); - then - crefExp; - end matchcontinue; -end buildCrefExpFromAsub; - -public function incrementInt -"Used by templates to create new integers that are increments of another." - input Integer inInt; - input Integer increment; - output Integer outInt; -algorithm - outInt := inInt + increment; -end incrementInt; - -public function decrementInt -"Used by templates to create new integers that are increments of another." - input Integer inInt; - input Integer decrement; - output Integer outInt; -algorithm - outInt := inInt - decrement; -end decrementInt; - - -public function protectedVars - input list InSimVars; - output list OutSimVars; - algorithm - OutSimVars:= List.filterOnTrue(InSimVars,isNotProtected); -end protectedVars; - -protected function isNotProtected - input SimCodeVar.SimVar simVar; - output Boolean isProtected; -algorithm - SimCodeVar.SIMVAR(isProtected=isProtected) := simVar; - isProtected := not isProtected; -end isNotProtected; - - -public function makeCrefRecordExp -"Helper function to generate records." - input DAE.ComponentRef inCRefRecord; - input DAE.Var inVar; - output DAE.Exp outExp; -algorithm - outExp := match (inCRefRecord, inVar) - local - DAE.ComponentRef cr, cr1; - String name; - DAE.Type tp; - case (cr, DAE.TYPES_VAR(name=name, ty=tp)) - equation - cr1 = ComponentReference.crefPrependIdent(cr, name, {}, tp); - outExp = Expression.makeCrefExp(cr1, tp); - then - outExp; - end match; -end makeCrefRecordExp; - -public function cref2simvar -"Used by templates to find SIMVAR for given cref (to gain representaion index info mainly)." - input DAE.ComponentRef inCref; - input SimCode.SimCode simCode; - output SimCodeVar.SimVar outSimVar; -algorithm - outSimVar := matchcontinue(inCref, simCode) - local - DAE.ComponentRef cref, badcref; - SimCodeVar.SimVar sv; - SimCode.HashTableCrefToSimVar crefToSimVarHT; - String errstr; - - case (cref, SimCode.SIMCODE(crefToSimVarHT = crefToSimVarHT) ) - equation - sv = get(cref, crefToSimVarHT); - then sv; - - case (_, _) - equation - //print("cref2simvar: " + ComponentReference.printComponentRefStr(inCref) + " not found!\n"); - badcref = ComponentReference.makeCrefIdent("ERROR_cref2simvar_failed", DAE.T_REAL_DEFAULT, {}); - /* Todo: This also generates an error for example itearation variables, so i commented out - "Template did not find the simulation variable for "+ ComponentReference.printComponentRefStr(cref) + ". "; - Error.addInternalError(errstr, sourceInfo());*/ - then - SimCodeVar.SIMVAR(badcref, BackendDAE.VARIABLE(), "", "", "", -2, NONE(), NONE(), NONE(), NONE(), false, DAE.T_REAL_DEFAULT, false, NONE(), SimCodeVar.NOALIAS(), DAE.emptyElementSource, SimCodeVar.INTERNAL(), NONE(), {}, false, true); - end matchcontinue; -end cref2simvar; - -public function isModelTooBigForCSharpInOneFile -"Used by C# template to determine if the generated code should be split into several files - to make Visual Studio responsive when the file is opened (C# compiler is OK, - but VS does not scale well for big C# files)." - input SimCode.SimCode simCode; - output Boolean outIsTooBig; -algorithm - outIsTooBig := match(simCode) - local - Integer numAlgVars; - - case (SimCode.SIMCODE(modelInfo = SimCode.MODELINFO(varInfo = SimCode.VARINFO(numAlgVars = numAlgVars)))) - equation - outIsTooBig = numAlgVars > 1000; - then outIsTooBig; - - end match; -end isModelTooBigForCSharpInOneFile; - -public function derComponentRef -"Used by templates to derrive a cref in a der(cref) expression. - Particularly, this function is called for the C# code generator, - while for C/C++, it is solved by prefixing the cref with '$P$DER' in daeExpCall() template. - The prefixing technique is not usable for C#, because there is no macroprocessor in C#. - TODO: all der(cref) expressions should be eliminated before the expressions enter templates - to pull this logic (and this function) out of templates." - input DAE.ComponentRef inCref; - output DAE.ComponentRef derCref; -algorithm - derCref := ComponentReference.crefPrefixDer(inCref); -end derComponentRef; - -public function hackArrayReverseToCref -"This is a hack transformation of an expanded array back to its cref. -It is used in daeExpArray() (for C# yet) to optimize the generated code. -TODO: This function should not exist! -Rather the array should not be let expanded when SimCode is entering templates. -" - input DAE.Exp inExp; - input SimCode.Context context; - output DAE.Exp outExp; -algorithm - outExp := matchcontinue (inExp, context) - local - list aRest; - DAE.ComponentRef cr; - DAE.Type aty; - DAE.Exp crefExp; - - case(DAE.ARRAY(ty=aty, scalar=true, array =(DAE.CREF(componentRef=cr) ::aRest)), _) - equation - failure(SimCode.FUNCTION_CONTEXT()=context); // only in the function context - failure(SimCode.PARALLEL_FUNCTION_CONTEXT()=context); // only in the function context - { DAE.INDEX(DAE.ICONST(1)) } = ComponentReference.crefLastSubs(cr); - cr = ComponentReference.crefStripLastSubs(cr); - true = isArrayExpansion(aRest, cr, 2); - crefExp = Expression.makeCrefExp(cr, aty); - then - crefExp; - - else inExp; - - end matchcontinue; -end hackArrayReverseToCref; - -protected function isArrayExpansion -"Helper funtion to hackArrayReverseToCref." - input list inArrayElems; - input DAE.ComponentRef inCref; - input Integer index; - output Boolean isExpanded; -algorithm - isExpanded := matchcontinue(inArrayElems, inCref, index) - local - list aRest; - Integer i; - DAE.ComponentRef cr; - case({}, _, _) then true; - case (DAE.CREF(componentRef=cr) :: aRest, _, _) - equation - { DAE.INDEX(DAE.ICONST(i)) } = ComponentReference.crefLastSubs(cr); - true = (i == index); - cr = ComponentReference.crefStripLastSubs(cr); - true = ComponentReference.crefEqualNoStringCompare(inCref, cr); - then isArrayExpansion(aRest, inCref, index+1); - else false; - end matchcontinue; -end isArrayExpansion; - -public function hackMatrixReverseToCref -"This is a hack transformation of an expanded matrix back to its cref. -It is used in daeExpMatrix() (for C# yet) to optimize the generated code. -TODO: This function should not exist! -Rather the matrix should not be let expanded when SimCode is entering templates -" - input DAE.Exp inExp; - input SimCode.Context context; - output DAE.Exp outExp; -algorithm - outExp := matchcontinue (inExp, context) - local - DAE.ComponentRef cr; - DAE.Type aty; - list> rows; - DAE.Exp crefExp; - - case(DAE.MATRIX(ty=aty, matrix = rows as (((DAE.CREF(componentRef=cr))::_)::_) ), _) - equation - failure(SimCode.FUNCTION_CONTEXT()=context); - failure(SimCode.PARALLEL_FUNCTION_CONTEXT()=context); // only in the function context - { DAE.INDEX(DAE.ICONST(1)), DAE.INDEX(DAE.ICONST(1)) } = ComponentReference.crefLastSubs(cr); - cr = ComponentReference.crefStripLastSubs(cr); - true = isMatrixExpansion(rows, cr, 1, 1); - crefExp = Expression.makeCrefExp(cr, aty); - then - crefExp; - - else inExp; - - end matchcontinue; -end hackMatrixReverseToCref; - -protected function isMatrixExpansion -"Helper funtion to hackMatrixReverseToCref." - input list> rows; - input DAE.ComponentRef inCref; - input Integer rowIndex; - input Integer colIndex; - output Boolean isExpanded; -algorithm - isExpanded := matchcontinue(rows, inCref, rowIndex, colIndex) - local - list> restRows; - list restElems; - Integer r, c; - DAE.ComponentRef cr; - case({}, _, _, _) then true; - case({} :: restRows, _, _, _) then isMatrixExpansion(restRows, inCref, rowIndex+1, 1); - case ( (DAE.CREF(componentRef=cr) :: restElems) :: restRows, _, _, _) - equation - { DAE.INDEX(DAE.ICONST(r)), DAE.INDEX(DAE.ICONST(c)) } = ComponentReference.crefLastSubs(cr); - true = (r == rowIndex) and (c == colIndex); - cr = ComponentReference.crefStripLastSubs(cr); - true = ComponentReference.crefEqualNoStringCompare(inCref, cr); - then isMatrixExpansion(restElems :: restRows, inCref, rowIndex, colIndex+1); - else false; - end matchcontinue; -end isMatrixExpansion; - -public function hackGetFirstExternalFunctionLib -"This is a hack to get the original library name given to an external function. -TODO: redesign OMC and Modelica specification so they are not so C/C++ centric." - input list libs; - output String outFirstLib; -algorithm - outFirstLib := matchcontinue (libs) - local - String lib; - - case _ - equation - lib = List.last(libs); - lib = System.stringReplace(lib, "-l", ""); - then - lib; - - else "NO_LIB"; - - end matchcontinue; -end hackGetFirstExternalFunctionLib; - -public function createAssertforSqrt - input DAE.Exp inExp; - output DAE.Exp outExp; -algorithm - outExp := - match (inExp) - case(_) - equation - // Simplify things like abs(exp) >= 0 to exp - (outExp, _) = ExpressionSimplify.simplify(DAE.RELATION(inExp, DAE.GREATEREQ(DAE.T_REAL_DEFAULT), DAE.RCONST(0.0), -1, NONE())); - then outExp; - end match; -end createAssertforSqrt; - -public function createDAEString - input String inString; - output DAE.Exp outExp; - annotation(__OpenModelica_EarlyInline = true); -algorithm - outExp := DAE.SCONST(inString); -end createDAEString; - public function appendLists input list inEqn1; input list inEqn2; @@ -483,743 +112,18 @@ end appendLists; protected function compareEqSystems input SimCode.SimEqSystem eq1; - input SimCode.SimEqSystem eq2; - output Boolean b; -algorithm - b := simEqSystemIndex(eq1) > simEqSystemIndex(eq2); -end compareEqSystems; - -public function sortEqSystems - input list eqs; - output list outEqs; -algorithm - outEqs := List.sort(eqs,compareEqSystems); -end sortEqSystems; - -/** end of TypeView published functions **/ - -// ============================================================================= -// section to generate SimCode from functions -// -// Finds the called functions in BackendDAE and transforms them to a list of -// libraries and a list of SimCode.Function uniontypes. -// ============================================================================= - -public function createFunctions - input Absyn.Program inProgram; - input DAE.DAElist inDAElist; - input BackendDAE.BackendDAE inBackendDAE; - input Absyn.Path inPath; - output list libs; - output list libPaths; - output list includes; - output list includeDirs; - output list recordDecls; - output list functions; - output BackendDAE.BackendDAE outBackendDAE; - output DAE.DAElist outDAE; - output tuple> literals; -algorithm - (libs,libPaths, includes, includeDirs, recordDecls, functions, outBackendDAE, outDAE, literals) := - matchcontinue (inProgram, inDAElist, inBackendDAE, inPath) - local - list libs2,libpaths2, includes2, includeDirs2; - list funcelems, part_func_elems, recFuncs; - DAE.DAElist dae; - BackendDAE.BackendDAE dlow; - DAE.FunctionTree functionTree; - Absyn.Path path; - list fns; - list lits; - - case (_, dae, dlow as BackendDAE.DAE(shared=BackendDAE.SHARED(functionTree=functionTree)), _) - equation - // get all the used functions from the function tree - funcelems = DAEUtil.getFunctionList(functionTree); - funcelems = setRecordVariability(funcelems,inBackendDAE); - funcelems = Inline.inlineCallsInFunctions(funcelems, (NONE(), {DAE.NORM_INLINE(), DAE.AFTER_INDEX_RED_INLINE()}), {}); - (funcelems, literals as (_, _, lits)) = simulationFindLiterals(dlow, funcelems); - (fns, recordDecls, includes2, includeDirs2, libs2,libpaths2) = elaborateFunctions(inProgram, funcelems, {}, lits, {}); // Do we need metarecords here as well? - then - (libs2, libpaths2,includes2, includeDirs2, recordDecls, fns, dlow, dae, literals); - else - equation - Error.addInternalError("Creation of Modelica functions failed.", sourceInfo()); - then - fail(); - end matchcontinue; -end createFunctions; - -protected function orderRecordDecls - input SimCode.RecordDeclaration decl1; - input SimCode.RecordDeclaration decl2; - output Boolean b; -algorithm - b := match (decl1,decl2) - local - Absyn.Path path1,path2; - case (SimCode.RECORD_DECL_DEF(path=path1),SimCode.RECORD_DECL_DEF(path=path2)) then Absyn.pathGe(path1,path2); - else true; - end match; -end orderRecordDecls; - -public function elaborateFunctions - input Absyn.Program program; - input list daeElements; - input list metarecordTypes; - input list literals; - input list includes; - output list functions; - output list extraRecordDecls; - output list outIncludes; - output list includeDirs; - output list libs; - output list libpaths; -protected - list fns; - list outRecordTypes; - HashTableStringToPath.HashTable ht; - list>> g; -algorithm - (extraRecordDecls, outRecordTypes) := elaborateRecordDeclarationsForMetarecords(literals, {}, {}); - (functions, outRecordTypes, extraRecordDecls, outIncludes, includeDirs, libs,libpaths) := elaborateFunctions2(program, daeElements, {}, outRecordTypes, extraRecordDecls, includes, {}, {},{}); - extraRecordDecls := List.unique(extraRecordDecls); - (extraRecordDecls, _) := elaborateRecordDeclarationsFromTypes(metarecordTypes, extraRecordDecls, outRecordTypes); - extraRecordDecls := List.sort(extraRecordDecls, orderRecordDecls); - ht := HashTableStringToPath.emptyHashTableSized(BaseHashTable.lowBucketSize); - (extraRecordDecls,_) := List.mapFold(extraRecordDecls, aliasRecordDeclarations, ht); - // Topological sort since we have no guarantees in the order of generated records - g := Graph.buildGraph(extraRecordDecls, getRecordDependencies, extraRecordDecls); - (extraRecordDecls, {}) := Graph.topologicalSort(g, isRecordDeclEqual); -end elaborateFunctions; - -protected function getRecordDependencies - input SimCode.RecordDeclaration decl; - input list allDecls; - output list dependencies; -algorithm - dependencies := match (decl,allDecls) - local - String name; - list vars; - list tys; - list> tyss; - case (SimCode.RECORD_DECL_FULL(aliasName=SOME(name)),_) - then List.select1(allDecls, isRecordDecl, name); - case (SimCode.RECORD_DECL_FULL(variables=vars),_) - equation - tys = List.map(vars, getVarType); - tyss = List.map1(tys, Types.getAllInnerTypesOfType, Util.anyReturnTrue); - tys = List.flatten(tyss); - dependencies = List.filterMap1(tys, getRecordDependenciesFromType, allDecls); - then List.unique(dependencies); - else {}; - end match; -end getRecordDependencies; - -protected function getVarType - input SimCode.Variable var; - output DAE.Type ty; -algorithm - ty := match var - case SimCode.VARIABLE(ty=ty) then ty; - else DAE.T_ANYTYPE_DEFAULT; - end match; -end getVarType; - -protected function getRecordDependenciesFromType - input DAE.Type ty; - input list allDecls; - output SimCode.RecordDeclaration decl; -protected - Absyn.Path path; - String name; -algorithm - DAE.T_COMPLEX(complexClassType = ClassInf.RECORD(path)) := ty; - name := Absyn.pathStringUnquoteReplaceDot(path, "_"); - decl := List.selectFirst1(allDecls, isRecordDecl, name); -end getRecordDependenciesFromType; - -protected function isRecordDecl - input SimCode.RecordDeclaration decl; - input String name; - output Boolean b; -algorithm - b := match (decl,name) - local - String name1; - case (SimCode.RECORD_DECL_FULL(name=name1),_) then stringEq(name,name1); - else false; - end match; -end isRecordDecl; - -protected function isRecordDeclEqual - input SimCode.RecordDeclaration decl1; - input SimCode.RecordDeclaration decl2; - output Boolean b; -algorithm - b := match (decl1,decl2) - local - String name1,name2; - Absyn.Path path1,path2; - case (SimCode.RECORD_DECL_FULL(name=name1),SimCode.RECORD_DECL_FULL(name=name2)) then stringEq(name1,name2); - case (SimCode.RECORD_DECL_DEF(path=path1),SimCode.RECORD_DECL_DEF(path=path2)) then Absyn.pathEqual(path1,path2); - else false; - end match; -end isRecordDeclEqual; - -protected function elaborateFunctions2 - input Absyn.Program program; - input list daeElements; - input list inFunctions; - input list inRecordTypes; - input list inDecls; - input list inIncludes; - input list inIncludeDirs; - input list inLibs; - input list inPaths; - output list outFunctions; - output list outRecordTypes; - output list outDecls; - output list outIncludes; - output list outIncludeDirs; - output list outLibs; - output list outLibsPaths; -algorithm - (outFunctions, outRecordTypes, outDecls, outIncludes, outIncludeDirs, outLibs,outLibsPaths) := - match (program, daeElements, inFunctions, inRecordTypes, inDecls, inIncludes, inIncludeDirs, inLibs,inPaths) - local - Boolean b; - list accfns, fns; - SimCode.Function fn; - list rt, rt_1, rt_2, includes, libs,libPaths; - DAE.Function fel; - list rest; - list decls; - String name; - list includeDirs; - Absyn.Path path; - - case (_, {}, accfns, rt, decls, includes, includeDirs, libs,libPaths) - then (listReverse(accfns), rt, decls, includes, includeDirs, libs,libPaths); - case (_, (DAE.FUNCTION( type_ = DAE.T_FUNCTION(functionAttributes=DAE.FUNCTION_ATTRIBUTES(isBuiltin=DAE.FUNCTION_BUILTIN_PTR()))) :: rest), accfns, rt, decls, includes, includeDirs, libs,libPaths) - equation - // skip over builtin functions - (fns, rt_2, decls, includes, includeDirs, libs,libPaths) = elaborateFunctions2(program, rest, accfns, rt, decls, includes, includeDirs, libs,libPaths); - then - (fns, rt_2, decls, includes, includeDirs, libs,libPaths); - case (_, (DAE.FUNCTION(partialPrefix = true) :: rest), accfns, rt, decls, includes, includeDirs, libs,libPaths) - equation - // skip over partial functions - (fns, rt_2, decls, includes, includeDirs, libs,libPaths) = elaborateFunctions2(program, rest, accfns, rt, decls, includes, includeDirs, libs,libPaths); - then - (fns, rt_2, decls, includes, includeDirs, libs,libPaths); - case (_, DAE.FUNCTION(functions = DAE.FUNCTION_EXT(externalDecl = DAE.EXTERNALDECL(language="builtin"))::_)::rest, accfns, rt, decls, includes, includeDirs, libs,libPaths) - equation - // skip over builtin functions - (fns, rt_2, decls, includes, includeDirs, libs,libPaths) = elaborateFunctions2(program, rest, accfns, rt, decls, includes, includeDirs, libs,libPaths); - then - (fns, rt_2, decls, includes, includeDirs, libs,libPaths); - - case (_, (fel as DAE.FUNCTION(functions = DAE.FUNCTION_EXT(externalDecl = DAE.EXTERNALDECL(name=name, language="C"))::_))::rest, accfns, rt, decls, includes, includeDirs, libs,libPaths) - equation - // skip over builtin functions - b = listMember(name, SCode.knownExternalCFunctions); - (fn,_, decls, includes, includeDirs, libs,libPaths) = elaborateFunction(program, fel, rt, decls, includes, includeDirs, libs,libPaths); - (fns, rt_2, decls, includes, includeDirs, libs,libPaths) = elaborateFunctions2(program, rest, List.consOnTrue(not b, fn, accfns), rt, decls, includes, includeDirs, libs,libPaths); - then - (fns, rt_2, decls, includes, includeDirs, libs,libPaths); - - case (_, (fel :: rest), accfns, rt, decls, includes, includeDirs, libs,libPaths) - equation - (fn, rt_1, decls, includes, includeDirs, libs,libPaths) = elaborateFunction(program, fel, rt, decls, includes, includeDirs, libs,libPaths); - (fns, rt_2, decls, includes, includeDirs, libs,libPaths) = elaborateFunctions2(program, rest, (fn :: accfns), rt_1, decls, includes, includeDirs, libs,libPaths); - then - (fns, rt_2, decls, includes, includeDirs, libs,libPaths); - end match; -end elaborateFunctions2; - -/* Does the actual work of transforming a DAE.FUNCTION to a SimCode.Function. */ -protected function elaborateFunction - input Absyn.Program program; - input DAE.Function inElement; - input list inRecordTypes; - input list inRecordDecls; - input list inIncludes; - input list inIncludeDirs; - input list inLibs; - input list inLibPaths; - output SimCode.Function outFunction; - output list outRecordTypes; - output list outRecordDecls; - output list outIncludes; - output list outIncludeDirs; - output list outLibs; - output list outLibPaths; -algorithm - (outFunction, outRecordTypes, outRecordDecls, outIncludes, outIncludeDirs, outLibs,outLibPaths):= - matchcontinue (program, inElement, inRecordTypes, inRecordDecls, inIncludes, inIncludeDirs, inLibs,inLibPaths) - local - DAE.Function fn; - String extfnname, lang, str; - list algs, vars; // , bivars, invars, outvars; - list includes, libs, libPaths, fn_libs,fn_paths, fn_includes, fn_includeDirs, rt, rt_1; - Absyn.Path fpath; - list args; - DAE.Type restype, tp; - list extargs; - list simextargs; - SimCode.SimExtArg extReturn; - DAE.ExtArg extretarg; - Option ann; - DAE.ExternalDecl extdecl; - list outVars, inVars, biVars, funArgs, varDecls; - list recordDecls; - list bodyStmts; - list daeElts; - Absyn.Path name; - DAE.ElementSource source; - SourceInfo info; - Boolean dynamicLoad, hasIncludeAnnotation, hasLibraryAnnotation; - list includeDirs; - DAE.FunctionAttributes funAttrs; - list varlst; - DAE.VarKind kind; - SCode.Visibility visibility; - - // Modelica functions. - case (_, DAE.FUNCTION(path = fpath, source = source, visibility = visibility, - functions = DAE.FUNCTION_DEF(body = daeElts)::_, // might be followed by derivative maps - type_ = DAE.T_FUNCTION(funcArg=args, functionAttributes=funAttrs), - partialPrefix=false), rt, recordDecls, includes, includeDirs, libs,libPaths) - equation - - DAE.FUNCTION_ATTRIBUTES(functionParallelism=DAE.FP_NON_PARALLEL()) = funAttrs; - - outVars = List.map(DAEUtil.getOutputVars(daeElts), daeInOutSimVar); - funArgs = List.map1(args, typesSimFunctionArg, NONE()); - (recordDecls, rt_1) = elaborateRecordDeclarations(daeElts, recordDecls, rt); - vars = List.filter(daeElts, isVarQ); - varDecls = List.map(vars, daeInOutSimVar); - algs = List.filterOnTrue(daeElts, DAEUtil.isAlgorithm); - bodyStmts = List.map(algs, elaborateStatement); - info = DAEUtil.getElementSourceFileInfo(source); - then - (SimCode.FUNCTION(fpath, outVars, funArgs, varDecls, bodyStmts, visibility, info), rt_1, recordDecls, includes, includeDirs, libs,libPaths); - - - case (_, DAE.FUNCTION(path = fpath, source = source, - functions = DAE.FUNCTION_DEF(body = daeElts)::_, // might be followed by derivative maps - type_ = DAE.T_FUNCTION(funcArg=args, functionAttributes=funAttrs), - partialPrefix=false), rt, recordDecls, includes, includeDirs, libs,libPaths) - equation - - DAE.FUNCTION_ATTRIBUTES(functionParallelism=DAE.FP_KERNEL_FUNCTION()) = funAttrs; - - outVars = List.map(DAEUtil.getOutputVars(daeElts), daeInOutSimVar); - funArgs = List.map1(args, typesSimFunctionArg, NONE()); - (recordDecls, rt_1) = elaborateRecordDeclarations(daeElts, recordDecls, rt); - vars = List.filter(daeElts, isVarNotInputNotOutput); - varDecls = List.map(vars, daeInOutSimVar); - algs = List.filterOnTrue(daeElts, DAEUtil.isAlgorithm); - bodyStmts = List.map(algs, elaborateStatement); - info = DAEUtil.getElementSourceFileInfo(source); - then - (SimCode.KERNEL_FUNCTION(fpath, outVars, funArgs, varDecls, bodyStmts, info), rt_1, recordDecls, includes, includeDirs, libs,libPaths); - - - case (_, DAE.FUNCTION(path = fpath, source = source, - functions = DAE.FUNCTION_DEF(body = daeElts)::_, // might be followed by derivative maps - type_ = DAE.T_FUNCTION(funcArg=args, functionAttributes = funAttrs), - partialPrefix=false), rt, recordDecls, includes, includeDirs, libs,libPaths) - equation - - DAE.FUNCTION_ATTRIBUTES(functionParallelism=DAE.FP_PARALLEL_FUNCTION()) = funAttrs; - - outVars = List.map(DAEUtil.getOutputVars(daeElts), daeInOutSimVar); - funArgs = List.map1(args, typesSimFunctionArg, NONE()); - (recordDecls, rt_1) = elaborateRecordDeclarations(daeElts, recordDecls, rt); - vars = List.filter(daeElts, isVarQ); - varDecls = List.map(vars, daeInOutSimVar); - algs = List.filterOnTrue(daeElts, DAEUtil.isAlgorithm); - bodyStmts = List.map(algs, elaborateStatement); - info = DAEUtil.getElementSourceFileInfo(source); - then - (SimCode.PARALLEL_FUNCTION(fpath, outVars, funArgs, varDecls, bodyStmts, info), rt_1, recordDecls, includes, includeDirs, libs,libPaths); - - // External functions. - case (_, DAE.FUNCTION(path = fpath, source = source, visibility = visibility, - functions = DAE.FUNCTION_EXT(body = daeElts, externalDecl = extdecl)::_, // might be followed by derivative maps - type_ = (DAE.T_FUNCTION(funcArg = args))), rt, recordDecls, includes, includeDirs, libs,libPaths) - equation - DAE.EXTERNALDECL(name=extfnname, args=extargs, - returnArg=extretarg, language=lang, ann=ann) = extdecl; - // outvars = DAEUtil.getOutputVars(daeElts); - // invars = DAEUtil.getInputVars(daeElts); - // bivars = DAEUtil.getBidirVars(daeElts); - funArgs = List.map1(args, typesSimFunctionArg, NONE()); - outVars = List.map(DAEUtil.getOutputVars(daeElts), daeInOutSimVar); - inVars = List.map(DAEUtil.getInputVars(daeElts), daeInOutSimVar); - biVars = List.map(DAEUtil.getBidirVars(daeElts), daeInOutSimVar); - (recordDecls, rt_1) = elaborateRecordDeclarations(daeElts, recordDecls, rt); - info = DAEUtil.getElementSourceFileInfo(source); - (fn_includes, fn_includeDirs, fn_libs, fn_paths,dynamicLoad) = generateExtFunctionIncludes(program, fpath, ann, info); - includes = List.union(fn_includes, includes); - includeDirs = List.union(fn_includeDirs, includeDirs); - libs = List.union(fn_libs, libs); - libPaths = List.union(fn_paths, libPaths); - simextargs = List.map(extargs, extArgsToSimExtArgs); - extReturn = extArgsToSimExtArgs(extretarg); - (simextargs, extReturn) = fixOutputIndex(outVars, simextargs, extReturn); - // make lang to-upper as we have FORTRAN 77 and Fortran 77 in the Modelica Library! - lang = System.toupper(lang); - then - (SimCode.EXTERNAL_FUNCTION(fpath, extfnname, funArgs, simextargs, extReturn, - inVars, outVars, biVars, fn_includes, fn_libs, lang, visibility, info, dynamicLoad), - rt_1, recordDecls, includes, includeDirs, libs,libPaths); - - // Record constructor. - case (_, DAE.RECORD_CONSTRUCTOR(source = source, type_ = DAE.T_FUNCTION(funcArg = args, funcResultType = restype as DAE.T_COMPLEX(complexClassType = ClassInf.RECORD(name))),kind=kind), rt, recordDecls, includes, includeDirs, libs,libPaths) - equation - funArgs = List.map1(args, typesSimFunctionArg, NONE()); - (recordDecls, rt_1) = elaborateRecordDeclarationsForRecord(restype, recordDecls, rt); - DAE.T_COMPLEX(varLst = varlst) = restype; - varlst = List.filterOnTrue(varlst, Types.isProtectedVar); - varDecls = List.map(varlst, typesVar); - info = DAEUtil.getElementSourceFileInfo(source); - then - (SimCode.RECORD_CONSTRUCTOR(name, funArgs, varDecls, SCode.PUBLIC(), info, kind), rt_1, recordDecls, includes, includeDirs, libs,libPaths); - - // failure - case (_, fn, _, _, _, _, _,_) - equation - Error.addInternalError("function elaborateFunction failed for function: \n" + DAEDump.dumpFunctionStr(fn), sourceInfo()); - then - fail(); - end matchcontinue; -end elaborateFunction; - -protected function typesSimFunctionArg -"Generates code from a function argument." - input DAE.FuncArg inFuncArg; - input Option binding; - output SimCode.Variable outVar; -algorithm - outVar := matchcontinue (inFuncArg, binding) - local - DAE.Type tty; - String name; - DAE.ComponentRef cref_; - DAE.Const const; - list args; - DAE.Type res_ty; - list var_args; - list tys; - DAE.VarKind kind; - DAE.VarParallelism prl; - - case (DAE.FUNCARG(name=name, ty=DAE.T_FUNCTION(funcArg = args, funcResultType = DAE.T_TUPLE(types = tys))), _) - equation - var_args = List.map1(args, typesSimFunctionArg, NONE()); - tys = List.map(tys, Types.simplifyType); - then - SimCode.FUNCTION_PTR(name, tys, var_args, binding); - - case (DAE.FUNCARG(name=name, ty=DAE.T_FUNCTION(funcArg = args, funcResultType = DAE.T_NORETCALL())), _) - equation - var_args = List.map1(args, typesSimFunctionArg, NONE()); - then - SimCode.FUNCTION_PTR(name, {}, var_args, binding); - - case (DAE.FUNCARG(name=name, ty=DAE.T_FUNCTION(funcArg = args, funcResultType = res_ty)), _) - equation - res_ty = Types.simplifyType(res_ty); - var_args = List.map1(args, typesSimFunctionArg, NONE()); - then - SimCode.FUNCTION_PTR(name, {res_ty}, var_args, binding); - - case (DAE.FUNCARG(name=name, ty=tty, par=prl, const=const), _) - equation - tty = Types.simplifyType(tty); - cref_ = ComponentReference.makeCrefIdent(name, tty, {}); - kind = DAEUtil.const2VarKind(const); - then - SimCode.VARIABLE(cref_, tty, binding, {}, prl, kind); - end matchcontinue; -end typesSimFunctionArg; - -protected function daeInOutSimVar - input DAE.Element inElement; - output SimCode.Variable outVar; -algorithm - outVar := matchcontinue(inElement) - local - String name; - DAE.Type daeType; - DAE.ComponentRef id; - DAE.VarKind kind; - DAE.VarParallelism prl; - list inst_dims; - list inst_dims_exp; - Option binding; - SimCode.Variable var; - case (DAE.VAR(componentRef = DAE.CREF_IDENT(ident=name), ty = daeType as DAE.T_FUNCTION(), parallelism = prl, binding = binding)) - equation - var = typesSimFunctionArg(DAE.FUNCARG(name, daeType, DAE.C_VAR(), prl, NONE()), binding); - then var; - - case (DAE.VAR(componentRef = id, - parallelism = prl, - ty = daeType, - binding = binding, - dims = inst_dims, - kind = kind - )) - equation - daeType = Types.simplifyType(daeType); - inst_dims_exp = List.map(inst_dims, Expression.dimensionSizeExpHandleUnkown); - then SimCode.VARIABLE(id, daeType, binding, inst_dims_exp, prl, kind); - else - equation - // TODO: ArrayEqn fails here - Error.addInternalError("function daeInOutSimVar failed\n", sourceInfo()); - then - fail(); - end matchcontinue; -end daeInOutSimVar; - -protected function extArgsToSimExtArgs - input DAE.ExtArg extArg; - output SimCode.SimExtArg simExtArg; -algorithm - simExtArg := - match (extArg) - local - DAE.ComponentRef componentRef; - DAE.Attributes attributes; - DAE.Type type_; - Boolean isInput; - Boolean isOutput; - Boolean isArray; - DAE.Exp exp_; - Integer outputIndex; - - case DAE.EXTARG(componentRef, attributes, type_) - equation - isInput = Types.isInputAttr(attributes); - isOutput = Types.isOutputAttr(attributes); - outputIndex = if isOutput then -1 else 0; // correct output index is added later by fixOutputIndex - isArray = Types.isArray(type_); - type_ = Types.simplifyType(type_); - then SimCode.SIMEXTARG(componentRef, isInput, outputIndex, isArray, false /*fixed later*/, type_); - - case DAE.EXTARGEXP(exp_, type_) - equation - type_ = Types.simplifyType(type_); - then SimCode.SIMEXTARGEXP(exp_, type_); - - case DAE.EXTARGSIZE(componentRef, attributes, type_, exp_) - equation - isInput = Types.isInputAttr(attributes); - isOutput = Types.isOutputAttr(attributes); - outputIndex = if isOutput then -1 else 0; // correct output index is added later by fixOutputIndex - type_ = Types.simplifyType(type_); - then SimCode.SIMEXTARGSIZE(componentRef, isInput, outputIndex, type_, exp_); - - case DAE.NOEXTARG() then SimCode.SIMNOEXTARG(); - end match; -end extArgsToSimExtArgs; - -protected function fixOutputIndex - input list outVars; - input list simExtArgsIn; - input SimCode.SimExtArg extReturnIn; - output list simExtArgsOut; - output SimCode.SimExtArg extReturnOut; -algorithm - (simExtArgsOut, extReturnOut) := match (outVars, simExtArgsIn, extReturnIn) - local - case (_, _, _) - equation - simExtArgsOut = List.map1(simExtArgsIn, assignOutputIndex, outVars); - extReturnOut = assignOutputIndex(extReturnIn, outVars); - then - (simExtArgsOut, extReturnOut); - end match; -end fixOutputIndex; - -protected function assignOutputIndex - input SimCode.SimExtArg simExtArgIn; - input list outVars; - output SimCode.SimExtArg simExtArgOut; -algorithm - simExtArgOut := - matchcontinue (simExtArgIn, outVars) - local - DAE.ComponentRef cref, fcref; - Boolean isInput; - Integer outputIndex; // > 0 if output - Boolean isArray, hasBinding; - DAE.Type type_; - DAE.Exp exp; - Integer newOutputIndex; - - case (SimCode.SIMEXTARG(cref, isInput, outputIndex, isArray, _, type_), _) - equation - true = outputIndex == -1; - fcref = ComponentReference.crefFirstCref(cref); - (newOutputIndex, hasBinding) = findIndexInList(fcref, outVars, 1); - then - SimCode.SIMEXTARG(cref, isInput, newOutputIndex, isArray, hasBinding, type_); - - case (SimCode.SIMEXTARGSIZE(cref, isInput, outputIndex, type_, exp), _) - equation - true = outputIndex == -1; - (newOutputIndex, _) = findIndexInList(cref, outVars, 1); - then - SimCode.SIMEXTARGSIZE(cref, isInput, newOutputIndex, type_, exp); - - else - simExtArgIn; - end matchcontinue; -end assignOutputIndex; - -protected function findIndexInList - input DAE.ComponentRef cref; - input list outVars; - input Integer inCurrentIndex; - output Integer crefIndexInOutVars; - output Boolean hasBinding; -algorithm - (crefIndexInOutVars, hasBinding) := - matchcontinue (cref, outVars, inCurrentIndex) - local - DAE.ComponentRef name; - list restOutVars; - Option v; - Integer currentIndex; - - case (_, {}, _) then (-1, false); - case (_, SimCode.VARIABLE(name=name, value=v) :: _, currentIndex) - equation - true = ComponentReference.crefEqualNoStringCompare(cref, name); - then (currentIndex, Util.isSome(v)); - case (_, _ :: restOutVars, currentIndex) - equation - currentIndex = currentIndex + 1; - (currentIndex, hasBinding) = findIndexInList(cref, restOutVars, currentIndex); - then (currentIndex, hasBinding); - end matchcontinue; -end findIndexInList; - -protected function elaborateStatement - input DAE.Element inElement; - output SimCode.Statement outStatement; -algorithm - (outStatement):= - matchcontinue (inElement) - local - list stmts; - case (DAE.ALGORITHM(algorithm_ = DAE.ALGORITHM_STMTS(statementLst = stmts))) - then - SimCode.ALGORITHM(stmts); - else - equation - true = Flags.isSet(Flags.FAILTRACE); - Debug.trace("# SimCode.elaborateStatement failed\n"); - then - fail(); - end matchcontinue; -end elaborateStatement; - - -public function checkValidMainFunction -"Verifies that an in-function can be generated. -This is not the case if the input involves function-pointers." - input String name; - input SimCode.Function fn; -algorithm - _ := matchcontinue (name, fn) - local - list inVars; - case (_, SimCode.FUNCTION(functionArguments = inVars)) - equation - failure(_ = List.selectFirst(inVars, isFunctionPtr)); - then (); - case (_, SimCode.EXTERNAL_FUNCTION(inVars = inVars)) - equation - failure(_ = List.selectFirst(inVars, isFunctionPtr)); - then (); - else - equation - Error.addMessage(Error.GENERATECODE_INVARS_HAS_FUNCTION_PTR, {name}); - then fail(); - end matchcontinue; -end checkValidMainFunction; - -public function isBoxedFunction -"Verifies that an in-function can be generated. -This is not the case if the input involves function-pointers." - input SimCode.Function fn; - output Boolean b; -algorithm - b := matchcontinue fn - local - list inVars, outVars; - case (SimCode.FUNCTION(functionArguments = inVars, outVars = outVars)) - equation - List.map_0(inVars, isBoxedArg); - List.map_0(outVars, isBoxedArg); - then true; - case (SimCode.EXTERNAL_FUNCTION(inVars = inVars, outVars = outVars)) - equation - List.map_0(inVars, isBoxedArg); - List.map_0(outVars, isBoxedArg); - then true; - else false; - end matchcontinue; -end isBoxedFunction; - -protected function isFunctionPtr -"Checks if an input variable is a function pointer" - input SimCode.Variable var; - output Boolean b; -algorithm - b := match var - /* Yes, they are VARIABLE, not SimCode.FUNCTION_PTR. */ - case SimCode.FUNCTION_PTR() then true; - else false; - end match; -end isFunctionPtr; - -protected function isBoxedArg -"Checks if a variable is a boxed datatype" - input SimCode.Variable var; -algorithm - _ := match var - case SimCode.FUNCTION_PTR() then (); - case SimCode.VARIABLE(ty = DAE.T_METABOXED()) then (); - case SimCode.VARIABLE(ty = DAE.T_METATYPE()) then (); - case SimCode.VARIABLE(ty = DAE.T_STRING()) then (); - end match; -end isBoxedArg; - -// ============================================================================= -// section of literals translation SimCode -// -// ============================================================================= + input SimCode.SimEqSystem eq2; + output Boolean b; +algorithm + b := simEqSystemIndex(eq1) > simEqSystemIndex(eq2); +end compareEqSystems; -public function findLiterals - "Finds all literal expressions in functions" - input list fns; - output list ofns; - output list literals; +public function sortEqSystems + input list eqs; + output list outEqs; algorithm - (ofns, (_, _, literals)) := DAEUtil.traverseDAEFunctions( - fns, findLiteralsHelper, - (0, HashTableExpToIndex.emptyHashTableSized(BaseHashTable.bigBucketSize), {}), {}); - literals := listReverse(literals); -end findLiterals; + outEqs := List.sort(eqs,compareEqSystems); +end sortEqSystems; protected function simulationFindLiterals "Finds all literal expressions in the DAE" @@ -1229,247 +133,12 @@ protected function simulationFindLiterals output tuple> literals; algorithm (ofns, literals) := DAEUtil.traverseDAEFunctions( - fns, findLiteralsHelper, + fns, SimCodeFunctionUtil.findLiteralsHelper, (0, HashTableExpToIndex.emptyHashTableSized(BaseHashTable.bigBucketSize), {}), {}); // Broke things :( // ((i, ht, literals)) := BackendDAEUtil.traverseBackendDAEExpsNoCopyWithUpdate(dae, findLiteralsHelper, (i, ht, literals)); end simulationFindLiterals; -protected function findLiteralsHelper - input DAE.Exp inExp; - input tuple> inTpl; - output DAE.Exp exp; - output tuple> tpl; -algorithm - exp := inExp; - tpl := inTpl; - (exp, tpl) := Expression.traverseExpBottomUp(exp, replaceLiteralExp, tpl); - (exp, tpl) := Expression.traverseExpTopDown(exp, replaceLiteralArrayExp, tpl); -end findLiteralsHelper; - -protected function replaceLiteralArrayExp - "The tuples contain: - * The expression to be replaced (or not) - * Index of next literal - * HashTable Exp->Index (Number of the literal) - * The list of literals - - Handles only array expressions (needs to be performed in a top-down fashion) - " - input DAE.Exp inExp; - input tuple> inTpl; - output DAE.Exp outExp; - output Boolean cont; - output tuple> outTpl; -algorithm - (outExp,cont,outTpl) := matchcontinue (inExp,inTpl) - local - DAE.Exp exp,exp2; - tuple> tpl; - case (DAE.ARRAY(), _) - equation - isLiteralArrayExp(inExp); - (exp2, tpl) = replaceLiteralExp2(inExp, inTpl); - then (exp2, false, tpl); - case (exp as DAE.ARRAY(), tpl) - equation - failure(isLiteralArrayExp(exp)); - then (exp, false, tpl); - case (exp as DAE.MATRIX(), _) - equation - isLiteralArrayExp(exp); - (exp2, tpl) = replaceLiteralExp2(inExp, inTpl); - then (exp2, false, tpl); - case (exp as DAE.MATRIX(), tpl) - equation - failure(isLiteralArrayExp(exp)); - then (exp, false, tpl); - else (inExp, true, inTpl); - end matchcontinue; -end replaceLiteralArrayExp; - -protected function replaceLiteralExp - "The tuples contain: - * The expression to be replaced (or not) - * Index of next literal - * HashTable Exp->Index (Number of the literal) - * The list of literals - " - input DAE.Exp inExp; - input tuple> inTpl; - output DAE.Exp outExp; - output tuple> outTpl; -algorithm - (outExp,outTpl) := matchcontinue (inExp,inTpl) - local - DAE.Exp exp; - String msg; - tuple> t; - list es; - case (exp, t) - equation - failure(isLiteralExp(exp)); - then (exp, t); - case (exp, t) - equation - isTrivialLiteralExp(exp); - then (exp, t); - case (DAE.LIST(valList=es), t) - equation - true = listLength(es) > 25; - (exp,t) = replaceLiteralExp2(inExp, t); - then (exp, t); // Too large list; causes performance issues to find all sublists... - case (exp, t) - equation - exp = listToCons(exp); - (exp, t) = Expression.traverseExpBottomUp(exp, replaceLiteralExp, t); - then (exp, t); // All sublists should also be added as literals... - case (exp, _) - equation - failure(_ = listToCons(exp)); - (exp,t) = replaceLiteralExp2(exp, inTpl); - then (exp, t); - case (exp, _) - equation - msg = "function replaceLiteralExp failed. Falling back to not replacing "+ExpressionDump.printExpStr(exp)+"."; - Error.addInternalError(msg, sourceInfo()); - then (inExp,inTpl); - end matchcontinue; -end replaceLiteralExp; - -protected function replaceLiteralExp2 - "The tuples contain: - * The expression to be replaced (or not) - * Index of next literal - * HashTable Exp->Index (Number of the literal) - * The list of literals - " - input DAE.Exp inExp; - input tuple> inTpl; - output DAE.Exp outExp; - output tuple> outTpl; -algorithm - (outExp,outTpl) := matchcontinue (inExp,inTpl) - local - DAE.Exp exp, nexp; - Integer i, ix; - list l; - DAE.Type et; - HashTableExpToIndex.HashTable ht; - case (exp, (i, ht, l)) - equation - ix = BaseHashTable.get(exp, ht); - nexp = DAE.SHARED_LITERAL(ix, exp); - then (nexp, (i, ht, l)); - case (exp, (i, ht, l)) - equation - ht = BaseHashTable.add((exp, i), ht); - nexp = DAE.SHARED_LITERAL(i, exp); - then (nexp, (i+1, ht, exp::l)); - end matchcontinue; -end replaceLiteralExp2; - -protected function listToCons -"Converts a DAE.LIST to a chain of DAE.CONS" - input DAE.Exp e; - output DAE.Exp o; -algorithm - o := match e - local - list es; - case DAE.LIST(es as _::_) then listToCons2(es); - end match; -end listToCons; - -protected function listToCons2 -"Converts a DAE.LIST to a chain of DAE.CONS" - input list ies; - output DAE.Exp o; -algorithm - o := match ies - local - DAE.Exp car, cdr; - list es; - case ({}) then DAE.LIST({}); - case (car::es) - equation - cdr = listToCons2(es); - then DAE.CONS(car, cdr); - end match; -end listToCons2; - -protected function isTrivialLiteralExp -"Succeeds if the expression should not be translated to a constant literal because it is too simple" - input DAE.Exp exp; -algorithm - _ := match exp - case DAE.BOX(DAE.SCONST(_)) then fail(); - case DAE.BOX(DAE.RCONST(_)) then fail(); - case DAE.BOX(_) then (); - case DAE.ICONST(_) then (); - case DAE.BCONST(_) then (); - case DAE.RCONST(_) then (); - case DAE.ENUM_LITERAL() then (); - case DAE.LIST(valList={}) then (); - case DAE.META_OPTION(NONE()) then (); - case DAE.SHARED_LITERAL() then (); - else fail(); - end match; -end isTrivialLiteralExp; - -protected function isLiteralArrayExp - input DAE.Exp iexp; -algorithm - _ := match iexp - local - DAE.Exp e1, e2, exp; - list expl; - list> expll; - - case DAE.SCONST(_) then (); - case DAE.ICONST(_) then (); - case DAE.RCONST(_) then (); - case DAE.BCONST(_) then (); - case DAE.ARRAY(array=expl) equation List.map_0(expl, isLiteralArrayExp); then (); - case DAE.MATRIX(matrix=expll) equation List.map_0(List.flatten(expll), isLiteralArrayExp); then (); - case DAE.ENUM_LITERAL() then (); - case DAE.META_OPTION(NONE()) then (); - case DAE.META_OPTION(SOME(exp)) equation isLiteralArrayExp(exp); then (); - case DAE.BOX(exp) equation isLiteralArrayExp(exp); then (); - case DAE.CONS(car = e1, cdr = e2) equation isLiteralArrayExp(e1); isLiteralArrayExp(e2); then (); - case DAE.LIST(valList = expl) equation List.map_0(expl, isLiteralArrayExp); then (); - case DAE.META_TUPLE(expl) equation List.map_0(expl, isLiteralArrayExp); then (); - case DAE.METARECORDCALL(args=expl) equation List.map_0(expl, isLiteralArrayExp); then (); - case DAE.SHARED_LITERAL() then (); - else fail(); - end match; -end isLiteralArrayExp; - -protected function isLiteralExp -"Returns if the expression may be replaced by a constant literal" - input DAE.Exp iexp; -algorithm - _ := match iexp - local - DAE.Exp e1, e2, exp; - list expl; - case DAE.SCONST(_) then (); - case DAE.ICONST(_) then (); - case DAE.RCONST(_) then (); - case DAE.BCONST(_) then (); - case DAE.ENUM_LITERAL() then (); - case DAE.META_OPTION(NONE()) then (); - case DAE.META_OPTION(SOME(exp)) equation isLiteralExp(exp); then (); - case DAE.BOX(exp) equation isLiteralExp(exp); then (); - case DAE.CONS(car = e1, cdr = e2) equation isLiteralExp(e1); isLiteralExp(e2); then (); - case DAE.LIST(valList = expl) equation List.map_0(expl, isLiteralExp); then (); - case DAE.META_TUPLE(expl) equation List.map_0(expl, isLiteralExp); then (); - case DAE.METARECORDCALL(args=expl) equation List.map_0(expl, isLiteralExp); then (); - case DAE.SHARED_LITERAL() then (); - else fail(); - end match; -end isLiteralExp; - // ============================================================================= // section to create SimCode from BackendDAE // @@ -1632,7 +301,7 @@ algorithm ((uniqueEqIndex, algorithmAndEquationAsserts)) = BackendDAEUtil.foldEqSystem(dlow, createAlgorithmAndEquationAsserts, (uniqueEqIndex, {})); discreteModelVars = BackendDAEUtil.foldEqSystem(dlow, extractDiscreteModelVars, {}); - makefileParams = createMakefileParams(includeDirs, libs, libPaths,false); + makefileParams = SimCodeFunctionUtil.createMakefileParams(includeDirs, libs, libPaths,false); (delayedExps, maxDelayedExpIndex) = extractDelayedExpressions(dlow); // append removed equation to all equations, since these are actually @@ -1782,7 +451,7 @@ algorithm SOME(backendMapping), modelStruct); - (simCode, (_, _, lits)) = traverseExpsSimCode(simCode, findLiteralsHelper, literals); + (simCode, (_, _, lits)) = traverseExpsSimCode(simCode, SimCodeFunctionUtil.findLiteralsHelper, literals); simCode = setSimCodeLiterals(simCode, listReverse(lits)); @@ -1809,6 +478,51 @@ algorithm end matchcontinue; end createSimCode; +public function createFunctions + input Absyn.Program inProgram; + input DAE.DAElist inDAElist; + input BackendDAE.BackendDAE inBackendDAE; + input Absyn.Path inPath; + output list libs; + output list libPaths; + output list includes; + output list includeDirs; + output list recordDecls; + output list functions; + output BackendDAE.BackendDAE outBackendDAE; + output DAE.DAElist outDAE; + output tuple> literals; +algorithm + (libs,libPaths, includes, includeDirs, recordDecls, functions, outBackendDAE, outDAE, literals) := + matchcontinue (inProgram, inDAElist, inBackendDAE, inPath) + local + list libs2,libpaths2, includes2, includeDirs2; + list funcelems, part_func_elems, recFuncs; + DAE.DAElist dae; + BackendDAE.BackendDAE dlow; + DAE.FunctionTree functionTree; + Absyn.Path path; + list fns; + list lits; + + case (_, dae, dlow as BackendDAE.DAE(shared=BackendDAE.SHARED(functionTree=functionTree)), _) + equation + // get all the used functions from the function tree + funcelems = DAEUtil.getFunctionList(functionTree); + funcelems = setRecordVariability(funcelems,inBackendDAE); + funcelems = Inline.inlineCallsInFunctions(funcelems, (NONE(), {DAE.NORM_INLINE(), DAE.AFTER_INDEX_RED_INLINE()}), {}); + (funcelems, literals as (_, _, lits)) = simulationFindLiterals(dlow, funcelems); + (fns, recordDecls, includes2, includeDirs2, libs2,libpaths2) = SimCodeFunctionUtil.elaborateFunctions(inProgram, funcelems, {}, lits, {}); // Do we need metarecords here as well? + then + (libs2, libpaths2,includes2, includeDirs2, recordDecls, fns, dlow, dae, literals); + else + equation + Error.addInternalError("Creation of Modelica functions failed.", sourceInfo()); + then + fail(); + end matchcontinue; +end createFunctions; + protected function collectPartitions input BackendDAE.EqSystem syst; input BackendDAE.Shared shared; @@ -5230,7 +3944,7 @@ protected function getSimVars2Crefs algorithm for cref in inCrefs loop try - outSimVars := get(cref, inSimVarHT)::outSimVars; + outSimVars := SimCodeFunctionUtil.get(cref, inSimVarHT)::outSimVars; else end try; end for; @@ -5614,239 +4328,6 @@ algorithm end match; end extractIdAndExpFromDelayExp; -public function createMakefileParams - input list includes; - input list libs; - input list libPaths; - input Boolean isFunction; - output SimCode.MakefileParams makefileParams; -protected - String omhome, ccompiler, cxxcompiler, linker, exeext, dllext, cflags, ldflags, rtlibs, platform, fopenmp,compileDir; -algorithm - ccompiler := if stringEq(Config.simCodeTarget(),"JavaScript") then "emcc" else - (if Flags.isSet(Flags.HPCOM) then System.getOMPCCompiler() else System.getCCompiler()); - cxxcompiler := if stringEq(Config.simCodeTarget(),"JavaScript") then "emcc" else System.getCXXCompiler(); - linker := if stringEq(Config.simCodeTarget(),"JavaScript") then "emcc" else System.getLinker(); - exeext := if stringEq(Config.simCodeTarget(),"JavaScript") then ".js" else System.getExeExt(); - dllext := System.getDllExt(); - omhome := Settings.getInstallationDirectoryPath(); - omhome := System.trim(omhome, "\""); // Remove any quotation marks from omhome. - cflags := System.getCFlags() + " " + - (if Flags.isSet(Flags.HPCOM) then "-fopenmp" else ""); - cflags := if stringEq(Config.simCodeTarget(),"JavaScript") then "-Os -Wno-warn-absolute-paths" else cflags; - ldflags := System.getLDFlags(); - rtlibs := if isFunction then System.getRTLibs() else System.getRTLibsSim(); - platform := System.modelicaPlatform(); - compileDir := System.pwd() + System.pathDelimiter(); - makefileParams := SimCode.MAKEFILE_PARAMS(ccompiler, cxxcompiler, linker, exeext, dllext, - omhome, cflags, ldflags, rtlibs, includes, libs,libPaths, platform,compileDir); -end createMakefileParams; - -protected function elaborateRecordDeclarationsFromTypes - input list inTypes; - input list inAccRecordDecls; - input list inReturnTypes; - output list outRecordDecls; - output list outReturnTypes; -algorithm - (outRecordDecls, outReturnTypes) := - match (inTypes, inAccRecordDecls, inReturnTypes) - local - list accRecDecls; - DAE.Type firstType; - list restTypes; - list returnTypes; - - case ({}, accRecDecls, _) - then (accRecDecls, inReturnTypes); - case (firstType :: restTypes, accRecDecls, _) - equation - (accRecDecls, returnTypes) = - elaborateRecordDeclarationsForRecord(firstType, accRecDecls, inReturnTypes); - (accRecDecls, returnTypes) = - elaborateRecordDeclarationsFromTypes(restTypes, accRecDecls, returnTypes); - then (accRecDecls, returnTypes); - end match; -end elaborateRecordDeclarationsFromTypes; - -protected function elaborateRecordDeclarations -"Translate all records used by varlist to structs." - input list inVars; - input list inAccRecordDecls; - input list inReturnTypes; - output list outRecordDecls; - output list outReturnTypes; -algorithm - (outRecordDecls, outReturnTypes) := - matchcontinue (inVars, inAccRecordDecls, inReturnTypes) - local - DAE.Element var; - list rest; - DAE.Type ft; - list rt, rt_1, rt_2; - list accRecDecls; - DAE.Algorithm algorithm_; - list expl; - - case ({}, accRecDecls, rt) then (accRecDecls, rt); - - case (((DAE.VAR(ty = ft)) :: rest), accRecDecls, rt) - equation - (accRecDecls, rt_1) = elaborateRecordDeclarationsForRecord(ft, accRecDecls, rt); - (accRecDecls, rt_2) = elaborateRecordDeclarations(rest, accRecDecls, rt_1); - then - (accRecDecls, rt_2); - - case ((DAE.ALGORITHM(algorithm_ = algorithm_) :: rest), accRecDecls, rt) - equation - true = Config.acceptMetaModelicaGrammar(); - ((_, expl)) = BackendDAEUtil.traverseAlgorithmExps(algorithm_, Expression.traverseSubexpressionsHelper, (matchMetarecordCalls, {})); - (accRecDecls, rt_2) = elaborateRecordDeclarationsForMetarecords(expl, accRecDecls, rt); - // TODO: ? what about rest ? , can be there something else after the ALGORITHM - (accRecDecls, rt_2) = elaborateRecordDeclarations(rest, accRecDecls, rt_2); - then - (accRecDecls, rt_2); - - case ((_ :: rest), accRecDecls, rt) - equation - (accRecDecls, rt_1) = elaborateRecordDeclarations(rest, accRecDecls, rt); - then - (accRecDecls, rt_1); - end matchcontinue; -end elaborateRecordDeclarations; - -protected function elaborateRecordDeclarationsForRecord -"Helper function to generateStructsForRecords." - input DAE.Type inRecordType; - input list inAccRecordDecls; - input list inReturnTypes; - output list outRecordDecls; - output list outReturnTypes; -algorithm - (outRecordDecls, outReturnTypes) := match (inRecordType, inAccRecordDecls, inReturnTypes) - local - Absyn.Path path, name; - list varlst; - String sname; - list rt, rt_1, rt_2, fieldNames; - list accRecDecls; - list vars; - Integer index; - SimCode.RecordDeclaration recDecl; - - case (DAE.T_COMPLEX(complexClassType = ClassInf.RECORD(name), varLst = varlst, source = {_}), accRecDecls, rt) - equation - sname = Absyn.pathStringUnquoteReplaceDot(name, "_"); - if not listMember(sname, rt) then - vars = List.map(varlst, typesVarNoBinding); - vars = List.sort(vars,compareVariable); - rt_1 = sname :: rt; - (accRecDecls, rt_2) = elaborateNestedRecordDeclarations(varlst, accRecDecls, rt_1); - recDecl = SimCode.RECORD_DECL_FULL(sname, NONE(), name, vars); - accRecDecls = List.appendElt(recDecl, accRecDecls); - else - rt_2 = rt; - end if; - then (accRecDecls, rt_2); - - case (DAE.T_COMPLEX(complexClassType = ClassInf.RECORD(_)), accRecDecls, rt) - then (accRecDecls, rt); - - case (DAE.T_METARECORD(source = {Absyn.QUALIFIED(name="SourceInfo")}), accRecDecls, rt) - then (accRecDecls, rt); - - case (DAE.T_METARECORD( fields = varlst, source = {path}), accRecDecls, rt) - equation - sname = Absyn.pathStringUnquoteReplaceDot(path, "_"); - if not listMember(sname, rt) then - fieldNames = List.map(varlst, generateVarName); - accRecDecls = SimCode.RECORD_DECL_DEF(path, fieldNames) :: accRecDecls; - rt_1 = sname::rt; - (accRecDecls, rt_2) = elaborateNestedRecordDeclarations(varlst, accRecDecls, rt_1); - else - rt_2 = rt; - end if; - then (accRecDecls, rt_2); - - case (_, accRecDecls, rt) - then (accRecDecls, rt); - - end match; -end elaborateRecordDeclarationsForRecord; - -protected function generateVarName - input DAE.Var inVar; - output String outName; -algorithm - outName := - match (inVar) - local - DAE.Ident name; - case DAE.TYPES_VAR(name = name) then name; - else "NULL"; - end match; -end generateVarName; - -protected function elaborateNestedRecordDeclarations -"Helper function to elaborateRecordDeclarations." - input list inRecordTypes; - input list inAccRecordDecls; - input list inReturnTypes; - output list outRecordDecls; - output list outReturnTypes; -algorithm - (outRecordDecls, outReturnTypes) := matchcontinue (inRecordTypes, inAccRecordDecls, inReturnTypes) - local - DAE.Type ty; - list rest; - list rt, rt_1, rt_2; - list accRecDecls; - case ({}, accRecDecls, rt) - then (accRecDecls, rt); - case (DAE.TYPES_VAR(ty = ty as DAE.T_COMPLEX(complexClassType = ClassInf.RECORD(_)))::rest, accRecDecls, rt) - equation - (accRecDecls, rt_1) = elaborateRecordDeclarationsForRecord(ty, accRecDecls, rt); - (accRecDecls, rt_2) = elaborateNestedRecordDeclarations(rest, accRecDecls, rt_1); - then (accRecDecls, rt_2); - case (_::rest, accRecDecls, rt) - equation - (accRecDecls, rt_1) = elaborateNestedRecordDeclarations(rest, accRecDecls, rt); - then (accRecDecls, rt_1); - end matchcontinue; -end elaborateNestedRecordDeclarations; - -protected function elaborateRecordDeclarationsForMetarecords - input list inExpl; - input list inAccRecordDecls; - input list inReturnTypes; - output list outRecordDecls; - output list outReturnTypes; -algorithm - (outRecordDecls, outReturnTypes) := match (inExpl, inAccRecordDecls, inReturnTypes) - local - list rt, rt_1, rt_2, fieldNames; - list rest; - String name; - Absyn.Path path; - list accRecDecls; - Boolean b; - - case ({}, accRecDecls, rt) then (accRecDecls, rt); - case (DAE.METARECORDCALL(path=path, fieldNames=fieldNames)::rest, accRecDecls, rt) - equation - name = Absyn.pathStringUnquoteReplaceDot(path, "_"); - b = listMember(name, rt); - accRecDecls = List.consOnTrue(not b, SimCode.RECORD_DECL_DEF(path, fieldNames), accRecDecls); - rt_1 = List.consOnTrue(not b, name, rt); - (accRecDecls, rt_2) = elaborateRecordDeclarationsForMetarecords(rest, accRecDecls, rt_1); - then (accRecDecls, rt_2); - case (_::rest, accRecDecls, rt) - equation - (accRecDecls, rt_1) = elaborateRecordDeclarationsForMetarecords(rest, accRecDecls, rt); - then (accRecDecls, rt_1); - end match; -end elaborateRecordDeclarationsForMetarecords; - protected function createExtObjInfo input BackendDAE.Shared shared; output SimCode.ExtObjInfo extObjInfo; @@ -8796,7 +7277,7 @@ algorithm size = numStateVars+numAlgVars+numIntAlgVars+numBoolAlgVars+numAlgAliasVars+numIntAliasVars+ numBoolAliasVars+numParams+numIntParams+numBoolParams+numOutVars+numInVars + numOptimizeConstraints + numOptimizeFinalConstraints; size = intMax(size,1000); - ht = emptyHashTableSized(size); + ht = SimCodeFunctionUtil.emptyHashTableSized(size); arraySimVars = HashTableCrILst.emptyHashTableSized(size); ht = List.fold(stateVars, addSimVarToHashTable, ht); //true = intLt(size, -1); @@ -8848,14 +7329,14 @@ algorithm case (sv as SimCodeVar.SIMVAR(name = cr, arrayCref = NONE()), _) equation //print("addSimVarToHashTable: handling variable '" + ComponentReference.printComponentRefStr(cr) + "'\n"); - outHT = add((cr, sv), inHT); + outHT = SimCodeFunctionUtil.add((cr, sv), inHT); then outHT; // add the whole array crefs to the hashtable, too case (sv as SimCodeVar.SIMVAR(name = cr, arrayCref = SOME(acr)), _) equation //print("addSimVarToHashTable: handling array variable '" + ComponentReference.printComponentRefStr(cr) + "'\n"); - outHT = add((acr, sv), inHT); - outHT = add((cr, sv), outHT); + outHT = SimCodeFunctionUtil.add((acr, sv), inHT); + outHT = SimCodeFunctionUtil.add((cr, sv), outHT); then outHT; else equation @@ -9037,324 +7518,75 @@ algorithm (e22, rhs); // not succeded to solve, return unsolved equation., catched later. - else (e1, e2); - end matchcontinue; -end solveTrivialArrayEquation; - -protected function solveTrivialArrayEquation2 -"author: Frenkel TUD - 2012-07 - helper for solveTrivialArrayEquation" - input DAE.Exp e1; - input DAE.Exp e2; - output DAE.Exp outE1; - output DAE.Exp outE2; -algorithm - (outE1, outE2) := match(e1, e2) - local - DAE.Exp lhs, rhs; - case(DAE.CREF(), _) - equation - (rhs, _) = ExpressionSimplify.simplify(Expression.negate(e2)); - then - (e1, rhs); - - case(DAE.UNARY(exp=lhs as DAE.CREF()), _) - equation - (rhs, _) = ExpressionSimplify.simplify(e2); - then - (lhs, rhs); - - end match; -end solveTrivialArrayEquation2; - -protected function getVectorizedCrefFromExp "author: PA - Returns the component ref v if expression is on form - {v{1}, v{2}, ...v{n}} for some n. - TODO: implement for 2D as well." - input DAE.Exp inExp; - output DAE.ComponentRef outComponentRef; -algorithm - outComponentRef := match (inExp) - local - list crefs, crefs_1; - DAE.ComponentRef cr; - list expl; - list> column; - - case (DAE.ARRAY(array = expl)) - equation - ((crefs as (cr :: _))) = List.map(expl, Expression.expCref); // Get all CRefs from exp1. - crefs_1 = List.map(crefs, ComponentReference.crefStripLastSubs); // Strip last subscripts - List.reduce(crefs_1, ComponentReference.crefEqualReturn); // Check if elements are equal, remove one - then - cr; - - case (DAE.MATRIX(matrix = column)) - equation - expl = List.flatten(column); - ((crefs as (cr :: _))) = List.map(expl, Expression.expCref); // Get all CRefs from exp1. - crefs_1 = List.map(crefs, ComponentReference.crefStripLastSubs); // Strip last subscripts - List.reduce(crefs_1, ComponentReference.crefEqualReturn); // Check if elements are equal, remove one - then - cr; - end match; -end getVectorizedCrefFromExp; - -protected function getCalledFunctionsInFunctions "Goes through the given DAE, finds the given functions and collects - the names of the functions called from within those functions" - input list paths; - input HashTableStringToPath.HashTable inHt; - input DAE.FunctionTree funcs; - output HashTableStringToPath.HashTable outHt; -algorithm - outHt := match (paths, inHt, funcs) - local - list rest; - Absyn.Path path; - HashTableStringToPath.HashTable ht; - - case ({}, ht, _) then ht; - case (path::rest, ht, _) - equation - ht = getCalledFunctionsInFunction2(path, Absyn.pathStringNoQual(path), ht, funcs); - ht = getCalledFunctionsInFunctions(rest, ht, funcs); - then ht; - end match; -end getCalledFunctionsInFunctions; - -public function getCalledFunctionsInFunction2 "Goes through the given DAE, finds the given function and collects - the names of the functions called from within those functions" - input Absyn.Path inPath; - input String pathstr; - input HashTableStringToPath.HashTable inHt "paths to not add"; - input DAE.FunctionTree funcs; - output HashTableStringToPath.HashTable outHt "paths to not add"; -algorithm - outHt := matchcontinue (inPath, pathstr, inHt, funcs) - local - String str; - Absyn.Path path; - DAE.Function funcelem; - list calledfuncs, varfuncs; - list els; - HashTableStringToPath.HashTable ht; - - case (_, _, ht, _) - equation - BaseHashTable.get(pathstr, ht); - then ht; - - case (path, _, ht, _) - equation - funcelem = DAEUtil.getNamedFunction(path, funcs); - els = DAEUtil.getFunctionElements(funcelem); - // SimCode.Function reference variables are filtered out - varfuncs = List.fold(els, DAEUtil.collectFunctionRefVarPaths, {}); - (_, (_, varfuncs)) = DAEUtil.traverseDAE2(els, Expression.traverseSubexpressionsHelper, (DAEUtil.collectValueblockFunctionRefVars, varfuncs)); - (_, (_, (calledfuncs, _))) = DAEUtil.traverseDAE2(els, Expression.traverseSubexpressionsHelper, (matchNonBuiltinCallsAndFnRefPaths, ({}, varfuncs))); - ht = BaseHashTable.add((pathstr, path), ht); - ht = addDestructor(funcelem, ht); - ht = getCalledFunctionsInFunctions(calledfuncs, ht, funcs); - then ht; - - case (path, _, _, _) - equation - failure(_ = DAEUtil.getNamedFunction(path, funcs)); - str = "function getCalledFunctionsInFunction2: Class " + pathstr + " not found in global scope."; - Error.addInternalError(str, sourceInfo()); - then - fail(); - end matchcontinue; -end getCalledFunctionsInFunction2; - -protected function addDestructor - input DAE.Function func; - input HashTableStringToPath.HashTable inHt; - output HashTableStringToPath.HashTable outHt; -algorithm - outHt := match (func,inHt) - local - Absyn.Path path; - String pathstr; - case (DAE.FUNCTION(type_=DAE.T_FUNCTION(funcResultType=DAE.T_COMPLEX(complexClassType=ClassInf.EXTERNAL_OBJ(path=path)))),_) - equation - path = Absyn.joinPaths(path,Absyn.IDENT("destructor")); - then addDestructor2(path,Absyn.pathStringNoQual(path),inHt); - else inHt; - end match; -end addDestructor; - -protected function addDestructor2 - input Absyn.Path path; - input String pathstr; - input HashTableStringToPath.HashTable inHt; - output HashTableStringToPath.HashTable ht = inHt; -algorithm - if not BaseHashTable.hasKey(pathstr, ht) then - BaseHashTable.add((pathstr, path), ht); - end if; -end addDestructor2; - -// ============================================================================= -// section for ??? -// -// ============================================================================= + else (e1, e2); + end matchcontinue; +end solveTrivialArrayEquation; -protected function isVarQ -"Succeeds if inElement is a variable or constant that is not input." - input DAE.Element inElement; +protected function solveTrivialArrayEquation2 +"author: Frenkel TUD - 2012-07 + helper for solveTrivialArrayEquation" + input DAE.Exp e1; + input DAE.Exp e2; + output DAE.Exp outE1; + output DAE.Exp outE2; algorithm - _ := match (inElement) + (outE1, outE2) := match(e1, e2) local - DAE.VarKind vk; - DAE.VarDirection vd; - case DAE.VAR(kind=vk, direction=vd) + DAE.Exp lhs, rhs; + case(DAE.CREF(), _) equation - isVarVarOrConstant(vk); - isDirectionNotInput(vd); - then (); - end match; -end isVarQ; + (rhs, _) = ExpressionSimplify.simplify(Expression.negate(e2)); + then + (e1, rhs); -/*mahge: kernel functions*/ -protected function isVarNotInputNotOutput -"Succeeds if inElement is a variable or constant that is not input or output. -needed in kernel functions since they shouldn't have output vars." - input DAE.Element inElement; -algorithm - _ := match (inElement) - local - DAE.VarKind vk; - DAE.VarDirection vd; - case DAE.VAR(kind=vk, direction=vd) + case(DAE.UNARY(exp=lhs as DAE.CREF()), _) equation - isVarVarOrConstant(vk); - isDirectionNotInputNotOutput(vd); - then (); - end match; -end isVarNotInputNotOutput; - -protected function isVarVarOrConstant - input DAE.VarKind inVarKind; -algorithm - _ := match (inVarKind) - case DAE.VARIABLE() then (); - case DAE.PARAM() then (); - case DAE.CONST() then (); - end match; -end isVarVarOrConstant; - -protected function isDirectionNotInput - input DAE.VarDirection inVarDirection; -algorithm - _ := match (inVarDirection) - case DAE.OUTPUT() then (); - case DAE.BIDIR() then (); - end match; -end isDirectionNotInput; + (rhs, _) = ExpressionSimplify.simplify(e2); + then + (lhs, rhs); -protected function isDirectionNotInputNotOutput - input DAE.VarDirection inVarDirection; -algorithm - _ := match (inVarDirection) - case DAE.BIDIR() then (); end match; -end isDirectionNotInputNotOutput; - -protected function filterNg "Sets the number of zero crossings to zero if events are disabled." - input Integer ng; - output Integer outInteger; -algorithm - outInteger := if useZerocrossing() then ng else 0; -end filterNg; - -protected function useZerocrossing - output Boolean res; -algorithm - res := Flags.isSet(Flags.EVENTS); -end useZerocrossing; +end solveTrivialArrayEquation2; -protected function getCrefFromExp "Assume input Exp is CREF and return the ComponentRef, fail otherwise." - input DAE.Exp e; - output Absyn.ComponentRef c; +protected function getVectorizedCrefFromExp "author: PA + Returns the component ref v if expression is on form + {v{1}, v{2}, ...v{n}} for some n. + TODO: implement for 2D as well." + input DAE.Exp inExp; + output DAE.ComponentRef outComponentRef; algorithm - c := match (e) + outComponentRef := match (inExp) local - DAE.ComponentRef crefe; - Absyn.ComponentRef crefa; + list crefs, crefs_1; + DAE.ComponentRef cr; + list expl; + list> column; - case(DAE.CREF(componentRef = crefe)) + case (DAE.ARRAY(array = expl)) equation - crefa = ComponentReference.unelabCref(crefe); + ((crefs as (cr :: _))) = List.map(expl, Expression.expCref); // Get all CRefs from exp1. + crefs_1 = List.map(crefs, ComponentReference.crefStripLastSubs); // Strip last subscripts + List.reduce(crefs_1, ComponentReference.crefEqualReturn); // Check if elements are equal, remove one then - crefa; + cr; - else + case (DAE.MATRIX(matrix = column)) equation - Error.addInternalError("function getCrefFromExp failed: input was not of type DAE.CREF", sourceInfo()); + expl = List.flatten(column); + ((crefs as (cr :: _))) = List.map(expl, Expression.expCref); // Get all CRefs from exp1. + crefs_1 = List.map(crefs, ComponentReference.crefStripLastSubs); // Strip last subscripts + List.reduce(crefs_1, ComponentReference.crefEqualReturn); // Check if elements are equal, remove one then - fail(); - end match; -end getCrefFromExp; - -protected function scodeParallelismToDAEParallelism - input SCode.Parallelism inParallelism; - output DAE.VarParallelism outParallelism; -algorithm - outParallelism := match(inParallelism) - case(SCode.PARGLOBAL()) then DAE.PARGLOBAL(); - case(SCode.PARLOCAL()) then DAE.PARLOCAL(); - case(SCode.NON_PARALLEL()) then DAE.NON_PARALLEL(); + cr; end match; -end scodeParallelismToDAEParallelism; +end getVectorizedCrefFromExp; -protected function typesVarNoBinding - input DAE.Var inTypesVar; - output SimCode.Variable outVar; -algorithm - outVar := match (inTypesVar) - local - String name; - DAE.Type ty; - DAE.ComponentRef cref_; - DAE.Attributes attr; - SCode.Parallelism scPrl; - DAE.VarParallelism prl; - - case (DAE.TYPES_VAR(name=name, attributes = attr, ty=ty)) - equation - ty = Types.simplifyType(ty); - cref_ = ComponentReference.makeCrefIdent(name, ty, {}); - DAE.ATTR(parallelism = scPrl) = attr; - prl = scodeParallelismToDAEParallelism(scPrl); - then SimCode.VARIABLE(cref_, ty, NONE(), {}, prl,DAE.VARIABLE()); - end match; -end typesVarNoBinding; +// ============================================================================= +// section for ??? +// +// ============================================================================= -protected function typesVar - input DAE.Var inTypesVar; - output SimCode.Variable outVar; -algorithm - outVar := match (inTypesVar) - local - String name; - DAE.Type ty; - DAE.ComponentRef cref_; - DAE.Attributes attr; - SCode.Parallelism scPrl; - DAE.VarParallelism prl; - DAE.Exp bindExp; - - case (DAE.TYPES_VAR(name=name, attributes = attr, ty=ty)) - equation - ty = Types.simplifyType(ty); - cref_ = ComponentReference.makeCrefIdent(name, ty, {}); - DAE.ATTR(parallelism = scPrl) = attr; - prl = scodeParallelismToDAEParallelism(scPrl); - bindExp = Types.getBindingExp(inTypesVar, Absyn.IDENT(name)); - then SimCode.VARIABLE(cref_, ty, SOME(bindExp), {}, prl, DAE.VARIABLE()); - end match; -end typesVar; +/*mahge: kernel functions*/ protected function dlowvarToSimvar input BackendDAE.Var dlowVar; @@ -9499,628 +7731,68 @@ end dlowvarToSimvar; // str = "Initial value of unknown type: " + ExpressionDump.printExpStr(exp); // Error.addSourceMessage(Error.INTERNAL_ERROR, {str}, info); // then (); -// end match; -// end checkInitVal; - -protected function getCausality - input BackendDAE.Var dlowVar; - input BackendDAE.Variables inVars; - output SimCodeVar.Causality caus; -algorithm - caus := matchcontinue (dlowVar, inVars) - local - DAE.ComponentRef cr; - BackendDAE.Variables knvars; - case (BackendDAE.VAR(varName = cr, varDirection = DAE.OUTPUT()), _) then SimCodeVar.OUTPUT(); - case (BackendDAE.VAR(varName = cr, varDirection = DAE.INPUT()), knvars) - equation - (_, _) = BackendVariable.getVar(cr, knvars); - then SimCodeVar.INPUT(); - else SimCodeVar.INTERNAL(); - end matchcontinue; -end getCausality; - -protected function traversingdlowvarToSimvarFold - input BackendDAE.Var v; - input tuple, BackendDAE.Variables> inTpl; - output tuple, BackendDAE.Variables> outTpl; -algorithm - (_, outTpl) := traversingdlowvarToSimvar(v, inTpl); -end traversingdlowvarToSimvarFold; - -protected function traversingdlowvarToSimvar - input BackendDAE.Var inVar; - input tuple, BackendDAE.Variables> inTpl; - output BackendDAE.Var outVar; - output tuple, BackendDAE.Variables> outTpl; -algorithm - (outVar,outTpl) := match (inVar,inTpl) - local - BackendDAE.Var v; - list sv_lst; - SimCodeVar.SimVar sv; - BackendDAE.Variables vars; - case (v, (sv_lst, vars)) - equation - sv = dlowvarToSimvar(v, NONE(), vars); - then (v, (sv::sv_lst, vars)); - else (inVar,inTpl); - end match; -end traversingdlowvarToSimvar; - -protected function subsToScalar "scalar expression." - input list inExpSubscriptLst; - output Boolean outBoolean; -algorithm - outBoolean := match (inExpSubscriptLst) - local - Boolean b; - list r; - case {} then true; - case (DAE.SLICE() :: _) then false; - case (DAE.WHOLEDIM() :: _) then false; - case (DAE.INDEX() :: r) - equation - b = subsToScalar(r); - then - b; - end match; -end subsToScalar; - -public function getMatchingExpsList - input list inExps; - input MatchFn inFn; - output list outExpLst; - partial function MatchFn - input DAE.Exp inExp; - input list inExps; - output DAE.Exp outExp; - output list outExps; - end MatchFn; -algorithm - (_, outExpLst) := Expression.traverseExpList(inExps, inFn, {}); -end getMatchingExpsList; - -protected function matchNonBuiltinCallsAndFnRefPaths "The extra argument is a tuple; the second list is the list of variable - names to filter out (so we don't add function references variables)" - input DAE.Exp inExp; - input tuple, list> itpl; - output DAE.Exp outExp; - output tuple, list> otpl; -algorithm - (outExp,otpl) := matchcontinue (inExp,itpl) - local - Absyn.Path path; - list acc, filter; - case (DAE.CALL(path = path, attr = DAE.CALL_ATTR(builtin = false)), (acc, filter)) - equation - path = Absyn.makeNotFullyQualified(path); - false = List.isMemberOnTrue(path, filter, Absyn.pathEqual); - then (inExp, (path::acc, filter)); - case (DAE.REDUCTION(reductionInfo = DAE.REDUCTIONINFO(path = path)), (acc, filter)) - equation - false = List.isMemberOnTrue(path, {Absyn.IDENT("list"),Absyn.IDENT("listReverse"),Absyn.IDENT("array"),Absyn.IDENT("min"),Absyn.IDENT("max"),Absyn.IDENT("sum"),Absyn.IDENT("product")}, Absyn.pathEqual); - false = List.isMemberOnTrue(path, filter, Absyn.pathEqual); - then (inExp, (path::acc, filter)); - case (DAE.PARTEVALFUNCTION(path = path), (acc, filter)) - equation - path = Absyn.makeNotFullyQualified(path); - false = List.isMemberOnTrue(path, filter, Absyn.pathEqual); - then (inExp, (path::acc, filter)); - case (DAE.CREF(ty = DAE.T_FUNCTION_REFERENCE_FUNC(builtin = false)), (acc, filter)) - equation - path = Absyn.crefToPath(getCrefFromExp(inExp)); - false = List.isMemberOnTrue(path, filter, Absyn.pathEqual); - then (inExp, (path::acc, filter)); - else (inExp,itpl); - end matchcontinue; -end matchNonBuiltinCallsAndFnRefPaths; - -protected function matchMetarecordCalls "Used together with getMatchingExps" - input DAE.Exp e; - input list acc; - output DAE.Exp outExp; - output list outExps; -algorithm - (outExp,outExps) := matchcontinue (e,acc) - local - Integer index; - case (DAE.METARECORDCALL(index = index), _) - equation - outExps = List.consOnTrue(-1 <> index, e, acc); - then (e, outExps); - else (e,acc); - end matchcontinue; -end matchMetarecordCalls; - -protected function generateExtFunctionIncludes "by investigating the annotation of an external function." - input Absyn.Program program; - input Absyn.Path path; - input Option inAbsynAnnotationOption; - input SourceInfo info; - output list includes; - output list includeDirs; - output list libs; - output list paths; - output Boolean dynamcLoad; -algorithm - (includes, includeDirs, libs,paths, dynamcLoad):= - match (program, path, inAbsynAnnotationOption) - local - SCode.Mod mod; - Boolean b; - String target; - Option odir, resources; - list libNames, fullLibNames, dirs; - - case (_, _, SOME(SCode.ANNOTATION(mod))) - algorithm - b := generateExtFunctionDynamicLoad(mod); - target := Flags.getConfigString(Flags.TARGET); - (libs, libNames) := generateExtFunctionIncludesLibstr(target,mod); - includes := generateExtFunctionIncludesIncludestr(mod); - (libs, dirs, resources) := generateExtFunctionLibraryDirectoryFlags(program, path, mod, libs); - for name in if Flags.isSet(Flags.CHECK_EXT_LIBS) then libNames else {} loop - if target=="msvc" or System.os()=="Windows_NT" then - fullLibNames := {name + System.getDllExt(), "lib" + name + ".a", "lib" + name + ".lib"}; - else - fullLibNames := {"lib" + name + ".a", "lib" + name + System.getDllExt()}; - end if; - lookForExtFunctionLibrary(fullLibNames, dirs, name, resources, path, info); - end for; - paths := generateExtFunctionLibraryDirectoryPaths(program, path, mod); - includeDirs := generateExtFunctionIncludeDirectoryFlags(program, path, mod, includes); - then - (includes, includeDirs, libs,paths, b); - case (_, _, NONE()) then ({}, {}, {},{}, false); - end match; -end generateExtFunctionIncludes; - -protected function lookForExtFunctionLibrary - input list names; - input list dirs; - input String name; - input Option resources; - input Absyn.Path path; - input SourceInfo info; -algorithm - if not max(System.regularFileExists(d+"/"+n) for d in dirs, n in names) then - _ := match resources - local - String resourcesStr, tmpdir, cmd, pwd, contents, found; - Integer status; - Boolean didFind; - case SOME(resourcesStr) - algorithm - if System.directoryExists(resourcesStr) then - didFind := false; - for dir in list(dir for dir guard System.regularFileExists(resourcesStr + "/BuildProjects/" + dir + "/autogen.sh") in System.subDirectories(resourcesStr + "/BuildProjects")) loop - tmpdir := System.createTemporaryDirectory(Settings.getTempDirectoryPath() + "/omc_compile_" + name + "_"); - Error.addSourceMessage(Error.COMPILER_NOTIFICATION, {"Created directory " + tmpdir}, info); - cmd := "cp -a \"" + resourcesStr + "\"/* \"" + tmpdir + "\""; - Error.addSourceMessage(Error.COMPILER_NOTIFICATION, {cmd}, info); - System.systemCall(cmd); - pwd := System.pwd(); - if 0==System.cd(tmpdir + "/BuildProjects/" + dir) then - Error.addSourceMessage(Error.COMPILER_NOTIFICATION, {"Changed directory to " + System.pwd()}, info); - // TODO: Add $(host) - cmd := "sh ./autogen.sh && ./configure --libdir='"+userCompiledBinariesDirectory(path)+"' && make && make install"; - status := System.systemCall(cmd, "log"); - contents := System.readFile("log"); - if status <> 0 then - Error.addSourceMessage(Error.COMPILER_WARNING, {"Failed to run "+cmd+": " + contents}, info); - else - Error.addSourceMessage(Error.COMPILER_NOTIFICATION, {"Succeeded with compilation and installation of the library using:\ncommand: "+cmd+"\n" + contents}, info); - if not max(System.regularFileExists(d+"/"+n) for d in dirs, n in names) then - Error.addSourceMessage(Error.EXT_LIBRARY_NOT_FOUND_DESPITE_COMPILATION_SUCCESS, {cmd, System.pwd()}, info); - else - found := listHead(list(x for x guard System.regularFileExists(x) in List.flatten(list(d+"/"+n for d in dirs, n in names)))); - Error.addSourceMessage(Error.COMPILER_NOTIFICATION, {"Compiled "+found+" by running build project " + resourcesStr + "/BuildProjects/" + dir}, info); - didFind := true; - end if; - end if; - else - Error.addSourceMessage(Error.COMPILER_WARNING, {"Failed to change directory to " + tmpdir + "/BuildProjects/" + dir}, info); - end if; - System.cd(pwd); - System.removeDirectory(tmpdir); - Error.addSourceMessage(Error.COMPILER_NOTIFICATION, {"Removed directory " + tmpdir}, info); - if didFind then - break; - end if; - end for; - end if; - then (); - else (); - end match; - if not max(System.regularFileExists(d+"/"+n) for d in dirs, n in names) then - // suppress this warning if we're running the testsuite - if not Config.getRunningTestsuite() then - Error.addSourceMessage(Error.EXT_LIBRARY_NOT_FOUND, {name, sum("\n " + d + "/" + n for d in dirs, n in names)}, info); - end if; - end if; - end if; -end lookForExtFunctionLibrary; - -protected function generateExtFunctionIncludeDirectoryFlags - "Process LibraryDirectory and IncludeDirectory" - input Absyn.Program program; - input Absyn.Path path; - input SCode.Mod inMod; - input list includes; - output list outDirs; -algorithm - outDirs := matchcontinue (program, path, inMod, includes) - local - String str,istr; - case (_, _, _, {}) then {}; - case (_, _, _, _) - equation - SCode.MOD(binding = SOME(Absyn.STRING(str))) = - Mod.getUnelabedSubMod(inMod, "IncludeDirectory"); - str = CevalScript.getFullPathFromUri(program, str, false); - istr = "\"-I"+str+"\""; - then if System.directoryExists(str) then {istr} else {}; - case (_, _, _, _) - equation - str = "modelica://" + Absyn.pathFirstIdent(path) + "/Resources/Include"; - str = CevalScript.getFullPathFromUri(program, str, false); - istr = "\"-I"+str+"\""; - then if System.directoryExists(str) then {istr} else {}; - // Read SourceInfo instead? - else {}; - end matchcontinue; -end generateExtFunctionIncludeDirectoryFlags; - -protected function generateExtFunctionLibraryDirectoryFlags - "Process LibraryDirectory and IncludeDirectory" - input Absyn.Program program; - input Absyn.Path path; - input SCode.Mod inMod; - input list inLibs; - output list outLibs; - output list installDirs; - output Option resources; -algorithm - (outLibs, installDirs, resources) := matchcontinue (program, path, inMod, inLibs) - local - String str, str1, str2, str3, platform1, platform2, target, dir, resourcesStr; - list libs, libs2; - Boolean isLinux; - case (_, _, _, {}) then ({}, {}, NONE()); - case (_, _, _, libs) - algorithm - str := matchcontinue inMod - case _ - equation - SCode.MOD(binding = SOME(Absyn.STRING(str))) = Mod.getUnelabedSubMod(inMod, "LibraryDirectory"); - then str; - else "modelica://" + Absyn.pathFirstIdent(path) + "/Resources/Library"; - end matchcontinue; - str := CevalScript.getFullPathFromUri(program, str, false); - resourcesStr := CevalScript.getFullPathFromUri(program, "modelica://" + Absyn.pathFirstIdent(path) + "/Resources", false); - platform1 := str + "/" + System.openModelicaPlatform(); - platform2 := str + "/" + System.modelicaPlatform(); - isLinux := stringEq("linux",System.os()); - target := Flags.getConfigString(Flags.TARGET); - // please, take care about ordering these libraries, the most specific should have the highest priority - libs2 := str::platform2::platform1::(Settings.getHomeDir(false)+"/.openmodelica/binaries/"+Absyn.pathFirstIdent(path))::(Settings.getInstallationDirectoryPath() + "/lib/" + System.getTriple() + "/omc")::(Settings.getInstallationDirectoryPath() + "/lib/")::{}; - libs := List.fold2(libs2, generateExtFunctionLibraryDirectoryFlags2, isLinux, target, libs); - then (libs, listReverse(libs2), SOME(resourcesStr)); - else (inLibs, {}, NONE()); - end matchcontinue; -end generateExtFunctionLibraryDirectoryFlags; - -protected function generateExtFunctionLibraryDirectoryFlags2 - input String dir; - input Boolean isLinux; - input String target; - input list inLibs; - output list libs; -algorithm - libs := if isLinux then "-Wl,-rpath=\"" + dir + "\""::inLibs else inLibs; - libs := (if target=="msvc" then "/LIBPATH:\"" + dir + "\"" else "\"-L" + dir + "\"")::libs; -end generateExtFunctionLibraryDirectoryFlags2; - -protected function userCompiledBinariesDirectory - input Absyn.Path path; - output String str = Settings.getHomeDir(false)+"/.openmodelica/binaries/"+Absyn.pathFirstIdent(path); -end userCompiledBinariesDirectory; - -protected function generateExtFunctionLibraryDirectoryPaths - "Process LibraryDirectory and IncludeDirectory" - input Absyn.Program program; - input Absyn.Path path; - input SCode.Mod inMod; - output list outLibs; -algorithm - outLibs := matchcontinue (program, path, inMod) - local - String str, str1, str2, str3, platform1, platform2,target; - list libs; - Boolean isLinux; - case (_, _, _) - equation - SCode.MOD(binding = SOME(Absyn.STRING(str))) = - Mod.getUnelabedSubMod(inMod, "LibraryDirectory"); - str = CevalScript.getFullPathFromUri(program, str, false); - platform1 = System.openModelicaPlatform(); - platform2 = System.modelicaPlatform(); - isLinux = stringEq("linux",System.os()); - // please, take care about ordering these libraries, the most specific should go first (in reverse here) - libs = generateExtFunctionLibraryDirectoryPaths2(true, str, isLinux, {} ); - libs = generateExtFunctionLibraryDirectoryPaths2(not stringEq(platform2,""), str + "/" + platform2, isLinux, libs); - libs = generateExtFunctionLibraryDirectoryPaths2(not stringEq(platform1,""), str + "/" + platform1, isLinux, libs); - then libs; - case (_, _, _) - equation - str = "modelica://" + Absyn.pathFirstIdent(path) + "/Resources/Library"; - str = CevalScript.getFullPathFromUri(program, str, false); - platform1 = System.openModelicaPlatform(); - platform2 = System.modelicaPlatform(); - isLinux = stringEq("linux",System.os()); - // please, take care about ordering these libraries, the most specific should go first (in reverse here) - libs = generateExtFunctionLibraryDirectoryPaths2(true, str, isLinux, {} ); - libs = generateExtFunctionLibraryDirectoryPaths2(not stringEq(platform2,""), str + "/" + platform2, isLinux, libs); - libs = generateExtFunctionLibraryDirectoryPaths2(not stringEq(platform1,""), str + "/" + platform1, isLinux, libs); - then libs; - else {}; - end matchcontinue; -end generateExtFunctionLibraryDirectoryPaths; - - -protected function generateExtFunctionLibraryDirectoryPaths2 - input Boolean add; - input String dir; - input Boolean isLinux; - input list inLibs; - output list libs; -algorithm - libs := match (add,dir,isLinux,inLibs) - local - Boolean b; - case (true,_,_,libs) - equation - b = System.directoryExists(dir); - libs = List.consOnTrue(b, dir , libs); - then libs; - else inLibs; - end match; -end generateExtFunctionLibraryDirectoryPaths2; - - -protected function getLibraryStringInMSVCFormat -"Takes an Absyn.STRING describing a library and outputs a list -of strings corresponding to it. -Note: Normally only outputs a single string, but Lapack on MinGW is special." - input Absyn.Exp exp; - output list strs; - output list names; -algorithm - (strs,names) := matchcontinue exp - local - String str; - - // seems lapack can show on Lapack form or lapack (different case) (MLS revision 6155) - // Lapack on MinGW/Windows is linked against f2c - case Absyn.STRING(str) guard str=="Lapack" or str=="lapack" - then ({"lapack_win32_MT.lib", "f2c.lib"}, {}); - - // omcruntime on windows needs linking with mico2313 and wsock and then some :) - case Absyn.STRING("omcruntime") - equation - true = "Windows_NT" == System.os(); - strs = {"f2c.lib", "initialization.lib", "libexpat.lib", "math-support.lib", "meta.lib", "ModelicaExternalC.lib", "results.lib", "simulation.lib", "solver.lib", "sundials_kinsol.lib", "sundials_nvecserial.lib", "util.lib", "lapack_win32_MT.lib"}; - then - (strs, {}); - - // Wonder if there may be issues if we have duplicates in the Corba libs - // and the other libs. Some other developer will probably swear over this - // hack some day, but at least I get an early weekend. - case Absyn.STRING("OpenModelicaCorba") - equation - str = System.getCorbaLibs(); - then ({str},{}); - - case Absyn.STRING("fmilib") - then ({"fmilib.lib","shlwapi.lib"},{}); - - // If the string starts with a -, it's probably -l or -L gcc flags - case Absyn.STRING(str) - equation - true = "-" == stringGetStringChar(str, 1); - then ({str},{}); - - case Absyn.STRING(str) - equation - str = str + ".lib"; - then ({str},{}); - - else - equation - Error.addInternalError("Failed to process Library annotation for external function", sourceInfo()); - then fail(); - end matchcontinue; -end getLibraryStringInMSVCFormat; - -protected function getLibraryStringInGccFormat -"Takes an Absyn.STRING describing a library and outputs a list -of strings corresponding to it. -Note: Normally only outputs a single string, but Lapack on MinGW is special." - input Absyn.Exp exp; - output list strs; - output list names; -algorithm - (strs,names) := matchcontinue exp - local - String str, fopenmp; - - // Lapack is always included - case Absyn.STRING("lapack") then ({},{}); - case Absyn.STRING("Lapack") then ({},{}); - - case Absyn.STRING(str as "omcruntime") - equation - if "Windows_NT" == System.os() then - // omcruntime on windows needs linking with mico2313 and wsock and then some :) - str = "-l" + str; - strs = str :: "-lintl" :: "-liconv" :: "-lexpat" :: "-lsqlite3" :: "-llpsolve55" :: "-lmico2313" :: "-lws2_32" :: "-lregex" :: {}; - else - strs = System.getRuntimeLibs(); - end if; - then (strs,{}); - - // Wonder if there may be issues if we have duplicates in the Corba libs - // and the other libs. Some other developer will probably swear over this - // hack some day, but at least I get an early weekend. - case Absyn.STRING("OpenModelicaCorba") - equation - str = System.getCorbaLibs(); - then ({str},{}); - - case Absyn.STRING("fmilib") - then (if System.os()=="Windows_NT" then {"-lfmilib","-lshlwapi"} else {"-lfmilib"},{}); - - case Absyn.STRING(str) - equation - // If the string is a file, return it as it is - // If the string starts with a -, it's probably -l or -L gcc flags - if System.regularFileExists(str) or "-" == stringGetStringChar(str, 1) then - strs = {str}; - names = {}; - else - strs = {"-l" + str}; - names = {str}; - end if; - - then (strs,names); - - else - equation - Error.addInternalError("Failed to process Library annotation for external function", sourceInfo()); - then fail(); - end matchcontinue; -end getLibraryStringInGccFormat; +// end match; +// end checkInitVal; -protected function generateExtFunctionIncludesLibstr - input String target; - input SCode.Mod inMod; - output list outStringLst; - output list names; +protected function getCausality + input BackendDAE.Var dlowVar; + input BackendDAE.Variables inVars; + output SimCodeVar.Causality caus; algorithm - (outStringLst, names) := matchcontinue (target,inMod) + caus := matchcontinue (dlowVar, inVars) local - list arr; - list libs; - list> libsList, namesList; - Absyn.Exp exp; - case ("msvc",_) - equation - SCode.MOD(binding = SOME(Absyn.ARRAY(arr))) = - Mod.getUnelabedSubMod(inMod, "Library"); - (libsList, namesList) = List.map_2(arr, getLibraryStringInMSVCFormat); - then - (List.flatten(libsList), List.flatten(namesList)); - case ("msvc",_) - equation - SCode.MOD(binding = SOME(exp)) = - Mod.getUnelabedSubMod(inMod, "Library"); - (libs,names) = getLibraryStringInMSVCFormat(exp); - then - (libs,names); - case (_,_) - equation - SCode.MOD(binding = SOME(Absyn.ARRAY(arr))) = - Mod.getUnelabedSubMod(inMod, "Library"); - (libsList, namesList) = List.map_2(arr, getLibraryStringInGccFormat); - then - (List.flatten(libsList), List.flatten(namesList)); - case (_,_) + DAE.ComponentRef cr; + BackendDAE.Variables knvars; + case (BackendDAE.VAR(varName = cr, varDirection = DAE.OUTPUT()), _) then SimCodeVar.OUTPUT(); + case (BackendDAE.VAR(varName = cr, varDirection = DAE.INPUT()), knvars) equation - SCode.MOD(binding = SOME(exp)) = - Mod.getUnelabedSubMod(inMod, "Library"); - (libs,names) = getLibraryStringInGccFormat(exp); - then - (libs,names); - else ({},{}); + (_, _) = BackendVariable.getVar(cr, knvars); + then SimCodeVar.INPUT(); + else SimCodeVar.INTERNAL(); end matchcontinue; -end generateExtFunctionIncludesLibstr; +end getCausality; -protected function generateExtFunctionIncludesIncludestr - input SCode.Mod inMod; - output list includes; +protected function traversingdlowvarToSimvarFold + input BackendDAE.Var v; + input tuple, BackendDAE.Variables> inTpl; + output tuple, BackendDAE.Variables> outTpl; algorithm - includes := matchcontinue (inMod) - local - String inc, inc_1; - Integer lineNumberStart; - String str,fileName; - case (_) - equation - SCode.MOD(binding = SOME(Absyn.STRING(inc)), info = SOURCEINFO(fileName=fileName,lineNumberStart=lineNumberStart)) = - Mod.getUnelabedSubMod(inMod, "Include"); - str = "#line "+intString(lineNumberStart)+" \""+fileName+"\""; - inc_1 = System.unescapedString(inc); - includes = if Config.acceptMetaModelicaGrammar() or Flags.isSet(Flags.GEN_DEBUG_SYMBOLS) then {str,inc_1} else {inc_1}; - then includes; - else {}; - end matchcontinue; -end generateExtFunctionIncludesIncludestr; + (_, outTpl) := traversingdlowvarToSimvar(v, inTpl); +end traversingdlowvarToSimvarFold; -protected function generateExtFunctionDynamicLoad - input SCode.Mod inMod; - output Boolean outDynamicLoad; +protected function traversingdlowvarToSimvar + input BackendDAE.Var inVar; + input tuple, BackendDAE.Variables> inTpl; + output BackendDAE.Var outVar; + output tuple, BackendDAE.Variables> outTpl; algorithm - outDynamicLoad:= matchcontinue (inMod) + (outVar,outTpl) := match (inVar,inTpl) local - Boolean b; - case (_) + BackendDAE.Var v; + list sv_lst; + SimCodeVar.SimVar sv; + BackendDAE.Variables vars; + case (v, (sv_lst, vars)) equation - SCode.MOD(binding = SOME((Absyn.BOOL(b)))) = - Mod.getUnelabedSubMod(inMod, "DynamicLoad"); - then - b; - else false; - end matchcontinue; -end generateExtFunctionDynamicLoad; - -public function getImplicitRecordConstructors - "If a record instance is sent to a function we need to generate code for the - record constructor even if it's not explicitly called, because the constructor - is used by the generated code. This function checks the arguments of a - function for these implicit record constructor calls and returns a list of all - record constructors that are used." - input list inExpLst; + sv = dlowvarToSimvar(v, NONE(), vars); + then (v, (sv::sv_lst, vars)); + else (inVar,inTpl); + end match; +end traversingdlowvarToSimvar; + +public function getMatchingExpsList + input list inExps; + input MatchFn inFn; output list outExpLst; + partial function MatchFn + input DAE.Exp inExp; + input list inExps; + output DAE.Exp outExp; + output list outExps; + end MatchFn; algorithm - outExpLst := matchcontinue(inExpLst) - local - DAE.ComponentRef cref; - DAE.Type record_type; - Absyn.Path record_path; - list rest_expr; - DAE.Exp record_cref; - case ({}) then {}; - // A record component reference. - case (DAE.CREF( - componentRef = cref, - ty = (DAE.T_COMPLEX( - complexClassType = ClassInf.RECORD(path = record_path)))) :: rest_expr) - equation - // Make sure it has no subscripts, i.e. it's a component reference for - // an entire record instance. - {} = ComponentReference.crefLastSubs(cref); - // Build a DAE.CREF from the record path. - cref = ComponentReference.pathToCref(record_path); - record_cref = Expression.crefExp(cref); - rest_expr = getImplicitRecordConstructors(rest_expr); - then record_cref :: rest_expr; - case (_ :: rest_expr) - equation - rest_expr = getImplicitRecordConstructors(rest_expr); - then rest_expr; - end matchcontinue; -end getImplicitRecordConstructors; + (_, outExpLst) := Expression.traverseExpList(inExps, inFn, {}); +end getMatchingExpsList; protected function addDivExpErrorMsgtoExp "author: Frenkel TUD 2010-02, Adds the error msg to Expression.Div." input DAE.Exp inExp; @@ -10513,554 +8185,6 @@ algorithm end matchcontinue; end getNominalValue; - -/****** HashTable ComponentRef -> SimCodeVar.SimVar ******/ -/* a workaround to enable "cross public import" */ - - -/* HashTable instance specific code */ - -protected function keyEqual - input SimCode.Key key1; - input SimCode.Key key2; - output Boolean res; -algorithm - res := ComponentReference.crefEqualNoStringCompare(key1, key2); -end keyEqual; - -/* end of HashTable instance specific code */ - - -/* - public function cloneHashTable " - Author BZ 2008-06 - Make a stand-alone-copy of hashtable. - " - input HashTableCrefToSimVar inHash; - output HashTableCrefToSimVar outHash; - algorithm outHash := matchcontinue(inHash) - local - array>> arg1, arg1_2; - Integer arg3, arg4, arg3_2, arg4_2, arg21, arg21_2, arg22, arg22_2; - array>> arg23, arg23_2; - case(HASHTABLE(arg1, VALUE_ARRAY(arg21, arg22, arg23), arg3, arg4)) - equation - arg1_2 = arrayCopy(arg1); - arg21_2 = arg21; - arg22_2 = arg22; - arg23_2 = arrayCopy(arg23); - arg3_2 = arg3; - arg4_2 = arg4; - then - HASHTABLE(arg1_2, VALUE_ARRAY(arg21_2, arg22_2, arg23_2), arg3_2, arg4_2); - end matchcontinue; - end cloneHashTable; - - public function nullHashTable " - author: PA - - Returns an empty HashTable. - Using the bucketsize 100 and array size 10. - " - output HashTableCrefToSimVar hashTable; - array>> arr; - list>> lst; - array>> emptyarr; - algorithm - arr := fill({}, 0); - emptyarr := listArray({}); - hashTable := HASHTABLE(arr, VALUE_ARRAY(0, 0, emptyarr), 0, 0); - end nullHashTable; - */ - -protected function emptyHashTableSized " - author: PA - Returns an empty HashTable. - Using the bucketsize 100 and array size 10." - input Integer size; - output SimCode.HashTableCrefToSimVar hashTable; -protected - array>> arr; - list>> lst; - array>> emptyarr; - Integer szArr; -algorithm - arr := arrayCreate(size, {}); - emptyarr := arrayCreate(size, NONE()); - szArr:=realInt(realMul(intReal(size), 0.6)); - hashTable := SimCode.HASHTABLE(arr, SimCode.VALUE_ARRAY(0, szArr, emptyarr), size, 0); -end emptyHashTableSized; - -/* - public function isEmpty "Returns true if hashtable is empty" - input HashTableCrefToSimVar hashTable; - output Boolean res; - algorithm - res := matchcontinue(hashTable) - case(HASHTABLE(_, _, _, 0)) then true; - case(_) then false; - end matchcontinue; - end isEmpty; - */ - -public function add " - author: PA - - Add a Key-Value tuple to hashtable. - If the Key-Value tuple already exists, the function updates the Value. -" - input tuple entry; - input SimCode.HashTableCrefToSimVar hashTable; - output SimCode.HashTableCrefToSimVar outHashTable; -algorithm - outHashTable := matchcontinue (entry, hashTable) - local - Integer indx, newpos, n, n_1, bsize, indx_1; - SimCode.ValueArray varr_1, varr; - list> indexes; - array>> hashvec_1, hashvec; - tuple v, newv; - SimCode.Key key; - SimCode.Value value; - /* Adding when not existing previously */ - case ((v as (key, _)), (SimCode.HASHTABLE(hashvec, varr, bsize, _))) - equation - failure((_) = get(key, hashTable)); - indx = ComponentReference.hashComponentRefMod(key,bsize); - newpos = valueArrayLength(varr); - varr_1 = valueArrayAdd(varr, v); - indexes = hashvec[indx + 1]; - hashvec_1 = arrayUpdate(hashvec, indx + 1, ((key, newpos) :: indexes)); - n_1 = valueArrayLength(varr_1); - then SimCode.HASHTABLE(hashvec_1, varr_1, bsize, n_1); - - /* adding when already present => Updating value */ - case ((newv as (key, _)), (SimCode.HASHTABLE(hashvec, varr, bsize, n))) - equation - (_, indx) = get1(key, hashTable); - // print("adding when present, indx =" );print(intString(indx));print("\n"); - varr_1 = valueArraySetnth(varr, indx, newv); - then SimCode.HASHTABLE(hashvec, varr_1, bsize, n); - case (_, _) - equation - print("- HashTableCrefToSimVar.add failed\n"); - then - fail(); - end matchcontinue; -end add; -/* - public function anyKeyInHashTable "Returns true if any of the keys are present in the hashtable. Stops and returns true upon first occurence" - input list keys; - input HashTableCrefToSimVar ht; - output Boolean res; - algorithm - res := matchcontinue(keys, ht) - local Key key; - case({}, ht) then false; - case(key::keys, ht) equation - _ = get(key, ht); - then true; - case(_::keys, ht) then anyKeyInHashTable(keys, ht); - end matchcontinue; - end anyKeyInHashTable; - - public function addListNoUpd "adds several keys with the same value, using addNuUpdCheck. Can be used to use HashTable as a Set" - input list keys; - input Value v; - input HashTableCrefToSimVar ht; - output HashTableCrefToSimVar outHt; - algorithm - ht := matchcontinue(keys, v, ht) - local Key key; - case ({}, v, ht) then ht; - case(key::keys, v, ht) equation - ht = addNoUpdCheck((key, v), ht); - ht = addListNoUpd(keys, v, ht); - then ht; - end matchcontinue; - end addListNoUpd; - */ -public function addNoUpdCheck " - author: PA - - Add a Key-Value tuple to hashtable. - If the Key-Value tuple already exists, the function updates the Value. -" - input tuple entry; - input SimCode.HashTableCrefToSimVar hashTable; - output SimCode.HashTableCrefToSimVar outHashTable; -algorithm - outHashTable := matchcontinue (entry, hashTable) - local - Integer hval, indx, newpos, n, n_1, bsize, indx_1; - SimCode.ValueArray varr_1, varr; - list> indexes; - array>> hashvec_1, hashvec; - String name_str; - tuple v, newv; - SimCode.Key key; - SimCode.Value value; - - // adding when not existing previously - case ((v as (key, _)), SimCode.HASHTABLE(hashvec, varr, bsize, _)) - equation - indx = ComponentReference.hashComponentRefMod(key,bsize); - newpos = valueArrayLength(varr); - varr_1 = valueArrayAdd(varr, v); - indexes = hashvec[indx + 1]; - hashvec_1 = arrayUpdate(hashvec, indx + 1, ((key, newpos) :: indexes)); - n_1 = valueArrayLength(varr_1); - then SimCode.HASHTABLE(hashvec_1, varr_1, bsize, n_1); - - // failure - else - equation - print("- HashTableCrefToSimVar.addNoUpdCheck failed\n"); - then - fail(); - end matchcontinue; -end addNoUpdCheck; -/* - public function delete " - author: PA - - delete the Value associatied with Key from the HashTable. - Note: This function does not delete from the index table, only from the ValueArray. - This means that a lot of deletions will not make the HashTable more compact, it will still contain - a lot of incices information. - " - input Key key; - input HashTableCrefToSimVar hashTable; - output HashTableCrefToSimVar outHahsTable; - algorithm - outVariables:= - matchcontinue (key, hashTable) - local - Integer hval, indx, newpos, n, n_1, bsize, indx_1; - ValueArray varr_1, varr; - list> indexes; - array>> hashvec_1, hashvec; - String name_str; - tuple v, newv; - Value value; - // * adding when already present => Updating value * / - case (key, (hashTable as HASHTABLE(hashvec, varr, bsize, n))) - equation - (_, indx) = get1(key, hashTable); - indx_1 = indx - 1; - varr_1 = valueArrayClearnth(varr, indx); - then HASHTABLE(hashvec, varr_1, bsize, n); - case (_, hashTable) - equation - print("-HashTableCrefToSimVar.delete failed\n"); - print("content:"); dumpHashTable(hashTable); - then - fail(); - end matchcontinue; - end delete; - */ - -public function get " -author: PA - - Returns a Value given a Key and a HashTable. -" - input SimCode.Key key; - input SimCode.HashTableCrefToSimVar hashTable; - output SimCode.Value value; -algorithm - (value, _):= get1(key, hashTable); -end get; - -protected function get1 "help function to get" - input SimCode.Key key; - input SimCode.HashTableCrefToSimVar hashTable; - output SimCode.Value value; - output Integer indx; -algorithm - (value, indx):= - match (key, hashTable) - local - Integer bsize, n; - list> indexes; - SimCode.Value v; - array>> hashvec; - SimCode.ValueArray varr; - SimCode.Key k; - case (_, (SimCode.HASHTABLE(hashvec, varr, bsize, _))) - equation - indx = ComponentReference.hashComponentRefMod(key,bsize); - indexes = hashvec[indx + 1]; - indx = get2(key, indexes); - (k, v) = valueArrayNth(varr, indx); - true = keyEqual(k, key); - then - (v, indx); - end match; -end get1; - -protected function get2 " - author: PA - - Helper function to get -" - input SimCode.Key key; - input list> keyIndices; - output Integer index; -algorithm - index := - matchcontinue (key, keyIndices) - local - SimCode.Key key2; - list> xs; - case (_, ((key2, index) :: _)) - equation - true = keyEqual(key, key2); - then - index; - case (_, (_ :: xs)) - equation - index = get2(key, xs); - then - index; - end matchcontinue; -end get2; -/* - public function hashTableValueList "return the Value entries as a list of Values" - input HashTableCrefToSimVar hashTable; - output list valLst; - algorithm - valLst := List.map(hashTableList(hashTable), Util.tuple22); - end hashTableValueList; - - public function hashTableKeyList "return the Key entries as a list of Keys" - input HashTableCrefToSimVar hashTable; - output list valLst; - algorithm - valLst := List.map(hashTableList(hashTable), Util.tuple21); - end hashTableKeyList; - - public function hashTableList "returns the entries in the hashTable as a list of tuple" - input HashTableCrefToSimVar hashTable; - output list> tplLst; - algorithm - tplLst := matchcontinue(hashTable) - local ValueArray varr; - case(HASHTABLE(valueArr = varr)) equation - tplLst = valueArrayList(varr); - then tplLst; - end matchcontinue; - end hashTableList; - - public function valueArrayList " - author: PA - Transforms a ValueArray to a tuple list - " - input ValueArray valueArray; - output list> tplLst; - algorithm - tplLst := - matchcontinue (valueArray) - local - array>> arr; - tuple elt; - Integer lastpos, n, size; - list> lst; - case (VALUE_ARRAY(numberOfElements = 0, valueArray = arr)) then {}; - case (VALUE_ARRAY(numberOfElements = 1, valueArray = arr)) - equation - SOME(elt) = arr[0 + 1]; - then - {elt}; - case (VALUE_ARRAY(numberOfElements = n, arrSize = size, valueArray = arr)) - equation - lastpos = n - 1; - lst = valueArrayList2(arr, 0, lastpos); - then - lst; - end matchcontinue; - end valueArrayList; - - protected function valueArrayList2 "Helper function to valueArrayList" - input array>> inVarOptionArray1; - input Integer inInteger2; - input Integer inInteger3; - output list> outVarLst; - algorithm - outVarLst:= - matchcontinue (inVarOptionArray1, inInteger2, inInteger3) - local - tuple v; - array>> arr; - Integer pos, lastpos, pos_1; - list> res; - case (arr, pos, lastpos) - equation - (pos == lastpos) = true; - SOME(v) = arr[pos + 1]; - then - {v}; - case (arr, pos, lastpos) - equation - pos_1 = pos + 1; - SOME(v) = arr[pos + 1]; - res = valueArrayList2(arr, pos_1, lastpos); - then - (v :: res); - case (arr, pos, lastpos) - equation - pos_1 = pos + 1; - NONE = arr[pos + 1]; - res = valueArrayList2(arr, pos_1, lastpos); - then - (res); - end matchcontinue; - end valueArrayList2; - */ -public function valueArrayLength " - author: PA - - Returns the number of elements in the ValueArray -" - input SimCode.ValueArray valueArray; - output Integer size; -algorithm - size := match (valueArray) - case (SimCode.VALUE_ARRAY(numberOfElements = size)) then size; - end match; -end valueArrayLength; - -public function valueArrayAdd "author: PA - Adds an entry last to the ValueArray, increasing array size - if no space left by factor 1.4 -" - input SimCode.ValueArray valueArray; - input tuple entry; - output SimCode.ValueArray outValueArray; -algorithm - outValueArray:= - matchcontinue (valueArray, entry) - local - Integer n_1, n, size, expandsize, expandsize_1, newsize; - array>> arr_1, arr, arr_2; - Real rsize, rexpandsize; - case (SimCode.VALUE_ARRAY(numberOfElements = n, arrSize = size, valueArray = arr), _) - equation - (n < size) = true "Have space to add array elt."; - n_1 = n + 1; - arr_1 = arrayUpdate(arr, n + 1, SOME(entry)); - then - SimCode.VALUE_ARRAY(n_1, size, arr_1); - - case (SimCode.VALUE_ARRAY(numberOfElements = n, arrSize = size, valueArray = arr), _) - equation - (n < size) = false "Do NOT have splace to add array elt. Expand with factor 1.4"; - rsize = intReal(size); - rexpandsize = rsize * 0.4; - expandsize = realInt(rexpandsize); - expandsize_1 = intMax(expandsize, 1); - newsize = expandsize_1 + size; - arr_1 = Array.expand(expandsize_1, arr, NONE()); - n_1 = n + 1; - arr_2 = arrayUpdate(arr_1, n + 1, SOME(entry)); - then - SimCode.VALUE_ARRAY(n_1, newsize, arr_2); - case (_, _) - equation - print("-HashTableCrefToSimVar.valueArrayAdd failed\n"); - then - fail(); - end matchcontinue; -end valueArrayAdd; - -public function valueArraySetnth "author: PA - Set the n:th variable in the ValueArray to value. -" - input SimCode.ValueArray valueArray; - input Integer pos; - input tuple entry; - output SimCode.ValueArray outValueArray; -algorithm - outValueArray:= - matchcontinue (valueArray, pos, entry) - local - array>> arr_1, arr; - Integer n, size; - case (SimCode.VALUE_ARRAY(n, size, arr), _, _) - equation - (pos < size) = true; - arr_1 = arrayUpdate(arr, pos + 1, SOME(entry)); - then - SimCode.VALUE_ARRAY(n, size, arr_1); - case (_, _, _) - equation - print("-HashTableCrefToSimVar.valueArraySetnth failed\n"); - then - fail(); - end matchcontinue; -end valueArraySetnth; -/* - public function valueArrayClearnth " - author: PA - Clears the n:th variable in the ValueArray (set to NONE). - " - input ValueArray valueArray; - input Integer pos; - output ValueArray outValueArray; - algorithm - outValueArray:= - matchcontinue (valueArray, pos) - local - array>> arr_1, arr; - Integer n, size; - case (VALUE_ARRAY(n, size, arr), pos) - equation - (pos < size) = true; - arr_1 = arrayUpdate(arr, pos + 1, NONE); - then - VALUE_ARRAY(n, size, arr_1); - case (_, _) - equation - print("-HashTableCrefToSimVar.valueArrayClearnth failed\n"); - then - fail(); - end matchcontinue; - end valueArrayClearnth; - */ -public function valueArrayNth "author: PA - - Retrieve the n:th Vale from ValueArray, index from 0..n-1. - " - input SimCode.ValueArray valueArray; - input Integer pos; - output SimCode.Key key; - output SimCode.Value value; -algorithm - (key, value) := - matchcontinue (valueArray, pos) - local - SimCode.Key k; - SimCode.Value v; - Integer n; - array>> arr; - case (SimCode.VALUE_ARRAY(numberOfElements = n, valueArray = arr), _) - equation - (pos < n) = true; - SOME((k, v)) = arr[pos + 1]; - then - (k, v); - case (SimCode.VALUE_ARRAY(numberOfElements = n, valueArray = arr), _) - equation - (pos < n) = true; - NONE() = arr[pos + 1]; - then - fail(); - end matchcontinue; -end valueArrayNth; - - -/***** end of HashTable ComponentRef -> SimCodeVar.SimVar *******/ - public function functionInfo input SimCode.Function fn; output SourceInfo info; @@ -11121,27 +8245,6 @@ algorithm end match; end simEqSystemIndex; -function twodigit - input Integer i; - output String outS; -algorithm - outS := - matchcontinue (i) - local String s; - case _ - equation - (i < 10) = true; - s = intString(i); - s = stringAppend("0", s); - then - s; - else intString(i); - end matchcontinue; -end twodigit; - - - - /**************************************/ /************* for index ***************/ @@ -11591,20 +8694,6 @@ algorithm result := index1 > index2; end compareVarIndexGt; -public function varIndex - input SimCodeVar.SimVar var; - output Integer index; -algorithm - SimCodeVar.SIMVAR(index=index) := var; -end varIndex; - -public function varName - input SimCodeVar.SimVar var; - output DAE.ComponentRef name; -algorithm - SimCodeVar.SIMVAR(name=name) := var; -end varName; - public function countDynamicExternalFunctions input list inFncLst; output Integer outDynLoadFuncs; @@ -12750,16 +9839,6 @@ algorithm tpl := (eqs, i); end eqSystemWCET; -public function isParallelFunctionContext - input SimCode.Context context; - output Boolean outBool; -algorithm - outBool := match(context) - case (SimCode.PARALLEL_FUNCTION_CONTEXT()) then true; - else false; - end match; -end isParallelFunctionContext; - protected function getProtected input Option attr; output Boolean b; @@ -13204,64 +10283,6 @@ algorithm oMapping := arrayUpdate(iMapping,simVarIdx,SOME(simVar)); end createAllSCVarMapping1; - -protected function aliasRecordDeclarations - input SimCode.RecordDeclaration inDecl; - input HashTableStringToPath.HashTable inHt; - output SimCode.RecordDeclaration decl; - output HashTableStringToPath.HashTable ht; -algorithm - (decl,ht) := match (inDecl,inHt) - local - list vars; - Absyn.Path name; - String str,sname; - Option alias; - case (SimCode.RECORD_DECL_FULL(sname, _, name, vars),_) - equation - str = stringDelimitList(List.map(vars, variableString), "\n"); - (alias,ht) = aliasRecordDeclarations2(str, name, inHt); - then (SimCode.RECORD_DECL_FULL(sname, alias, name, vars),ht); - else (inDecl,inHt); - end match; -end aliasRecordDeclarations; - -protected function aliasRecordDeclarations2 - input String str; - input Absyn.Path path; - input HashTableStringToPath.HashTable inHt; - output Option alias; - output HashTableStringToPath.HashTable ht; -algorithm - (alias,ht) := matchcontinue (str,path,inHt) - local - String aliasStr; - case (_,_,_) - equation - aliasStr = Absyn.pathStringUnquoteReplaceDot(BaseHashTable.get(str, inHt),"_"); - then (SOME(aliasStr),inHt); - else - equation - ht = BaseHashTable.add((str,path),inHt); - then (NONE(),ht); - end matchcontinue; -end aliasRecordDeclarations2; - -protected function variableString - input SimCode.Variable var; - output String str; -algorithm - str := match var - local - DAE.ComponentRef name; - DAE.Type ty; - case SimCode.VARIABLE(name=name, ty=ty) - then Types.unparseType(ty) + " " + ComponentReference.printComponentRefStr(name); - case SimCode.FUNCTION_PTR(name=str) - then "modelica_fnptr " + str; - end match; -end variableString; - public function getEnumerationTypes input SimCodeVar.SimVars inVars; output list outVars; @@ -13378,24 +10399,6 @@ algorithm end match; end enumerationTypeExists; -protected function variableName - input SimCode.Variable v; - output String s; -algorithm - s := match v - case SimCode.VARIABLE(name=DAE.CREF_IDENT(ident=s)) then s; - case SimCode.FUNCTION_PTR(name=s) then s; - end match; -end variableName; - -protected function compareVariable - input SimCode.Variable v1; - input SimCode.Variable v2; - output Boolean b; -algorithm - b := stringCompare(variableName(v1),variableName(v2)) > 0; -end compareVariable; - public function equationIndexEqual input SimCode.SimEqSystem eq1; input SimCode.SimEqSystem eq2; @@ -13603,7 +10606,7 @@ algorithm vars = BackendVariable.equationSystemsVarsLst(eqs,{}); crefs = List.map(vars,BackendVariable.varCref); bVarIdcs = List.intRange(listLength(crefs)); - simVars = List.map1(crefs,get,ht); + simVars = List.map1(crefs,SimCodeFunctionUtil.get,ht); simVarIdcs = List.map2(simVars,getSimVarIndex,varInfo,allVars); varMapping = makeVarMapTuple(simVarIdcs,bVarIdcs,{}); List.fold1(simVars, fillSimVarMapping, simVarMapping, 1); @@ -14050,7 +11053,7 @@ algorithm case(SimCode.SES_LINEAR(SimCode.LINEARSYSTEM(vars=simVars,residual=residual))) equation crefs2 = List.flatten(List.map(residual,getSimEqSystemCrefsLHS)); - crefs = List.map(simVars,varName); + crefs = list(SimCodeFunctionUtil.varName(v) for v in simVars); crefs = listAppend(crefs,crefs2); then crefs; case(SimCode.SES_NONLINEAR(SimCode.NONLINEARSYSTEM(crefs=crefs))) @@ -14058,8 +11061,8 @@ algorithm then crefs; case(SimCode.SES_MIXED(discVars=simVars)) equation - crefs = List.map(simVars,varName); - then crefs; + crefs = list(SimCodeFunctionUtil.varName(v) for v in simVars); + then crefs; case(SimCode.SES_WHEN(left=cref)) equation then {cref}; @@ -15003,95 +12006,6 @@ algorithm end match; end getVariableIndex; -public function generateSubPalceholders - input DAE.ComponentRef cr; - output String outdef; -protected - list dims; - Integer nrdims; - list idxstrlst; -algorithm - dims := ComponentReference.crefDims(cr); - nrdims := listLength(dims); - idxstrlst := List.map(List.intRange(nrdims),intString); - outdef := stringDelimitList(List.threadMap(List.fill("i_", nrdims), idxstrlst, stringAppend), ","); -end generateSubPalceholders; - -public function execStat - "Prints an execution stat on the format: - *** %name% -> time: %time%, memory %memory% - Where you provide name, and time is the time since the last call using this - index (the clock is reset after each call). The memory is the total memory - consumed by the compiler at this point in time. - " - input String name; -algorithm - execStat2(Flags.isSet(Flags.EXEC_STAT),name); -end execStat; - -protected function execStat2 - input Boolean cond; - input String name; -algorithm - _ := match (cond,name) - local - Real t,total,used,allocated; - String timeStr,totalTimeStr,gcStr; - case (false,_) then (); - else - equation - t = System.realtimeTock(ClockIndexes.RT_CLOCK_EXECSTAT); - total = System.realtimeTock(ClockIndexes.RT_CLOCK_EXECSTAT_CUMULATIVE); - gcStr = GC.profStatsStr(GC.getProfStats(), head=""); - timeStr = System.snprintff("%.4g",20,t); - totalTimeStr = System.snprintff("%.4g",20,total); - if Flags.isSet(Flags.GC_PROF) then - Error.addMessage(Error.EXEC_STAT_GC,{name,timeStr,totalTimeStr,gcStr}); - else - Error.addMessage(Error.EXEC_STAT,{name,timeStr,totalTimeStr}); - end if; - System.realtimeTick(ClockIndexes.RT_CLOCK_EXECSTAT); - then (); - end match; -end execStat2; - -public - -function codegenResetTryThrowIndex -algorithm - setGlobalRoot(Global.codegenTryThrowIndex, {}); -end codegenResetTryThrowIndex; - -function codegenPushTryThrowIndex - input Integer i; -protected - list lst; -algorithm - lst := getGlobalRoot(Global.codegenTryThrowIndex); - setGlobalRoot(Global.codegenTryThrowIndex, i::lst); -end codegenPushTryThrowIndex; - -function codegenPopTryThrowIndex -protected - list lst; -algorithm - lst := getGlobalRoot(Global.codegenTryThrowIndex); - _::lst := lst; - setGlobalRoot(Global.codegenTryThrowIndex, lst); -end codegenPopTryThrowIndex; - -function codegenPeekTryThrowIndex - output Integer i; -protected - list lst; -algorithm - lst := getGlobalRoot(Global.codegenTryThrowIndex); - i := match lst - case i::_ then i; - else -1; - end match; -end codegenPeekTryThrowIndex; - protected function getHighestDerivation"computes the highest derivative among all states. this includes derivatives of derivatives as well author: waurich TUD 2015-05" input BackendDAE.BackendDAE inDAE; diff --git a/Compiler/Stubs/BackendDAECreate.mo b/Compiler/Stubs/BackendDAECreate.mo new file mode 100644 index 00000000000..ee0e5911796 --- /dev/null +++ b/Compiler/Stubs/BackendDAECreate.mo @@ -0,0 +1,16 @@ +encapsulated package BackendDAECreate + +import BackendDAE; + +function lower + input A a; + input B b; + input C c; + input D d; + output BackendDAE.BackendDAE outBackendDAE; +algorithm + assert(false, getInstanceName()); +end lower; + +annotation(__OpenModelica_Interface="backend"); +end BackendDAECreate; diff --git a/Compiler/Stubs/BackendDAEUtil.mo b/Compiler/Stubs/BackendDAEUtil.mo new file mode 100644 index 00000000000..80388db77bc --- /dev/null +++ b/Compiler/Stubs/BackendDAEUtil.mo @@ -0,0 +1,54 @@ +encapsulated package BackendDAEUtil + +import BackendDAE; + +function getSolvedSystem + input A inDAE; + input String fileNamePrefix; + input Option> strPreOptModules = NONE(); + input Option strmatchingAlgorithm = NONE(); + input Option strdaeHandler = NONE(); + input Option> strPostOptModules = NONE(); + output A outSODE; +algorithm + assert(false, getInstanceName()); +end getSolvedSystem; + +function preOptimizeBackendDAE + input T inDAE; + input Option> strPreOptModules; + output T outDAE; +algorithm + assert(false, getInstanceName()); +end preOptimizeBackendDAE; + +function transformBackendDAE + input A inDAE; + input Option inMatchingOptions; + input Option strmatchingAlgorithm; + input Option strindexReductionMethod; + output A outDAE; +algorithm + assert(false, getInstanceName()); +end transformBackendDAE; + +function getIncidenceMatrixfromOption + input BackendDAE.EqSystem inSyst; + input BackendDAE.IndexType inIndxType; + input Option inFunctionTree; + output BackendDAE.EqSystem outSyst; + output BackendDAE.IncidenceMatrix outM; + output BackendDAE.IncidenceMatrix outMT; +algorithm + assert(false, getInstanceName()); +end getIncidenceMatrixfromOption; + +function getAllVarLst + input BackendDAE.BackendDAE dae; + output list varLst; +algorithm + assert(false, getInstanceName()); +end getAllVarLst; + +annotation(__OpenModelica_Interface="backend"); +end BackendDAEUtil; diff --git a/Compiler/Stubs/CevalScriptBackend.mo b/Compiler/Stubs/CevalScriptBackend.mo new file mode 100644 index 00000000000..13b3205855b --- /dev/null +++ b/Compiler/Stubs/CevalScriptBackend.mo @@ -0,0 +1,64 @@ +encapsulated package CevalScriptBackend + +import Absyn; +import DAE; +import FCore; +import GlobalScript; +import Values; + +function runFrontEnd + input FCore.Cache inCache; + input FCore.Graph inEnv; + input Absyn.Path className; + input GlobalScript.SymbolTable inInteractiveSymbolTable; + input Boolean relaxedFrontEnd "Do not check for illegal simulation models, so we allow instantation of packages, etc"; + output FCore.Cache cache; + output FCore.Graph env; + output DAE.DAElist dae; + output GlobalScript.SymbolTable st; +algorithm + assert(false, getInstanceName()); +end runFrontEnd; + +function getSimulationResultType + output DAE.Type t; +algorithm + assert(false, getInstanceName()); +end getSimulationResultType; + +function getDrModelicaSimulationResultType = getSimulationResultType; + +function buildSimulationOptionsFromModelExperimentAnnotation + input GlobalScript.SymbolTable inSymTab; + input Absyn.Path inModelPath; + input String inFileNamePrefix; + input Option defaultOption; + output GlobalScript.SimulationOptions outSimOpt; +algorithm + assert(false, getInstanceName()); +end buildSimulationOptionsFromModelExperimentAnnotation; + +function getSimulationOption + input GlobalScript.SimulationOptions inSimOpt; + input String optionName; + output DAE.Exp outOptionValue; +algorithm + assert(false, getInstanceName()); +end getSimulationOption; + +function cevalInteractiveFunctions3 + input FCore.Cache inCache; + input FCore.Graph inEnv; + input String inFunctionName; + input list inVals; + input GlobalScript.SymbolTable inSt; + input Absyn.Msg msg; + output FCore.Cache outCache = inCache; + output Values.Value outValue = Values.INTEGER(0); + output GlobalScript.SymbolTable outInteractiveSymbolTable = inSt; +algorithm + assert(false, getInstanceName() + ": " + inFunctionName); +end cevalInteractiveFunctions3; + +annotation(__OpenModelica_Interface="backend"); +end CevalScriptBackend; diff --git a/Compiler/Stubs/DumpGraphviz.mo b/Compiler/Stubs/DumpGraphviz.mo new file mode 100644 index 00000000000..21f0f7e607a --- /dev/null +++ b/Compiler/Stubs/DumpGraphviz.mo @@ -0,0 +1,10 @@ +encapsulated package DumpGraphviz + +function dump + input T p; +algorithm + assert(false, getInstanceName()); +end dump; + +annotation(__OpenModelica_Interface="backend"); +end DumpGraphviz; diff --git a/Compiler/Stubs/FGraphStream.mo b/Compiler/Stubs/FGraphStream.mo new file mode 100644 index 00000000000..7516b79196d --- /dev/null +++ b/Compiler/Stubs/FGraphStream.mo @@ -0,0 +1,19 @@ +encapsulated package FGraphStream + +function start +end start; + +function finish = start; + +function edge + input A name; + input B source; + input B target; +end edge; + +function node + input N n; +end node; + +annotation(__OpenModelica_Interface="frontend"); +end FGraphStream; diff --git a/Compiler/Stubs/NFInstDump.mo b/Compiler/Stubs/NFInstDump.mo new file mode 100644 index 00000000000..266f62f11c3 --- /dev/null +++ b/Compiler/Stubs/NFInstDump.mo @@ -0,0 +1,11 @@ +encapsulated package NFInstDump + +function prefixStr + input T inPrefix; + output String outString; +algorithm + assert(false, getInstanceName()); +end prefixStr; + +annotation(__OpenModelica_Interface="frontend"); +end NFInstDump; diff --git a/Compiler/Stubs/Refactor.mo b/Compiler/Stubs/Refactor.mo new file mode 100644 index 00000000000..380878089d3 --- /dev/null +++ b/Compiler/Stubs/Refactor.mo @@ -0,0 +1,12 @@ +encapsulated package Refactor + +function refactorGraphicalAnnotation + input A wholeAST; + input B classToRefactor; + output B changedClass; +algorithm + assert(false, getInstanceName()); +end refactorGraphicalAnnotation; + +annotation(__OpenModelica_Interface="backend"); +end Refactor; diff --git a/Compiler/Stubs/RewriteRules.mo b/Compiler/Stubs/RewriteRules.mo new file mode 100644 index 00000000000..bd741d9040d --- /dev/null +++ b/Compiler/Stubs/RewriteRules.mo @@ -0,0 +1,28 @@ +encapsulated package RewriteRules + +function rewriteFrontEnd + input A inExp; + output A outExp = inExp; + output Boolean isChanged = false; +end rewriteFrontEnd; + +function noRewriteRulesFrontEnd + output Boolean noRules = true; +end noRewriteRulesFrontEnd; + +function noRewriteRulesBackEnd + output Boolean noRules = true; +end noRewriteRulesBackEnd; + +function loadRules +algorithm + assert(false, getInstanceName()); +end loadRules; + +function clearRules +algorithm + assert(false, getInstanceName()); +end clearRules; + +annotation(__OpenModelica_Interface="frontend"); +end RewriteRules; diff --git a/Compiler/Stubs/SimCodeMain.mo b/Compiler/Stubs/SimCodeMain.mo new file mode 100644 index 00000000000..c55ec62bed9 --- /dev/null +++ b/Compiler/Stubs/SimCodeMain.mo @@ -0,0 +1,99 @@ +encapsulated package SimCodeMain + +import BackendDAE; +import SimCode; +import Values; + +function createSimulationSettings + input Real startTime; + input Real stopTime; + input Integer inumberOfIntervals; + input Real tolerance; + input String method; + input String options; + input String outputFormat; + input String variableFilter; + input String cflags; + output SimCode.SimulationSettings simSettings; +algorithm + assert(false, getInstanceName()); +end createSimulationSettings; + +function generateModelCode + input T inBackendDAE; + input A p; + input B dae; + input C className; + input String filenamePrefix; + input D simSettingsOpt; + input E args; + output T outIndexedBackendDAE; + output list libs; + output String fileDir; + output Real timeSimCode; + output Real timeTemplates; +algorithm + assert(false, getInstanceName()); +end generateModelCode; + +function translateModelXML + input A inCache; + input B inEnv; + input C className; + input D inInteractiveSymbolTable; + input String inFileNamePrefix; + input Boolean addDummy; + input Option inSimSettingsOpt; + output A outCache; + output Values.Value outValue; + output D outInteractiveSymbolTable; + output BackendDAE.BackendDAE outBackendDAE; + output list outStringLst; + output String outFileDir; + output list> resultValues; +algorithm + assert(false, getInstanceName()); +end translateModelXML; + +function translateModel + input A inCache; + input B inEnv; + input C className; + input D inInteractiveSymbolTable; + input String inFileNamePrefix; + input Boolean addDummy; + input Option inSimSettingsOpt; + input F args; + output A outCache; + output D outInteractiveSymbolTable; + output BackendDAE.BackendDAE outBackendDAE; + output list outStringLst; + output String outFileDir; + output list> resultValues; +algorithm + assert(false, getInstanceName()); +end translateModel; + +function translateModelFMU + input A inCache; + input B inEnv; + input C className; + input D inInteractiveSymbolTable; + input String inFMUVersion; + input String inFMUType; + input String inFileNamePrefix; + input Boolean addDummy; + input Option inSimSettingsOpt; + output A outCache; + output Values.Value outValue; + output D outInteractiveSymbolTable; + output BackendDAE.BackendDAE outBackendDAE; + output list outStringLst; + output String outFileDir; + output list> resultValues; +algorithm + assert(false, getInstanceName()); +end translateModelFMU; + +annotation(__OpenModelica_Interface="backend"); +end SimCodeMain; diff --git a/Compiler/Stubs/SimCodeUtil.mo b/Compiler/Stubs/SimCodeUtil.mo new file mode 100644 index 00000000000..80272578d5d --- /dev/null +++ b/Compiler/Stubs/SimCodeUtil.mo @@ -0,0 +1,18 @@ +encapsulated package SimCodeUtil + +function sortEqSystems + input T eqs; + output T outEqs; +algorithm + assert(false, getInstanceName()); +end sortEqSystems; + +public function eqInfo + input T eq; + output SourceInfo info; +algorithm + assert(false, getInstanceName()); +end eqInfo; + +annotation(__OpenModelica_Interface="backend"); +end SimCodeUtil; diff --git a/Compiler/Stubs/UnitAbsynBuilder.mo b/Compiler/Stubs/UnitAbsynBuilder.mo new file mode 100644 index 00000000000..530cbbf9aa4 --- /dev/null +++ b/Compiler/Stubs/UnitAbsynBuilder.mo @@ -0,0 +1,43 @@ +encapsulated package UnitAbsynBuilder + +import UnitAbsyn; + +function emptyInstStore + output UnitAbsyn.InstStore st = UnitAbsyn.noStore; +end emptyInstStore; + +function instBuildUnitTerms + input A env; + input B dae; + input B compDae; + input UnitAbsyn.InstStore store; + output UnitAbsyn.InstStore outStore; + output UnitAbsyn.UnitTerms terms; +algorithm + assert(false, getInstanceName()); +end instBuildUnitTerms; + +function registerUnitWeights + input A cache; + input B env; + input C dae; +algorithm + assert(false, getInstanceName()); +end registerUnitWeights; + +function instAddStore + input UnitAbsyn.InstStore istore; + input A itp; + input B cr; + output UnitAbsyn.InstStore outStore = istore; +end instAddStore; + +function unit2str + input A unit; + output String res; +algorithm + assert(false, getInstanceName()); +end unit2str; + +annotation(__OpenModelica_Interface="frontend"); +end UnitAbsynBuilder; diff --git a/Compiler/Stubs/UnitChecker.mo b/Compiler/Stubs/UnitChecker.mo new file mode 100644 index 00000000000..20673a6f89a --- /dev/null +++ b/Compiler/Stubs/UnitChecker.mo @@ -0,0 +1,20 @@ +encapsulated package UnitChecker + +function check + input A tms; + input B ist; + output B outSt; +algorithm + assert(false, getInstanceName()); +end check; + +function isComplete + input A st; + output Boolean complete; + output A stout; +algorithm + assert(false, getInstanceName()); +end isComplete; + +annotation(__OpenModelica_Interface="frontend"); +end UnitChecker; diff --git a/Compiler/Template/CodegenC.tpl b/Compiler/Template/CodegenC.tpl index ee0cf607b81..114c5965be8 100644 --- a/Compiler/Template/CodegenC.tpl +++ b/Compiler/Template/CodegenC.tpl @@ -46,8 +46,9 @@ package CodegenC import interface SimCodeTV; +import interface SimCodeBackendTV; import CodegenUtil.*; - +import CodegenCFunctions.*; /* public */ template translateModel(SimCode simCode, String guid) "Generates C code and Makefile for compiling and running a simulation of a @@ -95,28 +96,6 @@ end translateModel; "" end translateInitFile; -/* public */ template translateFunctions(FunctionCode functionCode) - "Generates C code and Makefile for compiling and calling Modelica and - MetaModelica functions. - used in Compiler/SimCode/SimCodeMain.mo" -::= - match functionCode - case fc as FUNCTIONCODE(__) then - let()= System.tmpTickResetIndex(0,2) /* auxFunction index */ - let &staticPrototypes = buffer "" - let filePrefix = name - let _= (if mainFunction then textFile(functionsMakefile(functionCode), '<%filePrefix%>.makefile')) - let()= textFile(functionsHeaderFile(filePrefix, mainFunction, functions, extraRecordDecls, staticPrototypes), '<%filePrefix%>.h') - let()= textFileConvertLines(functionsFile(filePrefix, mainFunction, functions, literals, staticPrototypes), '<%filePrefix%>.c') - let()= textFile(externalFunctionIncludes(fc.externalFunctionIncludes), '<%filePrefix%>_includes.h') - let()= textFile(recordsFile(filePrefix, extraRecordDecls), '<%filePrefix%>_records.c') - // If ParModelica generate the kernels file too. - if acceptParModelicaGrammar() then - let()= textFile(functionsParModelicaKernelsFile(filePrefix, mainFunction, functions), '<%filePrefix%>_kernels.cl') - "" // Return empty result since result written to files directly - end match -end translateFunctions; - /* public */ template simulationHeaderFile(SimCode simCode, String guid) "Generates code for main C file for simulation target. used in Compiler/Template/CodegenFMU.tpl" @@ -735,29 +714,6 @@ template simulationFile(SimCode simCode, String guid) end match end simulationFile; -template mainTop(Text mainBody, String url) -::= - << - { - MMC_TRY_TOP() - - MMC_TRY_STACK() - - <%mainBody%> - - MMC_ELSE() - rml_execution_failed(); - fprintf(stderr, "Stack overflow detected and was not caught.\nSend us a bug report at <%url%>\n Include the following trace:\n"); - printStacktraceMessages(); - fflush(NULL); - return 1; - MMC_CATCH_STACK() - - MMC_CATCH_TOP(return rml_execution_failed()); - } - >> -end mainTop; - template simulationFileHeader(SimCode simCode) "Generates header part of simulation file." ::= @@ -1095,7 +1051,7 @@ template crefMacroSubsAtEndParNew(ComponentRef cr) let nosubfullpath = contextCref(crefStripSubs(cr),contextSimulationNonDiscrete, &auxFunction) let totnrdims = listLength(crefDims(cr)) let dimstr = crefDims(cr) |> dim => dimension(dim) ;separator=", " - let substr = SimCodeUtil.generateSubPalceholders(cr) + let substr = generateSubPalceholders(cr) let &subsDimThread = buffer "" /*BUFD*/ << #define <%nosubfullpath%>_index(<%substr%>) (&<%fullpath%>)[calc_base_index_dims_subs(<%totnrdims%>, <%dimstr%>, <%substr%>)] @@ -1109,7 +1065,7 @@ template crefMacroSubsAtEndVarNew(ComponentRef cr) let nosubfullpath = contextCref(crefStripSubs(cr),contextSimulationNonDiscrete, &auxFunction) let totnrdims = listLength(crefDims(cr)) let dimstr = crefDims(cr) |> dim => dimension(dim) ;separator=", " - let substr = SimCodeUtil.generateSubPalceholders(cr) + let substr = generateSubPalceholders(cr) let &subsDimThread = buffer "" /*BUFD*/ << #define <%nosubfullpath%>_index(<%substr%>) (&<%fullpath%>)[calc_base_index_dims_subs(<%totnrdims%>, <%dimstr%>, <%substr%>)] @@ -2640,7 +2596,7 @@ end functionWhenReinitStatementThen; // Begin: Modified functions for HpcOm //------------------------------------ -template functionXXX_systems_HPCOM(list> eqs, String name, Text &loop, Text &varDecls, Option> hpcOmSchedulesOpt, String modelNamePrefixStr) +template functionXXX_systems_HPCOM(list> eqs, String name, Text &loop, Text &varDecls, Option> hpcOmSchedulesOpt, String modelNamePrefixStr) ::= let funcs = (eqs |> eq hasindex i0 fromindex 0 => functionXXX_system_HPCOM(eq,name,i0,hpcOmSchedulesOpt, modelNamePrefixStr) ; separator="\n") match listLength(eqs) @@ -2687,11 +2643,11 @@ template functionXXX_systems_HPCOM(list> eqs, String name, Tex >> end functionXXX_systems_HPCOM; -template functionXXX_system_HPCOM(list derivativEquations, String name, Integer n, Option> hpcOmSchedulesOpt, String modelNamePrefixStr) +template functionXXX_system_HPCOM(list derivativEquations, String name, Integer n, Option> hpcOmSchedulesOpt, String modelNamePrefixStr) ::= let type = getConfigString(HPCOM_CODE) match hpcOmSchedulesOpt - case SOME((hpcOmSchedule as EMPTYSCHEDULE(__),_)) then + case SOME((hpcOmSchedule as EMPTYSCHEDULE(__),_,_)) then << void terminateHpcOmThreads() { @@ -2699,7 +2655,7 @@ template functionXXX_system_HPCOM(list derivativEquations, String n <%functionXXX_system(derivativEquations,name,n,modelNamePrefixStr)%> >> - case SOME((hpcOmSchedule as TASKDEPSCHEDULE(__),_)) then + case SOME((hpcOmSchedule as TASKDEPSCHEDULE(__),_,_)) then let taskEqs = functionXXX_system0_HPCOM_TaskDep(hpcOmSchedule.tasks, derivativEquations, type, name, modelNamePrefixStr); separator="\n" << void terminateHpcOmThreads() @@ -2712,7 +2668,7 @@ template functionXXX_system_HPCOM(list derivativEquations, String n <%taskEqs%> } >> - case SOME((hpcOmSchedule as LEVELSCHEDULE(__),_)) then + case SOME((hpcOmSchedule as LEVELSCHEDULE(__),_,_)) then let odeEqs = hpcOmSchedule.tasksOfLevels |> tasks => functionXXX_system0_HPCOM_Level(derivativEquations,name,tasks,type,modelNamePrefixStr); separator="\n" << void terminateHpcOmThreads() @@ -2729,7 +2685,7 @@ template functionXXX_system_HPCOM(list derivativEquations, String n } } >> - case SOME((hpcOmSchedule as THREADSCHEDULE(__),_)) then + case SOME((hpcOmSchedule as THREADSCHEDULE(__),_,_)) then let locks = hpcOmSchedule.outgoingDepTasks |> task => function_HPCOM_createLockByDepTask(task, "lock", type); separator="\n" let initlocks = hpcOmSchedule.outgoingDepTasks |> task => function_HPCOM_initializeLockByDepTask(task, "lock", type); separator="\n" let assignLocks = hpcOmSchedule.outgoingDepTasks |> task => function_HPCOM_assignLockByDepTask(task, "lock", type); separator="\n" @@ -3338,7 +3294,7 @@ match eqlstlst error(sourceInfo(), 'TODO more than ODE list in <%name%> systems') end functionXXX_systems_arrayFormat; -template functionODE(list> derivativEquations, Text method, Option> hpcOmSchedules, String modelNamePrefix) +template functionODE(list> derivativEquations, Text method, Option> hpcOmSchedules, String modelNamePrefix) "Generates function in simulation file." ::= let () = System.tmpTickReset(0) @@ -4695,52 +4651,6 @@ template simulationParModelicaKernelsFile(String filePrefix, list func end simulationParModelicaKernelsFile; -template functionsParModelicaKernelsFile(String filePrefix, Option mainFunction, list functions) - "Generates the content of the C file for functions in the simulation case." -::= - - /* Reset the parfor loop id counter to 0*/ - let()= System.tmpTickResetIndex(0,20) /* parfor index */ - - << - #include - - // ParModelica Parallel Function headers. - <%functionHeadersParModelica(filePrefix, functions)%> - - // Headers finish here. - - <%match mainFunction case SOME(fn) then functionBodyParModelica(fn,true)%> - <%functionBodiesParModelica(functions)%> - - - >> - -end functionsParModelicaKernelsFile; - -/* public */ template recordsFile(String filePrefix, list recordDecls) - "Generates the content of the C file for functions in the simulation case. - used in Compiler/Template/CodegenFMU.tpl" -::= - << - /* Additional record code for <%filePrefix%> generated by the OpenModelica Compiler <%getVersionNr()%>. */ - - #include "meta/meta_modelica.h" - - #ifdef __cplusplus - extern "C" { - #endif - - <%recordDecls |> rd => recordDeclaration(rd) ;separator="\n\n"%> - - #ifdef __cplusplus - } - #endif - - >> - /* adpro: leave a newline at the end of file to get rid of warnings! */ -end recordsFile; - /* public */ template simulationFunctionsHeaderFile(String filePrefix, list functions, list recordDecls) "Generates the content of the C file for functions in the simulation case. used in Compiler/Template/CodegenFMU.tpl" @@ -4778,23 +4688,6 @@ end recordsFile; /* adrpo: leave a newline at the end of file to get rid of the warning */ end simulationFunctionsHeaderFile; -template functionHeadersParModelica(String filePrefix, list functions) - "Generates the content of the C file for functions in the simulation case." -::= - << - #ifndef <%stringReplace(filePrefix,".","_")%>__H - #define <%stringReplace(filePrefix,".","_")%>__H - //#include "helper.cl" - - <%parallelFunctionHeadersImpl(functions)%> - - #endif - - <%\n%> - >> - /* adrpo: leave a newline at the end of file to get rid of the warning */ -end functionHeadersParModelica; - template simulationMakefile(String target, SimCode simCode) "Generates the contents of the makefile for the simulation case." ::= @@ -5002,234 +4895,6 @@ case SIMCODE(modelInfo = MODELINFO(functions = functions, varInfo = vi as VARINF >> end simulationInitFile; -// lochel: this is apparently not used -// template initVals(list varsLst) ::= -// varsLst |> SIMVAR(__) => -// << -// <%match initialValue -// case SOME(v) then initVal(v) -// else "0.0 //default" -// %> //<%crefStr(name)%> -// >> -// ;separator="\n" -// end initVals; -// -// template initVal(Exp initialValue) -// ::= -// match initialValue -// case ICONST(__) then integer -// case RCONST(__) then real -// case SCONST(__) then '<%Util.escapeModelicaStringToCString(string)%>' -// case BCONST(__) then if bool then "true" else "false" -// case ENUM_LITERAL(__) then '<%index%> /*ENUM:<%dotPath(name)%>*/' -// else error(sourceInfo(), 'initial value of unknown type: <%printExpStr(initialValue)%>') -// end initVal; - -template commonHeader(String filePrefix) -::= - << - #include "meta/meta_modelica.h" - #include "util/modelica.h" - #include - #include - #include - <%if acceptParModelicaGrammar() then - << - #include - /* the OpenCL Kernels file name needed in libOMOCLRuntime.a */ - const char* omc_ocl_kernels_source = "<%filePrefix%>_kernels.cl"; - /* the OpenCL program. Made global to avoid repeated builds */ - extern cl_program omc_ocl_program; - /* The default OpenCL device. If not set (=0) show the selection option.*/ - unsigned int default_ocl_device = <%getDefaultOpenCLDevice()%>; - >> - %> - - >> -end commonHeader; - -template functionsFile(String filePrefix, - Option mainFunction, - list functions, - list literals, - Text &staticPrototypes) - "Generates the contents of the main C file for the function case." -::= - let &preLit = buffer "" - let literalsRes = literals |> literal hasindex i0 fromindex 0 => literalExpConst(literal,i0,&preLit) ; separator="\n";empty - << - #include "<%filePrefix%>.h" - <% preLit %> - <% /* Note: The literals may not be part of the header due to separate compilation */ - literalsRes - %> - #include "util/modelica.h" - - #include "<%filePrefix%>_includes.h" - - <%if staticPrototypes then - << - /* default, do not make protected functions static */ - #if !defined(PROTECTED_FUNCTION_STATIC) - #define PROTECTED_FUNCTION_STATIC - #endif - <%staticPrototypes%> - >> - %> - - <% if mainFunction then - << - void (*omc_assert)(threadData_t*,FILE_INFO info,const char *msg,...) __attribute__((noreturn)) = omc_assert_function; - void (*omc_assert_warning)(FILE_INFO info,const char *msg,...) = omc_assert_warning_function; - void (*omc_terminate)(FILE_INFO info,const char *msg,...) = omc_terminate_function; - void (*omc_throw)(threadData_t*) __attribute__ ((noreturn)) = omc_throw_function; - >> %> - - <%match mainFunction case SOME(fn) then functionBody(fn,true,false)%> - <%functionBodies(functions,false)%> - <%\n%> - >> -end functionsFile; - -template functionsHeaderFile(String filePrefix, - Option mainFunction, - list functions, - list extraRecordDecls, - Text &staticPrototypes) - "Generates the contents of the main C file for the function case." -::= - << - #ifndef <%stringReplace(filePrefix,".","_")%>__H - #define <%stringReplace(filePrefix,".","_")%>__H - <%commonHeader(filePrefix)%> - #ifdef __cplusplus - extern "C" { - #endif - - <%extraRecordDecls |> rd => recordDeclarationHeader(rd) ;separator="\n"%> - - <%match mainFunction case SOME(fn) then functionHeader(fn,true,false,staticPrototypes)%> - - <%functionHeaders(functions, false, staticPrototypes)%> - - #ifdef __cplusplus - } - #endif - #endif<%\n%> - >> - /* adrpo: leave a newline at the end of file to get rid of the warning */ -end functionsHeaderFile; - -template functionsMakefile(FunctionCode fnCode) - "Generates the contents of the makefile for the function case." -::= -match fnCode -case FUNCTIONCODE(makefileParams=MAKEFILE_PARAMS(__)) then - let libsStr = (makefileParams.libs ;separator=" ") - let ParModelicaExpLibs = if acceptParModelicaGrammar() then '-lOMOCLRuntime -lOpenCL' // else "" - - << - # Makefile generated by OpenModelica - - # Dynamic loading uses -O0 by default - SIM_OR_DYNLOAD_OPT_LEVEL=-O0 - CC=<%if acceptParModelicaGrammar() then 'g++' else '<%makefileParams.ccompiler%>'%> - CXX=<%makefileParams.cxxcompiler%> - LINK=<%makefileParams.linker%> - EXEEXT=<%makefileParams.exeext%> - DLLEXT=<%makefileParams.dllext%> - DEBUG_FLAGS=<% if boolOr(acceptMetaModelicaGrammar(), Flags.isSet(Flags.GEN_DEBUG_SYMBOLS)) then " -g"%> - CFLAGS= -I"<%makefileParams.omhome%>/include/omc/c" <%makefileParams.includes ; separator=" "%> $(DEBUG_FLAGS) <%makefileParams.cflags%> - LDFLAGS= -L"<%makefileParams.omhome%>/lib/<%getTriple()%>/omc" -Wl,-rpath,'<%makefileParams.omhome%>/lib/<%getTriple()%>/omc' <%ParModelicaExpLibs%> <%makefileParams.ldflags%> <%makefileParams.runtimelibs%> - PERL=perl - MAINFILE=<%name%>.c - - .PHONY: <%name%> - <%name%>: $(MAINFILE) <%name%>.h <%name%>_records.c - <%\t%> $(CC) $(CFLAGS) -c -o <%name%>.o $(MAINFILE) - <%\t%> $(CC) $(CFLAGS) -c -o <%name%>_records.o <%name%>_records.c - <%\t%> $(LINK) -o <%name%>$(DLLEXT) <%name%>.o <%name%>_records.o <%libsStr%> $(CFLAGS) $(LDFLAGS) -lm - >> -end functionsMakefile; - -template contextCref(ComponentRef cr, Context context, Text &auxFunction) - "Generates code for a component reference depending on which context we're in." -::= - match context - case FUNCTION_CONTEXT(__) - case PARALLEL_FUNCTION_CONTEXT(__) then - (match cr - case CREF_QUAL(identType = T_ARRAY(ty = T_COMPLEX(complexClassType = record_state))) then - let &preExp = buffer "" - let &varDecls = buffer "" - let rec_name = '<%underscorePath(ClassInf.getStateName(record_state))%>' - let recPtr = tempDecl(rec_name + "*", &varDecls) - let dimsLenStr = listLength(crefSubs(cr)) - let dimsValuesStr = (crefSubs(cr) |> INDEX(__) => daeDimensionExp(exp, context, &preExp, &varDecls, &auxFunction) ; separator=", ") - << - ((<%rec_name%>*)(generic_array_element_addr(&_<%ident%>, sizeof(<%rec_name%>), <%dimsLenStr%>, <%dimsValuesStr%>)))-><%contextCref(componentRef, context, &auxFunction)%> - >> - else "_" + System.unquoteIdentifier(crefStr(cr)) - ) - else cref(cr) -end contextCref; - -template contextIteratorName(Ident name, Context context) - "Generates code for an iterator variable." -::= - match context - case FUNCTION_CONTEXT(__) then "_" + name - case PARALLEL_FUNCTION_CONTEXT(__) then "_" + name - else "$P" + name -end contextIteratorName; - -/* public */ template cref(ComponentRef cr) - "Generates C equivalent name for component reference. - used in Compiler/Template/CodegenFMU.tpl" -::= - match cr - case CREF_IDENT(ident = "xloc") then crefStr(cr) - case CREF_IDENT(ident = "time") then "time" - case WILD(__) then '' - else "$P" + crefToCStr(cr) -end cref; - -template crefToCStr(ComponentRef cr) - "Helper function to cref." -::= - match cr - case CREF_IDENT(__) then '<%unquoteIdentifier(ident)%><%subscriptsToCStr(subscriptLst)%>' - case CREF_QUAL(__) then '<%unquoteIdentifier(ident)%><%subscriptsToCStr(subscriptLst)%>$P<%crefToCStr(componentRef)%>' - case WILD(__) then '' - else "CREF_NOT_IDENT_OR_QUAL" -end crefToCStr; - -template subscriptsToCStr(list subscripts) -::= - if subscripts then - '$lB<%subscripts |> s => subscriptToCStr(s) ;separator="$c"%>$rB' -end subscriptsToCStr; - -template subscriptToCStr(Subscript subscript) -::= - match subscript - case SLICE(exp=ICONST(integer=i)) then i - case SLICE(__) then error(sourceInfo(), "Unknown slice " + printExpStr(exp)) - case WHOLEDIM(__) then "WHOLEDIM" - case INDEX(__) then - match exp - case ICONST(integer=i) then i - case ENUM_LITERAL(index=i) then i - case _ then - let &varDecls = buffer "" - let &preExp = buffer "" - let &auxFunction = buffer "" - let index = daeExp(exp, contextOther, &preExp, &varDecls, &auxFunction) - '<%index%>' - end match - else error(sourceInfo(), "UNKNOWN_SUBSCRIPT") -end subscriptToCStr; - template crefM(ComponentRef cr) "Generates Modelica equivalent name for component reference." ::= @@ -5239,6122 +4904,78 @@ template crefM(ComponentRef cr) else "P" + crefToMStr(cr) end crefM; -template crefToMStr(ComponentRef cr) - "Helper function to crefM." -::= - match cr - case CREF_IDENT(__) then '<%unquoteIdentifier(ident)%><%subscriptsToMStr(subscriptLst)%>' - case CREF_QUAL(__) then '<%unquoteIdentifier(ident)%><%subscriptsToMStr(subscriptLst)%>P<%crefToMStr(componentRef)%>' - else "CREF_NOT_IDENT_OR_QUAL" -end crefToMStr; - -template subscriptsToMStr(list subscripts) -::= - if subscripts then - 'lB<%subscripts |> s => subscriptToMStr(s) ;separator="c"%>rB' -end subscriptsToMStr; - -template subscriptToMStr(Subscript subscript) -::= - match subscript - case SLICE(exp=ICONST(integer=i)) then i - case SLICE(__) then error(sourceInfo(), "Unknown slice " + printExpStr(exp)) - case WHOLEDIM(__) then "WHOLEDIM" - case INDEX(__) then - match exp - case ICONST(integer=i) then i - case ENUM_LITERAL(index=i) then i - else - let &varDecls = buffer "" - let &preExp = buffer "" - let &auxFunction = buffer "" - daeExp(exp, contextOther, &preExp, &varDecls, &auxFunction) - end match - else error(sourceInfo(), "UNKNOWN_SUBSCRIPT") -end subscriptToMStr; - -template contextArrayCref(ComponentRef cr, Context context) - "Generates code for an array component reference depending on the context." -::= - match context - case FUNCTION_CONTEXT(__) then "_" + arrayCrefStr(cr) - case PARALLEL_FUNCTION_CONTEXT(__) then "_" + arrayCrefStr(cr) - else arrayCrefCStr(cr) -end contextArrayCref; - -template arrayCrefCStr(ComponentRef cr) -::= '$P<%arrayCrefCStr2(cr)%>' -end arrayCrefCStr; - -template arrayCrefCStr2(ComponentRef cr) -::= - match cr - case CREF_IDENT(__) then '<%unquoteIdentifier(ident)%>' - case CREF_QUAL(__) then '<%unquoteIdentifier(ident)%><%subscriptsToCStr(subscriptLst)%>$P<%arrayCrefCStr2(componentRef)%>' - else "CREF_NOT_IDENT_OR_QUAL" -end arrayCrefCStr2; - -template arrayCrefStr(ComponentRef cr) -::= - match cr - case CREF_IDENT(__) then '<%ident%>' - case CREF_QUAL(__) then '<%ident%>._<%arrayCrefStr(componentRef)%>' - else "CREF_NOT_IDENT_OR_QUAL" -end arrayCrefStr; - -template crefFunctionName(ComponentRef cr) -::= - match cr - case CREF_IDENT(__) then - System.stringReplace(unquoteIdentifier(ident), "_", "__") - case CREF_QUAL(__) then - '<%System.stringReplace(unquoteIdentifier(ident), "_", "__")%>_<%crefFunctionName(componentRef)%>' -end crefFunctionName; - -/* public */ template externalFunctionIncludes(list includes) - "Generates external includes part in function files. - used in Compiler/Template/CodegenFMU.tpl" -::= - if includes then - << - #ifdef __cplusplus - extern "C" { - #endif - <% (includes ;separator="\n") %> - #ifdef __cplusplus - } - #endif<%\n%> - >> -end externalFunctionIncludes; - - -template functionHeaders(list functions, Boolean isSimulation, Text &staticPrototypes) - "Generates function header part in function files." -::= - (functions |> fn => functionHeader(fn, false, isSimulation, staticPrototypes) ; separator="\n\n") -end functionHeaders; - -template parallelFunctionHeadersImpl(list functions) - "Generates function header part in function files." -::= - (functions |> fn => parallelFunctionHeader(fn, false) ; separator="\n\n") -end parallelFunctionHeadersImpl; - -template functionHeader(Function fn, Boolean inFunc, Boolean isSimulation, Text &staticPrototypes) - "Generates function header part in function files." +template equationInfo1(SimEqSystem eq, Text &preBuf, Text &eqnsDefines, Text &reverseProf) ::= - match fn - case FUNCTION(__) then - << - <%functionHeaderNormal(underscorePath(name), functionArguments, outVars, inFunc, visibility, false, isSimulation, staticPrototypes)%> - <%functionHeaderBoxed(underscorePath(name), functionArguments, outVars, inFunc, isBoxedFunction(fn), visibility, false, isSimulation, staticPrototypes)%> - >> - case KERNEL_FUNCTION(__) then + match eq + case SES_RESIDUAL(__) then + '{<%index%>,"SES_RESIDUAL <%index%>",0,NULL}' + case SES_SIMPLE_ASSIGN(__) then + let var = '<%cref(cref)%>__varInfo' + let &preBuf += 'const VAR_INFO** equationInfo_cref<%index%> = (const VAR_INFO**)calloc(1,sizeof(VAR_INFO*));<%\n%>' + let &preBuf += 'equationInfo_cref<%index%>[0] = &<%var%>;<%\n%>' + '{<%index%>,"SES_SIMPLE_ASSIGN <%index%>",1,equationInfo_cref<%index%>}' + case SES_ARRAY_CALL_ASSIGN(__) then + '{<%index%>,"SES_ARRAY_CALL_ASSIGN <%index%>",0,NULL}' + case SES_IFEQUATION(__) then + let branches = ifbranches |> (_,eqs) => (eqs |> eq => equationInfo1(eq,preBuf,eqnsDefines,reverseProf) + ',<%\n%>') + let elsebr = (elsebranch |> eq => equationInfo1(eq,preBuf,eqnsDefines,reverseProf) + ',<%\n%>') + '<%branches%><%elsebr%>{<%index%>,"SES_IFEQUATION <%index%>",0,NULL}' + case SES_ALGORITHM(__) then + '{<%index%>,"SES_ALGORITHM <%index%>", 0, NULL}' + case SES_WHEN(__) then + '{<%index%>,"SES_WHEN <%index%>", 0, NULL}' + // no dynamic tearing + case SES_LINEAR(lSystem=ls as LINEARSYSTEM(__), alternativeTearing=NONE()) then + let &eqnsDefines += functionSimProfDef(eq,System.tmpTick(),reverseProf) + let &preBuf += 'const VAR_INFO** equationInfo_crefs<%ls.index%> = (const VAR_INFO**)malloc(<%listLength(ls.vars)%>*sizeof(VAR_INFO*));<%\n%>' + let &preBuf += '<%ls.vars|>var hasindex i0 => 'equationInfo_crefs<%ls.index%>[<%i0%>] = &<%cref(varName(var))%>__varInfo;'; separator="\n"%>;' + '{<%ls.index%>,"linear system <%ls.index%> (size <%listLength(ls.vars)%>)", <%listLength(ls.vars)%>, equationInfo_crefs<%ls.index%>}' + case SES_NONLINEAR(nlSystem=nls as NONLINEARSYSTEM(__), alternativeTearing=NONE()) then + let residuals = SimCodeUtil.sortEqSystems(nls.eqs) |> e => (equationInfo1(e,preBuf,eqnsDefines,reverseProf) + ',<%\n%>') + let jac = match nls.jacobianMatrix case SOME(mat) then equationInfoMatrix(mat,preBuf,eqnsDefines,reverseProf) + let &eqnsDefines += functionSimProfDef(eq,System.tmpTick(),reverseProf) + let &preBuf += 'const VAR_INFO** equationInfo_crefs<%nls.index%> = (const VAR_INFO**)malloc(<%listLength(nls.crefs)%>*sizeof(VAR_INFO*));<%\n%>' + let &preBuf += '<%nls.crefs|>cr hasindex i0 => 'equationInfo_crefs<%nls.index%>[<%i0%>] = &<%cref(cr)%>__varInfo;'; separator="\n"%>;' + '<%residuals%>{<%nls.index%>,"residualFunc<%nls.index%> (size <%listLength(nls.crefs)%>)", <%listLength(nls.crefs)%>, equationInfo_crefs<%nls.index%>}<%if jac then ',<%\n%><%jac%>'%>' + // dynamic tearing + case SES_LINEAR(lSystem=ls as LINEARSYSTEM(__), alternativeTearing = SOME(at as LINEARSYSTEM(__))) then + // for strict tearing set + let &eqnsDefines += functionSimProfDef(eq,System.tmpTick(),reverseProf) + let &preBuf += 'const VAR_INFO** equationInfo_crefs<%ls.index%> = (const VAR_INFO**)malloc(<%listLength(ls.vars)%>*sizeof(VAR_INFO*));<%\n%>' + let &preBuf += '<%ls.vars|>var hasindex i0 => 'equationInfo_crefs<%ls.index%>[<%i0%>] = &<%cref(varName(var))%>__varInfo;'; separator="\n"%>;' + // for casual tearing set + // let &eqnsDefines += functionSimProfDef(eq,System.tmpTick(),reverseProf) + let &preBuf += 'const VAR_INFO** equationInfo_crefs<%at.index%> = (const VAR_INFO**)malloc(<%listLength(at.vars)%>*sizeof(VAR_INFO*));<%\n%>' + let &preBuf += '<%at.vars|>var hasindex i0 => 'equationInfo_crefs<%at.index%>[<%i0%>] = &<%cref(varName(var))%>__varInfo;'; separator="\n"%>;' << - <%functionHeaderKernelFunctionInterface(underscorePath(name), functionArguments, outVars)%> + {<%ls.index%>,"linear system <%ls.index%> (size <%listLength(ls.vars)%>)", <%listLength(ls.vars)%>, equationInfo_crefs<%ls.index%>} + {<%at.index%>,"linear system <%at.index%> (size <%listLength(at.vars)%>)", <%listLength(at.vars)%>, equationInfo_crefs<%at.index%>} >> - case EXTERNAL_FUNCTION(dynamicLoad=true) then + case SES_NONLINEAR(nlSystem=nls as NONLINEARSYSTEM(__), alternativeTearing = SOME(at as NONLINEARSYSTEM(__))) then + // for strict tearing set + let residuals = SimCodeUtil.sortEqSystems(nls.eqs) |> e => (equationInfo1(e,preBuf,eqnsDefines,reverseProf) + ',<%\n%>') + let jac = match nls.jacobianMatrix case SOME(mat) then equationInfoMatrix(mat,preBuf,eqnsDefines,reverseProf) + let &eqnsDefines += functionSimProfDef(eq,System.tmpTick(),reverseProf) + let &preBuf += 'const VAR_INFO** equationInfo_crefs<%nls.index%> = (const VAR_INFO**)malloc(<%listLength(nls.crefs)%>*sizeof(VAR_INFO*));<%\n%>' + let &preBuf += '<%nls.crefs|>cr hasindex i0 => 'equationInfo_crefs<%nls.index%>[<%i0%>] = &<%cref(cr)%>__varInfo;'; separator="\n"%>;' + // for casual tearing set + let residuals2 = SimCodeUtil.sortEqSystems(at.eqs) |> e => (equationInfo1(e,preBuf,eqnsDefines,reverseProf) + ',<%\n%>') + let jac2 = match at.jacobianMatrix case SOME(mat) then equationInfoMatrix(mat,preBuf,eqnsDefines,reverseProf) + // let &eqnsDefines += functionSimProfDef(eq,System.tmpTick(),reverseProf) + let &preBuf += 'const VAR_INFO** equationInfo_crefs<%at.index%> = (const VAR_INFO**)malloc(<%listLength(at.crefs)%>*sizeof(VAR_INFO*));<%\n%>' + let &preBuf += '<%at.crefs|>cr hasindex i0 => 'equationInfo_crefs<%at.index%>[<%i0%>] = &<%cref(cr)%>__varInfo;'; separator="\n"%>;' << - <%functionHeaderNormal(underscorePath(name), funArgs, outVars, inFunc, visibility, true, isSimulation, staticPrototypes)%> - <%functionHeaderBoxed(underscorePath(name), funArgs, outVars, inFunc, isBoxedFunction(fn), visibility, true, isSimulation, staticPrototypes)%> - - <%extFunDefDynamic(fn)%> + <%residuals%>{<%nls.index%>,"residualFunc<%nls.index%> (size <%listLength(nls.crefs)%>)", <%listLength(nls.crefs)%>, equationInfo_crefs<%nls.index%>}<%if jac then ',<%\n%><%jac%>'%> + <%residuals2%>{<%at.index%>,"residualFunc<%at.index%> (size <%listLength(at.crefs)%>)", <%listLength(at.crefs)%>, equationInfo_crefs<%at.index%>}<%if jac2 then ',<%\n%><%jac2%>'%> >> - case EXTERNAL_FUNCTION(__) then - << - <%functionHeaderNormal(underscorePath(name), funArgs, outVars, inFunc, visibility, false, isSimulation, staticPrototypes)%> - <%functionHeaderBoxed(underscorePath(name), funArgs, outVars, inFunc, isBoxedFunction(fn), visibility, false, isSimulation, staticPrototypes)%> - - <%extFunDef(fn)%> - >> - case RECORD_CONSTRUCTOR(__) then - let fname = underscorePath(name) - let funArgsStr = (funArgs |> var as VARIABLE(__) => ', <%varType(var)%> <%crefStr(name)%>') - << - <% match visibility case PUBLIC() then "DLLExport" %> - <%fname%> omc_<%fname%>(threadData_t *threadData<%funArgsStr%>); /* record head */ - - <%functionHeaderBoxed(fname, funArgs, boxedRecordOutVars, inFunc, false, visibility, false, isSimulation, staticPrototypes)%> - >> -end functionHeader; - -template parallelFunctionHeader(Function fn, Boolean inFunc) - "Generates function header part in function files." -::= - match fn - case PARALLEL_FUNCTION(__) then - << - <%functionHeaderParallelImpl(underscorePath(name), functionArguments, outVars, inFunc, false)%> - >> -end parallelFunctionHeader; - -template functionHeaderParallelImpl(String fname, list fargs, list outVars, Boolean inFunc, Boolean boxed) - "Generates parmodelica paralell function header part in kernels files." -::= - let fargsStr = (fargs |> var => funArgDefinition(var) ;separator=", ") - if outVars then - << - <%outVars |> _ hasindex i1 fromindex 1 => '#define <%fname%>_rettype_<%i1%> c<%i1%>' ;separator="\n"%> - typedef struct <%fname%>_rettype_s - { - <%outVars |> var hasindex i1 fromindex 1 => - match var - case VARIABLE(__) then - let dimStr = match ty case T_ARRAY(__) - then '[<%dims |> dim => dimension(dim) ;separator=", "%>]' - let typeStr = if boxed then varTypeBoxed(var) else varType(var) - '<%typeStr%> c<%i1%>; /* <%crefStr(name)%><%dimStr%> */' - case FUNCTION_PTR(__) then - 'modelica_fnptr c<%i1%>; /* <%name%> */' - ;separator="\n";empty - %> - } <%fname%>_rettype; - - <%fname%>_rettype omc_<%fname%>(<%fargsStr%>); - - >> -end functionHeaderParallelImpl; - -template recordDeclaration(RecordDeclaration recDecl) - "Generates structs for a record declaration." -::= - match recDecl - case RECORD_DECL_FULL(__) then - << - <%recordDefinition(dotPath(defPath), - underscorePath(defPath), - (variables |> VARIABLE(__) => '"_<%crefStr(name)%>"' ;separator=","), - listLength(variables))%> - >> - case RECORD_DECL_DEF(__) then - << - <%recordDefinition(dotPath(path), - underscorePath(path), - (fieldNames |> name => '"<%name%>"' ;separator=","), - listLength(fieldNames))%> - >> -end recordDeclaration; - -template recordDeclarationHeader(RecordDeclaration recDecl) - "Generates structs for a record declaration." -::= - match recDecl - case r as RECORD_DECL_FULL(__) then - << - <% match aliasName - case SOME(str) then 'typedef <%str%> <%r.name%>;' - else << - typedef struct <%r.name%>_s { - <%r.variables |> var as VARIABLE(__) => '<%varType(var)%> _<%crefStr(var.name)%>;' ;separator="\n"%> - } <%r.name%>; - >> %> - typedef base_array_t <%name%>_array; - <%recordDefinitionHeader(dotPath(defPath), - underscorePath(defPath), - listLength(variables))%> - >> - case RECORD_DECL_DEF(__) then - << - <%recordDefinitionHeader(dotPath(path), - underscorePath(path), - listLength(fieldNames))%> - >> -end recordDeclarationHeader; - -template recordDefinition(String origName, String encName, String fieldNames, Integer numFields) - "Generates the definition struct for a record declaration." -::= - match encName - case "SourceInfo_SOURCEINFO" then '' - else - /* adrpo: 2011-03-14 make MSVC happy, no arrays of 0 size! */ - let fieldsDescription = - match numFields - case 0 then - 'const char* <%encName%>__desc__fields[1] = {"no fields"};' - case _ then - 'const char* <%encName%>__desc__fields[<%numFields%>] = {<%fieldNames%>};' - << - #define <%encName%>__desc_added 1 - <%fieldsDescription%> - struct record_description <%encName%>__desc = { - "<%encName%>", /* package_record__X */ - "<%origName%>", /* package.record_X */ - <%encName%>__desc__fields - }; - >> -end recordDefinition; - -template recordDefinitionHeader(String origName, String encName, Integer numFields) - "Generates the definition struct for a record declaration." -::= - << - extern struct record_description <%encName%>__desc; - >> -end recordDefinitionHeader; - -template functionHeaderNormal(String fname, list fargs, list outVars, Boolean inFunc, SCode.Visibility visibility, Boolean dynLoad, Boolean isSimulation, Text &staticPrototypes) -::=functionHeaderImpl(fname, fargs, outVars, inFunc, false, visibility, dynLoad, isSimulation, staticPrototypes) -end functionHeaderNormal; - -template functionHeaderBoxed(String fname, list fargs, list outVars, Boolean inFunc, Boolean isBoxed, SCode.Visibility visibility, Boolean dynLoad, Boolean isSimulation, Text &staticPrototypes) -::= - let boxvar = - << - static const MMC_DEFSTRUCTLIT(boxvar_lit_<%fname%>,2,0) {(void*) boxptr_<%fname%>,0}}; - #define boxvar_<%fname%> MMC_REFSTRUCTLIT(boxvar_lit_<%fname%>)<%\n%> - >> - << - <%if isBoxed then '#define boxptr_<%fname%> omc_<%fname%><%\n%>' else functionHeaderImpl(fname, fargs, outVars, inFunc, true, visibility, dynLoad, isSimulation, staticPrototypes)%> - <% match visibility - case PROTECTED(__) then - let &staticPrototypes += (if isSimulation then "" else boxvar) - if isSimulation then '<%boxvar%> /* boxvar early */' else "" - else boxvar %> - >> -end functionHeaderBoxed; - -template functionHeaderImpl(String fname, list fargs, list outVars, Boolean inFunc, Boolean boxed, SCode.Visibility visibility, Boolean dynamicLoad, Boolean isSimulation, Text &staticPrototypes) - "Generates function header for a Modelica/MetaModelica function. Generates a - - boxed version of the header if boxed = true, otherwise a normal header" -::= - let prototype = functionPrototype(fname, fargs, outVars, boxed, visibility, isSimulation) - let inFnStr = if boolAnd(boxed,inFunc) then - << - DLLExport - int in_<%fname%>(threadData_t *threadData, type_description * inArgs, type_description * outVar); - >> - match visibility - case PROTECTED(__) then - if isSimulation then - if dynamicLoad then "" else '<%prototype%>;<%\n%>' - else - let &staticPrototypes += if dynamicLoad then "" else '<%prototype%>;<%\n%>' - inFnStr - else - << - <%inFnStr%> - <%if dynamicLoad then '' else 'DLLExport<%\n%><%prototype%>;'%> - >> -end functionHeaderImpl; - -template functionPrototype(String fname, list fargs, list outVars, Boolean boxed, SCode.Visibility visibility, Boolean isSimulation) - "Generates function header definition for a Modelica/MetaModelica function. Generates a boxed version of the header if boxed = true, otherwise a normal definition" -::= - let static = if isSimulation then "" else (match visibility case PROTECTED(__) then 'PROTECTED_FUNCTION_STATIC ') - let fargsStr = if boxed then - (fargs |> var => ", " + funArgBoxedDefinition(var) ) - else - (fargs |> var => ", " + funArgDefinition(var) ) - let outarg = (match outVars - case {} then "void" - case var::_ then (match var - case VARIABLE(__) then if boxed then varTypeBoxed(var) else varType(var) - case FUNCTION_PTR(__) then "modelica_fnptr")) - let boxPtrStr = if boxed then "boxptr" else "omc" - if outVars then - let outargs = List.rest(outVars) |> var => ", " + (match var - case var as VARIABLE(__) then '<%if boxed then varTypeBoxed(var) else varType(var)%> *out<%funArgName(var)%>' - case FUNCTION_PTR(__) then 'modelica_fnptr *out<%funArgName(var)%>') - '<%static%><%outarg%> <%boxPtrStr%>_<%fname%>(threadData_t *threadData<%fargsStr%><%outargs%>)' - else - '<%static%>void <%boxPtrStr%>_<%fname%>(threadData_t *threadData<%fargsStr%>)' -end functionPrototype; - -template functionHeaderKernelFunctionInterface(String fname, list fargs, list outVars) - "Generates function header for a ParModelica Kernel function interface." -::= - '<%functionHeaderKernelFunctionInterfacePrototype(fname, fargs, outVars)%>;' -end functionHeaderKernelFunctionInterface; - -template functionHeaderKernelFunctionInterfacePrototype(String fname, list fargs, list outVars) - "Generates function header for a ParModelica Kernel function interface." -::= - let fargsStr = 'threadData_t *threadData' - let &fargsStr += if fargs then ", " + (fargs |> var => funArgDefinitionKernelFunctionInterface(var) ;separator=", ") - // let &fargsStr += if outVars then ", " + (outVars |> var => tupleOutfunArgDefinitionKernelFunctionInterface(var) ;separator=", ") - // 'void omc_<%fname%>(<%fargsStr%>)' - - match outVars - case {} then - 'void omc_<%fname%>(<%fargsStr%>)' - - case fvar::rest then - let rettype = functionArgTypeKernelInterface(fvar) - let &fargsStr += if rest then ", " + (rest |> var => tupleOutfunArgDefinitionKernelFunctionInterface(var) ;separator=", ") - '<%rettype%> omc_<%fname%>(<%fargsStr%>)' - - else - error(sourceInfo(), 'functionHeaderKernelFunctionInterfacePrototype failed') -end functionHeaderKernelFunctionInterfacePrototype; - -template funArgName(Variable var) -::= - let &auxFunction = buffer "" - match var - case VARIABLE(__) then contextCref(name,contextFunction,&auxFunction) - case FUNCTION_PTR(__) then '_' + name -end funArgName; - -template funArgDefinition(Variable var) -::= - let &auxFunction = buffer "" - match var - case VARIABLE(__) then ('<%varType(var)%> <%contextCref(name,contextFunction,&auxFunction)%>' + (if var.instDims then " = {0}")) - case FUNCTION_PTR(__) then 'modelica_fnptr _<%name%>' -end funArgDefinition; - -template funArgDefinitionKernelFunctionInterface(Variable var) -::= - let &auxFunction = buffer "" - match var - case VARIABLE(__) then - '<%functionArgTypeKernelInterface(var)%> <%funArgName(var)%>' - else error(sourceInfo(), 'funArgDefinitionKernelFunctionInterface : unsupported function argument type') -end funArgDefinitionKernelFunctionInterface; - -template tupleOutfunArgDefinitionKernelFunctionInterface(Variable var) -::= - let &auxFunction = buffer "" - match var - case VARIABLE(__) then - '<%functionArgTypeKernelInterface(var)%> *out<%funArgName(var)%>' - else error(sourceInfo(), 'tupleOutfunArgDefinitionKernelFunctionInterface : unsupported function argument type') -end tupleOutfunArgDefinitionKernelFunctionInterface; - -template functionArgTypeKernelInterface(Variable var) -::= - match var - case VARIABLE(ty=T_ARRAY(__), parallelism = PARGLOBAL(__)) then 'device_<%varType(var)%>' - case VARIABLE(ty=T_ARRAY(__), parallelism = PARLOCAL(__)) then 'device_local_<%varType(var)%>' - case VARIABLE(__) then '<%varType(var)%>' - else 'Invalid function argument to Kernel function Interface.' -end functionArgTypeKernelInterface; - -template funArgDefinitionKernelFunctionBody(Variable var) - "Generates code to initialize variables. - Does not return anything: just appends declarations to buffers." -::= -let &auxFunction = buffer "" -match var -//function args will have nill instdims even if they are arrays. handled here -case var as VARIABLE(ty=T_ARRAY(__), parallelism = PARGLOBAL(__)) then - let varName = '<%contextCref(var.name,contextParallelFunction,&auxFunction)%>' - '__global modelica_<%expTypeShort(var.ty)%>* data_<%varName%>,<%\n%> __global modelica_integer* info_<%varName%>' - -case var as VARIABLE(ty=T_ARRAY(__), parallelism = PARLOCAL(__)) then - let varName = '<%contextCref(var.name,contextParallelFunction,&auxFunction)%>' - '__local modelica_<%expTypeShort(var.ty)%>* data_<%varName%>,<%\n%> __local modelica_integer* info_<%varName%>' - -case var as VARIABLE(__) then - let varName = '<%contextCref(var.name,contextParallelFunction,&auxFunction)%>' - if instDims then - (match parallelism - case PARGLOBAL(__) then - '__global modelica_<%expTypeShort(var.ty)%>* data_<%varName%>,<%\n%> __global modelica_integer* info_<%varName%>' - case PARLOCAL(__) then - '__global modelica_<%expTypeShort(var.ty)%>* data_<%varName%>,<%\n%> __global modelica_integer* info_<%varName%>' - ) - else - 'modelica_<%expTypeShort(var.ty)%> <%varName%>' - -else '#error Unknown variable type in as function argument funArgDefinitionKernelFunctionBody<%\n%>' -end funArgDefinitionKernelFunctionBody; - -template funArgDefinitionKernelFunctionBody2(Variable var, Text &parArgList /*BUFPA*/) - "Generates code to initialize variables. - Does not return anything: just appends declarations to buffers." -::= -let &auxFunction = buffer "" -match var -//function args will have nill instdims even if they are arrays. handled here -case var as VARIABLE(ty=T_ARRAY(__)) then - let varName = '<%contextCref(var.name,contextParallelFunction,&auxFunction)%>' - let &parArgList += ',<%\n%> __global modelica_<%expTypeShort(var.ty)%>* data_<%varName%>,' - let &parArgList += '<%\n%> __global modelica_integer* info_<%varName%>' - "" -case var as VARIABLE(__) then - let varName = '<%contextCref(var.name,contextParallelFunction,&auxFunction)%>' - if instDims then - let &parArgList += ',<%\n%> __global modelica_<%expTypeShort(var.ty)%>* data_<%varName%>,' - let &parArgList += '<%\n%> __global modelica_integer* info_<%varName%>' - " " - else - let &parArgList += ',<%\n%> modelica_<%expTypeShort(var.ty)%> <%varName%>' - "" -else let &parArgList += ' #error Unknown variable type in as function argument funArgDefinitionKernelFunctionBody2<%\n%>' "" -end funArgDefinitionKernelFunctionBody2; - -template parFunArgDefinitionFromLooptupleVar(tuple tupleVar) -::= -match tupleVar -case tupleVar as ((cref as CREF_IDENT(identType = T_ARRAY(__)),_)) then - let varName = contextArrayCref(cref,contextParallelFunction) - match cref.identType - case identType as T_ARRAY(ty = T_INTEGER(__)) then - '__global modelica_integer* data_<%varName%>,<%\n%>__global modelica_integer* info_<%varName%>' - case identType as T_ARRAY(ty = T_REAL(__)) then - '__global modelica_real* data_<%varName%>,<%\n%>__global modelica_integer* info_<%varName%>' - - else 'Template error in parFunArgDefinitionFromLooptupleVar' - -case tupleVar as ((cref as CREF_IDENT(__),_)) then - let varName = contextArrayCref(cref,contextParallelFunction) - match cref.identType - case identType as T_INTEGER(__) then - 'modelica_integer <%varName%>' - case identType as T_REAL(__) then - 'modelica_real <%varName%>' - - else 'Tempalte error in parFunArgDefinitionFromLooptupleVar' - -end parFunArgDefinitionFromLooptupleVar; - -template reconstructKernelArraysFromLooptupleVars(tuple tupleVar, Text &reconstructedArrs) - "reconstructs modelica arrays in the kernels." -::= -match tupleVar -case tupleVar as ((cref as CREF_IDENT(identType = T_ARRAY(__)),_)) then - let varName = contextArrayCref(cref,contextParallelFunction) - match cref.identType - case identType as T_ARRAY(ty = T_INTEGER(__)) then - let &reconstructedArrs += 'integer_array <%varName%>; <%\n%>' - let &reconstructedArrs += '<%varName%>.data = data_<%varName%>; <%\n%>' - let &reconstructedArrs += '<%varName%>.ndims = info_<%varName%>[0]; <%\n%>' - let &reconstructedArrs += '<%varName%>.dim_size = info_<%varName%> + 1; <%\n%>' - "" - case identType as T_ARRAY(ty = T_REAL(__)) then - let &reconstructedArrs += 'real_array <%varName%>; <%\n%>' - let &reconstructedArrs += '<%varName%>.data = data_<%varName%>; <%\n%>' - let &reconstructedArrs += '<%varName%>.ndims = info_<%varName%>[0]; <%\n%>' - let &reconstructedArrs += '<%varName%>.dim_size = info_<%varName%> + 1; <%\n%>' - "" -else let &reconstructedArrs += '#wiered variable in kerenl reconstruction of arrays<%\n%>' "" -end reconstructKernelArraysFromLooptupleVars; - -template reconstructKernelArrays(Variable var, Text &reconstructedArrs) - "reconstructs modelica arrays in the kernels." -::= -let &auxFunction = buffer "" -match var -//function args will have nill instdims even if they are arrays. handled here -case var as VARIABLE(ty=T_ARRAY(__),parallelism=PARGLOBAL(__)) then - let varName = '<%contextCref(var.name,contextParallelFunction,&auxFunction)%>' - let &reconstructedArrs += '<%expTypeShort(var.ty)%>_array <%varName%>; <%\n%>' - let &reconstructedArrs += '<%varName%>.data = data_<%varName%>; <%\n%>' - let &reconstructedArrs += '<%varName%>.ndims = info_<%varName%>[0]; <%\n%>' - let &reconstructedArrs += '<%varName%>.dim_size = info_<%varName%> + 1; <%\n%>' - "" -case var as VARIABLE(ty=T_ARRAY(__),parallelism=PARLOCAL(__)) then - let varName = '<%contextCref(var.name,contextParallelFunction,&auxFunction)%>' - let &reconstructedArrs += 'local_<%expTypeShort(var.ty)%>_array <%varName%>; <%\n%>' - let &reconstructedArrs += '<%varName%>.data = data_<%varName%>; <%\n%>' - let &reconstructedArrs += '<%varName%>.ndims = info_<%varName%>[0]; <%\n%>' - let &reconstructedArrs += '<%varName%>.dim_size = info_<%varName%> + 1; <%\n%>' - "" -case var as VARIABLE(__) then - let varName = '<%contextCref(var.name,contextParallelFunction,&auxFunction)%>' - if instDims then - let &reconstructedArrs += '<%expTypeShort(var.ty)%>_array <%varName%>; <%\n%>' - let &reconstructedArrs += '<%varName%>.data = data_<%varName%>; <%\n%>' - let &reconstructedArrs += '<%varName%>.ndims = info_<%varName%>[0]; <%\n%>' - let &reconstructedArrs += '<%varName%>.dim_size = info_<%varName%> + 1; <%\n%>' - " " - else - "" -else let &reconstructedArrs += '#wiered variable in kerenl reconstruction of arrays<%\n%>' "" -end reconstructKernelArrays; - -template funArgBoxedDefinition(Variable var) - "A definition for a boxed variable is always of type modelica_metatype, - unless it's a function pointer" -::= - let &auxFunction = buffer "" - match var - case VARIABLE(__) then 'modelica_metatype <%contextCref(name,contextFunction,&auxFunction)%>' - case FUNCTION_PTR(__) then 'modelica_fnptr _<%name%>' -end funArgBoxedDefinition; - -template extFunDef(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) - let fargsStrEscaped = '<%escapeCComments(fargsStr)%>' - let includesStr = includes |> i => i ;separator=", " - /* - * adrpo: - * only declare the external function definition IF THERE WERE NO INCLUDES! - * i did not put includesStr string in the comment below as it might include - * entire files - */ - if includes then - << - /* - * The function has annotation(Include=...>) - * the external function definition should be present - * in one of these files and have this prototype: - * extern <%extReturnType(extReturn)%> <%fn_name%>(<%fargsStrEscaped%>); - */ - >> - else - << - extern <%extReturnType(extReturn)%> <%fn_name%>(<%fargsStr%>); - >> -end match -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; - -/* public */ template extFunctionName(String name, String language) "used in Compiler/Template/CodegenFMU.tpl" -::= - match language - case "C" then '<%name%>' - case "FORTRAN 77" then '<%name%>_' - else error(sourceInfo(), 'Unsupport external language: <%language%>') -end extFunctionName; - -template extFunDefArgs(list args, String language) -::= - match language - case "C" then (args |> arg => extFunDefArg(arg) ;separator=", ") - case "FORTRAN 77" then (args |> arg => extFunDefArgF77(arg) ;separator=", ") - else error(sourceInfo(), 'Unsupport external language: <%language%>') -end extFunDefArgs; - -template extReturnType(SimExtArg extArg) - "Generates return type for external function." -::= - match extArg - case ex as SIMEXTARG(__) then extType(type_,true /*Treat this as an input (pass by value)*/,false) - case SIMNOEXTARG(__) then "void" - case SIMEXTARGEXP(__) then error(sourceInfo(), 'Expression types are unsupported as return arguments <%printExpStr(exp)%>') - else error(sourceInfo(), "Unsupported return argument") -end extReturnType; - - -template extType(Type type, Boolean isInput, Boolean isArray) - "Generates type for external function argument or return value." -::= - let s = match type - case T_INTEGER(__) then "int" - case T_REAL(__) then "double" - case T_STRING(__) then "const char*" - case T_BOOL(__) then "int" - case T_ENUMERATION(__) then "int" - case T_ARRAY(__) then extType(ty,isInput,true) - case T_COMPLEX(complexClassType=EXTERNAL_OBJ(__)) - then "void *" - case T_COMPLEX(complexClassType=RECORD(path=rname)) - then '<%underscorePath(rname)%>' - case T_METATYPE(__) - case T_METABOXED(__) - then "modelica_metatype" - case T_FUNCTION_REFERENCE_VAR(__) - then "modelica_fnptr" - else error(sourceInfo(), 'Unknown external C type <%unparseType(type)%>') - match type case T_ARRAY(__) then s else if isInput then (if isArray then '<%match s case "const char*" then "" else "const "%><%s%>*' else s) else '<%s%>*' -end extType; - -template extTypeF77(Type type, Boolean isReference) - "Generates type for external function argument or return value for F77." -::= - let s = match type - case T_INTEGER(__) then "int" - case T_REAL(__) then "double" - case T_STRING(__) then "char" - case T_BOOL(__) then "int" - case T_ENUMERATION(__) then "int" - case T_ARRAY(__) then extTypeF77(ty, true) - case T_COMPLEX(complexClassType=EXTERNAL_OBJ(__)) - then "void*" - case T_COMPLEX(complexClassType=RECORD(path=rname)) - then '<%underscorePath(rname)%>' - case T_METATYPE(__) case T_METABOXED(__) then "void*" - else error(sourceInfo(), 'Unknown external F77 type <%unparseType(type)%>') - match type case T_ARRAY(__) then s else if isReference then '<%s%>*' else s -end extTypeF77; - -template extFunDefArg(SimExtArg extArg) - "Generates the definition of an external function argument. - Assume that language is C for now." -::= - let &auxFunction = buffer "" - match extArg - case SIMEXTARG(cref=c, isInput=ii, isArray=ia, type_=t) then - let name = contextCref(c,contextFunction,&auxFunction) - let typeStr = extType(t,ii,ia) - << - <%typeStr%> /*<%name%>*/ - >> - case SIMEXTARGEXP(__) then - let typeStr = extType(type_,true,false) - << - <%typeStr%> - >> - case SIMEXTARGSIZE(cref=c) then - << - size_t - >> -end extFunDefArg; - -template extFunDefArgF77(SimExtArg extArg) -::= - let &auxFunction = buffer "" - match extArg - case SIMEXTARG(cref=c, isInput = isInput, type_=t) then - let name = contextCref(c,contextFunction,&auxFunction) - let typeStr = '<%extTypeF77(t,true)%>' - '<%typeStr%> /*<%name%>*/' - - case SIMEXTARGEXP(__) then '<%extTypeF77(type_,true)%>' - - /* adpro: 2011-06-23 - * DO NOT USE CONST HERE as sometimes is used with size(A, 1) - - * sometimes with n in Modelica.Math.Matrices.Lapack and you - * get conflicting external definitions in the same Model_function.h - * file - */ - case SIMEXTARGSIZE(__) then 'int *' -end extFunDefArgF77; - - -template functionName(Function fn, Boolean dotPath) -::= - match fn - case FUNCTION(__) - case EXTERNAL_FUNCTION(__) - case RECORD_CONSTRUCTOR(__) then if dotPath then dotPath(name) else underscorePath(name) -end functionName; - - -template functionBodies(list functions, Boolean isSimulation) - "Generates the body for a set of functions." -::= - (functions |> fn => functionBody(fn, false, isSimulation) ;separator="\n") -end functionBodies; - -template functionBodiesParModelica(list functions) - "Generates the body for a set of functions." -::= - (functions |> fn => functionBodyParModelica(fn, false) ;separator="\n") -end functionBodiesParModelica; - -template functionBody(Function fn, Boolean inFunc, Boolean isSimulation) - "Generates the body for a function." -::= - match fn - case fn as FUNCTION(__) then functionBodyRegularFunction(fn, inFunc, isSimulation) - case fn as KERNEL_FUNCTION(__) then functionBodyKernelFunctionInterface(fn, inFunc) - case fn as EXTERNAL_FUNCTION(__) then functionBodyExternalFunction(fn, inFunc, isSimulation) - case fn as RECORD_CONSTRUCTOR(__) then functionBodyRecordConstructor(fn, isSimulation) -end functionBody; - -template functionBodyParModelica(Function fn, Boolean inFunc) - "Generates the body for a function." -::= - match fn - case fn as FUNCTION(__) then extractParforBodies(fn, inFunc) - case fn as KERNEL_FUNCTION(__) then functionBodyKernelFunction(fn, inFunc) - case fn as PARALLEL_FUNCTION(__) then functionBodyParallelFunction(fn, inFunc) -end functionBodyParModelica; - -template extractParforBodies(Function fn, Boolean inFunc) - "Generates the body for a Modelica/MetaModelica function." -::= -match fn -case FUNCTION(__) then - let()= System.tmpTickReset(1) - let()= System.tmpTickResetIndex(0,1) /* Boxed array indices */ - - let &varDecls = buffer "" - let &auxFunction = buffer "" - let bodyPart = (body |> stmt => extractParFors(stmt, &varDecls, &auxFunction) ;separator="\n") - << - <%auxFunction%> - <%bodyPart%> - >> -end extractParforBodies; - -template functionBodyRegularFunction(Function fn, Boolean inFunc, Boolean isSimulation) - "Generates the body for a Modelica/MetaModelica function." -::= -match fn -case FUNCTION(__) then - let &auxFunction = buffer "" - let()= codegenResetTryThrowIndex() - let()= System.tmpTickReset(1) - let()= System.tmpTickResetIndex(0,1) /* Boxed array indices */ - let fname = underscorePath(name) - let &varDecls = buffer "" - let &varInits = buffer "" - let &varFrees = buffer "" - let &auxFunction = buffer "" - let _ = (variableDeclarations |> var hasindex i1 fromindex 1 => - varInit(var, "", &varDecls, &varInits, &varFrees, &auxFunction) ; empty /* increase the counter! */ - ) - let bodyPart = (body |> stmt => funStatement(stmt, &varDecls, &auxFunction) ;separator="\n") - let outVarAssign = (List.restOrEmpty(outVars) |> var => varOutput(var)) - - let freeConstructedExternalObjects = (variableDeclarations |> var as VARIABLE(ty=T_COMPLEX(complexClassType=EXTERNAL_OBJ(path=path_ext))) => 'omc_<%underscorePath(path_ext)%>_destructor(threadData,<%contextCref(var.name,contextFunction,&auxFunction)%>);'; separator = "\n") - /* Needs to be done last as it messes with the tmp ticks :) */ - let &varDecls += addRootsTempArray() - - let boxedFn = functionBodyBoxed(fn, isSimulation) - << - <%auxFunction%> - <% match visibility case PUBLIC(__) then "DLLExport" %> - <%functionPrototype(fname, functionArguments, outVars, false, visibility, isSimulation)%> - { - <%varDecls%> - _tailrecursive: OMC_LABEL_UNUSED - <%varInits%> - <%bodyPart%> - _return: OMC_LABEL_UNUSED - <%outVarAssign%> - <%if acceptParModelicaGrammar() then - '/* Free GPU/OpenCL CPU memory */<%\n%><%varFrees%>'%> - <%freeConstructedExternalObjects%> - <%match outVars - case {} then 'return;' - case v::_ then 'return <%funArgName(v)%>;' - %> - } - <% if inFunc then generateInFunc(fname,functionArguments,outVars) %> - <%boxedFn%> - >> -end functionBodyRegularFunction; - -template generateInFunc(Text fname, list functionArguments, list outVars) -::= - << - DLLExport - int in_<%fname%>(threadData_t *threadData, type_description * inArgs, type_description * outVar) - { - //if (!mmc_GC_state) mmc_GC_init(); - <%functionArguments |> var => '<%funArgDefinition(var)%>;' ;separator="\n"%> - <%outVars |> var => '<%funArgDefinition(var)%>;' ;separator="\n"%> - <%functionArguments |> arg => readInVar(arg) ;separator="\n"%> - MMC_TRY_TOP_INTERNAL() - <%match outVars - case v::_ then '<%funArgName(v)%> = ' - %>omc_<%fname%>(threadData<%functionArguments |> var => (", " + funArgName(var) )%><%List.restOrEmpty(outVars) |> var => (", &" + funArgName(var) )%>); - MMC_CATCH_TOP(return 1) - <% match outVars case {} then "write_noretcall(outVar);" case first::_ then writeOutVar(first) %> - <% List.restOrEmpty(outVars) |> var => writeOutVar(var) ;separator="\n"; empty %> - fflush(NULL); - return 0; - } - #ifdef GENERATE_MAIN_EXECUTABLE - static int rml_execution_failed() - { - fflush(NULL); - fprintf(stderr, "Execution failed!\n"); - fflush(NULL); - return 1; - } - - int main(int argc, char **argv) { - MMC_INIT(); - { - void *lst = mmc_mk_nil(); - int i = 0; - - for (i=argc-1; i>0; i--) { - lst = mmc_mk_cons(mmc_mk_scon(argv[i]), lst); - } - - <%mainTop('omc_<%fname%>(threadData, lst);',"https://trac.openmodelica.org/OpenModelica/newticket")%> - } - - <%if Flags.isSet(HPCOM) then "terminateHpcOmThreads();" %> - fflush(NULL); - EXIT(0); - return 0; - } - #endif - >> -end generateInFunc; - -template functionBodyKernelFunction(Function fn, Boolean inFunc) - "Generates the body for a ParModelica Kernel function." -::= -match fn -case KERNEL_FUNCTION(__) then - let()= System.tmpTickReset(1) - let()= System.tmpTickResetIndex(0,1) /* Boxed array indices */ - let fname = underscorePath(name) - - //retTyep for kernels is always void - //let retType = if outVars then '<%fname%>_rettype' else "void" - - let &varDecls = buffer "" - let &varInits = buffer "" - let &varFrees = buffer "" - let &auxFunction = buffer "" - let _ = (variableDeclarations |> var => - varInit(var, "", &varDecls, &varInits, &varFrees, &auxFunction) ; empty /* increase the counter! */ - ) - - // This odd arrangment and call is to get the commas in the right places - // between the argumetns. - // This puts correct comma placment even when the 'outvar' list is empty - let argStr = (functionArguments |> var => '<%funArgDefinitionKernelFunctionBody(var)%>' ;separator=", \n ") - //let &argStr += (outVars |> var => '<%parFunArgDefinition(var)%>' ;separator=", \n") - let _ = (outVars |> var => - funArgDefinitionKernelFunctionBody2(var, &argStr) ;separator=",\n") - - // Reconstruct array arguments to structures in the kernels - let &reconstrucedArrays = buffer "" - let _ = (functionArguments |> var => - reconstructKernelArrays(var, &reconstrucedArrays) - ) - let _ = (outVars |> var => - reconstructKernelArrays(var, &reconstrucedArrays) - ) - - let bodyPart = (body |> stmt => parModelicafunStatement(stmt, &varDecls, &auxFunction) ;separator="\n") - - /* Needs to be done last as it messes with the tmp ticks :) */ - let &varDecls += addRootsTempArray() - - << - <%auxFunction%> - - __kernel void omc_<%fname%>( - <%\t%><%\t%><%argStr%>) - { - /* functionBodyKernelFunction: Reconstruct Arrays */ - <%reconstrucedArrays%> - - /* functionBodyKernelFunction: locals */ - <%varDecls%> - - /* functionBodyKernelFunction: var inits */ - <%varInits%> - /* functionBodyKernelFunction: body */ - <%bodyPart%> - - /* Free GPU/OpenCL CPU memory */ - <%varFrees%> - } - - >> -end functionBodyKernelFunction; - -//Generates the body of a parallel function -template functionBodyParallelFunction(Function fn, Boolean inFunc) - "Generates the body for a Modelica parallel function." -::= -match fn -case PARALLEL_FUNCTION(__) then - let()= System.tmpTickReset(1) - let fname = underscorePath(name) - let retType = if outVars then '<%fname%>_rettype' else "void" - let &varDecls = buffer "" - let &varInits = buffer "" - let &varFrees = buffer "" - let &auxFunction = buffer "" - let retVar = if outVars then tempDecl(retType, &varDecls) - let _ = (variableDeclarations |> var hasindex i1 fromindex 1 => - varInitParallel(var, "", i1, &varDecls, &varInits, &varFrees, &auxFunction) - ;empty - ) - let bodyPart = (body |> stmt => parModelicafunStatement(stmt, &varDecls, &auxFunction) ;separator="\n") - let &outVarInits = buffer "" - let &outVarCopy = buffer "" - let &outVarAssign = buffer "" - let _1 = (outVars |> var hasindex i1 fromindex 1 => - varOutputParallel(var, retVar, i1, &varDecls, &outVarInits, &outVarCopy, &outVarAssign, &auxFunction) - ;separator="\n"; empty - ) - - - << - <%auxFunction%> - <%retType%> omc_<%fname%>(<%functionArguments |> var => funArgDefinition(var) ;separator=", "%>) - { - <%varDecls%> - <%outVarInits%> - - <%varInits%> - - <%bodyPart%> - - <%outVarCopy%> - <%outVarAssign%> - - /*mahge: Free unwanted meomory allocated*/ - <%varFrees%> - - return<%if outVars then ' <%retVar%>' %>; - } - - >> -end functionBodyParallelFunction; - -template functionBodyKernelFunctionInterface(Function fn, Boolean inFunc) - "Generates the body for a Modelica/MetaModelica function." -::= -match fn -case KERNEL_FUNCTION(__) then - let()= System.tmpTickReset(1) - let()= System.tmpTickResetIndex(0,1) /* Boxed array indices */ - let fname = underscorePath(name) - let &auxFunction = buffer "" - - let &varDecls = buffer "" - let &varInits = buffer "" - let &varFrees = buffer "" - let _ = (listGet(outVars,1) |> var hasindex i1 fromindex 1 => - varInit(var, "", &varDecls, &varInits, &varFrees, &auxFunction) ; empty /* increase the counter! */ - ) - - let outVarAssign = (List.restOrEmpty(outVars) |> var => varOutput(var)) - - let cl_kernelVar = tempDecl("cl_kernel", &varDecls) - let kernel_arg_number = '<%fname%>_arg_nr' - - let &kernelArgSets = buffer "" - let _ = (functionArguments |> var => - setKernelArg_ith(var, &cl_kernelVar, &kernel_arg_number, &kernelArgSets) - ) - let _ = (outVars |> var => - setKernelArg_ith(var, &cl_kernelVar, &kernel_arg_number, &kernelArgSets) - ) - - let defines = (List.restOrEmpty(outVars) |> var as VARIABLE(__) => '#define <%contextCref(name,contextFunction,&auxFunction)%> (*out<%contextCref(name,contextFunction,&auxFunction)%>)' ;separator="\n") - let undefines = (List.restOrEmpty(outVars) |> var as VARIABLE(__) => '#undef <%contextCref(name,contextFunction,&auxFunction)%>' ;separator="\n") - - << - - <%functionHeaderKernelFunctionInterfacePrototype(fname, functionArguments, outVars)%> - { - <%defines%> - - <%varDecls%> - - <%varInits%> - - /* functionBodyKernelFunctionInterface : <%fname%> Kernel creation and execution */ - int <%kernel_arg_number%> = 0; - <%cl_kernelVar%> = ocl_create_kernel(omc_ocl_program, "omc_<%fname%>"); - <%kernelArgSets%> - ocl_execute_kernel(<%cl_kernelVar%>); - clReleaseKernel(<%cl_kernelVar%>); - /*functionBodyKernelFunctionInterface : <%fname%> kernel execution ends here.*/ - - <%outVarAssign%> - - <%varFrees%> - - <%match outVars - case {} then 'return;' - case var::_ then 'return <%funArgName(var)%>;' - %> - - <%undefines%> - } - - >> - -end functionBodyKernelFunctionInterface; - -template setKernelArg_ith(Variable var, Text &KernelName, Text &argNr, Text &parVarList /*BUFPA*/) -::= -let &auxFunction = buffer "" -match var -//function args will have nill instdims even if they are arrays. handled here -case var as VARIABLE(ty=T_ARRAY(__),parallelism=PARGLOBAL(__)) then - let varName = '<%contextCref(var.name,contextFunction,&auxFunction)%>' - let &parVarList += 'ocl_set_kernel_arg(<%KernelName%>, <%argNr%>, <%varName%>.data); ++<%argNr%>; <%\n%>' - let &parVarList += 'ocl_set_kernel_arg(<%KernelName%>, <%argNr%>, <%varName%>.info_dev); ++<%argNr%>; <%\n%>' - "" -case var as VARIABLE(ty=T_ARRAY(__),parallelism=PARLOCAL(__)) then - let varName = '<%contextCref(var.name,contextFunction,&auxFunction)%>' - // Increment twice. Both data and info set in the function - // let &parVarList += 'ocl_set_local_array_kernel_arg(<%KernelName%>, <%argNr%>, &<%varName%>); ++<%argNr%>; ++<%argNr%>; <%\n%>' - let &parVarList += 'ocl_set_local_kernel_arg(<%KernelName%>, <%argNr%>, sizeof(modelica_<%expTypeShort(var.ty)%>) * device_array_nr_of_elements(&<%varName%>)); ++<%argNr%>; <%\n%>' - let &parVarList += 'ocl_set_local_kernel_arg(<%KernelName%>, <%argNr%>, sizeof(modelica_integer) * (<%varName%>.info[0]+1)*sizeof(modelica_integer)); ++<%argNr%>; <%\n%>' - "" -case var as VARIABLE(__) then - let varName = '<%contextCref(var.name,contextFunction,&auxFunction)%>' - if instDims then - let &parVarList += 'ocl_set_kernel_arg(<%KernelName%>, <%argNr%>, <%varName%>.data); ++<%argNr%>; <%\n%>' - let &parVarList += 'ocl_set_kernel_arg(<%KernelName%>, <%argNr%>, <%varName%>.info_dev); ++<%argNr%>; <%\n%>' - "" - else - let &parVarList += 'ocl_set_kernel_arg(<%KernelName%>, <%argNr%>, <%varName%>); ++<%argNr%>; <%\n%>' - "" -end setKernelArg_ith; - - -template setKernelArgFormTupleLoopVars_ith(tuple tupleVar, Text &KernelName, Text &argNr, Text &parVarList, Context context /*BUFPA*/) -::= -match tupleVar -//function args will have nill instdims even if they are arrays. handled here -case tupleVar as ((cref as CREF_IDENT(identType = T_ARRAY(__)),_)) then - let varName = contextArrayCref(cref,context) - let &parVarList += 'ocl_set_kernel_arg(<%KernelName%>, <%argNr%>, <%varName%>.data); ++<%argNr%>; <%\n%>' - let &parVarList += 'ocl_set_kernel_arg(<%KernelName%>, <%argNr%>, <%varName%>.info_dev); ++<%argNr%>; <%\n%>' - "" -case tupleVar as ((cref as CREF_IDENT(__),_)) then - let varName = contextArrayCref(cref,context) - let &parVarList += 'ocl_set_kernel_arg(<%KernelName%>, <%argNr%>, <%varName%>); ++<%argNr%>; <%\n%>' - "" -end setKernelArgFormTupleLoopVars_ith; - - -template functionBodyExternalFunction(Function fn, Boolean inFunc, Boolean isSimulation) - "Generates the body for an external function (just a wrapper)." -::= -match fn -case efn as EXTERNAL_FUNCTION(__) then - let()= System.tmpTickReset(1) - let()= System.tmpTickResetIndex(0,1) /* Boxed array indices */ - let fname = underscorePath(name) - let retType = if outVars then '<%fname%>_rettype' else "void" - let &preExp = buffer "" - let &varDecls = buffer "" - let &varFrees = buffer "" - let &outputAlloc = buffer "" - let &auxFunction = buffer "" - let callPart = extFunCall(fn, &preExp, &varDecls, &auxFunction) - let _ = ( outVars |> var => - varInit(var, "", &varDecls, &outputAlloc, &varFrees, &auxFunction) - ; empty /* increase the counter! */ ) - - let outVarAssign = (List.restOrEmpty(outVars) |> var => varOutput(var)) - - let &varDecls += addRootsTempArray() - let boxedFn = functionBodyBoxed(fn, isSimulation) - let fnBody = << - <%auxFunction%> - <%functionPrototype(fname, funArgs, outVars, false, visibility, isSimulation)%> - { - <%varDecls%> - <%modelicaLine(info)%> - <%preExp%> - <%outputAlloc%> - <%callPart%> - <%outVarAssign%> - <%match outVars - case {} then 'return;' - case v::_ then 'return <%funArgName(v)%>;' - %> - } - >> - << - <% if dynamicLoad then - << - ptrT_<%extFunctionName(extName, language)%> ptr_<%extFunctionName(extName, language)%>=NULL; - >> %> - <%fnBody%> - <% if inFunc then generateInFunc(fname, funArgs, outVars) %> - <%boxedFn%> - >> -end functionBodyExternalFunction; - - -template functionBodyRecordConstructor(Function fn, Boolean isSimulation) - "Generates the body for a record constructor." -::= -match fn -case RECORD_CONSTRUCTOR(__) then - let()= System.tmpTickReset(1) - let &varDecls = buffer "" - let &varInits = buffer "" - let &varFrees = buffer "" - let &auxFunction = buffer "" - let fname = underscorePath(name) - let structType = '<%fname%>' - let structVar = tempDecl(structType, &varDecls) - let _ = (locals |> var => - varInitRecord(var, structVar, &varDecls, &varInits, &auxFunction) ; empty /* increase the counter! */ - ) - let boxedFn = functionBodyBoxed(fn, isSimulation) - << - <%auxFunction%> - <%fname%> omc_<%fname%>(threadData_t *threadData<%funArgs |> VARIABLE(__) => ', <%expTypeArrayIf(ty)%> <%crefStr(name)%>'%>) - { - <%varDecls%> - <%varInits%> - <%funArgs |> VARIABLE(__) => '<%structVar%>._<%crefStr(name)%> = <%crefStr(name)%>;' ;separator="\n"%> - return <%structVar%>; - } - - <%boxedFn%> - >> -end functionBodyRecordConstructor; - -template varInitRecord(Variable var, String prefix, Text &varDecls, Text &varInits, Text &auxFunction) - "Generates code to initialize variables. - Does not return anything: just appends declarations to buffers." -::= -match var -case var as VARIABLE(parallelism = NON_PARALLEL(__)) then - let varName = '<%prefix%>._<%crefToCStr(var.name)%>' - let &varInits += initRecordMembers(var, &auxFunction) - let instDimsInit = (instDims |> exp => - daeExp(exp, contextFunction, &varInits, &varDecls, &auxFunction) - ;separator=", ") - if instDims then - let defaultAlloc = 'alloc_<%expTypeShort(var.ty)%>_array(&<%varName%>, <%listLength(instDims)%>, <%instDimsInit%>);<%\n%>' - let defaultValue = varAllocDefaultValue(var, "", varName, defaultAlloc, &varDecls, &varInits, &auxFunction) - let &varInits += defaultValue - "" - else - (match var.value - case SOME(exp) then - let defaultValue = '<%varName%> = <%daeExp(exp, contextFunction, &varInits, &varDecls, &auxFunction)%>;<%\n%>' - let &varInits += defaultValue - - " " - else - "") - -case var as FUNCTION_PTR(__) then - "" -else error(sourceInfo(), 'Unknown local variable type in record') -end varInitRecord; - -template functionBodyBoxed(Function fn, Boolean isSimulation) - "Generates code for a boxed version of a function. Extracts the needed data - from a function and calls functionBodyBoxedImpl" -::= - let fname = match fn - case FUNCTION(__) - case EXTERNAL_FUNCTION(__) - case RECORD_CONSTRUCTOR(__) then - underscorePath(name) - << - <% - match fn - case FUNCTION(__) then if not isBoxedFunction(fn) then functionBodyBoxedImpl(name, functionArguments, outVars, visibility, isSimulation) - case EXTERNAL_FUNCTION(__) then if not isBoxedFunction(fn) then functionBodyBoxedImpl(name, funArgs, outVars, visibility, isSimulation) - case RECORD_CONSTRUCTOR(__) then boxRecordConstructor(fn, isSimulation) - %> - >> -end functionBodyBoxed; - -template functionBodyBoxedImpl(Absyn.Path name, list funargs, list outvars, SCode.Visibility visibility, Boolean isSimulation) - "Helper template for functionBodyBoxed, does all the real work." -::= - let() = System.tmpTickReset(1) - let()= System.tmpTickResetIndex(0,1) /* Boxed array indices */ - let fname = underscorePath(name) - let retTypeBoxed = if outvars then 'modelica_metatype' else "void" - let &varDecls = buffer "" - let &varBox = buffer "" - let &varUnbox = buffer "" - let &auxFunction = buffer "" - let args = (funargs |> arg => (", " + funArgUnbox(arg, &varDecls, &varBox, &auxFunction))) - let &varBoxIgnore = buffer "" - let &outputAllocIgnore = buffer "" - let &varFreesIgnore = buffer "" - let &auxFunctionIgnore = buffer "" - let outputs = ( List.restOrEmpty(outvars) |> var hasindex i1 fromindex 1 => - match var - case v as VARIABLE(__) then - if mmcConstructorType(liftArrayListExp(v.ty,v.instDims)) then - let _ = varInit(var, "", &varDecls, &outputAllocIgnore, &varFreesIgnore, &auxFunctionIgnore) - ", &" + funArgName(var) - else - ", out" + funArgName(var) - case FUNCTION_PTR(__) then ", out" + funArgName(var) - ; empty - ) - let retvar = (match outvars - case {} then "" - case (v as VARIABLE(__))::_ then - let _ = varInit(v, "", &varDecls, &outputAllocIgnore, &varFreesIgnore, &auxFunctionIgnore) - let out = ("out" + funArgName(v)) - let _ = funArgBox(out, funArgName(v), "", liftArrayListExp(v.ty,v.instDims), &varUnbox, &varDecls) - (if mmcConstructorType(liftArrayListExp(v.ty,v.instDims)) then - let &varDecls += 'modelica_metatype <%out%>;<%\n%>' - out - else - funArgName(v)) - case v::_ then - let _ = varInit(v, "", &varDecls, &outputAllocIgnore, &varFreesIgnore, &auxFunctionIgnore) - funArgName(v) - ) - let _ = (List.restOrEmpty(outvars) |> var as VARIABLE(__) => - let arg = funArgName(var) - funArgBox('*out<%arg%>', arg, 'out<%arg%>', liftArrayListExp(var.ty,var.instDims), &varUnbox, &varDecls) - ; separator="\n") - let prototype = functionPrototype(fname, funargs, outvars, true, visibility, isSimulation) - << - <%auxFunction%> - <%prototype%> - { - <%varDecls%> - <%addRootsTempArray()%> - <%varBox%> - <%match outvars case v::_ then '<%funArgName(v)%> = '%>omc_<%fname%>(threadData<%args%><%outputs%>); - <%varUnbox%> - <%match outvars case v::_ then 'return <%retvar%>;' else "return;"%> - } - >> -end functionBodyBoxedImpl; - -template boxRecordConstructor(Function fn, Boolean isSimulation) -::= -let &auxFunction = buffer "" -match fn -case RECORD_CONSTRUCTOR(__) then - let() = System.tmpTickReset(1) - let fname = underscorePath(name) - let retType = '<%fname%>_rettypeboxed' - let funArgsStr = (funArgs |> var => match var - case VARIABLE(__) then ", " + contextCref(name,contextFunction,&auxFunction) - case FUNCTION_PTR(__) then ", " + name - else error(sourceInfo(),"boxRecordConstructor:Unknown variable")) - let start = daeExpMetaHelperBoxStart(incrementInt(listLength(funArgs), 1)) - << - <%if isSimulation then "" else match visibility case PROTECTED(__) then "PROTECTED_FUNCTION_STATIC "%>modelica_metatype boxptr_<%fname%>(threadData_t *threadData<%funArgs |> var => (", " + funArgBoxedDefinition(var))%>) - { - return mmc_mk_box<%start%>3, &<%fname%>__desc<%funArgsStr%>); - } - >> -end boxRecordConstructor; - -template funArgUnbox(Variable var, Text &varDecls, Text &varBox, Text &auxFunction) -::= -match var -case VARIABLE(__) then - let varName = contextCref(name,contextFunction,&auxFunction) - unboxVariable(varName, ty, &varBox, &varDecls) -case FUNCTION_PTR(__) then // Function pointers don't need to be boxed. - '_<%name%>' -end funArgUnbox; - -template unboxVariable(String varName, Type varType, Text &preExp, Text &varDecls) -::= -match varType -case T_COMPLEX(complexClassType = EXTERNAL_OBJ(__)) -case T_STRING(__) -case T_METATYPE(__) -case T_METARECORD(__) -case T_METAUNIONTYPE(__) -case T_METALIST(__) -case T_METAARRAY(__) -case T_METAPOLYMORPHIC(__) -case T_METAOPTION(__) -case T_METATUPLE(__) -case T_METABOXED(__) then varName -case T_COMPLEX(complexClassType = RECORD(__)) then - unboxRecord(varName, varType, &preExp, &varDecls) -case T_ARRAY(__) then - '*((base_array_t*)<%varName%>)' -else - let shortType = mmcTypeShort(varType) - let ty = 'modelica_<%shortType%>' - let tmpVar = tempDecl(ty, &varDecls) - let &preExp += '<%tmpVar%> = mmc_unbox_<%shortType%>(<%varName%>);<%\n%>' - tmpVar -end unboxVariable; - -template unboxRecord(String recordVar, Type ty, Text &preExp, Text &varDecls) -::= -match ty -case T_COMPLEX(complexClassType = RECORD(path = path), varLst = vars) then - let tmpVar = tempDecl('<%underscorePath(path)%>', &varDecls) - let &preExp += (vars |> TYPES_VAR(name = compname) hasindex offset fromindex 2 => - let varType = mmcTypeShort(ty) - let untagTmp = tempDecl('modelica_metatype', &varDecls) - //let offsetStr = incrementInt(i1, 1) - let &unboxBuf = buffer "" - let unboxStr = unboxVariable(untagTmp, ty, &unboxBuf, &varDecls) - << - <%untagTmp%> = (MMC_FETCH(MMC_OFFSET(MMC_UNTAGPTR(<%recordVar%>), <%offset%>))); - <%unboxBuf%> - <%tmpVar%>._<%compname%> = <%unboxStr%>; - >> - ;separator="\n") - tmpVar -end unboxRecord; - -template funArgBox(String outName, String varName, String condition, Type ty, Text &varUnbox, Text &varDecls) - "Generates code to box a variable." -::= - let constructorType = mmcConstructorType(ty) - if constructorType then - let constructor = mmcConstructor(ty, varName, &varUnbox, &varDecls) - let &varUnbox += if condition then 'if (<%condition%>) { <%outName%> = <%constructor%>; }<%\n%>' else '<%outName%> = <%constructor%>;<%\n%>' - outName - else // Some types don't need to be boxed, since they're already boxed. - let &varUnbox += '/* skip box <%varName%>; <%unparseType(ty)%> */' - varName -end funArgBox; - -template mmcConstructorType(Type type) -::= - match type - case T_INTEGER(__) - case T_BOOL(__) - case T_REAL(__) - case T_ENUMERATION(__) - case T_ARRAY(__) - case T_COMPLEX(complexClassType = RECORD(__)) then 'modelica_metatype' -end mmcConstructorType; - -template mmcConstructor(Type type, String varName, Text &preExp, Text &varDecls) -::= - match type - case T_INTEGER(__) then 'mmc_mk_icon(<%varName%>)' - case T_BOOL(__) then 'mmc_mk_icon(<%varName%>)' - case T_REAL(__) then 'mmc_mk_rcon(<%varName%>)' - case T_STRING(__) then 'mmc_mk_string(<%varName%>)' - case T_ENUMERATION(__) then 'mmc_mk_icon(<%varName%>)' - case T_ARRAY(__) then 'mmc_mk_modelica_array(<%varName%>)' - case T_COMPLEX(complexClassType = RECORD(path = path), varLst = vars) then - let varCount = daeExpMetaHelperBoxStart(incrementInt(listLength(vars), 1)) - let varsStr = (vars |> var as TYPES_VAR(__) => - let tmp = tempDecl("modelica_metatype", &varDecls) - let varname = '<%varName%>._<%name%>' - ", " + funArgBox(tmp, varname, "", ty, &preExp, &varDecls) - ) - 'mmc_mk_box<%varCount%>3, &<%underscorePath(path)%>__desc<%varsStr%>)' - case T_COMPLEX(__) then 'mmc_mk_box(<%varName%>)' -end mmcConstructor; - -template readInVar(Variable var) - "Generates code for reading a variable from inArgs." -::= - let &auxFunction = buffer "" - match var - case VARIABLE(name=cr, ty=T_COMPLEX(complexClassType=RECORD(__))) then - << - if (read_modelica_record(&inArgs, <%readInVarRecordMembers(ty, contextCref(cr,contextFunction,&auxFunction))%>)) return 1; - >> - case VARIABLE(name=cr, ty=T_STRING(__)) then - << - if (read_<%expTypeArrayIf(ty)%>(&inArgs, <%if not acceptMetaModelicaGrammar() then "(char**)"%> &<%contextCref(name,contextFunction,&auxFunction)%>)) return 1; - >> - case VARIABLE(__) then - << - if (read_<%expTypeArrayIf(ty)%>(&inArgs, &<%contextCref(name,contextFunction,&auxFunction)%>)) return 1; - >> -end readInVar; - - -template readInVarRecordMembers(Type type, String prefix) - "Helper to readInVar." -::= -match type -case T_COMPLEX(varLst=vl) then - (vl |> subvar as TYPES_VAR(__) => - match ty case T_COMPLEX(__) then - let newPrefix = '<%prefix%>._<%subvar.name%>' - readInVarRecordMembers(ty, newPrefix) - else - '&(<%prefix%>._<%subvar.name%>)' - ;separator=", ") -end readInVarRecordMembers; - - -template writeOutVar(Variable var) - "Generates code for writing a variable to outVar." - -::= - match var - case VARIABLE(ty=T_COMPLEX(complexClassType=RECORD(__))) then - << - write_modelica_record(outVar, <%writeOutVarRecordMembers(ty, funArgName(var))%>); - >> - case VARIABLE(__) then - - << - write_<%varType(var)%>(outVar, &<%funArgName(var)%>); - >> -end writeOutVar; - - -template writeOutVarRecordMembers(Type type, String prefix) - "Helper to writeOutVar." -::= -match type -case T_COMPLEX(varLst=vl, complexClassType=n) then - let basename = underscorePath(ClassInf.getStateName(n)) - let args = (vl |> subvar as TYPES_VAR(__) => - match ty case T_COMPLEX(__) then - let newPrefix = '<%prefix%>._<%subvar.name%>' - '<%expTypeRW(ty)%>, <%writeOutVarRecordMembers(ty, newPrefix)%>' - else - '<%expTypeRW(ty)%>, &(<%prefix%>._<%subvar.name%>)' - ;separator=", ") - << - &<%basename%>__desc<%if args then ', <%args%>'%>, TYPE_DESC_NONE - >> -end writeOutVarRecordMembers; - -template varInit(Variable var, String outStruct, Text &varDecls, Text &varInits, Text &varFrees, Text &auxFunction) - "Generates code to initialize variables. - Does not return anything: just appends declarations to buffers." -::= -match var -case var as VARIABLE(parallelism = NON_PARALLEL(__)) then - let varName = contextCref(var.name,contextFunction,&auxFunction) - let typ = varType(var) - let initVar = match typ case "modelica_metatype" - case "modelica_string" then ' = NULL' - else '' - let &varDecls += if not outStruct then '<%typ%> <%varName%><%initVar%>;<%\n%>' //else "" - let varName = contextCref(var.name,contextFunction,&auxFunction) - let &varInits += initRecordMembers(var, &auxFunction) - let instDimsInit = (instDims |> exp => - daeExp(exp, contextFunction, &varInits, &varDecls, &auxFunction) - ;separator=", ") - if instDims then - (match var.ty - case T_COMPLEX(__) then - let defaultAlloc = 'alloc_generic_array(&<%varName%>, sizeof(<%expTypeShort(var.ty)%>), <%listLength(instDims)%>, <%instDimsInit%>);<%\n%>' - (match var.value - case SOME(exp) then - let defaultValue = varAllocDefaultValue(var, outStruct, varName, defaultAlloc, &varDecls, &varInits, &auxFunction) - let &varInits += defaultValue - "" - else - let &varInits += defaultAlloc - "") - else - let defaultAlloc = 'alloc_<%expTypeShort(var.ty)%>_array(&<%varName%>, <%listLength(instDims)%>, <%instDimsInit%>);<%\n%>' - let defaultValue = varAllocDefaultValue(var, outStruct, varName, defaultAlloc, &varDecls, &varInits, &auxFunction) - let &varInits += defaultValue - "") - else - (match var.value - case SOME(exp) then - let defaultValue = '<%contextCref(var.name,contextFunction,&auxFunction)%> = <%daeExp(exp, contextFunction, &varInits, &varDecls, &auxFunction)%>;<%\n%>' - let &varInits += defaultValue - - " " - else - "") - -//mahge: OpenCL/CUDA GPU variables. -case var as VARIABLE(__) then - parVarInit(var, outStruct, &varDecls, &varInits, &varFrees, &auxFunction) - -case var as FUNCTION_PTR(__) then - let &varDecls += 'modelica_fnptr _<%name%>;<%\n%>' - let varInitText = (match defaultValue - case SOME(exp) then - let v = daeExp(exp, contextFunction, &varInits, &varDecls, &auxFunction) - '_<%name%> = <%v%>;<%\n%>') - let &varInits += varInitText - "" -else error(sourceInfo(), 'Unknown local variable type') -end varInit; - -/* ParModelica Extension. */ -template parVarInit(Variable var, String outStruct, Text &varDecls, Text &varInits, Text &varFrees, Text &auxFunction) - "Generates code to initialize ParModelica variables. - Does not return anything: just appends declarations to buffers." -::= -match var -case var as VARIABLE(parallelism = PARGLOBAL(__)) then - let varName = '<%contextCref(var.name, contextFunction, &auxFunction)%>' - - let instDimsInit = (instDims |> exp => - daeExp(exp, contextFunction, &varInits, &varDecls, &auxFunction) - ;separator=", ") - - if instDims then - let &varDecls += 'device_<%expTypeShort(var.ty)%>_array <%varName%>;<%\n%>' - let defaultAlloc = 'alloc_<%expTypeShort(var.ty)%>_array(&<%varName%>, <%listLength(instDims)%>, <%instDimsInit%>);<%\n%>' - let defaultValue = varAllocDefaultValue(var, outStruct, varName, defaultAlloc, &varDecls, &varInits, &auxFunction) - let &varInits += defaultValue - - let &varFrees += 'free_device_array(&<%varName%>);<%\n%>' - "" - else - (match var.value - case SOME(exp) then - let &varDecls += '<%varType(var)%> <%varName%>;<%\n%>' - let defaultValue = '<%contextCref(var.name,contextFunction,&auxFunction)%> = <%daeExp(exp, contextFunction, &varInits, &varDecls, &auxFunction)%>;<%\n%>' - let &varInits += defaultValue - - " " - else - let &varDecls += '<%varType(var)%> <%varName%>;<%\n%>' - "") - -case var as VARIABLE(parallelism = PARLOCAL(__)) then - let varName = '<%contextCref(var.name, contextFunction, &auxFunction)%>' - - let instDimsInit = (instDims |> exp => - daeExp(exp, contextFunction, &varInits, &varDecls, &auxFunction) - ;separator=", ") - if instDims then - let &varDecls += 'device_local_<%expTypeShort(var.ty)%>_array <%varName%>;<%\n%>' - let defaultAlloc = 'alloc_device_local_<%expTypeShort(var.ty)%>_array(&<%varName%>, <%listLength(instDims)%>, <%instDimsInit%>);<%\n%>' - let defaultValue = varAllocDefaultValue(var, outStruct, varName, defaultAlloc, &varDecls, &varInits, &auxFunction) - let &varInits += defaultValue - - // let &varFrees += 'free_device_array(&<%varName%>);<%\n%>' - "" - else - (match var.value - case SOME(exp) then - let &varDecls += '<%varType(var)%> <%varName%>;<%\n%>' - let defaultValue = '<%contextCref(var.name,contextFunction,&auxFunction)%> = <%daeExp(exp, contextFunction, &varInits, &varDecls, &auxFunction)%>;<%\n%>' - let &varInits += defaultValue - - " " - else - let &varDecls += '<%varType(var)%> <%varName%>;<%\n%>' - "") - -else - let &varDecls += '#error Unknown parallel variable type<%\n%>' - error(sourceInfo(), 'parVarInit:error Unknown parallel variable type') -end parVarInit; - -template varInitParallel(Variable var, String outStruct, Integer i, Text &varDecls, Text &varInits, Text &varFrees, Text &auxFunction) - "Generates code to initialize variables in PARALLEL FUNCTIONS. - Does not return anything: just appends declarations to buffers." -::= -match var -case var as VARIABLE(__) then - let &varDecls += if not outStruct then '<%varType(var)%> <%contextCref(var.name, contextFunction, &auxFunction)%>;<%\n%>' //else "" - let varName = if outStruct then '<%outStruct%>.targ<%i%>' else '<%contextCref(var.name, contextFunction, &auxFunction)%>' - let instDimsInit = (instDims |> exp => - daeExp(exp, contextFunction, &varInits, &varDecls, &auxFunction) - ;separator=", ") - if instDims then - let defaultAlloc = 'alloc_<%expTypeShort(var.ty)%>_array_c99_<%listLength(instDims)%>(&<%varName%>, <%listLength(instDims)%>, <%instDimsInit%>, memory_state);<%\n%>' - let defaultValue = varAllocDefaultValue(var, outStruct, varName, defaultAlloc, &varDecls, &varInits, &auxFunction) - let &varInits += defaultValue - " " - else - (match var.value - case SOME(exp) then - let defaultValue = '<%contextCref(var.name,contextFunction,&auxFunction)%> = <%daeExp(exp, contextFunction, &varInits, &varDecls, &auxFunction)%>;<%\n%>' - let &varInits += defaultValue - " " - else - "") -case var as FUNCTION_PTR(__) then - "" -else - let &varDecls += '#error Unknown local variable type<%\n%>' - error(sourceInfo(), 'varInitParallel:error Unknown local variable type') -end varInitParallel; - - -template varAllocDefaultValue(Variable var, String outStruct, String lhsVarName, Text allocNoDefault, Text &varDecls, Text &varInits, Text &auxFunction) -::= -match var -case var as VARIABLE(__) then - match value - case SOME(CREF(componentRef = cr)) then - 'copy_<%expTypeShort(var.ty)%>_array(<%contextCref(cr,contextFunction,&auxFunction)%>, &<%lhsVarName%>);<%\n%>' - case SOME(arr as ARRAY(ty = T_ARRAY(ty = T_COMPLEX(complexClassType = record_state)))) then - let &varInits += allocNoDefault - let varName = contextCref(var.name,contextFunction,&auxFunction) - let rec_name = '<%underscorePath(ClassInf.getStateName(record_state))%>' - let &preExp = buffer "" - let params = (arr.array |> e hasindex i1 fromindex 1 => - let prefix = if arr.scalar then '(<%expTypeFromExpModelica(e)%>)' else '&' - '(*((<%rec_name%>*)generic_array_element_addr(&<%varName%>, sizeof(<%rec_name%>), 1, <%i1%>))) = <%prefix%><%daeExp(e, contextFunction, &preExp, &varDecls, &auxFunction)%>;' - ;separator="\n") - << - <%preExp%> - <%params%> - >> - case SOME(arr as ARRAY(__)) then - let arrayExp = '<%daeExp(arr, contextFunction, &varInits, &varDecls, &auxFunction)%>' - 'copy_<%expTypeShort(var.ty)%>_array(<%arrayExp%>, &<%lhsVarName%>);<%\n%>' - case SOME(exp) then - '<%lhsVarName%> = <%daeExp(exp, contextFunction, &varInits, &varDecls, &auxFunction)%>;<%\n%>' - else - let &varInits += allocNoDefault - "" -end varAllocDefaultValue; - -template varOutput(Variable var) - "Generates code to copy result value from a function to dest." -::= - match var - case FUNCTION_PTR(__) then - 'if (out<%funArgName(var)%>) { *out<%funArgName(var)%> = (modelica_fnptr)<%funArgName(var)%>; }<%\n%>' - case VARIABLE(ty=T_ARRAY(__)) then - // If the dim_size is NULL, the output is an array with unknown dimensions. Copy the array. - 'if (out<%funArgName(var)%>) { if (out<%funArgName(var)%>->dim_size == NULL) {copy_<%expTypeShort(var.ty)%>_array(<%funArgName(var)%>, out<%funArgName(var)%>);} else {copy_<%expTypeShort(var.ty)%>_array_data(<%funArgName(var)%>, out<%funArgName(var)%>);} }<%\n%>' - case VARIABLE(__) then - /*Seems like we still get an array var with the wrong type here. It have instdims though >_<. TODO I guess*/ - if instDims then - 'if (out<%funArgName(var)%>) { if (out<%funArgName(var)%>->dim_size == NULL) {copy_<%expTypeShort(var.ty)%>_array(<%funArgName(var)%>, out<%funArgName(var)%>);} else {copy_<%expTypeShort(var.ty)%>_array_data(<%funArgName(var)%>, out<%funArgName(var)%>);} }<%\n%>' - else - 'if (out<%funArgName(var)%>) { *out<%funArgName(var)%> = <%funArgName(var)%>; }<%\n%>' - else error(sourceInfo(), 'varOutput:error Unknown variable type as output') -end varOutput; - -template varOutputParallel(Variable var, String dest, Integer ix, Text &varDecls, - Text &varInits, Text &varCopy, Text &varAssign, Text &auxFunction) - "Generates code to copy result value from a function to dest in a Parallel function." -::= -match var -/* The storage size of arrays is known at call time, so they can be allocated - * before set_memory_state. Strings are not known, so we copy them, etc... - */ -case var as VARIABLE(ty = T_STRING(__)) then - if not acceptMetaModelicaGrammar() then - // We need to strdup() all strings, then allocate them on the memory pool again, then free the temporary string - let &varCopy += 'String Variables not Allowed in ParModelica.' - let &varAssign += - << - String Variables not Allowed in ParModelica. - >> - "" - else - let &varAssign += 'How did you get here??' - "" -case var as VARIABLE(parallelism = PARGLOBAL(__)) then - let instDimsInit = (instDims |> exp => - daeExp(exp, contextFunction, &varInits, &varDecls, &auxFunction) - ;separator=", ") - if instDims then - let &varInits += 'alloc_<%expTypeShort(var.ty)%>_array_c99_<%listLength(instDims)%>(&<%dest%>.c<%ix%>, <%listLength(instDims)%>, <%instDimsInit%>, memory_state);<%\n%>' - let &varAssign += 'copy_<%expTypeShort(var.ty)%>_array_data(<%contextCref(var.name,contextFunction, &auxFunction)%>, &<%dest%>.c<%ix%>);<%\n%>' - "" - else - let &varInits += '<%dest%>.c<%ix%> = ocl_device_alloc(sizeof(modelica_<%expTypeShort(var.ty)%>));<%\n%>' - let &varAssign += 'copy_assignment_helper_<%expTypeShort(var.ty)%>(&<%dest%>.c<%ix%>, &<%contextCref(var.name,contextFunction,&auxFunction)%>);<%\n%>' - "" - -case var as VARIABLE(parallelism = PARLOCAL(__)) then - let instDimsInit = (instDims |> exp => - daeExp(exp, contextFunction, &varInits, &varDecls, &auxFunction) - ;separator=", ") - if instDims then - let &varInits += 'alloc_<%expTypeShort(var.ty)%>_array_c99_<%listLength(instDims)%>(&<%dest%>.c<%ix%>, <%listLength(instDims)%>, <%instDimsInit%>, memory_state);<%\n%>' - let &varAssign += 'copy_<%expTypeShort(var.ty)%>_array_data(<%contextCref(var.name, contextFunction, &auxFunction)%>, &<%dest%>.c<%ix%>);<%\n%>' - "" - else - let &varInits += 'LOCAL HERE!! <%dest%>.c<%ix%> = ocl_device_alloc(sizeof(modelica_<%expTypeShort(var.ty)%>));<%\n%>' - let &varAssign += 'LOCAL HERE!! copy_assignment_helper_<%expTypeShort(var.ty)%>(&<%dest%>.c<%ix%>, &<%contextCref(var.name,contextFunction,&auxFunction)%>);<%\n%>' - "" - -case var as VARIABLE(__) then - let instDimsInit = (instDims |> exp => - daeExp(exp, contextFunction, &varInits, &varDecls, &auxFunction) - ;separator=", ") - if instDims then - let &varInits += 'alloc_<%expTypeShort(var.ty)%>_array_c99_<%listLength(instDims)%>(&<%dest%>.c<%ix%>, <%listLength(instDims)%>, <%instDimsInit%>, memory_state);<%\n%>' - let &varAssign += 'copy_<%expTypeShort(var.ty)%>_array_data(<%contextCref(var.name,contextFunction,&auxFunction)%>, &<%dest%>.c<%ix%>);<%\n%>' - "" - else - let &varInits += initRecordMembers(var, &auxFunction) - let &varAssign += '<%dest%>.c<%ix%> = <%contextCref(var.name,contextFunction,&auxFunction)%>;<%\n%>' - "" -case var as FUNCTION_PTR(__) then - let &varAssign += '<%dest%>.c<%ix%> = (modelica_fnptr) _<%var.name%>;<%\n%>' - "" -end varOutputParallel; - -template varOutputKernelInterface(Variable var, String dest, Integer ix, Text &varDecls, - Text &varInits, Text &varCopy, Text &varAssign, Text &auxFunction) - "Generates code to copy result value from a function to dest." -::= -match var -case var as VARIABLE(parallelism = PARGLOBAL(__)) then - let &varDecls += '<%varType(var)%> <%contextCref(var.name,contextFunction,&auxFunction)%>;<%\n%>' - let varName = '<%contextCref(var.name,contextFunction,&auxFunction)%>' - let instDimsInit = (instDims |> exp => - daeExp(exp, contextFunction, &varInits, &varDecls, &auxFunction) - ;separator=", ") - if instDims then - let &varInits += 'alloc_<%expTypeShort(var.ty)%>_array(&<%varName%>, <%listLength(instDims)%>, <%instDimsInit%>);<%\n%>' - - let &varAssign += '<%dest%>.c<%ix%> = <%contextCref(var.name,contextFunction,&auxFunction)%>;<%\n%>' - "" - else - let &varInits += '<%varName%> = ocl_device_alloc(sizeof(modelica_<%expTypeShort(var.ty)%>));<%\n%>' - let &varAssign += '<%dest%>.c<%ix%> = <%contextCref(var.name,contextFunction,&auxFunction)%>;<%\n%>' - "" - -case var as VARIABLE(parallelism = PARLOCAL(__)) then - let &varDecls += '<%varType(var)%> <%contextCref(var.name,contextFunction,&auxFunction)%>;<%\n%>' - let varName = '<%contextCref(var.name,contextFunction,&auxFunction)%>' - let instDimsInit = (instDims |> exp => - daeExp(exp, contextFunction, &varInits, &varDecls, &auxFunction) - ;separator=", ") - if instDims then - let &varInits += 'alloc_<%expTypeShort(var.ty)%>_array(&<%varName%>, <%listLength(instDims)%>, <%instDimsInit%>);<%\n%>' - - let &varAssign += '<%dest%>.c<%ix%> = <%contextCref(var.name,contextFunction,&auxFunction)%>;<%\n%>' - "" - else - let &varInits += '<%varName%> = ocl_device_alloc(sizeof(modelica_<%expTypeShort(var.ty)%>));<%\n%>' - let &varAssign += '<%dest%>.c<%ix%> = <%contextCref(var.name,contextFunction,&auxFunction)%>;<%\n%>' - "" - -case var as VARIABLE(__) then - let &varDecls += '<%varType(var)%> <%contextCref(var.name,contextFunction,&auxFunction)%>;<%\n%>' - let varName = '<%contextCref(var.name,contextFunction,&auxFunction)%>' - let instDimsInit = (instDims |> exp => - daeExp(exp, contextFunction, &varInits, &varDecls, &auxFunction) - ;separator=", ") - if instDims then - let &varInits += 'alloc_<%expTypeShort(var.ty)%>_array(&<%varName%>, <%listLength(instDims)%>, <%instDimsInit%>);<%\n%>' - - let &varAssign += '<%dest%>.c<%ix%> = <%contextCref(var.name,contextFunction,&auxFunction)%>;<%\n%>' - "" - else - let &varInits += initRecordMembers(var, &auxFunction) - let &varAssign += '<%dest%>.c<%ix%> = <%contextCref(var.name,contextFunction,&auxFunction)%>;<%\n%>' - "" -case var as FUNCTION_PTR(__) then - let &varAssign += '<%dest%>.c<%ix%> = (modelica_fnptr) _<%var.name%>;<%\n%>' - "" -end varOutputKernelInterface; - -template initRecordMembers(Variable var, Text &auxFunction) -::= -match var -case VARIABLE(ty = T_COMPLEX(complexClassType = RECORD(__))) then - let varName = contextCref(name,contextFunction,&auxFunction) - (ty.varLst |> v => recordMemberInit(v, varName) ;separator="\n") -end initRecordMembers; - -template recordMemberInit(Var v, Text varName) -::= -match v -case TYPES_VAR(ty = T_ARRAY(__)) then - let arrayType = expType(ty, true) - let dims = (ty.dims |> dim => dimension(dim) ;separator=", ") - 'alloc_<%arrayType%>(&<%varName%>._<%name%>, <%listLength(ty.dims)%>, <%dims%>);' -end recordMemberInit; - -template extVarName(ComponentRef cr) -::= '_<%crefToMStr(appendStringFirstIdent("_ext", cr))%>' -end extVarName; - -template extFunCall(Function fun, Text &preExp, Text &varDecls, Text &auxFunction) - "Generates the call to an external function." -::= -match fun -case EXTERNAL_FUNCTION(__) then - match language - case "C" then extFunCallC(fun, &preExp, &varDecls, &auxFunction) - case "FORTRAN 77" then extFunCallF77(fun, &preExp, &varDecls, &auxFunction) -end extFunCall; - -template extFunCallC(Function fun, Text &preExp, Text &varDecls, Text &auxFunction) - "Generates the call to an external C function." -::= -match fun -case EXTERNAL_FUNCTION(__) then - /* adpro: 2011-06-24 do vardecls -> extArgs as there might be some sets in there! */ - let varDecs = (List.union(extArgs, extArgs) |> arg => extFunCallVardecl(arg, &varDecls, &auxFunction) ;separator="\n") - let _ = (biVars |> bivar => extFunCallBiVar(bivar, &preExp, &varDecls, &auxFunction) ;separator="\n") - let fname = if dynamicLoad then 'ptr_<%extFunctionName(extName, language)%>' else '<%extName%>' - let dynamicCheck = if dynamicLoad then - << - if(<%fname%>==NULL) - { - FILE_INFO info = {<%infoArgs(info)%>}; - omc_terminate(info, "dynamic external function <%extFunctionName(extName, language)%> not set!"); - } else - >> - else '' - let args = (extArgs |> arg => extArg(arg, &preExp, &varDecls, &auxFunction) ;separator=", ") - let returnAssign = match extReturn case SIMEXTARG(cref=c) then - '<%extVarName(c)%> = ' - else - "" - << - <%varDecs%> - <%match extReturn case SIMEXTARG(__) then extFunCallVardecl(extReturn, &varDecls, &auxFunction)%> - <%dynamicCheck%> - <%returnAssign%><%fname%>(<%args%>); - <%extArgs |> arg => extFunCallVarcopy(arg, &auxFunction) ;separator="\n"%> - <%match extReturn case SIMEXTARG(__) then extFunCallVarcopy(extReturn, &auxFunction)%> - >> -end extFunCallC; - -template extFunCallF77(Function fun, Text &preExp, Text &varDecls, Text &auxFunction) - "Generates the call to an external Fortran 77 function." -::= -match fun -case EXTERNAL_FUNCTION(__) then - /* adpro: 2011-06-24 do vardecls -> bivar -> extArgs as there might be some sets in there! */ - let &varDecls += '/* extFunCallF77: varDecs */<%\n%>' - let varDecs = (List.union(extArgs, extArgs) |> arg => extFunCallVardeclF77(arg, &varDecls, &auxFunction) ;separator="\n") - let &varDecls += '/* extFunCallF77: biVarDecs */<%\n%>' - let &preExp += '/* extFunCallF77: biVarDecs */<%\n%>' - let biVarDecs = (biVars |> arg => extFunCallBiVarF77(arg, &preExp, &varDecls, &auxFunction) ;separator="\n") - let &varDecls += '/* extFunCallF77: args */<%\n%>' - let &preExp += '/* extFunCallF77: args */<%\n%>' - let args = (extArgs |> arg => extArgF77(arg, &preExp, &varDecls, &auxFunction) ;separator=", ") - let &preExp += '/* extFunCallF77: end args */<%\n%>' - let returnAssign = match extReturn case SIMEXTARG(cref=c) then - '<%extVarName(c)%> = ' - else - "" - << - <%varDecs%> - <%biVarDecs%> - /* extFunCallF77: extReturn */ - <%match extReturn case SIMEXTARG(__) then extFunCallVardeclF77(extReturn, &varDecls, &auxFunction)%> - /* extFunCallF77: CALL */ - <%returnAssign%><%extName%>_(<%args%>); - /* extFunCallF77: copy args */ - <%List.union(extArgs,extArgs) |> arg => extFunCallVarcopyF77(arg, &auxFunction) ;separator="\n"%> - /* extFunCallF77: copy return */ - <%match extReturn case SIMEXTARG(__) then extFunCallVarcopyF77(extReturn, &auxFunction)%> - >> - -end extFunCallF77; - -template extFunCallVardecl(SimExtArg arg, Text &varDecls, Text &auxFunction) - "Helper to extFunCall." -::= - match arg - case SIMEXTARG(isInput = true, isArray = true, type_ = ty, cref = c) then - match expTypeShort(ty) - case "integer" then - 'pack_integer_array(&<%contextCref(c,contextFunction,&auxFunction)%>);' - else "" - case SIMEXTARG(isInput=true, isArray=false, type_=ty, cref=c) then - match ty - case T_STRING(__) then - "" - case T_FUNCTION_REFERENCE_VAR(__) then - (match c - case CREF_IDENT(__) then - let &varDecls += 'modelica_fnptr <%extVarName(c)%>;<%\n%>' - << - if (MMC_FETCH(MMC_OFFSET(MMC_UNTAGPTR(_<%ident%>), 2))) { - <%generateThrow()%> /* The FFI does not allow closures */ - } - <%extVarName(c)%> = MMC_FETCH(MMC_OFFSET(MMC_UNTAGPTR(_<%ident%>), 1)); - >> - else - error(sourceInfo(), 'Got function pointer that is not a CREF_IDENT: <%crefStr(c)%>, <%unparseType(ty)%>')) - else - let &varDecls += '<%extType(ty,true,false)%> <%extVarName(c)%>;<%\n%>' - << - <%extVarName(c)%> = (<%extType(ty,true,false)%>)<%contextCref(c,contextFunction,&auxFunction)%>; - >> - case SIMEXTARG(outputIndex=oi, isArray=false, type_=ty, cref=c) then - match oi case 0 then - "" - else - let &varDecls += '<%extType(ty,true,false)%> <%extVarName(c)%>;<%\n%>' - "" -end extFunCallVardecl; - -template extFunCallVardeclF77(SimExtArg arg, Text &varDecls, Text &auxFunction) -::= - match arg - case SIMEXTARG(isInput = true, isArray = true, type_ = ty, cref = c) then - let &varDecls += '<%expTypeArrayIf(ty)%> <%extVarName(c)%>;<%\n%>' - 'convert_alloc_<%expTypeArray(ty)%>_to_f77(&<%contextCref(c,contextFunction,&auxFunction)%>, &<%extVarName(c)%>);' - case ea as SIMEXTARG(outputIndex = oi, isArray = ia, type_= ty, cref = c) then - match oi case 0 then "" else - match ia - case false then - let default_val = typeDefaultValue(ty) - let default_exp = if ea.hasBinding then "" else match default_val case "" then "" else ' = <%default_val%>' - let &varDecls += '<%extTypeF77(ty,false)%> <%extVarName(c)%><%default_exp%>;<%\n%>' - "" - else - let &varDecls += '<%expTypeArrayIf(ty)%> <%extVarName(c)%>;<%\n%>' - 'convert_alloc_<%expTypeArray(ty)%>_to_f77(&<%contextCref(c,contextFunction,&auxFunction)%>, &<%extVarName(c)%>);' - case SIMEXTARG(type_ = ty, cref = c) then - let &varDecls += '<%extTypeF77(ty,false)%> <%extVarName(c)%>;<%\n%>' - "" -end extFunCallVardeclF77; - -template typeDefaultValue(DAE.Type ty) -::= - match ty - case ty as T_INTEGER(__) then '0' - case ty as T_REAL(__) then '0.0' - case ty as T_BOOL(__) then '0' - case ty as T_STRING(__) then '0' /* Always segfault is better than only sometimes segfault :) */ - else "" -end typeDefaultValue; - -template extFunCallBiVar(Variable var, Text &preExp, Text &varDecls, Text &auxFunction) -::= - match var - case var as VARIABLE(__) then - let var_name = extVarName(name) - let &varDecls += '<%varType(var)%> <%var_name%>;<%\n%>' - let defaultValue = match value - case SOME(v) then - daeExp(v, contextFunction, &preExp, &varDecls, &auxFunction) - else "" - let &preExp += if defaultValue then '<%var_name%> = <%defaultValue%>;<%\n%>' - "" -end extFunCallBiVar; - -template extFunCallBiVarF77(Variable var, Text &preExp, Text &varDecls, Text &auxFunction) -::= - match var - case var as VARIABLE(__) then - let var_name = contextCref(name,contextFunction,&auxFunction) - let &varDecls += '<%varType(var)%> <%var_name%>;<%\n%>' - let &varDecls += '<%varType(var)%> <%extVarName(name)%>;<%\n%>' - let defaultValue = match value - case SOME(v) then - '<%daeExp(v, contextFunction, &preExp, &varDecls, &auxFunction)%>' - else "" - let instDimsInit = (instDims |> exp => - daeExp(exp, contextFunction, &preExp, &varDecls, &auxFunction) ;separator=", ") - if instDims then - let type = expTypeArray(var.ty) - let &preExp += 'alloc_<%type%>(&<%var_name%>, <%listLength(instDims)%>, <%instDimsInit%>);<%\n%>' - let &preExp += if defaultValue then 'copy_<%type%>(<%defaultValue%>, &<%var_name%>);<%\n%>' else '' - let &preExp += 'convert_alloc_<%type%>_to_f77(&<%var_name%>, &<%extVarName(name)%>);<%\n%>' - "" - else - let &preExp += if defaultValue then '<%var_name%> = <%defaultValue%>;<%\n%>' else '' - "" -end extFunCallBiVarF77; - -template extFunCallVarcopy(SimExtArg arg, Text &auxFunction) - "Helper to extFunCall." -::= -match arg -case SIMEXTARG(outputIndex=0) then "" -case SIMEXTARG(outputIndex=oi, isArray=true, cref=c, type_=ty) then - match expTypeShort(ty) - case "integer" then - 'unpack_integer_array(&<%contextCref(c,contextFunction,&auxFunction)%>);' - case "string" then - 'unpack_string_array(&<%contextCref(c,contextFunction,&auxFunction)%>);' - else "" -case SIMEXTARG(outputIndex=oi, isArray=false, type_=ty, cref=c) then - let cr = '<%extVarName(c)%>' - << - <%contextCref(c,contextFunction,&auxFunction)%> = (<%expTypeModelica(ty)%>)<% - match ty - case T_STRING(__) then 'mmc_mk_scon(<%cr%>)' - else cr%>; - >> -end extFunCallVarcopy; - -template extFunCallVarcopyF77(SimExtArg arg, Text &auxFunction) - "Generates code to copy results from output variables into the out struct. - Helper to extFunCallF77." -::= -match arg -case SIMEXTARG(outputIndex=oi, isArray=ai, type_=ty, cref=c) then - match oi case 0 then - "" - else - let outarg = contextCref(c,contextFunction,&auxFunction) - let ext_name = extVarName(c) - match ai - case false then - '<%outarg%> = (<%expTypeModelica(ty)%>)<%ext_name%>;<%\n%>' - case true then - 'convert_alloc_<%expTypeArray(ty)%>_from_f77(&<%ext_name%>, &<%outarg%>);' -end extFunCallVarcopyF77; - -template extArg(SimExtArg extArg, Text &preExp, Text &varDecls, Text &auxFunction) - "Helper to extFunCall." -::= - match extArg - case SIMEXTARG(cref=c, outputIndex=oi, isArray=true, type_=t) then - let name = contextCref(c,contextFunction,&auxFunction) - let shortTypeStr = expTypeShort(t) - '(<%extType(t,isInput,true)%>) data_of_<%shortTypeStr%>_c89_array(&(<%name%>))' - case SIMEXTARG(cref=c, isInput=ii, outputIndex=0, type_=t) then - let cr = match t case T_STRING(__) then contextCref(c,contextFunction,&auxFunction) else extVarName(c) - (match t case T_STRING(__) then 'MMC_STRINGDATA(<%cr%>)' else cr) - case SIMEXTARG(cref=c, isInput=ii, outputIndex=oi, type_=t) then - '&<%extVarName(c)%>' - case SIMEXTARGEXP(__) then - daeExternalCExp(exp, contextFunction, &preExp, &varDecls, &auxFunction) - case SIMEXTARGSIZE(cref=c) then - let typeStr = expTypeShort(type_) - let name = contextCref(c,contextFunction, &auxFunction) - let dim = daeExp(exp, contextFunction, &preExp, &varDecls, &auxFunction) - 'size_of_dimension_base_array(<%name%>, <%dim%>)' -end extArg; - -template extArgF77(SimExtArg extArg, Text &preExp, Text &varDecls, Text &auxFunction) -::= - match extArg - case SIMEXTARG(cref=c, isArray=true, type_=t) then - // Arrays are converted to fortran format that are stored in _ext-variables. - 'data_of_<%expTypeShort(t)%>_f77_array(&(<%extVarName(c)%>))' - case SIMEXTARG(cref=c, outputIndex=oi, type_=T_INTEGER(__)) then - // Always prefix fortran arguments with &. - let suffix = if oi then "_ext" - '(int*) &<%contextCref(c,contextFunction,&auxFunction)%><%suffix%>' - case SIMEXTARG(cref=c, outputIndex=oi, type_ = T_STRING(__)) then - // modelica_string SHOULD NOT BE PREFIXED by &! - '(char*)MMC_STRINGDATA(<%contextCref(c,contextFunction,&auxFunction)%>)' - case SIMEXTARG(cref=c, outputIndex=oi, type_=t) then - // Always prefix fortran arguments with &. - let suffix = if oi then "_ext" - '&<%contextCref(c,contextFunction, &auxFunction)%><%suffix%>' - case SIMEXTARGEXP(exp=exp, type_ = T_STRING(__)) then - // modelica_string SHOULD NOT BE PREFIXED by &! - let texp = daeExp(exp, contextFunction, &preExp, &varDecls, &auxFunction) - let tvar = tempDecl(expTypeFromExpFlag(exp,8),&varDecls) - let &preExp += '<%tvar%> = <%texp%>;<%\n%>' - '(char*)MMC_STRINGDATA(<%tvar%>)' - case SIMEXTARGEXP(__) then - daeExternalF77Exp(exp, contextFunction, &preExp, &varDecls, &auxFunction) - case SIMEXTARGSIZE(cref=c) then - // Fortran functions only takes references to variables, so we must store - // the result from size_of_dimension__array in a temporary variable. - let sizeVarName = tempSizeVarName(c, exp, &auxFunction) - let sizeVar = tempDecl("int", &varDecls) - let dim = daeExp(exp, contextFunction, &preExp, &varDecls, &auxFunction) - let &preExp += '<%sizeVar%> = size_of_dimension_base_array(<%contextCref(c,contextFunction, &auxFunction)%>, <%dim%>);<%\n%>' - '&<%sizeVar%>' -end extArgF77; - -template tempSizeVarName(ComponentRef c, DAE.Exp indices, Text &auxFunction) - -::= - match indices - case ICONST(__) then '<%contextCref(c,contextFunction,&auxFunction)%>_size_<%integer%>' - else error(sourceInfo(), 'tempSizeVarName:UNHANDLED_EXPRESSION') -end tempSizeVarName; - -template funStatement(Statement stmt, Text &varDecls, Text &auxFunction) - "Generates function statements." -::= - match stmt - case ALGORITHM(__) then - (statementLst |> stmt => - algStatement(stmt, contextFunction, &varDecls, &auxFunction) - ;separator="\n") - else - error(sourceInfo(), 'funStatement:NOT IMPLEMENTED FUN STATEMENT') -end funStatement; - -template parModelicafunStatement(Statement stmt, Text &varDecls, Text &auxFunction) - "Generates function statements With PARALLEL context. Similar to Function context. - Except in some cases like assignments." -::= - match stmt - case ALGORITHM(__) then - (statementLst |> stmt => - algStatement(stmt, contextParallelFunction, &varDecls, &auxFunction) - ;separator="\n") - else - error(sourceInfo(), 'parModelicafunStatement:NOT IMPLEMENTED FUN STATEMENT') -end parModelicafunStatement; - -template extractParFors(Statement stmt, Text &varDecls, Text &auxFunction) - "Generates bodies of parfor loops to the kernel file. - The sequential C operations needed to implement the parallel - for loop will be handled by the normal funStatment template." -::= - match stmt - case ALGORITHM(__) then - (statementLst |> stmt => - extractParFors_impl(stmt, contextParallelFunction, &varDecls, &auxFunction) - ;separator="\n") - else - error(sourceInfo(), 'extractParFors:NOT IMPLEMENTED FUN STATEMENT') -end extractParFors; - - -template extractParFors_impl(DAE.Statement stmt, Context context, Text &varDecls, Text &auxFunction) - "Generates an algorithm statement." -::= - match stmt - case s as STMT_PARFOR(__) then algStmtParForBody(s, contextParallelFunction, &varDecls, &auxFunction) -end extractParFors_impl; - - - -template algStatement(DAE.Statement stmt, Context context, Text &varDecls, Text &auxFunction) - "Generates an algorithm statement." -::= - match System.tmpTickIndexReserve(1, 0) /* Remember the old tmpTick */ - case oldIndex - then let res = (match stmt - case s as STMT_ASSIGN(exp1=PATTERN(__)) then algStmtAssignPattern(s, context, &varDecls, &auxFunction) - case s as STMT_ASSIGN(__) then algStmtAssign(s, context, &varDecls, &auxFunction) - case s as STMT_ASSIGN_ARR(__) then algStmtAssignArr(s, context, &varDecls, &auxFunction) - case s as STMT_TUPLE_ASSIGN(__) then algStmtTupleAssign(s, context, &varDecls, &auxFunction) - case s as STMT_IF(__) then algStmtIf(s, context, &varDecls, &auxFunction) - case s as STMT_FOR(__) then algStmtFor(s, context, &varDecls, &auxFunction) - case s as STMT_PARFOR(__) then algStmtParForInterface(s, context, &varDecls, &auxFunction) - case s as STMT_WHILE(__) then algStmtWhile(s, context, &varDecls, &auxFunction) - case s as STMT_ASSERT(__) then algStmtAssert(s, context, &varDecls, &auxFunction) - case s as STMT_TERMINATE(__) then algStmtTerminate(s, context, &varDecls, &auxFunction) - case s as STMT_WHEN(__) then algStmtWhen(s, context, &varDecls, &auxFunction) - case s as STMT_BREAK(__) then 'break;<%\n%>' - case s as STMT_CONTINUE(__) then 'continue;<%\n%>' - case s as STMT_FAILURE(__) then algStmtFailure(s, context, &varDecls, &auxFunction) - case s as STMT_RETURN(__) then 'goto _return;<%\n%>' - case s as STMT_NORETCALL(__) then algStmtNoretcall(s, context, &varDecls, &auxFunction) - case s as STMT_REINIT(__) then algStmtReinit(s, context, &varDecls, &auxFunction) - else error(sourceInfo(), 'ALG_STATEMENT NYI')) - let () = System.tmpTickSetIndex(oldIndex,1) - << - <%modelicaLine(getElementSourceFileInfo(getStatementSource(stmt)))%><%res%> - <%endModelicaLine()%> - >> -end algStatement; - - -template algStmtAssign(DAE.Statement stmt, Context context, Text &varDecls, Text &auxFunction) - "Generates an assigment algorithm statement." -::= - match stmt - case STMT_ASSIGN(exp=CALL(path=IDENT(name="fail"))) then - '<%generateThrow()%><%\n%>' - case STMT_ASSIGN(exp1=CREF(componentRef=WILD(__)), exp=e) then - let &preExp = buffer "" - let expPart = daeExp(e, context, &preExp, &varDecls, &auxFunction) - << - <%preExp%> - >> - case STMT_ASSIGN(exp1=CREF(componentRef=cr as CREF_QUAL(identType=T_METATYPE(ty=t1 as T_METARECORD(__)), componentRef=cr2 as CREF_IDENT(__)),ty=t2)) then - let &preExp = buffer "" - let tmp = tempDecl("modelica_metatype",&varDecls) - let varPart = '_<%cr.ident%>' // So it only works in function context? - let expPart = daeExp(exp, context, &preExp, &varDecls, &auxFunction) - let indexInRecord = intAdd(1, lookupIndexInMetaRecord(t1.fields, cr2.ident)) - let len = intAdd(2, listLength(t1.fields)) - << - <%preExp%> - <%tmp%> = MMC_TAGPTR(mmc_alloc_words(<%len%>)); - memcpy(MMC_UNTAGPTR(<%tmp%>), MMC_UNTAGPTR(<%varPart%>), <%len%>*sizeof(modelica_metatype)); - ((modelica_metatype*)MMC_UNTAGPTR(<%tmp%>))[<%indexInRecord%>] = <%expPart%>; - <%varPart%> = <%tmp%>; - >> - case STMT_ASSIGN(exp1=CREF(ty = T_FUNCTION_REFERENCE_VAR(__))) - case STMT_ASSIGN(exp1=CREF(ty = T_FUNCTION_REFERENCE_FUNC(__))) then - let &preExp = buffer "" - let varPart = daeExpCrefLhs(exp1, context, &preExp, &varDecls, &auxFunction) - let expPart = daeExp(exp, context, &preExp, &varDecls, &auxFunction) - << - <%preExp%> - <%varPart%> = (modelica_fnptr) <%expPart%>; - >> - /* Records need to be traversed, assigning each component by itself */ - case STMT_ASSIGN(exp1=CREF(componentRef=cr,ty = ty as T_COMPLEX(varLst = varLst, complexClassType=RECORD(__)))) then - let &preExp = buffer "" - let rec = daeExp(exp, context, &preExp, &varDecls, &auxFunction) - let tmp = tempDecl(expTypeModelica(ty),&varDecls) - << - <%preExp%> - <%tmp%> = <%rec%>; - <% varLst |> var as TYPES_VAR(__) => - match var.ty - case T_ARRAY(__) then - copyArrayData(var.ty, '<%tmp%>._<%var.name%>', appendStringCref(var.name,cr), context, &preExp, &varDecls, &auxFunction) - else - let varPart = contextCref(appendStringCref(var.name,cr),context, &auxFunction) - '<%varPart%> = <%tmp%>._<%var.name%>;' - ; separator="\n" - %> - >> - case STMT_ASSIGN(exp1=CALL(path=path,expLst=expLst,attr=CALL_ATTR(ty= T_COMPLEX(varLst = varLst, complexClassType=RECORD(__))))) then - let &preExp = buffer "" - let rec = daeExp(exp, context, &preExp, &varDecls, &auxFunction) - << - <%preExp%> - <% varLst |> var as TYPES_VAR(__) hasindex i1 fromindex 1 => - let re = daeExp(listGet(expLst,i1), context, &preExp, &varDecls, &auxFunction) - '<%re%> = <%rec%>._<%var.name%>;' - ; separator="\n" - %> - >> - case STMT_ASSIGN(exp1=CREF(__)) then - let &preExp = buffer "" - let varPart = daeExpCrefLhs(exp1, context, &preExp, &varDecls, &auxFunction) - let expPart = daeExp(exp, context, &preExp, &varDecls, &auxFunction) - << - <%preExp%> - <%varPart%> = <%expPart%>; - >> - case STMT_ASSIGN(exp1=exp1 as ASUB(__),exp=val) then - (match expTypeFromExpShort(exp) - case "metatype" then - // MetaModelica Array - (match exp1 case ASUB(exp=arr, sub={idx}) then - let &preExp = buffer "" - let arr1 = daeExp(arr, context, &preExp, &varDecls, &auxFunction) - let idx1 = daeExp(idx, context, &preExp, &varDecls, &auxFunction) - let val1 = daeExp(val, context, &preExp, &varDecls, &auxFunction) - << - <%preExp%> - arrayUpdate(<%arr1%>,<%idx1%>,<%val1%>); - >>) - // Modelica Array - else - let &preExp = buffer "" - let varPart = daeExpAsub(exp1, context, &preExp, &varDecls, &auxFunction) - let expPart = daeExp(val, context, &preExp, &varDecls, &auxFunction) - << - <%preExp%> - <%varPart%> = <%expPart%>; - >> - ) - case STMT_ASSIGN(__) then - let &preExp = buffer "" - let expPart1 = daeExp(exp1, context, &preExp, &varDecls, &auxFunction) - let expPart2 = daeExp(exp, context, &preExp, &varDecls, &auxFunction) - << - <%preExp%> - <%expPart1%> = <%expPart2%>; - >> -end algStmtAssign; - - -template algStmtAssignArr(DAE.Statement stmt, Context context, - Text &varDecls, Text &auxFunction) - "Generates an array assigment algorithm statement." -::= -match stmt -case STMT_ASSIGN_ARR(lhs=lhsexp as CREF(componentRef=cr), exp=RANGE(__), type_=t) then - fillArrayFromRange(t,exp,cr,context,&varDecls,&auxFunction) - -case STMT_ASSIGN_ARR(lhs=lhsexp as CREF(componentRef=cr), exp=e, type_=t) then - let &preExp = buffer "" - let expPart = daeExp(e, context, &preExp, &varDecls, &auxFunction) - let assign = algStmtAssignArrWithRhsExpStr(lhsexp, expPart, context, &preExp, &varDecls, &auxFunction) - << - <%preExp%> - <%assign%> - >> -end algStmtAssignArr; - -template algStmtAssignWithRhsExpStr(DAE.Exp lhsexp, Text &rhsExpStr, Context context, - Text &preExp, Text &postExp, Text &varDecls, Text &auxFunction) - "Generates an array assigment algorithm statement." -::= -match lhsexp - case CREF(componentRef=WILD(__)) then - '<%rhsExpStr%>;' - case CREF(componentRef=cr, ty = T_ARRAY(ty=basety, dims=dims)) then - algStmtAssignArrWithRhsExpStr(lhsexp, rhsExpStr, context, &preExp, &varDecls, &auxFunction) - case CREF(componentRef = cr, ty=DAE.T_COMPLEX(complexClassType=RECORD(__))) then - algStmtAssignRecordWithRhsExpStr(lhsexp, rhsExpStr, context, &preExp, &varDecls, &auxFunction) - case CREF(__) then - let lhsStr = daeExpCrefLhs(lhsexp, context, &preExp, &varDecls, &auxFunction) - '<%lhsStr%> = <%rhsExpStr%>;' - - /*This CALL on left hand side case shouldn't have been created by the compiler. It only comes because of alias eliminations. On top of that - at least it should have been a record_constractor not a normal call. sigh. */ - case CALL(path=path,expLst=expLst,attr=CALL_ATTR(ty=ty as T_COMPLEX(varLst = varLst, complexClassType=RECORD(__)))) then - let tmp = tempDecl(expTypeModelica(ty),&varDecls) - /*TODO handle array record memebers. see algStmtAssign*/ - << - <%preExp%> - <%tmp%> = <%rhsExpStr%>; - <% varLst |> var as TYPES_VAR(__) hasindex i1 fromindex 1 => - let re = daeExp(listGet(expLst,i1), context, &preExp, &varDecls, &auxFunction) - '<%re%> = <%tmp%>._<%var.name%>;' - ; separator="\n" - %> - >> - /*TODO check*/ - case ARRAY(__) then - algStmtAssignArrWithRhsExpStr(lhsexp, rhsExpStr, context, &preExp, &varDecls, &auxFunction) - else - error(sourceInfo(), 'algStmtAssignWithRhsExpStr: Unhandled lhs expression. <%ExpressionDump.printExpStr(lhsexp)%>') -end algStmtAssignWithRhsExpStr; - -template algStmtAssignRecordWithRhsExpStr(DAE.Exp lhsexp, Text &rhsExpStr, Context context, - Text &preExp, Text &varDecls, Text &auxFunction) - "Generates an array assigment algorithm statement." -::= -match lhsexp - case CREF(componentRef = cr, ty=DAE.T_COMPLEX(varLst = varLst, complexClassType=RECORD(__))) then - let lhsStr = contextCref(cr, context, &auxFunction) - let tmp = tempDecl(expTypeModelica(ty),&varDecls) - /*TODO handle array record memebers. see algStmtAssign*/ - << - <%preExp%> - <%tmp%> = <%rhsExpStr%>; - <% varLst |> var as TYPES_VAR(__) hasindex i1 fromindex 0 => - '<%lhsStr%><%match context case FUNCTION_CONTEXT(__) then "._" else "$P"%><%var.name%> = <%tmp%>._<%var.name%>;' - ; separator="\n" - %> - >> -end algStmtAssignRecordWithRhsExpStr; - -template algStmtAssignArrWithRhsExpStr(DAE.Exp lhsexp, Text &rhsExpStr, Context context, - Text &preExp, Text &varDecls, Text &auxFunction) - "Generates an array assigment algorithm statement." -::= -match lhsexp - case CREF(componentRef=cr, ty = T_ARRAY(ty=basety, dims=dims)) then - let type = expTypeArray(ty) - if crefSubIsScalar(cr) then - let lhsStr = daeExpCrefLhs(lhsexp, context, &preExp, &varDecls, &auxFunction) - 'copy_<%type%>_data(<%rhsExpStr%>, &<%lhsStr%>);' - else - indexedAssign(lhsexp, rhsExpStr, context, &preExp, &varDecls, &auxFunction) -end algStmtAssignArrWithRhsExpStr; - -template fillArrayFromRange(DAE.Type ty, Exp exp, DAE.ComponentRef cr, Context context, - Text &varDecls, Text &auxFunction) - "Generates an array assigment to RANGE expressions. (Fills an array from range expresion)" -::= -match exp -case RANGE(__) then - let &preExp = buffer "" - let cref = contextArrayCref(cr, context) - let ty_str = expTypeArray(ty) - let start_exp = daeExp(start, context, &preExp, &varDecls, &auxFunction) - let stop_exp = daeExp(stop, context, &preExp, &varDecls, &auxFunction) - let step_exp = match step case SOME(stepExp) then daeExp(stepExp, context, &preExp, &varDecls, &auxFunction) else "1" - << - <%preExp%> - fill_<%ty_str%>_from_range(&<%cref%>, <%start_exp%>, <%step_exp%>, <%stop_exp%>);<%\n%> - >> - -end fillArrayFromRange; - -template indexedAssign(DAE.Exp lhs, String exp, Context context, - Text &preExp, Text &varDecls, Text &auxFunction) -::= - match lhs - case ecr as CREF(componentRef=cr, ty=T_ARRAY(ty=aty, dims=dims)) then - let arrayType = expTypeArray(ty) - let ispec = daeExpCrefIndexSpec(crefSubs(cr), context, &preExp, &varDecls, &auxFunction) - match context - case FUNCTION_CONTEXT(__) then - let cref = contextArrayCref(cr, context) - 'indexed_assign_<%arrayType%>(<%exp%>, &<%cref%>, &<%ispec%>);' - case PARALLEL_FUNCTION_CONTEXT(__) then - let cref = contextArrayCref(cr, context) - 'indexed_assign_<%arrayType%>(<%exp%>, &<%cref%>, &<%ispec%>);' - else - let type = expTypeShort(aty) - let wrapperArray = tempDecl(arrayType, &varDecls) - let dimsLenStr = listLength(crefDims(cr)) - let dimsValuesStr = (crefDims(cr) |> dim => dimension(dim) ;separator=", ") - let arrName = contextCref(crefStripSubs(cr), context,&auxFunction) - << - <%type%>_array_create(&<%wrapperArray%>, (modelica_<%type%>*)&<%arrName%>, <%dimsLenStr%>, <%dimsValuesStr%>);<%\n%> - indexed_assign_<%arrayType%>(<%exp%>, &<%wrapperArray%>, &<%ispec%>); - >> - else - error(sourceInfo(), 'indexedAssign simulationContext failed') -end indexedAssign; - -template copyArrayData(DAE.Type ty, String exp, DAE.ComponentRef cr, Context context, - Text &preExp, Text &varDecls, Text &auxFunction) -::= - let type = expTypeArray(ty) - let cref = contextArrayCref(cr, context) - match context - case FUNCTION_CONTEXT(__) then - 'copy_<%type%><%if dimensionsKnown(ty) then "_data" /* else we make allocate and copy data */%>(<%exp%>, &<%cref%>);' - case PARALLEL_FUNCTION_CONTEXT(__) then - 'copy_<%type%>_data(<%exp%>, &<%cref%>);' - else - 'copy_<%type%>_data_mem(<%exp%>, &<%cref%>);' -end copyArrayData; - -template algStmtTupleAssign(DAE.Statement stmt, Context context, Text &varDecls, Text &auxFunction) - "Generates a tuple assigment algorithm statement." -::= -match stmt - case STMT_TUPLE_ASSIGN(expExpLst={_}) then - error(sourceInfo(), "A tuple assignment of only one variable is a regular assignment") - - case STMT_TUPLE_ASSIGN(expExpLst = firstexp::_, exp = CALL(attr=CALL_ATTR(ty=T_TUPLE(types=ntys)))) then - let &preExp = buffer "" - let &postExp = buffer "" - - let lhsCrefs = (List.rest(expExpLst) |> e => " ," + tupleReturnVariableUpdates(e, context, varDecls, preExp, postExp, &auxFunction)) - // The tuple expressions might take fewer variables than the number of outputs. No worries. - let lhsCrefs2 = lhsCrefs + List.fill(", NULL", intMax(0,intSub(listLength(ntys),listLength(expExpLst)))) - - let call = daeExpCallTuple(exp, lhsCrefs2, context, &preExp, &varDecls, &auxFunction) - let callassign = algStmtAssignWithRhsExpStr(firstexp, call, context, &preExp, &postExp, &varDecls, &auxFunction) - << - /* tuple assignment <%expExpLst |> e => Util.escapeModelicaStringToCString(printExpStr(e)) ; separator=", "%>*/ - <%preExp%> - <%callassign%> - <%postExp%> - >> - - case STMT_TUPLE_ASSIGN(exp=MATCHEXPRESSION(__)) then - let &preExp = buffer "" - let prefix = 'tmp<%System.tmpTick()%>' - // get the current index of tmpMeta and reserve N=listLength(inputs) values in it! - let startIndexOutputs = '<%System.tmpTickIndexReserve(1, listLength(expExpLst))%>' - let _ = daeExpMatch2(exp, expExpLst, prefix, startIndexOutputs, context, &preExp, &varDecls, &auxFunction) - let lhsCrefs = (expExpLst |> crefexp as CREF(componentRef = cr) hasindex i0 fromindex 1 => - let rhsStr = getTempDeclMatchOutputName(expExpLst, prefix, startIndexOutputs, i0) - let lhsStr = contextCref(cr, context, &auxFunction) - << - <%lhsStr%> = <%rhsStr%>; - >> - ;separator="\n"; empty) - << - <%expExpLst |> crefexp hasindex i0 => - let typ = expTypeFromExpModelica(crefexp) - let decl = tempDeclMatchOutput(typ, prefix, startIndexOutputs, i0, &varDecls) - "" - ;separator="\n";empty%> - <%preExp%> - <%lhsCrefs%> - >> - else error(sourceInfo(), 'algStmtTupleAssign failed') - -end algStmtTupleAssign; - -template tupleReturnVariableUpdates(Exp inExp, Context context, Text &varDecls, Text &preExp, Text &varCopy, Text &auxFunction) - "Generates code for updating variables returned from fuctions that return tuples. - Generates copies depending on what kind of variable is returned." -::= - match inExp - case CREF(componentRef=WILD(__)) then - 'NULL' - case CREF(componentRef = cr, ty=DAE.T_COMPLEX(varLst = varLst, complexClassType=RECORD(__))) then - let rhsStr = tempDecl(expTypeArrayIf(ty), &varDecls) - let lhsStr = contextCref(cr, context, &auxFunction) - let &varCopy += - /*TODO handle array record memebers. see algStmtAssign*/ - << - <%preExp%> - <% varLst |> var as TYPES_VAR(__) hasindex i1 fromindex 0 => - '<%lhsStr%><%match context case FUNCTION_CONTEXT(__) then "._" else "$P"%><%var.name%> = <%rhsStr%>._<%var.name%>;' - ; separator="\n" - %> - >> /*varCopy end*/ - '&<%rhsStr%>' - - /*This CALL case shouldn't have been created by the compiler. It only comes because of alias eliminations. On top of that - at least it should have been a record_constractor not a normal call. sigh. */ - case CALL(path=path,expLst=expLst,attr=CALL_ATTR(ty=ty as T_COMPLEX(varLst = varLst, complexClassType=RECORD(__)))) then - let &preExp = buffer "" - let rhsStr = tempDecl(expTypeArrayIf(ty), &varDecls) - let tmp = tempDecl(expTypeModelica(ty),&varDecls) - let &varCopy += - /*TODO handle array record memebers. see algStmtAssign*/ - << - <%preExp%> - <% varLst |> var as TYPES_VAR(__) hasindex i1 fromindex 1 => - let re = daeExp(listGet(expLst,i1), context, &preExp, &varDecls, &auxFunction) - '<%re%> = <%rhsStr%>._<%var.name%>;' - ; separator="\n" - %> - >> /*varCopy end*/ - '&<%rhsStr%>' - case CREF(__) then - let res = daeExpCrefLhs(inExp, context, &preExp, &varDecls, &auxFunction) - if isArrayWithUnknownDimension(ty) - then - let &preExp += '<%res%>.dim_size = NULL;<%\n%>' - '&<%res%>' - else '&<%res%>' - else - error(sourceInfo(), 'tupleReturnVariableUpdates: Unhandled expression. <%ExpressionDump.printExpStr(inExp)%>') -end tupleReturnVariableUpdates; - -template algStmtIf(DAE.Statement stmt, Context context, Text &varDecls, Text &auxFunction) - "Generates an if algorithm statement." -::= -match stmt -case STMT_IF(__) then - let &preExp = buffer "" - let condExp = daeExp(exp, context, &preExp, &varDecls, &auxFunction) - << - <%preExp%> - if(<%condExp%>) - { - <%statementLst |> stmt => algStatement(stmt, context, &varDecls, &auxFunction) ;separator="\n"%> - } - <%elseExpr(else_, context, &varDecls, &auxFunction)%> - >> -end algStmtIf; - -template algStmtParForBody(DAE.Statement stmt, Context context, Text &varDecls, Text &auxFunction) - "Generates a for algorithm statement." -::= - match stmt - case s as STMT_PARFOR(range=rng as RANGE(__)) then - algStmtParForRangeBody(s, context, &varDecls, &auxFunction) - case s as STMT_PARFOR(__) then - algStmtForGeneric(s, context, &varDecls, &auxFunction) -end algStmtParForBody; - -template algStmtParForRangeBody(DAE.Statement stmt, Context context, Text &varDecls, Text &auxFunction) - "Generates a for algorithm statement where range is RANGE." -::= -match stmt -case STMT_PARFOR(range=rng as RANGE(__)) then - let iterName = contextIteratorName(iter, context) - let identType = expType(type_, iterIsArray) - let identTypeShort = expTypeShort(type_) - - let parforKernelName = 'parfor_<%System.tmpTickIndex(20 /* parfor */)%>' - - let &loopVarDecls = buffer "" - let body = (statementLst |> stmt => algStatement(stmt, context, &loopVarDecls, &auxFunction) - ;separator="\n") - - // Reconstruct array arguments to structures in the kernels - let &reconstrucedArrays = buffer "" - let _ = (loopPrlVars |> var => - reconstructKernelArraysFromLooptupleVars(var, &reconstrucedArrays) - ) - - let argStr = (loopPrlVars |> var => '<%parFunArgDefinitionFromLooptupleVar(var)%>' ;separator=", \n") - - << - - __kernel void <%parforKernelName%>( - modelica_integer loop_start, - modelica_integer loop_step, - modelica_integer loop_end, - <%argStr%>) - { - /* algStmtParForRangeBody : Thread managment for parfor loops */ - modelica_integer inner_start = (get_global_id(0) * loop_step) + (loop_start); - modelica_integer stride = get_global_size(0) * loop_step; - - for(modelica_integer <%iterName%> = (modelica_integer) inner_start; in_range_integer(<%iterName%>, loop_start, loop_end); <%iterName%> += stride) - { - /* algStmtParForRangeBody : Reconstruct Arrays */ - <%reconstrucedArrays%> - - /* algStmtParForRangeBody : locals */ - <%loopVarDecls%> - - <%body%> - } - } - >> -end algStmtParForRangeBody; - -template algStmtParForInterface(DAE.Statement stmt, Context context, Text &varDecls, Text &auxFunction) - "Generates a for algorithm statement." -::= - match stmt - case s as STMT_PARFOR(range=rng as RANGE(__)) then - algStmtParForRangeInterface(s, context, &varDecls, &auxFunction) - case s as STMT_PARFOR(__) then - algStmtForGeneric(s, context, &varDecls, &auxFunction) -end algStmtParForInterface; - -template algStmtParForRangeInterface(DAE.Statement stmt, Context context, Text &varDecls, Text &auxFunction) - "Generates a for algorithm statement where range is RANGE." -::= -match stmt -case STMT_PARFOR(range=rng as RANGE(__)) then - let identType = expType(type_, iterIsArray) - let identTypeShort = expTypeShort(type_) - let stmtStr = (statementLst |> stmt => algStatement(stmt, context, &varDecls, &auxFunction) - ;separator="\n") - algStmtParForRangeInterface_impl(rng, iter, identType, identTypeShort, loopPrlVars, stmtStr, context, &varDecls, &auxFunction) -end algStmtParForRangeInterface; - -template algStmtParForRangeInterface_impl(Exp range, Ident iterator, String type, String shortType, list> loopPrlVars, Text body, Context context, Text &varDecls, Text &auxFunction) - "The implementation of algStmtParForRangeInterface." -::= -match range -case RANGE(__) then - let iterName = contextIteratorName(iterator, context) - let startVar = tempDecl(type, &varDecls) - let stepVar = tempDecl(type, &varDecls) - let stopVar = tempDecl(type, &varDecls) - let &preExp = buffer "" - let startValue = daeExp(start, context, &preExp, &varDecls, &auxFunction) - let stepValue = match step case SOME(eo) then - daeExp(eo, context, &preExp, &varDecls, &auxFunction) - else - "(modelica_integer)1" - let stopValue = daeExp(stop, context, &preExp, &varDecls, &auxFunction) - - let cl_kernelVar = tempDecl("cl_kernel", &varDecls) - - let parforKernelName = 'parfor_<%System.tmpTickIndex(20 /* parfor */)%>' - - let kerArgNr = '<%parforKernelName%>_arg_nr' - - let &kernelArgSets = buffer "" - let _ = (loopPrlVars |> varTuple => - setKernelArgFormTupleLoopVars_ith(varTuple, &cl_kernelVar, &kerArgNr, &kernelArgSets, context) - ) - - << - <%preExp%> - <%startVar%> = <%startValue%>; <%stepVar%> = <%stepValue%>; <%stopVar%> = <%stopValue%>; - <%cl_kernelVar%> = ocl_create_kernel(omc_ocl_program, "<%parforKernelName%>"); - int <%kerArgNr%> = 0; - - ocl_set_kernel_arg(<%cl_kernelVar%>, <%kerArgNr%>, <%startVar%>); ++<%kerArgNr%>; <%\n%> - ocl_set_kernel_arg(<%cl_kernelVar%>, <%kerArgNr%>, <%stepVar%>); ++<%kerArgNr%>; <%\n%> - ocl_set_kernel_arg(<%cl_kernelVar%>, <%kerArgNr%>, <%stopVar%>); ++<%kerArgNr%>; <%\n%> - - <%kernelArgSets%> - - ocl_execute_kernel(<%cl_kernelVar%>); - clReleaseKernel(<%cl_kernelVar%>); - - - >> /* else we're looping over a zero-length range */ -end algStmtParForRangeInterface_impl; - - -template algStmtFor(DAE.Statement stmt, Context context, Text &varDecls, Text &auxFunction) - "Generates a for algorithm statement." -::= - match stmt - case s as STMT_FOR(range=rng as RANGE(__)) then - algStmtForRange(s, context, &varDecls, &auxFunction) - case s as STMT_FOR(__) then - algStmtForGeneric(s, context, &varDecls, &auxFunction) -end algStmtFor; - -template algStmtForRange(DAE.Statement stmt, Context context, Text &varDecls, Text &auxFunction) - "Generates a for algorithm statement where range is RANGE." -::= -match stmt -case STMT_FOR(range=rng as RANGE(__)) then - let identType = expType(type_, iterIsArray) - let identTypeShort = expTypeShort(type_) - let stmtStr = (statementLst |> stmt => algStatement(stmt, context, &varDecls, &auxFunction) - ;separator="\n") - algStmtForRange_impl(rng, iter, identType, identTypeShort, stmtStr, context, &varDecls, &auxFunction) -end algStmtForRange; - -template algStmtForRange_impl(Exp range, Ident iterator, String type, String shortType, Text body, Context context, Text &varDecls, Text &auxFunction) - "The implementation of algStmtForRange, which is also used by daeExpReduction." -::= -match range -case RANGE(__) then - let iterName = contextIteratorName(iterator, context) - let startVar = tempDecl(type, &varDecls) - let stepVar = tempDecl(type, &varDecls) - let stopVar = tempDecl(type, &varDecls) - let &preExp = buffer "" - let startValue = daeExp(start, context, &preExp, &varDecls, &auxFunction) - let stepValue = match step case SOME(eo) then - daeExp(eo, context, &preExp, &varDecls, &auxFunction) - else "1" - let stopValue = daeExp(stop, context, &preExp, &varDecls, &auxFunction) - let eqnsindx = match context case FUNCTION_CONTEXT(__) then '' else 'equationIndexes, ' - let AddionalFuncName = match context case FUNCTION_CONTEXT(__) then '' else '_withEquationIndexes' - << - <%preExp%> - <%startVar%> = <%startValue%>; <%stepVar%> = <%stepValue%>; <%stopVar%> = <%stopValue%>; - if(!<%stepVar%>) - { - FILE_INFO info = omc_dummyFileInfo; - omc_assert<%AddionalFuncName%>(threadData, info, <%eqnsindx%>"assertion range step != 0 failed"); - } - else if(!(((<%stepVar%> > 0) && (<%startVar%> > <%stopVar%>)) || ((<%stepVar%> < 0) && (<%startVar%> < <%stopVar%>)))) - { - <%type%> <%iterName%>; - for(<%iterName%> = <%startValue%>; in_range_<%shortType%>(<%iterName%>, <%startVar%>, <%stopVar%>); <%iterName%> += <%stepVar%>) - { - <%body%> - } - } - >> /* else we're looping over a zero-length range */ -end algStmtForRange_impl; - -template algStmtForGeneric(DAE.Statement stmt, Context context, Text &varDecls, Text &auxFunction) - "Generates a for algorithm statement where range is not RANGE." -::= -match stmt -case STMT_FOR(__) then - let iterType = match expType(type_, iterIsArray) - case "modelica_string" then "modelica_metatype" - case s then s - let arrayType = expTypeArray(type_) - let tvar = match iterType - case "modelica_metatype" - then tempDecl("modelica_metatype", &varDecls) - else tempDecl("int", &varDecls) - let stmtStr = (statementLst |> stmt => - algStatement(stmt, context, &varDecls, &auxFunction) ;separator="\n") - algStmtForGeneric_impl(range, iter, iterType, arrayType, iterIsArray, stmtStr, tvar, context, &varDecls, &auxFunction) -end algStmtForGeneric; - -template algStmtForGeneric_impl(Exp exp, Ident iterator, String type, - String arrayType, Boolean iterIsArray, Text &body, Text tvar, Context context, Text &varDecls, Text &auxFunction) - "The implementation of algStmtForGeneric, which is also used by daeExpReduction." -::= - let iterName = contextIteratorName(iterator, context) - let ivar = tempDecl(type, &varDecls) - let &preExp = buffer "" - let evar = daeExp(exp, context, &preExp, &varDecls, &auxFunction) - << - <%preExp%> - { - <%type%> <%iterName%>; - <% match type - case "modelica_metatype" then - (match typeof(exp) - case T_METATYPE(ty=T_METAARRAY(__)) then - let tmp = tempDecl("modelica_integer",&varDecls) - let len = tempDecl("modelica_integer",&varDecls) - << - for (<%tvar%> = <%evar%>, <%len%> = arrayLength(<%tvar%>), <%tmp%> = 1; <%tmp%> <= <%len%>; <%tmp%>++) - { - <%iterName%> = arrayGet(<%tvar%>,<%tmp%>); - <%body%> - } - >> - case T_METATYPE(ty=T_METALIST(__)) then - << - for (<%tvar%> = <%evar%>; !listEmpty(<%tvar%>); <%tvar%>=listRest(<%tvar%>)) - { - <%iterName%> = listHead(<%tvar%>); - <%body%> - } - >> - case ty then error(sourceInfo(), '<%unparseType(ty)%> iterator is not supported')) - else - let stmtStuff = if iterIsArray then - 'simple_index_alloc_<%type%>1(&<%evar%>, <%tvar%>, &<%ivar%>);' - else - '<%iterName%> = *(<%arrayType%>_element_addr1(&<%evar%>, 1, <%tvar%>));' - << - for(<%tvar%> = 1; <%tvar%> <= size_of_dimension_base_array(<%evar%>, 1); ++<%tvar%>) - { - <%stmtStuff%> - <%body%> - } - >> - %> - } - >> -end algStmtForGeneric_impl; - -template algStmtWhile(DAE.Statement stmt, Context context, Text &varDecls, Text &auxFunction) - "Generates a while algorithm statement." -::= -match stmt -case STMT_WHILE(__) then - let &preExp = buffer "" - let var = daeExp(exp, context, &preExp, &varDecls, &auxFunction) - << - while(1) - { - <%preExp%> - if(!<%var%>) break; - <%statementLst |> stmt => algStatement(stmt, context, &varDecls, &auxFunction) ;separator="\n"%> - } - >> -end algStmtWhile; - - -template algStmtAssert(DAE.Statement stmt, Context context, Text &varDecls, Text &auxFunction) - "Generates an assert algorithm statement." -::= -match stmt -case STMT_ASSERT(source=SOURCE(info=info)) then - assertCommon(cond, List.fill(msg,1), level, context, &varDecls, &auxFunction, info) -end algStmtAssert; - -template algStmtTerminate(DAE.Statement stmt, Context context, Text &varDecls, Text &auxFunction) - "Generates an assert algorithm statement." -::= -match stmt -case STMT_TERMINATE(__) then - let &preExp = buffer "" - let msgVar = daeExp(msg, context, &preExp, &varDecls, &auxFunction) - << - <%preExp%> - FILE_INFO info = {<%infoArgs(getElementSourceFileInfo(source))%>}; - omc_terminate(info, MMC_STRINGDATA(<%msgVar%>)); - >> -end algStmtTerminate; - -template algStmtFailure(DAE.Statement stmt, Context context, Text &varDecls, Text &auxFunction) - "Generates a failure() algorithm statement." -::= -match stmt -case STMT_FAILURE(__) then - let tmp = tempDecl("modelica_boolean", &varDecls) - let () = codegenPushTryThrowIndex(System.tmpTick()) - let goto = 'goto_<%codegenPeekTryThrowIndex()%>' - let stmtBody = (body |> stmt => - algStatement(stmt, context, &varDecls, &auxFunction) - ;separator="\n") - << - <%tmp%> = 0; /* begin failure */ - MMC_TRY_INTERNAL(mmc_jumper) - <%stmtBody%> - <%tmp%> = 1; - goto <%goto%>; - <%goto%>:; - MMC_CATCH_INTERNAL(mmc_jumper)<%let()=codegenPopTryThrowIndex() ""%> - if (<%tmp%>) {<%generateThrow()%>;} /* end failure */ - >> -end algStmtFailure; - -template algStmtNoretcall(DAE.Statement stmt, Context context, Text &varDecls, Text &auxFunction) - "Generates a no return call algorithm statement." -::= -match stmt -case STMT_NORETCALL(exp=DAE.MATCHEXPRESSION(__)) then - let &preExp = buffer "" - let expPart = daeExpMatch2(exp,listExpLength1,"","",context,&preExp,&varDecls, &auxFunction) - << - <%preExp%> - <%expPart%>; - >> -case STMT_NORETCALL(__) then - let &preExp = buffer "" - let expPart = daeExp(exp, context, &preExp, &varDecls, &auxFunction) - << - <%preExp%> - <% if isCIdentifier(expPart) then "" else '<%expPart%>;' %> - >> -end algStmtNoretcall; - -template algStmtWhen(DAE.Statement when, Context context, Text &varDecls, Text &auxFunction) - "Generates a when algorithm statement." -::= - match context - case SIMULATION_CONTEXT(__) then - match when - case STMT_WHEN(__) then - let helpIf = (conditions |> e => ' || (<%cref(e)%> && !$P$PRE<%cref(e)%> /* edge */)') - let statements = (statementLst |> stmt => - algStatement(stmt, context, &varDecls, &auxFunction) - ;separator="\n") - let initial_statements = match initialCall - case true then '<%statements%>' - else '; /* nothing to do */' - let else = algStatementWhenElse(elseWhen, &varDecls, &auxFunction) - << - if(data->simulationInfo.discreteCall == 1) - { - if(initial()) - { - <%initial_statements%> - } - else if(0<%helpIf%>) - { - <%statements%> - } - <%else%> - } - >> - end match - end match -end algStmtWhen; - - -template algStatementWhenElse(Option stmt, Text &varDecls, Text &auxFunction) - "Helper to algStmtWhen." -::= -match stmt -case SOME(when as STMT_WHEN(__)) then - let statements = (when.statementLst |> stmt => - algStatement(stmt, contextSimulationDiscrete, &varDecls, &auxFunction) - ;separator="\n") - let else = algStatementWhenElse(when.elseWhen, &varDecls, &auxFunction) - let elseCondStr = (when.conditions |> e => ' || (<%cref(e)%> && !$P$PRE<%cref(e)%> /* edge */)') - << - else if(0<%elseCondStr%>) - { - <%statements%> - } - <%else%> - >> -end algStatementWhenElse; - -template algStmtReinit(DAE.Statement stmt, Context context, Text &varDecls, Text &auxFunction) - "Generates an assigment algorithm statement." -::= - match stmt - case STMT_REINIT(__) then - let &preExp = buffer "" - let expPart1 = daeExp(var, context, &preExp, &varDecls, &auxFunction) - let expPart2 = daeExp(value, context, &preExp, &varDecls, &auxFunction) - << - <%preExp%> - <%expPart1%> = <%expPart2%>; - infoStreamPrint(LOG_EVENTS, 0, "reinit <%expPart1%> = %f", <%expPart1%>); - data->simulationInfo.needToIterate = 1; - >> -end algStmtReinit; - -template elseExpr(DAE.Else else_, Context context, Text &varDecls, Text &auxFunction) - "Helper to algStmtIf." - ::= - match else_ - case NOELSE(__) then - "" - case ELSEIF(__) then - let &preExp = buffer "" - let condExp = daeExp(exp, context, &preExp, &varDecls, &auxFunction) - << - else - { - <%preExp%> - if(<%condExp%>) - { - <%statementLst |> stmt => - algStatement(stmt, context, &varDecls, &auxFunction) - ;separator="\n"%> - } - <%elseExpr(else_, context, &varDecls, &auxFunction)%> - } - >> - case ELSE(__) then - - << - else - { - <%statementLst |> stmt => - algStatement(stmt, context, &varDecls, &auxFunction) - ;separator="\n"%> - } - >> -end elseExpr; - -/* public */ template daeExp(Exp exp, Context context, Text &preExp, Text &varDecls, Text &auxFunction) - "Generates code for an expression. - used in Compiler/Template/CodegenQSS.tpl" -::= - match exp - case e as ICONST(__) then '(modelica_integer) <%integer%>' /* Yes, we need to cast int to long on 64-bit arch... */ - case e as RCONST(__) then real - case e as SCONST(__) then daeExpSconst(string, &preExp, &varDecls) - case e as BCONST(__) then if bool then "1" else "0" - case e as ENUM_LITERAL(__) then index - case e as CREF(__) then daeExpCrefRhs(e, context, &preExp, &varDecls, &auxFunction) - case e as BINARY(__) then daeExpBinary(e, context, &preExp, &varDecls, &auxFunction) - case e as UNARY(__) then daeExpUnary(e, context, &preExp, &varDecls, &auxFunction) - case e as LBINARY(__) then daeExpLbinary(e, context, &preExp, &varDecls, &auxFunction) - case e as LUNARY(__) then daeExpLunary(e, context, &preExp, &varDecls, &auxFunction) - case e as RELATION(__) then daeExpRelation(e, context, &preExp, &varDecls, &auxFunction) - case e as IFEXP(__) then daeExpIf(e, context, &preExp, &varDecls, &auxFunction) - case e as CALL(__) then daeExpCall(e, context, &preExp, &varDecls, &auxFunction) - case e as RECORD(__) then daeExpRecord(e, context, &preExp, &varDecls, &auxFunction) - case e as PARTEVALFUNCTION(__)then daeExpPartEvalFunction(e, context, &preExp, &varDecls, &auxFunction) - case e as ARRAY(__) then daeExpArray(e, context, &preExp, &varDecls, &auxFunction) - case e as MATRIX(__) then daeExpMatrix(e, context, &preExp, &varDecls, &auxFunction) - case e as RANGE(__) then daeExpRange(e, context, &preExp, &varDecls, &auxFunction) - case e as CAST(__) then daeExpCast(e, context, &preExp, &varDecls, &auxFunction) - case e as ASUB(__) then daeExpAsub(e, context, &preExp, &varDecls, &auxFunction) - case e as TSUB(__) then daeExpTsub(e, context, &preExp, &varDecls, &auxFunction) - case e as SIZE(__) then daeExpSize(e, context, &preExp, &varDecls, &auxFunction) - case e as REDUCTION(__) then daeExpReduction(e, context, &preExp, &varDecls, &auxFunction) - case e as TUPLE(__) then daeExpTuple(e, context, &preExp, &varDecls, &auxFunction) - case e as LIST(__) then daeExpList(e, context, &preExp, &varDecls, &auxFunction) - case e as CONS(__) then daeExpCons(e, context, &preExp, &varDecls, &auxFunction) - case e as META_TUPLE(__) then daeExpMetaTuple(e, context, &preExp, &varDecls, &auxFunction) - case e as META_OPTION(__) then daeExpMetaOption(e, context, &preExp, &varDecls, &auxFunction) - case e as METARECORDCALL(__) then daeExpMetarecordcall(e, context, &preExp, &varDecls, &auxFunction) - case e as MATCHEXPRESSION(__) then daeExpMatch(e, context, &preExp, &varDecls, &auxFunction) - case e as BOX(__) then daeExpBox(e, context, &preExp, &varDecls, &auxFunction) - case e as UNBOX(__) then daeExpUnbox(e, context, &preExp, &varDecls, &auxFunction) - case e as SHARED_LITERAL(__) then daeExpSharedLiteral(e) - case e as SUM(__) then daeExpSum(e, context, &preExp, &varDecls, &auxFunction) - case e as CLKCONST(__) then '#error "<%ExpressionDump.printExpStr(e)%>"' - else error(sourceInfo(), 'Unknown expression: <%ExpressionDump.printExpStr(exp)%>') -end daeExp; - - -template daeExternalCExp(Exp exp, Context context, Text &preExp, Text &varDecls, Text &auxFunction) - "Like daeExp, but also converts the type to external C" -::= - match typeof(exp) - case T_ARRAY(__) then // Array-expressions - let shortTypeStr = expTypeShort(typeof(exp)) - '(<%extType(typeof(exp),true,true)%>) data_of_<%shortTypeStr%>_array(&<%daeExp(exp, context, &preExp, &varDecls, &auxFunction)%>)' - case T_STRING(__) then - let mstr = daeExp(exp, context, &preExp, &varDecls, &auxFunction) - 'MMC_STRINGDATA(<%mstr%>)' - else daeExp(exp, context, &preExp, &varDecls, &auxFunction) -end daeExternalCExp; - -template daeExternalF77Exp(Exp exp, Context context, Text &preExp, Text &varDecls, Text &auxFunction) - "Like daeExp, but also converts the type to external Fortran" -::= - match typeof(exp) - case T_ARRAY(__) then // Array-expressions - let shortTypeStr = expTypeShort(typeof(exp)) - '(<%extType(typeof(exp),true,true)%>) data_of_<%shortTypeStr%>_array(&<%daeExp(exp, context, &preExp, &varDecls, &auxFunction)%>)' - case T_STRING(__) then - let texp = daeExp(exp, contextFunction, &preExp, &varDecls, &auxFunction) - let tvar = tempDecl(expTypeFromExpFlag(exp,8),&varDecls) - let &preExp += '<%tvar%> = MMC_STRINGDATA(<%texp%>);<%\n%>' - '&<%tvar%>' - else - let texp = daeExp(exp, contextFunction, &preExp, &varDecls, &auxFunction) - let tvar = tempDecl(expTypeFromExpFlag(exp,8),&varDecls) - let &preExp += '<%tvar%> = <%texp%>;<%\n%>' - '&<%tvar%>' -end daeExternalF77Exp; - -template daeExpSconst(String string, Text &preExp, Text &varDecls) - "Generates code for a string constant." -::= - let escstr = Util.escapeModelicaStringToCString(string) - match stringLength(string) - case 0 then "(modelica_string) mmc_emptystring" - case 1 then '(modelica_string) mmc_strings_len1[<%stringGet(string, 1)%>]' - else - let tmp = 'tmp<%System.tmpTick()%>' - let &varDecls += 'static const MMC_DEFSTRINGLIT(<%tmp%>,<%unescapedStringLength(escstr)%>,"<%escstr%>");<%\n%>' - 'MMC_REFSTRINGLIT(<%tmp%>)' -end daeExpSconst; - - - -/********************************************************************* - ********************************************************************* - * RIGHT HAND SIDE - ********************************************************************* - *********************************************************************/ - - -template daeExpCrefRhs(Exp exp, Context context, Text &preExp, - Text &varDecls, Text &auxFunction) - "Generates code for a component reference on the right hand side of an - expression." -::= - match exp - case CREF(componentRef = cr, ty = T_FUNCTION_REFERENCE_FUNC(__)) then - 'boxvar_<%crefFunctionName(cr)%>' - case CREF(componentRef = cr, ty = T_FUNCTION_REFERENCE_VAR(__)) then - '((modelica_fnptr) _<%crefStr(cr)%>)' - case CREF(componentRef = cr as CREF_QUAL(subscriptLst={}, identType = T_METATYPE(ty=ty as T_METARECORD(__)), componentRef=cri as CREF_IDENT(__))) then - let offset = intAdd(findVarIndex(cri.ident,ty.fields),2) - '(MMC_FETCH(MMC_OFFSET(MMC_UNTAGPTR(_<%cr.ident%>), <%offset%>)))' - else - match context - case FUNCTION_CONTEXT(__) then daeExpCrefRhsFunContext(exp, context, &preExp, &varDecls, &auxFunction) - case PARALLEL_FUNCTION_CONTEXT(__) then daeExpCrefRhsFunContext(exp, context, &preExp, &varDecls, &auxFunction) - else daeExpCrefRhsSimContext(exp, context, &preExp, &varDecls, &auxFunction) -end daeExpCrefRhs; - -template daeExpCrefRhsSimContext(Exp ecr, Context context, Text &preExp, - Text &varDecls, Text &auxFunction) - "Generates code for a component reference in simulation context." -::= - match ecr - case ecr as CREF(componentRef = cr, ty = t as T_COMPLEX(complexClassType = EXTERNAL_OBJ(__))) then - contextCref(cr, context, &auxFunction) - - case ecr as CREF(componentRef = cr, ty = t as T_COMPLEX(complexClassType = record_state, varLst = var_lst)) then - let vars = var_lst |> v => (", " + daeExp(makeCrefRecordExp(cr,v), context, &preExp, &varDecls, &auxFunction)) - let record_type_name = underscorePath(ClassInf.getStateName(record_state)) - 'omc_<%record_type_name%>(threadData<%vars%>)' - - case ecr as CREF(componentRef=cr, ty=T_ARRAY(ty=aty, dims=dims)) then - let type = expTypeShort(aty) - let arrayType = type + "_array" - let wrapperArray = tempDecl(arrayType, &varDecls) - if crefSubIsScalar(cr) then - let dimsLenStr = listLength(dims) - let dimsValuesStr = (dims |> dim => dimension(dim) ;separator=", ") - let nosubname = contextCref(crefStripSubs(cr),context, &auxFunction) - let substring = (crefSubs(crefArrayGetFirstCref(cr)) |> INDEX(__) => - daeSubscriptExp(exp, context, &preExp, &varDecls, &auxFunction) - ;separator=", ") - let &preExp += '<%type%>_array_create(&<%wrapperArray%>, ((modelica_<%type%>*)&(<%nosubname%>_index(<%substring%>))), <%dimsLenStr%>, <%dimsValuesStr%>);<%\n%>' - wrapperArray - else - let dimsLenStr = listLength(crefDims(cr)) - let dimsValuesStr = (crefDims(cr) |> dim => dimension(dim) ;separator=", ") - let arrName = contextCref(crefStripSubs(cr), context,&auxFunction) - let &preExp += '<%type%>_array_create(&<%wrapperArray%>, (modelica_<%type%>*)&<%arrName%>, <%dimsLenStr%>, <%dimsValuesStr%>);<%\n%>' - let slicedArray = tempDecl(arrayType, &varDecls) - let spec1 = daeExpCrefIndexSpec(crefSubs(cr), context, &preExp, &varDecls, &auxFunction) - let &preExp += 'index_alloc_<%type%>_array(&<%wrapperArray%>, &<%spec1%>, &<%slicedArray%>);<%\n%>' - slicedArray - - case ecr as CREF(componentRef=cr, ty=ty) then - if crefIsScalarWithAllConstSubs(cr) then - let cast = match ty case T_INTEGER(__) then "(modelica_integer)" - case T_ENUMERATION(__) then "(modelica_integer)" //else "" - '<%cast%><%contextCref(cr,context, &auxFunction)%>' - else if crefIsScalarWithVariableSubs(cr) then - let nosubname = contextCref(crefStripSubs(cr),context, &auxFunction) - let substring = (crefSubs(cr) |> INDEX(__) => - daeSubscriptExp(exp, context, &preExp, &varDecls, &auxFunction) - ;separator=", ") - let cast = match ty case T_INTEGER(__) then "(modelica_integer)" - case T_ENUMERATION(__) then "(modelica_integer)" //else "" - '<%cast%><%nosubname%>_index(<%substring%>)' - else - error(sourceInfo(),'daeExpCrefRhsSimContext: UNHANDLED CREF: <%ExpressionDump.printExpStr(ecr)%>') -end daeExpCrefRhsSimContext; - -template daeExpCrefRhsFunContext(Exp ecr, Context context, Text &preExp, - Text &varDecls, Text &auxFunction) - "Generates code for a component reference." -::= - match ecr - case ecr as CREF(componentRef=cr, ty=ty) then - if crefIsScalar(cr, context) then - let cast = match ty case T_INTEGER(__) then "(modelica_integer)" - case T_ENUMERATION(__) then "(modelica_integer)" //else "" - '<%cast%><%contextCref(cr,context, &auxFunction)%>' - else - if crefSubIsScalar(cr) then - // The array subscript results in a scalar - let arrName = contextCref(crefStripLastSubs(cr), context, &auxFunction) - let arrayType = expTypeArray(ty) - let dimsLenStr = listLength(crefSubs(cr)) - let dimsValuesStr = (crefSubs(cr) |> INDEX(__) => - daeDimensionExp(exp, context, &preExp, &varDecls, &auxFunction) - ;separator=", ") - match cr - case CREF_IDENT(identType = T_METATYPE(ty = T_METAARRAY())) - case CREF_IDENT(identType = T_METAARRAY()) then - 'arrayGet(<%arrName%>, <%dimsValuesStr%>)' - else - match context - case FUNCTION_CONTEXT(__) then - match ty - case (T_ARRAY(ty = T_COMPLEX(complexClassType = record_state))) - case (T_COMPLEX(complexClassType = record_state)) then - let rec_name = '<%underscorePath(ClassInf.getStateName(record_state))%>' - << - (*((<%rec_name%>*)(generic_array_element_addr(&<%arrName%>, sizeof(<%rec_name%>), <%dimsLenStr%>, <%dimsValuesStr%>)))) - >> - else - << - (*<%arrayType%>_element_addr(&<%arrName%>, <%dimsLenStr%>, <%dimsValuesStr%>)) - >> - case PARALLEL_FUNCTION_CONTEXT(__) then - << - (*<%arrayType%>_element_addr_c99_<%dimsLenStr%>(&<%arrName%>, <%dimsLenStr%>, <%dimsValuesStr%>)) - >> - else - error(sourceInfo(),'This should have been handled in the new daeExpCrefRhsSimContext function. <%printExpStr(ecr)%>') - else - match context - case FUNCTION_CONTEXT(__) - case PARALLEL_FUNCTION_CONTEXT(__) then - // The array subscript denotes a slice - // let &preExp += '/* daeExpCrefRhsFunContext SLICE(<%ExpressionDump.printExpStr(ecr)%>) preExp */<%\n%>' - let arrName = contextArrayCref(cr, context) - let arrayType = expTypeArray(ty) - let tmp = tempDecl(arrayType, &varDecls) - let spec1 = daeExpCrefIndexSpec(crefSubs(cr), context, &preExp, &varDecls, &auxFunction) - let &preExp += 'index_alloc_<%arrayType%>(&<%arrName%>, &<%spec1%>, &<%tmp%>);<%\n%>' - tmp - else - error(sourceInfo(),'daeExpCrefRhsFunContext: Slice in simulation context: <%ExpressionDump.printExpStr(ecr)%>') - case ecr then - error(sourceInfo(),'daeExpCrefRhsFunContext: UNHANDLED EXPRESSION: <%ExpressionDump.printExpStr(ecr)%>') -end daeExpCrefRhsFunContext; - - -/********************************************************************* - ********************************************************************* - * LEFT HAND SIDE - ********************************************************************* - *********************************************************************/ - -template daeExpCrefLhs(Exp exp, Context context, Text &preExp, - Text &varDecls, Text &auxFunction) - "Generates code for a component reference on the left hand side of an expression." -::= - match exp - case CREF(componentRef = cr, ty = T_FUNCTION_REFERENCE_FUNC(__)) then - '((modelica_fnptr)boxptr_<%crefFunctionName(cr)%>)' - case CREF(componentRef = cr, ty = T_FUNCTION_REFERENCE_VAR(__)) then - '_<%crefStr(cr)%>' - else - match context - case FUNCTION_CONTEXT(__) then daeExpCrefLhsFunContext(exp, context, &preExp, &varDecls, &auxFunction) - case PARALLEL_FUNCTION_CONTEXT(__) then daeExpCrefLhsFunContext(exp, context, &preExp, &varDecls, &auxFunction) - else daeExpCrefLhsSimContext(exp, context, &preExp, &varDecls, &auxFunction) -end daeExpCrefLhs; - -template daeExpCrefLhsSimContext(Exp ecr, Context context, Text &preExp, - Text &varDecls, Text &auxFunction) - "Generates code for a component reference in simulation context." -::= - match ecr - case ecr as CREF(componentRef = cr, ty = t as T_COMPLEX(complexClassType = EXTERNAL_OBJ(__))) then - contextCref(cr, context, &auxFunction) - - case ecr as CREF(componentRef = cr, ty = t as T_COMPLEX(complexClassType = record_state, varLst = var_lst)) then - let vars = var_lst |> v => (", " + daeExp(makeCrefRecordExp(cr,v), context, &preExp, &varDecls, &auxFunction)) - let record_type_name = underscorePath(ClassInf.getStateName(record_state)) - // 'omc_<%record_type_name%>(threadData<%vars%>)' - error(sourceInfo(), 'daeExpCrefLhsSimContext got record <%crefStr(cr)%>. This does not make sense. Assigning to records is handled in a different way in the code generator, and reaching here is probably an error...') // '<%ret_var%>.c1' - - case ecr as CREF(componentRef=cr, ty=T_ARRAY(ty=aty, dims=dims)) then - let type = expTypeShort(aty) - let arrayType = type + "_array" - let wrapperArray = tempDecl(arrayType, &varDecls) - if crefSubIsScalar(cr) then - let dimsLenStr = listLength(dims) - let dimsValuesStr = (dims |> dim => dimension(dim) ;separator=", ") - let nosubname = contextCref(crefStripSubs(cr),context, &auxFunction) - let substring = (crefSubs(crefArrayGetFirstCref(cr)) |> INDEX(__) => - daeSubscriptExp(exp, context, &preExp, &varDecls, &auxFunction) - ;separator=", ") - let &preExp += '<%type%>_array_create(&<%wrapperArray%>, ((modelica_<%type%>*)&(<%nosubname%>_index(<%substring%>))), <%dimsLenStr%>, <%dimsValuesStr%>);<%\n%>' - wrapperArray - else - error(sourceInfo(),'daeExpCrefLhsSimContext: This should have been handled in indexed assign and should not have gotten here <%ExpressionDump.printExpStr(ecr)%>') - - - case ecr as CREF(componentRef=cr, ty=ty) then - if crefIsScalarWithAllConstSubs(cr) then - '<%contextCref(cr,context, &auxFunction)%>' - else if crefIsScalarWithVariableSubs(cr) then - let nosubname = contextCref(crefStripSubs(cr),context, &auxFunction) - let substring = (crefSubs(cr) |> INDEX(__) => - daeSubscriptExp(exp, context, &preExp, &varDecls, &auxFunction) - ;separator=", ") - '<%nosubname%>_index(<%substring%>)' - else - error(sourceInfo(),'daeExpCrefLhsSimContext: UNHANDLED CREF: <%ExpressionDump.printExpStr(ecr)%>') -end daeExpCrefLhsSimContext; - -template daeExpCrefLhsFunContext(Exp ecr, Context context, Text &preExp, - Text &varDecls, Text &auxFunction) - "Generates code for a component reference on the left hand side!" -::= - match ecr - case ecr as CREF(componentRef=cr, ty=ty) then - if crefIsScalar(cr, context) then - '<%contextCref(cr,context,&auxFunction)%>' - else - if crefSubIsScalar(cr) then - // The array subscript results in a scalar - let arrName = contextCref(crefStripLastSubs(cr), context, &auxFunction) - let arrayType = expTypeArray(ty) - let dimsLenStr = listLength(crefSubs(cr)) - let dimsValuesStr = (crefSubs(cr) |> INDEX(__) => - daeDimensionExp(exp, context, &preExp, &varDecls, &auxFunction) - ;separator=", ") - match context - case PARALLEL_FUNCTION_CONTEXT(__) then - << - (*<%arrayType%>_element_addr_c99_<%dimsLenStr%>(&<%arrName%>, <%dimsLenStr%>, <%dimsValuesStr%>)) - >> - case FUNCTION_CONTEXT(__) then - << - (*<%arrayType%>_element_addr(&<%arrName%>, <%dimsLenStr%>, <%dimsValuesStr%>)) - >> - else - error(sourceInfo(),'This should have been handled in the new daeExpCrefLhsSimContext function. <%printExpStr(ecr)%>') - - else - error(sourceInfo(),'This should have been handled in indexed assign and should not have gotten here. <%printExpStr(ecr)%>') - - case ecr then - error(sourceInfo(), 'SimCodeC.tpl template: daeExpCrefLhsFunContext: UNHANDLED EXPRESSION: <%ExpressionDump.printExpStr(ecr)%>') -end daeExpCrefLhsFunContext; - -template daeExpCrefIndexSpec(list subs, Context context, - Text &preExp, Text &varDecls, Text &auxFunction) - "Generates index lists for crefs involving slices" -::= - let nridx_str = listLength(subs) - let idx_str = (subs |> sub => - match sub - case INDEX(__) then - let expPart = daeExp(exp, context, &preExp, &varDecls, &auxFunction) - let str = <<(0), make_index_array(1, (int) <%expPart%>), 'S'>> - str - case WHOLEDIM(__) then - let str = <<(1), (int*)0, 'W'>> - str - case SLICE(__) then - let expPart = daeExp(exp, context, &preExp, &varDecls, &auxFunction) - let tmp = tempDecl("modelica_integer", &varDecls) - let &preExp += '<%tmp%> = size_of_dimension_base_array(<%expPart%>, 1);<%\n%>' - let str = <<(int) <%tmp%>, integer_array_make_index_array(&<%expPart%>), 'A'>> - str - ;separator=", ") - let tmp = tempDecl("index_spec_t", &varDecls) - let &preExp += 'create_index_spec(&<%tmp%>, <%nridx_str%>, <%idx_str%>);<%\n%>' - tmp -end daeExpCrefIndexSpec; - - -/********************************************************************* - ********************************************************************* - * DONE RHS and LHS - ********************************************************************* - *********************************************************************/ - - -template daeExpBinary(Exp exp, Context context, Text &preExp, - Text &varDecls, Text &auxFunction) - "Generates code for a binary expression." -::= - -match exp -case BINARY(__) then - let e1 = daeExp(exp1, context, &preExp, &varDecls, &auxFunction) - let e2 = daeExp(exp2, context, &preExp, &varDecls, &auxFunction) - match operator - case ADD(ty = T_STRING(__)) then - let tmpStr = tempDecl("modelica_metatype", &varDecls) - let &preExp += '<%tmpStr%> = stringAppend(<%e1%>,<%e2%>);<%\n%>' - tmpStr - case ADD(__) then '(<%e1%> + <%e2%>)' - case SUB(__) then '(<%e1%> - <%e2%>)' - case MUL(__) then '(<%e1%> * <%e2%>)' - case DIV(__) then - let tvar = tempDecl(expTypeModelica(ty),&varDecls) - let &preExp += '<%tvar%> = <%e2%>;<%\n%>' - let &preExp += - if acceptMetaModelicaGrammar() - then 'if (<%tvar%> == 0) {<%generateThrow()%>;}<%\n%>' - else 'if (<%tvar%> == 0) {throwStreamPrint(threadData, "Division by zero %s", "<%Util.escapeModelicaStringToCString(printExpStr(exp))%>");}<%\n%>' - '(<%e1%> / <%e2%>)' - case POW(__) then - if isHalf(exp2) then - (let tmp = tempDecl(expTypeFromExpModelica(exp1),&varDecls) - let ass = '(<%tmp%> >= 0.0)' - let &preExpMsg = buffer "" - let retPre = assertCommonVar(ass,'"Model error: Argument of sqrt(<%Util.escapeModelicaStringToCString(printExpStr(exp1))%>) was %g should be >= 0", <%tmp%>', context, &preExpMsg, &varDecls, dummyInfo) - let &preExp += '<%tmp%> = <%e1%>; <%\n%><%retPre%>' - 'sqrt(<%tmp%>)') - else match realExpIntLit(exp2) - case SOME(2) then - let tmp = tempDecl("modelica_real", &varDecls) - let &preExp += '<%tmp%> = <%e1%>;<%\n%>' - '(<%tmp%> * <%tmp%>)' - case SOME(3) then - let tmp = tempDecl("modelica_real", &varDecls) - let &preExp += '<%tmp%> = <%e1%>;<%\n%>' - '(<%tmp%> * <%tmp%> * <%tmp%>)' - case SOME(4) then - let tmp = tempDecl("modelica_real", &varDecls) - let &preExp += '<%tmp%> = <%e1%>;<%\n%>' - let &preExp += '<%tmp%> *= <%tmp%>;<%\n%>' - '(<%tmp%> * <%tmp%>)' - case SOME(i) then 'real_int_pow(threadData, <%e1%>, <%i%>)' - else 'pow(<%e1%>, <%e2%>)' - case UMINUS(__) then daeExpUnary(exp, context, &preExp, &varDecls, &auxFunction) - case ADD_ARR(__) then - let type = match ty case T_ARRAY(ty=T_INTEGER(__)) then "integer_array" - case T_ARRAY(ty=T_ENUMERATION(__)) then "integer_array" - else "real_array" - 'add_alloc_<%type%>(<%e1%>, <%e2%>)' - case SUB_ARR(__) then - let type = match ty case T_ARRAY(ty=T_INTEGER(__)) then "integer_array" - case T_ARRAY(ty=T_ENUMERATION(__)) then "integer_array" - else "real_array" - 'sub_alloc_<%type%>(<%e1%>, <%e2%>)' - case MUL_ARR(__) then - let type = match ty case T_ARRAY(ty=T_INTEGER(__)) then "integer_array" - case T_ARRAY(ty=T_ENUMERATION(__)) then "integer_array" - else "real_array" - 'mul_alloc_<%type%>(<%e1%>, <%e2%>)' - case DIV_ARR(__) then - let type = match ty case T_ARRAY(ty=T_INTEGER(__)) then "integer_array" - case T_ARRAY(ty=T_ENUMERATION(__)) then "integer_array" - else "real_array" - 'div_alloc_<%type%>(<%e1%>, <%e2%>)' - case MUL_ARRAY_SCALAR(__) then - let type = match ty case T_ARRAY(ty=T_INTEGER(__)) then "integer_array" - case T_ARRAY(ty=T_ENUMERATION(__)) then "integer_array" - else "real_array" - 'mul_alloc_<%type%>_scalar(<%e1%>, <%e2%>)' - case ADD_ARRAY_SCALAR(__) then error(sourceInfo(),'Code generation does not support ADD_ARRAY_SCALAR <%printExpStr(exp)%>') - case SUB_SCALAR_ARRAY(__) then error(sourceInfo(),'Code generation does not support SUB_SCALAR_ARRAY <%printExpStr(exp)%>') - case MUL_SCALAR_PRODUCT(__) then - let type = match ty case T_ARRAY(ty=T_INTEGER(__)) then "integer_scalar" - case T_ARRAY(ty=T_ENUMERATION(__)) then "integer_scalar" - case T_INTEGER(__) then "integer_scalar" - case T_ENUMERATION(__) then "integer_scalar" - else "real_scalar" - 'mul_<%type%>_product(<%e1%>, <%e2%>)' - case MUL_MATRIX_PRODUCT(__) then - let typeShort = match ty case T_ARRAY(ty=T_INTEGER(__)) then "integer" - case T_ARRAY(ty=T_ENUMERATION(__)) then "integer" - else "real" - let type = '<%typeShort%>_array' - 'mul_alloc_<%typeShort%>_matrix_product_smart(<%e1%>, <%e2%>)' - case DIV_ARRAY_SCALAR(__) then - let type = match ty case T_ARRAY(ty=T_INTEGER(__)) then "integer_array" - case T_ARRAY(ty=T_ENUMERATION(__)) then "integer_array" - else "real_array" - 'div_alloc_<%type%>_scalar(<%e1%>, <%e2%>)' - case DIV_SCALAR_ARRAY(__) then - let type = match ty case T_ARRAY(ty = T_INTEGER(__)) then "integer_array" - case T_ARRAY(ty = T_ENUMERATION(__)) then "integer_array" - else "real_array" - 'div_alloc_scalar_<%type%>(<%e1%>, <%e2%>)' - case POW_ARRAY_SCALAR(__) then - let type = match ty case T_ARRAY(ty = T_INTEGER(__)) then "integer_array" - case T_ARRAY(ty = T_ENUMERATION(__)) then "integer_array" - else "real_array" - 'pow_alloc_<%type%>_scalar(<%e1%>, <%e2%>)' - case POW_ARRAY_SCALAR(__) then 'daeExpBinary:ERR for POW_ARRAY_SCALAR' - case POW_SCALAR_ARRAY(__) then 'daeExpBinary:ERR for POW_SCALAR_ARRAY' - case POW_ARR(__) then 'daeExpBinary:ERR for POW_ARR' - case POW_ARR2(__) then 'daeExpBinary:ERR for POW_ARR2' - else error(sourceInfo(), 'daeExpBinary:ERR') -end daeExpBinary; - - -template daeExpUnary(Exp exp, Context context, Text &preExp, - Text &varDecls, Text &auxFunction) - "Generates code for a unary expression." -::= -match exp -case UNARY(__) then - let e = daeExp(exp, context, &preExp, &varDecls, &auxFunction) - match operator - case UMINUS(__) then '(-<%e%>)' - case UMINUS_ARR(ty=T_ARRAY(ty=T_REAL(__))) then - let var = tempDecl("real_array", &varDecls) - let &preExp += 'usub_alloc_real_array(<%e%>,&<%var%>);<%\n%>' - '<%var%>' - case UMINUS_ARR(ty=T_ARRAY(ty=T_INTEGER(__))) then - let var = tempDecl("integer_array", &varDecls) - let &preExp += 'usub_alloc_integer_array(<%e%>,&<%var%>);<%\n%>' - '<%var%>' - case UMINUS_ARR(__) then error(sourceInfo(),"unary minus for non-real arrays not implemented") - else error(sourceInfo(),"daeExpUnary:ERR") -end daeExpUnary; - - -template daeExpLbinary(Exp exp, Context context, Text &preExp, - Text &varDecls, Text &auxFunction) - "Generates code for a logical binary expression." -::= -match exp -case LBINARY(__) then - let e1 = daeExp(exp1, context, &preExp, &varDecls, &auxFunction) - let e2 = daeExp(exp2, context, &preExp, &varDecls, &auxFunction) - match operator - case AND(ty = T_ARRAY(__)) then - let var = tempDecl("boolean_array", &varDecls) - let &preExp += 'and_boolean_array(&<%e1%>,&<%e2%>,&<%var%>);<%\n%>' - '<%var%>' - case AND(__) then - '(<%e1%> && <%e2%>)' - case OR(ty = T_ARRAY(__)) then - let var = tempDecl("boolean_array", &varDecls) - let &preExp += 'or_boolean_array(&<%e1%>,&<%e2%>,&<%var%>);<%\n%>' - '<%var%>' - case OR(__) then - '(<%e1%> || <%e2%>)' - else error(sourceInfo(),"daeExpLbinary:ERR") -end daeExpLbinary; - - -template daeExpLunary(Exp exp, Context context, Text &preExp, - Text &varDecls, Text &auxFunction) - "Generates code for a logical unary expression." -::= -match exp -case LUNARY(__) then - let e = daeExp(exp, context, &preExp, &varDecls, &auxFunction) - match operator - case NOT(ty = T_ARRAY(__)) then - let var = tempDecl("boolean_array", &varDecls) - let &preExp += 'not_boolean_array(<%e%>,&<%var%>);<%\n%>' - '<%var%>' - else - '(!<%e%>)' -end daeExpLunary; - - -template daeExpRelation(Exp exp, Context context, Text &preExp, - Text &varDecls, Text &auxFunction) - "Generates code for a relation expression." -::= -match exp -case rel as RELATION(__) then - let &varDecls2 = buffer "" - let &preExp2 = buffer "" - let simRel = daeExpRelationSim(rel, context, &preExp2, &varDecls2, &auxFunction) - if simRel then - /* Don't add the allocated temp-var unless it is used */ - let &varDecls += varDecls2 - let &preExp += preExp2 - simRel - else - let e1 = daeExp(rel.exp1, context, &preExp, &varDecls, &auxFunction) - let e2 = daeExp(rel.exp2, context, &preExp, &varDecls, &auxFunction) - match rel.operator - - case LESS(ty = T_BOOL(__)) then '(!<%e1%> && <%e2%>)' - case LESS(ty = T_STRING(__)) then '(stringCompare(<%e1%>, <%e2%>) < 0)' - case LESS(ty = T_INTEGER(__)) then '(<%e1%> < <%e2%>)' - case LESS(ty = T_REAL(__)) then '(<%e1%> < <%e2%>)' - case LESS(ty = T_ENUMERATION(__)) then '(<%e1%> < <%e2%>)' - - case GREATER(ty = T_BOOL(__)) then '(<%e1%> && !<%e2%>)' - case GREATER(ty = T_STRING(__)) then '(stringCompare(<%e1%>, <%e2%>) > 0)' - case GREATER(ty = T_INTEGER(__)) then '(<%e1%> > <%e2%>)' - case GREATER(ty = T_REAL(__)) then '(<%e1%> > <%e2%>)' - case GREATER(ty = T_ENUMERATION(__)) then '(<%e1%> > <%e2%>)' - - case LESSEQ(ty = T_BOOL(__)) then '(!<%e1%> || <%e2%>)' - case LESSEQ(ty = T_STRING(__)) then '(stringCompare(<%e1%>, <%e2%>) <= 0)' - case LESSEQ(ty = T_INTEGER(__)) then '(<%e1%> <= <%e2%>)' - case LESSEQ(ty = T_REAL(__)) then '(<%e1%> <= <%e2%>)' - case LESSEQ(ty = T_ENUMERATION(__)) then '(<%e1%> <= <%e2%>)' - - case GREATEREQ(ty = T_BOOL(__)) then '(<%e1%> || !<%e2%>)' - case GREATEREQ(ty = T_STRING(__)) then '(stringCompare(<%e1%>, <%e2%>) >= 0)' - case GREATEREQ(ty = T_INTEGER(__)) then '(<%e1%> >= <%e2%>)' - case GREATEREQ(ty = T_REAL(__)) then '(<%e1%> >= <%e2%>)' - case GREATEREQ(ty = T_ENUMERATION(__)) then '(<%e1%> >= <%e2%>)' - - case EQUAL(ty = T_BOOL(__)) then '((!<%e1%> && !<%e2%>) || (<%e1%> && <%e2%>))' - case EQUAL(ty = T_STRING(__)) then '(stringEqual(<%e1%>, <%e2%>))' - case EQUAL(ty = T_INTEGER(__)) then '(<%e1%> == <%e2%>)' - case EQUAL(ty = T_REAL(__)) then '(<%e1%> == <%e2%>)' - case EQUAL(ty = T_ENUMERATION(__)) then '(<%e1%> == <%e2%>)' - case EQUAL(ty = T_ARRAY(__)) then '<%e2%>' /* Used for Boolean array. Called from daeExpLunary. */ - - case NEQUAL(ty = T_BOOL(__)) then '((!<%e1%> && <%e2%>) || (<%e1%> && !<%e2%>))' - case NEQUAL(ty = T_STRING(__)) then '(!stringEqual(<%e1%>, <%e2%>))' - case NEQUAL(ty = T_INTEGER(__)) then '(<%e1%> != <%e2%>)' - case NEQUAL(ty = T_REAL(__)) then '(<%e1%> != <%e2%>)' - case NEQUAL(ty = T_ENUMERATION(__)) then '(<%e1%> != <%e2%>)' - - else error(sourceInfo(), 'daeExpRelation <%printExpStr(exp)%>') -end daeExpRelation; - - - -template daeExpRelationSim(Exp exp, Context context, Text &preExp, - Text &varDecls, Text &auxFunction) - "Helper to daeExpRelation." -::= -match exp -case rel as RELATION(__) then - match context - case SIMULATION_CONTEXT(__) then - match rel.optionExpisASUB - case NONE() then - let e1 = daeExp(rel.exp1, context, &preExp, &varDecls, &auxFunction) - let e2 = daeExp(rel.exp2, context, &preExp, &varDecls, &auxFunction) - let res = tempDecl("modelica_boolean", &varDecls) - if intEq(rel.index,-1) then - match rel.operator - case LESS(__) then - let &preExp += '<%res%> = Less(<%e1%>,<%e2%>);<%\n%>' - res - case LESSEQ(__) then - let &preExp += '<%res%> = LessEq(<%e1%>,<%e2%>);<%\n%>' - res - case GREATER(__) then - let &preExp += '<%res%> = Greater(<%e1%>,<%e2%>);<%\n%>' - res - case GREATEREQ(__) then - let &preExp += '<%res%> = GreaterEq(<%e1%>,<%e2%>);<%\n%>' - res - end match - else - let isReal = if isRealType(typeof(rel.exp1)) then (if isRealType(typeof(rel.exp2)) then 'true' else '') else '' - let hysteresisfunction = if isReal then 'RELATIONHYSTERESIS' else 'RELATION' - match rel.operator - case LESS(__) then - let &preExp += '<%hysteresisfunction%>(<%res%>, <%e1%>, <%e2%>, <%rel.index%>, Less);<%\n%>' - res - case LESSEQ(__) then - let &preExp += '<%hysteresisfunction%>(<%res%>, <%e1%>, <%e2%>, <%rel.index%>, LessEq);<%\n%>' - res - case GREATER(__) then - let &preExp += '<%hysteresisfunction%>(<%res%>, <%e1%>, <%e2%>, <%rel.index%>, Greater);<%\n%>' - res - case GREATEREQ(__) then - let &preExp += '<%hysteresisfunction%>(<%res%>, <%e1%>, <%e2%>, <%rel.index%>, GreaterEq);<%\n%>' - res - end match - case SOME((exp,i,j)) then - let e1 = daeExp(rel.exp1, context, &preExp, &varDecls, &auxFunction) - let e2 = daeExp(rel.exp2, context, &preExp, &varDecls, &auxFunction) - let iterator = daeExp(exp, context, &preExp, &varDecls, &auxFunction) - let res = tempDecl("modelica_boolean", &varDecls) - if intEq(rel.index,-1) then - match rel.operator - case LESS(__) then - let &preExp += '<%res%> = Less(<%e1%>,<%e2%>);<%\n%>' - res - case LESSEQ(__) then - let &preExp += '<%res%> = LessEq(<%e1%>,<%e2%>);<%\n%>' - res - case GREATER(__) then - let &preExp += '<%res%> = Greater(<%e1%>,<%e2%>);<%\n%>' - res - case GREATEREQ(__) then - let &preExp += '<%res%> = GreaterEq(<%e1%>,<%e2%>);<%\n%>' - res - end match - else - let isReal = if isRealType(typeof(rel.exp1)) then (if isRealType(typeof(rel.exp2)) then 'true' else '') else '' - let hysteresisfunction = if isReal then 'RELATIONHYSTERESIS' else 'RELATION' - match rel.operator - case LESS(__) then - let &preExp += '<%hysteresisfunction%>(<%res%>, <%e1%>, <%e2%>, <%rel.index%> + (<%iterator%> - <%i%>)/<%j%>, Less);<%\n%>' - res - case LESSEQ(__) then - let &preExp += '<%hysteresisfunction%>(<%res%>, <%e1%>, <%e2%>, <%rel.index%> + (<%iterator%> - <%i%>)/<%j%>, LessEq);<%\n%>' - res - case GREATER(__) then - let &preExp += '<%hysteresisfunction%>(<%res%>, <%e1%>, <%e2%>, <%rel.index%> + (<%iterator%> - <%i%>)/<%j%>, Greater);<%\n%>' - res - case GREATEREQ(__) then - let &preExp += '<%hysteresisfunction%>(<%res%>, <%e1%>, <%e2%>, <%rel.index%> + (<%iterator%> - <%i%>)/<%j%>, GreaterEq);<%\n%>' - res - end match - end match - case ZEROCROSSINGS_CONTEXT(__) then - match rel.optionExpisASUB - case NONE() then - let e1 = daeExp(rel.exp1, context, &preExp, &varDecls, &auxFunction) - let e2 = daeExp(rel.exp2, context, &preExp, &varDecls, &auxFunction) - let res = tempDecl("modelica_boolean", &varDecls) - if intEq(rel.index,-1) then - match rel.operator - case LESS(__) then - let &preExp += '<%res%> = Less(<%e1%>,<%e2%>);<%\n%>' - res - case LESSEQ(__) then - let &preExp += '<%res%> = LessEq(<%e1%>,<%e2%>);<%\n%>' - res - case GREATER(__) then - let &preExp += '<%res%> = Greater(<%e1%>,<%e2%>);<%\n%>' - res - case GREATEREQ(__) then - let &preExp += '<%res%> = GreaterEq(<%e1%>,<%e2%>);<%\n%>' - res - end match - else - let isReal = if isRealType(typeof(rel.exp1)) then (if isRealType(typeof(rel.exp2)) then 'true' else '') else '' - match rel.operator - case LESS(__) then - let hysteresisfunction = if isReal then 'LessZC(<%e1%>, <%e2%>, data->simulationInfo.storedRelations[<%rel.index%>])' else 'Less(<%e1%>,<%e2%>)' - let &preExp += '<%res%> = <%hysteresisfunction%>;<%\n%>' - res - case LESSEQ(__) then - let hysteresisfunction = if isReal then 'LessEqZC(<%e1%>, <%e2%>, data->simulationInfo.storedRelations[<%rel.index%>])' else 'LessEq(<%e1%>,<%e2%>)' - let &preExp += '<%res%> = <%hysteresisfunction%>;<%\n%>' - res - case GREATER(__) then - let hysteresisfunction = if isReal then 'GreaterZC(<%e1%>, <%e2%>, data->simulationInfo.storedRelations[<%rel.index%>])' else 'Greater(<%e1%>,<%e2%>)' - let &preExp += '<%res%> = <%hysteresisfunction%>;<%\n%>' - res - case GREATEREQ(__) then - let hysteresisfunction = if isReal then 'GreaterEqZC(<%e1%>, <%e2%>, data->simulationInfo.storedRelations[<%rel.index%>])' else 'GreaterEq(<%e1%>,<%e2%>)' - let &preExp += '<%res%> = <%hysteresisfunction%>;<%\n%>' - res - end match - case SOME((exp,i,j)) then - let e1 = daeExp(rel.exp1, context, &preExp, &varDecls, &auxFunction) - let e2 = daeExp(rel.exp2, context, &preExp, &varDecls, &auxFunction) - let res = tempDecl("modelica_boolean", &varDecls) - if intEq(rel.index,-1) then - match rel.operator - case LESS(__) then - let &preExp += '<%res%> = Less(<%e1%>,<%e2%>);<%\n%>' - res - case LESSEQ(__) then - let &preExp += '<%res%> = LessEq(<%e1%>,<%e2%>);<%\n%>' - res - case GREATER(__) then - let &preExp += '<%res%> = Greater(<%e1%>,<%e2%>);<%\n%>' - res - case GREATEREQ(__) then - let &preExp += '<%res%> = GreaterEq(<%e1%>,<%e2%>);<%\n%>' - res - end match - else - let isReal = if isRealType(typeof(rel.exp1)) then (if isRealType(typeof(rel.exp2)) then 'true' else '') else '' - match rel.operator - case LESS(__) then - let hysteresisfunction = if isReal then 'LessZC(<%e1%>, <%e2%>, data->simulationInfo.storedRelations[<%rel.index%>])' else 'Less(<%e1%>,<%e2%>)' - let &preExp += '<%res%> = <%hysteresisfunction%>;<%\n%>' - res - case LESSEQ(__) then - let hysteresisfunction = if isReal then 'LessEqZC(<%e1%>, <%e2%>, data->simulationInfo.storedRelations[<%rel.index%>])' else 'LessEq(<%e1%>,<%e2%>)' - let &preExp += '<%res%> = <%hysteresisfunction%>;<%\n%>' - res - case GREATER(__) then - let hysteresisfunction = if isReal then 'GreaterZC(<%e1%>, <%e2%>, data->simulationInfo.storedRelations[<%rel.index%>])' else 'Greater(<%e1%>,<%e2%>)' - let &preExp += '<%res%> = <%hysteresisfunction%>;<%\n%>' - res - case GREATEREQ(__) then - let hysteresisfunction = if isReal then 'GreaterEqZC(<%e1%>, <%e2%>, data->simulationInfo.storedRelations[<%rel.index%>])' else 'GreaterEq(<%e1%>,<%e2%>)' - let &preExp += '<%res%> = <%hysteresisfunction%>;<%\n%>' - res - end match - end match - end match -end match -end daeExpRelationSim; - -template daeExpIf(Exp exp, Context context, Text &preExp, - Text &varDecls, Text &auxFunction) - "Generates code for an if expression." -::= -match exp -case IFEXP(__) then - let condExp = daeExp(expCond, context, &preExp, &varDecls, &auxFunction) - let &preExpThen = buffer "" - let eThen = daeExp(expThen, context, &preExpThen, &varDecls, &auxFunction) - let &preExpElse = buffer "" - let eElse = daeExp(expElse, context, &preExpElse, &varDecls, &auxFunction) - let shortIfExp = if preExpThen then "" else if preExpElse then "" else if isArrayType(typeof(exp)) then "" else "x" - (if shortIfExp - then - // Safe to do if eThen and eElse don't emit pre-expressions - '(<%condExp%>?<%eThen%>:<%eElse%>)' - else - let condVar = tempDecl("modelica_boolean", &varDecls) - let resVar = tempDeclTuple(typeof(exp), &varDecls) - let &preExp += - << - <%condVar%> = (modelica_boolean)<%condExp%>; - if(<%condVar%>) - { - <%preExpThen%> - <%if eThen then resultVarAssignment(typeof(exp),resVar,eThen)%> - } - else - { - <%preExpElse%> - <%if eElse then resultVarAssignment(typeof(exp),resVar,eElse)%> - }<%\n%> - >> - resVar) -end daeExpIf; - -template daeExpSum(Exp exp, Context context, Text &preExp, - Text &varDecls, Text &auxFunction) - "Generates code for an if expression." -::= -match exp -case SUM(__) then - let start = printExpStr(startIt) - let &anotherPre = buffer "" - let stop = printExpStr(endIt) - let bodyStr = daeExpIteratedCref(body) - let summationVar = <> - let iterVar = printExpStr(iterator) - let &preExp +=<< - - modelica_integer $P<%iterVar%> = 0; // the iterator - modelica_real <%summationVar%> = 0.0; //the sum - for($P<%iterVar%> = <%start%>; $P<%iterVar%> < <%stop%>; $P<%iterVar%>++) - { - <%summationVar%> += <%bodyStr%>($P<%iterVar%>); - } - - >> - summationVar -end daeExpSum; - -template daeExpIteratedCref(Exp exp) -::= -match exp -case (CREF(__)) then - let subs = (crefSubs(componentRef) |> sub => subscriptToCStr(sub) ; separator=",") - <<<%iteratedCrefStr(componentRef)%>_index>> -end daeExpIteratedCref; - -template iteratedCrefStr(ComponentRef cref) -::= -match cref -case (CREF_IDENT(__)) then - <<$P<%ident%>>> -case (CREF_QUAL(__)) then - <<$P<%ident%><%iteratedCrefStr(componentRef)%>>> -end iteratedCrefStr; - - -template resultVarAssignment(DAE.Type ty, Text lhs, Text rhs) "Tuple need to be considered" -::= -match ty -case T_TUPLE(__) then - (types |> t hasindex i1 fromindex 1 => '<%lhs%>.c<%i1%> = <%rhs%>.c<%i1%>;' ; separator="\n") -else - '<%lhs%> = <%rhs%>;' -end resultVarAssignment; - -template daeExpRecord(Exp rec, Context context, Text &preExp, Text &varDecls, Text &auxFunction) -::= - match rec - case RECORD(__) then - let name = tempDecl(underscorePath(path), &varDecls) - let ass = threadTuple(exps,comp) |> (exp,compn) => '<%name%>._<%compn%> = <%daeExp(exp, context, &preExp, &varDecls, &auxFunction)%>;<%\n%>' - let &preExp += ass - name -end daeExpRecord; - -template daeExpPartEvalFunction(Exp exp, Context context, Text &preExp, Text &varDecls, Text &auxFunction) -::= - match exp - case PARTEVALFUNCTION(ty=T_FUNCTION_REFERENCE_VAR(functionType = t as T_FUNCTION(__)),origType=T_FUNCTION_REFERENCE_VAR(functionType = orig as T_FUNCTION(functionAttributes=attr as FUNCTION_ATTRIBUTES(__), source={name}))) then - let &varDeclInner = buffer "" - let &ret = buffer "" - let retInput = match t.funcResultType - case T_TUPLE(types=_::tys) then - (tys |> ty => - let name = 'tmp<%System.tmpTick()%>' - let &ret += ', <%name%>' - ', <%expTypeArrayIf(ty)%> <%name%>') - let func = 'closure<%System.tmpTickIndex(2/*auxFunction*/)%>_<%underscorePath(name)%>' - let return = match t.funcResultType case T_NORETCALL(__) then "" else "return " - let closure = tempDecl("modelica_metatype",&varDecls) - let createClosure = (expList |> e => ', <%daeExp(e,context,&preExp,&varDecls,&auxFunction)%>') + (if attr.isFunctionPointer then ', _<%underscorePath(name)%>') - let &preExp += '<%closure%> = mmc_mk_box<%if attr.isFunctionPointer then daeExpMetaHelperBoxStart(incrementInt(listLength(expList),1)) else daeExpMetaHelperBoxStart(listLength(expList))%>0<%createClosure%>);<%\n%>' - let &auxFunction += - << - static <%match t.funcResultType case T_NORETCALL(__) then "void" else "modelica_metatype"%> <%func%>(threadData_t *thData, modelica_metatype closure<%t.funcArg |> a as FUNCARG(__) => ', <%expTypeArrayIf(a.ty)%> <%a.name%>'%><%retInput%>) - { - <%varDeclInner%> - <%setDifference(orig.funcArg,t.funcArg) |> a as FUNCARG(__) hasindex i1 fromindex 1 => '<%expTypeArrayIf(a.ty)%> <%a.name%> = MMC_FETCH(MMC_OFFSET(MMC_UNTAGPTR(closure),<%i1%>));<%\n%>'%> - <% - if attr.isFunctionPointer then - let fname = '_<%underscorePath(name)%>' - let func = '(MMC_FETCH(MMC_OFFSET(MMC_UNTAGPTR(<%fname%>), 1)))' - let typeCast1 = generateTypeCastFromType(orig, true) - let typeCast2 = generateTypeCastFromType(orig, false) - << - modelica_fnptr <%fname%> = MMC_FETCH(MMC_OFFSET(MMC_UNTAGPTR(closure),<%incrementInt(listLength(setDifference(orig.funcArg,t.funcArg)),1)%>)); - if (MMC_FETCH(MMC_OFFSET(MMC_UNTAGPTR(<%fname%>),2))) { - <%return%> (<%typeCast1%> <%func%>) (thData, MMC_FETCH(MMC_OFFSET(MMC_UNTAGPTR(<%fname%>),2))<%orig.funcArg |> a as FUNCARG(__) => ', <%a.name%>'%><%ret%>); - } else { /* No closure in the called variable */ - <%return%> (<%typeCast2%> <%func%>) (thData<%orig.funcArg |> a as FUNCARG(__) => ', <%a.name%>'%><%ret%>); - } - >> - else - '<%return%>boxptr_<%underscorePath(name)%>(thData<%orig.funcArg |> a as FUNCARG(__) => ', <%a.name%>'%><%ret%>);' - %> - } - >> - '(modelica_fnptr) mmc_mk_box2(0,<%func%>,<%closure%>)' - // error(sourceInfo(), 'PARTEVALFUNCTION: <%ExpressionDump.printExpStr(exp)%>, ty=<%unparseType(ty)%>, origType=<%unparseType(origType)%>') - case PARTEVALFUNCTION(__) then - error(sourceInfo(), 'PARTEVALFUNCTION: <%ExpressionDump.printExpStr(exp)%>, ty=<%unparseType(ty)%>, origType=<%unparseType(origType)%>') -end daeExpPartEvalFunction; - -template daeExpCall(Exp call, Context context, Text &preExp, Text &varDecls, Text &auxFunction) - "Generates code for a function call." -::= - match call - // special builtins - case CALL(path=IDENT(name="smooth"), - expLst={e1, e2}) then - let var1 = daeExp(e1, context, &preExp, &varDecls, &auxFunction) - let var2 = daeExp(e2, context, &preExp, &varDecls, &auxFunction) - '<%var2%>' - - case CALL(path=IDENT(name="DIVISION"), - expLst={e1, e2}) then - let var1 = daeExp(e1, context, &preExp, &varDecls, &auxFunction) - let var2 = daeExp(e2, context, &preExp, &varDecls, &auxFunction) - let var3 = Util.escapeModelicaStringToCString(printExpStr(e2)) - (match context - case FUNCTION_CONTEXT(__) then - 'DIVISION(<%var1%>,<%var2%>,"<%var3%>")' - else - 'DIVISION_SIM(<%var1%>,<%var2%>,"<%var3%>",equationIndexes)' - ) - - case CALL(attr=CALL_ATTR(ty=ty), - path=IDENT(name="DIVISION_ARRAY_SCALAR"), - expLst={e1, e2}) then - let type = match ty case T_ARRAY(ty=T_INTEGER(__)) then "integer_array" - case T_ARRAY(ty=T_ENUMERATION(__)) then "integer_array" - else "real_array" - let var1 = daeExp(e1, context, &preExp, &varDecls, &auxFunction) - let var2 = daeExp(e2, context, &preExp, &varDecls, &auxFunction) - let var3 = Util.escapeModelicaStringToCString(printExpStr(e2)) - 'division_alloc_<%type%>_scalar(threadData,<%var1%>,<%var2%>,"<%var3%>")' - - case exp as CALL(attr=CALL_ATTR(ty=ty), path=IDENT(name="DIVISION_ARRAY_SCALAR")) then - error(sourceInfo(),'Code generation does not support <%printExpStr(exp)%>') - - case CALL(path=IDENT(name="der"), expLst={arg as CREF(__)}) then - '$P$DER<%cref(arg.componentRef)%>' - case CALL(path=IDENT(name="der"), expLst={exp}) then - error(sourceInfo(), 'Code generation does not support der(<%printExpStr(exp)%>)') - case CALL(path=IDENT(name="pre"), expLst={arg}) then - daeExpCallPre(arg, context, preExp, varDecls, &auxFunction) - // a $_start is used to get get start value of a variable - case CALL(path=IDENT(name="$_start"), expLst={arg}) then - daeExpCallStart(arg, context, preExp, varDecls, &auxFunction) - // a $_initialGuess is used to get initial guess for nonlinear solver - case CALL(path=IDENT(name="$_initialGuess"), expLst={arg as CREF(__)}) then - let namestr = cref(arg.componentRef) - '( <%namestr%>)' // - case CALL(path=IDENT(name="$_old"), expLst={arg as CREF(__)}) then - let namestr = cref(arg.componentRef) - '( _<%namestr%>(1))' // - // if arg >= 0 then 1 else -1 - case CALL(path=IDENT(name="$_signNoNull"), expLst={e1}) then - let var1 = daeExp(e1, context, &preExp, &varDecls, &auxFunction) - '(<%var1%> >= 0.0 ? 1.0:-1.0)' - // numerical der() - case CALL(path=IDENT(name="$_DF$DER"), expLst={arg as CREF(__)}) then - let namestr = cref(arg.componentRef) - '($P<%BackendDAE.symEulerDT%> == 0.0 ? $P$DER<%namestr%> : (<%namestr%> - _<%namestr%>(1))/$P<%BackendDAE.symEulerDT%>)' - // round - case CALL(path=IDENT(name="$_round"), expLst={e1}) then - let var1 = daeExp(e1, context, &preExp, &varDecls, &auxFunction) - '((modelica_integer)round((modelica_real)<%var1%>))' - case CALL(path=IDENT(name="edge"), expLst={arg as CREF(__)}) then - '(<%cref(arg.componentRef)%> && !$P$PRE<%cref(arg.componentRef)%>)' - case CALL(path=IDENT(name="edge"), expLst={LUNARY(exp = arg as CREF(__))}) then - '(!<%cref(arg.componentRef)%> && $P$PRE<%cref(arg.componentRef)%>)' - case CALL(path=IDENT(name="edge"), expLst={exp}) then - error(sourceInfo(), 'Code generation does not support edge(<%printExpStr(exp)%>)') - case CALL(path=IDENT(name="change"), expLst={arg as CREF(__)}) then - '(<%cref(arg.componentRef)%> != $P$PRE<%cref(arg.componentRef)%>)' - case CALL(path=IDENT(name="change"), expLst={exp}) then - error(sourceInfo(), 'Code generation does not support change(<%printExpStr(exp)%>)') - case CALL(path=IDENT(name="cardinality"), expLst={exp}) then - error(sourceInfo(), 'Code generation does not support cardinality(<%printExpStr(exp)%>). It should have been handled somewhere else in the compiler.') - - case CALL(path=IDENT(name="print"), expLst={e1}) then - let var1 = daeExp(e1, context, &preExp, &varDecls, &auxFunction) - 'fputs(MMC_STRINGDATA(<%var1%>),stdout)' - - case CALL(path=IDENT(name="max"), attr=CALL_ATTR(ty = T_REAL(__)), expLst={e1,e2}) then - let var1 = daeExp(e1, context, &preExp, &varDecls, &auxFunction) - let var2 = daeExp(e2, context, &preExp, &varDecls, &auxFunction) - 'fmax(<%var1%>,<%var2%>)' - - case CALL(path=IDENT(name="max"), expLst={e1,e2}) then - let var1 = daeExp(e1, context, &preExp, &varDecls, &auxFunction) - let var2 = daeExp(e2, context, &preExp, &varDecls, &auxFunction) - 'modelica_integer_max((modelica_integer)<%var1%>,(modelica_integer)<%var2%>)' - - case CALL(path=IDENT(name="sum"), attr=CALL_ATTR(ty = ty), expLst={e}) then - let arr = daeExp(e, context, &preExp, &varDecls, &auxFunction) - let ty_str = '<%expTypeArray(ty)%>' - 'sum_<%ty_str%>(<%arr%>)' - - case CALL(path=IDENT(name="min"), attr=CALL_ATTR(ty = T_REAL(__)), expLst={e1,e2}) then - let var1 = daeExp(e1, context, &preExp, &varDecls, &auxFunction) - let var2 = daeExp(e2, context, &preExp, &varDecls, &auxFunction) - 'fmin(<%var1%>,<%var2%>)' - - case CALL(path=IDENT(name="min"), expLst={e1,e2}) then - let var1 = daeExp(e1, context, &preExp, &varDecls, &auxFunction) - let var2 = daeExp(e2, context, &preExp, &varDecls, &auxFunction) - 'modelica_integer_min((modelica_integer)<%var1%>,(modelica_integer)<%var2%>)' - - case CALL(path=IDENT(name="abs"), expLst={e1}, attr=CALL_ATTR(ty = T_INTEGER(__))) then - let var1 = daeExp(e1, context, &preExp, &varDecls, &auxFunction) - 'labs(<%var1%>)' - - case CALL(path=IDENT(name="abs"), expLst={e1}) then - let var1 = daeExp(e1, context, &preExp, &varDecls, &auxFunction) - 'fabs(<%var1%>)' - - case CALL(path=IDENT(name="sqrt"), expLst={e1}, attr=attr as CALL_ATTR(__)) then - let argStr = daeExp(e1, context, &preExp, &varDecls, &auxFunction) - (if isPositiveOrZero(e1) - then - 'sqrt(<%argStr%>)' - else - let tmp = tempDecl(expTypeFromExpModelica(e1),&varDecls) - let ass = '(<%tmp%> >= 0.0)' - let &preExpMsg = buffer "" - let retPre = assertCommonVar(ass,'"Model error: Argument of sqrt(<%Util.escapeModelicaStringToCString(printExpStr(e1))%>) was %g should be >= 0", <%tmp%>', context, &preExpMsg, &varDecls, dummyInfo) - let &preExp += '<%tmp%> = <%argStr%>; <%\n%><%retPre%>' - 'sqrt(<%tmp%>)') - - case CALL(path=IDENT(name="log"), expLst={e1}, attr=attr as CALL_ATTR(__)) then - let argStr = daeExp(e1, context, &preExp, &varDecls, &auxFunction) - let tmp = tempDecl(expTypeFromExpModelica(e1),&varDecls) - let ass = '(<%tmp%> > 0.0)' - let &preExpMsg = buffer "" - let retPre = assertCommonVar(ass,'"Model error: Argument of log(<%Util.escapeModelicaStringToCString(printExpStr(e1))%>) was %g should be > 0", <%tmp%>', context, &preExpMsg, &varDecls, dummyInfo) - let &preExp += '<%tmp%> = <%argStr%>;<%retPre%>' - 'log(<%tmp%>)' - - case CALL(path=IDENT(name="log10"), expLst={e1}, attr=attr as CALL_ATTR(__)) then - let argStr = daeExp(e1, context, &preExp, &varDecls, &auxFunction) - let tmp = tempDecl(expTypeFromExpModelica(e1),&varDecls) - let ass = '(<%tmp%> > 0.0)' - let &preExpMsg = buffer "" - let retPre = assertCommonVar(ass,'"Model error: Argument of log10(<%Util.escapeModelicaStringToCString(printExpStr(e1))%>) was %g should be > 0", <%tmp%>', context, &preExpMsg, &varDecls, dummyInfo) - let &preExp += '<%tmp%> = <%argStr%>;<%retPre%>' - 'log10(<%tmp%>)' - - case CALL(path=IDENT(name="acos"), expLst={e1}, attr=attr as CALL_ATTR(__)) then - let argStr = daeExp(e1, context, &preExp, &varDecls, &auxFunction) - let tmp = tempDecl("modelica_real",&varDecls) - let ass = '(<%tmp%> >= -1.0 && <%tmp%> <= 1.0)' - let &preExpMsg = buffer "" - let retPre = assertCommonVar(ass,'"Model error: Argument of <%Util.escapeModelicaStringToCString(printExpStr(call))%> outside the domain -1.0 <= %g <= 1.0", <%tmp%>', context, &preExpMsg, &varDecls, dummyInfo) - let &preExp += '<%tmp%> = <%argStr%>;<%retPre%>' - 'acos(<%tmp%>)' - - case CALL(path=IDENT(name="asin"), expLst={e1}, attr=attr as CALL_ATTR(__)) then - let argStr = daeExp(e1, context, &preExp, &varDecls, &auxFunction) - let tmp = tempDecl("modelica_real",&varDecls) - let ass = '(<%tmp%> >= -1.0 && <%tmp%> <= 1.0)' - let &preExpMsg = buffer "" - let retPre = assertCommonVar(ass,'"Model error: Argument of <%Util.escapeModelicaStringToCString(printExpStr(call))%> outside the domain -1.0 <= %g <= 1.0", <%tmp%>', context, &preExpMsg, &varDecls, dummyInfo) - let &preExp += '<%tmp%> = <%argStr%>;<%retPre%>' - 'asin(<%tmp%>)' - - /* Begin code generation of event triggering math functions */ - - case CALL(path=IDENT(name="div"), expLst={e1,e2, index}, attr=CALL_ATTR(ty = ty)) then - let var1 = daeExp(e1, context, &preExp, &varDecls, &auxFunction) - let var2 = daeExp(e2, context, &preExp, &varDecls, &auxFunction) - let constIndex = daeExp(index, context, &preExp, &varDecls, &auxFunction) - '_event_div_<%expTypeShort(ty)%>(<%var1%>, <%var2%>, <%constIndex%>, data)' - - case CALL(path=IDENT(name="integer"), expLst={inExp,index}) then - let exp = daeExp(inExp, context, &preExp, &varDecls, &auxFunction) - let constIndex = daeExp(index, context, &preExp, &varDecls, &auxFunction) - '(_event_integer(<%exp%>, <%constIndex%>, data))' - - case CALL(path=IDENT(name="floor"), expLst={inExp,index}, attr=CALL_ATTR(ty = ty)) then - let exp = daeExp(inExp, context, &preExp, &varDecls, &auxFunction) - let constIndex = daeExp(index, context, &preExp, &varDecls, &auxFunction) - '((modelica_<%expTypeShort(ty)%>)_event_floor(<%exp%>, <%constIndex%>, data))' - - case CALL(path=IDENT(name="ceil"), expLst={inExp,index}, attr=CALL_ATTR(ty = ty)) then - let exp = daeExp(inExp, context, &preExp, &varDecls, &auxFunction) - let constIndex = daeExp(index, context, &preExp, &varDecls, &auxFunction) - '((modelica_<%expTypeShort(ty)%>)_event_ceil(<%exp%>, <%constIndex%>, data))' - - /* end codegeneration of event triggering math functions */ - - case CALL(path=IDENT(name="integer"), expLst={inExp}) then - let exp = daeExp(inExp, context, &preExp, &varDecls, &auxFunction) - '((modelica_integer)floor(<%exp%>))' - - case CALL(path=IDENT(name="div"), expLst={e1,e2}, attr=CALL_ATTR(ty = T_INTEGER(__))) then - let var1 = daeExp(e1, context, &preExp, &varDecls, &auxFunction) - let var2 = daeExp(e2, context, &preExp, &varDecls, &auxFunction) - let tvar = tempDecl("modelica_integer", &varDecls) - let &preExp += '<%tvar%> = <%var2%>;<%\n%>' - let &preExp += - if acceptMetaModelicaGrammar() - then 'if (<%tvar%> == 0) {<%generateThrow()%>;}<%\n%>' - else 'if (<%tvar%> == 0) {throwStreamPrint(threadData, "Division by zero %s", "<%Util.escapeModelicaStringToCString(printExpStr(call))%>");}<%\n%>' - 'ldiv(<%var1%>,<%tvar%>).quot' - - case CALL(path=IDENT(name="div"), expLst={e1,e2}) then - let var1 = daeExp(e1, context, &preExp, &varDecls, &auxFunction) - let var2 = daeExp(e2, context, &preExp, &varDecls, &auxFunction) - let tvar = tempDecl("modelica_real", &varDecls) - let &preExp += '<%tvar%> = <%var2%>;<%\n%>' - let &preExp += - if acceptMetaModelicaGrammar() - then 'if (<%tvar%> == 0.0) {<%generateThrow()%>;}<%\n%>' - else 'if (<%tvar%> == 0.0) {throwStreamPrint(threadData, "Division by zero %s", "<%Util.escapeModelicaStringToCString(printExpStr(call))%>");}<%\n%>' - 'trunc(<%var1%>/<%var2%>)' - - case CALL(path=IDENT(name="mod"), expLst={e1,e2}, attr=CALL_ATTR(ty = ty)) then - let var1 = daeExp(e1, context, &preExp, &varDecls, &auxFunction) - let var2 = daeExp(e2, context, &preExp, &varDecls, &auxFunction) - 'modelica_mod_<%expTypeShort(ty)%>(<%var1%>,<%var2%>)' - - case CALL(path=IDENT(name="max"), attr=CALL_ATTR(ty = ty), expLst={array}) then - let expVar = daeExp(array, context, &preExp, &varDecls, &auxFunction) - let arr_tp_str = '<%expTypeArray(ty)%>' - let tvar = tempDecl(expTypeModelica(ty), &varDecls) - let &preExp += '<%tvar%> = max_<%arr_tp_str%>(<%expVar%>);<%\n%>' - '<%tvar%>' - - case CALL(path=IDENT(name="min"), attr=CALL_ATTR(ty = ty), expLst={array}) then - let expVar = daeExp(array, context, &preExp, &varDecls, &auxFunction) - let arr_tp_str = '<%expTypeArray(ty)%>' - let tvar = tempDecl(expTypeModelica(ty), &varDecls) - let &preExp += '<%tvar%> = min_<%arr_tp_str%>(<%expVar%>);<%\n%>' - '<%tvar%>' - - case CALL(path=IDENT(name="fill"), expLst=val::dims, attr=CALL_ATTR(ty = ty)) then - let valExp = daeExp(val, context, &preExp, &varDecls, &auxFunction) - let dimsExp = (dims |> dim => - daeExp(dim, context, &preExp, &varDecls, &auxFunction) ;separator=", ") - let ty_str = '<%expTypeArray(ty)%>' - let tvar = tempDecl(ty_str, &varDecls) - let &preExp += 'fill_alloc_<%ty_str%>(&<%tvar%>, <%valExp%>, <%listLength(dims)%>, <%dimsExp%>);<%\n%>' - '<%tvar%>' - - case call as CALL(path=IDENT(name="vector")) then - error(sourceInfo(),'vector() call does not have a C implementation <%printExpStr(call)%>') - - case CALL(path=IDENT(name="cat"), expLst=dim::arrays, attr=CALL_ATTR(ty = ty)) then - let dim_exp = daeExp(dim, context, &preExp, &varDecls, &auxFunction) - let arrays_exp = (arrays |> array => - daeExp(array, context, &preExp, &varDecls, &auxFunction) ;separator=", &") - let ty_str = '<%expTypeArray(ty)%>' - let tvar = tempDecl(ty_str, &varDecls) - let &preExp += 'cat_alloc_<%ty_str%>(<%dim_exp%>, &<%tvar%>, <%listLength(arrays)%>, &<%arrays_exp%>);<%\n%>' - '<%tvar%>' - - case CALL(path=IDENT(name="promote"), expLst={A, n}) then - let var1 = daeExp(A, context, &preExp, &varDecls, &auxFunction) - let var2 = daeExp(n, context, &preExp, &varDecls, &auxFunction) - let arr_tp_str = '<%expTypeFromExpArray(A)%>' - let tvar = tempDecl(arr_tp_str, &varDecls) - let &preExp += 'promote_alloc_<%arr_tp_str%>(&<%var1%>, <%var2%>, &<%tvar%>);<%\n%>' - '<%tvar%>' - - case CALL(path=IDENT(name="transpose"), expLst={A}) then - let var1 = daeExp(A, context, &preExp, &varDecls, &auxFunction) - let arr_tp_str = '<%expTypeFromExpArray(A)%>' - let tvar = tempDecl(arr_tp_str, &varDecls) - let &preExp += 'transpose_alloc_<%arr_tp_str%>(&<%var1%>, &<%tvar%>);<%\n%>' - '<%tvar%>' - - case CALL(path=IDENT(name="symmetric"), expLst={A}) then - let var1 = daeExp(A, context, &preExp, &varDecls, &auxFunction) - let arr_tp_str = '<%expTypeFromExpArray(A)%>' - let tvar = tempDecl(arr_tp_str, &varDecls) - let &preExp += 'symmetric_<%arr_tp_str%>(&<%var1%>, &<%tvar%>);<%\n%>' - '<%tvar%>' - - case CALL(path=IDENT(name="skew"), expLst={A}) then - let var1 = daeExp(A, context, &preExp, &varDecls, &auxFunction) - let arr_tp_str = '<%expTypeFromExpArray(A)%>' - let tvar = tempDecl(arr_tp_str, &varDecls) - let &preExp += 'skew_<%arr_tp_str%>(&<%var1%>, &<%tvar%>);<%\n%>' - '<%tvar%>' - - case CALL(path=IDENT(name="cross"), expLst={v1, v2}) then - let var1 = daeExp(v1, context, &preExp, &varDecls, &auxFunction) - let var2 = daeExp(v2, context, &preExp, &varDecls, &auxFunction) - let arr_tp_str = expTypeFromExpArray(v1) - let tvar = tempDecl(arr_tp_str, &varDecls) - let &preExp += 'cross_alloc_<%arr_tp_str%>(&<%var1%>, &<%var2%>, &<%tvar%>);<%\n%>' - '<%tvar%>' - - case CALL(path=IDENT(name="identity"), expLst={A}) then - let var1 = daeExp(A, context, &preExp, &varDecls, &auxFunction) - let arr_tp_str = expTypeFromExpArray(A) - let tvar = tempDecl(arr_tp_str, &varDecls) - let &preExp += 'identity_alloc_<%arr_tp_str%>(<%var1%>, &<%tvar%>);<%\n%>' - '<%tvar%>' - - case CALL(path=IDENT(name="diagonal"), expLst={A as ARRAY(__)}) then - let arr_tp_str = expTypeFromExpArray(A) - let tvar = tempDecl(arr_tp_str, &varDecls) - let params = (A.array |> e => - '<%daeExp(e, context, &preExp, &varDecls, &auxFunction)%>' - ;separator=", ") - let &preExp += 'diagonal_alloc_<%arr_tp_str%>(&<%tvar%>, <%listLength(A.array)%>, <%params%>);<%\n%>' - '<%tvar%>' - - case CALL(path=IDENT(name="String"), expLst={s, format}) then - let tvar = tempDecl("modelica_string", &varDecls) - let sExp = daeExp(s, context, &preExp, &varDecls, &auxFunction) - - let formatExp = daeExp(format, context, &preExp, &varDecls, &auxFunction) - let typeStr = expTypeFromExpModelica(s) - let &preExp += '<%tvar%> = <%typeStr%>_to_modelica_string_format(<%sExp%>, <%formatExp%>);<%\n%>' - '<%tvar%>' - - case CALL(path=IDENT(name="String"), expLst={s, minlen, leftjust}) then - let tvar = tempDecl("modelica_string", &varDecls) - let sExp = daeExp(s, context, &preExp, &varDecls, &auxFunction) - let minlenExp = daeExp(minlen, context, &preExp, &varDecls, &auxFunction) - let leftjustExp = daeExp(leftjust, context, &preExp, &varDecls, &auxFunction) - let typeStr = expTypeFromExpModelica(s) - match typeStr - case "modelica_real" then - let &preExp += '<%tvar%> = <%typeStr%>_to_modelica_string(<%sExp%>, <%minlenExp%>, <%leftjustExp%>, 6);<%\n%>' - '<%tvar%>' - else - let &preExp += '<%tvar%> = <%typeStr%>_to_modelica_string(<%sExp%>, <%minlenExp%>, <%leftjustExp%>);<%\n%>' - '<%tvar%>' - end match - - case CALL(path=IDENT(name="String"), expLst={s, minlen, leftjust, signdig}) then - let tvar = tempDecl("modelica_string", &varDecls) - let sExp = daeExp(s, context, &preExp, &varDecls, &auxFunction) - let minlenExp = daeExp(minlen, context, &preExp, &varDecls, &auxFunction) - let leftjustExp = daeExp(leftjust, context, &preExp, &varDecls, &auxFunction) - let signdigExp = daeExp(signdig, context, &preExp, &varDecls, &auxFunction) - let &preExp += '<%tvar%> = modelica_real_to_modelica_string(<%sExp%>, <%minlenExp%>, <%leftjustExp%>, <%signdigExp%>);<%\n%>' - '<%tvar%>' - - case CALL(path=IDENT(name="delay"), expLst={ICONST(integer=index), e, d, delayMax}) then - let tvar = tempDecl("modelica_real", &varDecls) - - let var1 = daeExp(e, context, &preExp, &varDecls, &auxFunction) - let var2 = daeExp(d, context, &preExp, &varDecls, &auxFunction) - let var3 = daeExp(delayMax, context, &preExp, &varDecls, &auxFunction) - let &preExp += '<%tvar%> = delayImpl(data, <%index%>, <%var1%>, time, <%var2%>, <%var3%>);<%\n%>' - '<%tvar%>' - - case CALL(path=IDENT(name="Integer"), expLst={toBeCasted}) then - let castedVar = daeExp(toBeCasted, context, &preExp, &varDecls, &auxFunction) - '((modelica_integer)<%castedVar%>)' - - case CALL(path=IDENT(name="clock"), expLst={}) then - 'mmc_clock()' - - case CALL(path=IDENT(name="noEvent"), expLst={e1}) then - daeExp(e1, context, &preExp, &varDecls, &auxFunction) - - case CALL(path=IDENT(name="sample"), expLst={ICONST(integer=index), _, _}) then - '$P$sample<%index%>' - - case CALL(path=IDENT(name="anyString"), expLst={e1}) then - 'mmc_anyString(<%daeExp(e1, context, &preExp, &varDecls, &auxFunction)%>)' - - case CALL(path=IDENT(name="fail"), attr = CALL_ATTR(builtin = true)) then - '<%generateThrow()%>' - - case CALL(path=IDENT(name="mmc_get_field"), expLst={s1, ICONST(integer=i)}) then - let tvar = tempDecl("modelica_metatype", &varDecls) - let expPart = daeExp(s1, context, &preExp, &varDecls, &auxFunction) - let &preExp += '<%tvar%> = MMC_FETCH(MMC_OFFSET(MMC_UNTAGPTR(<%expPart%>), <%i%>));<%\n%>' - '<%tvar%>' - - case CALL(path=IDENT(name = "mmc_unbox_record"), expLst={s1}, attr=CALL_ATTR(ty=ty)) then - let argStr = daeExp(s1, context, &preExp, &varDecls, &auxFunction) - unboxRecord(argStr, ty, &preExp, &varDecls) - - case CALL(path=IDENT(name = "threadData")) then - "threadData" - - case CALL(path=IDENT(name = "intBitNot"),expLst={e}) then - let e1 = daeExp(e, context, &preExp, &varDecls, &auxFunction) - '(~<%e1%>)' - - case CALL(path=IDENT(name = name as "intBitNot"),expLst={e1,e2}) - case CALL(path=IDENT(name = name as "intBitAnd"),expLst={e1,e2}) - case CALL(path=IDENT(name = name as "intBitOr"),expLst={e1,e2}) - case CALL(path=IDENT(name = name as "intBitXor"),expLst={e1,e2}) - case CALL(path=IDENT(name = name as "intBitLShift"),expLst={e1,e2}) - case CALL(path=IDENT(name = name as "intBitRShift"),expLst={e1,e2}) then - let i1 = daeExp(e1, context, &preExp, &varDecls, &auxFunction) - let i2 = daeExp(e1, context, &preExp, &varDecls, &auxFunction) - let op = (match name - case "intBitAnd" then "&" - case "intBitOr" then "|" - case "intBitXor" then "^" - case "intBitLShift" then "<<" - case "intBitRShift" then ">>") - '((<%i1%>) <%op%> (<%i2%>))' - - case exp as CALL(attr=attr as CALL_ATTR(tailCall=tail as TAIL(__))) then - let &postExp = buffer "" - let tail = daeExpTailCall(expLst, tail.vars, context, &preExp, &postExp, &varDecls, &auxFunction) - let res = << - /* Tail recursive call */ - <%tail%><%&postExp%>goto _tailrecursive; - /* TODO: Make sure any eventual dead code below is never generated */ - >> - let &preExp += res - "" - - case exp as CALL(attr=attr as CALL_ATTR(__)) then - let additionalOutputs = (match attr.ty - case T_TUPLE(types=t::ts) then List.fill(", NULL",listLength(ts))) - let res = daeExpCallTuple(exp, additionalOutputs, context, &preExp, &varDecls, &auxFunction) - match context - case FUNCTION_CONTEXT(__) then res - case PARALLEL_FUNCTION_CONTEXT(__) then res - else - if boolAnd(profileFunctions(),boolNot(attr.builtin)) then - let funName = '<%underscorePath(exp.path)%>' - let tvar = match attr.ty - case T_NORETCALL(__) then - "" - case T_TUPLE(types=t::_) - case t - then - let tvar2 = tempDecl(expTypeArrayIf(t),&varDecls) - let &preExp += if isArrayType(t) then '<%tvar2%>.dim_size = 0;<%\n%>' - tvar2 - let &preExp += 'SIM_PROF_TICK_FN(<%funName%>_index);<%\n%>' - let &preExp += if tvar then '<%tvar%> = <%res%>;<%\n%>' else '<%res%>;<%\n%>' - let &preExp += 'SIM_PROF_ACC_FN(<%funName%>_index);<%\n%>' - tvar - else res -end daeExpCall; - -template daeExpCallTuple(Exp call, Text additionalOutputs /* arguments 2..N */, Context context, Text &preExp, Text &varDecls, Text &auxFunction) -::= - match call - case exp as CALL(attr=attr as CALL_ATTR(__)) then - let argStr = if boolOr(attr.builtin,isParallelFunctionContext(context)) - then (expLst |> exp => '<%daeExp(exp, context, &preExp, &varDecls, &auxFunction)%>' ;separator=", ") - else ("threadData" + (expLst |> exp => (", " + daeExp(exp, context, &preExp, &varDecls, &auxFunction)))) - if attr.isFunctionPointerCall - then - let typeCast1 = generateTypeCast(attr.ty, expLst, true) - let typeCast2 = generateTypeCast(attr.ty, expLst, false) - let name = '_<%underscorePath(path)%>' - let func = '(MMC_FETCH(MMC_OFFSET(MMC_UNTAGPTR(<%name%>), 1)))' - let closure = '(MMC_FETCH(MMC_OFFSET(MMC_UNTAGPTR(<%name%>), 2)))' - let argStrPointer = ('threadData, <%closure%>' + (expLst |> exp => (", " + daeExp(exp, context, &preExp, &varDecls, &auxFunction)))) - //'<%name%>(<%argStr%><%additionalOutputs%>)' - '/*Closure?*/<%closure%> ? (<%typeCast1%> <%func%>) (<%argStrPointer%><%additionalOutputs%>) : (<%typeCast2%> <%func%>) (<%argStr%><%additionalOutputs%>)' - else - let name = '<% if attr.builtin then "" else "omc_" %><%underscorePath(path)%>' - '<%name%>(<%argStr%><%additionalOutputs%>)' -end daeExpCallTuple; - -template generateTypeCast(Type ty, list es, Boolean isClosure) -::= - let ret = (match ty - case T_NORETCALL(__) then "void" - else "modelica_metatype") - let inputs = es |> e => ', <%expTypeFromExpArrayIf(e)%>' - let outputs = match ty - case T_TUPLE(types=_::tys) then (tys |> t => ', <%expTypeArrayIf(t)%>') - '(<%ret%>(*)(threadData_t*<%if isClosure then ", modelica_metatype"%><%inputs%><%outputs%>))' -end generateTypeCast; - -template generateTypeCastFromType(Type ty, Boolean isClosure) -::= - let ret = (match ty - case T_FUNCTION(funcResultType=T_NORETCALL(__)) then "void" - else "modelica_metatype") - let inputs = match ty - case T_FUNCTION(__) then - (funcArg |> fa as FUNCARG(__) => ', <%expTypeArrayIf(fa.ty)%>') - let outputs = match ty - case T_FUNCTION(funcResultType=T_TUPLE(types=_::tys)) then (tys |> t => ', <%expTypeArrayIf(t)%>') - '(<%ret%>(*)(threadData_t*<%if isClosure then ", modelica_metatype"%><%inputs%><%outputs%>))' -end generateTypeCastFromType; - -template daeExpTailCall(list es, list vs, Context context, Text &preExp, Text &postExp, Text &varDecls, Text &auxFunction) -::= - match es - case e::erest then - match vs - case v::vrest then - let exp = daeExp(e,context,&preExp,&varDecls, &auxFunction) - match e - case CREF(componentRef = cr, ty = T_FUNCTION_REFERENCE_VAR(__)) then - // adrpo: ignore _x = _x! - if stringEq(v, crefStr(cr)) - then '<%daeExpTailCall(erest, vrest, context, &preExp, &postExp, &varDecls, &auxFunction)%>' - else '_<%v%> = <%exp%>;<%\n%><%daeExpTailCall(erest, vrest, context, &preExp, &postExp, &varDecls, &auxFunction)%>' - case _ then - (if anyExpHasCrefName(erest, v) then - /* We might overwrite a value with something else, so make an extra copy of it */ - let tmp = tempDecl(expTypeFromExpModelica(e),&varDecls) - let &postExp += '_<%v%> = <%tmp%>;<%\n%>' - '<%tmp%> = <%exp%>;<%\n%><%daeExpTailCall(erest, vrest, context, &preExp, &postExp, &varDecls, &auxFunction)%>' - else - let restText = daeExpTailCall(erest, vrest, context, &preExp, &postExp, &varDecls, &auxFunction) - let v2 = '_<%v%>' - if stringEq(v2, exp) - then restText - else '<%v2%> = <%exp%>;<%\n%><%restText%>') -end daeExpTailCall; - -template daeExpArray(Exp exp, Context context, Text &preExp, - Text &varDecls, Text &auxFunction) - "Generates code for an array expression." -::= -match exp -case ARRAY(array = array, scalar = scalar, ty = T_ARRAY(ty = t as T_COMPLEX(__))) then - let arrayTypeStr = expTypeArray(ty) - let arrayVar = tempDecl(arrayTypeStr, &varDecls) - let rec_name = expTypeShort(t) - let &preExp += '<%\n%>alloc_generic_array(&<%arrayVar%>, sizeof(<%rec_name%>), 1, <%listLength(array)%>);<%\n%>' - let params = (array |> e hasindex i1 fromindex 1 => - let prefix = if scalar then '(<%expTypeFromExpModelica(e)%>)' else '&' - '(*((<%rec_name%>*)generic_array_element_addr(&<%arrayVar%>, sizeof(<%rec_name%>), 1, <%i1%>))) = <%prefix%><%daeExp(e, context, &preExp, &varDecls, &auxFunction)%>;' - ;separator="\n") - let &preExp += '<%params%><%\n%>' - arrayVar -case ARRAY(array={}) then - let arrayVar = tempDecl("base_array_t", &varDecls) - let &preExp += 'simple_alloc_1d_base_array(&<%arrayVar%>, 0, NULL);<%\n%>' - arrayVar -case ARRAY(__) then - let arrayTypeStr = expTypeArray(ty) - let arrayVar = tempDecl(arrayTypeStr, &varDecls) - let scalarPrefix = if scalar then "scalar_" else "" - let scalarRef = if scalar then "&" else "" - let params = (array |> e => - let prefix = if scalar then '(<%expTypeFromExpModelica(e)%>)' else "" - '<%prefix%><%daeExp(e, context, &preExp, &varDecls, &auxFunction)%>' - ;separator=", ") - let &preExp += 'array_alloc_<%scalarPrefix%><%arrayTypeStr%>(&<%arrayVar%>, <%listLength(array)%><%if params then ", "%><%params%>);<%\n%>' - arrayVar -end daeExpArray; - - -template daeExpMatrix(Exp exp, Context context, Text &preExp, - Text &varDecls, Text &auxFunction) - "Generates code for a matrix expression." -::= - match exp - case MATRIX(matrix={{}}) // special case for empty matrix: create dimensional array Real[0,1] - case MATRIX(matrix={}) // special case for empty array: create dimensional array Real[0,1] - then - let arrayTypeStr = expTypeArray(ty) - let tmp = tempDecl(arrayTypeStr, &varDecls) - let &preExp += 'alloc_<%arrayTypeStr%>(&<%tmp%>, 2, 0, 1);<%\n%>' - tmp - case m as MATRIX(__) then - let typeStr = expTypeShort(m.ty) - let arrayTypeStr = expTypeArray(m.ty) - match typeStr - // faster creation of the matrix for basic types - case "real" - case "integer" - case "boolean" then - let tmp = tempDecl(arrayTypeStr, &varDecls) - let rows = '<%listLength(m.matrix)%>' - let cols = '<%listLength(listGet(m.matrix, 1))%>' - let matrix = (m.matrix |> row hasindex i0 => - let els = (row |> e hasindex j0 => - let expVar = daeExp(e, context, &preExp, &varDecls, &auxFunction) - 'put_<%typeStr%>_matrix_element(<%expVar%>, <%i0%>, <%j0%>, &<%tmp%>);' ;separator="\n") - '<%els%>' - ;separator="\n") - let &preExp += '/* -- start: matrix[<%rows%>,<%cols%>] -- */<%\n%>' - let &preExp += 'alloc_<%typeStr%>_array(&<%tmp%>, 2, <%rows%>, <%cols%>);<%\n%>' - let &preExp += '<%matrix%><%\n%>' - let &preExp += '/* -- end: matrix[<%rows%>,<%cols%>] -- */<%\n%>' - tmp - // everything else - case _ then - let &vars2 = buffer "" - let &promote = buffer "" - let catAlloc = (m.matrix |> row => - let tmp = tempDecl(arrayTypeStr, &varDecls) - let vars = daeExpMatrixRow(row, arrayTypeStr, context, - &promote, &varDecls, &auxFunction) - let &vars2 += ', &<%tmp%>' - 'cat_alloc_<%arrayTypeStr%>(2, &<%tmp%>, <%listLength(row)%><%vars%>);' - ;separator="\n") - let &preExp += promote - let &preExp += catAlloc - let &preExp += "\n" - let tmp = tempDecl(arrayTypeStr, &varDecls) - let &preExp += 'cat_alloc_<%arrayTypeStr%>(1, &<%tmp%>, <%listLength(m.matrix)%><%vars2%>);<%\n%>' - tmp -end daeExpMatrix; - - -template daeExpMatrixRow(list row, String arrayTypeStr, - Context context, Text &preExp, - Text &varDecls, Text &auxFunction) - "Helper to daeExpMatrix." -::= - let &varLstStr = buffer "" - - let preExp2 = (row |> e => - let expVar = daeExp(e, context, &preExp, &varDecls, &auxFunction) - let tmp = tempDecl(arrayTypeStr, &varDecls) - let &varLstStr += ', &<%tmp%>' - 'promote_scalar_<%arrayTypeStr%>(<%expVar%>, 2, &<%tmp%>);' - ;separator="\n") - let &preExp2 += "\n" - let &preExp += preExp2 - varLstStr -end daeExpMatrixRow; - -template daeExpRange(Exp exp, Context context, Text &preExp, - Text &varDecls, Text &auxFunction) - "Generates code for a range expression." -::= - match exp - case RANGE(__) then - let ty_str = expTypeArray(ty) - let start_exp = daeExp(start, context, &preExp, &varDecls, &auxFunction) - let stop_exp = daeExp(stop, context, &preExp, &varDecls, &auxFunction) - let tmp = tempDecl(ty_str, &varDecls) - let step_exp = match step case SOME(stepExp) then daeExp(stepExp, context, &preExp, &varDecls, &auxFunction) else "1" - let &preExp += 'create_<%ty_str%>_from_range(&<%tmp%>, <%start_exp%>, <%step_exp%>, <%stop_exp%>);<%\n%>' - '<%tmp%>' -end daeExpRange; - -template daeExpCast(Exp exp, Context context, Text &preExp, - Text &varDecls, Text &auxFunction) - "Generates code for a cast expression." -::= -match exp -case CAST(__) then - let expVar = daeExp(exp, context, &preExp, &varDecls, &auxFunction) - match ty - case T_INTEGER(__) then '((modelica_integer)<%expVar%>)' - case T_REAL(__) then '((modelica_real)<%expVar%>)' - case T_ENUMERATION(__) then '((modelica_integer)<%expVar%>)' - case T_BOOL(__) then '((modelica_boolean)<%expVar%>)' - case T_ARRAY(__) then - let arrayTypeStr = expTypeArray(ty) - let tvar = tempDecl(arrayTypeStr, &varDecls) - let tevar = tempDecl(arrayTypeStr, &varDecls) - let to = expTypeShort(ty) - let from = expTypeFromExpShort(exp) - let &preExp += '<%tevar%> = <%expVar%>;<%\n%>cast_<%from%>_array_to_<%to%>(&<%tevar%>, &<%tvar%>);<%\n%>' - '<%tvar%>' - case ty1 as T_COMPLEX(complexClassType=rec as RECORD(__)) then - match typeof(exp) - case ty2 as T_COMPLEX(__) then - if intEq(listLength(ty1.varLst),listLength(ty2.varLst)) then expVar - else - let tmp = tempDecl(expTypeModelica(ty2),&varDecls) - let res = tempDecl(expTypeModelica(ty1),&varDecls) - let &preExp += '<%tmp%> = <%expVar%>;<%\n%>' - let &preExp += ty1.varLst |> var as DAE.TYPES_VAR() => '<%res%>._<%var.name%> = <%tmp%>._<%var.name%>; /* cast */<%\n%>' - res - else - '(<%expVar%>) /* could not cast, using the variable as it is */' -end daeExpCast; - -template daeExpTsub(Exp inExp, Context context, Text &preExp, - Text &varDecls, Text &auxFunction) - "Generates code for an tsub expression." -::= - match inExp - case TSUB(ix=1) then - daeExp(exp, context, &preExp, &varDecls, &auxFunction) - case TSUB(exp=CALL(attr=CALL_ATTR(ty=T_TUPLE(types=tys)))) then - let v = tempDecl(expTypeArrayIf(listGet(tys,ix)), &varDecls) - let additionalOutputs = List.restOrEmpty(tys) |> ty hasindex i1 fromindex 2 => if intEq(i1,ix) then ', &<%v%>' else ", NULL" - let &preExp += if isArrayType(listGet(tys,ix)) then '<%v%>.dim_size = 0;<%\n%>' - let res = daeExpCallTuple(exp, additionalOutputs, context, &preExp, &varDecls, &auxFunction) - let &preExp += '<%res%>;<%\n%>' - v - case TSUB(__) then - error(sourceInfo(), '<%printExpStr(inExp)%>: TSUB only makes sense if the subscripted expression is a function call of tuple type') -end daeExpTsub; - -template daeExpAsub(Exp inExp, Context context, Text &preExp, - Text &varDecls, Text &auxFunction) - "Generates code for an asub expression." -::= - match expTypeFromExpShort(inExp) - case "metatype" then - // MetaModelica Array - (match inExp case ASUB(exp=e, sub={idx}) then - let e1 = daeExp(e, context, &preExp, &varDecls, &auxFunction) - let idx1 = daeExp(idx, context, &preExp, &varDecls, &auxFunction) - 'arrayGet(<%e1%>,<%idx1%>) /* DAE.ASUB */') - // Modelica Array - else - match inExp - case ASUB(exp=ASUB(__)) then - error(sourceInfo(),'Nested array subscripting *should* have been handled by the routine creating the asub, but for some reason it was not: <%printExpStr(exp)%>') - - // Faster asub: Do not construct a whole new array just to access one subscript - case ASUB(exp=exp as ARRAY(scalar=true), sub={idx}) then - let res = tempDecl(expTypeFromExpModelica(exp),&varDecls) - let idx1 = daeExp(idx, context, &preExp, &varDecls, &auxFunction) - let expl = (exp.array |> e hasindex i1 fromindex 1 => - let &caseVarDecls = buffer "" - let &casePreExp = buffer "" - let v = daeExp(e, context, &casePreExp, &caseVarDecls, &auxFunction) - << - case <%i1%>: { - <%&caseVarDecls%> - <%&casePreExp%> - <%res%> = <%v%>; - break; - } - >> ; separator = "\n") - let &preExp += - << - switch(<%idx1%>) - { /* ASUB */ - <%expl%> - default: - throwStreamPrint(threadData, "Index %ld out of bounds [1..<%listLength(exp.array)%>] for array <%Util.escapeModelicaStringToCString(printExpStr(exp))%>", (long) <%idx1%>); - } - <%\n%> - >> - res - - case ASUB(exp=range as RANGE(ty=T_INTEGER(),step=NONE()), sub={idx}) then - let res = tempDecl("modelica_integer", &varDecls) - let idx1 = daeExp(idx, context, &preExp, &varDecls, &auxFunction) - let start = daeExp(range.start, context, &preExp, &varDecls, &auxFunction) - let stop = daeExp(range.stop, context, &preExp, &varDecls, &auxFunction) - let &preExp += << - <%res%> = <%idx1%> + <%start%> - 1; - if (<%res%> > <%stop%>) { - throwStreamPrint(threadData, "Value %ld out of bounds for range <%Util.escapeModelicaStringToCString(printExpStr(range))%>", (long) <%res%>); - } - >> - res - - case ASUB(exp=RANGE(ty=t), sub={idx}) then - error(sourceInfo(),'ASUB_EASY_CASE type:<%unparseType(t)%> range:<%printExpStr(exp)%> index:<%printExpStr(idx)%>') - - case ASUB(exp=ecr as CREF(__), sub=subs) then - let arrName = daeExpCrefRhs(buildCrefExpFromAsub(ecr, subs), context, - &preExp, &varDecls, &auxFunction) - match context - case FUNCTION_CONTEXT(__) then - arrName - case PARALLEL_FUNCTION_CONTEXT(__) then - arrName - else - arrayScalarRhs(ecr.ty, subs, arrName, context, &preExp, &varDecls, &auxFunction) - - case ASUB(exp=e, sub=indexes) then - let exp = daeExp(e, context, &preExp, &varDecls, &auxFunction) - let typeShort = expTypeFromExpShort(e) - match Expression.typeof(inExp) - case T_ARRAY(__) then - error(sourceInfo(),'ASUB non-scalar <%printExpStr(inExp)%>. The inner exp has type: <%unparseType(Expression.typeof(e))%>. After ASUB it is still an array: <%unparseType(Expression.typeof(inExp))%>.') - else - let expIndexes = (indexes |> index => '<%daeExpASubIndex(index, context, &preExp, &varDecls, &auxFunction)%>' ;separator=", ") - '<%typeShort%>_get<%match listLength(indexes) case 1 then "" case i then '_<%i%>D'%>(<%exp%>, <%expIndexes%>)' - - else - error(sourceInfo(),'OTHER_ASUB <%printExpStr(inExp)%>') -end daeExpAsub; - -template daeExpASubIndex(Exp exp, Context context, Text &preExp, Text &varDecls, Text &auxFunction) -::= -match exp - case ICONST(__) then incrementInt(integer,-1) - case ENUM_LITERAL(__) then incrementInt(index,-1) - else '(<%daeExp(exp,context,&preExp,&varDecls, &auxFunction)%>)-1' -end daeExpASubIndex; - -template daeExpCallPre(Exp exp, Context context, Text &preExp, Text &varDecls, Text &auxFunction) - "Generates code for an asub of a cref, which becomes cref + offset." -::= - match exp - /*we use daeExpCrefLhs because daeExpCrefRhs returns with a cast. - will reslut in '$P$PRE(modelica_integer)$A$B... - pre() functions should actaully be eliminated in backend and $PRE prepened as ident - in all cases. (now it's done some places but not in others.)*/ - case cr as CREF(__) then - '$P$PRE<%daeExpCrefLhs(exp, context, &preExp, &varDecls, &auxFunction)%>' - else - error(sourceInfo(), 'Code generation does not support pre(<%printExpStr(exp)%>)') -end daeExpCallPre; - -template daeExpCallStart(Exp exp, Context context, Text &preExp, - Text &varDecls, Text &auxFunction) - "Generates code for an asub of a cref, which becomes cref + offset." -::= - match exp - case cr as CREF(__) then - '$P$ATTRIBUTE<%cref(cr.componentRef)%>.start' - case ASUB(exp = cr as CREF(__), sub = {sub_exp}) then - let offset = daeExp(sub_exp, context, &preExp, &varDecls, &auxFunction) - let cref = cref(cr.componentRef) - '*(&$P$ATTRIBUTE<%cref(cr.componentRef)%>.start + <%offset%>)' - else - error(sourceInfo(), 'Code generation does not support start(<%printExpStr(exp)%>)') -end daeExpCallStart; - - -template daeExpSize(Exp exp, Context context, Text &preExp, - Text &varDecls, Text &auxFunction) - "Generates code for a size expression." -::= - match exp - case SIZE(exp=CREF(__), sz=SOME(dim)) then - let expPart = daeExp(exp, context, &preExp, &varDecls, &auxFunction) - let dimPart = daeExp(dim, context, &preExp, &varDecls, &auxFunction) - let resVar = tempDecl("modelica_integer", &varDecls) - let &preExp += '<%resVar%> = size_of_dimension_base_array(<%expPart%>, <%dimPart%>);<%\n%>' - resVar - case SIZE(exp=CREF(__)) then - let expPart = daeExp(exp, context, &preExp, &varDecls, &auxFunction) - let resVar = tempDecl("integer_array", &varDecls) - let &preExp += 'sizes_of_dimensions_base_array(&<%expPart%>, &<%resVar%>);<%\n%>' - resVar - /* array of zero? */ - case SIZE(exp=ARRAY(array = {})) then - let resVar = tempDecl("modelica_integer", &varDecls) - let &preExp += '<%resVar%> = 0;<%\n%>' - resVar - else error(sourceInfo(), printExpStr(exp) + " not implemented") -end daeExpSize; - - -template daeExpReduction(Exp exp, Context context, Text &preExp, - Text &varDecls, Text &auxFunction) - "Generates code for a reduction expression. The code is quite messy because it handles all - special reduction functions (list, listReverse, array) and handles both list and array as input" -::= - match exp - case r as REDUCTION(reductionInfo=ri as REDUCTIONINFO(iterType=THREAD()),iterators=iterators) - case r as REDUCTION(reductionInfo=ri as REDUCTIONINFO(iterType=COMBINE()),iterators=iterators as {_}) then - ( - let &tmpVarDecls = buffer "" - let &tmpExpPre = buffer "" - let &bodyExpPre = buffer "" - let &rangeExpPre = buffer "" - let arrayTypeResult = expTypeFromExpArray(r) - let arrIndex = match ri.path case IDENT(name="array") then tempDecl("int",&tmpVarDecls) - let foundFirst = if not ri.defaultValue then tempDecl("int",&tmpVarDecls) - let resType = expTypeArrayIf(typeof(exp)) - let res = contextCref(makeUntypedCrefIdent(ri.resultName), context, &auxFunction) - let &tmpVarDecls += '<%resType%> <%res%>;<%\n%>' - let resTmp = tempDecl(resType,&varDecls) - let &preDefault = buffer "" - let resTail = (match ri.path case IDENT(name="list") then tempDecl("modelica_metatype*",&tmpVarDecls)) - let defaultValue = (match ri.path - case IDENT(name="array") then "" - else (match ri.defaultValue - case SOME(v) then daeExp(valueExp(v),context,&preDefault,&tmpVarDecls, &auxFunction))) - let reductionBodyExpr = contextCref(makeUntypedCrefIdent(ri.foldName), context, &auxFunction) - let bodyExprType = expTypeArrayIf(typeof(r.expr)) - let reductionBodyExprWork = daeExp(r.expr, context, &bodyExpPre, &tmpVarDecls, &auxFunction) - let &tmpVarDecls += '<%bodyExprType%> <%reductionBodyExpr%>;<%\n%>' - let &bodyExpPre += '<%reductionBodyExpr%> = <%reductionBodyExprWork%>;<%\n%>' - let foldExp = (match ri.path - case IDENT(name="list") then - << - *<%resTail%> = mmc_mk_cons(<%reductionBodyExpr%>,0); - <%resTail%> = &MMC_CDR(*<%resTail%>); - >> - case IDENT(name="listReverse") then // This is too easy; the damn list is already in the correct order - '<%res%> = mmc_mk_cons(<%reductionBodyExpr%>,<%res%>);' - case IDENT(name="array") then - match typeof(r.expr) - case T_COMPLEX(complexClassType = record_state) then - let rec_name = '<%underscorePath(ClassInf.getStateName(record_state))%>' - '*((<%rec_name%>*)generic_array_element_addr(&<%res%>, sizeof(<%rec_name%>), 1, <%arrIndex%>++)) = <%reductionBodyExpr%>;' - case T_ARRAY(__) then - let tmp = tempDecl("index_spec_t", &varDecls) - let nridx_str = intAdd(1,listLength(dims)) - let idx_str = (dims |> dim => ", (1), (int*)0, 'W'") - << - create_index_spec(&<%tmp%>, <%nridx_str%>, (0), make_index_array(1, (int) <%arrIndex%>++), 'S'<%idx_str%>); - indexed_assign_<%expTypeArray(ty)%>(<%reductionBodyExpr%>, &<%res%>, &<%tmp%>); - >> - else - '*(<%arrayTypeResult%>_element_addr1(&<%res%>, 1, <%arrIndex%>++)) = <%reductionBodyExpr%>;' - else match ri.foldExp case SOME(fExp) then - let &foldExpPre = buffer "" - let fExpStr = daeExp(fExp, context, &bodyExpPre, &tmpVarDecls, &auxFunction) - if not ri.defaultValue then - << - if(<%foundFirst%>) - { - <%res%> = <%fExpStr%>; - } - else - { - <%res%> = <%reductionBodyExpr%>; - <%foundFirst%> = 1; - } - >> - else '<%res%> = <%fExpStr%>;') - let endLoop = tempDecl("int",&tmpVarDecls) - let loopHeadIter = (iterators |> iter as REDUCTIONITER(__) => - let identType = expTypeFromExpModelica(iter.exp) - let arrayType = expTypeFromExpArray(iter.exp) - let loopVar = '<%iter.id%>_loopVar' - let &guardExpPre = buffer "" - let &tmpVarDecls += (match identType - case "modelica_metatype" then 'modelica_metatype <%loopVar%> = 0;<%\n%>' - else '<%arrayType%> <%loopVar%>;<%\n%>') - let firstIndex = match identType case "modelica_metatype" then (if isMetaArray(iter.exp) then tempDecl("int",&tmpVarDecls) else "") else tempDecl("int",&tmpVarDecls) - let rangeExp = daeExp(iter.exp,context,&rangeExpPre,&tmpVarDecls, &auxFunction) - let &rangeExpPre += '<%loopVar%> = <%rangeExp%>;<%\n%>' - let &rangeExpPre += if firstIndex then '<%firstIndex%> = 1;<%\n%>' - let guardCond = (match iter.guardExp case SOME(grd) then daeExp(grd, context, &guardExpPre, &tmpVarDecls, &auxFunction) else "1") - let iteratorName = contextIteratorName(iter.id, context) - let &tmpVarDecls += '<%identType%> <%iteratorName%>;<%\n%>' - let guardExp = - << - <%&guardExpPre%> - if(<%guardCond%>) { /* found non-guarded */ - <%endLoop%>--; - break; - } - >> - (match identType - case "modelica_metatype" then - (if isMetaArray(iter.exp) then - << - while (<%firstIndex%> <= arrayLength(<%loopVar%>)) { - <%iteratorName%> = arrayGet(<%loopVar%>, <%firstIndex%>++); - <%guardExp%> - } - >> - else - << - while (!listEmpty(<%loopVar%>)) { - <%iteratorName%> = MMC_CAR(<%loopVar%>); - <%loopVar%> = MMC_CDR(<%loopVar%>); - <%guardExp%> - } - >> - ) - else - let addr = match iter.ty - case T_ARRAY(ty=T_COMPLEX(complexClassType = record_state)) then - let rec_name = '<%underscorePath(ClassInf.getStateName(record_state))%>' - '*((<%rec_name%>*)generic_array_element_addr(&<%loopVar%>, sizeof(<%rec_name%>), 1, <%firstIndex%>++))' - else - '*(<%arrayType%>_element_addr1(&<%loopVar%>, 1, <%firstIndex%>++))' - << - while(<%firstIndex%> <= size_of_dimension_base_array(<%loopVar%>, 1)) { - <%iteratorName%> = <%addr%>; - <%guardExp%> - } - >>)) - let firstValue = (match ri.path - case IDENT(name="array") then - let length = tempDecl("int",&tmpVarDecls) - let &rangeExpPre += '<%length%> = 0;<%\n%>' - let _ = (iterators |> iter as REDUCTIONITER(__) => - let loopVar = '<%iter.id%>_loopVar' - let identType = expTypeFromExpModelica(iter.exp) - let &rangeExpPre += '<%length%> = modelica_integer_max(<%length%>,<%match identType case "modelica_metatype" then (if isMetaArray(iter.exp) then 'arrayLength(<%loopVar%>)' else 'listLength(<%loopVar%>)') else 'size_of_dimension_base_array(<%loopVar%>, 1)'%>);<%\n%>' - "") - << - <%arrIndex%> = 1; - <% match typeof(r.expr) - case T_COMPLEX(complexClassType = record_state) then - let rec_name = '<%underscorePath(ClassInf.getStateName(record_state))%>' - 'alloc_generic_array(&<%res%>,sizeof(<%rec_name%>),1,<%length%>);' - case T_ARRAY(__) then - let dimSizes = dims |> dim => match dim - case DIM_INTEGER(__) then ', <%integer%>' - case DIM_BOOLEAN(__) then ", 2" - case DIM_ENUM(__) then ', <%size%>' - else error(sourceInfo(), 'array reduction unable to generate code for element of unknown dimension sizes; type <%unparseType(typeof(r.expr))%>: <%ExpressionDump.printExpStr(r.expr)%>') - ; separator = ", " - 'alloc_<%arrayTypeResult%>(&<%res%>, <%intAdd(1,listLength(dims))%>, <%length%><%dimSizes%>);' - else - 'simple_alloc_1d_<%arrayTypeResult%>(&<%res%>,<%length%>);'%> - >> - else if ri.defaultValue then - << - <%&preDefault%> - <%res%> = <%defaultValue%>; /* defaultValue */ - >> - else - << - <%foundFirst%> = 0; /* <%dotPath(ri.path)%> lacks default-value */ - >>) - let loop = - << - while(1) { - <%endLoop%> = <%listLength(iterators)%>; - <%loopHeadIter%> - if (<%endLoop%> == 0) { - <%&bodyExpPre%> - <%foldExp%> - } <% match iterators case _::_ then - << - else if (<%endLoop%> == <%listLength(iterators)%>) { - break; - } else { - <%generateThrow()%>; - } - >> %> - } - >> - let &preExp += << - { - <%&tmpVarDecls%> - <%&rangeExpPre%> - <%firstValue%> - <% if resTail then '<%resTail%> = &<%res%>;' %> - <%loop%> - <% if not ri.defaultValue then 'if (!<%foundFirst%>) <%generateThrow()%>;' %> - <% if resTail then '*<%resTail%> = mmc_mk_nil();' %> - <% resTmp %> = <% res %>; - }<%\n%> - >> - resTmp) - else error(sourceInfo(), 'Code generation does not support multiple iterators: <%printExpStr(exp)%>') -end daeExpReduction; - -template daeExpMatch(Exp exp, Context context, Text &preExp, Text &varDecls, Text &auxFunction) - "Generates code for a match expression." -::= -match exp -case exp as MATCHEXPRESSION(__) then - let res = match et - case T_NORETCALL(__) then error(sourceInfo(), 'match expression not returning anything should be caught in a noretcall statement and not reach this code: <%printExpStr(exp)%>') - case T_TUPLE(types={}) then error(sourceInfo(), 'match expression returning an empty tuple should be caught in a noretcall statement and not reach this code: <%printExpStr(exp)%>') - else tempDeclZero(expTypeModelica(et), &varDecls) - let startIndexOutputs = "ERROR_INDEX" - daeExpMatch2(exp,listExpLength1,res,startIndexOutputs,context,&preExp,&varDecls,&auxFunction) -end daeExpMatch; - -template daeExpMatch2(Exp exp, list tupleAssignExps, Text res, Text startIndexOutputs, Context context, Text &preExp, Text &varDecls, Text &auxFunction) - "Generates code for a match expression." -::= -match exp -case exp as MATCHEXPRESSION(__) then - let () = codegenPushTryThrowIndex(System.tmpTick()) - let goto = 'goto_<%codegenPeekTryThrowIndex()%>' - let &preExpInner = buffer "" - let &preExpRes = buffer "" - let &varDeclsInput = buffer "" - let &varDeclsInner = buffer "" - let &varFrees = buffer "" - let &ignore = buffer "" - let ignore2 = (elementVars(localDecls) |> var => - varInit(var, "", &varDeclsInner, &preExpInner, &varFrees, &auxFunction) - ) - let prefix = 'tmp<%System.tmpTick()%>' - let &preExpInput = buffer "" - let &expInput = buffer "" - // get the current index of tmpMeta and reserve N=listLength(inputs) values in it! - let startIndexInputs = '<%System.tmpTickIndexReserve(1, listLength(inputs))%>' - let ignore3 = (List.threadTuple(inputs,aliases) |> (exp,alias) hasindex i0 => - let typ = '<%expTypeFromExpModelica(exp)%>' - let decl = tempDeclMatchInput(typ, prefix, startIndexInputs, i0, &varDeclsInput) - let &expInput += '<%decl%> = <%daeExp(exp, context, &preExpInput, &varDeclsInput, &auxFunction)%>;<%\n%>' - let &expInput += alias |> a => let &varDeclsInput += '<%typ%> _<%a%>;' '_<%a%> = <%decl%>;' ; separator="\n" - ""; empty) - let ix = match exp.matchType - case MATCH(switch=SOME((switchIndex,ty as T_STRING(__),div))) then - let matchInputVar = getTempDeclMatchInputName(exp.inputs, prefix, startIndexInputs, switchIndex) - 'stringHashDjb2Mod(<%matchInputVar%>,<%div%>)' - case MATCH(switch=SOME((switchIndex,ty as T_METATYPE(__),_))) then - let matchInputVar = getTempDeclMatchInputName(exp.inputs, prefix, startIndexInputs, switchIndex) - 'valueConstructor(<%matchInputVar%>)' - case MATCH(switch=SOME((switchIndex,ty as T_INTEGER(__),_))) then - let matchInputVar = getTempDeclMatchInputName(exp.inputs, prefix, startIndexInputs, switchIndex) - '<%matchInputVar%>' - case MATCH(switch=SOME(_)) then - error(sourceInfo(), 'Unknown switch: <%printExpStr(exp)%>') - else tempDecl('volatile mmc_switch_type', &varDeclsInner) - let done = tempDecl('int', &varDeclsInner) - let &preExp += - << - <%endModelicaLine()%> - { /* <% match exp.matchType case MATCHCONTINUE(__) then "matchcontinue expression" case MATCH(__) then "match expression" %> */ - <%varDeclsInput%> - <%preExpInput%> - <%expInput%> - { - <%varDeclsInner%> - <%preExpInner%> - <%match exp.matchType - case MATCH(switch=SOME(_)) then '<%done%> = 0;<%\n%>{' - else - << - <%ix%> = 0; - <%done%> = 0; - <% match exp.matchType case MATCHCONTINUE(__) then - /* One additional MMC_TRY_INTERNAL() for each caught exception - * You would expect you could do the setjmp only once, but some counters I guess are stored in registers and would need to become volatile - * This is still a lot faster than doing MMC_TRY_INTERNAL() inside the for-loop - */ - << - MMC_TRY_INTERNAL(mmc_jumper) - <%prefix%>_top: - threadData->mmc_jumper = &new_mmc_jumper; - >> - %> - for (; <%ix%> < <%listLength(exp.cases)%> && !<%done%>; <%ix%>++) { - >> - %> - switch (MMC_SWITCH_CAST(<%ix%>)) { - <%daeExpMatchCases(exp.cases, tupleAssignExps, exp.matchType, ix, res, startIndexOutputs, prefix, startIndexInputs, exp.inputs, done, context, &varDecls, &auxFunction, System.tmpTickIndexReserve(1,0) /* Returns the current MM tick */)%> - } - goto <%prefix%>_end; - <%prefix%>_end: ; - }<%let() = codegenPopTryThrowIndex() ""%> - goto <%goto%>; - <%goto%>:; - <% match exp.matchType case MATCHCONTINUE(__) then - << - MMC_CATCH_INTERNAL(mmc_jumper); - if (!<%done%> && ++<%ix%> < <%listLength(exp.cases)%>) { - goto <%prefix%>_top; - } - >> - %> - if (!<%done%>) <%generateThrow()%>; - } - } - >> - res -end daeExpMatch2; - -template daeExpMatchCases(list cases, list tupleAssignExps, DAE.MatchType ty, Text ix, Text res, Text startIndexOutputs, Text prefix, Text startIndexInputs, list inputs, Text done, Context context, Text &varDecls, Text &auxFunction, Integer startTmpTickIndex) -::= - cases |> c as CASE(__) hasindex i0 => - let() = System.tmpTickSetIndex(startTmpTickIndex,1) - // Susan doesn't let us do this outside the loop... - let lastSwitchIndex = (match ty - case MATCH(switch=SOME((n,ty as T_STRING(__),div))) then - (match List.last(cases) - case last as CASE(__) then - (match switchIndex(listGet(last.patterns,n),div) - case "default" then 'goto <%prefix%>_default' - else 'goto <%prefix%>_end')) - else 'goto <%prefix%>_end') - let onPatternFail = (match ty - case MATCH(switch=SOME((switchIndex,ty as T_STRING(__),div))) then - lastSwitchIndex - else 'goto <%prefix%>_end') - let &varDeclsCaseInner = buffer "" - let &preExpCaseInner = buffer "" - let &assignments = buffer "" - let &preRes = buffer "" - let &varFrees = buffer "" - let patternMatching = (sortPatternsByComplexity(c.patterns) |> (lhs,i0) => patternMatch(lhs,'<%getTempDeclMatchInputName(inputs, prefix, startIndexInputs, i0)%>', onPatternFail, &varDeclsCaseInner, &assignments); empty) - let() = System.tmpTickSetIndex(startTmpTickIndex,1) - let stmts = (c.body |> stmt => algStatement(stmt, context, &varDeclsCaseInner, &auxFunction); separator="\n") - let &preGuardCheck = buffer "" - let guardCheck = (match c.patternGuard case SOME(exp) then - << - /* Check guard condition after assignments */ - if (!<%daeExp(exp,context,&preGuardCheck,&varDeclsCaseInner, &auxFunction)%>) <%onPatternFail%>;<%\n%> - >>) - let caseRes = (match c.result - case SOME(TUPLE(PR=exps)) then - (exps |> e hasindex i1 fromindex 1 => - '<%getTempDeclMatchOutputName(exps, res, startIndexOutputs, i1)%> = <%daeExp(e,context,&preRes,&varDeclsCaseInner, &auxFunction)%>;<%\n%>') - case SOME(exp as CALL(attr=CALL_ATTR(tailCall=TAIL(__)))) then - daeExp(exp, context, &preRes, &varDeclsCaseInner, &auxFunction) - case SOME(exp as CALL(attr=CALL_ATTR(tuple_=true))) then - let additionalOutputs = List.restOrEmpty(tupleAssignExps) |> cr hasindex i0 fromindex 2 /* starting with second element */ => - ', &<%getTempDeclMatchOutputName(tupleAssignExps, res, startIndexOutputs, i0)%>' - let retStruct = daeExpCallTuple(exp, additionalOutputs, context, &preRes, &varDeclsCaseInner, &auxFunction) - let callRet = match tupleAssignExps - case {} then '<%retStruct%>;<%\n%>' - case e::_ then '<%getTempDeclMatchOutputName(tupleAssignExps, res, startIndexOutputs, 1)%> = <%retStruct%>;<%\n%>' - callRet - case SOME(e) then '<%res%> = <%daeExp(e,context,&preRes,&varDeclsCaseInner, &auxFunction)%>;<%\n%>') - let _ = (elementVars(c.localDecls) |> var => varInit(var, "", &varDeclsCaseInner, &preExpCaseInner, &varFrees, &auxFunction)) - <<<%match ty case MATCH(switch=SOME((n,_,ea))) - then - let name = switchIndex(listGet(c.patterns,n),ea) - (match name - case "default" then - << - <%name%>: { - <%prefix%>_default: OMC_LABEL_UNUSED; - >> - else - '<%name%>: {') - else - 'case <%i0%>: {'%> - <%varDeclsCaseInner%> - <%preExpCaseInner%> - <%patternMatching%> - <%assignments%> - <%&preGuardCheck%> - <%guardCheck%> - <% match c.jump - case 0 then "/* Pattern matching succeeded */" - else '<%ix%> += <%c.jump%>; /* Pattern matching succeeded; we may skip some cases if we fail */' - %> - <%stmts%> - <%modelicaLine(c.resultInfo)%> - <% if c.result then '<%preRes%><%caseRes%>' else '<%generateThrow()%>;<%\n%>' %> - <%endModelicaLine()%> - <%done%> = 1; - break; - }<%\n%> - >> -end daeExpMatchCases; - -template switchIndex(Pattern pattern, Integer extraArg) -::= - match pattern - case PAT_CALL(__) then 'case <%getValueCtor(index)%>' - case PAT_CONSTANT(exp=e as SCONST(__)) then 'case <%stringHashDjb2Mod(e.string,extraArg)%> /* <%e.string%> */' - case PAT_CONSTANT(exp=e as ICONST(__)) then 'case <%e.integer%>' - else 'default' -end switchIndex; - -template daeExpBox(Exp exp, Context context, Text &preExp, Text &varDecls, Text &auxFunction) - "Generates code for a match expression." -::= -match exp -case BOX(__) then - let ty = if isArrayType(typeof(exp)) then "modelica_array" else expTypeFromExpShort(exp) - let res = daeExp(exp,context,&preExp,&varDecls, &auxFunction) - 'mmc_mk_<%ty%>(<%res%>)' -end daeExpBox; - -template daeExpUnbox(Exp exp, Context context, Text &preExp, Text &varDecls, Text &auxFunction) - "Generates code for a match expression." -::= -match exp -case exp as UNBOX(__) then - let ty = expTypeShort(exp.ty) - let res = daeExp(exp.exp,context,&preExp,&varDecls, &auxFunction) - 'mmc_unbox_<%ty%>(<%res%>) /* DAE.UNBOX <%unparseType(exp.ty) %> */' -end daeExpUnbox; - -template daeExpSharedLiteral(Exp exp) - "Generates code for a match expression." -::= -match exp case exp as SHARED_LITERAL(__) then '_OMC_LIT<%exp.index%>' -end daeExpSharedLiteral; - - -// TODO: Optimize as in Codegen -// TODO: Use this function in other places where almost the same thing is hard -// coded -template arrayScalarRhs(Type ty, list subs, String arrName, Context context, - Text &preExp, Text &varDecls, Text &auxFunction) - "Helper to daeExpAsub." -::= - let arrayType = expTypeArray(ty) - let dimsLenStr = listLength(subs) - let dimsValuesStr = (subs |> exp => - daeDimensionExp(exp, context, &preExp, &varDecls, &auxFunction) - - ;separator=", ") - match arrayType - case "metatype_array" then - 'arrayGet(<%arrName%>,<%dimsValuesStr%>) /*arrayScalarRhs*/' - else - match context - case PARALLEL_FUNCTION_CONTEXT(__) then - << - (*<%arrayType%>_element_addr_c99_<%dimsLenStr%>(&<%arrName%>, <%dimsLenStr%>, <%dimsValuesStr%>)) - >> - else - << - (*<%arrayType%>_element_addr(&<%arrName%>, <%dimsLenStr%>, <%dimsValuesStr%>)) - >> -end arrayScalarRhs; - -template daeExpList(Exp exp, Context context, Text &preExp, - Text &varDecls, Text &auxFunction) - "Generates code for a meta modelica list expression." -::= -match exp -case LIST(__) then - let tmp = tempDecl("modelica_metatype", &varDecls) - let expPart = daeExpListToCons(valList, context, &preExp, &varDecls, &auxFunction) - let &preExp += '<%tmp%> = <%expPart%>;<%\n%>' - tmp -end daeExpList; - - -template daeExpListToCons(list listItems, Context context, Text &preExp, - Text &varDecls, Text &auxFunction) - "Helper to daeExpList." -::= - match listItems - case {} then "MMC_REFSTRUCTLIT(mmc_nil)" - case e :: rest then - let expPart = daeExp(e, context, &preExp, &varDecls, &auxFunction) - let restList = daeExpListToCons(rest, context, &preExp, &varDecls, &auxFunction) - << - mmc_mk_cons(<%expPart%>, <%restList%>) - >> -end daeExpListToCons; - - -template daeExpCons(Exp exp, Context context, Text &preExp, - Text &varDecls, Text &auxFunction) - "Generates code for a meta modelica cons expression." -::= -match exp -case CONS(__) then - let tmp = tempDecl("modelica_metatype", &varDecls) - let carExp = daeExp(car, context, &preExp, &varDecls, &auxFunction) - - let cdrExp = daeExp(cdr, context, &preExp, &varDecls, &auxFunction) - let &preExp += '<%tmp%> = mmc_mk_cons(<%carExp%>, <%cdrExp%>);<%\n%>' - tmp -end daeExpCons; - -template tempDeclTuple(DAE.Type inType, Text &varDecls) -::= - match inType - case T_TUPLE(__) then - let tmpVar = 'tmp<%System.tmpTick()%>' - let &varDecls += - << - struct { - <%types |> ty hasindex i1 fromindex 1 => '<%expTypeModelica(ty)%> c<%i1%>;<%\n%>'%> - } <%tmpVar%>; - >> - tmpVar - else tempDecl(expTypeArrayIf(inType),&varDecls) -end tempDeclTuple; - -template daeExpTuple(Exp exp, Context context, Text &preExp, Text &varDecls, Text &auxFunction) - "Generates code for a meta modelica tuple expression." -::= -match exp -case TUPLE(__) then - let tmpVar = tempDeclTuple(typeof(exp),&varDecls) - let tmp = (PR |> e hasindex i1 fromindex 1 => '<%tmpVar%>.c<%i1%> = <%daeExp(e, context, &preExp, &varDecls, &auxFunction)%>;<%\n%>') - let &preExp += tmp - tmpVar -end daeExpTuple; - -template daeExpMetaTuple(Exp exp, Context context, Text &preExp, - Text &varDecls, Text &auxFunction) - "Generates code for a meta modelica tuple expression." -::= -match exp -case META_TUPLE(__) then - let start = daeExpMetaHelperBoxStart(listLength(listExp)) - let args = (listExp |> e => daeExp(e, context, &preExp, &varDecls, &auxFunction) - ;separator=", ") - let tmp = tempDecl("modelica_metatype", &varDecls) - let &preExp += '<%tmp%> = mmc_mk_box<%start%>0<%if args then ", "%><%args%>);<%\n%>' - tmp -end daeExpMetaTuple; - - -template daeExpMetaOption(Exp exp, Context context, Text &preExp, Text &varDecls, Text &auxFunction) - "Generates code for a meta modelica option expression." -::= - match exp - case META_OPTION(exp=NONE()) then - "mmc_mk_none()" - case META_OPTION(exp=SOME(e)) then - let expPart = daeExp(e, context, &preExp, &varDecls, &auxFunction) - 'mmc_mk_some(<%expPart%>)' -end daeExpMetaOption; - - -template daeExpMetarecordcall(Exp exp, Context context, Text &preExp, Text &varDecls, Text &auxFunction) - "Generates code for a meta modelica record call expression." -::= -match exp -case METARECORDCALL(__) then - let newIndex = getValueCtor(index) - let argsStr = if args then - ', <%args |> exp => - daeExp(exp, context, &preExp, &varDecls, &auxFunction) - ;separator=", "%>' - else - "" - let box = 'mmc_mk_box<%daeExpMetaHelperBoxStart(incrementInt(listLength(args), 1))%><%newIndex%>, &<%underscorePath(path)%>__desc<%argsStr%>)' - let tmp = tempDecl("modelica_metatype", &varDecls) - let &preExp += '<%tmp%> = <%box%>;<%\n%>' - tmp -end daeExpMetarecordcall; - -template daeExpMetaHelperBoxStart(Integer numVariables) - "Helper to determine how mmc_mk_box should be called." -::= - if intGt(numVariables,20) then '(<%numVariables%>, ' else '<%numVariables%>(' -end daeExpMetaHelperBoxStart; - -template tempDecl(String ty, Text &varDecls) - "Declares a temporary variable in varDecls and returns the name." -::= - let newVar = - match ty /* TODO! FIXME! UGLY! UGLY! hack! */ - case "modelica_metatype" - case "metamodelica_string" - case "metamodelica_string_const" - then 'tmpMeta[<%System.tmpTickIndex(1)%>]' - else - let newVarIx = 'tmp<%System.tmpTick()%>' - let &varDecls += '<%ty%> <%newVarIx%>;<%\n%>' - newVarIx - newVar -end tempDecl; - -template tempDeclZero(String ty, Text &varDecls) - "Declares a temporary variable initialized to zero in varDecls and returns the name." -::= - let newVar - = - match ty /* TODO! FIXME! UGLY! UGLY! hack! */ - case "modelica_metatype" - case "metamodelica_string" - case "metamodelica_string_const" - then 'tmpMeta[<%System.tmpTickIndex(1)%>]' - else - let newVarIx = 'tmp<%System.tmpTick()%>' - let &varDecls += '<%ty%> <%newVarIx%> = 0;<%\n%>' - newVarIx - newVar -end tempDeclZero; - -template tempDeclMatchInput(String ty, String prefix, String startIndex, String index, Text &varDecls) - "Declares a temporary variable in varDecls for variables in match input list and returns the name." -::= - let newVar - = - match ty /* TODO! FIXME! UGLY! UGLY! hack! */ - case "modelica_metatype" - case "metamodelica_string" - case "metamodelica_string_const" - then 'tmpMeta[<%startIndex%>+<%index%>]' - else - let newVarIx = '<%prefix%>_in<%index%>' - let &varDecls += '<%ty%> <%newVarIx%>;<%\n%>' - newVarIx - newVar -end tempDeclMatchInput; - -template getTempDeclMatchInputName(list inputs, String prefix, String startIndex, Integer index) - "Returns the name of the temporary variable from the match input list." -::= - let typ = '<%expTypeFromExpModelica(listGet(inputs, index))%>' - let newVar = - match typ /* TODO! FIXME! UGLY! UGLY! hack! */ - case "modelica_metatype" - case "metamodelica_string" - case "metamodelica_string_const" - then 'tmpMeta[<%startIndex%>+<%intSub(index, 1)%>]' - else - let newVarIx = '<%prefix%>_in<%intSub(index, 1)%>' - newVarIx - newVar -end getTempDeclMatchInputName; - -template tempDeclMatchOutput(String ty, String prefix, String startIndex, String index, Text &varDecls) - "Declares a temporary variable in varDecls for variables in match output list and returns the name." -::= - let newVar - = - match ty /* TODO! FIXME! UGLY! UGLY! hack! */ - case "modelica_metatype" - case "metamodelica_string" - case "metamodelica_string_const" - then 'tmpMeta[<%startIndex%>+<%index%>]' - else - let newVarIx = '<%prefix%>_c<%index%>' - let &varDecls += '<%ty%> <%newVarIx%> __attribute__((unused)) = 0;<%\n%>' - newVarIx - newVar -end tempDeclMatchOutput; - -template getTempDeclMatchOutputName(list outputs, String prefix, String startIndex, Integer index) - "Returns the name of the temporary variable from the match input list." -::= - let typ = '<%expTypeFromExpModelica(listGet(outputs, index))%>' - let newVar = - match typ /* TODO! FIXME! UGLY! UGLY! hack! */ - case "modelica_metatype" - case "metamodelica_string" - case "metamodelica_string_const" - then 'tmpMeta[<%startIndex%>+<%intSub(index, 1)%>]' - else - let newVarIx = '<%prefix%>_c<%intSub(index, 1)%>' - newVarIx - newVar -end getTempDeclMatchOutputName; - -template varType(Variable var) - "Generates type for a variable." -::= -match var -case var as VARIABLE(parallelism = NON_PARALLEL()) then - if instDims then - expTypeArray(var.ty) - else - expTypeArrayIf(var.ty) -case var as VARIABLE(parallelism = PARGLOBAL()) then - if instDims then - 'device_<%expTypeArray(var.ty)%>' - else - '<%expTypeArrayIf(var.ty)%>' -case var as VARIABLE(parallelism = PARLOCAL()) then - if instDims then - 'device_local_<%expTypeArray(var.ty)%>' - else - expTypeArrayIf(var.ty) -end varType; - -template varTypeBoxed(Variable var) -::= -match var -case VARIABLE(__) then 'modelica_metatype' -case FUNCTION_PTR(__) then 'modelica_fnptr' -end varTypeBoxed; - - - -template expTypeRW(DAE.Type type) - "Helper to writeOutVarRecordMembers." -::= - match type - case T_INTEGER(__) then "TYPE_DESC_INT" - case T_REAL(__) then "TYPE_DESC_REAL" - case T_STRING(__) then "TYPE_DESC_STRING" - case T_BOOL(__) then "TYPE_DESC_BOOL" - case T_ENUMERATION(__) then "TYPE_DESC_INT" - case T_ARRAY(__) then '<%expTypeRW(ty)%>_ARRAY' - case T_COMPLEX(complexClassType=RECORD(__)) - then "TYPE_DESC_RECORD" - case T_METATYPE(__) case T_METABOXED(__) then "TYPE_DESC_MMC" -end expTypeRW; - -template expTypeShort(DAE.Type type) - "Generate type helper." -::= - match type - case T_INTEGER(__) then "integer" - case T_REAL(__) then "real" - case T_STRING(__) then "string" - case T_BOOL(__) then "boolean" - case T_ENUMERATION(__) then "integer" - case T_SUBTYPE_BASIC(__) then expTypeShort(complexType) - case T_ARRAY(__) then expTypeShort(ty) - case T_COMPLEX(complexClassType=EXTERNAL_OBJ(__)) then "complex" - case T_COMPLEX(__) then '<%underscorePath(ClassInf.getStateName(complexClassType))%>' - case T_METAUNIONTYPE(__) - case T_METAARRAY(__) - case T_METALIST(__) - case T_METATUPLE(__) - case T_METAOPTION(__) - case T_METAPOLYMORPHIC(__) - case T_METATYPE(__) - case T_METABOXED(__) then "metatype" - case T_FUNCTION(__) - case T_FUNCTION_REFERENCE_FUNC(__) - case T_FUNCTION_REFERENCE_VAR(__) then "fnptr" - case T_UNKNOWN(__) then if acceptMetaModelicaGrammar() /* TODO: Don't do this to me! */ - then "complex /* assumming void* for unknown type! when +g=MetaModelica */ " - else "real /* assumming real for uknown type! */" - case T_ANYTYPE(__) then "complex" /* TODO: Don't do this to me! */ - else error(sourceInfo(),'expTypeShort: <%unparseType(type)%>') -end expTypeShort; - -template mmcTypeShort(DAE.Type type) -::= - match type - case T_INTEGER(__) then "integer" - case T_REAL(__) then "real" - case T_STRING(__) then "string" - case T_BOOL(__) then "integer" - case T_ENUMERATION(__) then "integer" - case T_ARRAY(__) then "array" - case T_METAUNIONTYPE(__) - case T_METATYPE(__) - case T_METALIST(__) - case T_METAARRAY(__) - case T_METAPOLYMORPHIC(__) - case T_METAOPTION(__) - case T_METATUPLE(__) - case T_METABOXED(__) then "metatype" - case T_FUNCTION_REFERENCE_VAR(__) then "fnptr" - - case T_COMPLEX(__) then "metatype" - else error(sourceInfo(), 'mmcTypeShort:ERROR <%unparseType(type)%>') -end mmcTypeShort; - - -template expType(DAE.Type ty, Boolean array) - "Generate type helper." -::= - match array - case true then expTypeArray(ty) - case false then expTypeModelica(ty) -end expType; - - -template expTypeModelica(DAE.Type ty) - "Generate type helper." -::= - expTypeFlag(ty, 2) -end expTypeModelica; - - -template expTypeArray(DAE.Type ty) - "Generate type helper." -::= - expTypeFlag(ty, 3) -end expTypeArray; - - -template expTypeArrayIf(DAE.Type ty) - "Generate type helper." -::= - expTypeFlag(ty, 4) -end expTypeArrayIf; - - -template expTypeFromExpShort(Exp exp) - "Generate type helper." -::= - expTypeFromExpFlag(exp, 1) -end expTypeFromExpShort; - - -template expTypeFromExpModelica(Exp exp) - "Generate type helper." -::= - expTypeFromExpFlag(exp, 2) -end expTypeFromExpModelica; - - -template expTypeFromExpArray(Exp exp) - "Generate type helper." -::= - expTypeFromExpFlag(exp, 3) -end expTypeFromExpArray; - -template expTypeFromExpArrayIf(Exp exp) - "Generate type helper." -::= - expTypeFromExpFlag(exp, 4) -end expTypeFromExpArrayIf; - -template expTypeFlag(DAE.Type ty, Integer flag) - "Generate type helper." -::= - match flag - case 1 then - // we want the short type - expTypeShort(ty) - case 2 then - // we want the "modelica type" - match ty case T_COMPLEX(complexClassType=EXTERNAL_OBJ(__)) then - 'modelica_<%expTypeShort(ty)%>' - else match ty case T_COMPLEX(__) then - '<%underscorePath(ClassInf.getStateName(complexClassType))%>' - else match ty case T_ARRAY(ty = t as T_COMPLEX(__)) then - expTypeShort(t) - else - 'modelica_<%expTypeShort(ty)%>' - case 3 then - // we want the "array type" - '<%expTypeShort(ty)%>_array' - case 4 then - // we want the "array type" only if type is array, otherwise "modelica type" - (match ty - case T_ARRAY(__) then '<%expTypeShort(ty)%>_array' - else expTypeFlag(ty, 2)) - case 8 then - (match ty - case T_ARRAY(__) then '<%expTypeFlag(ty,8)%>*' - case T_INTEGER(__) then 'int' - case T_BOOL(__) then 'int' - case T_REAL(__) then 'double' - case T_STRING(__) then 'const char*' - case T_SUBTYPE_BASIC(__) then '<%expTypeFlag(complexType,8)%>*' - else error(sourceInfo(),'I do not know the external type of <%unparseType(ty)%>')) -end expTypeFlag; - -template expTypeFromExpFlag(Exp exp, Integer flag) - "Generate type helper." -::= - match exp - case ICONST(__) then match flag case 8 then "int" case 1 then "integer" else "modelica_integer" - case RCONST(__) then match flag case 1 then "real" else "modelica_real" - case SCONST(__) then match flag case 1 then "string" else "modelica_string" - case BCONST(__) then match flag case 1 then "boolean" else "modelica_boolean" - case ENUM_LITERAL(__) then match flag case 8 then "int" case 1 then "integer" else "modelica_integer" - case e as BINARY(__) - case e as UNARY(__) - case e as LBINARY(__) - case e as LUNARY(__) then expTypeFromOpFlag(e.operator, flag) - case e as RELATION(__) then match flag case 1 then "boolean" else "modelica_boolean" - case IFEXP(__) then expTypeFromExpFlag(expThen, flag) - case CALL(attr=CALL_ATTR(__)) then expTypeFlag(attr.ty, flag) - case c as RECORD(__) then expTypeFlag(c.ty, flag) - case c as ARRAY(__) - case c as MATRIX(__) - case c as RANGE(__) - case c as CAST(__) - case c as TSUB(__) - case c as CREF(__) - case c as CODE(__) then expTypeFlag(c.ty, flag) - case c as ASUB(__) then expTypeFlag(typeof(c), flag) - case REDUCTION(__) then expTypeFlag(typeof(exp), flag) - case CONS(__) - case LIST(__) - case SIZE(__) then expTypeFlag(typeof(exp), flag) - - case META_TUPLE(__) - case META_OPTION(__) - case MATCHEXPRESSION(__) - case METARECORDCALL(__) - case BOX(__) then match flag case 1 then "metatype" else "modelica_metatype" - case c as UNBOX(__) then expTypeFlag(c.ty, flag) - case c as SHARED_LITERAL(__) then expTypeFromExpFlag(c.exp, flag) - else error(sourceInfo(), 'expTypeFromExpFlag(flag=<%flag%>):<%printExpStr(exp)%>') -end expTypeFromExpFlag; - - -template expTypeFromOpFlag(Operator op, Integer flag) - "Generate type helper." -::= - match op - case o as ADD(__) - case o as SUB(__) - case o as MUL(__) - case o as DIV(__) - case o as POW(__) - - case o as UMINUS(__) - case o as UMINUS_ARR(__) - case o as ADD_ARR(__) - case o as SUB_ARR(__) - case o as MUL_ARR(__) - case o as DIV_ARR(__) - case o as MUL_ARRAY_SCALAR(__) - case o as ADD_ARRAY_SCALAR(__) - case o as SUB_SCALAR_ARRAY(__) - case o as MUL_SCALAR_PRODUCT(__) - case o as MUL_MATRIX_PRODUCT(__) - case o as DIV_ARRAY_SCALAR(__) - case o as DIV_SCALAR_ARRAY(__) - case o as POW_ARRAY_SCALAR(__) - case o as POW_SCALAR_ARRAY(__) - case o as POW_ARR(__) - case o as POW_ARR2(__) - case o as LESS(__) - case o as LESSEQ(__) - case o as GREATER(__) - case o as GREATEREQ(__) - case o as EQUAL(__) - case o as NEQUAL(__) then - expTypeFlag(o.ty, flag) - case o as AND(__) - case o as OR(__) - case o as NOT(__) then - match flag case 1 then "boolean" else "modelica_boolean" - else error(sourceInfo(), 'expTypeFromOpFlag:ERROR') -end expTypeFromOpFlag; - -template dimension(Dimension d) -::= - match d - case DAE.DIM_BOOLEAN(__) then '2' - case DAE.DIM_ENUM(__) then size - case DAE.DIM_EXP(exp=e) then dimensionExp(e) - case DAE.DIM_INTEGER(__) then - if intEq(integer, -1) then - error(sourceInfo(),"Negeative dimension(unknown dimensions) may not be part of generated code. This is most likely an error on the part of OpenModelica. Please submit a detailed bug-report.") - else - integer - case DAE.DIM_UNKNOWN(__) then error(sourceInfo(),"Unknown dimensions may not be part of generated code. This is most likely an error on the part of OpenModelica. Please submit a detailed bug-report.") - else error(sourceInfo(), 'dimension: INVALID_DIMENSION') -end dimension; - -template dimensionExp(DAE.Exp dimExp) -::= - match dimExp - case DAE.CREF(componentRef = cr) then cref(cr) - else error(sourceInfo(), 'dimensionExp: INVALID_DIMENSION <%printExpStr(dimExp)%>') -end dimensionExp; - -template algStmtAssignPattern(DAE.Statement stmt, Context context, Text &varDecls, Text &auxFunction) - "Generates an assigment algorithm statement." -::= - match stmt - case s as STMT_ASSIGN(exp1=lhs as PATTERN(pattern=PAT_CALL_TUPLE(patterns=pat::patterns)),exp=CALL(attr=CALL_ATTR(ty=T_TUPLE(types=ty::tys)))) then - let &preExp = buffer "" - let &assignments1 = buffer "" - let &assignments = buffer "" - let &additionalOutputs = buffer "" - let &matchPhase = buffer "" - let _ = threadTuple(patterns,tys) |> (pat,ty) => match pat - case PAT_WILD(__) then - let &additionalOutputs += ", NULL" - "" - else - let v = tempDecl(expTypeArrayIf(ty), &varDecls) - let &additionalOutputs += ', &<%v%>' - let &matchPhase += patternMatch(pat,v,generateThrow(),&varDecls,&assignments) - "" - let expPart = daeExpCallTuple(s.exp,additionalOutputs,context, &preExp, &varDecls, &auxFunction) - match pat - case PAT_WILD(__) then '/* Pattern-matching tuple assignment, wild first pattern */<%\n%><%preExp%><%expPart%>;<%\n%><%matchPhase%><%assignments%>' - else - let v = tempDecl(expTypeArrayIf(ty), &varDecls) - let res = patternMatch(pat,v,generateThrow(),&varDecls,&assignments1) - << - /* Pattern-matching tuple assignment */ - <%preExp%> - <%v%> = <%expPart%>; - <%res%><%assignments1%><%matchPhase%><%assignments%> - >> - case s as STMT_ASSIGN(exp1=lhs as PATTERN(pattern=PAT_WILD(__))) then - error(sourceInfo(),'Improve simplifcation, got pattern assignment _ = <%printExpStr(exp)%>, expected NORETCALL') - case s as STMT_ASSIGN(exp1=lhs as PATTERN(__)) then - let &preExp = buffer "" - let &assignments = buffer "" - let expPart = daeExp(s.exp, context, &preExp, &varDecls, &auxFunction) - let v = tempDecl(expTypeFromExpModelica(s.exp), &varDecls) - << - /* Pattern-matching assignment */ - <%preExp%> - <%v%> = <%expPart%>; - <%patternMatch(lhs.pattern,v,generateThrow(),&varDecls,&assignments)%><%assignments%> - >> -end algStmtAssignPattern; - -template patternMatch(Pattern pat, Text rhs, Text onPatternFail, Text &varDecls, Text &assignments) -::= - match pat - case PAT_WILD(__) then "" - case p as PAT_CONSTANT(__) - then - let &unboxBuf = buffer "" - let urhs = (match p.ty - case SOME(et) then unboxVariable(rhs, et, &unboxBuf, &varDecls) - else rhs - ) - <<<%unboxBuf%><%match p.exp - case c as ICONST(__) then 'if (<%c.integer%> != <%urhs%>) <%onPatternFail%>;<%\n%>' - case c as RCONST(__) then 'if (<%c.real%> != <%urhs%>) <%onPatternFail%>;<%\n%>' - case c as SCONST(__) then - let escstr = Util.escapeModelicaStringToCString(c.string) - 'if (<%unescapedStringLength(escstr)%> != MMC_STRLEN(<%urhs%>) || strcmp("<%escstr%>", MMC_STRINGDATA(<%urhs%>)) != 0) <%onPatternFail%>;<%\n%>' - case c as BCONST(__) then 'if (<%if c.bool then 1 else 0%> != <%urhs%>) <%onPatternFail%>;<%\n%>' - case c as LIST(valList = {}) then 'if (!listEmpty(<%urhs%>)) <%onPatternFail%>;<%\n%>' - case c as META_OPTION(exp = NONE()) then 'if (!optionNone(<%urhs%>)) <%onPatternFail%>;<%\n%>' - case c as ENUM_LITERAL() then 'if (<%c.index%> != <%urhs%>) <%onPatternFail%>;<%\n%>' - else error(sourceInfo(), 'UNKNOWN_CONSTANT_PATTERN <%printExpStr(p.exp)%>') - %>>> - case p as PAT_SOME(__) then - let tvar = tempDecl("modelica_metatype", &varDecls) - <)) <%onPatternFail%>; - <%tvar%> = MMC_FETCH(MMC_OFFSET(MMC_UNTAGPTR(<%rhs%>), 1)); - <%patternMatch(p.pat,tvar,onPatternFail,&varDecls,&assignments)%>>> - case PAT_CONS(__) then - let tvarHead = tempDecl("modelica_metatype", &varDecls) - let tvarTail = tempDecl("modelica_metatype", &varDecls) - <)) <%onPatternFail%>; - <%tvarHead%> = MMC_CAR(<%rhs%>); - <%tvarTail%> = MMC_CDR(<%rhs%>); - <%patternMatch(head,tvarHead,onPatternFail,&varDecls,&assignments)%><%patternMatch(tail,tvarTail,onPatternFail,&varDecls,&assignments)%>>> - case PAT_META_TUPLE(__) - then - (patterns |> p hasindex i1 fromindex 1 => - match p - case PAT_WILD(__) then "" - else - let tvar = tempDecl("modelica_metatype", &varDecls) - <<<%tvar%> = MMC_FETCH(MMC_OFFSET(MMC_UNTAGPTR(<%rhs%>), <%i1%>)); - <%patternMatch(p,tvar,onPatternFail,&varDecls,&assignments)%> - >>; empty /* increase the counter even if no output is produced */) - case PAT_CALL_TUPLE(__) - then - // misnomer. Call expressions no longer return tuples using these structs. match-expressions and if-expressions converted to Modelica tuples do - (patterns |> p hasindex i1 fromindex 1 => - match p - case PAT_WILD(__) then "" - else - let nrhs = '<%rhs%>.c<%i1%>' - patternMatch(p,nrhs,onPatternFail,&varDecls,&assignments) - ; empty /* increase the counter even if no output is produced */ - ) - case PAT_CALL_NAMED(__) - then - <<<%patterns |> (p,n,t) => - match p - case PAT_WILD(__) then "" - else - let tvar = tempDecl(expTypeArrayIf(t), &varDecls) - <<<%tvar%> = <%rhs%>._<%n%>; - <%patternMatch(p,tvar,onPatternFail,&varDecls,&assignments)%> - >>%> - >> - case PAT_CALL(__) - then - <<<%if not knownSingleton then 'if (mmc__uniontype__metarecord__typedef__equal(<%rhs%>,<%index%>,<%listLength(patterns)%>) == 0) <%onPatternFail%>;<%\n%>'%><% - (patterns |> p hasindex i2 fromindex 2 => - match p - case PAT_WILD(__) then "" - else - let tvar = tempDecl("modelica_metatype", &varDecls) - <<<%tvar%> = MMC_FETCH(MMC_OFFSET(MMC_UNTAGPTR(<%rhs%>), <%i2%>)); - <%patternMatch(p,tvar,onPatternFail,&varDecls,&assignments)%> - >> ;empty) /* increase the counter even if no output is produced */ - %> - >> - case p as PAT_AS_FUNC_PTR(__) then - let &assignments += '_<%p.id%> = <%rhs%>;<%\n%>' - <<<%patternMatch(p.pat,rhs,onPatternFail,&varDecls,&assignments)%> - >> - case p as PAT_AS(ty = NONE()) then - let &assignments += '_<%p.id%> = <%rhs%>;<%\n%>' - <<<%patternMatch(p.pat,rhs,onPatternFail,&varDecls,&assignments)%> - >> - case p as PAT_AS(ty = SOME(et)) then - let &unboxBuf = buffer "" - let &assignments += '_<%p.id%> = <%unboxVariable(rhs, et, &unboxBuf, &varDecls)%> /* pattern as ty=<%unparseType(et)%> */;<%\n%>' - <<<%&unboxBuf%> - <%patternMatch(p.pat,rhs,onPatternFail,&varDecls,&assignments)%> - >> - else error(sourceInfo(), 'UNKNOWN_PATTERN /* rhs: <%rhs%> */<%\n%>') -end patternMatch; - -template infoArgs(SourceInfo info) -::= - match info - case SOURCEINFO(__) then '"<%Util.escapeModelicaStringToCString(testsuiteFriendly(fileName))%>",<%lineNumberStart%>,<%columnNumberStart%>,<%lineNumberEnd%>,<%columnNumberEnd%>,<%if isReadOnly then 1 else 0%>' -end infoArgs; - -template assertCommon(Exp condition, list messages, Exp level, Context context, Text &varDecls, Text &auxFunction, builtin.SourceInfo info) -::= - let &preExpCond = buffer "" - let condVar = daeExp(condition, context, &preExpCond, &varDecls, &auxFunction) - let &preExpMsg = buffer "" - let msgVar = messages |> message => expToFormatString(message,context,&preExpMsg,&varDecls,&auxFunction) ; separator = ", " - let eqnsindx = match context case FUNCTION_CONTEXT(__) then '' else 'equationIndexes, ' - let AddionalFuncName = match context case FUNCTION_CONTEXT(__) then '' else '_withEquationIndexes' - let addInfoTextContext = match context case FUNCTION_CONTEXT(__) then '' else '<%\n%>omc_assert_warning(info, "The following assertion has been violated at time %f\n<%Util.escapeModelicaStringToCString(printExpStr(condition))%>", time);' - let omcAssertFunc = match level case ENUM_LITERAL(index=2) then 'omc_assert_warning<%AddionalFuncName%>(' else 'omc_assert<%AddionalFuncName%>(threadData, ' - let warningTriggered = tempDeclZero("static int", &varDecls) - let TriggerIf = match level case ENUM_LITERAL(index=2) then 'if(!<%warningTriggered%>)<%\n%>' else '' - let TriggerVarSet = match level case ENUM_LITERAL(index=2) then '<%warningTriggered%> = 1;<%\n%>' else '' - << - <%TriggerIf%> - { - <%preExpCond%> - if(!<%condVar%>) - { - <%preExpMsg%> - FILE_INFO info = {<%infoArgs(info)%>};<%addInfoTextContext%> - <%omcAssertFunc%>info, <%eqnsindx%><%msgVar%>); - <%TriggerVarSet%> - } - }<%\n%> - >> -end assertCommon; - -template expToFormatString(Exp exp, Context context, Text &preExp, Text &varDecls, Text &auxFunction) -::= - 'MMC_STRINGDATA(<%daeExp(exp, context, &preExp, &varDecls, &auxFunction)%>)' -end expToFormatString; - -template assertCommonVar(Text condVar, Text msgVar, Context context, Text &preExpMsg, Text &varDecls, builtin.SourceInfo info) -::= - match context - case FUNCTION_CONTEXT(__) then - << - if(!<%condVar%>) - { - <%preExpMsg%> - FILE_INFO info = {<%infoArgs(info)%>}; - omc_assert(threadData, info, <%msgVar%>); - }<%\n%> - >> - else - << - if(!<%condVar%>) - { - <%preExpMsg%> - FILE_INFO info = {<%infoArgs(info)%>}; - omc_assert_warning(info, "The following assertion has been violated at time %f", time); - throwStreamPrintWithEquationIndexes(threadData, equationIndexes, <%msgVar%>); - }<%\n%> - >> -end assertCommonVar; - -template literalExpConst(Exp lit, Integer litindex, Text &preLit) "These should all be declared static X const" -::= - let name = '_OMC_LIT<%litindex%>' - let tmp = '_OMC_LIT_STRUCT<%litindex%>' - let meta = 'static modelica_metatype const <%name%>' - - match lit - case SCONST(__) then - let escstr = Util.escapeModelicaStringToCString(string) - /* TODO: Change this when OMC takes constant input arguments (so we cannot write to them) - The cost of not doing this properly is small (<257 bytes of constants) - match unescapedStringLength(escstr) - case 0 then '#define <%name%> mmc_emptystring' - case 1 then '#define <%name%> mmc_strings_len1["<%escstr%>"[0]]' - else */ - << - #define <%name%>_data "<%escstr%>" - static const MMC_DEFSTRINGLIT(<%tmp%>,<%unescapedStringLength(escstr)%>,<%name%>_data); - #define <%name%> MMC_REFSTRINGLIT(<%tmp%>) - >> - case lit as MATRIX(ty=ty as T_ARRAY(__)) - case lit as ARRAY(ty=ty as T_ARRAY(__)) then - let ndim = listLength(getDimensionSizes(ty)) - let sty = expTypeShort(ty) - let dims = (getDimensionSizes(ty) |> dim => dim ;separator=", ") - let data = flattenArrayExpToList(lit) |> exp => literalExpConstArrayVal(exp) ; separator=", " - << - static _index_t <%name%>_dims[<%ndim%>] = {<%dims%>}; - <% match data case "" then - << - static base_array_t const <%name%> = { - <%ndim%>, <%name%>_dims, (void*) 0 - }; - >> - else - << - static const modelica_<%sty%> <%name%>_data[] = {<%data%>}; - static <%sty%>_array const <%name%> = { - <%ndim%>, <%name%>_dims, (void*) <%name%>_data - }; - >> - %> - >> - case BOX(exp=exp as ICONST(__)) then - << - <%meta%> = MMC_IMMEDIATE(MMC_TAGFIXNUM(<%exp.integer%>)); - >> - case BOX(exp=exp as BCONST(__)) then - << - <%meta%> = MMC_IMMEDIATE(MMC_TAGFIXNUM(<%if exp.bool then 1 else 0%>)); - >> - case BOX(exp=exp as RCONST(__)) then - /* We need to use #define's to be C-compliant. Yea, total crap :) */ - << - static const MMC_DEFREALLIT(<%tmp%>,<%exp.real%>); - #define <%name%> MMC_REFREALLIT(<%tmp%>) - >> - case CONS(__) then - /* We need to use #define's to be C-compliant. Yea, total crap :) */ - << - static const MMC_DEFSTRUCTLIT(<%tmp%>,2,1) {<%literalExpConstBoxedVal(car,litindex + "_car", &preLit)%>,<%literalExpConstBoxedVal(cdr, litindex + "_cdr", &preLit)%>}}; - #define <%name%> MMC_REFSTRUCTLIT(<%tmp%>) - >> - case LIST(__) then - let x = listReverse(valList) |> v hasindex i fromindex 1 => - /* We need to use #define's to be C-compliant. Yea, total crap :) */ - 'static const MMC_DEFSTRUCTLIT(<%tmp + "_cons_" + i%>,2,1) {<%literalExpConstBoxedVal(v,tmp + "_elt_" + i, &preLit)%>,MMC_REFSTRUCTLIT(<% match i case 1 then "mmc_nil" else (tmp + "_cons_" + intSub(i,1))%>)}};<%\n%>' - << - <%x%> - #define <%name%> MMC_REFSTRUCTLIT(<%tmp%>_cons_<%listLength(valList)%>) - >> - case META_TUPLE(__) then - /* We need to use #define's to be C-compliant. Yea, total crap :) */ - << - static const MMC_DEFSTRUCTLIT(<%tmp%>,<%listLength(listExp)%>,0) {<%listExp |> exp hasindex i0 => literalExpConstBoxedVal(exp,litindex+"_"+i0, &preLit); separator=","%>}}; - #define <%name%> MMC_REFSTRUCTLIT(<%tmp%>) - >> - case META_OPTION(exp=SOME(exp)) then - /* We need to use #define's to be C-compliant. Yea, total crap :) */ - << - static const MMC_DEFSTRUCTLIT(<%tmp%>,1,1) {<%literalExpConstBoxedVal(exp,litindex+"_1", &preLit)%>}}; - #define <%name%> MMC_REFSTRUCTLIT(<%tmp%>) - >> - case METARECORDCALL(__) then - /* We need to use #define's to be C-compliant. Yea, total crap :) */ - let newIndex = getValueCtor(index) - << - static const MMC_DEFSTRUCTLIT(<%tmp%>,<%intAdd(1,listLength(args))%>,<%newIndex%>) {&<%underscorePath(path)%>__desc,<%args |> exp hasindex i0 => literalExpConstBoxedVal(exp,litindex+"_"+i0, &preLit); separator=","%>}}; - #define <%name%> MMC_REFSTRUCTLIT(<%tmp%>) - >> - else error(sourceInfo(), 'literalExpConst failed: <%printExpStr(lit)%>') -end literalExpConst; - -template literalExpConstBoxedVal(Exp lit, Text index, Text &preLit) -::= - let name = '_OMC_LIT<%index%>' - let tmp = '_OMC_LIT_STRUCT<%index%>' - match lit - case ICONST(__) then 'MMC_IMMEDIATE(MMC_TAGFIXNUM(<%integer%>))' - case ENUM_LITERAL(__) then 'MMC_IMMEDIATE(MMC_TAGFIXNUM(<%index%>))' - case lit as BCONST(__) then 'MMC_IMMEDIATE(MMC_TAGFIXNUM(<%if lit.bool then 1 else 0%>))' - case lit as RCONST(__) then - let &preLit += - << - static const MMC_DEFREALLIT(<%tmp%>,<%lit.real%>); - #define <%name%> MMC_REFREALLIT(<%tmp%>)<%\n%> - >> - name - case LIST(valList={}) then - << - MMC_REFSTRUCTLIT(mmc_nil) - >> - case META_OPTION(exp=NONE()) then - << - MMC_REFSTRUCTLIT(mmc_none) - >> - case lit as BOX(__) then literalExpConstBoxedVal(lit.exp, index, &preLit) - case lit as SHARED_LITERAL(__) then '_OMC_LIT<%lit.index%>' - else error(sourceInfo(), 'literalExpConstBoxedVal failed: <%printExpStr(lit)%>') -end literalExpConstBoxedVal; - -template literalExpConstArrayVal(Exp lit) -::= - match lit - case ICONST(__) then integer - case lit as BCONST(__) then if lit.bool then 1 else 0 - case RCONST(__) then real - case ENUM_LITERAL(__) then index - case lit as SHARED_LITERAL(__) then '_OMC_LIT<%lit.index%>' - else error(sourceInfo(), 'literalExpConstArrayVal failed: <%printExpStr(lit)%>') -end literalExpConstArrayVal; - -template equationInfo1(SimEqSystem eq, Text &preBuf, Text &eqnsDefines, Text &reverseProf) -::= - match eq - case SES_RESIDUAL(__) then - '{<%index%>,"SES_RESIDUAL <%index%>",0,NULL}' - case SES_SIMPLE_ASSIGN(__) then - let var = '<%cref(cref)%>__varInfo' - let &preBuf += 'const VAR_INFO** equationInfo_cref<%index%> = (const VAR_INFO**)calloc(1,sizeof(VAR_INFO*));<%\n%>' - let &preBuf += 'equationInfo_cref<%index%>[0] = &<%var%>;<%\n%>' - '{<%index%>,"SES_SIMPLE_ASSIGN <%index%>",1,equationInfo_cref<%index%>}' - case SES_ARRAY_CALL_ASSIGN(__) then - '{<%index%>,"SES_ARRAY_CALL_ASSIGN <%index%>",0,NULL}' - case SES_IFEQUATION(__) then - let branches = ifbranches |> (_,eqs) => (eqs |> eq => equationInfo1(eq,preBuf,eqnsDefines,reverseProf) + ',<%\n%>') - let elsebr = (elsebranch |> eq => equationInfo1(eq,preBuf,eqnsDefines,reverseProf) + ',<%\n%>') - '<%branches%><%elsebr%>{<%index%>,"SES_IFEQUATION <%index%>",0,NULL}' - case SES_ALGORITHM(__) then - '{<%index%>,"SES_ALGORITHM <%index%>", 0, NULL}' - case SES_WHEN(__) then - '{<%index%>,"SES_WHEN <%index%>", 0, NULL}' - // no dynamic tearing - case SES_LINEAR(lSystem=ls as LINEARSYSTEM(__), alternativeTearing=NONE()) then - let &eqnsDefines += functionSimProfDef(eq,System.tmpTick(),reverseProf) - let &preBuf += 'const VAR_INFO** equationInfo_crefs<%ls.index%> = (const VAR_INFO**)malloc(<%listLength(ls.vars)%>*sizeof(VAR_INFO*));<%\n%>' - let &preBuf += '<%ls.vars|>var hasindex i0 => 'equationInfo_crefs<%ls.index%>[<%i0%>] = &<%cref(varName(var))%>__varInfo;'; separator="\n"%>;' - '{<%ls.index%>,"linear system <%ls.index%> (size <%listLength(ls.vars)%>)", <%listLength(ls.vars)%>, equationInfo_crefs<%ls.index%>}' - case SES_NONLINEAR(nlSystem=nls as NONLINEARSYSTEM(__), alternativeTearing=NONE()) then - let residuals = SimCodeUtil.sortEqSystems(nls.eqs) |> e => (equationInfo1(e,preBuf,eqnsDefines,reverseProf) + ',<%\n%>') - let jac = match nls.jacobianMatrix case SOME(mat) then equationInfoMatrix(mat,preBuf,eqnsDefines,reverseProf) - let &eqnsDefines += functionSimProfDef(eq,System.tmpTick(),reverseProf) - let &preBuf += 'const VAR_INFO** equationInfo_crefs<%nls.index%> = (const VAR_INFO**)malloc(<%listLength(nls.crefs)%>*sizeof(VAR_INFO*));<%\n%>' - let &preBuf += '<%nls.crefs|>cr hasindex i0 => 'equationInfo_crefs<%nls.index%>[<%i0%>] = &<%cref(cr)%>__varInfo;'; separator="\n"%>;' - '<%residuals%>{<%nls.index%>,"residualFunc<%nls.index%> (size <%listLength(nls.crefs)%>)", <%listLength(nls.crefs)%>, equationInfo_crefs<%nls.index%>}<%if jac then ',<%\n%><%jac%>'%>' - // dynamic tearing - case SES_LINEAR(lSystem=ls as LINEARSYSTEM(__), alternativeTearing = SOME(at as LINEARSYSTEM(__))) then - // for strict tearing set - let &eqnsDefines += functionSimProfDef(eq,System.tmpTick(),reverseProf) - let &preBuf += 'const VAR_INFO** equationInfo_crefs<%ls.index%> = (const VAR_INFO**)malloc(<%listLength(ls.vars)%>*sizeof(VAR_INFO*));<%\n%>' - let &preBuf += '<%ls.vars|>var hasindex i0 => 'equationInfo_crefs<%ls.index%>[<%i0%>] = &<%cref(varName(var))%>__varInfo;'; separator="\n"%>;' - // for casual tearing set - // let &eqnsDefines += functionSimProfDef(eq,System.tmpTick(),reverseProf) - let &preBuf += 'const VAR_INFO** equationInfo_crefs<%at.index%> = (const VAR_INFO**)malloc(<%listLength(at.vars)%>*sizeof(VAR_INFO*));<%\n%>' - let &preBuf += '<%at.vars|>var hasindex i0 => 'equationInfo_crefs<%at.index%>[<%i0%>] = &<%cref(varName(var))%>__varInfo;'; separator="\n"%>;' - << - {<%ls.index%>,"linear system <%ls.index%> (size <%listLength(ls.vars)%>)", <%listLength(ls.vars)%>, equationInfo_crefs<%ls.index%>} - {<%at.index%>,"linear system <%at.index%> (size <%listLength(at.vars)%>)", <%listLength(at.vars)%>, equationInfo_crefs<%at.index%>} - >> - case SES_NONLINEAR(nlSystem=nls as NONLINEARSYSTEM(__), alternativeTearing = SOME(at as NONLINEARSYSTEM(__))) then - // for strict tearing set - let residuals = SimCodeUtil.sortEqSystems(nls.eqs) |> e => (equationInfo1(e,preBuf,eqnsDefines,reverseProf) + ',<%\n%>') - let jac = match nls.jacobianMatrix case SOME(mat) then equationInfoMatrix(mat,preBuf,eqnsDefines,reverseProf) - let &eqnsDefines += functionSimProfDef(eq,System.tmpTick(),reverseProf) - let &preBuf += 'const VAR_INFO** equationInfo_crefs<%nls.index%> = (const VAR_INFO**)malloc(<%listLength(nls.crefs)%>*sizeof(VAR_INFO*));<%\n%>' - let &preBuf += '<%nls.crefs|>cr hasindex i0 => 'equationInfo_crefs<%nls.index%>[<%i0%>] = &<%cref(cr)%>__varInfo;'; separator="\n"%>;' - // for casual tearing set - let residuals2 = SimCodeUtil.sortEqSystems(at.eqs) |> e => (equationInfo1(e,preBuf,eqnsDefines,reverseProf) + ',<%\n%>') - let jac2 = match at.jacobianMatrix case SOME(mat) then equationInfoMatrix(mat,preBuf,eqnsDefines,reverseProf) - // let &eqnsDefines += functionSimProfDef(eq,System.tmpTick(),reverseProf) - let &preBuf += 'const VAR_INFO** equationInfo_crefs<%at.index%> = (const VAR_INFO**)malloc(<%listLength(at.crefs)%>*sizeof(VAR_INFO*));<%\n%>' - let &preBuf += '<%at.crefs|>cr hasindex i0 => 'equationInfo_crefs<%at.index%>[<%i0%>] = &<%cref(cr)%>__varInfo;'; separator="\n"%>;' - << - <%residuals%>{<%nls.index%>,"residualFunc<%nls.index%> (size <%listLength(nls.crefs)%>)", <%listLength(nls.crefs)%>, equationInfo_crefs<%nls.index%>}<%if jac then ',<%\n%><%jac%>'%> - <%residuals2%>{<%at.index%>,"residualFunc<%at.index%> (size <%listLength(at.crefs)%>)", <%listLength(at.crefs)%>, equationInfo_crefs<%at.index%>}<%if jac2 then ',<%\n%><%jac2%>'%> - >> - case SES_MIXED(__) then - let conEqn = equationInfo1(cont,preBuf,eqnsDefines,reverseProf) - let &eqnsDefines += functionSimProfDef(eq,System.tmpTick(),reverseProf) - let &preBuf += '<%\n%>const VAR_INFO** equationInfo_crefs<%index%> = (const VAR_INFO**)malloc(<%listLength(discVars)%>*sizeof(VAR_INFO*));<%\n%>' - let &preBuf += '<%discVars|>var hasindex i0 => 'equationInfo_crefs<%index%>[<%i0%>] = &<%cref(varName(var))%>__varInfo;'; separator="\n"%>;' - '<%conEqn%>,<%\n%>{<%index%>,"MIXED<%index%>", <%listLength(discVars)%>, equationInfo_crefs<%index%>}' - else '<%error(sourceInfo(), 'Unkown Equation Type in equationInfo1')%>' -end equationInfo1; + case SES_MIXED(__) then + let conEqn = equationInfo1(cont,preBuf,eqnsDefines,reverseProf) + let &eqnsDefines += functionSimProfDef(eq,System.tmpTick(),reverseProf) + let &preBuf += '<%\n%>const VAR_INFO** equationInfo_crefs<%index%> = (const VAR_INFO**)malloc(<%listLength(discVars)%>*sizeof(VAR_INFO*));<%\n%>' + let &preBuf += '<%discVars|>var hasindex i0 => 'equationInfo_crefs<%index%>[<%i0%>] = &<%cref(varName(var))%>__varInfo;'; separator="\n"%>;' + '<%conEqn%>,<%\n%>{<%index%>,"MIXED<%index%>", <%listLength(discVars)%>, equationInfo_crefs<%index%>}' + else '<%error(sourceInfo(), 'Unkown Equation Type in equationInfo1')%>' +end equationInfo1; template equationInfoMatrix(JacobianMatrix jacobianMatrix, Text &preBuf, Text &eqnsDefines, Text &reverseProf) ::= @@ -11479,26 +5100,6 @@ template getCausality(Causality c) case INPUT(__) then "input" end getCausality; -template addRootsTempArray() -::= - match System.tmpTickMaximum(1) - case 0 then "" - case i then /* TODO: Find out where we add tmpIndex but discard its use causing us to generate unused tmpMeta with size 1 */ - << - modelica_metatype tmpMeta[<%i%>] __attribute__((unused)) = {0}; - >> -end addRootsTempArray; - -template modelicaLine(builtin.SourceInfo info) -::= - if boolOr(acceptMetaModelicaGrammar(), Flags.isSet(Flags.GEN_DEBUG_SYMBOLS)) then '/*#modelicaLine <%infoStr(info)%>*/<%\n%>' -end modelicaLine; - -template endModelicaLine() -::= - if boolOr(acceptMetaModelicaGrammar(), Flags.isSet(Flags.GEN_DEBUG_SYMBOLS)) then '/*#endModelicaLine*/<%\n%>' -end endModelicaLine; - /***************************************************************************** * SECTION: GENERATE OPTIMIZATION IN SIMULATION FILE *****************************************************************************/ @@ -11641,108 +5242,6 @@ template optimizationComponents1(ClassAttributes classAttribute, SimCode simCode else error(sourceInfo(), 'Unknown Constraint List') end optimizationComponents1; -/* public */ template generateEntryPoint(Path entryPoint, String url) "used in Compiler/Script/CevalScript.mo" -::= -let name = ("omc_" + underscorePath(entryPoint)) -<< -/* This is an automatically generated entry point to a MetaModelica function */ - -#if defined(__cplusplus) -extern "C" { -#endif - -#if defined(OMC_ENTRYPOINT_STATIC) - -#include -#include - -DLLImport extern int __omc_main(int argc, char **argv); - -int main(int argc, char **argv) -{ - return __omc_main(argc, argv); -} - -#else - -#include -#include -extern void <%name%>(threadData_t*,modelica_metatype); - -void (*omc_assert)(threadData_t*,FILE_INFO info,const char *msg,...) __attribute__((noreturn)) = omc_assert_function; -void (*omc_assert_warning)(FILE_INFO info,const char *msg,...) = omc_assert_warning_function; -void (*omc_terminate)(FILE_INFO info,const char *msg,...) = omc_terminate_function; -void (*omc_throw)(threadData_t*) __attribute__ ((noreturn)) = omc_throw_function; - -#ifdef _OPENMP -#include -/* Hack to make gcc-4.8 link in the OpenMP runtime if -fopenmp is given */ -int (*force_link_omp)(void) = omp_get_num_threads; -#endif - -static int rml_execution_failed() -{ - fflush(NULL); - fprintf(stderr, "Execution failed!\n"); - fflush(NULL); - return 1; -} - -DLLExport int __omc_main(int argc, char **argv) -{ - MMC_INIT(); - { - void *lst = mmc_mk_nil(); - int i = 0; - - for (i=argc-1; i>0; i--) { - lst = mmc_mk_cons(mmc_mk_scon(argv[i]), lst); - } - - <%mainTop('<%name%>(threadData, lst);',url)%> - } - - <%if Flags.isSet(HPCOM) then "terminateHpcOmThreads();" %> - fflush(NULL); - EXIT(0); - return 0; -} - -#endif - -#if defined(__cplusplus) -} /* end extern "C" */ -#endif - ->> -end generateEntryPoint; - -/* Dimensions need to return expressions that are different than for normal expressions. - * The reason is that dimensions use 1-based indexing, but Boolean indexes start at 0 - */ -template daeDimensionExp(Exp exp, Context context, Text &preExp, Text &varDecls, Text &auxFunction) -::= - let res = daeExp(exp,context,&preExp,&varDecls,&auxFunction) - match expTypeFromExpModelica(exp) - case "modelica_boolean" then '(<%res%>+1)' - else '/* <%expTypeFromExpModelica(exp)%> */ <%res%>' -end daeDimensionExp; - -template daeSubscriptExp(Exp exp, Context context, Text &preExp, Text &varDecls, Text &auxFunction) -::= - let res = daeExp(exp,context,&preExp,&varDecls,&auxFunction) - match expTypeFromExpModelica(exp) - case "modelica_boolean" then '(<%res%>+1)' - else '<%res%>' /* <%expTypeFromExpModelica(exp)%> */ -end daeSubscriptExp; - -template generateThrow() -::= - match codegenPeekTryThrowIndex() - case -1 then "MMC_THROW_INTERNAL()" - case i then 'goto goto_<%i%>' -end generateThrow; - annotation(__OpenModelica_Interface="backend"); end CodegenC; diff --git a/Compiler/Template/CodegenCFunctions.tpl b/Compiler/Template/CodegenCFunctions.tpl new file mode 100644 index 00000000000..25ba47106dd --- /dev/null +++ b/Compiler/Template/CodegenCFunctions.tpl @@ -0,0 +1,6472 @@ +// This file defines templates for transforming Modelica/MetaModelica code to C +// code. They are used in the code generator phase of the compiler to write +// target code. +// +// CodegenC.tpl has the root template translateModel while +// this template contains only translateFunctions. +// These templates do not return any +// result but instead write the result to files. All other templates return +// text and are used by the root templates (most of them indirectly). + +package CodegenCFunctions + +import interface SimCodeTV; +import CodegenUtil.*; + +/* public */ template generateEntryPoint(Path entryPoint, String url) "used in Compiler/Script/CevalScript.mo" +::= +let name = ("omc_" + underscorePath(entryPoint)) +<< +/* This is an automatically generated entry point to a MetaModelica function */ + +#if defined(__cplusplus) +extern "C" { +#endif + +#if defined(OMC_ENTRYPOINT_STATIC) + +#include +#include + +DLLImport extern int __omc_main(int argc, char **argv); + +int main(int argc, char **argv) +{ + return __omc_main(argc, argv); +} + +#else + +#include +#include +extern void <%name%>(threadData_t*,modelica_metatype); + +void (*omc_assert)(threadData_t*,FILE_INFO info,const char *msg,...) __attribute__((noreturn)) = omc_assert_function; +void (*omc_assert_warning)(FILE_INFO info,const char *msg,...) = omc_assert_warning_function; +void (*omc_terminate)(FILE_INFO info,const char *msg,...) = omc_terminate_function; +void (*omc_throw)(threadData_t*) __attribute__ ((noreturn)) = omc_throw_function; + +#ifdef _OPENMP +#include +/* Hack to make gcc-4.8 link in the OpenMP runtime if -fopenmp is given */ +int (*force_link_omp)(void) = omp_get_num_threads; +#endif + +static int rml_execution_failed() +{ + fflush(NULL); + fprintf(stderr, "Execution failed!\n"); + fflush(NULL); + return 1; +} + +DLLExport int __omc_main(int argc, char **argv) +{ + MMC_INIT(); + { + void *lst = mmc_mk_nil(); + int i = 0; + + for (i=argc-1; i>0; i--) { + lst = mmc_mk_cons(mmc_mk_scon(argv[i]), lst); + } + + <%mainTop('<%name%>(threadData, lst);',url)%> + } + + <%if Flags.isSet(HPCOM) then "terminateHpcOmThreads();" %> + fflush(NULL); + EXIT(0); + return 0; +} + +#endif + +#if defined(__cplusplus) +} /* end extern "C" */ +#endif + +>> +end generateEntryPoint; + +template mainTop(Text mainBody, String url) +::= + << + { + MMC_TRY_TOP() + + MMC_TRY_STACK() + + <%mainBody%> + + MMC_ELSE() + rml_execution_failed(); + fprintf(stderr, "Stack overflow detected and was not caught.\nSend us a bug report at <%url%>\n Include the following trace:\n"); + printStacktraceMessages(); + fflush(NULL); + return 1; + MMC_CATCH_STACK() + + MMC_CATCH_TOP(return rml_execution_failed()); + } + >> +end mainTop; + +/* public */ template translateFunctions(FunctionCode functionCode) + "Generates C code and Makefile for compiling and calling Modelica and + MetaModelica functions. + used in Compiler/SimCode/SimCodeMain.mo" +::= + match functionCode + case fc as FUNCTIONCODE(__) then + let()= System.tmpTickResetIndex(0,2) /* auxFunction index */ + let &staticPrototypes = buffer "" + let filePrefix = name + let _= (if mainFunction then textFile(functionsMakefile(functionCode), '<%filePrefix%>.makefile')) + let()= textFile(functionsHeaderFile(filePrefix, mainFunction, functions, extraRecordDecls, staticPrototypes), '<%filePrefix%>.h') + let()= textFileConvertLines(functionsFile(filePrefix, mainFunction, functions, literals, staticPrototypes), '<%filePrefix%>.c') + let()= textFile(externalFunctionIncludes(fc.externalFunctionIncludes), '<%filePrefix%>_includes.h') + let()= textFile(recordsFile(filePrefix, extraRecordDecls), '<%filePrefix%>_records.c') + // If ParModelica generate the kernels file too. + if acceptParModelicaGrammar() then + let()= textFile(functionsParModelicaKernelsFile(filePrefix, mainFunction, functions), '<%filePrefix%>_kernels.cl') + "" // Return empty result since result written to files directly + end match +end translateFunctions; + +template functionsFile(String filePrefix, + Option mainFunction, + list functions, + list literals, + Text &staticPrototypes) + "Generates the contents of the main C file for the function case." +::= + let &preLit = buffer "" + let literalsRes = literals |> literal hasindex i0 fromindex 0 => literalExpConst(literal,i0,&preLit) ; separator="\n";empty + << + #include "<%filePrefix%>.h" + <% preLit %> + <% /* Note: The literals may not be part of the header due to separate compilation */ + literalsRes + %> + #include "util/modelica.h" + + #include "<%filePrefix%>_includes.h" + + <%if staticPrototypes then + << + /* default, do not make protected functions static */ + #if !defined(PROTECTED_FUNCTION_STATIC) + #define PROTECTED_FUNCTION_STATIC + #endif + <%staticPrototypes%> + >> + %> + + <% if mainFunction then + << + void (*omc_assert)(threadData_t*,FILE_INFO info,const char *msg,...) __attribute__((noreturn)) = omc_assert_function; + void (*omc_assert_warning)(FILE_INFO info,const char *msg,...) = omc_assert_warning_function; + void (*omc_terminate)(FILE_INFO info,const char *msg,...) = omc_terminate_function; + void (*omc_throw)(threadData_t*) __attribute__ ((noreturn)) = omc_throw_function; + >> %> + + <%match mainFunction case SOME(fn) then functionBody(fn,true,false)%> + <%functionBodies(functions,false)%> + <%\n%> + >> +end functionsFile; + +template functionsHeaderFile(String filePrefix, + Option mainFunction, + list functions, + list extraRecordDecls, + Text &staticPrototypes) + "Generates the contents of the main C file for the function case." +::= + << + #ifndef <%stringReplace(filePrefix,".","_")%>__H + #define <%stringReplace(filePrefix,".","_")%>__H + <%commonHeader(filePrefix)%> + #ifdef __cplusplus + extern "C" { + #endif + + <%extraRecordDecls |> rd => recordDeclarationHeader(rd) ;separator="\n"%> + + <%match mainFunction case SOME(fn) then functionHeader(fn,true,false,staticPrototypes)%> + + <%functionHeaders(functions, false, staticPrototypes)%> + + #ifdef __cplusplus + } + #endif + #endif<%\n%> + >> + /* adrpo: leave a newline at the end of file to get rid of the warning */ +end functionsHeaderFile; + +template functionsMakefile(FunctionCode fnCode) + "Generates the contents of the makefile for the function case." +::= +match fnCode +case FUNCTIONCODE(makefileParams=MAKEFILE_PARAMS(__)) then + let libsStr = (makefileParams.libs ;separator=" ") + let ParModelicaExpLibs = if acceptParModelicaGrammar() then '-lOMOCLRuntime -lOpenCL' // else "" + + << + # Makefile generated by OpenModelica + + # Dynamic loading uses -O0 by default + SIM_OR_DYNLOAD_OPT_LEVEL=-O0 + CC=<%if acceptParModelicaGrammar() then 'g++' else '<%makefileParams.ccompiler%>'%> + CXX=<%makefileParams.cxxcompiler%> + LINK=<%makefileParams.linker%> + EXEEXT=<%makefileParams.exeext%> + DLLEXT=<%makefileParams.dllext%> + DEBUG_FLAGS=<% if boolOr(acceptMetaModelicaGrammar(), Flags.isSet(Flags.GEN_DEBUG_SYMBOLS)) then " -g"%> + CFLAGS= -I"<%makefileParams.omhome%>/include/omc/c" <%makefileParams.includes ; separator=" "%> $(DEBUG_FLAGS) <%makefileParams.cflags%> + LDFLAGS= -L"<%makefileParams.omhome%>/lib/<%getTriple()%>/omc" -Wl,-rpath,'<%makefileParams.omhome%>/lib/<%getTriple()%>/omc' <%ParModelicaExpLibs%> <%makefileParams.ldflags%> <%makefileParams.runtimelibs%> + PERL=perl + MAINFILE=<%name%>.c + + .PHONY: <%name%> + <%name%>: $(MAINFILE) <%name%>.h <%name%>_records.c + <%\t%> $(CC) $(CFLAGS) -c -o <%name%>.o $(MAINFILE) + <%\t%> $(CC) $(CFLAGS) -c -o <%name%>_records.o <%name%>_records.c + <%\t%> $(LINK) -o <%name%>$(DLLEXT) <%name%>.o <%name%>_records.o <%libsStr%> $(CFLAGS) $(LDFLAGS) -lm + >> +end functionsMakefile; + +template commonHeader(String filePrefix) +::= + << + #include "meta/meta_modelica.h" + #include "util/modelica.h" + #include + #include + #include + <%if acceptParModelicaGrammar() then + << + #include + /* the OpenCL Kernels file name needed in libOMOCLRuntime.a */ + const char* omc_ocl_kernels_source = "<%filePrefix%>_kernels.cl"; + /* the OpenCL program. Made global to avoid repeated builds */ + extern cl_program omc_ocl_program; + /* The default OpenCL device. If not set (=0) show the selection option.*/ + unsigned int default_ocl_device = <%getDefaultOpenCLDevice()%>; + >> + %> + + >> +end commonHeader; + + +/* public */ template externalFunctionIncludes(list includes) + "Generates external includes part in function files. + used in Compiler/Template/CodegenFMU.tpl" +::= + if includes then + << + #ifdef __cplusplus + extern "C" { + #endif + <% (includes ;separator="\n") %> + #ifdef __cplusplus + } + #endif<%\n%> + >> +end externalFunctionIncludes; + +template functionHeaders(list functions, Boolean isSimulation, Text &staticPrototypes) + "Generates function header part in function files." +::= + (functions |> fn => functionHeader(fn, false, isSimulation, staticPrototypes) ; separator="\n\n") +end functionHeaders; + +template functionHeadersParModelica(String filePrefix, list functions) + "Generates the content of the C file for functions in the simulation case." +::= + << + #ifndef <%stringReplace(filePrefix,".","_")%>__H + #define <%stringReplace(filePrefix,".","_")%>__H + //#include "helper.cl" + + <%parallelFunctionHeadersImpl(functions)%> + + #endif + + <%\n%> + >> + /* adrpo: leave a newline at the end of file to get rid of the warning */ +end functionHeadersParModelica; + +template parallelFunctionHeadersImpl(list functions) + "Generates function header part in function files." +::= + (functions |> fn => parallelFunctionHeader(fn, false) ; separator="\n\n") +end parallelFunctionHeadersImpl; + +template functionHeader(Function fn, Boolean inFunc, Boolean isSimulation, Text &staticPrototypes) + "Generates function header part in function files." +::= + match fn + case FUNCTION(__) then + << + <%functionHeaderNormal(underscorePath(name), functionArguments, outVars, inFunc, visibility, false, isSimulation, staticPrototypes)%> + <%functionHeaderBoxed(underscorePath(name), functionArguments, outVars, inFunc, isBoxedFunction(fn), visibility, false, isSimulation, staticPrototypes)%> + >> + case KERNEL_FUNCTION(__) then + << + <%functionHeaderKernelFunctionInterface(underscorePath(name), functionArguments, outVars)%> + >> + case EXTERNAL_FUNCTION(dynamicLoad=true) then + << + <%functionHeaderNormal(underscorePath(name), funArgs, outVars, inFunc, visibility, true, isSimulation, staticPrototypes)%> + <%functionHeaderBoxed(underscorePath(name), funArgs, outVars, inFunc, isBoxedFunction(fn), visibility, true, isSimulation, staticPrototypes)%> + + <%extFunDefDynamic(fn)%> + >> + case EXTERNAL_FUNCTION(__) then + << + <%functionHeaderNormal(underscorePath(name), funArgs, outVars, inFunc, visibility, false, isSimulation, staticPrototypes)%> + <%functionHeaderBoxed(underscorePath(name), funArgs, outVars, inFunc, isBoxedFunction(fn), visibility, false, isSimulation, staticPrototypes)%> + + <%extFunDef(fn)%> + >> + case RECORD_CONSTRUCTOR(__) then + let fname = underscorePath(name) + let funArgsStr = (funArgs |> var as VARIABLE(__) => ', <%varType(var)%> <%crefStr(name)%>') + << + <% match visibility case PUBLIC() then "DLLExport" %> + <%fname%> omc_<%fname%>(threadData_t *threadData<%funArgsStr%>); /* record head */ + + <%functionHeaderBoxed(fname, funArgs, boxedRecordOutVars, inFunc, false, visibility, false, isSimulation, staticPrototypes)%> + >> +end functionHeader; + +template parallelFunctionHeader(Function fn, Boolean inFunc) + "Generates function header part in function files." +::= + match fn + case PARALLEL_FUNCTION(__) then + << + <%functionHeaderParallelImpl(underscorePath(name), functionArguments, outVars, inFunc, false)%> + >> +end parallelFunctionHeader; + +template functionHeaderParallelImpl(String fname, list fargs, list outVars, Boolean inFunc, Boolean boxed) + "Generates parmodelica paralell function header part in kernels files." +::= + let fargsStr = (fargs |> var => funArgDefinition(var) ;separator=", ") + if outVars then + << + <%outVars |> _ hasindex i1 fromindex 1 => '#define <%fname%>_rettype_<%i1%> c<%i1%>' ;separator="\n"%> + typedef struct <%fname%>_rettype_s + { + <%outVars |> var hasindex i1 fromindex 1 => + match var + case VARIABLE(__) then + let dimStr = match ty case T_ARRAY(__) + then '[<%dims |> dim => dimension(dim) ;separator=", "%>]' + let typeStr = if boxed then varTypeBoxed(var) else varType(var) + '<%typeStr%> c<%i1%>; /* <%crefStr(name)%><%dimStr%> */' + case FUNCTION_PTR(__) then + 'modelica_fnptr c<%i1%>; /* <%name%> */' + ;separator="\n";empty + %> + } <%fname%>_rettype; + + <%fname%>_rettype omc_<%fname%>(<%fargsStr%>); + + >> +end functionHeaderParallelImpl; + +template recordDeclaration(RecordDeclaration recDecl) + "Generates structs for a record declaration." +::= + match recDecl + case RECORD_DECL_FULL(__) then + << + <%recordDefinition(dotPath(defPath), + underscorePath(defPath), + (variables |> VARIABLE(__) => '"_<%crefStr(name)%>"' ;separator=","), + listLength(variables))%> + >> + case RECORD_DECL_DEF(__) then + << + <%recordDefinition(dotPath(path), + underscorePath(path), + (fieldNames |> name => '"<%name%>"' ;separator=","), + listLength(fieldNames))%> + >> +end recordDeclaration; + +template recordDeclarationHeader(RecordDeclaration recDecl) + "Generates structs for a record declaration." +::= + match recDecl + case r as RECORD_DECL_FULL(__) then + << + <% match aliasName + case SOME(str) then 'typedef <%str%> <%r.name%>;' + else << + typedef struct <%r.name%>_s { + <%r.variables |> var as VARIABLE(__) => '<%varType(var)%> _<%crefStr(var.name)%>;' ;separator="\n"%> + } <%r.name%>; + >> %> + typedef base_array_t <%name%>_array; + <%recordDefinitionHeader(dotPath(defPath), + underscorePath(defPath), + listLength(variables))%> + >> + case RECORD_DECL_DEF(__) then + << + <%recordDefinitionHeader(dotPath(path), + underscorePath(path), + listLength(fieldNames))%> + >> +end recordDeclarationHeader; + +template recordDefinition(String origName, String encName, String fieldNames, Integer numFields) + "Generates the definition struct for a record declaration." +::= + match encName + case "SourceInfo_SOURCEINFO" then '' + else + /* adrpo: 2011-03-14 make MSVC happy, no arrays of 0 size! */ + let fieldsDescription = + match numFields + case 0 then + 'const char* <%encName%>__desc__fields[1] = {"no fields"};' + case _ then + 'const char* <%encName%>__desc__fields[<%numFields%>] = {<%fieldNames%>};' + << + #define <%encName%>__desc_added 1 + <%fieldsDescription%> + struct record_description <%encName%>__desc = { + "<%encName%>", /* package_record__X */ + "<%origName%>", /* package.record_X */ + <%encName%>__desc__fields + }; + >> +end recordDefinition; + +template recordDefinitionHeader(String origName, String encName, Integer numFields) + "Generates the definition struct for a record declaration." +::= + << + extern struct record_description <%encName%>__desc; + >> +end recordDefinitionHeader; + +template functionHeaderNormal(String fname, list fargs, list outVars, Boolean inFunc, SCode.Visibility visibility, Boolean dynLoad, Boolean isSimulation, Text &staticPrototypes) +::=functionHeaderImpl(fname, fargs, outVars, inFunc, false, visibility, dynLoad, isSimulation, staticPrototypes) +end functionHeaderNormal; + +template functionHeaderBoxed(String fname, list fargs, list outVars, Boolean inFunc, Boolean isBoxed, SCode.Visibility visibility, Boolean dynLoad, Boolean isSimulation, Text &staticPrototypes) +::= + let boxvar = + << + static const MMC_DEFSTRUCTLIT(boxvar_lit_<%fname%>,2,0) {(void*) boxptr_<%fname%>,0}}; + #define boxvar_<%fname%> MMC_REFSTRUCTLIT(boxvar_lit_<%fname%>)<%\n%> + >> + << + <%if isBoxed then '#define boxptr_<%fname%> omc_<%fname%><%\n%>' else functionHeaderImpl(fname, fargs, outVars, inFunc, true, visibility, dynLoad, isSimulation, staticPrototypes)%> + <% match visibility + case PROTECTED(__) then + let &staticPrototypes += (if isSimulation then "" else boxvar) + if isSimulation then '<%boxvar%> /* boxvar early */' else "" + else boxvar %> + >> +end functionHeaderBoxed; + +template functionHeaderImpl(String fname, list fargs, list outVars, Boolean inFunc, Boolean boxed, SCode.Visibility visibility, Boolean dynamicLoad, Boolean isSimulation, Text &staticPrototypes) + "Generates function header for a Modelica/MetaModelica function. Generates a + + boxed version of the header if boxed = true, otherwise a normal header" +::= + let prototype = functionPrototype(fname, fargs, outVars, boxed, visibility, isSimulation) + let inFnStr = if boolAnd(boxed,inFunc) then + << + DLLExport + int in_<%fname%>(threadData_t *threadData, type_description * inArgs, type_description * outVar); + >> + match visibility + case PROTECTED(__) then + if isSimulation then + if dynamicLoad then "" else '<%prototype%>;<%\n%>' + else + let &staticPrototypes += if dynamicLoad then "" else '<%prototype%>;<%\n%>' + inFnStr + else + << + <%inFnStr%> + <%if dynamicLoad then '' else 'DLLExport<%\n%><%prototype%>;'%> + >> +end functionHeaderImpl; + +template functionPrototype(String fname, list fargs, list outVars, Boolean boxed, SCode.Visibility visibility, Boolean isSimulation) + "Generates function header definition for a Modelica/MetaModelica function. Generates a boxed version of the header if boxed = true, otherwise a normal definition" +::= + let static = if isSimulation then "" else (match visibility case PROTECTED(__) then 'PROTECTED_FUNCTION_STATIC ') + let fargsStr = if boxed then + (fargs |> var => ", " + funArgBoxedDefinition(var) ) + else + (fargs |> var => ", " + funArgDefinition(var) ) + let outarg = (match outVars + case {} then "void" + case var::_ then (match var + case VARIABLE(__) then if boxed then varTypeBoxed(var) else varType(var) + case FUNCTION_PTR(__) then "modelica_fnptr")) + let boxPtrStr = if boxed then "boxptr" else "omc" + if outVars then + let outargs = List.rest(outVars) |> var => ", " + (match var + case var as VARIABLE(__) then '<%if boxed then varTypeBoxed(var) else varType(var)%> *out<%funArgName(var)%>' + case FUNCTION_PTR(__) then 'modelica_fnptr *out<%funArgName(var)%>') + '<%static%><%outarg%> <%boxPtrStr%>_<%fname%>(threadData_t *threadData<%fargsStr%><%outargs%>)' + else + '<%static%>void <%boxPtrStr%>_<%fname%>(threadData_t *threadData<%fargsStr%>)' +end functionPrototype; + +template functionHeaderKernelFunctionInterface(String fname, list fargs, list outVars) + "Generates function header for a ParModelica Kernel function interface." +::= + '<%functionHeaderKernelFunctionInterfacePrototype(fname, fargs, outVars)%>;' +end functionHeaderKernelFunctionInterface; + +template functionHeaderKernelFunctionInterfacePrototype(String fname, list fargs, list outVars) + "Generates function header for a ParModelica Kernel function interface." +::= + let fargsStr = 'threadData_t *threadData' + let &fargsStr += if fargs then ", " + (fargs |> var => funArgDefinitionKernelFunctionInterface(var) ;separator=", ") + // let &fargsStr += if outVars then ", " + (outVars |> var => tupleOutfunArgDefinitionKernelFunctionInterface(var) ;separator=", ") + // 'void omc_<%fname%>(<%fargsStr%>)' + + match outVars + case {} then + 'void omc_<%fname%>(<%fargsStr%>)' + + case fvar::rest then + let rettype = functionArgTypeKernelInterface(fvar) + let &fargsStr += if rest then ", " + (rest |> var => tupleOutfunArgDefinitionKernelFunctionInterface(var) ;separator=", ") + '<%rettype%> omc_<%fname%>(<%fargsStr%>)' + + else + error(sourceInfo(), 'functionHeaderKernelFunctionInterfacePrototype failed') +end functionHeaderKernelFunctionInterfacePrototype; + +template funArgName(Variable var) +::= + let &auxFunction = buffer "" + match var + case VARIABLE(__) then contextCref(name,contextFunction,&auxFunction) + case FUNCTION_PTR(__) then '_' + name +end funArgName; + +template funArgDefinition(Variable var) +::= + let &auxFunction = buffer "" + match var + case VARIABLE(__) then ('<%varType(var)%> <%contextCref(name,contextFunction,&auxFunction)%>' + (if var.instDims then " = {0}")) + case FUNCTION_PTR(__) then 'modelica_fnptr _<%name%>' +end funArgDefinition; + +template funArgDefinitionKernelFunctionInterface(Variable var) +::= + let &auxFunction = buffer "" + match var + case VARIABLE(__) then + '<%functionArgTypeKernelInterface(var)%> <%funArgName(var)%>' + else error(sourceInfo(), 'funArgDefinitionKernelFunctionInterface : unsupported function argument type') +end funArgDefinitionKernelFunctionInterface; + +template tupleOutfunArgDefinitionKernelFunctionInterface(Variable var) +::= + let &auxFunction = buffer "" + match var + case VARIABLE(__) then + '<%functionArgTypeKernelInterface(var)%> *out<%funArgName(var)%>' + else error(sourceInfo(), 'tupleOutfunArgDefinitionKernelFunctionInterface : unsupported function argument type') +end tupleOutfunArgDefinitionKernelFunctionInterface; + +template functionArgTypeKernelInterface(Variable var) +::= + match var + case VARIABLE(ty=T_ARRAY(__), parallelism = PARGLOBAL(__)) then 'device_<%varType(var)%>' + case VARIABLE(ty=T_ARRAY(__), parallelism = PARLOCAL(__)) then 'device_local_<%varType(var)%>' + case VARIABLE(__) then '<%varType(var)%>' + else 'Invalid function argument to Kernel function Interface.' +end functionArgTypeKernelInterface; + +template funArgDefinitionKernelFunctionBody(Variable var) + "Generates code to initialize variables. + Does not return anything: just appends declarations to buffers." +::= +let &auxFunction = buffer "" +match var +//function args will have nill instdims even if they are arrays. handled here +case var as VARIABLE(ty=T_ARRAY(__), parallelism = PARGLOBAL(__)) then + let varName = '<%contextCref(var.name,contextParallelFunction,&auxFunction)%>' + '__global modelica_<%expTypeShort(var.ty)%>* data_<%varName%>,<%\n%> __global modelica_integer* info_<%varName%>' + +case var as VARIABLE(ty=T_ARRAY(__), parallelism = PARLOCAL(__)) then + let varName = '<%contextCref(var.name,contextParallelFunction,&auxFunction)%>' + '__local modelica_<%expTypeShort(var.ty)%>* data_<%varName%>,<%\n%> __local modelica_integer* info_<%varName%>' + +case var as VARIABLE(__) then + let varName = '<%contextCref(var.name,contextParallelFunction,&auxFunction)%>' + if instDims then + (match parallelism + case PARGLOBAL(__) then + '__global modelica_<%expTypeShort(var.ty)%>* data_<%varName%>,<%\n%> __global modelica_integer* info_<%varName%>' + case PARLOCAL(__) then + '__global modelica_<%expTypeShort(var.ty)%>* data_<%varName%>,<%\n%> __global modelica_integer* info_<%varName%>' + ) + else + 'modelica_<%expTypeShort(var.ty)%> <%varName%>' + +else '#error Unknown variable type in as function argument funArgDefinitionKernelFunctionBody<%\n%>' +end funArgDefinitionKernelFunctionBody; + +template funArgDefinitionKernelFunctionBody2(Variable var, Text &parArgList /*BUFPA*/) + "Generates code to initialize variables. + Does not return anything: just appends declarations to buffers." +::= +let &auxFunction = buffer "" +match var +//function args will have nill instdims even if they are arrays. handled here +case var as VARIABLE(ty=T_ARRAY(__)) then + let varName = '<%contextCref(var.name,contextParallelFunction,&auxFunction)%>' + let &parArgList += ',<%\n%> __global modelica_<%expTypeShort(var.ty)%>* data_<%varName%>,' + let &parArgList += '<%\n%> __global modelica_integer* info_<%varName%>' + "" +case var as VARIABLE(__) then + let varName = '<%contextCref(var.name,contextParallelFunction,&auxFunction)%>' + if instDims then + let &parArgList += ',<%\n%> __global modelica_<%expTypeShort(var.ty)%>* data_<%varName%>,' + let &parArgList += '<%\n%> __global modelica_integer* info_<%varName%>' + " " + else + let &parArgList += ',<%\n%> modelica_<%expTypeShort(var.ty)%> <%varName%>' + "" +else let &parArgList += ' #error Unknown variable type in as function argument funArgDefinitionKernelFunctionBody2<%\n%>' "" +end funArgDefinitionKernelFunctionBody2; + +template parFunArgDefinitionFromLooptupleVar(tuple tupleVar) +::= +match tupleVar +case tupleVar as ((cref as CREF_IDENT(identType = T_ARRAY(__)),_)) then + let varName = contextArrayCref(cref,contextParallelFunction) + match cref.identType + case identType as T_ARRAY(ty = T_INTEGER(__)) then + '__global modelica_integer* data_<%varName%>,<%\n%>__global modelica_integer* info_<%varName%>' + case identType as T_ARRAY(ty = T_REAL(__)) then + '__global modelica_real* data_<%varName%>,<%\n%>__global modelica_integer* info_<%varName%>' + + else 'Template error in parFunArgDefinitionFromLooptupleVar' + +case tupleVar as ((cref as CREF_IDENT(__),_)) then + let varName = contextArrayCref(cref,contextParallelFunction) + match cref.identType + case identType as T_INTEGER(__) then + 'modelica_integer <%varName%>' + case identType as T_REAL(__) then + 'modelica_real <%varName%>' + + else 'Tempalte error in parFunArgDefinitionFromLooptupleVar' + +end parFunArgDefinitionFromLooptupleVar; + +template reconstructKernelArraysFromLooptupleVars(tuple tupleVar, Text &reconstructedArrs) + "reconstructs modelica arrays in the kernels." +::= +match tupleVar +case tupleVar as ((cref as CREF_IDENT(identType = T_ARRAY(__)),_)) then + let varName = contextArrayCref(cref,contextParallelFunction) + match cref.identType + case identType as T_ARRAY(ty = T_INTEGER(__)) then + let &reconstructedArrs += 'integer_array <%varName%>; <%\n%>' + let &reconstructedArrs += '<%varName%>.data = data_<%varName%>; <%\n%>' + let &reconstructedArrs += '<%varName%>.ndims = info_<%varName%>[0]; <%\n%>' + let &reconstructedArrs += '<%varName%>.dim_size = info_<%varName%> + 1; <%\n%>' + "" + case identType as T_ARRAY(ty = T_REAL(__)) then + let &reconstructedArrs += 'real_array <%varName%>; <%\n%>' + let &reconstructedArrs += '<%varName%>.data = data_<%varName%>; <%\n%>' + let &reconstructedArrs += '<%varName%>.ndims = info_<%varName%>[0]; <%\n%>' + let &reconstructedArrs += '<%varName%>.dim_size = info_<%varName%> + 1; <%\n%>' + "" +else let &reconstructedArrs += '#wiered variable in kerenl reconstruction of arrays<%\n%>' "" +end reconstructKernelArraysFromLooptupleVars; + +template reconstructKernelArrays(Variable var, Text &reconstructedArrs) + "reconstructs modelica arrays in the kernels." +::= +let &auxFunction = buffer "" +match var +//function args will have nill instdims even if they are arrays. handled here +case var as VARIABLE(ty=T_ARRAY(__),parallelism=PARGLOBAL(__)) then + let varName = '<%contextCref(var.name,contextParallelFunction,&auxFunction)%>' + let &reconstructedArrs += '<%expTypeShort(var.ty)%>_array <%varName%>; <%\n%>' + let &reconstructedArrs += '<%varName%>.data = data_<%varName%>; <%\n%>' + let &reconstructedArrs += '<%varName%>.ndims = info_<%varName%>[0]; <%\n%>' + let &reconstructedArrs += '<%varName%>.dim_size = info_<%varName%> + 1; <%\n%>' + "" +case var as VARIABLE(ty=T_ARRAY(__),parallelism=PARLOCAL(__)) then + let varName = '<%contextCref(var.name,contextParallelFunction,&auxFunction)%>' + let &reconstructedArrs += 'local_<%expTypeShort(var.ty)%>_array <%varName%>; <%\n%>' + let &reconstructedArrs += '<%varName%>.data = data_<%varName%>; <%\n%>' + let &reconstructedArrs += '<%varName%>.ndims = info_<%varName%>[0]; <%\n%>' + let &reconstructedArrs += '<%varName%>.dim_size = info_<%varName%> + 1; <%\n%>' + "" +case var as VARIABLE(__) then + let varName = '<%contextCref(var.name,contextParallelFunction,&auxFunction)%>' + if instDims then + let &reconstructedArrs += '<%expTypeShort(var.ty)%>_array <%varName%>; <%\n%>' + let &reconstructedArrs += '<%varName%>.data = data_<%varName%>; <%\n%>' + let &reconstructedArrs += '<%varName%>.ndims = info_<%varName%>[0]; <%\n%>' + let &reconstructedArrs += '<%varName%>.dim_size = info_<%varName%> + 1; <%\n%>' + " " + else + "" +else let &reconstructedArrs += '#wiered variable in kerenl reconstruction of arrays<%\n%>' "" +end reconstructKernelArrays; + +template funArgBoxedDefinition(Variable var) + "A definition for a boxed variable is always of type modelica_metatype, + unless it's a function pointer" +::= + let &auxFunction = buffer "" + match var + case VARIABLE(__) then 'modelica_metatype <%contextCref(name,contextFunction,&auxFunction)%>' + case FUNCTION_PTR(__) then 'modelica_fnptr _<%name%>' +end funArgBoxedDefinition; + +template extFunDef(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) + let fargsStrEscaped = '<%escapeCComments(fargsStr)%>' + let includesStr = includes |> i => i ;separator=", " + /* + * adrpo: + * only declare the external function definition IF THERE WERE NO INCLUDES! + * i did not put includesStr string in the comment below as it might include + * entire files + */ + if includes then + << + /* + * The function has annotation(Include=...>) + * the external function definition should be present + * in one of these files and have this prototype: + * extern <%extReturnType(extReturn)%> <%fn_name%>(<%fargsStrEscaped%>); + */ + >> + else + << + extern <%extReturnType(extReturn)%> <%fn_name%>(<%fargsStr%>); + >> +end match +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; + +/* public */ template extFunctionName(String name, String language) "used in Compiler/Template/CodegenFMU.tpl" +::= + match language + case "C" then '<%name%>' + case "FORTRAN 77" then '<%name%>_' + else error(sourceInfo(), 'Unsupport external language: <%language%>') +end extFunctionName; + +template extFunDefArgs(list args, String language) +::= + match language + case "C" then (args |> arg => extFunDefArg(arg) ;separator=", ") + case "FORTRAN 77" then (args |> arg => extFunDefArgF77(arg) ;separator=", ") + else error(sourceInfo(), 'Unsupport external language: <%language%>') +end extFunDefArgs; + +template extReturnType(SimExtArg extArg) + "Generates return type for external function." +::= + match extArg + case ex as SIMEXTARG(__) then extType(type_,true /*Treat this as an input (pass by value)*/,false) + case SIMNOEXTARG(__) then "void" + case SIMEXTARGEXP(__) then error(sourceInfo(), 'Expression types are unsupported as return arguments <%printExpStr(exp)%>') + else error(sourceInfo(), "Unsupported return argument") +end extReturnType; + + +template extType(Type type, Boolean isInput, Boolean isArray) + "Generates type for external function argument or return value." +::= + let s = match type + case T_INTEGER(__) then "int" + case T_REAL(__) then "double" + case T_STRING(__) then "const char*" + case T_BOOL(__) then "int" + case T_ENUMERATION(__) then "int" + case T_ARRAY(__) then extType(ty,isInput,true) + case T_COMPLEX(complexClassType=EXTERNAL_OBJ(__)) + then "void *" + case T_COMPLEX(complexClassType=RECORD(path=rname)) + then '<%underscorePath(rname)%>' + case T_METATYPE(__) + case T_METABOXED(__) + then "modelica_metatype" + case T_FUNCTION_REFERENCE_VAR(__) + then "modelica_fnptr" + else error(sourceInfo(), 'Unknown external C type <%unparseType(type)%>') + match type case T_ARRAY(__) then s else if isInput then (if isArray then '<%match s case "const char*" then "" else "const "%><%s%>*' else s) else '<%s%>*' +end extType; + +template extTypeF77(Type type, Boolean isReference) + "Generates type for external function argument or return value for F77." +::= + let s = match type + case T_INTEGER(__) then "int" + case T_REAL(__) then "double" + case T_STRING(__) then "char" + case T_BOOL(__) then "int" + case T_ENUMERATION(__) then "int" + case T_ARRAY(__) then extTypeF77(ty, true) + case T_COMPLEX(complexClassType=EXTERNAL_OBJ(__)) + then "void*" + case T_COMPLEX(complexClassType=RECORD(path=rname)) + then '<%underscorePath(rname)%>' + case T_METATYPE(__) case T_METABOXED(__) then "void*" + else error(sourceInfo(), 'Unknown external F77 type <%unparseType(type)%>') + match type case T_ARRAY(__) then s else if isReference then '<%s%>*' else s +end extTypeF77; + +template extFunDefArg(SimExtArg extArg) + "Generates the definition of an external function argument. + Assume that language is C for now." +::= + let &auxFunction = buffer "" + match extArg + case SIMEXTARG(cref=c, isInput=ii, isArray=ia, type_=t) then + let name = contextCref(c,contextFunction,&auxFunction) + let typeStr = extType(t,ii,ia) + << + <%typeStr%> /*<%name%>*/ + >> + case SIMEXTARGEXP(__) then + let typeStr = extType(type_,true,false) + << + <%typeStr%> + >> + case SIMEXTARGSIZE(cref=c) then + << + size_t + >> +end extFunDefArg; + +template extFunDefArgF77(SimExtArg extArg) +::= + let &auxFunction = buffer "" + match extArg + case SIMEXTARG(cref=c, isInput = isInput, type_=t) then + let name = contextCref(c,contextFunction,&auxFunction) + let typeStr = '<%extTypeF77(t,true)%>' + '<%typeStr%> /*<%name%>*/' + + case SIMEXTARGEXP(__) then '<%extTypeF77(type_,true)%>' + + /* adpro: 2011-06-23 + * DO NOT USE CONST HERE as sometimes is used with size(A, 1) + + * sometimes with n in Modelica.Math.Matrices.Lapack and you + * get conflicting external definitions in the same Model_function.h + * file + */ + case SIMEXTARGSIZE(__) then 'int *' +end extFunDefArgF77; + + +template functionName(Function fn, Boolean dotPath) +::= + match fn + case FUNCTION(__) + case EXTERNAL_FUNCTION(__) + case RECORD_CONSTRUCTOR(__) then if dotPath then dotPath(name) else underscorePath(name) +end functionName; + + +template functionBodies(list functions, Boolean isSimulation) + "Generates the body for a set of functions." +::= + (functions |> fn => functionBody(fn, false, isSimulation) ;separator="\n") +end functionBodies; + +template functionBodiesParModelica(list functions) + "Generates the body for a set of functions." +::= + (functions |> fn => functionBodyParModelica(fn, false) ;separator="\n") +end functionBodiesParModelica; + +template functionBody(Function fn, Boolean inFunc, Boolean isSimulation) + "Generates the body for a function." +::= + match fn + case fn as FUNCTION(__) then functionBodyRegularFunction(fn, inFunc, isSimulation) + case fn as KERNEL_FUNCTION(__) then functionBodyKernelFunctionInterface(fn, inFunc) + case fn as EXTERNAL_FUNCTION(__) then functionBodyExternalFunction(fn, inFunc, isSimulation) + case fn as RECORD_CONSTRUCTOR(__) then functionBodyRecordConstructor(fn, isSimulation) +end functionBody; + +template functionBodyParModelica(Function fn, Boolean inFunc) + "Generates the body for a function." +::= + match fn + case fn as FUNCTION(__) then extractParforBodies(fn, inFunc) + case fn as KERNEL_FUNCTION(__) then functionBodyKernelFunction(fn, inFunc) + case fn as PARALLEL_FUNCTION(__) then functionBodyParallelFunction(fn, inFunc) +end functionBodyParModelica; + +template extractParforBodies(Function fn, Boolean inFunc) + "Generates the body for a Modelica/MetaModelica function." +::= +match fn +case FUNCTION(__) then + let()= System.tmpTickReset(1) + let()= System.tmpTickResetIndex(0,1) /* Boxed array indices */ + + let &varDecls = buffer "" + let &auxFunction = buffer "" + let bodyPart = (body |> stmt => extractParFors(stmt, &varDecls, &auxFunction) ;separator="\n") + << + <%auxFunction%> + <%bodyPart%> + >> +end extractParforBodies; + +template functionBodyRegularFunction(Function fn, Boolean inFunc, Boolean isSimulation) + "Generates the body for a Modelica/MetaModelica function." +::= +match fn +case FUNCTION(__) then + let &auxFunction = buffer "" + let()= codegenResetTryThrowIndex() + let()= System.tmpTickReset(1) + let()= System.tmpTickResetIndex(0,1) /* Boxed array indices */ + let fname = underscorePath(name) + let &varDecls = buffer "" + let &varInits = buffer "" + let &varFrees = buffer "" + let &auxFunction = buffer "" + let _ = (variableDeclarations |> var hasindex i1 fromindex 1 => + varInit(var, "", &varDecls, &varInits, &varFrees, &auxFunction) ; empty /* increase the counter! */ + ) + let bodyPart = (body |> stmt => funStatement(stmt, &varDecls, &auxFunction) ;separator="\n") + let outVarAssign = (List.restOrEmpty(outVars) |> var => varOutput(var)) + + let freeConstructedExternalObjects = (variableDeclarations |> var as VARIABLE(ty=T_COMPLEX(complexClassType=EXTERNAL_OBJ(path=path_ext))) => 'omc_<%underscorePath(path_ext)%>_destructor(threadData,<%contextCref(var.name,contextFunction,&auxFunction)%>);'; separator = "\n") + /* Needs to be done last as it messes with the tmp ticks :) */ + let &varDecls += addRootsTempArray() + + let boxedFn = functionBodyBoxed(fn, isSimulation) + << + <%auxFunction%> + <% match visibility case PUBLIC(__) then "DLLExport" %> + <%functionPrototype(fname, functionArguments, outVars, false, visibility, isSimulation)%> + { + <%varDecls%> + _tailrecursive: OMC_LABEL_UNUSED + <%varInits%> + <%bodyPart%> + _return: OMC_LABEL_UNUSED + <%outVarAssign%> + <%if acceptParModelicaGrammar() then + '/* Free GPU/OpenCL CPU memory */<%\n%><%varFrees%>'%> + <%freeConstructedExternalObjects%> + <%match outVars + case {} then 'return;' + case v::_ then 'return <%funArgName(v)%>;' + %> + } + <% if inFunc then generateInFunc(fname,functionArguments,outVars) %> + <%boxedFn%> + >> +end functionBodyRegularFunction; + +template generateInFunc(Text fname, list functionArguments, list outVars) +::= + << + DLLExport + int in_<%fname%>(threadData_t *threadData, type_description * inArgs, type_description * outVar) + { + //if (!mmc_GC_state) mmc_GC_init(); + <%functionArguments |> var => '<%funArgDefinition(var)%>;' ;separator="\n"%> + <%outVars |> var => '<%funArgDefinition(var)%>;' ;separator="\n"%> + <%functionArguments |> arg => readInVar(arg) ;separator="\n"%> + MMC_TRY_TOP_INTERNAL() + <%match outVars + case v::_ then '<%funArgName(v)%> = ' + %>omc_<%fname%>(threadData<%functionArguments |> var => (", " + funArgName(var) )%><%List.restOrEmpty(outVars) |> var => (", &" + funArgName(var) )%>); + MMC_CATCH_TOP(return 1) + <% match outVars case {} then "write_noretcall(outVar);" case first::_ then writeOutVar(first) %> + <% List.restOrEmpty(outVars) |> var => writeOutVar(var) ;separator="\n"; empty %> + fflush(NULL); + return 0; + } + #ifdef GENERATE_MAIN_EXECUTABLE + static int rml_execution_failed() + { + fflush(NULL); + fprintf(stderr, "Execution failed!\n"); + fflush(NULL); + return 1; + } + + int main(int argc, char **argv) { + MMC_INIT(); + { + void *lst = mmc_mk_nil(); + int i = 0; + + for (i=argc-1; i>0; i--) { + lst = mmc_mk_cons(mmc_mk_scon(argv[i]), lst); + } + + <%mainTop('omc_<%fname%>(threadData, lst);',"https://trac.openmodelica.org/OpenModelica/newticket")%> + } + + <%if Flags.isSet(HPCOM) then "terminateHpcOmThreads();" %> + fflush(NULL); + EXIT(0); + return 0; + } + #endif + >> +end generateInFunc; + +template functionBodyKernelFunction(Function fn, Boolean inFunc) + "Generates the body for a ParModelica Kernel function." +::= +match fn +case KERNEL_FUNCTION(__) then + let()= System.tmpTickReset(1) + let()= System.tmpTickResetIndex(0,1) /* Boxed array indices */ + let fname = underscorePath(name) + + //retTyep for kernels is always void + //let retType = if outVars then '<%fname%>_rettype' else "void" + + let &varDecls = buffer "" + let &varInits = buffer "" + let &varFrees = buffer "" + let &auxFunction = buffer "" + let _ = (variableDeclarations |> var => + varInit(var, "", &varDecls, &varInits, &varFrees, &auxFunction) ; empty /* increase the counter! */ + ) + + // This odd arrangment and call is to get the commas in the right places + // between the argumetns. + // This puts correct comma placment even when the 'outvar' list is empty + let argStr = (functionArguments |> var => '<%funArgDefinitionKernelFunctionBody(var)%>' ;separator=", \n ") + //let &argStr += (outVars |> var => '<%parFunArgDefinition(var)%>' ;separator=", \n") + let _ = (outVars |> var => + funArgDefinitionKernelFunctionBody2(var, &argStr) ;separator=",\n") + + // Reconstruct array arguments to structures in the kernels + let &reconstrucedArrays = buffer "" + let _ = (functionArguments |> var => + reconstructKernelArrays(var, &reconstrucedArrays) + ) + let _ = (outVars |> var => + reconstructKernelArrays(var, &reconstrucedArrays) + ) + + let bodyPart = (body |> stmt => parModelicafunStatement(stmt, &varDecls, &auxFunction) ;separator="\n") + + /* Needs to be done last as it messes with the tmp ticks :) */ + let &varDecls += addRootsTempArray() + + << + <%auxFunction%> + + __kernel void omc_<%fname%>( + <%\t%><%\t%><%argStr%>) + { + /* functionBodyKernelFunction: Reconstruct Arrays */ + <%reconstrucedArrays%> + + /* functionBodyKernelFunction: locals */ + <%varDecls%> + + /* functionBodyKernelFunction: var inits */ + <%varInits%> + /* functionBodyKernelFunction: body */ + <%bodyPart%> + + /* Free GPU/OpenCL CPU memory */ + <%varFrees%> + } + + >> +end functionBodyKernelFunction; + +//Generates the body of a parallel function +template functionBodyParallelFunction(Function fn, Boolean inFunc) + "Generates the body for a Modelica parallel function." +::= +match fn +case PARALLEL_FUNCTION(__) then + let()= System.tmpTickReset(1) + let fname = underscorePath(name) + let retType = if outVars then '<%fname%>_rettype' else "void" + let &varDecls = buffer "" + let &varInits = buffer "" + let &varFrees = buffer "" + let &auxFunction = buffer "" + let retVar = if outVars then tempDecl(retType, &varDecls) + let _ = (variableDeclarations |> var hasindex i1 fromindex 1 => + varInitParallel(var, "", i1, &varDecls, &varInits, &varFrees, &auxFunction) + ;empty + ) + let bodyPart = (body |> stmt => parModelicafunStatement(stmt, &varDecls, &auxFunction) ;separator="\n") + let &outVarInits = buffer "" + let &outVarCopy = buffer "" + let &outVarAssign = buffer "" + let _1 = (outVars |> var hasindex i1 fromindex 1 => + varOutputParallel(var, retVar, i1, &varDecls, &outVarInits, &outVarCopy, &outVarAssign, &auxFunction) + ;separator="\n"; empty + ) + + + << + <%auxFunction%> + <%retType%> omc_<%fname%>(<%functionArguments |> var => funArgDefinition(var) ;separator=", "%>) + { + <%varDecls%> + <%outVarInits%> + + <%varInits%> + + <%bodyPart%> + + <%outVarCopy%> + <%outVarAssign%> + + /*mahge: Free unwanted meomory allocated*/ + <%varFrees%> + + return<%if outVars then ' <%retVar%>' %>; + } + + >> +end functionBodyParallelFunction; + +template functionBodyKernelFunctionInterface(Function fn, Boolean inFunc) + "Generates the body for a Modelica/MetaModelica function." +::= +match fn +case KERNEL_FUNCTION(__) then + let()= System.tmpTickReset(1) + let()= System.tmpTickResetIndex(0,1) /* Boxed array indices */ + let fname = underscorePath(name) + let &auxFunction = buffer "" + + let &varDecls = buffer "" + let &varInits = buffer "" + let &varFrees = buffer "" + let _ = (listGet(outVars,1) |> var hasindex i1 fromindex 1 => + varInit(var, "", &varDecls, &varInits, &varFrees, &auxFunction) ; empty /* increase the counter! */ + ) + + let outVarAssign = (List.restOrEmpty(outVars) |> var => varOutput(var)) + + let cl_kernelVar = tempDecl("cl_kernel", &varDecls) + let kernel_arg_number = '<%fname%>_arg_nr' + + let &kernelArgSets = buffer "" + let _ = (functionArguments |> var => + setKernelArg_ith(var, &cl_kernelVar, &kernel_arg_number, &kernelArgSets) + ) + let _ = (outVars |> var => + setKernelArg_ith(var, &cl_kernelVar, &kernel_arg_number, &kernelArgSets) + ) + + let defines = (List.restOrEmpty(outVars) |> var as VARIABLE(__) => '#define <%contextCref(name,contextFunction,&auxFunction)%> (*out<%contextCref(name,contextFunction,&auxFunction)%>)' ;separator="\n") + let undefines = (List.restOrEmpty(outVars) |> var as VARIABLE(__) => '#undef <%contextCref(name,contextFunction,&auxFunction)%>' ;separator="\n") + + << + + <%functionHeaderKernelFunctionInterfacePrototype(fname, functionArguments, outVars)%> + { + <%defines%> + + <%varDecls%> + + <%varInits%> + + /* functionBodyKernelFunctionInterface : <%fname%> Kernel creation and execution */ + int <%kernel_arg_number%> = 0; + <%cl_kernelVar%> = ocl_create_kernel(omc_ocl_program, "omc_<%fname%>"); + <%kernelArgSets%> + ocl_execute_kernel(<%cl_kernelVar%>); + clReleaseKernel(<%cl_kernelVar%>); + /*functionBodyKernelFunctionInterface : <%fname%> kernel execution ends here.*/ + + <%outVarAssign%> + + <%varFrees%> + + <%match outVars + case {} then 'return;' + case var::_ then 'return <%funArgName(var)%>;' + %> + + <%undefines%> + } + + >> + +end functionBodyKernelFunctionInterface; + +template setKernelArg_ith(Variable var, Text &KernelName, Text &argNr, Text &parVarList /*BUFPA*/) +::= +let &auxFunction = buffer "" +match var +//function args will have nill instdims even if they are arrays. handled here +case var as VARIABLE(ty=T_ARRAY(__),parallelism=PARGLOBAL(__)) then + let varName = '<%contextCref(var.name,contextFunction,&auxFunction)%>' + let &parVarList += 'ocl_set_kernel_arg(<%KernelName%>, <%argNr%>, <%varName%>.data); ++<%argNr%>; <%\n%>' + let &parVarList += 'ocl_set_kernel_arg(<%KernelName%>, <%argNr%>, <%varName%>.info_dev); ++<%argNr%>; <%\n%>' + "" +case var as VARIABLE(ty=T_ARRAY(__),parallelism=PARLOCAL(__)) then + let varName = '<%contextCref(var.name,contextFunction,&auxFunction)%>' + // Increment twice. Both data and info set in the function + // let &parVarList += 'ocl_set_local_array_kernel_arg(<%KernelName%>, <%argNr%>, &<%varName%>); ++<%argNr%>; ++<%argNr%>; <%\n%>' + let &parVarList += 'ocl_set_local_kernel_arg(<%KernelName%>, <%argNr%>, sizeof(modelica_<%expTypeShort(var.ty)%>) * device_array_nr_of_elements(&<%varName%>)); ++<%argNr%>; <%\n%>' + let &parVarList += 'ocl_set_local_kernel_arg(<%KernelName%>, <%argNr%>, sizeof(modelica_integer) * (<%varName%>.info[0]+1)*sizeof(modelica_integer)); ++<%argNr%>; <%\n%>' + "" +case var as VARIABLE(__) then + let varName = '<%contextCref(var.name,contextFunction,&auxFunction)%>' + if instDims then + let &parVarList += 'ocl_set_kernel_arg(<%KernelName%>, <%argNr%>, <%varName%>.data); ++<%argNr%>; <%\n%>' + let &parVarList += 'ocl_set_kernel_arg(<%KernelName%>, <%argNr%>, <%varName%>.info_dev); ++<%argNr%>; <%\n%>' + "" + else + let &parVarList += 'ocl_set_kernel_arg(<%KernelName%>, <%argNr%>, <%varName%>); ++<%argNr%>; <%\n%>' + "" +end setKernelArg_ith; + + +template setKernelArgFormTupleLoopVars_ith(tuple tupleVar, Text &KernelName, Text &argNr, Text &parVarList, Context context /*BUFPA*/) +::= +match tupleVar +//function args will have nill instdims even if they are arrays. handled here +case tupleVar as ((cref as CREF_IDENT(identType = T_ARRAY(__)),_)) then + let varName = contextArrayCref(cref,context) + let &parVarList += 'ocl_set_kernel_arg(<%KernelName%>, <%argNr%>, <%varName%>.data); ++<%argNr%>; <%\n%>' + let &parVarList += 'ocl_set_kernel_arg(<%KernelName%>, <%argNr%>, <%varName%>.info_dev); ++<%argNr%>; <%\n%>' + "" +case tupleVar as ((cref as CREF_IDENT(__),_)) then + let varName = contextArrayCref(cref,context) + let &parVarList += 'ocl_set_kernel_arg(<%KernelName%>, <%argNr%>, <%varName%>); ++<%argNr%>; <%\n%>' + "" +end setKernelArgFormTupleLoopVars_ith; + + +template functionBodyExternalFunction(Function fn, Boolean inFunc, Boolean isSimulation) + "Generates the body for an external function (just a wrapper)." +::= +match fn +case efn as EXTERNAL_FUNCTION(__) then + let()= System.tmpTickReset(1) + let()= System.tmpTickResetIndex(0,1) /* Boxed array indices */ + let fname = underscorePath(name) + let retType = if outVars then '<%fname%>_rettype' else "void" + let &preExp = buffer "" + let &varDecls = buffer "" + let &varFrees = buffer "" + let &outputAlloc = buffer "" + let &auxFunction = buffer "" + let callPart = extFunCall(fn, &preExp, &varDecls, &auxFunction) + let _ = ( outVars |> var => + varInit(var, "", &varDecls, &outputAlloc, &varFrees, &auxFunction) + ; empty /* increase the counter! */ ) + + let outVarAssign = (List.restOrEmpty(outVars) |> var => varOutput(var)) + + let &varDecls += addRootsTempArray() + let boxedFn = functionBodyBoxed(fn, isSimulation) + let fnBody = << + <%auxFunction%> + <%functionPrototype(fname, funArgs, outVars, false, visibility, isSimulation)%> + { + <%varDecls%> + <%modelicaLine(info)%> + <%preExp%> + <%outputAlloc%> + <%callPart%> + <%outVarAssign%> + <%match outVars + case {} then 'return;' + case v::_ then 'return <%funArgName(v)%>;' + %> + } + >> + << + <% if dynamicLoad then + << + ptrT_<%extFunctionName(extName, language)%> ptr_<%extFunctionName(extName, language)%>=NULL; + >> %> + <%fnBody%> + <% if inFunc then generateInFunc(fname, funArgs, outVars) %> + <%boxedFn%> + >> +end functionBodyExternalFunction; + + +template functionBodyRecordConstructor(Function fn, Boolean isSimulation) + "Generates the body for a record constructor." +::= +match fn +case RECORD_CONSTRUCTOR(__) then + let()= System.tmpTickReset(1) + let &varDecls = buffer "" + let &varInits = buffer "" + let &varFrees = buffer "" + let &auxFunction = buffer "" + let fname = underscorePath(name) + let structType = '<%fname%>' + let structVar = tempDecl(structType, &varDecls) + let _ = (locals |> var => + varInitRecord(var, structVar, &varDecls, &varInits, &auxFunction) ; empty /* increase the counter! */ + ) + let boxedFn = functionBodyBoxed(fn, isSimulation) + << + <%auxFunction%> + <%fname%> omc_<%fname%>(threadData_t *threadData<%funArgs |> VARIABLE(__) => ', <%expTypeArrayIf(ty)%> <%crefStr(name)%>'%>) + { + <%varDecls%> + <%varInits%> + <%funArgs |> VARIABLE(__) => '<%structVar%>._<%crefStr(name)%> = <%crefStr(name)%>;' ;separator="\n"%> + return <%structVar%>; + } + + <%boxedFn%> + >> +end functionBodyRecordConstructor; + +template varInitRecord(Variable var, String prefix, Text &varDecls, Text &varInits, Text &auxFunction) + "Generates code to initialize variables. + Does not return anything: just appends declarations to buffers." +::= +match var +case var as VARIABLE(parallelism = NON_PARALLEL(__)) then + let varName = '<%prefix%>._<%crefToCStr(var.name)%>' + let &varInits += initRecordMembers(var, &auxFunction) + let instDimsInit = (instDims |> exp => + daeExp(exp, contextFunction, &varInits, &varDecls, &auxFunction) + ;separator=", ") + if instDims then + let defaultAlloc = 'alloc_<%expTypeShort(var.ty)%>_array(&<%varName%>, <%listLength(instDims)%>, <%instDimsInit%>);<%\n%>' + let defaultValue = varAllocDefaultValue(var, "", varName, defaultAlloc, &varDecls, &varInits, &auxFunction) + let &varInits += defaultValue + "" + else + (match var.value + case SOME(exp) then + let defaultValue = '<%varName%> = <%daeExp(exp, contextFunction, &varInits, &varDecls, &auxFunction)%>;<%\n%>' + let &varInits += defaultValue + + " " + else + "") + +case var as FUNCTION_PTR(__) then + "" +else error(sourceInfo(), 'Unknown local variable type in record') +end varInitRecord; + +template functionBodyBoxed(Function fn, Boolean isSimulation) + "Generates code for a boxed version of a function. Extracts the needed data + from a function and calls functionBodyBoxedImpl" +::= + let fname = match fn + case FUNCTION(__) + case EXTERNAL_FUNCTION(__) + case RECORD_CONSTRUCTOR(__) then + underscorePath(name) + << + <% + match fn + case FUNCTION(__) then if not isBoxedFunction(fn) then functionBodyBoxedImpl(name, functionArguments, outVars, visibility, isSimulation) + case EXTERNAL_FUNCTION(__) then if not isBoxedFunction(fn) then functionBodyBoxedImpl(name, funArgs, outVars, visibility, isSimulation) + case RECORD_CONSTRUCTOR(__) then boxRecordConstructor(fn, isSimulation) + %> + >> +end functionBodyBoxed; + +template functionBodyBoxedImpl(Absyn.Path name, list funargs, list outvars, SCode.Visibility visibility, Boolean isSimulation) + "Helper template for functionBodyBoxed, does all the real work." +::= + let() = System.tmpTickReset(1) + let()= System.tmpTickResetIndex(0,1) /* Boxed array indices */ + let fname = underscorePath(name) + let retTypeBoxed = if outvars then 'modelica_metatype' else "void" + let &varDecls = buffer "" + let &varBox = buffer "" + let &varUnbox = buffer "" + let &auxFunction = buffer "" + let args = (funargs |> arg => (", " + funArgUnbox(arg, &varDecls, &varBox, &auxFunction))) + let &varBoxIgnore = buffer "" + let &outputAllocIgnore = buffer "" + let &varFreesIgnore = buffer "" + let &auxFunctionIgnore = buffer "" + let outputs = ( List.restOrEmpty(outvars) |> var hasindex i1 fromindex 1 => + match var + case v as VARIABLE(__) then + if mmcConstructorType(liftArrayListExp(v.ty,v.instDims)) then + let _ = varInit(var, "", &varDecls, &outputAllocIgnore, &varFreesIgnore, &auxFunctionIgnore) + ", &" + funArgName(var) + else + ", out" + funArgName(var) + case FUNCTION_PTR(__) then ", out" + funArgName(var) + ; empty + ) + let retvar = (match outvars + case {} then "" + case (v as VARIABLE(__))::_ then + let _ = varInit(v, "", &varDecls, &outputAllocIgnore, &varFreesIgnore, &auxFunctionIgnore) + let out = ("out" + funArgName(v)) + let _ = funArgBox(out, funArgName(v), "", liftArrayListExp(v.ty,v.instDims), &varUnbox, &varDecls) + (if mmcConstructorType(liftArrayListExp(v.ty,v.instDims)) then + let &varDecls += 'modelica_metatype <%out%>;<%\n%>' + out + else + funArgName(v)) + case v::_ then + let _ = varInit(v, "", &varDecls, &outputAllocIgnore, &varFreesIgnore, &auxFunctionIgnore) + funArgName(v) + ) + let _ = (List.restOrEmpty(outvars) |> var as VARIABLE(__) => + let arg = funArgName(var) + funArgBox('*out<%arg%>', arg, 'out<%arg%>', liftArrayListExp(var.ty,var.instDims), &varUnbox, &varDecls) + ; separator="\n") + let prototype = functionPrototype(fname, funargs, outvars, true, visibility, isSimulation) + << + <%auxFunction%> + <%prototype%> + { + <%varDecls%> + <%addRootsTempArray()%> + <%varBox%> + <%match outvars case v::_ then '<%funArgName(v)%> = '%>omc_<%fname%>(threadData<%args%><%outputs%>); + <%varUnbox%> + <%match outvars case v::_ then 'return <%retvar%>;' else "return;"%> + } + >> +end functionBodyBoxedImpl; + +template boxRecordConstructor(Function fn, Boolean isSimulation) +::= +let &auxFunction = buffer "" +match fn +case RECORD_CONSTRUCTOR(__) then + let() = System.tmpTickReset(1) + let fname = underscorePath(name) + let retType = '<%fname%>_rettypeboxed' + let funArgsStr = (funArgs |> var => match var + case VARIABLE(__) then ", " + contextCref(name,contextFunction,&auxFunction) + case FUNCTION_PTR(__) then ", " + name + else error(sourceInfo(),"boxRecordConstructor:Unknown variable")) + let start = daeExpMetaHelperBoxStart(incrementInt(listLength(funArgs), 1)) + << + <%if isSimulation then "" else match visibility case PROTECTED(__) then "PROTECTED_FUNCTION_STATIC "%>modelica_metatype boxptr_<%fname%>(threadData_t *threadData<%funArgs |> var => (", " + funArgBoxedDefinition(var))%>) + { + return mmc_mk_box<%start%>3, &<%fname%>__desc<%funArgsStr%>); + } + >> +end boxRecordConstructor; + +template funArgUnbox(Variable var, Text &varDecls, Text &varBox, Text &auxFunction) +::= +match var +case VARIABLE(__) then + let varName = contextCref(name,contextFunction,&auxFunction) + unboxVariable(varName, ty, &varBox, &varDecls) +case FUNCTION_PTR(__) then // Function pointers don't need to be boxed. + '_<%name%>' +end funArgUnbox; + +template unboxVariable(String varName, Type varType, Text &preExp, Text &varDecls) +::= +match varType +case T_COMPLEX(complexClassType = EXTERNAL_OBJ(__)) +case T_STRING(__) +case T_METATYPE(__) +case T_METARECORD(__) +case T_METAUNIONTYPE(__) +case T_METALIST(__) +case T_METAARRAY(__) +case T_METAPOLYMORPHIC(__) +case T_METAOPTION(__) +case T_METATUPLE(__) +case T_METABOXED(__) then varName +case T_COMPLEX(complexClassType = RECORD(__)) then + unboxRecord(varName, varType, &preExp, &varDecls) +case T_ARRAY(__) then + '*((base_array_t*)<%varName%>)' +else + let shortType = mmcTypeShort(varType) + let ty = 'modelica_<%shortType%>' + let tmpVar = tempDecl(ty, &varDecls) + let &preExp += '<%tmpVar%> = mmc_unbox_<%shortType%>(<%varName%>);<%\n%>' + tmpVar +end unboxVariable; + +template unboxRecord(String recordVar, Type ty, Text &preExp, Text &varDecls) +::= +match ty +case T_COMPLEX(complexClassType = RECORD(path = path), varLst = vars) then + let tmpVar = tempDecl('<%underscorePath(path)%>', &varDecls) + let &preExp += (vars |> TYPES_VAR(name = compname) hasindex offset fromindex 2 => + let varType = mmcTypeShort(ty) + let untagTmp = tempDecl('modelica_metatype', &varDecls) + //let offsetStr = incrementInt(i1, 1) + let &unboxBuf = buffer "" + let unboxStr = unboxVariable(untagTmp, ty, &unboxBuf, &varDecls) + << + <%untagTmp%> = (MMC_FETCH(MMC_OFFSET(MMC_UNTAGPTR(<%recordVar%>), <%offset%>))); + <%unboxBuf%> + <%tmpVar%>._<%compname%> = <%unboxStr%>; + >> + ;separator="\n") + tmpVar +end unboxRecord; + +template funArgBox(String outName, String varName, String condition, Type ty, Text &varUnbox, Text &varDecls) + "Generates code to box a variable." +::= + let constructorType = mmcConstructorType(ty) + if constructorType then + let constructor = mmcConstructor(ty, varName, &varUnbox, &varDecls) + let &varUnbox += if condition then 'if (<%condition%>) { <%outName%> = <%constructor%>; }<%\n%>' else '<%outName%> = <%constructor%>;<%\n%>' + outName + else // Some types don't need to be boxed, since they're already boxed. + let &varUnbox += '/* skip box <%varName%>; <%unparseType(ty)%> */<%\n%>' + varName +end funArgBox; + +template mmcConstructorType(Type type) +::= + match type + case T_INTEGER(__) + case T_BOOL(__) + case T_REAL(__) + case T_ENUMERATION(__) + case T_ARRAY(__) + case T_COMPLEX(complexClassType = RECORD(__)) then 'modelica_metatype' +end mmcConstructorType; + +template mmcConstructor(Type type, String varName, Text &preExp, Text &varDecls) +::= + match type + case T_INTEGER(__) then 'mmc_mk_icon(<%varName%>)' + case T_BOOL(__) then 'mmc_mk_icon(<%varName%>)' + case T_REAL(__) then 'mmc_mk_rcon(<%varName%>)' + case T_STRING(__) then 'mmc_mk_string(<%varName%>)' + case T_ENUMERATION(__) then 'mmc_mk_icon(<%varName%>)' + case T_ARRAY(__) then 'mmc_mk_modelica_array(<%varName%>)' + case T_COMPLEX(complexClassType = RECORD(path = path), varLst = vars) then + let varCount = daeExpMetaHelperBoxStart(incrementInt(listLength(vars), 1)) + let varsStr = (vars |> var as TYPES_VAR(__) => + let tmp = tempDecl("modelica_metatype", &varDecls) + let varname = '<%varName%>._<%name%>' + ", " + funArgBox(tmp, varname, "", ty, &preExp, &varDecls) + ) + 'mmc_mk_box<%varCount%>3, &<%underscorePath(path)%>__desc<%varsStr%>)' + case T_COMPLEX(__) then 'mmc_mk_box(<%varName%>)' +end mmcConstructor; + +template readInVar(Variable var) + "Generates code for reading a variable from inArgs." +::= + let &auxFunction = buffer "" + match var + case VARIABLE(name=cr, ty=T_COMPLEX(complexClassType=RECORD(__))) then + << + if (read_modelica_record(&inArgs, <%readInVarRecordMembers(ty, contextCref(cr,contextFunction,&auxFunction))%>)) return 1; + >> + case VARIABLE(name=cr, ty=T_STRING(__)) then + << + if (read_<%expTypeArrayIf(ty)%>(&inArgs, <%if not acceptMetaModelicaGrammar() then "(char**)"%> &<%contextCref(name,contextFunction,&auxFunction)%>)) return 1; + >> + case VARIABLE(__) then + << + if (read_<%expTypeArrayIf(ty)%>(&inArgs, &<%contextCref(name,contextFunction,&auxFunction)%>)) return 1; + >> +end readInVar; + + +template readInVarRecordMembers(Type type, String prefix) + "Helper to readInVar." +::= +match type +case T_COMPLEX(varLst=vl) then + (vl |> subvar as TYPES_VAR(__) => + match ty case T_COMPLEX(__) then + let newPrefix = '<%prefix%>._<%subvar.name%>' + readInVarRecordMembers(ty, newPrefix) + else + '&(<%prefix%>._<%subvar.name%>)' + ;separator=", ") +end readInVarRecordMembers; + + +template writeOutVar(Variable var) + "Generates code for writing a variable to outVar." + +::= + match var + case VARIABLE(ty=T_COMPLEX(complexClassType=RECORD(__))) then + << + write_modelica_record(outVar, <%writeOutVarRecordMembers(ty, funArgName(var))%>); + >> + case VARIABLE(__) then + + << + write_<%varType(var)%>(outVar, &<%funArgName(var)%>); + >> +end writeOutVar; + + +template writeOutVarRecordMembers(Type type, String prefix) + "Helper to writeOutVar." +::= +match type +case T_COMPLEX(varLst=vl, complexClassType=n) then + let basename = underscorePath(ClassInf.getStateName(n)) + let args = (vl |> subvar as TYPES_VAR(__) => + match ty case T_COMPLEX(__) then + let newPrefix = '<%prefix%>._<%subvar.name%>' + '<%expTypeRW(ty)%>, <%writeOutVarRecordMembers(ty, newPrefix)%>' + else + '<%expTypeRW(ty)%>, &(<%prefix%>._<%subvar.name%>)' + ;separator=", ") + << + &<%basename%>__desc<%if args then ', <%args%>'%>, TYPE_DESC_NONE + >> +end writeOutVarRecordMembers; + +template varInit(Variable var, String outStruct, Text &varDecls, Text &varInits, Text &varFrees, Text &auxFunction) + "Generates code to initialize variables. + Does not return anything: just appends declarations to buffers." +::= +match var +case var as VARIABLE(parallelism = NON_PARALLEL(__)) then + let varName = contextCref(var.name,contextFunction,&auxFunction) + let typ = varType(var) + let initVar = match typ case "modelica_metatype" + case "modelica_string" then ' = NULL' + else '' + let &varDecls += if not outStruct then '<%typ%> <%varName%><%initVar%>;<%\n%>' //else "" + let varName = contextCref(var.name,contextFunction,&auxFunction) + let &varInits += initRecordMembers(var, &auxFunction) + let instDimsInit = (instDims |> exp => + daeExp(exp, contextFunction, &varInits, &varDecls, &auxFunction) + ;separator=", ") + if instDims then + (match var.ty + case T_COMPLEX(__) then + let defaultAlloc = 'alloc_generic_array(&<%varName%>, sizeof(<%expTypeShort(var.ty)%>), <%listLength(instDims)%>, <%instDimsInit%>);<%\n%>' + (match var.value + case SOME(exp) then + let defaultValue = varAllocDefaultValue(var, outStruct, varName, defaultAlloc, &varDecls, &varInits, &auxFunction) + let &varInits += defaultValue + "" + else + let &varInits += defaultAlloc + "") + else + let defaultAlloc = 'alloc_<%expTypeShort(var.ty)%>_array(&<%varName%>, <%listLength(instDims)%>, <%instDimsInit%>);<%\n%>' + let defaultValue = varAllocDefaultValue(var, outStruct, varName, defaultAlloc, &varDecls, &varInits, &auxFunction) + let &varInits += defaultValue + "") + else + (match var.value + case SOME(exp) then + let defaultValue = '<%contextCref(var.name,contextFunction,&auxFunction)%> = <%daeExp(exp, contextFunction, &varInits, &varDecls, &auxFunction)%>;<%\n%>' + let &varInits += defaultValue + + " " + else + "") + +//mahge: OpenCL/CUDA GPU variables. +case var as VARIABLE(__) then + parVarInit(var, outStruct, &varDecls, &varInits, &varFrees, &auxFunction) + +case var as FUNCTION_PTR(__) then + let &varDecls += 'modelica_fnptr _<%name%>;<%\n%>' + let varInitText = (match defaultValue + case SOME(exp) then + let v = daeExp(exp, contextFunction, &varInits, &varDecls, &auxFunction) + '_<%name%> = <%v%>;<%\n%>') + let &varInits += varInitText + "" +else error(sourceInfo(), 'Unknown local variable type') +end varInit; + +/* ParModelica Extension. */ +template parVarInit(Variable var, String outStruct, Text &varDecls, Text &varInits, Text &varFrees, Text &auxFunction) + "Generates code to initialize ParModelica variables. + Does not return anything: just appends declarations to buffers." +::= +match var +case var as VARIABLE(parallelism = PARGLOBAL(__)) then + let varName = '<%contextCref(var.name, contextFunction, &auxFunction)%>' + + let instDimsInit = (instDims |> exp => + daeExp(exp, contextFunction, &varInits, &varDecls, &auxFunction) + ;separator=", ") + + if instDims then + let &varDecls += 'device_<%expTypeShort(var.ty)%>_array <%varName%>;<%\n%>' + let defaultAlloc = 'alloc_<%expTypeShort(var.ty)%>_array(&<%varName%>, <%listLength(instDims)%>, <%instDimsInit%>);<%\n%>' + let defaultValue = varAllocDefaultValue(var, outStruct, varName, defaultAlloc, &varDecls, &varInits, &auxFunction) + let &varInits += defaultValue + + let &varFrees += 'free_device_array(&<%varName%>);<%\n%>' + "" + else + (match var.value + case SOME(exp) then + let &varDecls += '<%varType(var)%> <%varName%>;<%\n%>' + let defaultValue = '<%contextCref(var.name,contextFunction,&auxFunction)%> = <%daeExp(exp, contextFunction, &varInits, &varDecls, &auxFunction)%>;<%\n%>' + let &varInits += defaultValue + + " " + else + let &varDecls += '<%varType(var)%> <%varName%>;<%\n%>' + "") + +case var as VARIABLE(parallelism = PARLOCAL(__)) then + let varName = '<%contextCref(var.name, contextFunction, &auxFunction)%>' + + let instDimsInit = (instDims |> exp => + daeExp(exp, contextFunction, &varInits, &varDecls, &auxFunction) + ;separator=", ") + if instDims then + let &varDecls += 'device_local_<%expTypeShort(var.ty)%>_array <%varName%>;<%\n%>' + let defaultAlloc = 'alloc_device_local_<%expTypeShort(var.ty)%>_array(&<%varName%>, <%listLength(instDims)%>, <%instDimsInit%>);<%\n%>' + let defaultValue = varAllocDefaultValue(var, outStruct, varName, defaultAlloc, &varDecls, &varInits, &auxFunction) + let &varInits += defaultValue + + // let &varFrees += 'free_device_array(&<%varName%>);<%\n%>' + "" + else + (match var.value + case SOME(exp) then + let &varDecls += '<%varType(var)%> <%varName%>;<%\n%>' + let defaultValue = '<%contextCref(var.name,contextFunction,&auxFunction)%> = <%daeExp(exp, contextFunction, &varInits, &varDecls, &auxFunction)%>;<%\n%>' + let &varInits += defaultValue + + " " + else + let &varDecls += '<%varType(var)%> <%varName%>;<%\n%>' + "") + +else + let &varDecls += '#error Unknown parallel variable type<%\n%>' + error(sourceInfo(), 'parVarInit:error Unknown parallel variable type') +end parVarInit; + +template varInitParallel(Variable var, String outStruct, Integer i, Text &varDecls, Text &varInits, Text &varFrees, Text &auxFunction) + "Generates code to initialize variables in PARALLEL FUNCTIONS. + Does not return anything: just appends declarations to buffers." +::= +match var +case var as VARIABLE(__) then + let &varDecls += if not outStruct then '<%varType(var)%> <%contextCref(var.name, contextFunction, &auxFunction)%>;<%\n%>' //else "" + let varName = if outStruct then '<%outStruct%>.targ<%i%>' else '<%contextCref(var.name, contextFunction, &auxFunction)%>' + let instDimsInit = (instDims |> exp => + daeExp(exp, contextFunction, &varInits, &varDecls, &auxFunction) + ;separator=", ") + if instDims then + let defaultAlloc = 'alloc_<%expTypeShort(var.ty)%>_array_c99_<%listLength(instDims)%>(&<%varName%>, <%listLength(instDims)%>, <%instDimsInit%>, memory_state);<%\n%>' + let defaultValue = varAllocDefaultValue(var, outStruct, varName, defaultAlloc, &varDecls, &varInits, &auxFunction) + let &varInits += defaultValue + " " + else + (match var.value + case SOME(exp) then + let defaultValue = '<%contextCref(var.name,contextFunction,&auxFunction)%> = <%daeExp(exp, contextFunction, &varInits, &varDecls, &auxFunction)%>;<%\n%>' + let &varInits += defaultValue + " " + else + "") +case var as FUNCTION_PTR(__) then + "" +else + let &varDecls += '#error Unknown local variable type<%\n%>' + error(sourceInfo(), 'varInitParallel:error Unknown local variable type') +end varInitParallel; + + +template varAllocDefaultValue(Variable var, String outStruct, String lhsVarName, Text allocNoDefault, Text &varDecls, Text &varInits, Text &auxFunction) +::= +match var +case var as VARIABLE(__) then + match value + case SOME(CREF(componentRef = cr)) then + 'copy_<%expTypeShort(var.ty)%>_array(<%contextCref(cr,contextFunction,&auxFunction)%>, &<%lhsVarName%>);<%\n%>' + case SOME(arr as ARRAY(ty = T_ARRAY(ty = T_COMPLEX(complexClassType = record_state)))) then + let &varInits += allocNoDefault + let varName = contextCref(var.name,contextFunction,&auxFunction) + let rec_name = '<%underscorePath(ClassInf.getStateName(record_state))%>' + let &preExp = buffer "" + let params = (arr.array |> e hasindex i1 fromindex 1 => + let prefix = if arr.scalar then '(<%expTypeFromExpModelica(e)%>)' else '&' + '(*((<%rec_name%>*)generic_array_element_addr(&<%varName%>, sizeof(<%rec_name%>), 1, <%i1%>))) = <%prefix%><%daeExp(e, contextFunction, &preExp, &varDecls, &auxFunction)%>;' + ;separator="\n") + << + <%preExp%> + <%params%> + >> + case SOME(arr as ARRAY(__)) then + let arrayExp = '<%daeExp(arr, contextFunction, &varInits, &varDecls, &auxFunction)%>' + 'copy_<%expTypeShort(var.ty)%>_array(<%arrayExp%>, &<%lhsVarName%>);<%\n%>' + case SOME(exp) then + '<%lhsVarName%> = <%daeExp(exp, contextFunction, &varInits, &varDecls, &auxFunction)%>;<%\n%>' + else + let &varInits += allocNoDefault + "" +end varAllocDefaultValue; + +template varOutput(Variable var) + "Generates code to copy result value from a function to dest." +::= + match var + case FUNCTION_PTR(__) then + 'if (out<%funArgName(var)%>) { *out<%funArgName(var)%> = (modelica_fnptr)<%funArgName(var)%>; }<%\n%>' + case VARIABLE(ty=T_ARRAY(__)) then + // If the dim_size is NULL, the output is an array with unknown dimensions. Copy the array. + 'if (out<%funArgName(var)%>) { if (out<%funArgName(var)%>->dim_size == NULL) {copy_<%expTypeShort(var.ty)%>_array(<%funArgName(var)%>, out<%funArgName(var)%>);} else {copy_<%expTypeShort(var.ty)%>_array_data(<%funArgName(var)%>, out<%funArgName(var)%>);} }<%\n%>' + case VARIABLE(__) then + /*Seems like we still get an array var with the wrong type here. It have instdims though >_<. TODO I guess*/ + if instDims then + 'if (out<%funArgName(var)%>) { if (out<%funArgName(var)%>->dim_size == NULL) {copy_<%expTypeShort(var.ty)%>_array(<%funArgName(var)%>, out<%funArgName(var)%>);} else {copy_<%expTypeShort(var.ty)%>_array_data(<%funArgName(var)%>, out<%funArgName(var)%>);} }<%\n%>' + else + 'if (out<%funArgName(var)%>) { *out<%funArgName(var)%> = <%funArgName(var)%>; }<%\n%>' + else error(sourceInfo(), 'varOutput:error Unknown variable type as output') +end varOutput; + +template varOutputParallel(Variable var, String dest, Integer ix, Text &varDecls, + Text &varInits, Text &varCopy, Text &varAssign, Text &auxFunction) + "Generates code to copy result value from a function to dest in a Parallel function." +::= +match var +/* The storage size of arrays is known at call time, so they can be allocated + * before set_memory_state. Strings are not known, so we copy them, etc... + */ +case var as VARIABLE(ty = T_STRING(__)) then + if not acceptMetaModelicaGrammar() then + // We need to strdup() all strings, then allocate them on the memory pool again, then free the temporary string + let &varCopy += 'String Variables not Allowed in ParModelica.' + let &varAssign += + << + String Variables not Allowed in ParModelica. + >> + "" + else + let &varAssign += 'How did you get here??' + "" +case var as VARIABLE(parallelism = PARGLOBAL(__)) then + let instDimsInit = (instDims |> exp => + daeExp(exp, contextFunction, &varInits, &varDecls, &auxFunction) + ;separator=", ") + if instDims then + let &varInits += 'alloc_<%expTypeShort(var.ty)%>_array_c99_<%listLength(instDims)%>(&<%dest%>.c<%ix%>, <%listLength(instDims)%>, <%instDimsInit%>, memory_state);<%\n%>' + let &varAssign += 'copy_<%expTypeShort(var.ty)%>_array_data(<%contextCref(var.name,contextFunction, &auxFunction)%>, &<%dest%>.c<%ix%>);<%\n%>' + "" + else + let &varInits += '<%dest%>.c<%ix%> = ocl_device_alloc(sizeof(modelica_<%expTypeShort(var.ty)%>));<%\n%>' + let &varAssign += 'copy_assignment_helper_<%expTypeShort(var.ty)%>(&<%dest%>.c<%ix%>, &<%contextCref(var.name,contextFunction,&auxFunction)%>);<%\n%>' + "" + +case var as VARIABLE(parallelism = PARLOCAL(__)) then + let instDimsInit = (instDims |> exp => + daeExp(exp, contextFunction, &varInits, &varDecls, &auxFunction) + ;separator=", ") + if instDims then + let &varInits += 'alloc_<%expTypeShort(var.ty)%>_array_c99_<%listLength(instDims)%>(&<%dest%>.c<%ix%>, <%listLength(instDims)%>, <%instDimsInit%>, memory_state);<%\n%>' + let &varAssign += 'copy_<%expTypeShort(var.ty)%>_array_data(<%contextCref(var.name, contextFunction, &auxFunction)%>, &<%dest%>.c<%ix%>);<%\n%>' + "" + else + let &varInits += 'LOCAL HERE!! <%dest%>.c<%ix%> = ocl_device_alloc(sizeof(modelica_<%expTypeShort(var.ty)%>));<%\n%>' + let &varAssign += 'LOCAL HERE!! copy_assignment_helper_<%expTypeShort(var.ty)%>(&<%dest%>.c<%ix%>, &<%contextCref(var.name,contextFunction,&auxFunction)%>);<%\n%>' + "" + +case var as VARIABLE(__) then + let instDimsInit = (instDims |> exp => + daeExp(exp, contextFunction, &varInits, &varDecls, &auxFunction) + ;separator=", ") + if instDims then + let &varInits += 'alloc_<%expTypeShort(var.ty)%>_array_c99_<%listLength(instDims)%>(&<%dest%>.c<%ix%>, <%listLength(instDims)%>, <%instDimsInit%>, memory_state);<%\n%>' + let &varAssign += 'copy_<%expTypeShort(var.ty)%>_array_data(<%contextCref(var.name,contextFunction,&auxFunction)%>, &<%dest%>.c<%ix%>);<%\n%>' + "" + else + let &varInits += initRecordMembers(var, &auxFunction) + let &varAssign += '<%dest%>.c<%ix%> = <%contextCref(var.name,contextFunction,&auxFunction)%>;<%\n%>' + "" +case var as FUNCTION_PTR(__) then + let &varAssign += '<%dest%>.c<%ix%> = (modelica_fnptr) _<%var.name%>;<%\n%>' + "" +end varOutputParallel; + +template varOutputKernelInterface(Variable var, String dest, Integer ix, Text &varDecls, + Text &varInits, Text &varCopy, Text &varAssign, Text &auxFunction) + "Generates code to copy result value from a function to dest." +::= +match var +case var as VARIABLE(parallelism = PARGLOBAL(__)) then + let &varDecls += '<%varType(var)%> <%contextCref(var.name,contextFunction,&auxFunction)%>;<%\n%>' + let varName = '<%contextCref(var.name,contextFunction,&auxFunction)%>' + let instDimsInit = (instDims |> exp => + daeExp(exp, contextFunction, &varInits, &varDecls, &auxFunction) + ;separator=", ") + if instDims then + let &varInits += 'alloc_<%expTypeShort(var.ty)%>_array(&<%varName%>, <%listLength(instDims)%>, <%instDimsInit%>);<%\n%>' + + let &varAssign += '<%dest%>.c<%ix%> = <%contextCref(var.name,contextFunction,&auxFunction)%>;<%\n%>' + "" + else + let &varInits += '<%varName%> = ocl_device_alloc(sizeof(modelica_<%expTypeShort(var.ty)%>));<%\n%>' + let &varAssign += '<%dest%>.c<%ix%> = <%contextCref(var.name,contextFunction,&auxFunction)%>;<%\n%>' + "" + +case var as VARIABLE(parallelism = PARLOCAL(__)) then + let &varDecls += '<%varType(var)%> <%contextCref(var.name,contextFunction,&auxFunction)%>;<%\n%>' + let varName = '<%contextCref(var.name,contextFunction,&auxFunction)%>' + let instDimsInit = (instDims |> exp => + daeExp(exp, contextFunction, &varInits, &varDecls, &auxFunction) + ;separator=", ") + if instDims then + let &varInits += 'alloc_<%expTypeShort(var.ty)%>_array(&<%varName%>, <%listLength(instDims)%>, <%instDimsInit%>);<%\n%>' + + let &varAssign += '<%dest%>.c<%ix%> = <%contextCref(var.name,contextFunction,&auxFunction)%>;<%\n%>' + "" + else + let &varInits += '<%varName%> = ocl_device_alloc(sizeof(modelica_<%expTypeShort(var.ty)%>));<%\n%>' + let &varAssign += '<%dest%>.c<%ix%> = <%contextCref(var.name,contextFunction,&auxFunction)%>;<%\n%>' + "" + +case var as VARIABLE(__) then + let &varDecls += '<%varType(var)%> <%contextCref(var.name,contextFunction,&auxFunction)%>;<%\n%>' + let varName = '<%contextCref(var.name,contextFunction,&auxFunction)%>' + let instDimsInit = (instDims |> exp => + daeExp(exp, contextFunction, &varInits, &varDecls, &auxFunction) + ;separator=", ") + if instDims then + let &varInits += 'alloc_<%expTypeShort(var.ty)%>_array(&<%varName%>, <%listLength(instDims)%>, <%instDimsInit%>);<%\n%>' + + let &varAssign += '<%dest%>.c<%ix%> = <%contextCref(var.name,contextFunction,&auxFunction)%>;<%\n%>' + "" + else + let &varInits += initRecordMembers(var, &auxFunction) + let &varAssign += '<%dest%>.c<%ix%> = <%contextCref(var.name,contextFunction,&auxFunction)%>;<%\n%>' + "" +case var as FUNCTION_PTR(__) then + let &varAssign += '<%dest%>.c<%ix%> = (modelica_fnptr) _<%var.name%>;<%\n%>' + "" +end varOutputKernelInterface; + +template initRecordMembers(Variable var, Text &auxFunction) +::= +match var +case VARIABLE(ty = T_COMPLEX(complexClassType = RECORD(__))) then + let varName = contextCref(name,contextFunction,&auxFunction) + (ty.varLst |> v => recordMemberInit(v, varName) ;separator="\n") +end initRecordMembers; + +template recordMemberInit(Var v, Text varName) +::= +match v +case TYPES_VAR(ty = T_ARRAY(__)) then + let arrayType = expType(ty, true) + let dims = (ty.dims |> dim => dimension(dim) ;separator=", ") + 'alloc_<%arrayType%>(&<%varName%>._<%name%>, <%listLength(ty.dims)%>, <%dims%>);' +end recordMemberInit; + +template extVarName(ComponentRef cr) +::= '_<%crefToMStr(appendStringFirstIdent("_ext", cr))%>' +end extVarName; + +template extFunCall(Function fun, Text &preExp, Text &varDecls, Text &auxFunction) + "Generates the call to an external function." +::= +match fun +case EXTERNAL_FUNCTION(__) then + match language + case "C" then extFunCallC(fun, &preExp, &varDecls, &auxFunction) + case "FORTRAN 77" then extFunCallF77(fun, &preExp, &varDecls, &auxFunction) +end extFunCall; + +template extFunCallC(Function fun, Text &preExp, Text &varDecls, Text &auxFunction) + "Generates the call to an external C function." +::= +match fun +case EXTERNAL_FUNCTION(__) then + /* adpro: 2011-06-24 do vardecls -> extArgs as there might be some sets in there! */ + let varDecs = (List.union(extArgs, extArgs) |> arg => extFunCallVardecl(arg, &varDecls, &auxFunction) ;separator="\n") + let _ = (biVars |> bivar => extFunCallBiVar(bivar, &preExp, &varDecls, &auxFunction) ;separator="\n") + let fname = if dynamicLoad then 'ptr_<%extFunctionName(extName, language)%>' else '<%extName%>' + let dynamicCheck = if dynamicLoad then + << + if(<%fname%>==NULL) + { + FILE_INFO info = {<%infoArgs(info)%>}; + omc_terminate(info, "dynamic external function <%extFunctionName(extName, language)%> not set!"); + } else + >> + else '' + let args = (extArgs |> arg => extArg(arg, &preExp, &varDecls, &auxFunction) ;separator=", ") + let returnAssign = match extReturn case SIMEXTARG(cref=c) then + '<%extVarName(c)%> = ' + else + "" + << + <%varDecs%> + <%match extReturn case SIMEXTARG(__) then extFunCallVardecl(extReturn, &varDecls, &auxFunction)%> + <%dynamicCheck%> + <%returnAssign%><%fname%>(<%args%>); + <%extArgs |> arg => extFunCallVarcopy(arg, &auxFunction) ;separator="\n"%> + <%match extReturn case SIMEXTARG(__) then extFunCallVarcopy(extReturn, &auxFunction)%> + >> +end extFunCallC; + +template extFunCallF77(Function fun, Text &preExp, Text &varDecls, Text &auxFunction) + "Generates the call to an external Fortran 77 function." +::= +match fun +case EXTERNAL_FUNCTION(__) then + /* adpro: 2011-06-24 do vardecls -> bivar -> extArgs as there might be some sets in there! */ + let &varDecls += '/* extFunCallF77: varDecs */<%\n%>' + let varDecs = (List.union(extArgs, extArgs) |> arg => extFunCallVardeclF77(arg, &varDecls, &auxFunction) ;separator="\n") + let &varDecls += '/* extFunCallF77: biVarDecs */<%\n%>' + let &preExp += '/* extFunCallF77: biVarDecs */<%\n%>' + let biVarDecs = (biVars |> arg => extFunCallBiVarF77(arg, &preExp, &varDecls, &auxFunction) ;separator="\n") + let &varDecls += '/* extFunCallF77: args */<%\n%>' + let &preExp += '/* extFunCallF77: args */<%\n%>' + let args = (extArgs |> arg => extArgF77(arg, &preExp, &varDecls, &auxFunction) ;separator=", ") + let &preExp += '/* extFunCallF77: end args */<%\n%>' + let returnAssign = match extReturn case SIMEXTARG(cref=c) then + '<%extVarName(c)%> = ' + else + "" + << + <%varDecs%> + <%biVarDecs%> + /* extFunCallF77: extReturn */ + <%match extReturn case SIMEXTARG(__) then extFunCallVardeclF77(extReturn, &varDecls, &auxFunction)%> + /* extFunCallF77: CALL */ + <%returnAssign%><%extName%>_(<%args%>); + /* extFunCallF77: copy args */ + <%List.union(extArgs,extArgs) |> arg => extFunCallVarcopyF77(arg, &auxFunction) ;separator="\n"%> + /* extFunCallF77: copy return */ + <%match extReturn case SIMEXTARG(__) then extFunCallVarcopyF77(extReturn, &auxFunction)%> + >> + +end extFunCallF77; + +template extFunCallVardecl(SimExtArg arg, Text &varDecls, Text &auxFunction) + "Helper to extFunCall." +::= + match arg + case SIMEXTARG(isInput = true, isArray = true, type_ = ty, cref = c) then + match expTypeShort(ty) + case "integer" then + 'pack_integer_array(&<%contextCref(c,contextFunction,&auxFunction)%>);' + else "" + case SIMEXTARG(isInput=true, isArray=false, type_=ty, cref=c) then + match ty + case T_STRING(__) then + "" + case T_FUNCTION_REFERENCE_VAR(__) then + (match c + case CREF_IDENT(__) then + let &varDecls += 'modelica_fnptr <%extVarName(c)%>;<%\n%>' + << + if (MMC_FETCH(MMC_OFFSET(MMC_UNTAGPTR(_<%ident%>), 2))) { + <%generateThrow()%> /* The FFI does not allow closures */ + } + <%extVarName(c)%> = MMC_FETCH(MMC_OFFSET(MMC_UNTAGPTR(_<%ident%>), 1)); + >> + else + error(sourceInfo(), 'Got function pointer that is not a CREF_IDENT: <%crefStr(c)%>, <%unparseType(ty)%>')) + else + let &varDecls += '<%extType(ty,true,false)%> <%extVarName(c)%>;<%\n%>' + << + <%extVarName(c)%> = (<%extType(ty,true,false)%>)<%contextCref(c,contextFunction,&auxFunction)%>; + >> + case SIMEXTARG(outputIndex=oi, isArray=false, type_=ty, cref=c) then + match oi case 0 then + "" + else + let &varDecls += '<%extType(ty,true,false)%> <%extVarName(c)%>;<%\n%>' + "" +end extFunCallVardecl; + +template extFunCallVardeclF77(SimExtArg arg, Text &varDecls, Text &auxFunction) +::= + match arg + case SIMEXTARG(isInput = true, isArray = true, type_ = ty, cref = c) then + let &varDecls += '<%expTypeArrayIf(ty)%> <%extVarName(c)%>;<%\n%>' + 'convert_alloc_<%expTypeArray(ty)%>_to_f77(&<%contextCref(c,contextFunction,&auxFunction)%>, &<%extVarName(c)%>);' + case ea as SIMEXTARG(outputIndex = oi, isArray = ia, type_= ty, cref = c) then + match oi case 0 then "" else + match ia + case false then + let default_val = typeDefaultValue(ty) + let default_exp = if ea.hasBinding then "" else match default_val case "" then "" else ' = <%default_val%>' + let &varDecls += '<%extTypeF77(ty,false)%> <%extVarName(c)%><%default_exp%>;<%\n%>' + "" + else + let &varDecls += '<%expTypeArrayIf(ty)%> <%extVarName(c)%>;<%\n%>' + 'convert_alloc_<%expTypeArray(ty)%>_to_f77(&<%contextCref(c,contextFunction,&auxFunction)%>, &<%extVarName(c)%>);' + case SIMEXTARG(type_ = ty, cref = c) then + let &varDecls += '<%extTypeF77(ty,false)%> <%extVarName(c)%>;<%\n%>' + "" +end extFunCallVardeclF77; + +template typeDefaultValue(DAE.Type ty) +::= + match ty + case ty as T_INTEGER(__) then '0' + case ty as T_REAL(__) then '0.0' + case ty as T_BOOL(__) then '0' + case ty as T_STRING(__) then '0' /* Always segfault is better than only sometimes segfault :) */ + else "" +end typeDefaultValue; + +template extFunCallBiVar(Variable var, Text &preExp, Text &varDecls, Text &auxFunction) +::= + match var + case var as VARIABLE(__) then + let var_name = extVarName(name) + let &varDecls += '<%varType(var)%> <%var_name%>;<%\n%>' + let defaultValue = match value + case SOME(v) then + daeExp(v, contextFunction, &preExp, &varDecls, &auxFunction) + else "" + let &preExp += if defaultValue then '<%var_name%> = <%defaultValue%>;<%\n%>' + "" +end extFunCallBiVar; + +template extFunCallBiVarF77(Variable var, Text &preExp, Text &varDecls, Text &auxFunction) +::= + match var + case var as VARIABLE(__) then + let var_name = contextCref(name,contextFunction,&auxFunction) + let &varDecls += '<%varType(var)%> <%var_name%>;<%\n%>' + let &varDecls += '<%varType(var)%> <%extVarName(name)%>;<%\n%>' + let defaultValue = match value + case SOME(v) then + '<%daeExp(v, contextFunction, &preExp, &varDecls, &auxFunction)%>' + else "" + let instDimsInit = (instDims |> exp => + daeExp(exp, contextFunction, &preExp, &varDecls, &auxFunction) ;separator=", ") + if instDims then + let type = expTypeArray(var.ty) + let &preExp += 'alloc_<%type%>(&<%var_name%>, <%listLength(instDims)%>, <%instDimsInit%>);<%\n%>' + let &preExp += if defaultValue then 'copy_<%type%>(<%defaultValue%>, &<%var_name%>);<%\n%>' else '' + let &preExp += 'convert_alloc_<%type%>_to_f77(&<%var_name%>, &<%extVarName(name)%>);<%\n%>' + "" + else + let &preExp += if defaultValue then '<%var_name%> = <%defaultValue%>;<%\n%>' else '' + "" +end extFunCallBiVarF77; + +template extFunCallVarcopy(SimExtArg arg, Text &auxFunction) + "Helper to extFunCall." +::= +match arg +case SIMEXTARG(outputIndex=0) then "" +case SIMEXTARG(outputIndex=oi, isArray=true, cref=c, type_=ty) then + match expTypeShort(ty) + case "integer" then + 'unpack_integer_array(&<%contextCref(c,contextFunction,&auxFunction)%>);' + case "string" then + 'unpack_string_array(&<%contextCref(c,contextFunction,&auxFunction)%>);' + else "" +case SIMEXTARG(outputIndex=oi, isArray=false, type_=ty, cref=c) then + let cr = '<%extVarName(c)%>' + << + <%contextCref(c,contextFunction,&auxFunction)%> = (<%expTypeModelica(ty)%>)<% + match ty + case T_STRING(__) then 'mmc_mk_scon(<%cr%>)' + else cr%>; + >> +end extFunCallVarcopy; + +template extFunCallVarcopyF77(SimExtArg arg, Text &auxFunction) + "Generates code to copy results from output variables into the out struct. + Helper to extFunCallF77." +::= +match arg +case SIMEXTARG(outputIndex=oi, isArray=ai, type_=ty, cref=c) then + match oi case 0 then + "" + else + let outarg = contextCref(c,contextFunction,&auxFunction) + let ext_name = extVarName(c) + match ai + case false then + '<%outarg%> = (<%expTypeModelica(ty)%>)<%ext_name%>;<%\n%>' + case true then + 'convert_alloc_<%expTypeArray(ty)%>_from_f77(&<%ext_name%>, &<%outarg%>);' +end extFunCallVarcopyF77; + +template extArg(SimExtArg extArg, Text &preExp, Text &varDecls, Text &auxFunction) + "Helper to extFunCall." +::= + match extArg + case SIMEXTARG(cref=c, outputIndex=oi, isArray=true, type_=t) then + let name = contextCref(c,contextFunction,&auxFunction) + let shortTypeStr = expTypeShort(t) + '(<%extType(t,isInput,true)%>) data_of_<%shortTypeStr%>_c89_array(&(<%name%>))' + case SIMEXTARG(cref=c, isInput=ii, outputIndex=0, type_=t) then + let cr = match t case T_STRING(__) then contextCref(c,contextFunction,&auxFunction) else extVarName(c) + (match t case T_STRING(__) then 'MMC_STRINGDATA(<%cr%>)' else cr) + case SIMEXTARG(cref=c, isInput=ii, outputIndex=oi, type_=t) then + '&<%extVarName(c)%>' + case SIMEXTARGEXP(__) then + daeExternalCExp(exp, contextFunction, &preExp, &varDecls, &auxFunction) + case SIMEXTARGSIZE(cref=c) then + let typeStr = expTypeShort(type_) + let name = contextCref(c,contextFunction, &auxFunction) + let dim = daeExp(exp, contextFunction, &preExp, &varDecls, &auxFunction) + 'size_of_dimension_base_array(<%name%>, <%dim%>)' +end extArg; + +template extArgF77(SimExtArg extArg, Text &preExp, Text &varDecls, Text &auxFunction) +::= + match extArg + case SIMEXTARG(cref=c, isArray=true, type_=t) then + // Arrays are converted to fortran format that are stored in _ext-variables. + 'data_of_<%expTypeShort(t)%>_f77_array(&(<%extVarName(c)%>))' + case SIMEXTARG(cref=c, outputIndex=oi, type_=T_INTEGER(__)) then + // Always prefix fortran arguments with &. + let suffix = if oi then "_ext" + '(int*) &<%contextCref(c,contextFunction,&auxFunction)%><%suffix%>' + case SIMEXTARG(cref=c, outputIndex=oi, type_ = T_STRING(__)) then + // modelica_string SHOULD NOT BE PREFIXED by &! + '(char*)MMC_STRINGDATA(<%contextCref(c,contextFunction,&auxFunction)%>)' + case SIMEXTARG(cref=c, outputIndex=oi, type_=t) then + // Always prefix fortran arguments with &. + let suffix = if oi then "_ext" + '&<%contextCref(c,contextFunction, &auxFunction)%><%suffix%>' + case SIMEXTARGEXP(exp=exp, type_ = T_STRING(__)) then + // modelica_string SHOULD NOT BE PREFIXED by &! + let texp = daeExp(exp, contextFunction, &preExp, &varDecls, &auxFunction) + let tvar = tempDecl(expTypeFromExpFlag(exp,8),&varDecls) + let &preExp += '<%tvar%> = <%texp%>;<%\n%>' + '(char*)MMC_STRINGDATA(<%tvar%>)' + case SIMEXTARGEXP(__) then + daeExternalF77Exp(exp, contextFunction, &preExp, &varDecls, &auxFunction) + case SIMEXTARGSIZE(cref=c) then + // Fortran functions only takes references to variables, so we must store + // the result from size_of_dimension__array in a temporary variable. + let sizeVarName = tempSizeVarName(c, exp, &auxFunction) + let sizeVar = tempDecl("int", &varDecls) + let dim = daeExp(exp, contextFunction, &preExp, &varDecls, &auxFunction) + let &preExp += '<%sizeVar%> = size_of_dimension_base_array(<%contextCref(c,contextFunction, &auxFunction)%>, <%dim%>);<%\n%>' + '&<%sizeVar%>' +end extArgF77; + +template tempSizeVarName(ComponentRef c, DAE.Exp indices, Text &auxFunction) + +::= + match indices + case ICONST(__) then '<%contextCref(c,contextFunction,&auxFunction)%>_size_<%integer%>' + else error(sourceInfo(), 'tempSizeVarName:UNHANDLED_EXPRESSION') +end tempSizeVarName; + +template funStatement(Statement stmt, Text &varDecls, Text &auxFunction) + "Generates function statements." +::= + match stmt + case ALGORITHM(__) then + (statementLst |> stmt => + algStatement(stmt, contextFunction, &varDecls, &auxFunction) + ;separator="\n") + else + error(sourceInfo(), 'funStatement:NOT IMPLEMENTED FUN STATEMENT') +end funStatement; + +template parModelicafunStatement(Statement stmt, Text &varDecls, Text &auxFunction) + "Generates function statements With PARALLEL context. Similar to Function context. + Except in some cases like assignments." +::= + match stmt + case ALGORITHM(__) then + (statementLst |> stmt => + algStatement(stmt, contextParallelFunction, &varDecls, &auxFunction) + ;separator="\n") + else + error(sourceInfo(), 'parModelicafunStatement:NOT IMPLEMENTED FUN STATEMENT') +end parModelicafunStatement; + +template extractParFors(Statement stmt, Text &varDecls, Text &auxFunction) + "Generates bodies of parfor loops to the kernel file. + The sequential C operations needed to implement the parallel + for loop will be handled by the normal funStatment template." +::= + match stmt + case ALGORITHM(__) then + (statementLst |> stmt => + extractParFors_impl(stmt, contextParallelFunction, &varDecls, &auxFunction) + ;separator="\n") + else + error(sourceInfo(), 'extractParFors:NOT IMPLEMENTED FUN STATEMENT') +end extractParFors; + + +template extractParFors_impl(DAE.Statement stmt, Context context, Text &varDecls, Text &auxFunction) + "Generates an algorithm statement." +::= + match stmt + case s as STMT_PARFOR(__) then algStmtParForBody(s, contextParallelFunction, &varDecls, &auxFunction) +end extractParFors_impl; + + + +template algStatement(DAE.Statement stmt, Context context, Text &varDecls, Text &auxFunction) + "Generates an algorithm statement." +::= + match System.tmpTickIndexReserve(1, 0) /* Remember the old tmpTick */ + case oldIndex + then let res = (match stmt + case s as STMT_ASSIGN(exp1=PATTERN(__)) then algStmtAssignPattern(s, context, &varDecls, &auxFunction) + case s as STMT_ASSIGN(__) then algStmtAssign(s, context, &varDecls, &auxFunction) + case s as STMT_ASSIGN_ARR(__) then algStmtAssignArr(s, context, &varDecls, &auxFunction) + case s as STMT_TUPLE_ASSIGN(__) then algStmtTupleAssign(s, context, &varDecls, &auxFunction) + case s as STMT_IF(__) then algStmtIf(s, context, &varDecls, &auxFunction) + case s as STMT_FOR(__) then algStmtFor(s, context, &varDecls, &auxFunction) + case s as STMT_PARFOR(__) then algStmtParForInterface(s, context, &varDecls, &auxFunction) + case s as STMT_WHILE(__) then algStmtWhile(s, context, &varDecls, &auxFunction) + case s as STMT_ASSERT(__) then algStmtAssert(s, context, &varDecls, &auxFunction) + case s as STMT_TERMINATE(__) then algStmtTerminate(s, context, &varDecls, &auxFunction) + case s as STMT_WHEN(__) then algStmtWhen(s, context, &varDecls, &auxFunction) + case s as STMT_BREAK(__) then 'break;<%\n%>' + case s as STMT_CONTINUE(__) then 'continue;<%\n%>' + case s as STMT_FAILURE(__) then algStmtFailure(s, context, &varDecls, &auxFunction) + case s as STMT_RETURN(__) then 'goto _return;<%\n%>' + case s as STMT_NORETCALL(__) then algStmtNoretcall(s, context, &varDecls, &auxFunction) + case s as STMT_REINIT(__) then algStmtReinit(s, context, &varDecls, &auxFunction) + else error(sourceInfo(), 'ALG_STATEMENT NYI')) + let () = System.tmpTickSetIndex(oldIndex,1) + << + <%modelicaLine(getElementSourceFileInfo(getStatementSource(stmt)))%><%res%> + <%endModelicaLine()%> + >> +end algStatement; + + +template algStmtAssign(DAE.Statement stmt, Context context, Text &varDecls, Text &auxFunction) + "Generates an assigment algorithm statement." +::= + match stmt + case STMT_ASSIGN(exp=CALL(path=IDENT(name="fail"))) then + '<%generateThrow()%><%\n%>' + case STMT_ASSIGN(exp1=CREF(componentRef=WILD(__)), exp=e) then + let &preExp = buffer "" + let expPart = daeExp(e, context, &preExp, &varDecls, &auxFunction) + << + <%preExp%> + >> + case STMT_ASSIGN(exp1=CREF(componentRef=cr as CREF_QUAL(identType=T_METATYPE(ty=t1 as T_METARECORD(__)), componentRef=cr2 as CREF_IDENT(__)),ty=t2)) then + let &preExp = buffer "" + let tmp = tempDecl("modelica_metatype",&varDecls) + let varPart = '_<%cr.ident%>' // So it only works in function context? + let expPart = daeExp(exp, context, &preExp, &varDecls, &auxFunction) + let indexInRecord = intAdd(1, lookupIndexInMetaRecord(t1.fields, cr2.ident)) + let len = intAdd(2, listLength(t1.fields)) + << + <%preExp%> + <%tmp%> = MMC_TAGPTR(mmc_alloc_words(<%len%>)); + memcpy(MMC_UNTAGPTR(<%tmp%>), MMC_UNTAGPTR(<%varPart%>), <%len%>*sizeof(modelica_metatype)); + ((modelica_metatype*)MMC_UNTAGPTR(<%tmp%>))[<%indexInRecord%>] = <%expPart%>; + <%varPart%> = <%tmp%>; + >> + case STMT_ASSIGN(exp1=CREF(ty = T_FUNCTION_REFERENCE_VAR(__))) + case STMT_ASSIGN(exp1=CREF(ty = T_FUNCTION_REFERENCE_FUNC(__))) then + let &preExp = buffer "" + let varPart = daeExpCrefLhs(exp1, context, &preExp, &varDecls, &auxFunction) + let expPart = daeExp(exp, context, &preExp, &varDecls, &auxFunction) + << + <%preExp%> + <%varPart%> = (modelica_fnptr) <%expPart%>; + >> + /* Records need to be traversed, assigning each component by itself */ + case STMT_ASSIGN(exp1=CREF(componentRef=cr,ty = ty as T_COMPLEX(varLst = varLst, complexClassType=RECORD(__)))) then + let &preExp = buffer "" + let rec = daeExp(exp, context, &preExp, &varDecls, &auxFunction) + let tmp = tempDecl(expTypeModelica(ty),&varDecls) + << + <%preExp%> + <%tmp%> = <%rec%>; + <% varLst |> var as TYPES_VAR(__) => + match var.ty + case T_ARRAY(__) then + copyArrayData(var.ty, '<%tmp%>._<%var.name%>', appendStringCref(var.name,cr), context, &preExp, &varDecls, &auxFunction) + else + let varPart = contextCref(appendStringCref(var.name,cr),context, &auxFunction) + '<%varPart%> = <%tmp%>._<%var.name%>;' + ; separator="\n" + %> + >> + case STMT_ASSIGN(exp1=CALL(path=path,expLst=expLst,attr=CALL_ATTR(ty= T_COMPLEX(varLst = varLst, complexClassType=RECORD(__))))) then + let &preExp = buffer "" + let rec = daeExp(exp, context, &preExp, &varDecls, &auxFunction) + << + <%preExp%> + <% varLst |> var as TYPES_VAR(__) hasindex i1 fromindex 1 => + let re = daeExp(listGet(expLst,i1), context, &preExp, &varDecls, &auxFunction) + '<%re%> = <%rec%>._<%var.name%>;' + ; separator="\n" + %> + >> + case STMT_ASSIGN(exp1=CREF(__)) then + let &preExp = buffer "" + let varPart = daeExpCrefLhs(exp1, context, &preExp, &varDecls, &auxFunction) + let expPart = daeExp(exp, context, &preExp, &varDecls, &auxFunction) + << + <%preExp%> + <%varPart%> = <%expPart%>; + >> + case STMT_ASSIGN(exp1=exp1 as ASUB(__),exp=val) then + (match expTypeFromExpShort(exp) + case "metatype" then + // MetaModelica Array + (match exp1 case ASUB(exp=arr, sub={idx}) then + let &preExp = buffer "" + let arr1 = daeExp(arr, context, &preExp, &varDecls, &auxFunction) + let idx1 = daeExp(idx, context, &preExp, &varDecls, &auxFunction) + let val1 = daeExp(val, context, &preExp, &varDecls, &auxFunction) + << + <%preExp%> + arrayUpdate(<%arr1%>,<%idx1%>,<%val1%>); + >>) + // Modelica Array + else + let &preExp = buffer "" + let varPart = daeExpAsub(exp1, context, &preExp, &varDecls, &auxFunction) + let expPart = daeExp(val, context, &preExp, &varDecls, &auxFunction) + << + <%preExp%> + <%varPart%> = <%expPart%>; + >> + ) + case STMT_ASSIGN(__) then + let &preExp = buffer "" + let expPart1 = daeExp(exp1, context, &preExp, &varDecls, &auxFunction) + let expPart2 = daeExp(exp, context, &preExp, &varDecls, &auxFunction) + << + <%preExp%> + <%expPart1%> = <%expPart2%>; + >> +end algStmtAssign; + + +template algStmtAssignArr(DAE.Statement stmt, Context context, + Text &varDecls, Text &auxFunction) + "Generates an array assigment algorithm statement." +::= +match stmt +case STMT_ASSIGN_ARR(lhs=lhsexp as CREF(componentRef=cr), exp=RANGE(__), type_=t) then + fillArrayFromRange(t,exp,cr,context,&varDecls,&auxFunction) + +case STMT_ASSIGN_ARR(lhs=lhsexp as CREF(componentRef=cr), exp=e, type_=t) then + let &preExp = buffer "" + let expPart = daeExp(e, context, &preExp, &varDecls, &auxFunction) + let assign = algStmtAssignArrWithRhsExpStr(lhsexp, expPart, context, &preExp, &varDecls, &auxFunction) + << + <%preExp%> + <%assign%> + >> +end algStmtAssignArr; + +template algStmtAssignWithRhsExpStr(DAE.Exp lhsexp, Text &rhsExpStr, Context context, + Text &preExp, Text &postExp, Text &varDecls, Text &auxFunction) + "Generates an array assigment algorithm statement." +::= +match lhsexp + case CREF(componentRef=WILD(__)) then + '<%rhsExpStr%>;' + case CREF(componentRef=cr, ty = T_ARRAY(ty=basety, dims=dims)) then + algStmtAssignArrWithRhsExpStr(lhsexp, rhsExpStr, context, &preExp, &varDecls, &auxFunction) + case CREF(componentRef = cr, ty=DAE.T_COMPLEX(complexClassType=RECORD(__))) then + algStmtAssignRecordWithRhsExpStr(lhsexp, rhsExpStr, context, &preExp, &varDecls, &auxFunction) + case CREF(__) then + let lhsStr = daeExpCrefLhs(lhsexp, context, &preExp, &varDecls, &auxFunction) + '<%lhsStr%> = <%rhsExpStr%>;' + + /*This CALL on left hand side case shouldn't have been created by the compiler. It only comes because of alias eliminations. On top of that + at least it should have been a record_constractor not a normal call. sigh. */ + case CALL(path=path,expLst=expLst,attr=CALL_ATTR(ty=ty as T_COMPLEX(varLst = varLst, complexClassType=RECORD(__)))) then + let tmp = tempDecl(expTypeModelica(ty),&varDecls) + /*TODO handle array record memebers. see algStmtAssign*/ + << + <%preExp%> + <%tmp%> = <%rhsExpStr%>; + <% varLst |> var as TYPES_VAR(__) hasindex i1 fromindex 1 => + let re = daeExp(listGet(expLst,i1), context, &preExp, &varDecls, &auxFunction) + '<%re%> = <%tmp%>._<%var.name%>;' + ; separator="\n" + %> + >> + /*TODO check*/ + case ARRAY(__) then + algStmtAssignArrWithRhsExpStr(lhsexp, rhsExpStr, context, &preExp, &varDecls, &auxFunction) + else + error(sourceInfo(), 'algStmtAssignWithRhsExpStr: Unhandled lhs expression. <%ExpressionDump.printExpStr(lhsexp)%>') +end algStmtAssignWithRhsExpStr; + +template algStmtAssignRecordWithRhsExpStr(DAE.Exp lhsexp, Text &rhsExpStr, Context context, + Text &preExp, Text &varDecls, Text &auxFunction) + "Generates an array assigment algorithm statement." +::= +match lhsexp + case CREF(componentRef = cr, ty=DAE.T_COMPLEX(varLst = varLst, complexClassType=RECORD(__))) then + let lhsStr = contextCref(cr, context, &auxFunction) + let tmp = tempDecl(expTypeModelica(ty),&varDecls) + /*TODO handle array record memebers. see algStmtAssign*/ + << + <%preExp%> + <%tmp%> = <%rhsExpStr%>; + <% varLst |> var as TYPES_VAR(__) hasindex i1 fromindex 0 => + '<%lhsStr%><%match context case FUNCTION_CONTEXT(__) then "._" else "$P"%><%var.name%> = <%tmp%>._<%var.name%>;' + ; separator="\n" + %> + >> +end algStmtAssignRecordWithRhsExpStr; + +template algStmtAssignArrWithRhsExpStr(DAE.Exp lhsexp, Text &rhsExpStr, Context context, + Text &preExp, Text &varDecls, Text &auxFunction) + "Generates an array assigment algorithm statement." +::= +match lhsexp + case CREF(componentRef=cr, ty = T_ARRAY(ty=basety, dims=dims)) then + let type = expTypeArray(ty) + if crefSubIsScalar(cr) then + let lhsStr = daeExpCrefLhs(lhsexp, context, &preExp, &varDecls, &auxFunction) + 'copy_<%type%>_data(<%rhsExpStr%>, &<%lhsStr%>);' + else + indexedAssign(lhsexp, rhsExpStr, context, &preExp, &varDecls, &auxFunction) +end algStmtAssignArrWithRhsExpStr; + +template fillArrayFromRange(DAE.Type ty, Exp exp, DAE.ComponentRef cr, Context context, + Text &varDecls, Text &auxFunction) + "Generates an array assigment to RANGE expressions. (Fills an array from range expresion)" +::= +match exp +case RANGE(__) then + let &preExp = buffer "" + let cref = contextArrayCref(cr, context) + let ty_str = expTypeArray(ty) + let start_exp = daeExp(start, context, &preExp, &varDecls, &auxFunction) + let stop_exp = daeExp(stop, context, &preExp, &varDecls, &auxFunction) + let step_exp = match step case SOME(stepExp) then daeExp(stepExp, context, &preExp, &varDecls, &auxFunction) else "1" + << + <%preExp%> + fill_<%ty_str%>_from_range(&<%cref%>, <%start_exp%>, <%step_exp%>, <%stop_exp%>);<%\n%> + >> + +end fillArrayFromRange; + +template indexedAssign(DAE.Exp lhs, String exp, Context context, + Text &preExp, Text &varDecls, Text &auxFunction) +::= + match lhs + case ecr as CREF(componentRef=cr, ty=T_ARRAY(ty=aty, dims=dims)) then + let arrayType = expTypeArray(ty) + let ispec = daeExpCrefIndexSpec(crefSubs(cr), context, &preExp, &varDecls, &auxFunction) + match context + case FUNCTION_CONTEXT(__) then + let cref = contextArrayCref(cr, context) + 'indexed_assign_<%arrayType%>(<%exp%>, &<%cref%>, &<%ispec%>);' + case PARALLEL_FUNCTION_CONTEXT(__) then + let cref = contextArrayCref(cr, context) + 'indexed_assign_<%arrayType%>(<%exp%>, &<%cref%>, &<%ispec%>);' + else + let type = expTypeShort(aty) + let wrapperArray = tempDecl(arrayType, &varDecls) + let dimsLenStr = listLength(crefDims(cr)) + let dimsValuesStr = (crefDims(cr) |> dim => dimension(dim) ;separator=", ") + let arrName = contextCref(crefStripSubs(cr), context,&auxFunction) + << + <%type%>_array_create(&<%wrapperArray%>, (modelica_<%type%>*)&<%arrName%>, <%dimsLenStr%>, <%dimsValuesStr%>);<%\n%> + indexed_assign_<%arrayType%>(<%exp%>, &<%wrapperArray%>, &<%ispec%>); + >> + else + error(sourceInfo(), 'indexedAssign simulationContext failed') +end indexedAssign; + +template copyArrayData(DAE.Type ty, String exp, DAE.ComponentRef cr, Context context, + Text &preExp, Text &varDecls, Text &auxFunction) +::= + let type = expTypeArray(ty) + let cref = contextArrayCref(cr, context) + match context + case FUNCTION_CONTEXT(__) then + 'copy_<%type%><%if dimensionsKnown(ty) then "_data" /* else we make allocate and copy data */%>(<%exp%>, &<%cref%>);' + case PARALLEL_FUNCTION_CONTEXT(__) then + 'copy_<%type%>_data(<%exp%>, &<%cref%>);' + else + 'copy_<%type%>_data_mem(<%exp%>, &<%cref%>);' +end copyArrayData; + +template algStmtTupleAssign(DAE.Statement stmt, Context context, Text &varDecls, Text &auxFunction) + "Generates a tuple assigment algorithm statement." +::= +match stmt + case STMT_TUPLE_ASSIGN(expExpLst={_}) then + error(sourceInfo(), "A tuple assignment of only one variable is a regular assignment") + + case STMT_TUPLE_ASSIGN(expExpLst = firstexp::_, exp = CALL(attr=CALL_ATTR(ty=T_TUPLE(types=ntys)))) then + let &preExp = buffer "" + let &postExp = buffer "" + + let lhsCrefs = (List.rest(expExpLst) |> e => " ," + tupleReturnVariableUpdates(e, context, varDecls, preExp, postExp, &auxFunction)) + // The tuple expressions might take fewer variables than the number of outputs. No worries. + let lhsCrefs2 = lhsCrefs + List.fill(", NULL", intMax(0,intSub(listLength(ntys),listLength(expExpLst)))) + + let call = daeExpCallTuple(exp, lhsCrefs2, context, &preExp, &varDecls, &auxFunction) + let callassign = algStmtAssignWithRhsExpStr(firstexp, call, context, &preExp, &postExp, &varDecls, &auxFunction) + << + /* tuple assignment <%expExpLst |> e => Util.escapeModelicaStringToCString(printExpStr(e)) ; separator=", "%>*/ + <%preExp%> + <%callassign%> + <%postExp%> + >> + + case STMT_TUPLE_ASSIGN(exp=MATCHEXPRESSION(__)) then + let &preExp = buffer "" + let prefix = 'tmp<%System.tmpTick()%>' + // get the current index of tmpMeta and reserve N=listLength(inputs) values in it! + let startIndexOutputs = '<%System.tmpTickIndexReserve(1, listLength(expExpLst))%>' + let _ = daeExpMatch2(exp, expExpLst, prefix, startIndexOutputs, context, &preExp, &varDecls, &auxFunction) + let lhsCrefs = (expExpLst |> crefexp as CREF(componentRef = cr) hasindex i0 fromindex 1 => + let rhsStr = getTempDeclMatchOutputName(expExpLst, prefix, startIndexOutputs, i0) + let lhsStr = contextCref(cr, context, &auxFunction) + << + <%lhsStr%> = <%rhsStr%>; + >> + ;separator="\n"; empty) + << + <%expExpLst |> crefexp hasindex i0 => + let typ = expTypeFromExpModelica(crefexp) + let decl = tempDeclMatchOutput(typ, prefix, startIndexOutputs, i0, &varDecls) + "" + ;separator="\n";empty%> + <%preExp%> + <%lhsCrefs%> + >> + else error(sourceInfo(), 'algStmtTupleAssign failed') + +end algStmtTupleAssign; + +template tupleReturnVariableUpdates(Exp inExp, Context context, Text &varDecls, Text &preExp, Text &varCopy, Text &auxFunction) + "Generates code for updating variables returned from fuctions that return tuples. + Generates copies depending on what kind of variable is returned." +::= + match inExp + case CREF(componentRef=WILD(__)) then + 'NULL' + case CREF(componentRef = cr, ty=DAE.T_COMPLEX(varLst = varLst, complexClassType=RECORD(__))) then + let rhsStr = tempDecl(expTypeArrayIf(ty), &varDecls) + let lhsStr = contextCref(cr, context, &auxFunction) + let &varCopy += + /*TODO handle array record memebers. see algStmtAssign*/ + << + <%preExp%> + <% varLst |> var as TYPES_VAR(__) hasindex i1 fromindex 0 => + '<%lhsStr%><%match context case FUNCTION_CONTEXT(__) then "._" else "$P"%><%var.name%> = <%rhsStr%>._<%var.name%>;' + ; separator="\n" + %> + >> /*varCopy end*/ + '&<%rhsStr%>' + + /*This CALL case shouldn't have been created by the compiler. It only comes because of alias eliminations. On top of that + at least it should have been a record_constractor not a normal call. sigh. */ + case CALL(path=path,expLst=expLst,attr=CALL_ATTR(ty=ty as T_COMPLEX(varLst = varLst, complexClassType=RECORD(__)))) then + let &preExp = buffer "" + let rhsStr = tempDecl(expTypeArrayIf(ty), &varDecls) + let tmp = tempDecl(expTypeModelica(ty),&varDecls) + let &varCopy += + /*TODO handle array record memebers. see algStmtAssign*/ + << + <%preExp%> + <% varLst |> var as TYPES_VAR(__) hasindex i1 fromindex 1 => + let re = daeExp(listGet(expLst,i1), context, &preExp, &varDecls, &auxFunction) + '<%re%> = <%rhsStr%>._<%var.name%>;' + ; separator="\n" + %> + >> /*varCopy end*/ + '&<%rhsStr%>' + case CREF(__) then + let res = daeExpCrefLhs(inExp, context, &preExp, &varDecls, &auxFunction) + if isArrayWithUnknownDimension(ty) + then + let &preExp += '<%res%>.dim_size = NULL;<%\n%>' + '&<%res%>' + else '&<%res%>' + else + error(sourceInfo(), 'tupleReturnVariableUpdates: Unhandled expression. <%ExpressionDump.printExpStr(inExp)%>') +end tupleReturnVariableUpdates; + +template algStmtIf(DAE.Statement stmt, Context context, Text &varDecls, Text &auxFunction) + "Generates an if algorithm statement." +::= +match stmt +case STMT_IF(__) then + let &preExp = buffer "" + let condExp = daeExp(exp, context, &preExp, &varDecls, &auxFunction) + << + <%preExp%> + if(<%condExp%>) + { + <%statementLst |> stmt => algStatement(stmt, context, &varDecls, &auxFunction) ;separator="\n"%> + } + <%elseExpr(else_, context, &varDecls, &auxFunction)%> + >> +end algStmtIf; + +template algStmtParForBody(DAE.Statement stmt, Context context, Text &varDecls, Text &auxFunction) + "Generates a for algorithm statement." +::= + match stmt + case s as STMT_PARFOR(range=rng as RANGE(__)) then + algStmtParForRangeBody(s, context, &varDecls, &auxFunction) + case s as STMT_PARFOR(__) then + algStmtForGeneric(s, context, &varDecls, &auxFunction) +end algStmtParForBody; + +template algStmtParForRangeBody(DAE.Statement stmt, Context context, Text &varDecls, Text &auxFunction) + "Generates a for algorithm statement where range is RANGE." +::= +match stmt +case STMT_PARFOR(range=rng as RANGE(__)) then + let iterName = contextIteratorName(iter, context) + let identType = expType(type_, iterIsArray) + let identTypeShort = expTypeShort(type_) + + let parforKernelName = 'parfor_<%System.tmpTickIndex(20 /* parfor */)%>' + + let &loopVarDecls = buffer "" + let body = (statementLst |> stmt => algStatement(stmt, context, &loopVarDecls, &auxFunction) + ;separator="\n") + + // Reconstruct array arguments to structures in the kernels + let &reconstrucedArrays = buffer "" + let _ = (loopPrlVars |> var => + reconstructKernelArraysFromLooptupleVars(var, &reconstrucedArrays) + ) + + let argStr = (loopPrlVars |> var => '<%parFunArgDefinitionFromLooptupleVar(var)%>' ;separator=", \n") + + << + + __kernel void <%parforKernelName%>( + modelica_integer loop_start, + modelica_integer loop_step, + modelica_integer loop_end, + <%argStr%>) + { + /* algStmtParForRangeBody : Thread managment for parfor loops */ + modelica_integer inner_start = (get_global_id(0) * loop_step) + (loop_start); + modelica_integer stride = get_global_size(0) * loop_step; + + for(modelica_integer <%iterName%> = (modelica_integer) inner_start; in_range_integer(<%iterName%>, loop_start, loop_end); <%iterName%> += stride) + { + /* algStmtParForRangeBody : Reconstruct Arrays */ + <%reconstrucedArrays%> + + /* algStmtParForRangeBody : locals */ + <%loopVarDecls%> + + <%body%> + } + } + >> +end algStmtParForRangeBody; + +template algStmtParForInterface(DAE.Statement stmt, Context context, Text &varDecls, Text &auxFunction) + "Generates a for algorithm statement." +::= + match stmt + case s as STMT_PARFOR(range=rng as RANGE(__)) then + algStmtParForRangeInterface(s, context, &varDecls, &auxFunction) + case s as STMT_PARFOR(__) then + algStmtForGeneric(s, context, &varDecls, &auxFunction) +end algStmtParForInterface; + +template algStmtParForRangeInterface(DAE.Statement stmt, Context context, Text &varDecls, Text &auxFunction) + "Generates a for algorithm statement where range is RANGE." +::= +match stmt +case STMT_PARFOR(range=rng as RANGE(__)) then + let identType = expType(type_, iterIsArray) + let identTypeShort = expTypeShort(type_) + let stmtStr = (statementLst |> stmt => algStatement(stmt, context, &varDecls, &auxFunction) + ;separator="\n") + algStmtParForRangeInterface_impl(rng, iter, identType, identTypeShort, loopPrlVars, stmtStr, context, &varDecls, &auxFunction) +end algStmtParForRangeInterface; + +template algStmtParForRangeInterface_impl(Exp range, Ident iterator, String type, String shortType, list> loopPrlVars, Text body, Context context, Text &varDecls, Text &auxFunction) + "The implementation of algStmtParForRangeInterface." +::= +match range +case RANGE(__) then + let iterName = contextIteratorName(iterator, context) + let startVar = tempDecl(type, &varDecls) + let stepVar = tempDecl(type, &varDecls) + let stopVar = tempDecl(type, &varDecls) + let &preExp = buffer "" + let startValue = daeExp(start, context, &preExp, &varDecls, &auxFunction) + let stepValue = match step case SOME(eo) then + daeExp(eo, context, &preExp, &varDecls, &auxFunction) + else + "(modelica_integer)1" + let stopValue = daeExp(stop, context, &preExp, &varDecls, &auxFunction) + + let cl_kernelVar = tempDecl("cl_kernel", &varDecls) + + let parforKernelName = 'parfor_<%System.tmpTickIndex(20 /* parfor */)%>' + + let kerArgNr = '<%parforKernelName%>_arg_nr' + + let &kernelArgSets = buffer "" + let _ = (loopPrlVars |> varTuple => + setKernelArgFormTupleLoopVars_ith(varTuple, &cl_kernelVar, &kerArgNr, &kernelArgSets, context) + ) + + << + <%preExp%> + <%startVar%> = <%startValue%>; <%stepVar%> = <%stepValue%>; <%stopVar%> = <%stopValue%>; + <%cl_kernelVar%> = ocl_create_kernel(omc_ocl_program, "<%parforKernelName%>"); + int <%kerArgNr%> = 0; + + ocl_set_kernel_arg(<%cl_kernelVar%>, <%kerArgNr%>, <%startVar%>); ++<%kerArgNr%>; <%\n%> + ocl_set_kernel_arg(<%cl_kernelVar%>, <%kerArgNr%>, <%stepVar%>); ++<%kerArgNr%>; <%\n%> + ocl_set_kernel_arg(<%cl_kernelVar%>, <%kerArgNr%>, <%stopVar%>); ++<%kerArgNr%>; <%\n%> + + <%kernelArgSets%> + + ocl_execute_kernel(<%cl_kernelVar%>); + clReleaseKernel(<%cl_kernelVar%>); + + + >> /* else we're looping over a zero-length range */ +end algStmtParForRangeInterface_impl; + + +template algStmtFor(DAE.Statement stmt, Context context, Text &varDecls, Text &auxFunction) + "Generates a for algorithm statement." +::= + match stmt + case s as STMT_FOR(range=rng as RANGE(__)) then + algStmtForRange(s, context, &varDecls, &auxFunction) + case s as STMT_FOR(__) then + algStmtForGeneric(s, context, &varDecls, &auxFunction) +end algStmtFor; + +template algStmtForRange(DAE.Statement stmt, Context context, Text &varDecls, Text &auxFunction) + "Generates a for algorithm statement where range is RANGE." +::= +match stmt +case STMT_FOR(range=rng as RANGE(__)) then + let identType = expType(type_, iterIsArray) + let identTypeShort = expTypeShort(type_) + let stmtStr = (statementLst |> stmt => algStatement(stmt, context, &varDecls, &auxFunction) + ;separator="\n") + algStmtForRange_impl(rng, iter, identType, identTypeShort, stmtStr, context, &varDecls, &auxFunction) +end algStmtForRange; + +template algStmtForRange_impl(Exp range, Ident iterator, String type, String shortType, Text body, Context context, Text &varDecls, Text &auxFunction) + "The implementation of algStmtForRange, which is also used by daeExpReduction." +::= +match range +case RANGE(__) then + let iterName = contextIteratorName(iterator, context) + let startVar = tempDecl(type, &varDecls) + let stepVar = tempDecl(type, &varDecls) + let stopVar = tempDecl(type, &varDecls) + let &preExp = buffer "" + let startValue = daeExp(start, context, &preExp, &varDecls, &auxFunction) + let stepValue = match step case SOME(eo) then + daeExp(eo, context, &preExp, &varDecls, &auxFunction) + else "1" + let stopValue = daeExp(stop, context, &preExp, &varDecls, &auxFunction) + let eqnsindx = match context case FUNCTION_CONTEXT(__) then '' else 'equationIndexes, ' + let AddionalFuncName = match context case FUNCTION_CONTEXT(__) then '' else '_withEquationIndexes' + << + <%preExp%> + <%startVar%> = <%startValue%>; <%stepVar%> = <%stepValue%>; <%stopVar%> = <%stopValue%>; + if(!<%stepVar%>) + { + FILE_INFO info = omc_dummyFileInfo; + omc_assert<%AddionalFuncName%>(threadData, info, <%eqnsindx%>"assertion range step != 0 failed"); + } + else if(!(((<%stepVar%> > 0) && (<%startVar%> > <%stopVar%>)) || ((<%stepVar%> < 0) && (<%startVar%> < <%stopVar%>)))) + { + <%type%> <%iterName%>; + for(<%iterName%> = <%startValue%>; in_range_<%shortType%>(<%iterName%>, <%startVar%>, <%stopVar%>); <%iterName%> += <%stepVar%>) + { + <%body%> + } + } + >> /* else we're looping over a zero-length range */ +end algStmtForRange_impl; + +template algStmtForGeneric(DAE.Statement stmt, Context context, Text &varDecls, Text &auxFunction) + "Generates a for algorithm statement where range is not RANGE." +::= +match stmt +case STMT_FOR(__) then + let iterType = match expType(type_, iterIsArray) + case "modelica_string" then "modelica_metatype" + case s then s + let arrayType = expTypeArray(type_) + let tvar = match iterType + case "modelica_metatype" + then tempDecl("modelica_metatype", &varDecls) + else tempDecl("int", &varDecls) + let stmtStr = (statementLst |> stmt => + algStatement(stmt, context, &varDecls, &auxFunction) ;separator="\n") + algStmtForGeneric_impl(range, iter, iterType, arrayType, iterIsArray, stmtStr, tvar, context, &varDecls, &auxFunction) +end algStmtForGeneric; + +template algStmtForGeneric_impl(Exp exp, Ident iterator, String type, + String arrayType, Boolean iterIsArray, Text &body, Text tvar, Context context, Text &varDecls, Text &auxFunction) + "The implementation of algStmtForGeneric, which is also used by daeExpReduction." +::= + let iterName = contextIteratorName(iterator, context) + let ivar = tempDecl(type, &varDecls) + let &preExp = buffer "" + let evar = daeExp(exp, context, &preExp, &varDecls, &auxFunction) + << + <%preExp%> + { + <%type%> <%iterName%>; + <% match type + case "modelica_metatype" then + (match typeof(exp) + case T_METATYPE(ty=T_METAARRAY(__)) then + let tmp = tempDecl("modelica_integer",&varDecls) + let len = tempDecl("modelica_integer",&varDecls) + << + for (<%tvar%> = <%evar%>, <%len%> = arrayLength(<%tvar%>), <%tmp%> = 1; <%tmp%> <= <%len%>; <%tmp%>++) + { + <%iterName%> = arrayGet(<%tvar%>,<%tmp%>); + <%body%> + } + >> + case T_METATYPE(ty=T_METALIST(__)) then + << + for (<%tvar%> = <%evar%>; !listEmpty(<%tvar%>); <%tvar%>=listRest(<%tvar%>)) + { + <%iterName%> = listHead(<%tvar%>); + <%body%> + } + >> + case ty then error(sourceInfo(), '<%unparseType(ty)%> iterator is not supported')) + else + let stmtStuff = if iterIsArray then + 'simple_index_alloc_<%type%>1(&<%evar%>, <%tvar%>, &<%ivar%>);' + else + '<%iterName%> = *(<%arrayType%>_element_addr1(&<%evar%>, 1, <%tvar%>));' + << + for(<%tvar%> = 1; <%tvar%> <= size_of_dimension_base_array(<%evar%>, 1); ++<%tvar%>) + { + <%stmtStuff%> + <%body%> + } + >> + %> + } + >> +end algStmtForGeneric_impl; + +template algStmtWhile(DAE.Statement stmt, Context context, Text &varDecls, Text &auxFunction) + "Generates a while algorithm statement." +::= +match stmt +case STMT_WHILE(__) then + let &preExp = buffer "" + let var = daeExp(exp, context, &preExp, &varDecls, &auxFunction) + << + while(1) + { + <%preExp%> + if(!<%var%>) break; + <%statementLst |> stmt => algStatement(stmt, context, &varDecls, &auxFunction) ;separator="\n"%> + } + >> +end algStmtWhile; + + +template algStmtAssert(DAE.Statement stmt, Context context, Text &varDecls, Text &auxFunction) + "Generates an assert algorithm statement." +::= +match stmt +case STMT_ASSERT(source=SOURCE(info=info)) then + assertCommon(cond, List.fill(msg,1), level, context, &varDecls, &auxFunction, info) +end algStmtAssert; + +template algStmtTerminate(DAE.Statement stmt, Context context, Text &varDecls, Text &auxFunction) + "Generates an assert algorithm statement." +::= +match stmt +case STMT_TERMINATE(__) then + let &preExp = buffer "" + let msgVar = daeExp(msg, context, &preExp, &varDecls, &auxFunction) + << + <%preExp%> + FILE_INFO info = {<%infoArgs(getElementSourceFileInfo(source))%>}; + omc_terminate(info, MMC_STRINGDATA(<%msgVar%>)); + >> +end algStmtTerminate; + +template algStmtFailure(DAE.Statement stmt, Context context, Text &varDecls, Text &auxFunction) + "Generates a failure() algorithm statement." +::= +match stmt +case STMT_FAILURE(__) then + let tmp = tempDecl("modelica_boolean", &varDecls) + let () = codegenPushTryThrowIndex(System.tmpTick()) + let goto = 'goto_<%codegenPeekTryThrowIndex()%>' + let stmtBody = (body |> stmt => + algStatement(stmt, context, &varDecls, &auxFunction) + ;separator="\n") + << + <%tmp%> = 0; /* begin failure */ + MMC_TRY_INTERNAL(mmc_jumper) + <%stmtBody%> + <%tmp%> = 1; + goto <%goto%>; + <%goto%>:; + MMC_CATCH_INTERNAL(mmc_jumper)<%let()=codegenPopTryThrowIndex() ""%> + if (<%tmp%>) {<%generateThrow()%>;} /* end failure */ + >> +end algStmtFailure; + +template algStmtNoretcall(DAE.Statement stmt, Context context, Text &varDecls, Text &auxFunction) + "Generates a no return call algorithm statement." +::= +match stmt +case STMT_NORETCALL(exp=DAE.MATCHEXPRESSION(__)) then + let &preExp = buffer "" + let expPart = daeExpMatch2(exp,listExpLength1,"","",context,&preExp,&varDecls, &auxFunction) + << + <%preExp%> + <%expPart%>; + >> +case STMT_NORETCALL(__) then + let &preExp = buffer "" + let expPart = daeExp(exp, context, &preExp, &varDecls, &auxFunction) + << + <%preExp%> + <% if isCIdentifier(expPart) then "" else '<%expPart%>;' %> + >> +end algStmtNoretcall; + +template algStmtWhen(DAE.Statement when, Context context, Text &varDecls, Text &auxFunction) + "Generates a when algorithm statement." +::= + match context + case SIMULATION_CONTEXT(__) then + match when + case STMT_WHEN(__) then + let helpIf = (conditions |> e => ' || (<%cref(e)%> && !$P$PRE<%cref(e)%> /* edge */)') + let statements = (statementLst |> stmt => + algStatement(stmt, context, &varDecls, &auxFunction) + ;separator="\n") + let initial_statements = match initialCall + case true then '<%statements%>' + else '; /* nothing to do */' + let else = algStatementWhenElse(elseWhen, &varDecls, &auxFunction) + << + if(data->simulationInfo.discreteCall == 1) + { + if(initial()) + { + <%initial_statements%> + } + else if(0<%helpIf%>) + { + <%statements%> + } + <%else%> + } + >> + end match + end match +end algStmtWhen; + + +template algStatementWhenElse(Option stmt, Text &varDecls, Text &auxFunction) + "Helper to algStmtWhen." +::= +match stmt +case SOME(when as STMT_WHEN(__)) then + let statements = (when.statementLst |> stmt => + algStatement(stmt, contextSimulationDiscrete, &varDecls, &auxFunction) + ;separator="\n") + let else = algStatementWhenElse(when.elseWhen, &varDecls, &auxFunction) + let elseCondStr = (when.conditions |> e => ' || (<%cref(e)%> && !$P$PRE<%cref(e)%> /* edge */)') + << + else if(0<%elseCondStr%>) + { + <%statements%> + } + <%else%> + >> +end algStatementWhenElse; + +template algStmtReinit(DAE.Statement stmt, Context context, Text &varDecls, Text &auxFunction) + "Generates an assigment algorithm statement." +::= + match stmt + case STMT_REINIT(__) then + let &preExp = buffer "" + let expPart1 = daeExp(var, context, &preExp, &varDecls, &auxFunction) + let expPart2 = daeExp(value, context, &preExp, &varDecls, &auxFunction) + << + <%preExp%> + <%expPart1%> = <%expPart2%>; + infoStreamPrint(LOG_EVENTS, 0, "reinit <%expPart1%> = %f", <%expPart1%>); + data->simulationInfo.needToIterate = 1; + >> +end algStmtReinit; + +template elseExpr(DAE.Else else_, Context context, Text &varDecls, Text &auxFunction) + "Helper to algStmtIf." + ::= + match else_ + case NOELSE(__) then + "" + case ELSEIF(__) then + let &preExp = buffer "" + let condExp = daeExp(exp, context, &preExp, &varDecls, &auxFunction) + << + else + { + <%preExp%> + if(<%condExp%>) + { + <%statementLst |> stmt => + algStatement(stmt, context, &varDecls, &auxFunction) + ;separator="\n"%> + } + <%elseExpr(else_, context, &varDecls, &auxFunction)%> + } + >> + case ELSE(__) then + + << + else + { + <%statementLst |> stmt => + algStatement(stmt, context, &varDecls, &auxFunction) + ;separator="\n"%> + } + >> +end elseExpr; + +template functionsParModelicaKernelsFile(String filePrefix, Option mainFunction, list functions) + "Generates the content of the C file for functions in the simulation case." +::= + + /* Reset the parfor loop id counter to 0*/ + let()= System.tmpTickResetIndex(0,20) /* parfor index */ + + << + #include + + // ParModelica Parallel Function headers. + <%functionHeadersParModelica(filePrefix, functions)%> + + // Headers finish here. + + <%match mainFunction case SOME(fn) then functionBodyParModelica(fn,true)%> + <%functionBodiesParModelica(functions)%> + + + >> + +end functionsParModelicaKernelsFile; + +/* public */ template recordsFile(String filePrefix, list recordDecls) + "Generates the content of the C file for functions in the simulation case. + used in Compiler/Template/CodegenFMU.tpl" +::= + << + /* Additional record code for <%filePrefix%> generated by the OpenModelica Compiler <%getVersionNr()%>. */ + + #include "meta/meta_modelica.h" + + #ifdef __cplusplus + extern "C" { + #endif + + <%recordDecls |> rd => recordDeclaration(rd) ;separator="\n\n"%> + + #ifdef __cplusplus + } + #endif + + >> + /* adpro: leave a newline at the end of file to get rid of warnings! */ +end recordsFile; + +template literalExpConst(Exp lit, Integer litindex, Text &preLit) "These should all be declared static X const" +::= + let name = '_OMC_LIT<%litindex%>' + let tmp = '_OMC_LIT_STRUCT<%litindex%>' + let meta = 'static modelica_metatype const <%name%>' + + match lit + case SCONST(__) then + let escstr = Util.escapeModelicaStringToCString(string) + /* TODO: Change this when OMC takes constant input arguments (so we cannot write to them) + The cost of not doing this properly is small (<257 bytes of constants) + match unescapedStringLength(escstr) + case 0 then '#define <%name%> mmc_emptystring' + case 1 then '#define <%name%> mmc_strings_len1["<%escstr%>"[0]]' + else */ + << + #define <%name%>_data "<%escstr%>" + static const MMC_DEFSTRINGLIT(<%tmp%>,<%unescapedStringLength(escstr)%>,<%name%>_data); + #define <%name%> MMC_REFSTRINGLIT(<%tmp%>) + >> + case lit as MATRIX(ty=ty as T_ARRAY(__)) + case lit as ARRAY(ty=ty as T_ARRAY(__)) then + let ndim = listLength(getDimensionSizes(ty)) + let sty = expTypeShort(ty) + let dims = (getDimensionSizes(ty) |> dim => dim ;separator=", ") + let data = flattenArrayExpToList(lit) |> exp => literalExpConstArrayVal(exp) ; separator=", " + << + static _index_t <%name%>_dims[<%ndim%>] = {<%dims%>}; + <% match data case "" then + << + static base_array_t const <%name%> = { + <%ndim%>, <%name%>_dims, (void*) 0 + }; + >> + else + << + static const modelica_<%sty%> <%name%>_data[] = {<%data%>}; + static <%sty%>_array const <%name%> = { + <%ndim%>, <%name%>_dims, (void*) <%name%>_data + }; + >> + %> + >> + case BOX(exp=exp as ICONST(__)) then + << + <%meta%> = MMC_IMMEDIATE(MMC_TAGFIXNUM(<%exp.integer%>)); + >> + case BOX(exp=exp as BCONST(__)) then + << + <%meta%> = MMC_IMMEDIATE(MMC_TAGFIXNUM(<%if exp.bool then 1 else 0%>)); + >> + case BOX(exp=exp as RCONST(__)) then + /* We need to use #define's to be C-compliant. Yea, total crap :) */ + << + static const MMC_DEFREALLIT(<%tmp%>,<%exp.real%>); + #define <%name%> MMC_REFREALLIT(<%tmp%>) + >> + case CONS(__) then + /* We need to use #define's to be C-compliant. Yea, total crap :) */ + << + static const MMC_DEFSTRUCTLIT(<%tmp%>,2,1) {<%literalExpConstBoxedVal(car,litindex + "_car", &preLit)%>,<%literalExpConstBoxedVal(cdr, litindex + "_cdr", &preLit)%>}}; + #define <%name%> MMC_REFSTRUCTLIT(<%tmp%>) + >> + case LIST(__) then + let x = listReverse(valList) |> v hasindex i fromindex 1 => + /* We need to use #define's to be C-compliant. Yea, total crap :) */ + 'static const MMC_DEFSTRUCTLIT(<%tmp + "_cons_" + i%>,2,1) {<%literalExpConstBoxedVal(v,tmp + "_elt_" + i, &preLit)%>,MMC_REFSTRUCTLIT(<% match i case 1 then "mmc_nil" else (tmp + "_cons_" + intSub(i,1))%>)}};<%\n%>' + << + <%x%> + #define <%name%> MMC_REFSTRUCTLIT(<%tmp%>_cons_<%listLength(valList)%>) + >> + case META_TUPLE(__) then + /* We need to use #define's to be C-compliant. Yea, total crap :) */ + << + static const MMC_DEFSTRUCTLIT(<%tmp%>,<%listLength(listExp)%>,0) {<%listExp |> exp hasindex i0 => literalExpConstBoxedVal(exp,litindex+"_"+i0, &preLit); separator=","%>}}; + #define <%name%> MMC_REFSTRUCTLIT(<%tmp%>) + >> + case META_OPTION(exp=SOME(exp)) then + /* We need to use #define's to be C-compliant. Yea, total crap :) */ + << + static const MMC_DEFSTRUCTLIT(<%tmp%>,1,1) {<%literalExpConstBoxedVal(exp,litindex+"_1", &preLit)%>}}; + #define <%name%> MMC_REFSTRUCTLIT(<%tmp%>) + >> + case METARECORDCALL(__) then + /* We need to use #define's to be C-compliant. Yea, total crap :) */ + let newIndex = getValueCtor(index) + << + static const MMC_DEFSTRUCTLIT(<%tmp%>,<%intAdd(1,listLength(args))%>,<%newIndex%>) {&<%underscorePath(path)%>__desc,<%args |> exp hasindex i0 => literalExpConstBoxedVal(exp,litindex+"_"+i0, &preLit); separator=","%>}}; + #define <%name%> MMC_REFSTRUCTLIT(<%tmp%>) + >> + else error(sourceInfo(), 'literalExpConst failed: <%printExpStr(lit)%>') +end literalExpConst; + +template literalExpConstBoxedVal(Exp lit, Text index, Text &preLit) +::= + let name = '_OMC_LIT<%index%>' + let tmp = '_OMC_LIT_STRUCT<%index%>' + match lit + case ICONST(__) then 'MMC_IMMEDIATE(MMC_TAGFIXNUM(<%integer%>))' + case ENUM_LITERAL(__) then 'MMC_IMMEDIATE(MMC_TAGFIXNUM(<%index%>))' + case lit as BCONST(__) then 'MMC_IMMEDIATE(MMC_TAGFIXNUM(<%if lit.bool then 1 else 0%>))' + case lit as RCONST(__) then + let &preLit += + << + static const MMC_DEFREALLIT(<%tmp%>,<%lit.real%>); + #define <%name%> MMC_REFREALLIT(<%tmp%>)<%\n%> + >> + name + case LIST(valList={}) then + << + MMC_REFSTRUCTLIT(mmc_nil) + >> + case META_OPTION(exp=NONE()) then + << + MMC_REFSTRUCTLIT(mmc_none) + >> + case lit as BOX(__) then literalExpConstBoxedVal(lit.exp, index, &preLit) + case lit as SHARED_LITERAL(__) then '_OMC_LIT<%lit.index%>' + else error(sourceInfo(), 'literalExpConstBoxedVal failed: <%printExpStr(lit)%>') +end literalExpConstBoxedVal; + +template literalExpConstArrayVal(Exp lit) +::= + match lit + case ICONST(__) then integer + case lit as BCONST(__) then if lit.bool then 1 else 0 + case RCONST(__) then real + case ENUM_LITERAL(__) then index + case lit as SHARED_LITERAL(__) then '_OMC_LIT<%lit.index%>' + else error(sourceInfo(), 'literalExpConstArrayVal failed: <%printExpStr(lit)%>') +end literalExpConstArrayVal; + +template varType(Variable var) + "Generates type for a variable." +::= +match var +case var as VARIABLE(parallelism = NON_PARALLEL()) then + if instDims then + expTypeArray(var.ty) + else + expTypeArrayIf(var.ty) +case var as VARIABLE(parallelism = PARGLOBAL()) then + if instDims then + 'device_<%expTypeArray(var.ty)%>' + else + '<%expTypeArrayIf(var.ty)%>' +case var as VARIABLE(parallelism = PARLOCAL()) then + if instDims then + 'device_local_<%expTypeArray(var.ty)%>' + else + expTypeArrayIf(var.ty) +end varType; + +template varTypeBoxed(Variable var) +::= +match var +case VARIABLE(__) then 'modelica_metatype' +case FUNCTION_PTR(__) then 'modelica_fnptr' +end varTypeBoxed; + + + +template expTypeRW(DAE.Type type) + "Helper to writeOutVarRecordMembers." +::= + match type + case T_INTEGER(__) then "TYPE_DESC_INT" + case T_REAL(__) then "TYPE_DESC_REAL" + case T_STRING(__) then "TYPE_DESC_STRING" + case T_BOOL(__) then "TYPE_DESC_BOOL" + case T_ENUMERATION(__) then "TYPE_DESC_INT" + case T_ARRAY(__) then '<%expTypeRW(ty)%>_ARRAY' + case T_COMPLEX(complexClassType=RECORD(__)) + then "TYPE_DESC_RECORD" + case T_METATYPE(__) case T_METABOXED(__) then "TYPE_DESC_MMC" +end expTypeRW; + +template expTypeShort(DAE.Type type) + "Generate type helper." +::= + match type + case T_INTEGER(__) then "integer" + case T_REAL(__) then "real" + case T_STRING(__) then "string" + case T_BOOL(__) then "boolean" + case T_ENUMERATION(__) then "integer" + case T_SUBTYPE_BASIC(__) then expTypeShort(complexType) + case T_ARRAY(__) then expTypeShort(ty) + case T_COMPLEX(complexClassType=EXTERNAL_OBJ(__)) then "complex" + case T_COMPLEX(__) then '<%underscorePath(ClassInf.getStateName(complexClassType))%>' + case T_METAUNIONTYPE(__) + case T_METAARRAY(__) + case T_METALIST(__) + case T_METATUPLE(__) + case T_METAOPTION(__) + case T_METAPOLYMORPHIC(__) + case T_METATYPE(__) + case T_METABOXED(__) then "metatype" + case T_FUNCTION(__) + case T_FUNCTION_REFERENCE_FUNC(__) + case T_FUNCTION_REFERENCE_VAR(__) then "fnptr" + case T_UNKNOWN(__) then if acceptMetaModelicaGrammar() /* TODO: Don't do this to me! */ + then "complex /* assumming void* for unknown type! when +g=MetaModelica */ " + else "real /* assumming real for uknown type! */" + case T_ANYTYPE(__) then "complex" /* TODO: Don't do this to me! */ + else error(sourceInfo(),'expTypeShort: <%unparseType(type)%>') +end expTypeShort; + +template mmcTypeShort(DAE.Type type) +::= + match type + case T_INTEGER(__) then "integer" + case T_REAL(__) then "real" + case T_STRING(__) then "string" + case T_BOOL(__) then "integer" + case T_ENUMERATION(__) then "integer" + case T_ARRAY(__) then "array" + case T_METAUNIONTYPE(__) + case T_METATYPE(__) + case T_METALIST(__) + case T_METAARRAY(__) + case T_METAPOLYMORPHIC(__) + case T_METAOPTION(__) + case T_METATUPLE(__) + case T_METABOXED(__) then "metatype" + case T_FUNCTION_REFERENCE_VAR(__) then "fnptr" + + case T_COMPLEX(__) then "metatype" + else error(sourceInfo(), 'mmcTypeShort:ERROR <%unparseType(type)%>') +end mmcTypeShort; + + +template expType(DAE.Type ty, Boolean array) + "Generate type helper." +::= + match array + case true then expTypeArray(ty) + case false then expTypeModelica(ty) +end expType; + + +template expTypeModelica(DAE.Type ty) + "Generate type helper." +::= + expTypeFlag(ty, 2) +end expTypeModelica; + + +template expTypeArray(DAE.Type ty) + "Generate type helper." +::= + expTypeFlag(ty, 3) +end expTypeArray; + + +template expTypeArrayIf(DAE.Type ty) + "Generate type helper." +::= + expTypeFlag(ty, 4) +end expTypeArrayIf; + + +template expTypeFromExpShort(Exp exp) + "Generate type helper." +::= + expTypeFromExpFlag(exp, 1) +end expTypeFromExpShort; + + +template expTypeFromExpModelica(Exp exp) + "Generate type helper." +::= + expTypeFromExpFlag(exp, 2) +end expTypeFromExpModelica; + + +template expTypeFromExpArray(Exp exp) + "Generate type helper." +::= + expTypeFromExpFlag(exp, 3) +end expTypeFromExpArray; + +template expTypeFromExpArrayIf(Exp exp) + "Generate type helper." +::= + expTypeFromExpFlag(exp, 4) +end expTypeFromExpArrayIf; + +template expTypeFlag(DAE.Type ty, Integer flag) + "Generate type helper." +::= + match flag + case 1 then + // we want the short type + expTypeShort(ty) + case 2 then + // we want the "modelica type" + match ty case T_COMPLEX(complexClassType=EXTERNAL_OBJ(__)) then + 'modelica_<%expTypeShort(ty)%>' + else match ty case T_COMPLEX(__) then + '<%underscorePath(ClassInf.getStateName(complexClassType))%>' + else match ty case T_ARRAY(ty = t as T_COMPLEX(__)) then + expTypeShort(t) + else + 'modelica_<%expTypeShort(ty)%>' + case 3 then + // we want the "array type" + '<%expTypeShort(ty)%>_array' + case 4 then + // we want the "array type" only if type is array, otherwise "modelica type" + (match ty + case T_ARRAY(__) then '<%expTypeShort(ty)%>_array' + else expTypeFlag(ty, 2)) + case 8 then + (match ty + case T_ARRAY(__) then '<%expTypeFlag(ty,8)%>*' + case T_INTEGER(__) then 'int' + case T_BOOL(__) then 'int' + case T_REAL(__) then 'double' + case T_STRING(__) then 'const char*' + case T_SUBTYPE_BASIC(__) then '<%expTypeFlag(complexType,8)%>*' + else error(sourceInfo(),'I do not know the external type of <%unparseType(ty)%>')) +end expTypeFlag; + +template expTypeFromExpFlag(Exp exp, Integer flag) + "Generate type helper." +::= + match exp + case ICONST(__) then match flag case 8 then "int" case 1 then "integer" else "modelica_integer" + case RCONST(__) then match flag case 1 then "real" else "modelica_real" + case SCONST(__) then match flag case 1 then "string" else "modelica_string" + case BCONST(__) then match flag case 1 then "boolean" else "modelica_boolean" + case ENUM_LITERAL(__) then match flag case 8 then "int" case 1 then "integer" else "modelica_integer" + case e as BINARY(__) + case e as UNARY(__) + case e as LBINARY(__) + case e as LUNARY(__) then expTypeFromOpFlag(e.operator, flag) + case e as RELATION(__) then match flag case 1 then "boolean" else "modelica_boolean" + case IFEXP(__) then expTypeFromExpFlag(expThen, flag) + case CALL(attr=CALL_ATTR(__)) then expTypeFlag(attr.ty, flag) + case c as RECORD(__) then expTypeFlag(c.ty, flag) + case c as ARRAY(__) + case c as MATRIX(__) + case c as RANGE(__) + case c as CAST(__) + case c as TSUB(__) + case c as CREF(__) + case c as CODE(__) then expTypeFlag(c.ty, flag) + case c as ASUB(__) then expTypeFlag(typeof(c), flag) + case REDUCTION(__) then expTypeFlag(typeof(exp), flag) + case CONS(__) + case LIST(__) + case SIZE(__) then expTypeFlag(typeof(exp), flag) + + case META_TUPLE(__) + case META_OPTION(__) + case MATCHEXPRESSION(__) + case METARECORDCALL(__) + case BOX(__) then match flag case 1 then "metatype" else "modelica_metatype" + case c as UNBOX(__) then expTypeFlag(c.ty, flag) + case c as SHARED_LITERAL(__) then expTypeFromExpFlag(c.exp, flag) + else error(sourceInfo(), 'expTypeFromExpFlag(flag=<%flag%>):<%printExpStr(exp)%>') +end expTypeFromExpFlag; + + +template expTypeFromOpFlag(Operator op, Integer flag) + "Generate type helper." +::= + match op + case o as ADD(__) + case o as SUB(__) + case o as MUL(__) + case o as DIV(__) + case o as POW(__) + + case o as UMINUS(__) + case o as UMINUS_ARR(__) + case o as ADD_ARR(__) + case o as SUB_ARR(__) + case o as MUL_ARR(__) + case o as DIV_ARR(__) + case o as MUL_ARRAY_SCALAR(__) + case o as ADD_ARRAY_SCALAR(__) + case o as SUB_SCALAR_ARRAY(__) + case o as MUL_SCALAR_PRODUCT(__) + case o as MUL_MATRIX_PRODUCT(__) + case o as DIV_ARRAY_SCALAR(__) + case o as DIV_SCALAR_ARRAY(__) + case o as POW_ARRAY_SCALAR(__) + case o as POW_SCALAR_ARRAY(__) + case o as POW_ARR(__) + case o as POW_ARR2(__) + case o as LESS(__) + case o as LESSEQ(__) + case o as GREATER(__) + case o as GREATEREQ(__) + case o as EQUAL(__) + case o as NEQUAL(__) then + expTypeFlag(o.ty, flag) + case o as AND(__) + case o as OR(__) + case o as NOT(__) then + match flag case 1 then "boolean" else "modelica_boolean" + else error(sourceInfo(), 'expTypeFromOpFlag:ERROR') +end expTypeFromOpFlag; + +template dimension(Dimension d) +::= + match d + case DAE.DIM_BOOLEAN(__) then '2' + case DAE.DIM_ENUM(__) then size + case DAE.DIM_EXP(exp=e) then dimensionExp(e) + case DAE.DIM_INTEGER(__) then + if intEq(integer, -1) then + error(sourceInfo(),"Negeative dimension(unknown dimensions) may not be part of generated code. This is most likely an error on the part of OpenModelica. Please submit a detailed bug-report.") + else + integer + case DAE.DIM_UNKNOWN(__) then error(sourceInfo(),"Unknown dimensions may not be part of generated code. This is most likely an error on the part of OpenModelica. Please submit a detailed bug-report.") + else error(sourceInfo(), 'dimension: INVALID_DIMENSION') +end dimension; + +template dimensionExp(DAE.Exp dimExp) +::= + match dimExp + case DAE.CREF(componentRef = cr) then cref(cr) + else error(sourceInfo(), 'dimensionExp: INVALID_DIMENSION <%printExpStr(dimExp)%>') +end dimensionExp; + +template algStmtAssignPattern(DAE.Statement stmt, Context context, Text &varDecls, Text &auxFunction) + "Generates an assigment algorithm statement." +::= + match stmt + case s as STMT_ASSIGN(exp1=lhs as PATTERN(pattern=PAT_CALL_TUPLE(patterns=pat::patterns)),exp=CALL(attr=CALL_ATTR(ty=T_TUPLE(types=ty::tys)))) then + let &preExp = buffer "" + let &assignments1 = buffer "" + let &assignments = buffer "" + let &additionalOutputs = buffer "" + let &matchPhase = buffer "" + let _ = threadTuple(patterns,tys) |> (pat,ty) => match pat + case PAT_WILD(__) then + let &additionalOutputs += ", NULL" + "" + else + let v = tempDecl(expTypeArrayIf(ty), &varDecls) + let &additionalOutputs += ', &<%v%>' + let &matchPhase += patternMatch(pat,v,generateThrow(),&varDecls,&assignments) + "" + let expPart = daeExpCallTuple(s.exp,additionalOutputs,context, &preExp, &varDecls, &auxFunction) + match pat + case PAT_WILD(__) then '/* Pattern-matching tuple assignment, wild first pattern */<%\n%><%preExp%><%expPart%>;<%\n%><%matchPhase%><%assignments%>' + else + let v = tempDecl(expTypeArrayIf(ty), &varDecls) + let res = patternMatch(pat,v,generateThrow(),&varDecls,&assignments1) + << + /* Pattern-matching tuple assignment */ + <%preExp%> + <%v%> = <%expPart%>; + <%res%><%assignments1%><%matchPhase%><%assignments%> + >> + case s as STMT_ASSIGN(exp1=lhs as PATTERN(pattern=PAT_WILD(__))) then + error(sourceInfo(),'Improve simplifcation, got pattern assignment _ = <%printExpStr(exp)%>, expected NORETCALL') + case s as STMT_ASSIGN(exp1=lhs as PATTERN(__)) then + let &preExp = buffer "" + let &assignments = buffer "" + let expPart = daeExp(s.exp, context, &preExp, &varDecls, &auxFunction) + let v = tempDecl(expTypeFromExpModelica(s.exp), &varDecls) + << + /* Pattern-matching assignment */ + <%preExp%> + <%v%> = <%expPart%>; + <%patternMatch(lhs.pattern,v,generateThrow(),&varDecls,&assignments)%><%assignments%> + >> +end algStmtAssignPattern; + +template patternMatch(Pattern pat, Text rhs, Text onPatternFail, Text &varDecls, Text &assignments) +::= + match pat + case PAT_WILD(__) then "" + case p as PAT_CONSTANT(__) + then + let &unboxBuf = buffer "" + let urhs = (match p.ty + case SOME(et) then unboxVariable(rhs, et, &unboxBuf, &varDecls) + else rhs + ) + <<<%unboxBuf%><%match p.exp + case c as ICONST(__) then 'if (<%c.integer%> != <%urhs%>) <%onPatternFail%>;<%\n%>' + case c as RCONST(__) then 'if (<%c.real%> != <%urhs%>) <%onPatternFail%>;<%\n%>' + case c as SCONST(__) then + let escstr = Util.escapeModelicaStringToCString(c.string) + 'if (<%unescapedStringLength(escstr)%> != MMC_STRLEN(<%urhs%>) || strcmp("<%escstr%>", MMC_STRINGDATA(<%urhs%>)) != 0) <%onPatternFail%>;<%\n%>' + case c as BCONST(__) then 'if (<%if c.bool then 1 else 0%> != <%urhs%>) <%onPatternFail%>;<%\n%>' + case c as LIST(valList = {}) then 'if (!listEmpty(<%urhs%>)) <%onPatternFail%>;<%\n%>' + case c as META_OPTION(exp = NONE()) then 'if (!optionNone(<%urhs%>)) <%onPatternFail%>;<%\n%>' + case c as ENUM_LITERAL() then 'if (<%c.index%> != <%urhs%>) <%onPatternFail%>;<%\n%>' + else error(sourceInfo(), 'UNKNOWN_CONSTANT_PATTERN <%printExpStr(p.exp)%>') + %>>> + case p as PAT_SOME(__) then + let tvar = tempDecl("modelica_metatype", &varDecls) + <)) <%onPatternFail%>; + <%tvar%> = MMC_FETCH(MMC_OFFSET(MMC_UNTAGPTR(<%rhs%>), 1)); + <%patternMatch(p.pat,tvar,onPatternFail,&varDecls,&assignments)%>>> + case PAT_CONS(__) then + let tvarHead = tempDecl("modelica_metatype", &varDecls) + let tvarTail = tempDecl("modelica_metatype", &varDecls) + <)) <%onPatternFail%>; + <%tvarHead%> = MMC_CAR(<%rhs%>); + <%tvarTail%> = MMC_CDR(<%rhs%>); + <%patternMatch(head,tvarHead,onPatternFail,&varDecls,&assignments)%><%patternMatch(tail,tvarTail,onPatternFail,&varDecls,&assignments)%>>> + case PAT_META_TUPLE(__) + then + (patterns |> p hasindex i1 fromindex 1 => + match p + case PAT_WILD(__) then "" + else + let tvar = tempDecl("modelica_metatype", &varDecls) + <<<%tvar%> = MMC_FETCH(MMC_OFFSET(MMC_UNTAGPTR(<%rhs%>), <%i1%>)); + <%patternMatch(p,tvar,onPatternFail,&varDecls,&assignments)%> + >>; empty /* increase the counter even if no output is produced */) + case PAT_CALL_TUPLE(__) + then + // misnomer. Call expressions no longer return tuples using these structs. match-expressions and if-expressions converted to Modelica tuples do + (patterns |> p hasindex i1 fromindex 1 => + match p + case PAT_WILD(__) then "" + else + let nrhs = '<%rhs%>.c<%i1%>' + patternMatch(p,nrhs,onPatternFail,&varDecls,&assignments) + ; empty /* increase the counter even if no output is produced */ + ) + case PAT_CALL_NAMED(__) + then + <<<%patterns |> (p,n,t) => + match p + case PAT_WILD(__) then "" + else + let tvar = tempDecl(expTypeArrayIf(t), &varDecls) + <<<%tvar%> = <%rhs%>._<%n%>; + <%patternMatch(p,tvar,onPatternFail,&varDecls,&assignments)%> + >>%> + >> + case PAT_CALL(__) + then + <<<%if not knownSingleton then 'if (mmc__uniontype__metarecord__typedef__equal(<%rhs%>,<%index%>,<%listLength(patterns)%>) == 0) <%onPatternFail%>;<%\n%>'%><% + (patterns |> p hasindex i2 fromindex 2 => + match p + case PAT_WILD(__) then "" + else + let tvar = tempDecl("modelica_metatype", &varDecls) + <<<%tvar%> = MMC_FETCH(MMC_OFFSET(MMC_UNTAGPTR(<%rhs%>), <%i2%>)); + <%patternMatch(p,tvar,onPatternFail,&varDecls,&assignments)%> + >> ;empty) /* increase the counter even if no output is produced */ + %> + >> + case p as PAT_AS_FUNC_PTR(__) then + let &assignments += '_<%p.id%> = <%rhs%>;<%\n%>' + <<<%patternMatch(p.pat,rhs,onPatternFail,&varDecls,&assignments)%> + >> + case p as PAT_AS(ty = NONE()) then + let &assignments += '_<%p.id%> = <%rhs%>;<%\n%>' + <<<%patternMatch(p.pat,rhs,onPatternFail,&varDecls,&assignments)%> + >> + case p as PAT_AS(ty = SOME(et)) then + let &unboxBuf = buffer "" + let &assignments += '_<%p.id%> = <%unboxVariable(rhs, et, &unboxBuf, &varDecls)%> /* pattern as ty=<%unparseType(et)%> */;<%\n%>' + <<<%&unboxBuf%> + <%patternMatch(p.pat,rhs,onPatternFail,&varDecls,&assignments)%> + >> + else error(sourceInfo(), 'UNKNOWN_PATTERN /* rhs: <%rhs%> */<%\n%>') +end patternMatch; + +template infoArgs(SourceInfo info) +::= + match info + case SOURCEINFO(__) then '"<%Util.escapeModelicaStringToCString(testsuiteFriendly(fileName))%>",<%lineNumberStart%>,<%columnNumberStart%>,<%lineNumberEnd%>,<%columnNumberEnd%>,<%if isReadOnly then 1 else 0%>' +end infoArgs; + +template assertCommon(Exp condition, list messages, Exp level, Context context, Text &varDecls, Text &auxFunction, builtin.SourceInfo info) +::= + let &preExpCond = buffer "" + let condVar = daeExp(condition, context, &preExpCond, &varDecls, &auxFunction) + let &preExpMsg = buffer "" + let msgVar = messages |> message => expToFormatString(message,context,&preExpMsg,&varDecls,&auxFunction) ; separator = ", " + let eqnsindx = match context case FUNCTION_CONTEXT(__) then '' else 'equationIndexes, ' + let AddionalFuncName = match context case FUNCTION_CONTEXT(__) then '' else '_withEquationIndexes' + let addInfoTextContext = match context case FUNCTION_CONTEXT(__) then '' else '<%\n%>omc_assert_warning(info, "The following assertion has been violated at time %f\n<%Util.escapeModelicaStringToCString(printExpStr(condition))%>", time);' + let omcAssertFunc = match level case ENUM_LITERAL(index=2) then 'omc_assert_warning<%AddionalFuncName%>(' else 'omc_assert<%AddionalFuncName%>(threadData, ' + let warningTriggered = tempDeclZero("static int", &varDecls) + let TriggerIf = match level case ENUM_LITERAL(index=2) then 'if(!<%warningTriggered%>)<%\n%>' else '' + let TriggerVarSet = match level case ENUM_LITERAL(index=2) then '<%warningTriggered%> = 1;<%\n%>' else '' + << + <%TriggerIf%> + { + <%preExpCond%> + if(!<%condVar%>) + { + <%preExpMsg%> + FILE_INFO info = {<%infoArgs(info)%>};<%addInfoTextContext%> + <%omcAssertFunc%>info, <%eqnsindx%><%msgVar%>); + <%TriggerVarSet%> + } + }<%\n%> + >> +end assertCommon; + +template expToFormatString(Exp exp, Context context, Text &preExp, Text &varDecls, Text &auxFunction) +::= + 'MMC_STRINGDATA(<%daeExp(exp, context, &preExp, &varDecls, &auxFunction)%>)' +end expToFormatString; + +template assertCommonVar(Text condVar, Text msgVar, Context context, Text &preExpMsg, Text &varDecls, builtin.SourceInfo info) +::= + match context + case FUNCTION_CONTEXT(__) then + << + if(!<%condVar%>) + { + <%preExpMsg%> + FILE_INFO info = {<%infoArgs(info)%>}; + omc_assert(threadData, info, <%msgVar%>); + }<%\n%> + >> + else + << + if(!<%condVar%>) + { + <%preExpMsg%> + FILE_INFO info = {<%infoArgs(info)%>}; + omc_assert_warning(info, "The following assertion has been violated at time %f", time); + throwStreamPrintWithEquationIndexes(threadData, equationIndexes, <%msgVar%>); + }<%\n%> + >> +end assertCommonVar; + +template contextCref(ComponentRef cr, Context context, Text &auxFunction) + "Generates code for a component reference depending on which context we're in." +::= + match context + case FUNCTION_CONTEXT(__) + case PARALLEL_FUNCTION_CONTEXT(__) then + (match cr + case CREF_QUAL(identType = T_ARRAY(ty = T_COMPLEX(complexClassType = record_state))) then + let &preExp = buffer "" + let &varDecls = buffer "" + let rec_name = '<%underscorePath(ClassInf.getStateName(record_state))%>' + let recPtr = tempDecl(rec_name + "*", &varDecls) + let dimsLenStr = listLength(crefSubs(cr)) + let dimsValuesStr = (crefSubs(cr) |> INDEX(__) => daeDimensionExp(exp, context, &preExp, &varDecls, &auxFunction) ; separator=", ") + << + ((<%rec_name%>*)(generic_array_element_addr(&_<%ident%>, sizeof(<%rec_name%>), <%dimsLenStr%>, <%dimsValuesStr%>)))-><%contextCref(componentRef, context, &auxFunction)%> + >> + else "_" + System.unquoteIdentifier(crefStr(cr)) + ) + else cref(cr) +end contextCref; + +template contextIteratorName(Ident name, Context context) + "Generates code for an iterator variable." +::= + match context + case FUNCTION_CONTEXT(__) then "_" + name + case PARALLEL_FUNCTION_CONTEXT(__) then "_" + name + else "$P" + name +end contextIteratorName; + +/* public */ template cref(ComponentRef cr) + "Generates C equivalent name for component reference. + used in Compiler/Template/CodegenFMU.tpl" +::= + match cr + case CREF_IDENT(ident = "xloc") then crefStr(cr) + case CREF_IDENT(ident = "time") then "time" + case WILD(__) then '' + else "$P" + crefToCStr(cr) +end cref; + +template crefToCStr(ComponentRef cr) + "Helper function to cref." +::= + match cr + case CREF_IDENT(__) then '<%unquoteIdentifier(ident)%><%subscriptsToCStr(subscriptLst)%>' + case CREF_QUAL(__) then '<%unquoteIdentifier(ident)%><%subscriptsToCStr(subscriptLst)%>$P<%crefToCStr(componentRef)%>' + case WILD(__) then '' + else "CREF_NOT_IDENT_OR_QUAL" +end crefToCStr; + +template subscriptsToCStr(list subscripts) +::= + if subscripts then + '$lB<%subscripts |> s => subscriptToCStr(s) ;separator="$c"%>$rB' +end subscriptsToCStr; + +template subscriptToCStr(Subscript subscript) +::= + match subscript + case SLICE(exp=ICONST(integer=i)) then i + case SLICE(__) then error(sourceInfo(), "Unknown slice " + printExpStr(exp)) + case WHOLEDIM(__) then "WHOLEDIM" + case INDEX(__) then + match exp + case ICONST(integer=i) then i + case ENUM_LITERAL(index=i) then i + case _ then + let &varDecls = buffer "" + let &preExp = buffer "" + let &auxFunction = buffer "" + let index = daeExp(exp, contextOther, &preExp, &varDecls, &auxFunction) + '<%index%>' + end match + else error(sourceInfo(), "UNKNOWN_SUBSCRIPT") +end subscriptToCStr; + +template contextArrayCref(ComponentRef cr, Context context) + "Generates code for an array component reference depending on the context." +::= + match context + case FUNCTION_CONTEXT(__) then "_" + arrayCrefStr(cr) + case PARALLEL_FUNCTION_CONTEXT(__) then "_" + arrayCrefStr(cr) + else arrayCrefCStr(cr) +end contextArrayCref; + +template arrayCrefCStr(ComponentRef cr) +::= '$P<%arrayCrefCStr2(cr)%>' +end arrayCrefCStr; + +template arrayCrefCStr2(ComponentRef cr) +::= + match cr + case CREF_IDENT(__) then '<%unquoteIdentifier(ident)%>' + case CREF_QUAL(__) then '<%unquoteIdentifier(ident)%><%subscriptsToCStr(subscriptLst)%>$P<%arrayCrefCStr2(componentRef)%>' + else "CREF_NOT_IDENT_OR_QUAL" +end arrayCrefCStr2; + +template arrayCrefStr(ComponentRef cr) +::= + match cr + case CREF_IDENT(__) then '<%ident%>' + case CREF_QUAL(__) then '<%ident%>._<%arrayCrefStr(componentRef)%>' + else "CREF_NOT_IDENT_OR_QUAL" +end arrayCrefStr; + +template crefFunctionName(ComponentRef cr) +::= + match cr + case CREF_IDENT(__) then + System.stringReplace(unquoteIdentifier(ident), "_", "__") + case CREF_QUAL(__) then + '<%System.stringReplace(unquoteIdentifier(ident), "_", "__")%>_<%crefFunctionName(componentRef)%>' +end crefFunctionName; + +template addRootsTempArray() +::= + match System.tmpTickMaximum(1) + case 0 then "" + case i then /* TODO: Find out where we add tmpIndex but discard its use causing us to generate unused tmpMeta with size 1 */ + << + modelica_metatype tmpMeta[<%i%>] __attribute__((unused)) = {0}; + >> +end addRootsTempArray; + +template modelicaLine(builtin.SourceInfo info) +::= + if boolOr(acceptMetaModelicaGrammar(), Flags.isSet(Flags.GEN_DEBUG_SYMBOLS)) then '/*#modelicaLine <%infoStr(info)%>*/<%\n%>' +end modelicaLine; + +template endModelicaLine() +::= + if boolOr(acceptMetaModelicaGrammar(), Flags.isSet(Flags.GEN_DEBUG_SYMBOLS)) then '/*#endModelicaLine*/<%\n%>' +end endModelicaLine; + +template tempDecl(String ty, Text &varDecls) + "Declares a temporary variable in varDecls and returns the name." +::= + let newVar = + match ty /* TODO! FIXME! UGLY! UGLY! hack! */ + case "modelica_metatype" + case "metamodelica_string" + case "metamodelica_string_const" + then 'tmpMeta[<%System.tmpTickIndex(1)%>]' + else + let newVarIx = 'tmp<%System.tmpTick()%>' + let &varDecls += '<%ty%> <%newVarIx%>;<%\n%>' + newVarIx + newVar +end tempDecl; + +template tempDeclZero(String ty, Text &varDecls) + "Declares a temporary variable initialized to zero in varDecls and returns the name." +::= + let newVar + = + match ty /* TODO! FIXME! UGLY! UGLY! hack! */ + case "modelica_metatype" + case "metamodelica_string" + case "metamodelica_string_const" + then 'tmpMeta[<%System.tmpTickIndex(1)%>]' + else + let newVarIx = 'tmp<%System.tmpTick()%>' + let &varDecls += '<%ty%> <%newVarIx%> = 0;<%\n%>' + newVarIx + newVar +end tempDeclZero; + +template tempDeclMatchInput(String ty, String prefix, String startIndex, String index, Text &varDecls) + "Declares a temporary variable in varDecls for variables in match input list and returns the name." +::= + let newVar + = + match ty /* TODO! FIXME! UGLY! UGLY! hack! */ + case "modelica_metatype" + case "metamodelica_string" + case "metamodelica_string_const" + then 'tmpMeta[<%startIndex%>+<%index%>]' + else + let newVarIx = '<%prefix%>_in<%index%>' + let &varDecls += '<%ty%> <%newVarIx%>;<%\n%>' + newVarIx + newVar +end tempDeclMatchInput; + +template getTempDeclMatchInputName(list inputs, String prefix, String startIndex, Integer index) + "Returns the name of the temporary variable from the match input list." +::= + let typ = '<%expTypeFromExpModelica(listGet(inputs, index))%>' + let newVar = + match typ /* TODO! FIXME! UGLY! UGLY! hack! */ + case "modelica_metatype" + case "metamodelica_string" + case "metamodelica_string_const" + then 'tmpMeta[<%startIndex%>+<%intSub(index, 1)%>]' + else + let newVarIx = '<%prefix%>_in<%intSub(index, 1)%>' + newVarIx + newVar +end getTempDeclMatchInputName; + +template tempDeclMatchOutput(String ty, String prefix, String startIndex, String index, Text &varDecls) + "Declares a temporary variable in varDecls for variables in match output list and returns the name." +::= + let newVar + = + match ty /* TODO! FIXME! UGLY! UGLY! hack! */ + case "modelica_metatype" + case "metamodelica_string" + case "metamodelica_string_const" + then 'tmpMeta[<%startIndex%>+<%index%>]' + else + let newVarIx = '<%prefix%>_c<%index%>' + let &varDecls += '<%ty%> <%newVarIx%> __attribute__((unused)) = 0;<%\n%>' + newVarIx + newVar +end tempDeclMatchOutput; + +template getTempDeclMatchOutputName(list outputs, String prefix, String startIndex, Integer index) + "Returns the name of the temporary variable from the match input list." +::= + let typ = '<%expTypeFromExpModelica(listGet(outputs, index))%>' + let newVar = + match typ /* TODO! FIXME! UGLY! UGLY! hack! */ + case "modelica_metatype" + case "metamodelica_string" + case "metamodelica_string_const" + then 'tmpMeta[<%startIndex%>+<%intSub(index, 1)%>]' + else + let newVarIx = '<%prefix%>_c<%intSub(index, 1)%>' + newVarIx + newVar +end getTempDeclMatchOutputName; + +/* public */ template daeExp(Exp exp, Context context, Text &preExp, Text &varDecls, Text &auxFunction) + "Generates code for an expression. + used in Compiler/Template/CodegenQSS.tpl" +::= + match exp + case e as ICONST(__) then '(modelica_integer) <%integer%>' /* Yes, we need to cast int to long on 64-bit arch... */ + case e as RCONST(__) then real + case e as SCONST(__) then daeExpSconst(string, &preExp, &varDecls) + case e as BCONST(__) then if bool then "1" else "0" + case e as ENUM_LITERAL(__) then index + case e as CREF(__) then daeExpCrefRhs(e, context, &preExp, &varDecls, &auxFunction) + case e as BINARY(__) then daeExpBinary(e, context, &preExp, &varDecls, &auxFunction) + case e as UNARY(__) then daeExpUnary(e, context, &preExp, &varDecls, &auxFunction) + case e as LBINARY(__) then daeExpLbinary(e, context, &preExp, &varDecls, &auxFunction) + case e as LUNARY(__) then daeExpLunary(e, context, &preExp, &varDecls, &auxFunction) + case e as RELATION(__) then daeExpRelation(e, context, &preExp, &varDecls, &auxFunction) + case e as IFEXP(__) then daeExpIf(e, context, &preExp, &varDecls, &auxFunction) + case e as CALL(__) then daeExpCall(e, context, &preExp, &varDecls, &auxFunction) + case e as RECORD(__) then daeExpRecord(e, context, &preExp, &varDecls, &auxFunction) + case e as PARTEVALFUNCTION(__)then daeExpPartEvalFunction(e, context, &preExp, &varDecls, &auxFunction) + case e as ARRAY(__) then daeExpArray(e, context, &preExp, &varDecls, &auxFunction) + case e as MATRIX(__) then daeExpMatrix(e, context, &preExp, &varDecls, &auxFunction) + case e as RANGE(__) then daeExpRange(e, context, &preExp, &varDecls, &auxFunction) + case e as CAST(__) then daeExpCast(e, context, &preExp, &varDecls, &auxFunction) + case e as ASUB(__) then daeExpAsub(e, context, &preExp, &varDecls, &auxFunction) + case e as TSUB(__) then daeExpTsub(e, context, &preExp, &varDecls, &auxFunction) + case e as SIZE(__) then daeExpSize(e, context, &preExp, &varDecls, &auxFunction) + case e as REDUCTION(__) then daeExpReduction(e, context, &preExp, &varDecls, &auxFunction) + case e as TUPLE(__) then daeExpTuple(e, context, &preExp, &varDecls, &auxFunction) + case e as LIST(__) then daeExpList(e, context, &preExp, &varDecls, &auxFunction) + case e as CONS(__) then daeExpCons(e, context, &preExp, &varDecls, &auxFunction) + case e as META_TUPLE(__) then daeExpMetaTuple(e, context, &preExp, &varDecls, &auxFunction) + case e as META_OPTION(__) then daeExpMetaOption(e, context, &preExp, &varDecls, &auxFunction) + case e as METARECORDCALL(__) then daeExpMetarecordcall(e, context, &preExp, &varDecls, &auxFunction) + case e as MATCHEXPRESSION(__) then daeExpMatch(e, context, &preExp, &varDecls, &auxFunction) + case e as BOX(__) then daeExpBox(e, context, &preExp, &varDecls, &auxFunction) + case e as UNBOX(__) then daeExpUnbox(e, context, &preExp, &varDecls, &auxFunction) + case e as SHARED_LITERAL(__) then daeExpSharedLiteral(e) + case e as SUM(__) then daeExpSum(e, context, &preExp, &varDecls, &auxFunction) + case e as CLKCONST(__) then '#error "<%ExpressionDump.printExpStr(e)%>"' + else error(sourceInfo(), 'Unknown expression: <%ExpressionDump.printExpStr(exp)%>') +end daeExp; + + +template daeExternalCExp(Exp exp, Context context, Text &preExp, Text &varDecls, Text &auxFunction) + "Like daeExp, but also converts the type to external C" +::= + match typeof(exp) + case T_ARRAY(__) then // Array-expressions + let shortTypeStr = expTypeShort(typeof(exp)) + '(<%extType(typeof(exp),true,true)%>) data_of_<%shortTypeStr%>_array(&<%daeExp(exp, context, &preExp, &varDecls, &auxFunction)%>)' + case T_STRING(__) then + let mstr = daeExp(exp, context, &preExp, &varDecls, &auxFunction) + 'MMC_STRINGDATA(<%mstr%>)' + else daeExp(exp, context, &preExp, &varDecls, &auxFunction) +end daeExternalCExp; + +template daeExternalF77Exp(Exp exp, Context context, Text &preExp, Text &varDecls, Text &auxFunction) + "Like daeExp, but also converts the type to external Fortran" +::= + match typeof(exp) + case T_ARRAY(__) then // Array-expressions + let shortTypeStr = expTypeShort(typeof(exp)) + '(<%extType(typeof(exp),true,true)%>) data_of_<%shortTypeStr%>_array(&<%daeExp(exp, context, &preExp, &varDecls, &auxFunction)%>)' + case T_STRING(__) then + let texp = daeExp(exp, contextFunction, &preExp, &varDecls, &auxFunction) + let tvar = tempDecl(expTypeFromExpFlag(exp,8),&varDecls) + let &preExp += '<%tvar%> = MMC_STRINGDATA(<%texp%>);<%\n%>' + '&<%tvar%>' + else + let texp = daeExp(exp, contextFunction, &preExp, &varDecls, &auxFunction) + let tvar = tempDecl(expTypeFromExpFlag(exp,8),&varDecls) + let &preExp += '<%tvar%> = <%texp%>;<%\n%>' + '&<%tvar%>' +end daeExternalF77Exp; + +template daeExpSconst(String string, Text &preExp, Text &varDecls) + "Generates code for a string constant." +::= + let escstr = Util.escapeModelicaStringToCString(string) + match stringLength(string) + case 0 then "(modelica_string) mmc_emptystring" + case 1 then '(modelica_string) mmc_strings_len1[<%stringGet(string, 1)%>]' + else + let tmp = 'tmp<%System.tmpTick()%>' + let &varDecls += 'static const MMC_DEFSTRINGLIT(<%tmp%>,<%unescapedStringLength(escstr)%>,"<%escstr%>");<%\n%>' + 'MMC_REFSTRINGLIT(<%tmp%>)' +end daeExpSconst; + +template daeExpList(Exp exp, Context context, Text &preExp, + Text &varDecls, Text &auxFunction) + "Generates code for a meta modelica list expression." +::= +match exp +case LIST(__) then + let tmp = tempDecl("modelica_metatype", &varDecls) + let expPart = daeExpListToCons(valList, context, &preExp, &varDecls, &auxFunction) + let &preExp += '<%tmp%> = <%expPart%>;<%\n%>' + tmp +end daeExpList; + + +template daeExpListToCons(list listItems, Context context, Text &preExp, + Text &varDecls, Text &auxFunction) + "Helper to daeExpList." +::= + match listItems + case {} then "MMC_REFSTRUCTLIT(mmc_nil)" + case e :: rest then + let expPart = daeExp(e, context, &preExp, &varDecls, &auxFunction) + let restList = daeExpListToCons(rest, context, &preExp, &varDecls, &auxFunction) + << + mmc_mk_cons(<%expPart%>, <%restList%>) + >> +end daeExpListToCons; + + +template daeExpCons(Exp exp, Context context, Text &preExp, + Text &varDecls, Text &auxFunction) + "Generates code for a meta modelica cons expression." +::= +match exp +case CONS(__) then + let tmp = tempDecl("modelica_metatype", &varDecls) + let carExp = daeExp(car, context, &preExp, &varDecls, &auxFunction) + + let cdrExp = daeExp(cdr, context, &preExp, &varDecls, &auxFunction) + let &preExp += '<%tmp%> = mmc_mk_cons(<%carExp%>, <%cdrExp%>);<%\n%>' + tmp +end daeExpCons; + +template tempDeclTuple(DAE.Type inType, Text &varDecls) +::= + match inType + case T_TUPLE(__) then + let tmpVar = 'tmp<%System.tmpTick()%>' + let &varDecls += + << + struct { + <%types |> ty hasindex i1 fromindex 1 => '<%expTypeModelica(ty)%> c<%i1%>;<%\n%>'%> + } <%tmpVar%>; + >> + tmpVar + else tempDecl(expTypeArrayIf(inType),&varDecls) +end tempDeclTuple; + +template daeExpTuple(Exp exp, Context context, Text &preExp, Text &varDecls, Text &auxFunction) + "Generates code for a meta modelica tuple expression." +::= +match exp +case TUPLE(__) then + let tmpVar = tempDeclTuple(typeof(exp),&varDecls) + let tmp = (PR |> e hasindex i1 fromindex 1 => '<%tmpVar%>.c<%i1%> = <%daeExp(e, context, &preExp, &varDecls, &auxFunction)%>;<%\n%>') + let &preExp += tmp + tmpVar +end daeExpTuple; + +template daeExpMetaTuple(Exp exp, Context context, Text &preExp, + Text &varDecls, Text &auxFunction) + "Generates code for a meta modelica tuple expression." +::= +match exp +case META_TUPLE(__) then + let start = daeExpMetaHelperBoxStart(listLength(listExp)) + let args = (listExp |> e => daeExp(e, context, &preExp, &varDecls, &auxFunction) + ;separator=", ") + let tmp = tempDecl("modelica_metatype", &varDecls) + let &preExp += '<%tmp%> = mmc_mk_box<%start%>0<%if args then ", "%><%args%>);<%\n%>' + tmp +end daeExpMetaTuple; + + +template daeExpMetaOption(Exp exp, Context context, Text &preExp, Text &varDecls, Text &auxFunction) + "Generates code for a meta modelica option expression." +::= + match exp + case META_OPTION(exp=NONE()) then + "mmc_mk_none()" + case META_OPTION(exp=SOME(e)) then + let expPart = daeExp(e, context, &preExp, &varDecls, &auxFunction) + 'mmc_mk_some(<%expPart%>)' +end daeExpMetaOption; + + +template daeExpMetarecordcall(Exp exp, Context context, Text &preExp, Text &varDecls, Text &auxFunction) + "Generates code for a meta modelica record call expression." +::= +match exp +case METARECORDCALL(__) then + let newIndex = getValueCtor(index) + let argsStr = if args then + ', <%args |> exp => + daeExp(exp, context, &preExp, &varDecls, &auxFunction) + ;separator=", "%>' + else + "" + let box = 'mmc_mk_box<%daeExpMetaHelperBoxStart(incrementInt(listLength(args), 1))%><%newIndex%>, &<%underscorePath(path)%>__desc<%argsStr%>)' + let tmp = tempDecl("modelica_metatype", &varDecls) + let &preExp += '<%tmp%> = <%box%>;<%\n%>' + tmp +end daeExpMetarecordcall; + +template daeExpMetaHelperBoxStart(Integer numVariables) + "Helper to determine how mmc_mk_box should be called." +::= + if intGt(numVariables,20) then '(<%numVariables%>, ' else '<%numVariables%>(' +end daeExpMetaHelperBoxStart; + +template crefToMStr(ComponentRef cr) + "Helper function to crefM." +::= + match cr + case CREF_IDENT(__) then '<%unquoteIdentifier(ident)%><%subscriptsToMStr(subscriptLst)%>' + case CREF_QUAL(__) then '<%unquoteIdentifier(ident)%><%subscriptsToMStr(subscriptLst)%>P<%crefToMStr(componentRef)%>' + else "CREF_NOT_IDENT_OR_QUAL" +end crefToMStr; + +template subscriptsToMStr(list subscripts) +::= + if subscripts then + 'lB<%subscripts |> s => subscriptToMStr(s) ;separator="c"%>rB' +end subscriptsToMStr; + +template subscriptToMStr(Subscript subscript) +::= + match subscript + case SLICE(exp=ICONST(integer=i)) then i + case SLICE(__) then error(sourceInfo(), "Unknown slice " + printExpStr(exp)) + case WHOLEDIM(__) then "WHOLEDIM" + case INDEX(__) then + match exp + case ICONST(integer=i) then i + case ENUM_LITERAL(index=i) then i + else + let &varDecls = buffer "" + let &preExp = buffer "" + let &auxFunction = buffer "" + daeExp(exp, contextOther, &preExp, &varDecls, &auxFunction) + end match + else error(sourceInfo(), "UNKNOWN_SUBSCRIPT") +end subscriptToMStr; + +template generateThrow() +::= + match codegenPeekTryThrowIndex() + case -1 then "MMC_THROW_INTERNAL()" + case i then 'goto goto_<%i%>' +end generateThrow; + +template daeExpCrefRhs(Exp exp, Context context, Text &preExp, + Text &varDecls, Text &auxFunction) + "Generates code for a component reference on the right hand side of an + expression." +::= + match exp + case CREF(componentRef = cr, ty = T_FUNCTION_REFERENCE_FUNC(__)) then + 'boxvar_<%crefFunctionName(cr)%>' + case CREF(componentRef = cr, ty = T_FUNCTION_REFERENCE_VAR(__)) then + '((modelica_fnptr) _<%crefStr(cr)%>)' + case CREF(componentRef = cr as CREF_QUAL(subscriptLst={}, identType = T_METATYPE(ty=ty as T_METARECORD(__)), componentRef=cri as CREF_IDENT(__))) then + let offset = intAdd(findVarIndex(cri.ident,ty.fields),2) + '(MMC_FETCH(MMC_OFFSET(MMC_UNTAGPTR(_<%cr.ident%>), <%offset%>)))' + else + match context + case FUNCTION_CONTEXT(__) then daeExpCrefRhsFunContext(exp, context, &preExp, &varDecls, &auxFunction) + case PARALLEL_FUNCTION_CONTEXT(__) then daeExpCrefRhsFunContext(exp, context, &preExp, &varDecls, &auxFunction) + else daeExpCrefRhsSimContext(exp, context, &preExp, &varDecls, &auxFunction) +end daeExpCrefRhs; + +template daeExpCrefRhsSimContext(Exp ecr, Context context, Text &preExp, + Text &varDecls, Text &auxFunction) + "Generates code for a component reference in simulation context." +::= + match ecr + case ecr as CREF(componentRef = cr, ty = t as T_COMPLEX(complexClassType = EXTERNAL_OBJ(__))) then + contextCref(cr, context, &auxFunction) + + case ecr as CREF(componentRef = cr, ty = t as T_COMPLEX(complexClassType = record_state, varLst = var_lst)) then + let vars = var_lst |> v => (", " + daeExp(makeCrefRecordExp(cr,v), context, &preExp, &varDecls, &auxFunction)) + let record_type_name = underscorePath(ClassInf.getStateName(record_state)) + 'omc_<%record_type_name%>(threadData<%vars%>)' + + case ecr as CREF(componentRef=cr, ty=T_ARRAY(ty=aty, dims=dims)) then + let type = expTypeShort(aty) + let arrayType = type + "_array" + let wrapperArray = tempDecl(arrayType, &varDecls) + if crefSubIsScalar(cr) then + let dimsLenStr = listLength(dims) + let dimsValuesStr = (dims |> dim => dimension(dim) ;separator=", ") + let nosubname = contextCref(crefStripSubs(cr),context, &auxFunction) + let substring = (crefSubs(crefArrayGetFirstCref(cr)) |> INDEX(__) => + daeSubscriptExp(exp, context, &preExp, &varDecls, &auxFunction) + ;separator=", ") + let &preExp += '<%type%>_array_create(&<%wrapperArray%>, ((modelica_<%type%>*)&(<%nosubname%>_index(<%substring%>))), <%dimsLenStr%>, <%dimsValuesStr%>);<%\n%>' + wrapperArray + else + let dimsLenStr = listLength(crefDims(cr)) + let dimsValuesStr = (crefDims(cr) |> dim => dimension(dim) ;separator=", ") + let arrName = contextCref(crefStripSubs(cr), context,&auxFunction) + let &preExp += '<%type%>_array_create(&<%wrapperArray%>, (modelica_<%type%>*)&<%arrName%>, <%dimsLenStr%>, <%dimsValuesStr%>);<%\n%>' + let slicedArray = tempDecl(arrayType, &varDecls) + let spec1 = daeExpCrefIndexSpec(crefSubs(cr), context, &preExp, &varDecls, &auxFunction) + let &preExp += 'index_alloc_<%type%>_array(&<%wrapperArray%>, &<%spec1%>, &<%slicedArray%>);<%\n%>' + slicedArray + + case ecr as CREF(componentRef=cr, ty=ty) then + if crefIsScalarWithAllConstSubs(cr) then + let cast = match ty case T_INTEGER(__) then "(modelica_integer)" + case T_ENUMERATION(__) then "(modelica_integer)" //else "" + '<%cast%><%contextCref(cr,context, &auxFunction)%>' + else if crefIsScalarWithVariableSubs(cr) then + let nosubname = contextCref(crefStripSubs(cr),context, &auxFunction) + let substring = (crefSubs(cr) |> INDEX(__) => + daeSubscriptExp(exp, context, &preExp, &varDecls, &auxFunction) + ;separator=", ") + let cast = match ty case T_INTEGER(__) then "(modelica_integer)" + case T_ENUMERATION(__) then "(modelica_integer)" //else "" + '<%cast%><%nosubname%>_index(<%substring%>)' + else + error(sourceInfo(),'daeExpCrefRhsSimContext: UNHANDLED CREF: <%ExpressionDump.printExpStr(ecr)%>') +end daeExpCrefRhsSimContext; + +template daeExpCrefRhsFunContext(Exp ecr, Context context, Text &preExp, + Text &varDecls, Text &auxFunction) + "Generates code for a component reference." +::= + match ecr + case ecr as CREF(componentRef=cr, ty=ty) then + if crefIsScalar(cr, context) then + let cast = match ty case T_INTEGER(__) then "(modelica_integer)" + case T_ENUMERATION(__) then "(modelica_integer)" //else "" + '<%cast%><%contextCref(cr,context, &auxFunction)%>' + else + if crefSubIsScalar(cr) then + // The array subscript results in a scalar + let arrName = contextCref(crefStripLastSubs(cr), context, &auxFunction) + let arrayType = expTypeArray(ty) + let dimsLenStr = listLength(crefSubs(cr)) + let dimsValuesStr = (crefSubs(cr) |> INDEX(__) => + daeDimensionExp(exp, context, &preExp, &varDecls, &auxFunction) + ;separator=", ") + match cr + case CREF_IDENT(identType = T_METATYPE(ty = T_METAARRAY())) + case CREF_IDENT(identType = T_METAARRAY()) then + 'arrayGet(<%arrName%>, <%dimsValuesStr%>)' + else + match context + case FUNCTION_CONTEXT(__) then + match ty + case (T_ARRAY(ty = T_COMPLEX(complexClassType = record_state))) + case (T_COMPLEX(complexClassType = record_state)) then + let rec_name = '<%underscorePath(ClassInf.getStateName(record_state))%>' + << + (*((<%rec_name%>*)(generic_array_element_addr(&<%arrName%>, sizeof(<%rec_name%>), <%dimsLenStr%>, <%dimsValuesStr%>)))) + >> + else + << + (*<%arrayType%>_element_addr(&<%arrName%>, <%dimsLenStr%>, <%dimsValuesStr%>)) + >> + case PARALLEL_FUNCTION_CONTEXT(__) then + << + (*<%arrayType%>_element_addr_c99_<%dimsLenStr%>(&<%arrName%>, <%dimsLenStr%>, <%dimsValuesStr%>)) + >> + else + error(sourceInfo(),'This should have been handled in the new daeExpCrefRhsSimContext function. <%printExpStr(ecr)%>') + else + match context + case FUNCTION_CONTEXT(__) + case PARALLEL_FUNCTION_CONTEXT(__) then + // The array subscript denotes a slice + // let &preExp += '/* daeExpCrefRhsFunContext SLICE(<%ExpressionDump.printExpStr(ecr)%>) preExp */<%\n%>' + let arrName = contextArrayCref(cr, context) + let arrayType = expTypeArray(ty) + let tmp = tempDecl(arrayType, &varDecls) + let spec1 = daeExpCrefIndexSpec(crefSubs(cr), context, &preExp, &varDecls, &auxFunction) + let &preExp += 'index_alloc_<%arrayType%>(&<%arrName%>, &<%spec1%>, &<%tmp%>);<%\n%>' + tmp + else + error(sourceInfo(),'daeExpCrefRhsFunContext: Slice in simulation context: <%ExpressionDump.printExpStr(ecr)%>') + case ecr then + error(sourceInfo(),'daeExpCrefRhsFunContext: UNHANDLED EXPRESSION: <%ExpressionDump.printExpStr(ecr)%>') +end daeExpCrefRhsFunContext; + +// TODO: Optimize as in Codegen +// TODO: Use this function in other places where almost the same thing is hard +// coded +template arrayScalarRhs(Type ty, list subs, String arrName, Context context, + Text &preExp, Text &varDecls, Text &auxFunction) + "Helper to daeExpAsub." +::= + let arrayType = expTypeArray(ty) + let dimsLenStr = listLength(subs) + let dimsValuesStr = (subs |> exp => + daeDimensionExp(exp, context, &preExp, &varDecls, &auxFunction) + + ;separator=", ") + match arrayType + case "metatype_array" then + 'arrayGet(<%arrName%>,<%dimsValuesStr%>) /*arrayScalarRhs*/' + else + match context + case PARALLEL_FUNCTION_CONTEXT(__) then + << + (*<%arrayType%>_element_addr_c99_<%dimsLenStr%>(&<%arrName%>, <%dimsLenStr%>, <%dimsValuesStr%>)) + >> + else + << + (*<%arrayType%>_element_addr(&<%arrName%>, <%dimsLenStr%>, <%dimsValuesStr%>)) + >> +end arrayScalarRhs; + +template daeExpCrefLhs(Exp exp, Context context, Text &preExp, + Text &varDecls, Text &auxFunction) + "Generates code for a component reference on the left hand side of an expression." +::= + match exp + case CREF(componentRef = cr, ty = T_FUNCTION_REFERENCE_FUNC(__)) then + '((modelica_fnptr)boxptr_<%crefFunctionName(cr)%>)' + case CREF(componentRef = cr, ty = T_FUNCTION_REFERENCE_VAR(__)) then + '_<%crefStr(cr)%>' + else + match context + case FUNCTION_CONTEXT(__) then daeExpCrefLhsFunContext(exp, context, &preExp, &varDecls, &auxFunction) + case PARALLEL_FUNCTION_CONTEXT(__) then daeExpCrefLhsFunContext(exp, context, &preExp, &varDecls, &auxFunction) + else daeExpCrefLhsSimContext(exp, context, &preExp, &varDecls, &auxFunction) +end daeExpCrefLhs; + +template daeExpCrefLhsSimContext(Exp ecr, Context context, Text &preExp, + Text &varDecls, Text &auxFunction) + "Generates code for a component reference in simulation context." +::= + match ecr + case ecr as CREF(componentRef = cr, ty = t as T_COMPLEX(complexClassType = EXTERNAL_OBJ(__))) then + contextCref(cr, context, &auxFunction) + + case ecr as CREF(componentRef = cr, ty = t as T_COMPLEX(complexClassType = record_state, varLst = var_lst)) then + let vars = var_lst |> v => (", " + daeExp(makeCrefRecordExp(cr,v), context, &preExp, &varDecls, &auxFunction)) + let record_type_name = underscorePath(ClassInf.getStateName(record_state)) + // 'omc_<%record_type_name%>(threadData<%vars%>)' + error(sourceInfo(), 'daeExpCrefLhsSimContext got record <%crefStr(cr)%>. This does not make sense. Assigning to records is handled in a different way in the code generator, and reaching here is probably an error...') // '<%ret_var%>.c1' + + case ecr as CREF(componentRef=cr, ty=T_ARRAY(ty=aty, dims=dims)) then + let type = expTypeShort(aty) + let arrayType = type + "_array" + let wrapperArray = tempDecl(arrayType, &varDecls) + if crefSubIsScalar(cr) then + let dimsLenStr = listLength(dims) + let dimsValuesStr = (dims |> dim => dimension(dim) ;separator=", ") + let nosubname = contextCref(crefStripSubs(cr),context, &auxFunction) + let substring = (crefSubs(crefArrayGetFirstCref(cr)) |> INDEX(__) => + daeSubscriptExp(exp, context, &preExp, &varDecls, &auxFunction) + ;separator=", ") + let &preExp += '<%type%>_array_create(&<%wrapperArray%>, ((modelica_<%type%>*)&(<%nosubname%>_index(<%substring%>))), <%dimsLenStr%>, <%dimsValuesStr%>);<%\n%>' + wrapperArray + else + error(sourceInfo(),'daeExpCrefLhsSimContext: This should have been handled in indexed assign and should not have gotten here <%ExpressionDump.printExpStr(ecr)%>') + + + case ecr as CREF(componentRef=cr, ty=ty) then + if crefIsScalarWithAllConstSubs(cr) then + '<%contextCref(cr,context, &auxFunction)%>' + else if crefIsScalarWithVariableSubs(cr) then + let nosubname = contextCref(crefStripSubs(cr),context, &auxFunction) + let substring = (crefSubs(cr) |> INDEX(__) => + daeSubscriptExp(exp, context, &preExp, &varDecls, &auxFunction) + ;separator=", ") + '<%nosubname%>_index(<%substring%>)' + else + error(sourceInfo(),'daeExpCrefLhsSimContext: UNHANDLED CREF: <%ExpressionDump.printExpStr(ecr)%>') +end daeExpCrefLhsSimContext; + +template daeExpCrefLhsFunContext(Exp ecr, Context context, Text &preExp, + Text &varDecls, Text &auxFunction) + "Generates code for a component reference on the left hand side!" +::= + match ecr + case ecr as CREF(componentRef=cr, ty=ty) then + if crefIsScalar(cr, context) then + '<%contextCref(cr,context,&auxFunction)%>' + else + if crefSubIsScalar(cr) then + // The array subscript results in a scalar + let arrName = contextCref(crefStripLastSubs(cr), context, &auxFunction) + let arrayType = expTypeArray(ty) + let dimsLenStr = listLength(crefSubs(cr)) + let dimsValuesStr = (crefSubs(cr) |> INDEX(__) => + daeDimensionExp(exp, context, &preExp, &varDecls, &auxFunction) + ;separator=", ") + match context + case PARALLEL_FUNCTION_CONTEXT(__) then + << + (*<%arrayType%>_element_addr_c99_<%dimsLenStr%>(&<%arrName%>, <%dimsLenStr%>, <%dimsValuesStr%>)) + >> + case FUNCTION_CONTEXT(__) then + << + (*<%arrayType%>_element_addr(&<%arrName%>, <%dimsLenStr%>, <%dimsValuesStr%>)) + >> + else + error(sourceInfo(),'This should have been handled in the new daeExpCrefLhsSimContext function. <%printExpStr(ecr)%>') + + else + error(sourceInfo(),'This should have been handled in indexed assign and should not have gotten here. <%printExpStr(ecr)%>') + + case ecr then + error(sourceInfo(), 'SimCodeC.tpl template: daeExpCrefLhsFunContext: UNHANDLED EXPRESSION: <%ExpressionDump.printExpStr(ecr)%>') +end daeExpCrefLhsFunContext; + +template daeExpCrefIndexSpec(list subs, Context context, + Text &preExp, Text &varDecls, Text &auxFunction) + "Generates index lists for crefs involving slices" +::= + let nridx_str = listLength(subs) + let idx_str = (subs |> sub => + match sub + case INDEX(__) then + let expPart = daeExp(exp, context, &preExp, &varDecls, &auxFunction) + let str = <<(0), make_index_array(1, (int) <%expPart%>), 'S'>> + str + case WHOLEDIM(__) then + let str = <<(1), (int*)0, 'W'>> + str + case SLICE(__) then + let expPart = daeExp(exp, context, &preExp, &varDecls, &auxFunction) + let tmp = tempDecl("modelica_integer", &varDecls) + let &preExp += '<%tmp%> = size_of_dimension_base_array(<%expPart%>, 1);<%\n%>' + let str = <<(int) <%tmp%>, integer_array_make_index_array(&<%expPart%>), 'A'>> + str + ;separator=", ") + let tmp = tempDecl("index_spec_t", &varDecls) + let &preExp += 'create_index_spec(&<%tmp%>, <%nridx_str%>, <%idx_str%>);<%\n%>' + tmp +end daeExpCrefIndexSpec; + +template daeExpBinary(Exp exp, Context context, Text &preExp, + Text &varDecls, Text &auxFunction) + "Generates code for a binary expression." +::= + +match exp +case BINARY(__) then + let e1 = daeExp(exp1, context, &preExp, &varDecls, &auxFunction) + let e2 = daeExp(exp2, context, &preExp, &varDecls, &auxFunction) + match operator + case ADD(ty = T_STRING(__)) then + let tmpStr = tempDecl("modelica_metatype", &varDecls) + let &preExp += '<%tmpStr%> = stringAppend(<%e1%>,<%e2%>);<%\n%>' + tmpStr + case ADD(__) then '(<%e1%> + <%e2%>)' + case SUB(__) then '(<%e1%> - <%e2%>)' + case MUL(__) then '(<%e1%> * <%e2%>)' + case DIV(__) then + let tvar = tempDecl(expTypeModelica(ty),&varDecls) + let &preExp += '<%tvar%> = <%e2%>;<%\n%>' + let &preExp += + if acceptMetaModelicaGrammar() + then 'if (<%tvar%> == 0) {<%generateThrow()%>;}<%\n%>' + else 'if (<%tvar%> == 0) {throwStreamPrint(threadData, "Division by zero %s", "<%Util.escapeModelicaStringToCString(printExpStr(exp))%>");}<%\n%>' + '(<%e1%> / <%e2%>)' + case POW(__) then + if isHalf(exp2) then + (let tmp = tempDecl(expTypeFromExpModelica(exp1),&varDecls) + let ass = '(<%tmp%> >= 0.0)' + let &preExpMsg = buffer "" + let retPre = assertCommonVar(ass,'"Model error: Argument of sqrt(<%Util.escapeModelicaStringToCString(printExpStr(exp1))%>) was %g should be >= 0", <%tmp%>', context, &preExpMsg, &varDecls, dummyInfo) + let &preExp += '<%tmp%> = <%e1%>; <%\n%><%retPre%>' + 'sqrt(<%tmp%>)') + else match realExpIntLit(exp2) + case SOME(2) then + let tmp = tempDecl("modelica_real", &varDecls) + let &preExp += '<%tmp%> = <%e1%>;<%\n%>' + '(<%tmp%> * <%tmp%>)' + case SOME(3) then + let tmp = tempDecl("modelica_real", &varDecls) + let &preExp += '<%tmp%> = <%e1%>;<%\n%>' + '(<%tmp%> * <%tmp%> * <%tmp%>)' + case SOME(4) then + let tmp = tempDecl("modelica_real", &varDecls) + let &preExp += '<%tmp%> = <%e1%>;<%\n%>' + let &preExp += '<%tmp%> *= <%tmp%>;<%\n%>' + '(<%tmp%> * <%tmp%>)' + case SOME(i) then 'real_int_pow(threadData, <%e1%>, <%i%>)' + else 'pow(<%e1%>, <%e2%>)' + case UMINUS(__) then daeExpUnary(exp, context, &preExp, &varDecls, &auxFunction) + case ADD_ARR(__) then + let type = match ty case T_ARRAY(ty=T_INTEGER(__)) then "integer_array" + case T_ARRAY(ty=T_ENUMERATION(__)) then "integer_array" + else "real_array" + 'add_alloc_<%type%>(<%e1%>, <%e2%>)' + case SUB_ARR(__) then + let type = match ty case T_ARRAY(ty=T_INTEGER(__)) then "integer_array" + case T_ARRAY(ty=T_ENUMERATION(__)) then "integer_array" + else "real_array" + 'sub_alloc_<%type%>(<%e1%>, <%e2%>)' + case MUL_ARR(__) then + let type = match ty case T_ARRAY(ty=T_INTEGER(__)) then "integer_array" + case T_ARRAY(ty=T_ENUMERATION(__)) then "integer_array" + else "real_array" + 'mul_alloc_<%type%>(<%e1%>, <%e2%>)' + case DIV_ARR(__) then + let type = match ty case T_ARRAY(ty=T_INTEGER(__)) then "integer_array" + case T_ARRAY(ty=T_ENUMERATION(__)) then "integer_array" + else "real_array" + 'div_alloc_<%type%>(<%e1%>, <%e2%>)' + case MUL_ARRAY_SCALAR(__) then + let type = match ty case T_ARRAY(ty=T_INTEGER(__)) then "integer_array" + case T_ARRAY(ty=T_ENUMERATION(__)) then "integer_array" + else "real_array" + 'mul_alloc_<%type%>_scalar(<%e1%>, <%e2%>)' + case ADD_ARRAY_SCALAR(__) then error(sourceInfo(),'Code generation does not support ADD_ARRAY_SCALAR <%printExpStr(exp)%>') + case SUB_SCALAR_ARRAY(__) then error(sourceInfo(),'Code generation does not support SUB_SCALAR_ARRAY <%printExpStr(exp)%>') + case MUL_SCALAR_PRODUCT(__) then + let type = match ty case T_ARRAY(ty=T_INTEGER(__)) then "integer_scalar" + case T_ARRAY(ty=T_ENUMERATION(__)) then "integer_scalar" + case T_INTEGER(__) then "integer_scalar" + case T_ENUMERATION(__) then "integer_scalar" + else "real_scalar" + 'mul_<%type%>_product(<%e1%>, <%e2%>)' + case MUL_MATRIX_PRODUCT(__) then + let typeShort = match ty case T_ARRAY(ty=T_INTEGER(__)) then "integer" + case T_ARRAY(ty=T_ENUMERATION(__)) then "integer" + else "real" + let type = '<%typeShort%>_array' + 'mul_alloc_<%typeShort%>_matrix_product_smart(<%e1%>, <%e2%>)' + case DIV_ARRAY_SCALAR(__) then + let type = match ty case T_ARRAY(ty=T_INTEGER(__)) then "integer_array" + case T_ARRAY(ty=T_ENUMERATION(__)) then "integer_array" + else "real_array" + 'div_alloc_<%type%>_scalar(<%e1%>, <%e2%>)' + case DIV_SCALAR_ARRAY(__) then + let type = match ty case T_ARRAY(ty = T_INTEGER(__)) then "integer_array" + case T_ARRAY(ty = T_ENUMERATION(__)) then "integer_array" + else "real_array" + 'div_alloc_scalar_<%type%>(<%e1%>, <%e2%>)' + case POW_ARRAY_SCALAR(__) then + let type = match ty case T_ARRAY(ty = T_INTEGER(__)) then "integer_array" + case T_ARRAY(ty = T_ENUMERATION(__)) then "integer_array" + else "real_array" + 'pow_alloc_<%type%>_scalar(<%e1%>, <%e2%>)' + case POW_ARRAY_SCALAR(__) then 'daeExpBinary:ERR for POW_ARRAY_SCALAR' + case POW_SCALAR_ARRAY(__) then 'daeExpBinary:ERR for POW_SCALAR_ARRAY' + case POW_ARR(__) then 'daeExpBinary:ERR for POW_ARR' + case POW_ARR2(__) then 'daeExpBinary:ERR for POW_ARR2' + else error(sourceInfo(), 'daeExpBinary:ERR') +end daeExpBinary; + + +template daeExpUnary(Exp exp, Context context, Text &preExp, + Text &varDecls, Text &auxFunction) + "Generates code for a unary expression." +::= +match exp +case UNARY(__) then + let e = daeExp(exp, context, &preExp, &varDecls, &auxFunction) + match operator + case UMINUS(__) then '(-<%e%>)' + case UMINUS_ARR(ty=T_ARRAY(ty=T_REAL(__))) then + let var = tempDecl("real_array", &varDecls) + let &preExp += 'usub_alloc_real_array(<%e%>,&<%var%>);<%\n%>' + '<%var%>' + case UMINUS_ARR(ty=T_ARRAY(ty=T_INTEGER(__))) then + let var = tempDecl("integer_array", &varDecls) + let &preExp += 'usub_alloc_integer_array(<%e%>,&<%var%>);<%\n%>' + '<%var%>' + case UMINUS_ARR(__) then error(sourceInfo(),"unary minus for non-real arrays not implemented") + else error(sourceInfo(),"daeExpUnary:ERR") +end daeExpUnary; + + +template daeExpLbinary(Exp exp, Context context, Text &preExp, + Text &varDecls, Text &auxFunction) + "Generates code for a logical binary expression." +::= +match exp +case LBINARY(__) then + let e1 = daeExp(exp1, context, &preExp, &varDecls, &auxFunction) + let e2 = daeExp(exp2, context, &preExp, &varDecls, &auxFunction) + match operator + case AND(ty = T_ARRAY(__)) then + let var = tempDecl("boolean_array", &varDecls) + let &preExp += 'and_boolean_array(&<%e1%>,&<%e2%>,&<%var%>);<%\n%>' + '<%var%>' + case AND(__) then + '(<%e1%> && <%e2%>)' + case OR(ty = T_ARRAY(__)) then + let var = tempDecl("boolean_array", &varDecls) + let &preExp += 'or_boolean_array(&<%e1%>,&<%e2%>,&<%var%>);<%\n%>' + '<%var%>' + case OR(__) then + '(<%e1%> || <%e2%>)' + else error(sourceInfo(),"daeExpLbinary:ERR") +end daeExpLbinary; + + +template daeExpLunary(Exp exp, Context context, Text &preExp, + Text &varDecls, Text &auxFunction) + "Generates code for a logical unary expression." +::= +match exp +case LUNARY(__) then + let e = daeExp(exp, context, &preExp, &varDecls, &auxFunction) + match operator + case NOT(ty = T_ARRAY(__)) then + let var = tempDecl("boolean_array", &varDecls) + let &preExp += 'not_boolean_array(<%e%>,&<%var%>);<%\n%>' + '<%var%>' + else + '(!<%e%>)' +end daeExpLunary; + + +template daeExpRelation(Exp exp, Context context, Text &preExp, + Text &varDecls, Text &auxFunction) + "Generates code for a relation expression." +::= +match exp +case rel as RELATION(__) then + let &varDecls2 = buffer "" + let &preExp2 = buffer "" + let simRel = daeExpRelationSim(rel, context, &preExp2, &varDecls2, &auxFunction) + if simRel then + /* Don't add the allocated temp-var unless it is used */ + let &varDecls += varDecls2 + let &preExp += preExp2 + simRel + else + let e1 = daeExp(rel.exp1, context, &preExp, &varDecls, &auxFunction) + let e2 = daeExp(rel.exp2, context, &preExp, &varDecls, &auxFunction) + match rel.operator + + case LESS(ty = T_BOOL(__)) then '(!<%e1%> && <%e2%>)' + case LESS(ty = T_STRING(__)) then '(stringCompare(<%e1%>, <%e2%>) < 0)' + case LESS(ty = T_INTEGER(__)) then '(<%e1%> < <%e2%>)' + case LESS(ty = T_REAL(__)) then '(<%e1%> < <%e2%>)' + case LESS(ty = T_ENUMERATION(__)) then '(<%e1%> < <%e2%>)' + + case GREATER(ty = T_BOOL(__)) then '(<%e1%> && !<%e2%>)' + case GREATER(ty = T_STRING(__)) then '(stringCompare(<%e1%>, <%e2%>) > 0)' + case GREATER(ty = T_INTEGER(__)) then '(<%e1%> > <%e2%>)' + case GREATER(ty = T_REAL(__)) then '(<%e1%> > <%e2%>)' + case GREATER(ty = T_ENUMERATION(__)) then '(<%e1%> > <%e2%>)' + + case LESSEQ(ty = T_BOOL(__)) then '(!<%e1%> || <%e2%>)' + case LESSEQ(ty = T_STRING(__)) then '(stringCompare(<%e1%>, <%e2%>) <= 0)' + case LESSEQ(ty = T_INTEGER(__)) then '(<%e1%> <= <%e2%>)' + case LESSEQ(ty = T_REAL(__)) then '(<%e1%> <= <%e2%>)' + case LESSEQ(ty = T_ENUMERATION(__)) then '(<%e1%> <= <%e2%>)' + + case GREATEREQ(ty = T_BOOL(__)) then '(<%e1%> || !<%e2%>)' + case GREATEREQ(ty = T_STRING(__)) then '(stringCompare(<%e1%>, <%e2%>) >= 0)' + case GREATEREQ(ty = T_INTEGER(__)) then '(<%e1%> >= <%e2%>)' + case GREATEREQ(ty = T_REAL(__)) then '(<%e1%> >= <%e2%>)' + case GREATEREQ(ty = T_ENUMERATION(__)) then '(<%e1%> >= <%e2%>)' + + case EQUAL(ty = T_BOOL(__)) then '((!<%e1%> && !<%e2%>) || (<%e1%> && <%e2%>))' + case EQUAL(ty = T_STRING(__)) then '(stringEqual(<%e1%>, <%e2%>))' + case EQUAL(ty = T_INTEGER(__)) then '(<%e1%> == <%e2%>)' + case EQUAL(ty = T_REAL(__)) then '(<%e1%> == <%e2%>)' + case EQUAL(ty = T_ENUMERATION(__)) then '(<%e1%> == <%e2%>)' + case EQUAL(ty = T_ARRAY(__)) then '<%e2%>' /* Used for Boolean array. Called from daeExpLunary. */ + + case NEQUAL(ty = T_BOOL(__)) then '((!<%e1%> && <%e2%>) || (<%e1%> && !<%e2%>))' + case NEQUAL(ty = T_STRING(__)) then '(!stringEqual(<%e1%>, <%e2%>))' + case NEQUAL(ty = T_INTEGER(__)) then '(<%e1%> != <%e2%>)' + case NEQUAL(ty = T_REAL(__)) then '(<%e1%> != <%e2%>)' + case NEQUAL(ty = T_ENUMERATION(__)) then '(<%e1%> != <%e2%>)' + + else error(sourceInfo(), 'daeExpRelation <%printExpStr(exp)%>') +end daeExpRelation; + + + +template daeExpRelationSim(Exp exp, Context context, Text &preExp, + Text &varDecls, Text &auxFunction) + "Helper to daeExpRelation." +::= +match exp +case rel as RELATION(__) then + match context + case SIMULATION_CONTEXT(__) then + match rel.optionExpisASUB + case NONE() then + let e1 = daeExp(rel.exp1, context, &preExp, &varDecls, &auxFunction) + let e2 = daeExp(rel.exp2, context, &preExp, &varDecls, &auxFunction) + let res = tempDecl("modelica_boolean", &varDecls) + if intEq(rel.index,-1) then + match rel.operator + case LESS(__) then + let &preExp += '<%res%> = Less(<%e1%>,<%e2%>);<%\n%>' + res + case LESSEQ(__) then + let &preExp += '<%res%> = LessEq(<%e1%>,<%e2%>);<%\n%>' + res + case GREATER(__) then + let &preExp += '<%res%> = Greater(<%e1%>,<%e2%>);<%\n%>' + res + case GREATEREQ(__) then + let &preExp += '<%res%> = GreaterEq(<%e1%>,<%e2%>);<%\n%>' + res + end match + else + let isReal = if isRealType(typeof(rel.exp1)) then (if isRealType(typeof(rel.exp2)) then 'true' else '') else '' + let hysteresisfunction = if isReal then 'RELATIONHYSTERESIS' else 'RELATION' + match rel.operator + case LESS(__) then + let &preExp += '<%hysteresisfunction%>(<%res%>, <%e1%>, <%e2%>, <%rel.index%>, Less);<%\n%>' + res + case LESSEQ(__) then + let &preExp += '<%hysteresisfunction%>(<%res%>, <%e1%>, <%e2%>, <%rel.index%>, LessEq);<%\n%>' + res + case GREATER(__) then + let &preExp += '<%hysteresisfunction%>(<%res%>, <%e1%>, <%e2%>, <%rel.index%>, Greater);<%\n%>' + res + case GREATEREQ(__) then + let &preExp += '<%hysteresisfunction%>(<%res%>, <%e1%>, <%e2%>, <%rel.index%>, GreaterEq);<%\n%>' + res + end match + case SOME((exp,i,j)) then + let e1 = daeExp(rel.exp1, context, &preExp, &varDecls, &auxFunction) + let e2 = daeExp(rel.exp2, context, &preExp, &varDecls, &auxFunction) + let iterator = daeExp(exp, context, &preExp, &varDecls, &auxFunction) + let res = tempDecl("modelica_boolean", &varDecls) + if intEq(rel.index,-1) then + match rel.operator + case LESS(__) then + let &preExp += '<%res%> = Less(<%e1%>,<%e2%>);<%\n%>' + res + case LESSEQ(__) then + let &preExp += '<%res%> = LessEq(<%e1%>,<%e2%>);<%\n%>' + res + case GREATER(__) then + let &preExp += '<%res%> = Greater(<%e1%>,<%e2%>);<%\n%>' + res + case GREATEREQ(__) then + let &preExp += '<%res%> = GreaterEq(<%e1%>,<%e2%>);<%\n%>' + res + end match + else + let isReal = if isRealType(typeof(rel.exp1)) then (if isRealType(typeof(rel.exp2)) then 'true' else '') else '' + let hysteresisfunction = if isReal then 'RELATIONHYSTERESIS' else 'RELATION' + match rel.operator + case LESS(__) then + let &preExp += '<%hysteresisfunction%>(<%res%>, <%e1%>, <%e2%>, <%rel.index%> + (<%iterator%> - <%i%>)/<%j%>, Less);<%\n%>' + res + case LESSEQ(__) then + let &preExp += '<%hysteresisfunction%>(<%res%>, <%e1%>, <%e2%>, <%rel.index%> + (<%iterator%> - <%i%>)/<%j%>, LessEq);<%\n%>' + res + case GREATER(__) then + let &preExp += '<%hysteresisfunction%>(<%res%>, <%e1%>, <%e2%>, <%rel.index%> + (<%iterator%> - <%i%>)/<%j%>, Greater);<%\n%>' + res + case GREATEREQ(__) then + let &preExp += '<%hysteresisfunction%>(<%res%>, <%e1%>, <%e2%>, <%rel.index%> + (<%iterator%> - <%i%>)/<%j%>, GreaterEq);<%\n%>' + res + end match + end match + case ZEROCROSSINGS_CONTEXT(__) then + match rel.optionExpisASUB + case NONE() then + let e1 = daeExp(rel.exp1, context, &preExp, &varDecls, &auxFunction) + let e2 = daeExp(rel.exp2, context, &preExp, &varDecls, &auxFunction) + let res = tempDecl("modelica_boolean", &varDecls) + if intEq(rel.index,-1) then + match rel.operator + case LESS(__) then + let &preExp += '<%res%> = Less(<%e1%>,<%e2%>);<%\n%>' + res + case LESSEQ(__) then + let &preExp += '<%res%> = LessEq(<%e1%>,<%e2%>);<%\n%>' + res + case GREATER(__) then + let &preExp += '<%res%> = Greater(<%e1%>,<%e2%>);<%\n%>' + res + case GREATEREQ(__) then + let &preExp += '<%res%> = GreaterEq(<%e1%>,<%e2%>);<%\n%>' + res + end match + else + let isReal = if isRealType(typeof(rel.exp1)) then (if isRealType(typeof(rel.exp2)) then 'true' else '') else '' + match rel.operator + case LESS(__) then + let hysteresisfunction = if isReal then 'LessZC(<%e1%>, <%e2%>, data->simulationInfo.storedRelations[<%rel.index%>])' else 'Less(<%e1%>,<%e2%>)' + let &preExp += '<%res%> = <%hysteresisfunction%>;<%\n%>' + res + case LESSEQ(__) then + let hysteresisfunction = if isReal then 'LessEqZC(<%e1%>, <%e2%>, data->simulationInfo.storedRelations[<%rel.index%>])' else 'LessEq(<%e1%>,<%e2%>)' + let &preExp += '<%res%> = <%hysteresisfunction%>;<%\n%>' + res + case GREATER(__) then + let hysteresisfunction = if isReal then 'GreaterZC(<%e1%>, <%e2%>, data->simulationInfo.storedRelations[<%rel.index%>])' else 'Greater(<%e1%>,<%e2%>)' + let &preExp += '<%res%> = <%hysteresisfunction%>;<%\n%>' + res + case GREATEREQ(__) then + let hysteresisfunction = if isReal then 'GreaterEqZC(<%e1%>, <%e2%>, data->simulationInfo.storedRelations[<%rel.index%>])' else 'GreaterEq(<%e1%>,<%e2%>)' + let &preExp += '<%res%> = <%hysteresisfunction%>;<%\n%>' + res + end match + case SOME((exp,i,j)) then + let e1 = daeExp(rel.exp1, context, &preExp, &varDecls, &auxFunction) + let e2 = daeExp(rel.exp2, context, &preExp, &varDecls, &auxFunction) + let res = tempDecl("modelica_boolean", &varDecls) + if intEq(rel.index,-1) then + match rel.operator + case LESS(__) then + let &preExp += '<%res%> = Less(<%e1%>,<%e2%>);<%\n%>' + res + case LESSEQ(__) then + let &preExp += '<%res%> = LessEq(<%e1%>,<%e2%>);<%\n%>' + res + case GREATER(__) then + let &preExp += '<%res%> = Greater(<%e1%>,<%e2%>);<%\n%>' + res + case GREATEREQ(__) then + let &preExp += '<%res%> = GreaterEq(<%e1%>,<%e2%>);<%\n%>' + res + end match + else + let isReal = if isRealType(typeof(rel.exp1)) then (if isRealType(typeof(rel.exp2)) then 'true' else '') else '' + match rel.operator + case LESS(__) then + let hysteresisfunction = if isReal then 'LessZC(<%e1%>, <%e2%>, data->simulationInfo.storedRelations[<%rel.index%>])' else 'Less(<%e1%>,<%e2%>)' + let &preExp += '<%res%> = <%hysteresisfunction%>;<%\n%>' + res + case LESSEQ(__) then + let hysteresisfunction = if isReal then 'LessEqZC(<%e1%>, <%e2%>, data->simulationInfo.storedRelations[<%rel.index%>])' else 'LessEq(<%e1%>,<%e2%>)' + let &preExp += '<%res%> = <%hysteresisfunction%>;<%\n%>' + res + case GREATER(__) then + let hysteresisfunction = if isReal then 'GreaterZC(<%e1%>, <%e2%>, data->simulationInfo.storedRelations[<%rel.index%>])' else 'Greater(<%e1%>,<%e2%>)' + let &preExp += '<%res%> = <%hysteresisfunction%>;<%\n%>' + res + case GREATEREQ(__) then + let hysteresisfunction = if isReal then 'GreaterEqZC(<%e1%>, <%e2%>, data->simulationInfo.storedRelations[<%rel.index%>])' else 'GreaterEq(<%e1%>,<%e2%>)' + let &preExp += '<%res%> = <%hysteresisfunction%>;<%\n%>' + res + end match + end match + end match +end match +end daeExpRelationSim; + +template daeExpIf(Exp exp, Context context, Text &preExp, + Text &varDecls, Text &auxFunction) + "Generates code for an if expression." +::= +match exp +case IFEXP(__) then + let condExp = daeExp(expCond, context, &preExp, &varDecls, &auxFunction) + let &preExpThen = buffer "" + let eThen = daeExp(expThen, context, &preExpThen, &varDecls, &auxFunction) + let &preExpElse = buffer "" + let eElse = daeExp(expElse, context, &preExpElse, &varDecls, &auxFunction) + let shortIfExp = if preExpThen then "" else if preExpElse then "" else if isArrayType(typeof(exp)) then "" else "x" + (if shortIfExp + then + // Safe to do if eThen and eElse don't emit pre-expressions + '(<%condExp%>?<%eThen%>:<%eElse%>)' + else + let condVar = tempDecl("modelica_boolean", &varDecls) + let resVar = tempDeclTuple(typeof(exp), &varDecls) + let &preExp += + << + <%condVar%> = (modelica_boolean)<%condExp%>; + if(<%condVar%>) + { + <%preExpThen%> + <%if eThen then resultVarAssignment(typeof(exp),resVar,eThen)%> + } + else + { + <%preExpElse%> + <%if eElse then resultVarAssignment(typeof(exp),resVar,eElse)%> + }<%\n%> + >> + resVar) +end daeExpIf; + +template daeExpSum(Exp exp, Context context, Text &preExp, + Text &varDecls, Text &auxFunction) + "Generates code for an if expression." +::= +match exp +case SUM(__) then + let start = printExpStr(startIt) + let &anotherPre = buffer "" + let stop = printExpStr(endIt) + let bodyStr = daeExpIteratedCref(body) + let summationVar = <> + let iterVar = printExpStr(iterator) + let &preExp +=<< + + modelica_integer $P<%iterVar%> = 0; // the iterator + modelica_real <%summationVar%> = 0.0; //the sum + for($P<%iterVar%> = <%start%>; $P<%iterVar%> < <%stop%>; $P<%iterVar%>++) + { + <%summationVar%> += <%bodyStr%>($P<%iterVar%>); + } + + >> + summationVar +end daeExpSum; + +template daeExpIteratedCref(Exp exp) +::= +match exp +case (CREF(__)) then + let subs = (crefSubs(componentRef) |> sub => subscriptToCStr(sub) ; separator=",") + <<<%iteratedCrefStr(componentRef)%>_index>> +end daeExpIteratedCref; + +template iteratedCrefStr(ComponentRef cref) +::= +match cref +case (CREF_IDENT(__)) then + <<$P<%ident%>>> +case (CREF_QUAL(__)) then + <<$P<%ident%><%iteratedCrefStr(componentRef)%>>> +end iteratedCrefStr; + +template resultVarAssignment(DAE.Type ty, Text lhs, Text rhs) "Tuple need to be considered" +::= +match ty +case T_TUPLE(__) then + (types |> t hasindex i1 fromindex 1 => '<%lhs%>.c<%i1%> = <%rhs%>.c<%i1%>;' ; separator="\n") +else + '<%lhs%> = <%rhs%>;' +end resultVarAssignment; + +template daeExpRecord(Exp rec, Context context, Text &preExp, Text &varDecls, Text &auxFunction) +::= + match rec + case RECORD(__) then + let name = tempDecl(underscorePath(path), &varDecls) + let ass = threadTuple(exps,comp) |> (exp,compn) => '<%name%>._<%compn%> = <%daeExp(exp, context, &preExp, &varDecls, &auxFunction)%>;<%\n%>' + let &preExp += ass + name +end daeExpRecord; + +template daeExpPartEvalFunction(Exp exp, Context context, Text &preExp, Text &varDecls, Text &auxFunction) +::= + match exp + case PARTEVALFUNCTION(ty=T_FUNCTION_REFERENCE_VAR(functionType = t as T_FUNCTION(__)),origType=T_FUNCTION_REFERENCE_VAR(functionType = orig as T_FUNCTION(functionAttributes=attr as FUNCTION_ATTRIBUTES(__), source={name}))) then + let &varDeclInner = buffer "" + let &ret = buffer "" + let retInput = match t.funcResultType + case T_TUPLE(types=_::tys) then + (tys |> ty => + let name = 'tmp<%System.tmpTick()%>' + let &ret += ', <%name%>' + ', <%expTypeArrayIf(ty)%> <%name%>') + let func = 'closure<%System.tmpTickIndex(2/*auxFunction*/)%>_<%underscorePath(name)%>' + let return = match t.funcResultType case T_NORETCALL(__) then "" else "return " + let closure = tempDecl("modelica_metatype",&varDecls) + let createClosure = (expList |> e => ', <%daeExp(e,context,&preExp,&varDecls,&auxFunction)%>') + (if attr.isFunctionPointer then ', _<%underscorePath(name)%>') + let &preExp += '<%closure%> = mmc_mk_box<%if attr.isFunctionPointer then daeExpMetaHelperBoxStart(incrementInt(listLength(expList),1)) else daeExpMetaHelperBoxStart(listLength(expList))%>0<%createClosure%>);<%\n%>' + let &auxFunction += + << + static <%match t.funcResultType case T_NORETCALL(__) then "void" else "modelica_metatype"%> <%func%>(threadData_t *thData, modelica_metatype closure<%t.funcArg |> a as FUNCARG(__) => ', <%expTypeArrayIf(a.ty)%> <%a.name%>'%><%retInput%>) + { + <%varDeclInner%> + <%setDifference(orig.funcArg,t.funcArg) |> a as FUNCARG(__) hasindex i1 fromindex 1 => '<%expTypeArrayIf(a.ty)%> <%a.name%> = MMC_FETCH(MMC_OFFSET(MMC_UNTAGPTR(closure),<%i1%>));<%\n%>'%> + <% + if attr.isFunctionPointer then + let fname = '_<%underscorePath(name)%>' + let func = '(MMC_FETCH(MMC_OFFSET(MMC_UNTAGPTR(<%fname%>), 1)))' + let typeCast1 = generateTypeCastFromType(orig, true) + let typeCast2 = generateTypeCastFromType(orig, false) + << + modelica_fnptr <%fname%> = MMC_FETCH(MMC_OFFSET(MMC_UNTAGPTR(closure),<%incrementInt(listLength(setDifference(orig.funcArg,t.funcArg)),1)%>)); + if (MMC_FETCH(MMC_OFFSET(MMC_UNTAGPTR(<%fname%>),2))) { + <%return%> (<%typeCast1%> <%func%>) (thData, MMC_FETCH(MMC_OFFSET(MMC_UNTAGPTR(<%fname%>),2))<%orig.funcArg |> a as FUNCARG(__) => ', <%a.name%>'%><%ret%>); + } else { /* No closure in the called variable */ + <%return%> (<%typeCast2%> <%func%>) (thData<%orig.funcArg |> a as FUNCARG(__) => ', <%a.name%>'%><%ret%>); + } + >> + else + '<%return%>boxptr_<%underscorePath(name)%>(thData<%orig.funcArg |> a as FUNCARG(__) => ', <%a.name%>'%><%ret%>);' + %> + } + >> + '(modelica_fnptr) mmc_mk_box2(0,<%func%>,<%closure%>)' + // error(sourceInfo(), 'PARTEVALFUNCTION: <%ExpressionDump.printExpStr(exp)%>, ty=<%unparseType(ty)%>, origType=<%unparseType(origType)%>') + case PARTEVALFUNCTION(__) then + error(sourceInfo(), 'PARTEVALFUNCTION: <%ExpressionDump.printExpStr(exp)%>, ty=<%unparseType(ty)%>, origType=<%unparseType(origType)%>') +end daeExpPartEvalFunction; + +template daeExpCall(Exp call, Context context, Text &preExp, Text &varDecls, Text &auxFunction) + "Generates code for a function call." +::= + match call + // special builtins + case CALL(path=IDENT(name="smooth"), + expLst={e1, e2}) then + let var1 = daeExp(e1, context, &preExp, &varDecls, &auxFunction) + let var2 = daeExp(e2, context, &preExp, &varDecls, &auxFunction) + '<%var2%>' + + case CALL(path=IDENT(name="DIVISION"), + expLst={e1, e2}) then + let var1 = daeExp(e1, context, &preExp, &varDecls, &auxFunction) + let var2 = daeExp(e2, context, &preExp, &varDecls, &auxFunction) + let var3 = Util.escapeModelicaStringToCString(printExpStr(e2)) + (match context + case FUNCTION_CONTEXT(__) then + 'DIVISION(<%var1%>,<%var2%>,"<%var3%>")' + else + 'DIVISION_SIM(<%var1%>,<%var2%>,"<%var3%>",equationIndexes)' + ) + + case CALL(attr=CALL_ATTR(ty=ty), + path=IDENT(name="DIVISION_ARRAY_SCALAR"), + expLst={e1, e2}) then + let type = match ty case T_ARRAY(ty=T_INTEGER(__)) then "integer_array" + case T_ARRAY(ty=T_ENUMERATION(__)) then "integer_array" + else "real_array" + let var1 = daeExp(e1, context, &preExp, &varDecls, &auxFunction) + let var2 = daeExp(e2, context, &preExp, &varDecls, &auxFunction) + let var3 = Util.escapeModelicaStringToCString(printExpStr(e2)) + 'division_alloc_<%type%>_scalar(threadData,<%var1%>,<%var2%>,"<%var3%>")' + + case exp as CALL(attr=CALL_ATTR(ty=ty), path=IDENT(name="DIVISION_ARRAY_SCALAR")) then + error(sourceInfo(),'Code generation does not support <%printExpStr(exp)%>') + + case CALL(path=IDENT(name="der"), expLst={arg as CREF(__)}) then + '$P$DER<%cref(arg.componentRef)%>' + case CALL(path=IDENT(name="der"), expLst={exp}) then + error(sourceInfo(), 'Code generation does not support der(<%printExpStr(exp)%>)') + case CALL(path=IDENT(name="pre"), expLst={arg}) then + daeExpCallPre(arg, context, preExp, varDecls, &auxFunction) + // a $_start is used to get get start value of a variable + case CALL(path=IDENT(name="$_start"), expLst={arg}) then + daeExpCallStart(arg, context, preExp, varDecls, &auxFunction) + // a $_initialGuess is used to get initial guess for nonlinear solver + case CALL(path=IDENT(name="$_initialGuess"), expLst={arg as CREF(__)}) then + let namestr = cref(arg.componentRef) + '( <%namestr%>)' // + case CALL(path=IDENT(name="$_old"), expLst={arg as CREF(__)}) then + let namestr = cref(arg.componentRef) + '( _<%namestr%>(1))' // + // if arg >= 0 then 1 else -1 + case CALL(path=IDENT(name="$_signNoNull"), expLst={e1}) then + let var1 = daeExp(e1, context, &preExp, &varDecls, &auxFunction) + '(<%var1%> >= 0.0 ? 1.0:-1.0)' + // numerical der() + case CALL(path=IDENT(name="$_DF$DER"), expLst={arg as CREF(__)}) then + let namestr = cref(arg.componentRef) + '($P<%BackendDAE.symEulerDT%> == 0.0 ? $P$DER<%namestr%> : (<%namestr%> - _<%namestr%>(1))/$P<%BackendDAE.symEulerDT%>)' + // round + case CALL(path=IDENT(name="$_round"), expLst={e1}) then + let var1 = daeExp(e1, context, &preExp, &varDecls, &auxFunction) + '((modelica_integer)round((modelica_real)<%var1%>))' + case CALL(path=IDENT(name="edge"), expLst={arg as CREF(__)}) then + '(<%cref(arg.componentRef)%> && !$P$PRE<%cref(arg.componentRef)%>)' + case CALL(path=IDENT(name="edge"), expLst={LUNARY(exp = arg as CREF(__))}) then + '(!<%cref(arg.componentRef)%> && $P$PRE<%cref(arg.componentRef)%>)' + case CALL(path=IDENT(name="edge"), expLst={exp}) then + error(sourceInfo(), 'Code generation does not support edge(<%printExpStr(exp)%>)') + case CALL(path=IDENT(name="change"), expLst={arg as CREF(__)}) then + '(<%cref(arg.componentRef)%> != $P$PRE<%cref(arg.componentRef)%>)' + case CALL(path=IDENT(name="change"), expLst={exp}) then + error(sourceInfo(), 'Code generation does not support change(<%printExpStr(exp)%>)') + case CALL(path=IDENT(name="cardinality"), expLst={exp}) then + error(sourceInfo(), 'Code generation does not support cardinality(<%printExpStr(exp)%>). It should have been handled somewhere else in the compiler.') + + case CALL(path=IDENT(name="print"), expLst={e1}) then + let var1 = daeExp(e1, context, &preExp, &varDecls, &auxFunction) + 'fputs(MMC_STRINGDATA(<%var1%>),stdout)' + + case CALL(path=IDENT(name="max"), attr=CALL_ATTR(ty = T_REAL(__)), expLst={e1,e2}) then + let var1 = daeExp(e1, context, &preExp, &varDecls, &auxFunction) + let var2 = daeExp(e2, context, &preExp, &varDecls, &auxFunction) + 'fmax(<%var1%>,<%var2%>)' + + case CALL(path=IDENT(name="max"), expLst={e1,e2}) then + let var1 = daeExp(e1, context, &preExp, &varDecls, &auxFunction) + let var2 = daeExp(e2, context, &preExp, &varDecls, &auxFunction) + 'modelica_integer_max((modelica_integer)<%var1%>,(modelica_integer)<%var2%>)' + + case CALL(path=IDENT(name="sum"), attr=CALL_ATTR(ty = ty), expLst={e}) then + let arr = daeExp(e, context, &preExp, &varDecls, &auxFunction) + let ty_str = '<%expTypeArray(ty)%>' + 'sum_<%ty_str%>(<%arr%>)' + + case CALL(path=IDENT(name="min"), attr=CALL_ATTR(ty = T_REAL(__)), expLst={e1,e2}) then + let var1 = daeExp(e1, context, &preExp, &varDecls, &auxFunction) + let var2 = daeExp(e2, context, &preExp, &varDecls, &auxFunction) + 'fmin(<%var1%>,<%var2%>)' + + case CALL(path=IDENT(name="min"), expLst={e1,e2}) then + let var1 = daeExp(e1, context, &preExp, &varDecls, &auxFunction) + let var2 = daeExp(e2, context, &preExp, &varDecls, &auxFunction) + 'modelica_integer_min((modelica_integer)<%var1%>,(modelica_integer)<%var2%>)' + + case CALL(path=IDENT(name="abs"), expLst={e1}, attr=CALL_ATTR(ty = T_INTEGER(__))) then + let var1 = daeExp(e1, context, &preExp, &varDecls, &auxFunction) + 'labs(<%var1%>)' + + case CALL(path=IDENT(name="abs"), expLst={e1}) then + let var1 = daeExp(e1, context, &preExp, &varDecls, &auxFunction) + 'fabs(<%var1%>)' + + case CALL(path=IDENT(name="sqrt"), expLst={e1}, attr=attr as CALL_ATTR(__)) then + let argStr = daeExp(e1, context, &preExp, &varDecls, &auxFunction) + (if isPositiveOrZero(e1) + then + 'sqrt(<%argStr%>)' + else + let tmp = tempDecl(expTypeFromExpModelica(e1),&varDecls) + let ass = '(<%tmp%> >= 0.0)' + let &preExpMsg = buffer "" + let retPre = assertCommonVar(ass,'"Model error: Argument of sqrt(<%Util.escapeModelicaStringToCString(printExpStr(e1))%>) was %g should be >= 0", <%tmp%>', context, &preExpMsg, &varDecls, dummyInfo) + let &preExp += '<%tmp%> = <%argStr%>; <%\n%><%retPre%>' + 'sqrt(<%tmp%>)') + + case CALL(path=IDENT(name="log"), expLst={e1}, attr=attr as CALL_ATTR(__)) then + let argStr = daeExp(e1, context, &preExp, &varDecls, &auxFunction) + let tmp = tempDecl(expTypeFromExpModelica(e1),&varDecls) + let ass = '(<%tmp%> > 0.0)' + let &preExpMsg = buffer "" + let retPre = assertCommonVar(ass,'"Model error: Argument of log(<%Util.escapeModelicaStringToCString(printExpStr(e1))%>) was %g should be > 0", <%tmp%>', context, &preExpMsg, &varDecls, dummyInfo) + let &preExp += '<%tmp%> = <%argStr%>;<%retPre%>' + 'log(<%tmp%>)' + + case CALL(path=IDENT(name="log10"), expLst={e1}, attr=attr as CALL_ATTR(__)) then + let argStr = daeExp(e1, context, &preExp, &varDecls, &auxFunction) + let tmp = tempDecl(expTypeFromExpModelica(e1),&varDecls) + let ass = '(<%tmp%> > 0.0)' + let &preExpMsg = buffer "" + let retPre = assertCommonVar(ass,'"Model error: Argument of log10(<%Util.escapeModelicaStringToCString(printExpStr(e1))%>) was %g should be > 0", <%tmp%>', context, &preExpMsg, &varDecls, dummyInfo) + let &preExp += '<%tmp%> = <%argStr%>;<%retPre%>' + 'log10(<%tmp%>)' + + case CALL(path=IDENT(name="acos"), expLst={e1}, attr=attr as CALL_ATTR(__)) then + let argStr = daeExp(e1, context, &preExp, &varDecls, &auxFunction) + let tmp = tempDecl("modelica_real",&varDecls) + let ass = '(<%tmp%> >= -1.0 && <%tmp%> <= 1.0)' + let &preExpMsg = buffer "" + let retPre = assertCommonVar(ass,'"Model error: Argument of <%Util.escapeModelicaStringToCString(printExpStr(call))%> outside the domain -1.0 <= %g <= 1.0", <%tmp%>', context, &preExpMsg, &varDecls, dummyInfo) + let &preExp += '<%tmp%> = <%argStr%>;<%retPre%>' + 'acos(<%tmp%>)' + + case CALL(path=IDENT(name="asin"), expLst={e1}, attr=attr as CALL_ATTR(__)) then + let argStr = daeExp(e1, context, &preExp, &varDecls, &auxFunction) + let tmp = tempDecl("modelica_real",&varDecls) + let ass = '(<%tmp%> >= -1.0 && <%tmp%> <= 1.0)' + let &preExpMsg = buffer "" + let retPre = assertCommonVar(ass,'"Model error: Argument of <%Util.escapeModelicaStringToCString(printExpStr(call))%> outside the domain -1.0 <= %g <= 1.0", <%tmp%>', context, &preExpMsg, &varDecls, dummyInfo) + let &preExp += '<%tmp%> = <%argStr%>;<%retPre%>' + 'asin(<%tmp%>)' + + /* Begin code generation of event triggering math functions */ + + case CALL(path=IDENT(name="div"), expLst={e1,e2, index}, attr=CALL_ATTR(ty = ty)) then + let var1 = daeExp(e1, context, &preExp, &varDecls, &auxFunction) + let var2 = daeExp(e2, context, &preExp, &varDecls, &auxFunction) + let constIndex = daeExp(index, context, &preExp, &varDecls, &auxFunction) + '_event_div_<%expTypeShort(ty)%>(<%var1%>, <%var2%>, <%constIndex%>, data)' + + case CALL(path=IDENT(name="integer"), expLst={inExp,index}) then + let exp = daeExp(inExp, context, &preExp, &varDecls, &auxFunction) + let constIndex = daeExp(index, context, &preExp, &varDecls, &auxFunction) + '(_event_integer(<%exp%>, <%constIndex%>, data))' + + case CALL(path=IDENT(name="floor"), expLst={inExp,index}, attr=CALL_ATTR(ty = ty)) then + let exp = daeExp(inExp, context, &preExp, &varDecls, &auxFunction) + let constIndex = daeExp(index, context, &preExp, &varDecls, &auxFunction) + '((modelica_<%expTypeShort(ty)%>)_event_floor(<%exp%>, <%constIndex%>, data))' + + case CALL(path=IDENT(name="ceil"), expLst={inExp,index}, attr=CALL_ATTR(ty = ty)) then + let exp = daeExp(inExp, context, &preExp, &varDecls, &auxFunction) + let constIndex = daeExp(index, context, &preExp, &varDecls, &auxFunction) + '((modelica_<%expTypeShort(ty)%>)_event_ceil(<%exp%>, <%constIndex%>, data))' + + /* end codegeneration of event triggering math functions */ + + case CALL(path=IDENT(name="integer"), expLst={inExp}) then + let exp = daeExp(inExp, context, &preExp, &varDecls, &auxFunction) + '((modelica_integer)floor(<%exp%>))' + + case CALL(path=IDENT(name="div"), expLst={e1,e2}, attr=CALL_ATTR(ty = T_INTEGER(__))) then + let var1 = daeExp(e1, context, &preExp, &varDecls, &auxFunction) + let var2 = daeExp(e2, context, &preExp, &varDecls, &auxFunction) + let tvar = tempDecl("modelica_integer", &varDecls) + let &preExp += '<%tvar%> = <%var2%>;<%\n%>' + let &preExp += + if acceptMetaModelicaGrammar() + then 'if (<%tvar%> == 0) {<%generateThrow()%>;}<%\n%>' + else 'if (<%tvar%> == 0) {throwStreamPrint(threadData, "Division by zero %s", "<%Util.escapeModelicaStringToCString(printExpStr(call))%>");}<%\n%>' + 'ldiv(<%var1%>,<%tvar%>).quot' + + case CALL(path=IDENT(name="div"), expLst={e1,e2}) then + let var1 = daeExp(e1, context, &preExp, &varDecls, &auxFunction) + let var2 = daeExp(e2, context, &preExp, &varDecls, &auxFunction) + let tvar = tempDecl("modelica_real", &varDecls) + let &preExp += '<%tvar%> = <%var2%>;<%\n%>' + let &preExp += + if acceptMetaModelicaGrammar() + then 'if (<%tvar%> == 0.0) {<%generateThrow()%>;}<%\n%>' + else 'if (<%tvar%> == 0.0) {throwStreamPrint(threadData, "Division by zero %s", "<%Util.escapeModelicaStringToCString(printExpStr(call))%>");}<%\n%>' + 'trunc(<%var1%>/<%var2%>)' + + case CALL(path=IDENT(name="mod"), expLst={e1,e2}, attr=CALL_ATTR(ty = ty)) then + let var1 = daeExp(e1, context, &preExp, &varDecls, &auxFunction) + let var2 = daeExp(e2, context, &preExp, &varDecls, &auxFunction) + 'modelica_mod_<%expTypeShort(ty)%>(<%var1%>,<%var2%>)' + + case CALL(path=IDENT(name="max"), attr=CALL_ATTR(ty = ty), expLst={array}) then + let expVar = daeExp(array, context, &preExp, &varDecls, &auxFunction) + let arr_tp_str = '<%expTypeArray(ty)%>' + let tvar = tempDecl(expTypeModelica(ty), &varDecls) + let &preExp += '<%tvar%> = max_<%arr_tp_str%>(<%expVar%>);<%\n%>' + '<%tvar%>' + + case CALL(path=IDENT(name="min"), attr=CALL_ATTR(ty = ty), expLst={array}) then + let expVar = daeExp(array, context, &preExp, &varDecls, &auxFunction) + let arr_tp_str = '<%expTypeArray(ty)%>' + let tvar = tempDecl(expTypeModelica(ty), &varDecls) + let &preExp += '<%tvar%> = min_<%arr_tp_str%>(<%expVar%>);<%\n%>' + '<%tvar%>' + + case CALL(path=IDENT(name="fill"), expLst=val::dims, attr=CALL_ATTR(ty = ty)) then + let valExp = daeExp(val, context, &preExp, &varDecls, &auxFunction) + let dimsExp = (dims |> dim => + daeExp(dim, context, &preExp, &varDecls, &auxFunction) ;separator=", ") + let ty_str = '<%expTypeArray(ty)%>' + let tvar = tempDecl(ty_str, &varDecls) + let &preExp += 'fill_alloc_<%ty_str%>(&<%tvar%>, <%valExp%>, <%listLength(dims)%>, <%dimsExp%>);<%\n%>' + '<%tvar%>' + + case call as CALL(path=IDENT(name="vector")) then + error(sourceInfo(),'vector() call does not have a C implementation <%printExpStr(call)%>') + + case CALL(path=IDENT(name="cat"), expLst=dim::arrays, attr=CALL_ATTR(ty = ty)) then + let dim_exp = daeExp(dim, context, &preExp, &varDecls, &auxFunction) + let arrays_exp = (arrays |> array => + daeExp(array, context, &preExp, &varDecls, &auxFunction) ;separator=", &") + let ty_str = '<%expTypeArray(ty)%>' + let tvar = tempDecl(ty_str, &varDecls) + let &preExp += 'cat_alloc_<%ty_str%>(<%dim_exp%>, &<%tvar%>, <%listLength(arrays)%>, &<%arrays_exp%>);<%\n%>' + '<%tvar%>' + + case CALL(path=IDENT(name="promote"), expLst={A, n}) then + let var1 = daeExp(A, context, &preExp, &varDecls, &auxFunction) + let var2 = daeExp(n, context, &preExp, &varDecls, &auxFunction) + let arr_tp_str = '<%expTypeFromExpArray(A)%>' + let tvar = tempDecl(arr_tp_str, &varDecls) + let &preExp += 'promote_alloc_<%arr_tp_str%>(&<%var1%>, <%var2%>, &<%tvar%>);<%\n%>' + '<%tvar%>' + + case CALL(path=IDENT(name="transpose"), expLst={A}) then + let var1 = daeExp(A, context, &preExp, &varDecls, &auxFunction) + let arr_tp_str = '<%expTypeFromExpArray(A)%>' + let tvar = tempDecl(arr_tp_str, &varDecls) + let &preExp += 'transpose_alloc_<%arr_tp_str%>(&<%var1%>, &<%tvar%>);<%\n%>' + '<%tvar%>' + + case CALL(path=IDENT(name="symmetric"), expLst={A}) then + let var1 = daeExp(A, context, &preExp, &varDecls, &auxFunction) + let arr_tp_str = '<%expTypeFromExpArray(A)%>' + let tvar = tempDecl(arr_tp_str, &varDecls) + let &preExp += 'symmetric_<%arr_tp_str%>(&<%var1%>, &<%tvar%>);<%\n%>' + '<%tvar%>' + + case CALL(path=IDENT(name="skew"), expLst={A}) then + let var1 = daeExp(A, context, &preExp, &varDecls, &auxFunction) + let arr_tp_str = '<%expTypeFromExpArray(A)%>' + let tvar = tempDecl(arr_tp_str, &varDecls) + let &preExp += 'skew_<%arr_tp_str%>(&<%var1%>, &<%tvar%>);<%\n%>' + '<%tvar%>' + + case CALL(path=IDENT(name="cross"), expLst={v1, v2}) then + let var1 = daeExp(v1, context, &preExp, &varDecls, &auxFunction) + let var2 = daeExp(v2, context, &preExp, &varDecls, &auxFunction) + let arr_tp_str = expTypeFromExpArray(v1) + let tvar = tempDecl(arr_tp_str, &varDecls) + let &preExp += 'cross_alloc_<%arr_tp_str%>(&<%var1%>, &<%var2%>, &<%tvar%>);<%\n%>' + '<%tvar%>' + + case CALL(path=IDENT(name="identity"), expLst={A}) then + let var1 = daeExp(A, context, &preExp, &varDecls, &auxFunction) + let arr_tp_str = expTypeFromExpArray(A) + let tvar = tempDecl(arr_tp_str, &varDecls) + let &preExp += 'identity_alloc_<%arr_tp_str%>(<%var1%>, &<%tvar%>);<%\n%>' + '<%tvar%>' + + case CALL(path=IDENT(name="diagonal"), expLst={A as ARRAY(__)}) then + let arr_tp_str = expTypeFromExpArray(A) + let tvar = tempDecl(arr_tp_str, &varDecls) + let params = (A.array |> e => + '<%daeExp(e, context, &preExp, &varDecls, &auxFunction)%>' + ;separator=", ") + let &preExp += 'diagonal_alloc_<%arr_tp_str%>(&<%tvar%>, <%listLength(A.array)%>, <%params%>);<%\n%>' + '<%tvar%>' + + case CALL(path=IDENT(name="String"), expLst={s, format}) then + let tvar = tempDecl("modelica_string", &varDecls) + let sExp = daeExp(s, context, &preExp, &varDecls, &auxFunction) + + let formatExp = daeExp(format, context, &preExp, &varDecls, &auxFunction) + let typeStr = expTypeFromExpModelica(s) + let &preExp += '<%tvar%> = <%typeStr%>_to_modelica_string_format(<%sExp%>, <%formatExp%>);<%\n%>' + '<%tvar%>' + + case CALL(path=IDENT(name="String"), expLst={s, minlen, leftjust}) then + let tvar = tempDecl("modelica_string", &varDecls) + let sExp = daeExp(s, context, &preExp, &varDecls, &auxFunction) + let minlenExp = daeExp(minlen, context, &preExp, &varDecls, &auxFunction) + let leftjustExp = daeExp(leftjust, context, &preExp, &varDecls, &auxFunction) + let typeStr = expTypeFromExpModelica(s) + match typeStr + case "modelica_real" then + let &preExp += '<%tvar%> = <%typeStr%>_to_modelica_string(<%sExp%>, <%minlenExp%>, <%leftjustExp%>, 6);<%\n%>' + '<%tvar%>' + else + let &preExp += '<%tvar%> = <%typeStr%>_to_modelica_string(<%sExp%>, <%minlenExp%>, <%leftjustExp%>);<%\n%>' + '<%tvar%>' + end match + + case CALL(path=IDENT(name="String"), expLst={s, minlen, leftjust, signdig}) then + let tvar = tempDecl("modelica_string", &varDecls) + let sExp = daeExp(s, context, &preExp, &varDecls, &auxFunction) + let minlenExp = daeExp(minlen, context, &preExp, &varDecls, &auxFunction) + let leftjustExp = daeExp(leftjust, context, &preExp, &varDecls, &auxFunction) + let signdigExp = daeExp(signdig, context, &preExp, &varDecls, &auxFunction) + let &preExp += '<%tvar%> = modelica_real_to_modelica_string(<%sExp%>, <%minlenExp%>, <%leftjustExp%>, <%signdigExp%>);<%\n%>' + '<%tvar%>' + + case CALL(path=IDENT(name="delay"), expLst={ICONST(integer=index), e, d, delayMax}) then + let tvar = tempDecl("modelica_real", &varDecls) + + let var1 = daeExp(e, context, &preExp, &varDecls, &auxFunction) + let var2 = daeExp(d, context, &preExp, &varDecls, &auxFunction) + let var3 = daeExp(delayMax, context, &preExp, &varDecls, &auxFunction) + let &preExp += '<%tvar%> = delayImpl(data, <%index%>, <%var1%>, time, <%var2%>, <%var3%>);<%\n%>' + '<%tvar%>' + + case CALL(path=IDENT(name="Integer"), expLst={toBeCasted}) then + let castedVar = daeExp(toBeCasted, context, &preExp, &varDecls, &auxFunction) + '((modelica_integer)<%castedVar%>)' + + case CALL(path=IDENT(name="clock"), expLst={}) then + 'mmc_clock()' + + case CALL(path=IDENT(name="noEvent"), expLst={e1}) then + daeExp(e1, context, &preExp, &varDecls, &auxFunction) + + case CALL(path=IDENT(name="sample"), expLst={ICONST(integer=index), _, _}) then + '$P$sample<%index%>' + + case CALL(path=IDENT(name="anyString"), expLst={e1}) then + 'mmc_anyString(<%daeExp(e1, context, &preExp, &varDecls, &auxFunction)%>)' + + case CALL(path=IDENT(name="fail"), attr = CALL_ATTR(builtin = true)) then + '<%generateThrow()%>' + + case CALL(path=IDENT(name="mmc_get_field"), expLst={s1, ICONST(integer=i)}) then + let tvar = tempDecl("modelica_metatype", &varDecls) + let expPart = daeExp(s1, context, &preExp, &varDecls, &auxFunction) + let &preExp += '<%tvar%> = MMC_FETCH(MMC_OFFSET(MMC_UNTAGPTR(<%expPart%>), <%i%>));<%\n%>' + '<%tvar%>' + + case CALL(path=IDENT(name = "mmc_unbox_record"), expLst={s1}, attr=CALL_ATTR(ty=ty)) then + let argStr = daeExp(s1, context, &preExp, &varDecls, &auxFunction) + unboxRecord(argStr, ty, &preExp, &varDecls) + + case CALL(path=IDENT(name = "threadData")) then + "threadData" + + case CALL(path=IDENT(name = "intBitNot"),expLst={e}) then + let e1 = daeExp(e, context, &preExp, &varDecls, &auxFunction) + '(~<%e1%>)' + + case CALL(path=IDENT(name = name as "intBitNot"),expLst={e1,e2}) + case CALL(path=IDENT(name = name as "intBitAnd"),expLst={e1,e2}) + case CALL(path=IDENT(name = name as "intBitOr"),expLst={e1,e2}) + case CALL(path=IDENT(name = name as "intBitXor"),expLst={e1,e2}) + case CALL(path=IDENT(name = name as "intBitLShift"),expLst={e1,e2}) + case CALL(path=IDENT(name = name as "intBitRShift"),expLst={e1,e2}) then + let i1 = daeExp(e1, context, &preExp, &varDecls, &auxFunction) + let i2 = daeExp(e1, context, &preExp, &varDecls, &auxFunction) + let op = (match name + case "intBitAnd" then "&" + case "intBitOr" then "|" + case "intBitXor" then "^" + case "intBitLShift" then "<<" + case "intBitRShift" then ">>") + '((<%i1%>) <%op%> (<%i2%>))' + + case exp as CALL(attr=attr as CALL_ATTR(tailCall=tail as TAIL(__))) then + let &postExp = buffer "" + let tail = daeExpTailCall(expLst, tail.vars, context, &preExp, &postExp, &varDecls, &auxFunction) + let res = << + /* Tail recursive call */ + <%tail%><%&postExp%>goto _tailrecursive; + /* TODO: Make sure any eventual dead code below is never generated */ + >> + let &preExp += res + "" + + case exp as CALL(attr=attr as CALL_ATTR(__)) then + let additionalOutputs = (match attr.ty + case T_TUPLE(types=t::ts) then List.fill(", NULL",listLength(ts))) + let res = daeExpCallTuple(exp, additionalOutputs, context, &preExp, &varDecls, &auxFunction) + match context + case FUNCTION_CONTEXT(__) then res + case PARALLEL_FUNCTION_CONTEXT(__) then res + else + if boolAnd(profileFunctions(),boolNot(attr.builtin)) then + let funName = '<%underscorePath(exp.path)%>' + let tvar = match attr.ty + case T_NORETCALL(__) then + "" + case T_TUPLE(types=t::_) + case t + then + let tvar2 = tempDecl(expTypeArrayIf(t),&varDecls) + let &preExp += if isArrayType(t) then '<%tvar2%>.dim_size = 0;<%\n%>' + tvar2 + let &preExp += 'SIM_PROF_TICK_FN(<%funName%>_index);<%\n%>' + let &preExp += if tvar then '<%tvar%> = <%res%>;<%\n%>' else '<%res%>;<%\n%>' + let &preExp += 'SIM_PROF_ACC_FN(<%funName%>_index);<%\n%>' + tvar + else res +end daeExpCall; + +template daeExpCallTuple(Exp call, Text additionalOutputs /* arguments 2..N */, Context context, Text &preExp, Text &varDecls, Text &auxFunction) +::= + match call + case exp as CALL(attr=attr as CALL_ATTR(__)) then + let argStr = if boolOr(attr.builtin,isParallelFunctionContext(context)) + then (expLst |> exp => '<%daeExp(exp, context, &preExp, &varDecls, &auxFunction)%>' ;separator=", ") + else ("threadData" + (expLst |> exp => (", " + daeExp(exp, context, &preExp, &varDecls, &auxFunction)))) + if attr.isFunctionPointerCall + then + let typeCast1 = generateTypeCast(attr.ty, expLst, true) + let typeCast2 = generateTypeCast(attr.ty, expLst, false) + let name = '_<%underscorePath(path)%>' + let func = '(MMC_FETCH(MMC_OFFSET(MMC_UNTAGPTR(<%name%>), 1)))' + let closure = '(MMC_FETCH(MMC_OFFSET(MMC_UNTAGPTR(<%name%>), 2)))' + let argStrPointer = ('threadData, <%closure%>' + (expLst |> exp => (", " + daeExp(exp, context, &preExp, &varDecls, &auxFunction)))) + //'<%name%>(<%argStr%><%additionalOutputs%>)' + '<%closure%> ? (<%typeCast1%> <%func%>) (<%argStrPointer%><%additionalOutputs%>) : (<%typeCast2%> <%func%>) (<%argStr%><%additionalOutputs%>)' + else + let name = '<% if attr.builtin then "" else "omc_" %><%underscorePath(path)%>' + '<%name%>(<%argStr%><%additionalOutputs%>)' +end daeExpCallTuple; + +template generateTypeCast(Type ty, list es, Boolean isClosure) +::= + let ret = (match ty + case T_NORETCALL(__) then "void" + else "modelica_metatype") + let inputs = es |> e => ', <%expTypeFromExpArrayIf(e)%>' + let outputs = match ty + case T_TUPLE(types=_::tys) then (tys |> t => ', <%expTypeArrayIf(t)%>') + '(<%ret%>(*)(threadData_t*<%if isClosure then ", modelica_metatype"%><%inputs%><%outputs%>))' +end generateTypeCast; + +template generateTypeCastFromType(Type ty, Boolean isClosure) +::= + let ret = (match ty + case T_FUNCTION(funcResultType=T_NORETCALL(__)) then "void" + else "modelica_metatype") + let inputs = match ty + case T_FUNCTION(__) then + (funcArg |> fa as FUNCARG(__) => ', <%expTypeArrayIf(fa.ty)%>') + let outputs = match ty + case T_FUNCTION(funcResultType=T_TUPLE(types=_::tys)) then (tys |> t => ', <%expTypeArrayIf(t)%>') + '(<%ret%>(*)(threadData_t*<%if isClosure then ", modelica_metatype"%><%inputs%><%outputs%>))' +end generateTypeCastFromType; + +template daeExpTailCall(list es, list vs, Context context, Text &preExp, Text &postExp, Text &varDecls, Text &auxFunction) +::= + match es + case e::erest then + match vs + case v::vrest then + let exp = daeExp(e,context,&preExp,&varDecls, &auxFunction) + match e + case CREF(componentRef = cr, ty = T_FUNCTION_REFERENCE_VAR(__)) then + // adrpo: ignore _x = _x! + if stringEq(v, crefStr(cr)) + then '<%daeExpTailCall(erest, vrest, context, &preExp, &postExp, &varDecls, &auxFunction)%>' + else '_<%v%> = <%exp%>;<%\n%><%daeExpTailCall(erest, vrest, context, &preExp, &postExp, &varDecls, &auxFunction)%>' + case _ then + (if anyExpHasCrefName(erest, v) then + /* We might overwrite a value with something else, so make an extra copy of it */ + let tmp = tempDecl(expTypeFromExpModelica(e),&varDecls) + let &postExp += '_<%v%> = <%tmp%>;<%\n%>' + '<%tmp%> = <%exp%>;<%\n%><%daeExpTailCall(erest, vrest, context, &preExp, &postExp, &varDecls, &auxFunction)%>' + else + let restText = daeExpTailCall(erest, vrest, context, &preExp, &postExp, &varDecls, &auxFunction) + let v2 = '_<%v%>' + if stringEq(v2, exp) + then restText + else '<%v2%> = <%exp%>;<%\n%><%restText%>') +end daeExpTailCall; + +template daeExpArray(Exp exp, Context context, Text &preExp, + Text &varDecls, Text &auxFunction) + "Generates code for an array expression." +::= +match exp +case ARRAY(array = array, scalar = scalar, ty = T_ARRAY(ty = t as T_COMPLEX(__))) then + let arrayTypeStr = expTypeArray(ty) + let arrayVar = tempDecl(arrayTypeStr, &varDecls) + let rec_name = expTypeShort(t) + let &preExp += '<%\n%>alloc_generic_array(&<%arrayVar%>, sizeof(<%rec_name%>), 1, <%listLength(array)%>);<%\n%>' + let params = (array |> e hasindex i1 fromindex 1 => + let prefix = if scalar then '(<%expTypeFromExpModelica(e)%>)' else '&' + '(*((<%rec_name%>*)generic_array_element_addr(&<%arrayVar%>, sizeof(<%rec_name%>), 1, <%i1%>))) = <%prefix%><%daeExp(e, context, &preExp, &varDecls, &auxFunction)%>;' + ;separator="\n") + let &preExp += '<%params%><%\n%>' + arrayVar +case ARRAY(array={}) then + let arrayVar = tempDecl("base_array_t", &varDecls) + let &preExp += 'simple_alloc_1d_base_array(&<%arrayVar%>, 0, NULL);<%\n%>' + arrayVar +case ARRAY(__) then + let arrayTypeStr = expTypeArray(ty) + let arrayVar = tempDecl(arrayTypeStr, &varDecls) + let scalarPrefix = if scalar then "scalar_" else "" + let scalarRef = if scalar then "&" else "" + let params = (array |> e => + let prefix = if scalar then '(<%expTypeFromExpModelica(e)%>)' else "" + '<%prefix%><%daeExp(e, context, &preExp, &varDecls, &auxFunction)%>' + ;separator=", ") + let &preExp += 'array_alloc_<%scalarPrefix%><%arrayTypeStr%>(&<%arrayVar%>, <%listLength(array)%><%if params then ", "%><%params%>);<%\n%>' + arrayVar +end daeExpArray; + + +template daeExpMatrix(Exp exp, Context context, Text &preExp, + Text &varDecls, Text &auxFunction) + "Generates code for a matrix expression." +::= + match exp + case MATRIX(matrix={{}}) // special case for empty matrix: create dimensional array Real[0,1] + case MATRIX(matrix={}) // special case for empty array: create dimensional array Real[0,1] + then + let arrayTypeStr = expTypeArray(ty) + let tmp = tempDecl(arrayTypeStr, &varDecls) + let &preExp += 'alloc_<%arrayTypeStr%>(&<%tmp%>, 2, 0, 1);<%\n%>' + tmp + case m as MATRIX(__) then + let typeStr = expTypeShort(m.ty) + let arrayTypeStr = expTypeArray(m.ty) + match typeStr + // faster creation of the matrix for basic types + case "real" + case "integer" + case "boolean" then + let tmp = tempDecl(arrayTypeStr, &varDecls) + let rows = '<%listLength(m.matrix)%>' + let cols = '<%listLength(listGet(m.matrix, 1))%>' + let matrix = (m.matrix |> row hasindex i0 => + let els = (row |> e hasindex j0 => + let expVar = daeExp(e, context, &preExp, &varDecls, &auxFunction) + 'put_<%typeStr%>_matrix_element(<%expVar%>, <%i0%>, <%j0%>, &<%tmp%>);' ;separator="\n") + '<%els%>' + ;separator="\n") + let &preExp += '/* -- start: matrix[<%rows%>,<%cols%>] -- */<%\n%>' + let &preExp += 'alloc_<%typeStr%>_array(&<%tmp%>, 2, <%rows%>, <%cols%>);<%\n%>' + let &preExp += '<%matrix%><%\n%>' + let &preExp += '/* -- end: matrix[<%rows%>,<%cols%>] -- */<%\n%>' + tmp + // everything else + case _ then + let &vars2 = buffer "" + let &promote = buffer "" + let catAlloc = (m.matrix |> row => + let tmp = tempDecl(arrayTypeStr, &varDecls) + let vars = daeExpMatrixRow(row, arrayTypeStr, context, + &promote, &varDecls, &auxFunction) + let &vars2 += ', &<%tmp%>' + 'cat_alloc_<%arrayTypeStr%>(2, &<%tmp%>, <%listLength(row)%><%vars%>);' + ;separator="\n") + let &preExp += promote + let &preExp += catAlloc + let &preExp += "\n" + let tmp = tempDecl(arrayTypeStr, &varDecls) + let &preExp += 'cat_alloc_<%arrayTypeStr%>(1, &<%tmp%>, <%listLength(m.matrix)%><%vars2%>);<%\n%>' + tmp +end daeExpMatrix; + + +template daeExpMatrixRow(list row, String arrayTypeStr, + Context context, Text &preExp, + Text &varDecls, Text &auxFunction) + "Helper to daeExpMatrix." +::= + let &varLstStr = buffer "" + + let preExp2 = (row |> e => + let expVar = daeExp(e, context, &preExp, &varDecls, &auxFunction) + let tmp = tempDecl(arrayTypeStr, &varDecls) + let &varLstStr += ', &<%tmp%>' + 'promote_scalar_<%arrayTypeStr%>(<%expVar%>, 2, &<%tmp%>);' + ;separator="\n") + let &preExp2 += "\n" + let &preExp += preExp2 + varLstStr +end daeExpMatrixRow; + +template daeExpRange(Exp exp, Context context, Text &preExp, + Text &varDecls, Text &auxFunction) + "Generates code for a range expression." +::= + match exp + case RANGE(__) then + let ty_str = expTypeArray(ty) + let start_exp = daeExp(start, context, &preExp, &varDecls, &auxFunction) + let stop_exp = daeExp(stop, context, &preExp, &varDecls, &auxFunction) + let tmp = tempDecl(ty_str, &varDecls) + let step_exp = match step case SOME(stepExp) then daeExp(stepExp, context, &preExp, &varDecls, &auxFunction) else "1" + let &preExp += 'create_<%ty_str%>_from_range(&<%tmp%>, <%start_exp%>, <%step_exp%>, <%stop_exp%>);<%\n%>' + '<%tmp%>' +end daeExpRange; + +template daeExpCast(Exp exp, Context context, Text &preExp, + Text &varDecls, Text &auxFunction) + "Generates code for a cast expression." +::= +match exp +case CAST(__) then + let expVar = daeExp(exp, context, &preExp, &varDecls, &auxFunction) + match ty + case T_INTEGER(__) then '((modelica_integer)<%expVar%>)' + case T_REAL(__) then '((modelica_real)<%expVar%>)' + case T_ENUMERATION(__) then '((modelica_integer)<%expVar%>)' + case T_BOOL(__) then '((modelica_boolean)<%expVar%>)' + case T_ARRAY(__) then + let arrayTypeStr = expTypeArray(ty) + let tvar = tempDecl(arrayTypeStr, &varDecls) + let tevar = tempDecl(arrayTypeStr, &varDecls) + let to = expTypeShort(ty) + let from = expTypeFromExpShort(exp) + let &preExp += '<%tevar%> = <%expVar%>;<%\n%>cast_<%from%>_array_to_<%to%>(&<%tevar%>, &<%tvar%>);<%\n%>' + '<%tvar%>' + case ty1 as T_COMPLEX(complexClassType=rec as RECORD(__)) then + match typeof(exp) + case ty2 as T_COMPLEX(__) then + if intEq(listLength(ty1.varLst),listLength(ty2.varLst)) then expVar + else + let tmp = tempDecl(expTypeModelica(ty2),&varDecls) + let res = tempDecl(expTypeModelica(ty1),&varDecls) + let &preExp += '<%tmp%> = <%expVar%>;<%\n%>' + let &preExp += ty1.varLst |> var as DAE.TYPES_VAR() => '<%res%>._<%var.name%> = <%tmp%>._<%var.name%>; /* cast */<%\n%>' + res + else + '(<%expVar%>) /* could not cast, using the variable as it is */' +end daeExpCast; + +template daeExpTsub(Exp inExp, Context context, Text &preExp, + Text &varDecls, Text &auxFunction) + "Generates code for an tsub expression." +::= + match inExp + case TSUB(ix=1) then + daeExp(exp, context, &preExp, &varDecls, &auxFunction) + case TSUB(exp=CALL(attr=CALL_ATTR(ty=T_TUPLE(types=tys)))) then + let v = tempDecl(expTypeArrayIf(listGet(tys,ix)), &varDecls) + let additionalOutputs = List.restOrEmpty(tys) |> ty hasindex i1 fromindex 2 => if intEq(i1,ix) then ', &<%v%>' else ", NULL" + let &preExp += if isArrayType(listGet(tys,ix)) then '<%v%>.dim_size = 0;<%\n%>' + let res = daeExpCallTuple(exp, additionalOutputs, context, &preExp, &varDecls, &auxFunction) + let &preExp += '<%res%>;<%\n%>' + v + case TSUB(__) then + error(sourceInfo(), '<%printExpStr(inExp)%>: TSUB only makes sense if the subscripted expression is a function call of tuple type') +end daeExpTsub; + +template daeExpAsub(Exp inExp, Context context, Text &preExp, + Text &varDecls, Text &auxFunction) + "Generates code for an asub expression." +::= + match expTypeFromExpShort(inExp) + case "metatype" then + // MetaModelica Array + (match inExp case ASUB(exp=e, sub={idx}) then + let e1 = daeExp(e, context, &preExp, &varDecls, &auxFunction) + let idx1 = daeExp(idx, context, &preExp, &varDecls, &auxFunction) + 'arrayGet(<%e1%>,<%idx1%>) /* DAE.ASUB */') + // Modelica Array + else + match inExp + case ASUB(exp=ASUB(__)) then + error(sourceInfo(),'Nested array subscripting *should* have been handled by the routine creating the asub, but for some reason it was not: <%printExpStr(exp)%>') + + // Faster asub: Do not construct a whole new array just to access one subscript + case ASUB(exp=exp as ARRAY(scalar=true), sub={idx}) then + let res = tempDecl(expTypeFromExpModelica(exp),&varDecls) + let idx1 = daeExp(idx, context, &preExp, &varDecls, &auxFunction) + let expl = (exp.array |> e hasindex i1 fromindex 1 => + let &caseVarDecls = buffer "" + let &casePreExp = buffer "" + let v = daeExp(e, context, &casePreExp, &caseVarDecls, &auxFunction) + << + case <%i1%>: { + <%&caseVarDecls%> + <%&casePreExp%> + <%res%> = <%v%>; + break; + } + >> ; separator = "\n") + let &preExp += + << + switch(<%idx1%>) + { /* ASUB */ + <%expl%> + default: + throwStreamPrint(threadData, "Index %ld out of bounds [1..<%listLength(exp.array)%>] for array <%Util.escapeModelicaStringToCString(printExpStr(exp))%>", (long) <%idx1%>); + } + <%\n%> + >> + res + + case ASUB(exp=range as RANGE(ty=T_INTEGER(),step=NONE()), sub={idx}) then + let res = tempDecl("modelica_integer", &varDecls) + let idx1 = daeExp(idx, context, &preExp, &varDecls, &auxFunction) + let start = daeExp(range.start, context, &preExp, &varDecls, &auxFunction) + let stop = daeExp(range.stop, context, &preExp, &varDecls, &auxFunction) + let &preExp += << + <%res%> = <%idx1%> + <%start%> - 1; + if (<%res%> > <%stop%>) { + throwStreamPrint(threadData, "Value %ld out of bounds for range <%Util.escapeModelicaStringToCString(printExpStr(range))%>", (long) <%res%>); + } + >> + res + + case ASUB(exp=RANGE(ty=t), sub={idx}) then + error(sourceInfo(),'ASUB_EASY_CASE type:<%unparseType(t)%> range:<%printExpStr(exp)%> index:<%printExpStr(idx)%>') + + case ASUB(exp=ecr as CREF(__), sub=subs) then + let arrName = daeExpCrefRhs(buildCrefExpFromAsub(ecr, subs), context, + &preExp, &varDecls, &auxFunction) + match context + case FUNCTION_CONTEXT(__) then + arrName + case PARALLEL_FUNCTION_CONTEXT(__) then + arrName + else + arrayScalarRhs(ecr.ty, subs, arrName, context, &preExp, &varDecls, &auxFunction) + + case ASUB(exp=e, sub=indexes) then + let exp = daeExp(e, context, &preExp, &varDecls, &auxFunction) + let typeShort = expTypeFromExpShort(e) + match Expression.typeof(inExp) + case T_ARRAY(__) then + error(sourceInfo(),'ASUB non-scalar <%printExpStr(inExp)%>. The inner exp has type: <%unparseType(Expression.typeof(e))%>. After ASUB it is still an array: <%unparseType(Expression.typeof(inExp))%>.') + else + let expIndexes = (indexes |> index => '<%daeExpASubIndex(index, context, &preExp, &varDecls, &auxFunction)%>' ;separator=", ") + '<%typeShort%>_get<%match listLength(indexes) case 1 then "" case i then '_<%i%>D'%>(<%exp%>, <%expIndexes%>)' + + else + error(sourceInfo(),'OTHER_ASUB <%printExpStr(inExp)%>') +end daeExpAsub; + +template daeExpASubIndex(Exp exp, Context context, Text &preExp, Text &varDecls, Text &auxFunction) +::= +match exp + case ICONST(__) then incrementInt(integer,-1) + case ENUM_LITERAL(__) then incrementInt(index,-1) + else '(<%daeExp(exp,context,&preExp,&varDecls, &auxFunction)%>)-1' +end daeExpASubIndex; + +template daeExpCallPre(Exp exp, Context context, Text &preExp, Text &varDecls, Text &auxFunction) + "Generates code for an asub of a cref, which becomes cref + offset." +::= + match exp + /*we use daeExpCrefLhs because daeExpCrefRhs returns with a cast. + will reslut in '$P$PRE(modelica_integer)$A$B... + pre() functions should actaully be eliminated in backend and $PRE prepened as ident + in all cases. (now it's done some places but not in others.)*/ + case cr as CREF(__) then + '$P$PRE<%daeExpCrefLhs(exp, context, &preExp, &varDecls, &auxFunction)%>' + else + error(sourceInfo(), 'Code generation does not support pre(<%printExpStr(exp)%>)') +end daeExpCallPre; + +template daeExpCallStart(Exp exp, Context context, Text &preExp, + Text &varDecls, Text &auxFunction) + "Generates code for an asub of a cref, which becomes cref + offset." +::= + match exp + case cr as CREF(__) then + '$P$ATTRIBUTE<%cref(cr.componentRef)%>.start' + case ASUB(exp = cr as CREF(__), sub = {sub_exp}) then + let offset = daeExp(sub_exp, context, &preExp, &varDecls, &auxFunction) + let cref = cref(cr.componentRef) + '*(&$P$ATTRIBUTE<%cref(cr.componentRef)%>.start + <%offset%>)' + else + error(sourceInfo(), 'Code generation does not support start(<%printExpStr(exp)%>)') +end daeExpCallStart; + + +template daeExpSize(Exp exp, Context context, Text &preExp, + Text &varDecls, Text &auxFunction) + "Generates code for a size expression." +::= + match exp + case SIZE(exp=CREF(__), sz=SOME(dim)) then + let expPart = daeExp(exp, context, &preExp, &varDecls, &auxFunction) + let dimPart = daeExp(dim, context, &preExp, &varDecls, &auxFunction) + let resVar = tempDecl("modelica_integer", &varDecls) + let &preExp += '<%resVar%> = size_of_dimension_base_array(<%expPart%>, <%dimPart%>);<%\n%>' + resVar + case SIZE(exp=CREF(__)) then + let expPart = daeExp(exp, context, &preExp, &varDecls, &auxFunction) + let resVar = tempDecl("integer_array", &varDecls) + let &preExp += 'sizes_of_dimensions_base_array(&<%expPart%>, &<%resVar%>);<%\n%>' + resVar + /* array of zero? */ + case SIZE(exp=ARRAY(array = {})) then + let resVar = tempDecl("modelica_integer", &varDecls) + let &preExp += '<%resVar%> = 0;<%\n%>' + resVar + else error(sourceInfo(), printExpStr(exp) + " not implemented") +end daeExpSize; + + +template daeExpReduction(Exp exp, Context context, Text &preExp, + Text &varDecls, Text &auxFunction) + "Generates code for a reduction expression. The code is quite messy because it handles all + special reduction functions (list, listReverse, array) and handles both list and array as input" +::= + match exp + case r as REDUCTION(reductionInfo=ri as REDUCTIONINFO(iterType=THREAD()),iterators=iterators) + case r as REDUCTION(reductionInfo=ri as REDUCTIONINFO(iterType=COMBINE()),iterators=iterators as {_}) then + ( + let &tmpVarDecls = buffer "" + let &tmpExpPre = buffer "" + let &bodyExpPre = buffer "" + let &rangeExpPre = buffer "" + let arrayTypeResult = expTypeFromExpArray(r) + let arrIndex = match ri.path case IDENT(name="array") then tempDecl("int",&tmpVarDecls) + let foundFirst = if not ri.defaultValue then tempDecl("int",&tmpVarDecls) + let resType = expTypeArrayIf(typeof(exp)) + let res = contextCref(makeUntypedCrefIdent(ri.resultName), context, &auxFunction) + let &tmpVarDecls += '<%resType%> <%res%>;<%\n%>' + let resTmp = tempDecl(resType,&varDecls) + let &preDefault = buffer "" + let resTail = (match ri.path case IDENT(name="list") then tempDecl("modelica_metatype*",&tmpVarDecls)) + let defaultValue = (match ri.path + case IDENT(name="array") then "" + else (match ri.defaultValue + case SOME(v) then daeExp(valueExp(v),context,&preDefault,&tmpVarDecls, &auxFunction))) + let reductionBodyExpr = contextCref(makeUntypedCrefIdent(ri.foldName), context, &auxFunction) + let bodyExprType = expTypeArrayIf(typeof(r.expr)) + let reductionBodyExprWork = daeExp(r.expr, context, &bodyExpPre, &tmpVarDecls, &auxFunction) + let &tmpVarDecls += '<%bodyExprType%> <%reductionBodyExpr%>;<%\n%>' + let &bodyExpPre += '<%reductionBodyExpr%> = <%reductionBodyExprWork%>;<%\n%>' + let foldExp = (match ri.path + case IDENT(name="list") then + << + *<%resTail%> = mmc_mk_cons(<%reductionBodyExpr%>,0); + <%resTail%> = &MMC_CDR(*<%resTail%>); + >> + case IDENT(name="listReverse") then // This is too easy; the damn list is already in the correct order + '<%res%> = mmc_mk_cons(<%reductionBodyExpr%>,<%res%>);' + case IDENT(name="array") then + match typeof(r.expr) + case T_COMPLEX(complexClassType = record_state) then + let rec_name = '<%underscorePath(ClassInf.getStateName(record_state))%>' + '*((<%rec_name%>*)generic_array_element_addr(&<%res%>, sizeof(<%rec_name%>), 1, <%arrIndex%>++)) = <%reductionBodyExpr%>;' + case T_ARRAY(__) then + let tmp = tempDecl("index_spec_t", &varDecls) + let nridx_str = intAdd(1,listLength(dims)) + let idx_str = (dims |> dim => ", (1), (int*)0, 'W'") + << + create_index_spec(&<%tmp%>, <%nridx_str%>, (0), make_index_array(1, (int) <%arrIndex%>++), 'S'<%idx_str%>); + indexed_assign_<%expTypeArray(ty)%>(<%reductionBodyExpr%>, &<%res%>, &<%tmp%>); + >> + else + '*(<%arrayTypeResult%>_element_addr1(&<%res%>, 1, <%arrIndex%>++)) = <%reductionBodyExpr%>;' + else match ri.foldExp case SOME(fExp) then + let &foldExpPre = buffer "" + let fExpStr = daeExp(fExp, context, &bodyExpPre, &tmpVarDecls, &auxFunction) + if not ri.defaultValue then + << + if(<%foundFirst%>) + { + <%res%> = <%fExpStr%>; + } + else + { + <%res%> = <%reductionBodyExpr%>; + <%foundFirst%> = 1; + } + >> + else '<%res%> = <%fExpStr%>;') + let endLoop = tempDecl("int",&tmpVarDecls) + let loopHeadIter = (iterators |> iter as REDUCTIONITER(__) => + let identType = expTypeFromExpModelica(iter.exp) + let arrayType = expTypeFromExpArray(iter.exp) + let loopVar = '<%iter.id%>_loopVar' + let &guardExpPre = buffer "" + let &tmpVarDecls += (match identType + case "modelica_metatype" then 'modelica_metatype <%loopVar%> = 0;<%\n%>' + else '<%arrayType%> <%loopVar%>;<%\n%>') + let firstIndex = match identType case "modelica_metatype" then (if isMetaArray(iter.exp) then tempDecl("int",&tmpVarDecls) else "") else tempDecl("int",&tmpVarDecls) + let rangeExp = daeExp(iter.exp,context,&rangeExpPre,&tmpVarDecls, &auxFunction) + let &rangeExpPre += '<%loopVar%> = <%rangeExp%>;<%\n%>' + let &rangeExpPre += if firstIndex then '<%firstIndex%> = 1;<%\n%>' + let guardCond = (match iter.guardExp case SOME(grd) then daeExp(grd, context, &guardExpPre, &tmpVarDecls, &auxFunction) else "1") + let iteratorName = contextIteratorName(iter.id, context) + let &tmpVarDecls += '<%identType%> <%iteratorName%>;<%\n%>' + let guardExp = + << + <%&guardExpPre%> + if(<%guardCond%>) { /* found non-guarded */ + <%endLoop%>--; + break; + } + >> + (match identType + case "modelica_metatype" then + (if isMetaArray(iter.exp) then + << + while (<%firstIndex%> <= arrayLength(<%loopVar%>)) { + <%iteratorName%> = arrayGet(<%loopVar%>, <%firstIndex%>++); + <%guardExp%> + } + >> + else + << + while (!listEmpty(<%loopVar%>)) { + <%iteratorName%> = MMC_CAR(<%loopVar%>); + <%loopVar%> = MMC_CDR(<%loopVar%>); + <%guardExp%> + } + >> + ) + else + let addr = match iter.ty + case T_ARRAY(ty=T_COMPLEX(complexClassType = record_state)) then + let rec_name = '<%underscorePath(ClassInf.getStateName(record_state))%>' + '*((<%rec_name%>*)generic_array_element_addr(&<%loopVar%>, sizeof(<%rec_name%>), 1, <%firstIndex%>++))' + else + '*(<%arrayType%>_element_addr1(&<%loopVar%>, 1, <%firstIndex%>++))' + << + while(<%firstIndex%> <= size_of_dimension_base_array(<%loopVar%>, 1)) { + <%iteratorName%> = <%addr%>; + <%guardExp%> + } + >>)) + let firstValue = (match ri.path + case IDENT(name="array") then + let length = tempDecl("int",&tmpVarDecls) + let &rangeExpPre += '<%length%> = 0;<%\n%>' + let _ = (iterators |> iter as REDUCTIONITER(__) => + let loopVar = '<%iter.id%>_loopVar' + let identType = expTypeFromExpModelica(iter.exp) + let &rangeExpPre += '<%length%> = modelica_integer_max(<%length%>,<%match identType case "modelica_metatype" then (if isMetaArray(iter.exp) then 'arrayLength(<%loopVar%>)' else 'listLength(<%loopVar%>)') else 'size_of_dimension_base_array(<%loopVar%>, 1)'%>);<%\n%>' + "") + << + <%arrIndex%> = 1; + <% match typeof(r.expr) + case T_COMPLEX(complexClassType = record_state) then + let rec_name = '<%underscorePath(ClassInf.getStateName(record_state))%>' + 'alloc_generic_array(&<%res%>,sizeof(<%rec_name%>),1,<%length%>);' + case T_ARRAY(__) then + let dimSizes = dims |> dim => match dim + case DIM_INTEGER(__) then ', <%integer%>' + case DIM_BOOLEAN(__) then ", 2" + case DIM_ENUM(__) then ', <%size%>' + else error(sourceInfo(), 'array reduction unable to generate code for element of unknown dimension sizes; type <%unparseType(typeof(r.expr))%>: <%ExpressionDump.printExpStr(r.expr)%>') + ; separator = ", " + 'alloc_<%arrayTypeResult%>(&<%res%>, <%intAdd(1,listLength(dims))%>, <%length%><%dimSizes%>);' + else + 'simple_alloc_1d_<%arrayTypeResult%>(&<%res%>,<%length%>);'%> + >> + else if ri.defaultValue then + << + <%&preDefault%> + <%res%> = <%defaultValue%>; /* defaultValue */ + >> + else + << + <%foundFirst%> = 0; /* <%dotPath(ri.path)%> lacks default-value */ + >>) + let loop = + << + while(1) { + <%endLoop%> = <%listLength(iterators)%>; + <%loopHeadIter%> + if (<%endLoop%> == 0) { + <%&bodyExpPre%> + <%foldExp%> + } <% match iterators case _::_ then + << + else if (<%endLoop%> == <%listLength(iterators)%>) { + break; + } else { + <%generateThrow()%>; + } + >> %> + } + >> + let &preExp += << + { + <%&tmpVarDecls%> + <%&rangeExpPre%> + <%firstValue%> + <% if resTail then '<%resTail%> = &<%res%>;' %> + <%loop%> + <% if not ri.defaultValue then 'if (!<%foundFirst%>) <%generateThrow()%>;' %> + <% if resTail then '*<%resTail%> = mmc_mk_nil();' %> + <% resTmp %> = <% res %>; + }<%\n%> + >> + resTmp) + else error(sourceInfo(), 'Code generation does not support multiple iterators: <%printExpStr(exp)%>') +end daeExpReduction; + +template daeExpMatch(Exp exp, Context context, Text &preExp, Text &varDecls, Text &auxFunction) + "Generates code for a match expression." +::= +match exp +case exp as MATCHEXPRESSION(__) then + let res = match et + case T_NORETCALL(__) then error(sourceInfo(), 'match expression not returning anything should be caught in a noretcall statement and not reach this code: <%printExpStr(exp)%>') + case T_TUPLE(types={}) then error(sourceInfo(), 'match expression returning an empty tuple should be caught in a noretcall statement and not reach this code: <%printExpStr(exp)%>') + else tempDeclZero(expTypeModelica(et), &varDecls) + let startIndexOutputs = "ERROR_INDEX" + daeExpMatch2(exp,listExpLength1,res,startIndexOutputs,context,&preExp,&varDecls,&auxFunction) +end daeExpMatch; + +template daeExpMatch2(Exp exp, list tupleAssignExps, Text res, Text startIndexOutputs, Context context, Text &preExp, Text &varDecls, Text &auxFunction) + "Generates code for a match expression." +::= +match exp +case exp as MATCHEXPRESSION(__) then + let () = codegenPushTryThrowIndex(System.tmpTick()) + let goto = 'goto_<%codegenPeekTryThrowIndex()%>' + let &preExpInner = buffer "" + let &preExpRes = buffer "" + let &varDeclsInput = buffer "" + let &varDeclsInner = buffer "" + let &varFrees = buffer "" + let &ignore = buffer "" + let ignore2 = (elementVars(localDecls) |> var => + varInit(var, "", &varDeclsInner, &preExpInner, &varFrees, &auxFunction) + ) + let prefix = 'tmp<%System.tmpTick()%>' + let &preExpInput = buffer "" + let &expInput = buffer "" + // get the current index of tmpMeta and reserve N=listLength(inputs) values in it! + let startIndexInputs = '<%System.tmpTickIndexReserve(1, listLength(inputs))%>' + let ignore3 = (List.threadTuple(inputs,aliases) |> (exp,alias) hasindex i0 => + let typ = '<%expTypeFromExpModelica(exp)%>' + let decl = tempDeclMatchInput(typ, prefix, startIndexInputs, i0, &varDeclsInput) + let &expInput += '<%decl%> = <%daeExp(exp, context, &preExpInput, &varDeclsInput, &auxFunction)%>;<%\n%>' + let &expInput += alias |> a => let &varDeclsInput += '<%typ%> _<%a%>;' '_<%a%> = <%decl%>;' ; separator="\n" + ""; empty) + let ix = match exp.matchType + case MATCH(switch=SOME((switchIndex,ty as T_STRING(__),div))) then + let matchInputVar = getTempDeclMatchInputName(exp.inputs, prefix, startIndexInputs, switchIndex) + 'stringHashDjb2Mod(<%matchInputVar%>,<%div%>)' + case MATCH(switch=SOME((switchIndex,ty as T_METATYPE(__),_))) then + let matchInputVar = getTempDeclMatchInputName(exp.inputs, prefix, startIndexInputs, switchIndex) + 'valueConstructor(<%matchInputVar%>)' + case MATCH(switch=SOME((switchIndex,ty as T_INTEGER(__),_))) then + let matchInputVar = getTempDeclMatchInputName(exp.inputs, prefix, startIndexInputs, switchIndex) + '<%matchInputVar%>' + case MATCH(switch=SOME(_)) then + error(sourceInfo(), 'Unknown switch: <%printExpStr(exp)%>') + else tempDecl('volatile mmc_switch_type', &varDeclsInner) + let done = tempDecl('int', &varDeclsInner) + let &preExp += + << + <%endModelicaLine()%> + { /* <% match exp.matchType case MATCHCONTINUE(__) then "matchcontinue expression" case MATCH(__) then "match expression" %> */ + <%varDeclsInput%> + <%preExpInput%> + <%expInput%> + { + <%varDeclsInner%> + <%preExpInner%> + <%match exp.matchType + case MATCH(switch=SOME(_)) then '<%done%> = 0;<%\n%>{' + else + << + <%ix%> = 0; + <%done%> = 0; + <% match exp.matchType case MATCHCONTINUE(__) then + /* One additional MMC_TRY_INTERNAL() for each caught exception + * You would expect you could do the setjmp only once, but some counters I guess are stored in registers and would need to become volatile + * This is still a lot faster than doing MMC_TRY_INTERNAL() inside the for-loop + */ + << + MMC_TRY_INTERNAL(mmc_jumper) + <%prefix%>_top: + threadData->mmc_jumper = &new_mmc_jumper; + >> + %> + for (; <%ix%> < <%listLength(exp.cases)%> && !<%done%>; <%ix%>++) { + >> + %> + switch (MMC_SWITCH_CAST(<%ix%>)) { + <%daeExpMatchCases(exp.cases, tupleAssignExps, exp.matchType, ix, res, startIndexOutputs, prefix, startIndexInputs, exp.inputs, done, context, &varDecls, &auxFunction, System.tmpTickIndexReserve(1,0) /* Returns the current MM tick */)%> + } + goto <%prefix%>_end; + <%prefix%>_end: ; + }<%let() = codegenPopTryThrowIndex() ""%> + goto <%goto%>; + <%goto%>:; + <% match exp.matchType case MATCHCONTINUE(__) then + << + MMC_CATCH_INTERNAL(mmc_jumper); + if (!<%done%> && ++<%ix%> < <%listLength(exp.cases)%>) { + goto <%prefix%>_top; + } + >> + %> + if (!<%done%>) <%generateThrow()%>; + } + } + >> + res +end daeExpMatch2; + +template daeExpMatchCases(list cases, list tupleAssignExps, DAE.MatchType ty, Text ix, Text res, Text startIndexOutputs, Text prefix, Text startIndexInputs, list inputs, Text done, Context context, Text &varDecls, Text &auxFunction, Integer startTmpTickIndex) +::= + cases |> c as CASE(__) hasindex i0 => + let() = System.tmpTickSetIndex(startTmpTickIndex,1) + // Susan doesn't let us do this outside the loop... + let lastSwitchIndex = (match ty + case MATCH(switch=SOME((n,ty as T_STRING(__),div))) then + (match List.last(cases) + case last as CASE(__) then + (match switchIndex(listGet(last.patterns,n),div) + case "default" then 'goto <%prefix%>_default' + else 'goto <%prefix%>_end')) + else 'goto <%prefix%>_end') + let onPatternFail = (match ty + case MATCH(switch=SOME((switchIndex,ty as T_STRING(__),div))) then + lastSwitchIndex + else 'goto <%prefix%>_end') + let &varDeclsCaseInner = buffer "" + let &preExpCaseInner = buffer "" + let &assignments = buffer "" + let &preRes = buffer "" + let &varFrees = buffer "" + let patternMatching = (sortPatternsByComplexity(c.patterns) |> (lhs,i0) => patternMatch(lhs,'<%getTempDeclMatchInputName(inputs, prefix, startIndexInputs, i0)%>', onPatternFail, &varDeclsCaseInner, &assignments); empty) + let() = System.tmpTickSetIndex(startTmpTickIndex,1) + let stmts = (c.body |> stmt => algStatement(stmt, context, &varDeclsCaseInner, &auxFunction); separator="\n") + let &preGuardCheck = buffer "" + let guardCheck = (match c.patternGuard case SOME(exp) then + << + /* Check guard condition after assignments */ + if (!<%daeExp(exp,context,&preGuardCheck,&varDeclsCaseInner, &auxFunction)%>) <%onPatternFail%>;<%\n%> + >>) + let caseRes = (match c.result + case SOME(TUPLE(PR=exps)) then + (exps |> e hasindex i1 fromindex 1 => + '<%getTempDeclMatchOutputName(exps, res, startIndexOutputs, i1)%> = <%daeExp(e,context,&preRes,&varDeclsCaseInner, &auxFunction)%>;<%\n%>') + case SOME(exp as CALL(attr=CALL_ATTR(tailCall=TAIL(__)))) then + daeExp(exp, context, &preRes, &varDeclsCaseInner, &auxFunction) + case SOME(exp as CALL(attr=CALL_ATTR(tuple_=true))) then + let additionalOutputs = List.restOrEmpty(tupleAssignExps) |> cr hasindex i0 fromindex 2 /* starting with second element */ => + ', &<%getTempDeclMatchOutputName(tupleAssignExps, res, startIndexOutputs, i0)%>' + let retStruct = daeExpCallTuple(exp, additionalOutputs, context, &preRes, &varDeclsCaseInner, &auxFunction) + let callRet = match tupleAssignExps + case {} then '<%retStruct%>;<%\n%>' + case e::_ then '<%getTempDeclMatchOutputName(tupleAssignExps, res, startIndexOutputs, 1)%> = <%retStruct%>;<%\n%>' + callRet + case SOME(e) then '<%res%> = <%daeExp(e,context,&preRes,&varDeclsCaseInner, &auxFunction)%>;<%\n%>') + let _ = (elementVars(c.localDecls) |> var => varInit(var, "", &varDeclsCaseInner, &preExpCaseInner, &varFrees, &auxFunction)) + <<<%match ty case MATCH(switch=SOME((n,_,ea))) + then + let name = switchIndex(listGet(c.patterns,n),ea) + (match name + case "default" then + << + <%name%>: { + <%prefix%>_default: OMC_LABEL_UNUSED; + >> + else + '<%name%>: {') + else + 'case <%i0%>: {'%> + <%varDeclsCaseInner%> + <%preExpCaseInner%> + <%patternMatching%> + <%assignments%> + <%&preGuardCheck%> + <%guardCheck%> + <% match c.jump + case 0 then "/* Pattern matching succeeded */" + else '<%ix%> += <%c.jump%>; /* Pattern matching succeeded; we may skip some cases if we fail */' + %> + <%stmts%> + <%modelicaLine(c.resultInfo)%> + <% if c.result then '<%preRes%><%caseRes%>' else '<%generateThrow()%>;<%\n%>' %> + <%endModelicaLine()%> + <%done%> = 1; + break; + }<%\n%> + >> +end daeExpMatchCases; + +template switchIndex(Pattern pattern, Integer extraArg) +::= + match pattern + case PAT_CALL(__) then 'case <%getValueCtor(index)%>' + case PAT_CONSTANT(exp=e as SCONST(__)) then 'case <%stringHashDjb2Mod(e.string,extraArg)%> /* <%e.string%> */' + case PAT_CONSTANT(exp=e as ICONST(__)) then 'case <%e.integer%>' + else 'default' +end switchIndex; + +template daeExpBox(Exp exp, Context context, Text &preExp, Text &varDecls, Text &auxFunction) + "Generates code for a match expression." +::= +match exp +case BOX(__) then + let ty = if isArrayType(typeof(exp)) then "modelica_array" else expTypeFromExpShort(exp) + let res = daeExp(exp,context,&preExp,&varDecls, &auxFunction) + 'mmc_mk_<%ty%>(<%res%>)' +end daeExpBox; + +template daeExpUnbox(Exp exp, Context context, Text &preExp, Text &varDecls, Text &auxFunction) + "Generates code for a match expression." +::= +match exp +case exp as UNBOX(__) then + let ty = expTypeShort(exp.ty) + let res = daeExp(exp.exp,context,&preExp,&varDecls, &auxFunction) + 'mmc_unbox_<%ty%>(<%res%>)' +end daeExpUnbox; + +template daeExpSharedLiteral(Exp exp) + "Generates code for a match expression." +::= +match exp case exp as SHARED_LITERAL(__) then '_OMC_LIT<%exp.index%>' +end daeExpSharedLiteral; + +/* Dimensions need to return expressions that are different than for normal expressions. + * The reason is that dimensions use 1-based indexing, but Boolean indexes start at 0 + */ +template daeDimensionExp(Exp exp, Context context, Text &preExp, Text &varDecls, Text &auxFunction) +::= + let res = daeExp(exp,context,&preExp,&varDecls,&auxFunction) + match expTypeFromExpModelica(exp) + case "modelica_boolean" then '(<%res%>+1)' + else '/* <%expTypeFromExpModelica(exp)%> */ <%res%>' +end daeDimensionExp; + +template daeSubscriptExp(Exp exp, Context context, Text &preExp, Text &varDecls, Text &auxFunction) +::= + let res = daeExp(exp,context,&preExp,&varDecls,&auxFunction) + match expTypeFromExpModelica(exp) + case "modelica_boolean" then '(<%res%>+1)' + else '<%res%>' /* <%expTypeFromExpModelica(exp)%> */ +end daeSubscriptExp; + +annotation(__OpenModelica_Interface="backend"); +end CodegenCFunctions; + +// vim: filetype=susan sw=2 sts=2 diff --git a/Compiler/Template/CodegenCSharp.tpl b/Compiler/Template/CodegenCSharp.tpl index 1ea9c94278b..c07dec259d9 100644 --- a/Compiler/Template/CodegenCSharp.tpl +++ b/Compiler/Template/CodegenCSharp.tpl @@ -17,7 +17,7 @@ end translateModel; template wrapIntoExtraFileIfModelTooBig(Text txtCode, String fileNamePostfix, SimCode simCode) ::= match simCode case SIMCODE(modelInfo = MODELINFO(__)) then - if SimCodeUtil.isModelTooBigForCSharpInOneFile(simCode) then + if isModelTooBigForCSharpInOneFile(simCode) then let wrappedCode = << // Simulation code for <%dotPath(modelInfo.name)%> generated by the OpenModelica Compiler. diff --git a/Compiler/Template/CodegenCpp.tpl b/Compiler/Template/CodegenCpp.tpl index 8597d2f3e33..c8ec5d9dc1d 100644 --- a/Compiler/Template/CodegenCpp.tpl +++ b/Compiler/Template/CodegenCpp.tpl @@ -1218,7 +1218,7 @@ case SIMCODE(modelInfo=MODELINFO(__)) then template createAssignArray(DAE.ComponentRef sourceOrTargetArrayCref, String sourceArrayName, String targetArrayName, SimCode simCode ,Text& extraFuncs,Text& extraFuncsDecl,Text extraFuncsNamespace, Boolean useFlatArrayNotationSource, Boolean useFlatArrayNotationTarget, String dimsArrayName) ::= - match SimCodeUtil.cref2simvar(sourceOrTargetArrayCref, simCode) + match cref2simvar(sourceOrTargetArrayCref, simCode) case v as SIMVAR(numArrayElement=num) then '<%targetArrayName%>.assign(<%sourceArrayName%>);' end createAssignArray; @@ -1575,6 +1575,7 @@ let modelname = identOfPath(modelInfo.name) #include #include #include +#include #include #define PATH string @@ -2040,6 +2041,7 @@ case SIMCODE(modelInfo=MODELINFO(__), makefileParams=MAKEFILE_PARAMS(__), simula #include #include #include + #include #include <% @@ -2141,6 +2143,8 @@ case SIMCODE(modelInfo=MODELINFO(__), makefileParams=MAKEFILE_PARAMS(__), simula %> try { + Logger::initialize(); + Logger::setEnabled(false); <%if boolNot(stringEq(getConfigString(PROFILING_LEVEL),"none")) then << std::vector measureTimeArraySimulation = std::vector(2); //0 all, 1 setup @@ -3490,7 +3494,7 @@ match simCode #ifdef MEASURETIME_MODELFUNCTIONS MeasureTime::addResultContentBlock("<%dotPath(modelInfo.name)%>","functions",&measureTimeFunctionsArray); - measureTimeFunctionsArray = std::vector(4); //1 evaluateODE ; 2 evaluateAll; 3 writeOutput; 4 handleTimeEvents + measureTimeFunctionsArray = std::vector(5); //1 evaluateODE ; 2 evaluateAll; 3 writeOutput; 4 handleTimeEvents; 5 evaluateZeroFuncs measuredFunctionStartValues = MeasureTime::getZeroValues(); measuredFunctionEndValues = MeasureTime::getZeroValues(); @@ -3498,6 +3502,7 @@ match simCode measureTimeFunctionsArray[1] = MeasureTimeData("evaluateAll"); measureTimeFunctionsArray[2] = MeasureTimeData("writeOutput"); measureTimeFunctionsArray[3] = MeasureTimeData("handleTimeEvents"); + measureTimeFunctionsArray[4] = MeasureTimeData("evaluateZeroFuncs"); #endif //MEASURETIME_MODELFUNCTIONS >> %> @@ -14562,7 +14567,7 @@ template createEvaluateAll( list allEquationsPlusWhen,list - /* Evaluate Equations*/ + // Evaluate Equations <%equation_all_func_calls%> // Reinits <%reinit%> @@ -14609,7 +14614,7 @@ template createEvaluate(list> odeEquations,list { <%if createMeasureTime then generateMeasureTimeStartCode("measuredFunctionStartValues", "evaluateODE", "MEASURETIME_MODELFUNCTIONS") else ""%> <%varDecls%> - /* Evaluate Equations*/ + // Evaluate Equations <%equation_ode_func_calls%> <%if createMeasureTime then generateMeasureTimeEndCode("measuredFunctionStartValues", "measuredFunctionEndValues", "measureTimeFunctionsArray[0]", "evaluateODE", "MEASURETIME_MODELFUNCTIONS") else ""%> } @@ -14630,7 +14635,7 @@ template createEvaluateZeroFuncs( list equationsForZeroCrossings, S void <%className%>::evaluateZeroFuncs(const UPDATETYPE command) { <%varDecls%> - /* Evaluate Equations*/ + // Evaluate Equations <%equation_zero_func_calls%> } >> diff --git a/Compiler/Template/CodegenCppHpcom.tpl b/Compiler/Template/CodegenCppHpcom.tpl index 863c36915ab..f8a9ddff265 100644 --- a/Compiler/Template/CodegenCppHpcom.tpl +++ b/Compiler/Template/CodegenCppHpcom.tpl @@ -7,6 +7,7 @@ package CodegenCppHpcom +import interface SimCodeBackendTV; import interface SimCodeTV; import CodegenUtil.*; import CodegenCpp.*; //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) @@ -121,7 +122,7 @@ template generateAdditionalIncludesForParallelCode(SimCode simCode, Text& extraF << #include #include - #include + #include #include #include #if TBB_INTERFACE_VERSION >= 8000 @@ -174,11 +175,12 @@ template generateAdditionalProtectedMemberDeclaration(SimCode simCode, Text& ext } <% match schedulesOpt - case SOME((odeSchedule as THREADSCHEDULE(__),_)) then + case SOME((odeSchedule as THREADSCHEDULE(__),_,_)) then << #ifdef MEASURETIME_MODELFUNCTIONS std::vector measureTimeThreadArrayOdeHpcom; std::vector measureTimeThreadArrayDaeHpcom; + std::vector measureTimeThreadArrayZeroFuncHpcom; <%List.intRange(arrayLength(odeSchedule.threadTasks)) |> threadIdx => 'MeasureTimeValues* measuredSchedulerStartValues_<%intSub(threadIdx,1)%>;'; separator="\n"%> <%List.intRange(arrayLength(odeSchedule.threadTasks)) |> threadIdx => 'MeasureTimeValues* measuredSchedulerEndValues_<%intSub(threadIdx,1)%>;'; separator="\n"%> #endif //MEASURETIME_MODELFUNCTIONS @@ -219,26 +221,26 @@ template generateAdditionalStructHeaders(Schedule odeSchedule) #if TBB_INTERFACE_VERSION >= 8000 struct TbbArenaFunctor { - tbb::flow::graph * g; - tbb::flow::broadcast_node * sn; - - TbbArenaFunctor( ) - { - g = NULL; - sn = NULL; - } - - TbbArenaFunctor( tbb::flow::graph & in_g , tbb::flow::broadcast_node & in_sn ) - { - g = &in_g; - sn = &in_sn; - } - - void operator()() - { - sn->try_put( tbb::flow::continue_msg() ); - g->wait_for_all(); - } + tbb::flow::graph * g; + tbb::flow::broadcast_node * sn; + + TbbArenaFunctor( ) + { + g = NULL; + sn = NULL; + } + + TbbArenaFunctor( tbb::flow::graph & in_g , tbb::flow::broadcast_node & in_sn ) + { + g = &in_g; + sn = &in_sn; + } + + void operator()() + { + sn->try_put( tbb::flow::continue_msg() ); + g->wait_for_all(); + } }; #endif @@ -249,24 +251,13 @@ template generateAdditionalStructHeaders(Schedule odeSchedule) end match end generateAdditionalStructHeaders; -template generateAdditionalFunctionHeaders(Option> schedulesOpt) +template generateAdditionalFunctionHeaders(Option> schedulesOpt) ::= let type = getConfigString(HPCOM_CODE) - let parallelEvaluate = 'FORCE_INLINE void evaluateParallel(const UPDATETYPE command, bool evaluateODE);' << - <%parallelEvaluate%> + FORCE_INLINE void evaluateParallel(const UPDATETYPE command, int evaluateMode); <%match schedulesOpt - case SOME((odeSchedule as LEVELSCHEDULE(useFixedAssignments=true),_)) then - match type - case ("pthreads") - case ("pthreads_spin") then - let threadFuncs = List.intRange(getConfigInt(NUM_PROC)) |> thIdx hasindex i0 fromindex 0 => 'void evaluateThreadFunc<%i0%>();'; separator="\n" - << - <%threadFuncs%> - >> - else "" - end match - case SOME((odeSchedule as THREADSCHEDULE(__),_)) then + case SOME((odeSchedule as THREADSCHEDULE(__),_,_)) then match type case ("openmp") then << @@ -277,7 +268,7 @@ template generateAdditionalFunctionHeaders(Option> sche <%headers%> >> end match - case SOME((odeSchedule as TASKDEPSCHEDULE(__),daeSchedule as TASKDEPSCHEDULE(__))) then + case SOME((odeSchedule as TASKDEPSCHEDULE(__),daeSchedule as TASKDEPSCHEDULE(__),zeroFuncSchedule as TASKDEPSCHEDULE(__))) then match type case ("openmp") then << @@ -299,11 +290,20 @@ template generateAdditionalFunctionHeaders(Option> sche >> else "" ); separator="\n" + let voidfuncsZeroFunc = zeroFuncSchedule.tasks |> task => ( + match task + case ((task as CALCTASK(__),parents)) then + << + void task_func_ZeroFunc_<%task.index%>(); + >> + else "" + ); separator="\n" << <%generateAdditionalStructHeaders(odeSchedule)%> <%voidfuncsOde%> <%voidfuncsDae%> + <%voidfuncsZeroFunc%> >> else "" end match @@ -312,15 +312,15 @@ template generateAdditionalFunctionHeaders(Option> sche >> end generateAdditionalFunctionHeaders; -template generateAdditionalHpcomVarHeaders(Option> schedulesOpt) +template generateAdditionalHpcomVarHeaders(Option> schedulesOpt) ::= let type = getConfigString(HPCOM_CODE) << UPDATETYPE _command; - bool _evaluateODE; + int _evaluateMode; <% match schedulesOpt - case SOME((odeSchedule as LEVELSCHEDULE(useFixedAssignments=true),_)) then + case SOME((odeSchedule as LEVELSCHEDULE(useFixedAssignments=true),_,_)) then match type case ("pthreads") case ("pthreads_spin") then @@ -332,15 +332,17 @@ template generateAdditionalHpcomVarHeaders(Option> sche >> else "" end match - case SOME((odeSchedule as THREADSCHEDULE(__),daeSchedule as THREADSCHEDULE(__))) then + case SOME((odeSchedule as THREADSCHEDULE(__),daeSchedule as THREADSCHEDULE(__),zeroFuncSchedule as THREADSCHEDULE(__))) then let odeLocks = createLockArrayByName(listLength(odeSchedule.outgoingDepTasks),"_lockOde",type)//odeSchedule.outgoingDepTasks |> task => createLockByDepTask(task, "_lockOde", type); separator="\n" let daeLocks = createLockArrayByName(listLength(daeSchedule.outgoingDepTasks),"_lockDae",type)//daeSchedule.outgoingDepTasks |> task => createLockByDepTask(task, "_lockDae", type); separator="\n" + let zeroFuncLocks = createLockArrayByName(listLength(zeroFuncSchedule.outgoingDepTasks),"_lockZeroFunc",type)//daeSchedule.outgoingDepTasks |> task => createLockByDepTask(task, "_lockDae", type); separator="\n" match type case ("openmp") then let threadDecl = arrayList(odeSchedule.threadTasks) |> tt hasindex i0 fromindex 0 => generateThreadHeaderDecl(i0, type); separator="\n" << <%odeLocks%> <%daeLocks%> + <%zeroFuncLocks%> <%threadDecl%> >> case "mpi" then @@ -355,12 +357,13 @@ template generateAdditionalHpcomVarHeaders(Option> sche bool _terminateThreads; <%odeLocks%> <%daeLocks%> + <%zeroFuncLocks%> <%thLocks%> <%thLocks1%> <%threadDecl%> >> end match - case SOME((odeSchedule as TASKDEPSCHEDULE(__),_)) then + case SOME((odeSchedule as TASKDEPSCHEDULE(__),_,_)) then match type case ("openmp") then << >> @@ -370,6 +373,7 @@ template generateAdditionalHpcomVarHeaders(Option> sche tbb::flow::broadcast_node _tbbStartNode; std::vector* > _tbbNodeList_ODE; std::vector* > _tbbNodeList_DAE; + std::vector* > _tbbNodeList_ZeroFunc; #if TBB_INTERFACE_VERSION >= 8000 tbb::task_arena _tbbArena; TbbArenaFunctor _tbbArenaFunctor; @@ -403,11 +407,11 @@ template generateThreadFunctionHeaderDecl(Integer threadIdx) >> end generateThreadFunctionHeaderDecl; -template generateAdditionalConstructorDefinitions(Option> scheduleOpt) +template generateAdditionalConstructorDefinitions(Option> scheduleOpt) ::= let type = getConfigString(HPCOM_CODE) match scheduleOpt - case SOME((odeSchedule as LEVELSCHEDULE(useFixedAssignments=true),_)) then + case SOME((odeSchedule as LEVELSCHEDULE(useFixedAssignments=true),_,_)) then match type case ("pthreads") case ("pthreads_spin") then @@ -417,7 +421,7 @@ template generateAdditionalConstructorDefinitions(Option >> else "" - case SOME((odeSchedule as TASKDEPSCHEDULE(__),daeSchedule as TASKDEPSCHEDULE(__))) then + case SOME((odeSchedule as TASKDEPSCHEDULE(__),daeSchedule as TASKDEPSCHEDULE(__),zeroFuncSchedule as TASKDEPSCHEDULE(__))) then match type case ("tbb") then << @@ -425,6 +429,7 @@ template generateAdditionalConstructorDefinitions(Option,NULL) ,_tbbNodeList_DAE(<%listLength(daeSchedule.tasks)%>,NULL) + ,_tbbNodeList_ZeroFunc(<%listLength(zeroFuncSchedule.tasks)%>,NULL) >> else "" end match @@ -432,11 +437,11 @@ template generateAdditionalConstructorDefinitions(Option> schedulesOpt, String modelNamePrefixStr, String fullModelName) +template generateAdditionalConstructorBodyStatements(Option> schedulesOpt, String modelNamePrefixStr, String fullModelName) ::= let type = getConfigString(HPCOM_CODE) match schedulesOpt - case SOME((odeSchedule as LEVELSCHEDULE(useFixedAssignments=true),_)) then + case SOME((odeSchedule as LEVELSCHEDULE(useFixedAssignments=true),_,_)) then match type case ("pthreads") case ("pthreads_spin") then @@ -458,11 +463,14 @@ template generateAdditionalConstructorBodyStatements(Option> else "" end match - case SOME((odeSchedule as THREADSCHEDULE(__),daeSchedule as THREADSCHEDULE(__))) then - let initlocksOde = initializeArrayLocks(listLength(odeSchedule.outgoingDepTasks),"_lockOde",type)//odeSchedule.outgoingDepTasks |> task => initializeLockByDepTask(task, "_lockOde", type); separator="\n" + case SOME((odeSchedule as THREADSCHEDULE(__),daeSchedule as THREADSCHEDULE(__),zeroFuncSchedule as THREADSCHEDULE(__))) then + let initLocksOde = initializeArrayLocks(listLength(odeSchedule.outgoingDepTasks),"_lockOde",type)//odeSchedule.outgoingDepTasks |> task => initializeLockByDepTask(task, "_lockOde", type); separator="\n" let assignLocksOde = assignArrayLocks(listLength(odeSchedule.outgoingDepTasks),"_lockOde",type)//odeSchedule.outgoingDepTasks |> task => assignLockByDepTask(task, "_lockOde", type); separator="\n" - let initlocksDae = initializeArrayLocks(listLength(daeSchedule.outgoingDepTasks),"_lockDae",type)//daeSchedule.outgoingDepTasks |> task => initializeLockByDepTask(task, "_lockDae", type); separator="\n" + let initLocksDae = initializeArrayLocks(listLength(daeSchedule.outgoingDepTasks),"_lockDae",type)//daeSchedule.outgoingDepTasks |> task => initializeLockByDepTask(task, "_lockDae", type); separator="\n" let assignLocksDae = assignArrayLocks(listLength(daeSchedule.outgoingDepTasks),"_lockDae",type)//daeSchedule.outgoingDepTasks |> task => assignLockByDepTask(task, "_lockDae", type); separator="\n" + let initLocksZeroFunc = initializeArrayLocks(listLength(zeroFuncSchedule.outgoingDepTasks),"_lockZeroFunc",type)//daeSchedule.outgoingDepTasks |> task => initializeLockByDepTask(task, "_lockDae", type); separator="\n" + let assignLocksZeroFunc = assignArrayLocks(listLength(zeroFuncSchedule.outgoingDepTasks),"_lockZeroFunc",type)//daeSchedule.outgoingDepTasks |> task => assignLockByDepTask(task, "_lockDae", type); separator="\n" + let threadMeasureTimeBlocks = generateThreadMeasureTimeDeclaration(fullModelName, arrayLength(odeSchedule.threadTasks)) match type @@ -471,8 +479,9 @@ template generateAdditionalConstructorBodyStatements(Option - <%initlocksOde%> - <%initlocksDae%> + <%initLocksOde%> + <%initLocksDae%> + <%initLocksZeroFunc%> <%threadMeasureTimeBlocks%> >> case ("mpi") then @@ -488,25 +497,27 @@ template generateAdditionalConstructorBodyStatements(Option - <%initlocksDae%> + <%initLocksOde%> + <%initLocksDae%> + <%initLocksZeroFunc%> <%threadLocksInit%> <%threadLocksInit1%> <%assignLocksDae%> <%assignLocksOde%> + <%assignLocksZeroFunc%> <%threadAssignLocks%> <%threadAssignLocks1%> <%threadFuncs%> <%threadMeasureTimeBlocks%> >> - case SOME((odeSchedule as TASKDEPSCHEDULE(__), daeSchedule as TASKDEPSCHEDULE(__))) then + case SOME((odeSchedule as TASKDEPSCHEDULE(__),daeSchedule as TASKDEPSCHEDULE(__),zeroFuncSchedule as TASKDEPSCHEDULE(__))) then match type case ("tbb") then - let tbbVars = generateTbbConstructorExtension(odeSchedule.tasks, daeSchedule.tasks, modelNamePrefixStr) + let tbbVars = generateTbbConstructorExtension(odeSchedule.tasks, daeSchedule.tasks, zeroFuncSchedule.tasks, modelNamePrefixStr) << <%tbbVars%> >> @@ -521,12 +532,15 @@ template generateThreadMeasureTimeDeclaration(String fullModelName, Integer numb #ifdef MEASURETIME_MODELFUNCTIONS measureTimeThreadArrayOdeHpcom = std::vector(<%numberOfThreads%>); measureTimeThreadArrayDaeHpcom = std::vector(<%numberOfThreads%>); + measureTimeThreadArrayZeroFuncHpcom = std::vector(<%numberOfThreads%>); MeasureTime::addResultContentBlock("<%fullModelName%>","evaluateODE_threads",&measureTimeThreadArrayOdeHpcom); MeasureTime::addResultContentBlock("<%fullModelName%>","evaluateDAE_threads",&measureTimeThreadArrayDaeHpcom); + MeasureTime::addResultContentBlock("<%fullModelName%>","evaluateZeroFunc_threads",&measureTimeThreadArrayDaeHpcom); <%List.intRange(numberOfThreads) |> threadIdx => 'measuredSchedulerStartValues_<%intSub(threadIdx,1)%> = MeasureTime::getZeroValues();'; separator="\n"%> <%List.intRange(numberOfThreads) |> threadIdx => 'measuredSchedulerEndValues_<%intSub(threadIdx,1)%> = MeasureTime::getZeroValues();'; separator="\n"%> <%List.intRange(numberOfThreads) |> threadIdx => 'measureTimeThreadArrayOdeHpcom[<%intSub(threadIdx,1)%>] = MeasureTimeData("evaluateODE_thread_<%threadIdx%>");'; separator="\n"%> <%List.intRange(numberOfThreads) |> threadIdx => 'measureTimeThreadArrayDaeHpcom[<%intSub(threadIdx,1)%>] = MeasureTimeData("evaluateDAE_thread_<%threadIdx%>");'; separator="\n"%> + <%List.intRange(numberOfThreads) |> threadIdx => 'measureTimeThreadArrayZeroFuncHpcom[<%intSub(threadIdx,1)%>] = MeasureTimeData("evaluateZeroFunc_thread_<%threadIdx%>");'; separator="\n"%> #endif //MEASURETIME_MODELFUNCTIONS >> end generateThreadMeasureTimeDeclaration; @@ -537,17 +551,17 @@ match(iType) case "openmp" then << for(unsigned i=0;i<<%numComms%>;++i) - omp_init_lock(&<%lockName%>_[i]); + omp_init_lock(&<%lockName%>_[i]); >> case "pthreads" then << for(unsigned i=0;i<<%numComms%>;++i) - <%lockName%>_[i] = new alignedLock(); + <%lockName%>_[i] = new alignedLock(); >> case "pthreads_spin" then << for(unsigned i=0;i<<%numComms%>;++i) - <%lockName%>_[i] = new alignedSpinlock(); + <%lockName%>_[i] = new alignedSpinlock(); >> else << @@ -561,13 +575,13 @@ template assignArrayLocks(Integer numComms, String lockName, String iType) case ("openmp") then << for(unsigned i=0;i<<%numComms%>;++i) - omp_set_lock(&<%lockName%>_[i]); + omp_set_lock(&<%lockName%>_[i]); >> case ("pthreads") case ("pthreads_spin") then << for(unsigned i=0;i<<%numComms%>;++i) - <%lockName%>_[i]->lock(); + <%lockName%>_[i]->lock(); >> else @@ -604,7 +618,7 @@ match(iType) case "openmp" then << for(unsigned i=0;i<<%numComms%>;++i) - omp_destroy_lock(&<%lockName%>_[i]); + omp_destroy_lock(&<%lockName%>_[i]); >> case "pthreads" case "pthreads_spin" then @@ -618,11 +632,11 @@ match(iType) >> end destroyArrayLocks; -template generateAdditionalDestructorBodyStatements(Option> schedulesOpt) +template generateAdditionalDestructorBodyStatements(Option> schedulesOpt) ::= let type = getConfigString(HPCOM_CODE) match schedulesOpt - case SOME((odeSchedule as LEVELSCHEDULE(useFixedAssignments=true),_)) then + case SOME((odeSchedule as LEVELSCHEDULE(useFixedAssignments=true),_,_)) then match type case ("pthreads") case ("pthreads_spin") then @@ -634,14 +648,16 @@ template generateAdditionalDestructorBodyStatements(Option> else "" - case SOME((odeSchedule as THREADSCHEDULE(__),daeSchedule as THREADSCHEDULE(__))) then + case SOME((odeSchedule as THREADSCHEDULE(__),daeSchedule as THREADSCHEDULE(__),zeroFuncSchedule as THREADSCHEDULE(__))) then let destroyLocksOde = destroyArrayLocks(listLength(odeSchedule.outgoingDepTasks),"_lockOde",type)//odeSchedule.outgoingDepTasks |> task => destroyLockByDepTask(task, "_lockOde", type); separator="\n" - let destroyLocksDae = destroyArrayLocks(listLength(odeSchedule.outgoingDepTasks),"_lockDae",type)//daeSchedule.outgoingDepTasks |> task => destroyLockByDepTask(task, "_lockDae", type); separator="\n" + let destroyLocksDae = destroyArrayLocks(listLength(daeSchedule.outgoingDepTasks),"_lockDae",type)//daeSchedule.outgoingDepTasks |> task => destroyLockByDepTask(task, "_lockDae", type); separator="\n" + let destroyLocksZeroFunc = destroyArrayLocks(listLength(zeroFuncSchedule.outgoingDepTasks),"_lockZeroFunc",type)//daeSchedule.outgoingDepTasks |> task => destroyLockByDepTask(task, "_lockDae", type); separator="\n" match type case ("openmp") then << <%destroyLocksOde%> <%destroyLocksDae%> + <%destroyLocksZeroFunc%> >> case "mpi" then << @@ -659,11 +675,12 @@ template generateAdditionalDestructorBodyStatements(Option <%destroyLocksOde%> <%destroyLocksDae%> + <%destroyLocksZeroFunc%> <%threadLocksDel%> <%threadLocksDel1%> <%destroyThreads%> >> - case SOME((odeSchedule as TASKDEPSCHEDULE(__),_)) then + case SOME((odeSchedule as TASKDEPSCHEDULE(__),_,_)) then match type case ("tbb") then << @@ -671,6 +688,8 @@ template generateAdditionalDestructorBodyStatements(Option* >::iterator it = _tbbNodeList_DAE.begin(); it != _tbbNodeList_DAE.end(); it++) delete *it; + for(std::vector* >::iterator it = _tbbNodeList_ZeroFunc.begin(); it != _tbbNodeList_ZeroFunc.end(); it++) + delete *it; >> else "" else "" @@ -684,132 +703,154 @@ template update(list allEquationsPlusWhen, list when match simCode case SIMCODE(modelInfo = MODELINFO(__), hpcomData=HPCOMDATA(__)) then - let parCode = generateParallelEvaluate(allEquationsPlusWhen, modelInfo.name, whenClauses, simCode, extraFuncs ,extraFuncsDecl, extraFuncsNamespace, hpcomData.schedules, context, lastIdentOfPath(modelInfo.name), useFlatArrayNotation) + let parCode = generateParallelEvaluate(allEquationsPlusWhen, modelInfo.name, whenClauses, simCode, extraFuncs ,extraFuncsDecl, extraFuncsNamespace, hpcomData.schedules, context, stateDerVectorName, lastIdentOfPath(modelInfo.name), useFlatArrayNotation) << <%equationFunctions(allEquations,whenClauses, simCode, &extraFuncs, &extraFuncsDecl, extraFuncsNamespace, contextSimulationDiscrete,stateDerVectorName,useFlatArrayNotation,false)%> - <%createEvaluateAll(allEquations,whenClauses,simCode , &extraFuncs , &extraFuncsDecl, extraFuncsNamespace,contextOther, stateDerVectorName, useFlatArrayNotation)%> - - <%createEvaluateZeroFuncs(equationsForZeroCrossings, simCode, &extraFuncs, &extraFuncsDecl, extraFuncsNamespace, contextOther) %> - <%createEvaluateConditions(allEquations,whenClauses, simCode, &extraFuncs, &extraFuncsDecl, extraFuncsNamespace, contextOther, stateDerVectorName, useFlatArrayNotation)%> + /* + <%createEvaluateZeroFuncs(equationsForZeroCrossings,simCode , &extraFuncs , &extraFuncsDecl, extraFuncsNamespace,contextOther)%> + + <%createEvaluateAll(allEquations,whenClauses,simCode , &extraFuncs , &extraFuncsDecl, extraFuncsNamespace,contextOther, stateDerVectorName, useFlatArrayNotation, boolNot(stringEq(getConfigString(PROFILING_LEVEL),"none")))%> + */ <%parCode%> >> end match end update; -template createEvaluateAll(list allEquationsPlusWhen,list whenClauses, SimCode simCode ,Text& extraFuncs,Text& extraFuncsDecl,Text extraFuncsNamespace, Context context, Text stateDerVectorName /*=__zDot*/, Boolean useFlatArrayNotation) +template generateParallelEvaluate(list allEquationsPlusWhen, Absyn.Path name, + list whenClauses, SimCode simCode, Text& extraFuncs, Text& extraFuncsDecl, Text extraFuncsNamespace, Option> schedulesOpt, Context context, Text stateDerVectorName /*=__zDot*/, + String modelNamePrefixStr, Boolean useFlatArrayNotation) ::= let &varDecls = buffer "" /*BUFD*/ let reinit = (whenClauses |> when hasindex i0 => genreinits(when, &varDecls,i0,simCode , &extraFuncs , &extraFuncsDecl, extraFuncsNamespace,context, stateDerVectorName, useFlatArrayNotation) ;separator="\n";empty) + + let measureTimeEvaluateOdeStart = if boolNot(stringEq(getConfigString(PROFILING_LEVEL),"none")) then generateMeasureTimeStartCode("measuredFunctionStartValues", "evaluateODE", "MEASURETIME_MODELFUNCTIONS") else "" + let measureTimeEvaluateOdeEnd = if boolNot(stringEq(getConfigString(PROFILING_LEVEL),"none")) then generateMeasureTimeEndCode("measuredFunctionStartValues", "measuredFunctionEndValues", "measureTimeFunctionsArray[0]", "evaluateODE", "MEASURETIME_MODELFUNCTIONS") else "" + + let measureTimeEvaluateAllStart = if boolNot(stringEq(getConfigString(PROFILING_LEVEL),"none")) then generateMeasureTimeStartCode("measuredFunctionStartValues", "evaluateAll", "MEASURETIME_MODELFUNCTIONS") else "" + let measureTimeEvaluateAllEnd = if boolNot(stringEq(getConfigString(PROFILING_LEVEL),"none")) then generateMeasureTimeEndCode("measuredFunctionStartValues", "measuredFunctionEndValues", "measureTimeFunctionsArray[1]", "evaluateAll", "MEASURETIME_MODELFUNCTIONS") else "" + + let measureTimeEvaluateZeroFuncStart = if boolNot(stringEq(getConfigString(PROFILING_LEVEL),"none")) then generateMeasureTimeStartCode("measuredFunctionStartValues", "evaluateZeroFuncs", "MEASURETIME_MODELFUNCTIONS") else "" + let measureTimeEvaluateZeroFuncEnd = if boolNot(stringEq(getConfigString(PROFILING_LEVEL),"none")) then generateMeasureTimeEndCode("measuredFunctionStartValues", "measuredFunctionEndValues", "measureTimeFunctionsArray[4]", "evaluateZeroFuncs", "MEASURETIME_MODELFUNCTIONS") else "" + + let type = getConfigString(HPCOM_CODE) + + // Head of function is the same for all schedulers and parallelization methods: + let functionHead = << - bool <%lastIdentOfPathFromSimCode(simCode , &extraFuncs , &extraFuncsDecl, extraFuncsNamespace)%>::evaluateAll(const UPDATETYPE command) + //using type: <%type%> + + void <%lastIdentOfPath(name)%>::evaluateZeroFuncs(const UPDATETYPE command) { + <%measureTimeEvaluateZeroFuncStart%> + evaluateParallel(command, 1); + <%measureTimeEvaluateZeroFuncEnd%> + } + + bool <%lastIdentOfPath(name)%>::evaluateAll(const UPDATETYPE command) + { + <%measureTimeEvaluateAllStart%> + bool state_var_reinitialized = false; <%varDecls%> - evaluateParallel(command, false); - + evaluateParallel(command, -1); <%reinit%> + <%measureTimeEvaluateAllEnd%> return state_var_reinitialized; } - >> -end createEvaluateAll; - -template generateParallelEvaluate(list allEquationsPlusWhen, Absyn.Path name, - list whenClauses, SimCode simCode, Text& extraFuncs, Text& extraFuncsDecl, Text extraFuncsNamespace, Option> schedulesOpt, Context context, - String modelNamePrefixStr, Boolean useFlatArrayNotation) -::= - let &varDecls = buffer "" /*BUFD*/ - /* let all_equations = (allEquationsPlusWhen |> eqs => (eqs |> eq => - equation_(eq, contextSimulationDiscrete, &varDecls /*BUFC*/,simCode, extraFuncs, extraFuncsDecl, extraFuncsNamespace)) - ;separator="\n") */ - /* let reinit = (whenClauses |> when hasindex i0 => genreinits(when, &varDecls,i0,simCode, extraFuncs, extraFuncsDecl, extraFuncsNamespace,context) - ;separator="\n";empty) */ - - // Head of function is the same for all schedulers and parallelization methods: - let functionHead = - ' - void <%lastIdentOfPath(name)%>::evaluateODE(const UPDATETYPE command) - { - evaluateParallel(command, true); - } - - void <%lastIdentOfPath(name)%>::evaluateParallel(const UPDATETYPE command, bool evaluateODE) - ' + void <%lastIdentOfPath(name)%>::evaluateODE(const UPDATETYPE command) + { + <%measureTimeEvaluateOdeStart%> + evaluateParallel(command, 0); + <%measureTimeEvaluateOdeEnd%> + } - let type = getConfigString(HPCOM_CODE) + //evaluateMode = 0 : evaluateODE + //evaluateMode < 0 : evaluateAll + //evaluateMode > 0 : evaluateZeroFunc + void <%lastIdentOfPath(name)%>::evaluateParallel(const UPDATETYPE command, int evaluateMode) + >> match schedulesOpt - case SOME((odeSchedule as EMPTYSCHEDULE(tasks=SERIALTASKLIST(tasks=taskListOde)), daeSchedule as EMPTYSCHEDULE(tasks=SERIALTASKLIST(tasks=taskListDae)))) then + case SOME((odeSchedule as EMPTYSCHEDULE(tasks=SERIALTASKLIST(tasks=taskListOde)), daeSchedule as EMPTYSCHEDULE(tasks=SERIALTASKLIST(tasks=taskListDae)), zeroFuncsSchedule as EMPTYSCHEDULE(tasks=SERIALTASKLIST(tasks=taskListZeroFunc)))) then << <%functionHead%> { - if(evaluateODE) + if(evaluateMode == 0) //evaluate ODE { - <%function_HPCOM_Thread0(allEquationsPlusWhen, taskListOde, 1, "", "", &varDecls, simCode, extraFuncs, extraFuncsDecl, extraFuncsNamespace, useFlatArrayNotation)%> + <%parallelThreadCodeWithSplit(allEquationsPlusWhen, taskListOde, 1, 1, "", "", &varDecls, simCode, extraFuncs, extraFuncsDecl, lastIdentOfPath(name), "evaluateODE_Th1", useFlatArrayNotation)%> } - else + else if(evaluateMode < 0) //evaluate All { - <%function_HPCOM_Thread0(allEquationsPlusWhen, taskListDae, 1, "", "", &varDecls, simCode, extraFuncs, extraFuncsDecl, extraFuncsNamespace, useFlatArrayNotation)%> + <%parallelThreadCodeWithSplit(allEquationsPlusWhen, taskListDae, 1, 1, "", "", &varDecls, simCode, extraFuncs, extraFuncsDecl, lastIdentOfPath(name), "evaluateAll_Th1", useFlatArrayNotation)%> + } + else //evaluate ZeroFuncs + { + <%parallelThreadCodeWithSplit(allEquationsPlusWhen, taskListZeroFunc, 1, 1, "", "", &varDecls, simCode, extraFuncs, extraFuncsDecl, lastIdentOfPath(name), "evaluateZeroFunc_Th1", useFlatArrayNotation)%> } } >> - case SOME((odeSchedule as LEVELSCHEDULE(useFixedAssignments=false, tasksOfLevels=tasksOfLevelsOde), daeSchedule as LEVELSCHEDULE(useFixedAssignments=false, tasksOfLevels=tasksOfLevelsDae))) then - let odeEqs = tasksOfLevelsOde |> tasks => generateLevelCodeForLevel(allEquationsPlusWhen, tasks, type, &varDecls, simCode, extraFuncs, extraFuncsDecl, extraFuncsNamespace, useFlatArrayNotation); separator="\n" - let daeEqs = tasksOfLevelsDae |> tasks => generateLevelCodeForLevel(allEquationsPlusWhen, tasks, type, &varDecls, simCode, extraFuncs, extraFuncsDecl, extraFuncsNamespace, useFlatArrayNotation); separator="\n" + case SOME((odeSchedule as LEVELSCHEDULE(useFixedAssignments=false, tasksOfLevels=tasksOfLevelsOde), daeSchedule as LEVELSCHEDULE(useFixedAssignments=false, tasksOfLevels=tasksOfLevelsDae), zeroFuncSchedule as LEVELSCHEDULE(useFixedAssignments=false, tasksOfLevels=tasksOfLevelsZeroFunc))) then + let odeEqs = tasksOfLevelsOde |> tasks => generateLevelCodeForLevel(allEquationsPlusWhen, tasks, type, &varDecls, simCode, extraFuncs, extraFuncsDecl, lastIdentOfPath(name), useFlatArrayNotation); separator="\n" + let daeEqs = tasksOfLevelsDae |> tasks => generateLevelCodeForLevel(allEquationsPlusWhen, tasks, type, &varDecls, simCode, extraFuncs, extraFuncsDecl, lastIdentOfPath(name), useFlatArrayNotation); separator="\n" + let zeroFuncEqs = tasksOfLevelsZeroFunc |> tasks => generateLevelCodeForLevel(allEquationsPlusWhen, tasks, type, &varDecls, simCode, extraFuncs, extraFuncsDecl, lastIdentOfPath(name), useFlatArrayNotation); separator="\n" match type case ("openmp") then + let &extraFuncsDecl += << - <%functionHead%> + void evaluateODE_Parallel(); + void evaluateAll_Parallel(); + void evaluateZeroFuncs_Parallel(); + >> + + << + void <%lastIdentOfPath(name)%>::evaluateODE_Parallel() { - this->_evaluateODE = evaluateODE; - this->_command = command; - <%generateMeasureTimeStartCode("measuredFunctionStartValues", "evaluateODE", "MEASURETIME_MODELFUNCTIONS")%> - <%if boolNot(stringEq(getConfigString(PROFILING_LEVEL),"none")) then '//MeasureTimeValues **threadValues = new MeasureTimeValues*[<%getConfigInt(NUM_PROC)%>];'%> #pragma omp parallel num_threads(<%getConfigInt(NUM_PROC)%>) { - <%if boolNot(stringEq(getConfigString(PROFILING_LEVEL),"none")) then - << - /*MeasureTimeValues *valuesStart = MeasureTime::getZeroValues(); - MeasureTimeValues *valuesEnd = MeasureTime::getZeroValues(); - <%generateMeasureTimeStartCode('valuesStart', "evaluateODEInner", "MEASURETIME_MODELFUNCTIONS")%>*/ - >>%> - - if(_evaluateODE) - { - <%odeEqs%> - } - else - { - <%daeEqs%> - } - - <%if boolNot(stringEq(getConfigString(PROFILING_LEVEL),"none")) then - << - /*MeasureTime::getTimeValuesEnd(valuesEnd); - valuesEnd->sub(valuesStart); - valuesEnd->sub(MeasureTime::getOverhead()); - #pragma omp critical - { - measureTimeArrayHpcom[0].sumMeasuredValues->add(valuesEnd); - } - delete valuesStart; - delete valuesEnd;*/ - >>%> + <%odeEqs%> } - <%if boolNot(stringEq(getConfigString(PROFILING_LEVEL),"none")) then - << - /*delete threadValues; - ++(measureTimeArrayHpcom[0].numCalcs);*/ - >>%> + } + + void <%lastIdentOfPath(name)%>::evaluateAll_Parallel() + { + #pragma omp parallel num_threads(<%getConfigInt(NUM_PROC)%>) + { + <%daeEqs%> + } + } - <%generateMeasureTimeEndCode("measuredFunctionStartValues", "measuredFunctionEndValues", "measureTimeFunctionsArray[0]", "evaluateODE", "MEASURETIME_MODELFUNCTIONS")%> + void <%lastIdentOfPath(name)%>::evaluateZeroFuncs_Parallel() + { + #pragma omp parallel num_threads(<%getConfigInt(NUM_PROC)%>) + { + <%zeroFuncEqs%> + } + } + + <%functionHead%> + { + this->_evaluateMode = _evaluateMode; + this->_command = command; + if(evaluateMode == 0) + { + evaluateODE_Parallel(); + } + else if(evaluateMode < 0) + { + evaluateAll_Parallel(); + } + else + { + evaluateZeroFuncs_Parallel(); + } } >> else @@ -820,48 +861,124 @@ template generateParallelEvaluate(list allEquationsPlusWhen, Absyn. } >> end match - case SOME((odeSchedule as LEVELSCHEDULE(useFixedAssignments=true), daeSchedule as LEVELSCHEDULE(useFixedAssignments=true))) then + case SOME((odeSchedule as LEVELSCHEDULE(useFixedAssignments=true), daeSchedule as LEVELSCHEDULE(useFixedAssignments=true), zeroFuncSchedule as LEVELSCHEDULE(useFixedAssignments=true))) then match type case ("pthreads") case ("pthreads_spin") then - let &mainThreadCode = buffer "" /*BUFD*/ - let eqsFuncs = arrayList(HpcOmScheduler.convertFixedLevelScheduleToTaskLists(odeSchedule, daeSchedule, getConfigInt(NUM_PROC))) |> tasks hasindex i0 fromindex 0 => generateLevelFixedCodeForThread(allEquationsPlusWhen, tasks, i0, type, &varDecls, name, simCode, extraFuncs, extraFuncsDecl, extraFuncsNamespace, &mainThreadCode, useFlatArrayNotation); separator="\n" + let eqsFuncs = arrayList(HpcOmScheduler.convertFixedLevelScheduleToTaskLists(odeSchedule, daeSchedule, zeroFuncSchedule, getConfigInt(NUM_PROC))) |> tasks hasindex i0 fromindex 0 => generateLevelFixedCodeForThread(allEquationsPlusWhen, tasks, i0, type, &varDecls, name, simCode, extraFuncs, extraFuncsDecl, lastIdentOfPath(name), useFlatArrayNotation); separator="\n" let threadLocks = List.intRange(getConfigInt(NUM_PROC)) |> tt => createLockByLockName('threadLock<%tt%>', "", type); separator="\n" << <%eqsFuncs%> <%functionHead%> { - <%generateMeasureTimeStartCode("measuredFunctionStartValues", "evaluateODE", "MEASURETIME_MODELFUNCTIONS")%> this->_command = command; - this->_evaluateODE = evaluateODE; - //_evaluateBarrier.wait(); //start calculation - <%mainThreadCode%> - //_evaluateBarrier.wait(); //calculation finished + this->_evaluateMode = evaluateMode; + + if(evaluateMode == 0) //evaluate ODE + { + _levelBarrier.wait(); + evaluateThreadFuncODE_0(); + _levelBarrier.wait(); - <%generateStateVarPrefetchCode(simCode, extraFuncs, extraFuncsDecl, extraFuncsNamespace)%> - <%generateMeasureTimeEndCode("measuredFunctionStartValues", "measuredFunctionEndValues", "measureTimeFunctionsArray[0]", "evaluateODE", "MEASURETIME_MODELFUNCTIONS")%> + <%generateStateVarPrefetchCode(simCode, extraFuncs, extraFuncsDecl, extraFuncsNamespace)%> + } + else if(evaluateMode < 0) //evaluate All + { + _levelBarrier.wait(); + evaluateThreadFuncAll_0(); + _levelBarrier.wait(); + } + else //evaluate ZeroFuncs + { + _levelBarrier.wait(); + evaluateThreadFuncZeroFunc_0(); + _levelBarrier.wait(); + } } >> else "" end match - case SOME((odeSchedule as THREADSCHEDULE(__), daeSchedule as THREADSCHEDULE(__))) then + case SOME((odeSchedule as THREADSCHEDULE(threadTasks=threadTasksOde), daeSchedule as THREADSCHEDULE(threadTasks=threadTasksDae), zeroFuncSchedule as THREADSCHEDULE(threadTasks=threadTasksZeroFunc))) then match type case ("openmp") then - let taskEqs = function_HPCOM_Thread(allEquationsPlusWhen, odeSchedule.threadTasks, daeSchedule.threadTasks, type, &varDecls, simCode, extraFuncs, extraFuncsDecl, extraFuncsNamespace, useFlatArrayNotation); separator="\n" + let threadAssignLocksOde = arrayList(threadTasksOde) |> tt hasindex i0 fromindex 0 => function_HPCOM_assignThreadLocks(arrayGet(threadTasksOde, intAdd(i0, 1)), "_lockOde", i0, type); separator="\n" + let threadReleaseLocksOde = arrayList(threadTasksOde) |> tt hasindex i0 fromindex 0 => function_HPCOM_releaseThreadLocks(arrayGet(threadTasksOde, intAdd(i0, 1)), "_lockOde", i0, type); separator="\n" + let threadAssignLocksDae = arrayList(threadTasksOde) |> tt hasindex i0 fromindex 0 => function_HPCOM_assignThreadLocks(arrayGet(threadTasksDae, intAdd(i0, 1)), "_lockDae", i0, type); separator="\n" + let threadReleaseLocksDae = arrayList(threadTasksOde) |> tt hasindex i0 fromindex 0 => function_HPCOM_releaseThreadLocks(arrayGet(threadTasksDae, intAdd(i0, 1)), "_lockDae", i0, type); separator="\n" + let threadAssignLocksZeroFunc = arrayList(threadTasksZeroFunc) |> tt hasindex i0 fromindex 0 => function_HPCOM_assignThreadLocks(arrayGet(threadTasksZeroFunc, intAdd(i0, 1)), "_lockZeroFunc", i0, type); separator="\n" + let threadReleaseLocksZeroFunc = arrayList(threadTasksZeroFunc) |> tt hasindex i0 fromindex 0 => function_HPCOM_releaseThreadLocks(arrayGet(threadTasksZeroFunc, intAdd(i0, 1)), "_lockZeroFunc", i0, type); separator="\n" + + let odeEqs = arrayList(threadTasksOde) |> tt hasindex i0 => parallelThreadCodeWithSplit(allEquationsPlusWhen,tt,i0,intSub(arrayLength(threadTasksOde),1),type,"_lockOde",&varDecls,simCode, extraFuncs, extraFuncsDecl, lastIdentOfPath(name), "evaluateODE", useFlatArrayNotation); separator="\n" + let daeEqs = arrayList(threadTasksDae) |> tt hasindex i0 => parallelThreadCodeWithSplit(allEquationsPlusWhen,tt,i0,intSub(arrayLength(threadTasksDae),1),type,"_lockDae",&varDecls,simCode, extraFuncs, extraFuncsDecl, lastIdentOfPath(name), "evaluateAll", useFlatArrayNotation); separator="\n" + let zeroFuncEqs = arrayList(threadTasksZeroFunc) |> tt hasindex i0 => parallelThreadCodeWithSplit(allEquationsPlusWhen,tt,i0,intSub(arrayLength(threadTasksZeroFunc),1),type,"_lockZeroFunc",&varDecls,simCode, extraFuncs, extraFuncsDecl, lastIdentOfPath(name), "evaluateZeroFunc", useFlatArrayNotation); separator="\n" + + let &extraFuncsDecl += + << + void evaluateODE_Parallel(); + void evaluateAll_Parallel(); + void evaluateZeroFuncs_Parallel(); + >> << - //using type: <%type%> + void <%lastIdentOfPath(name)%>::evaluateODE_Parallel() + { + #pragma omp parallel num_threads(<%getConfigInt(NUM_PROC)%>) + { + int threadNum = getThreadNumber(); + <%threadAssignLocksOde%> + #pragma omp barrier + <%odeEqs%> + #pragma omp barrier + <%threadReleaseLocksOde%> + } + } + + void <%lastIdentOfPath(name)%>::evaluateAll_Parallel() + { + #pragma omp parallel num_threads(<%getConfigInt(NUM_PROC)%>) + { + int threadNum = getThreadNumber(); + <%threadAssignLocksDae%> + #pragma omp barrier + <%daeEqs%> + #pragma omp barrier + <%threadReleaseLocksDae%> + } + } + + void <%lastIdentOfPath(name)%>::evaluateZeroFuncs_Parallel() + { + #pragma omp parallel num_threads(<%getConfigInt(NUM_PROC)%>) + { + int threadNum = getThreadNumber(); + <%threadAssignLocksZeroFunc%> + #pragma omp barrier + <%zeroFuncEqs%> + #pragma omp barrier + <%threadReleaseLocksZeroFunc%> + } + } + <%functionHead%> { - this->_evaluateODE = evaluateODE; + this->_evaluateMode = _evaluateMode; this->_command = command; - <%&varDecls%> - <%taskEqs%> + if(evaluateMode == 0) + { + evaluateODE_Parallel(); + } + else if(evaluateMode < 0) + { + evaluateAll_Parallel(); + } + else + { + evaluateZeroFuncs_Parallel(); + } } >> case ("mpi") then << - //using type: <%type%> and threadscheduling <%functionHead%> { // MFlehmig: Todo @@ -869,16 +986,15 @@ template generateParallelEvaluate(list allEquationsPlusWhen, Absyn. >> else let &mainThreadCode = buffer "" /*BUFD*/ - let threadFuncs = List.intRange(arrayLength(odeSchedule.threadTasks)) |> threadIdx => generateThreadFunc(allEquationsPlusWhen, arrayGet(odeSchedule.threadTasks, threadIdx), arrayGet(daeSchedule.threadTasks, threadIdx), type, intSub(threadIdx, 1), modelNamePrefixStr, &varDecls, simCode, extraFuncs, extraFuncsDecl, extraFuncsNamespace, &mainThreadCode, useFlatArrayNotation); separator="\n" + let threadFuncs = List.intRange(arrayLength(odeSchedule.threadTasks)) |> threadIdx => generateThreadFunc(allEquationsPlusWhen, arrayGet(odeSchedule.threadTasks, threadIdx), arrayGet(daeSchedule.threadTasks, threadIdx), arrayGet(zeroFuncSchedule.threadTasks, threadIdx), type, intSub(threadIdx, 1), modelNamePrefixStr, &varDecls, simCode, extraFuncs, extraFuncsDecl, lastIdentOfPath(name), &mainThreadCode, useFlatArrayNotation); separator="\n" let threadAssignLocks1 = List.rest(arrayList(odeSchedule.threadTasks)) |> tt hasindex i0 fromindex 1 => assignLockByLockName(i0, "th_lock1", type); separator="\n" let threadReleaseLocks = List.rest(arrayList(odeSchedule.threadTasks)) |> tt hasindex i0 fromindex 1 => releaseLockByLockName(i0, "th_lock", type); separator="\n" << <%threadFuncs%> - //using type: <%type%> <%functionHead%> { - this->_evaluateODE = evaluateODE; + this->_evaluateMode = _evaluateMode; this->_command = command; <%threadReleaseLocks%> <%mainThreadCode%> @@ -886,32 +1002,35 @@ template generateParallelEvaluate(list allEquationsPlusWhen, Absyn. } >> end match - case SOME((odeSchedule as TASKDEPSCHEDULE(__), daeSchedule as TASKDEPSCHEDULE(__))) then + case SOME((odeSchedule as TASKDEPSCHEDULE(__), daeSchedule as TASKDEPSCHEDULE(__), zeroFuncSchedule as TASKDEPSCHEDULE(__))) then match type case ("openmp") then let odeTaskEqs = function_HPCOM_TaskDep(odeSchedule.tasks, allEquationsPlusWhen, type, &varDecls, simCode, extraFuncs, extraFuncsDecl, extraFuncsNamespace, useFlatArrayNotation); separator="\n" let daeTaskEqs = function_HPCOM_TaskDep(daeSchedule.tasks, allEquationsPlusWhen, type, &varDecls, simCode, extraFuncs, extraFuncsDecl, extraFuncsNamespace, useFlatArrayNotation); separator="\n" + let zeroFuncTaskEqs = function_HPCOM_TaskDep(zeroFuncSchedule.tasks, allEquationsPlusWhen, type, &varDecls, simCode, extraFuncs, extraFuncsDecl, extraFuncsNamespace, useFlatArrayNotation); separator="\n" << - //using type: <%type%> <%functionHead%> { - this->_evaluateODE = evaluateODE; + this->_evaluateMode = _evaluateMode; this->_command = command; <%&varDecls%> - if(_evaluateODE) + if(_evaluateMode == 0) { <%odeTaskEqs%> } - else + else if(_evaluateMode < 0) { <%daeTaskEqs%> } + else + { + <%zeroFuncTaskEqs%> + } } >> case ("tbb") then - let taskFuncs = function_HPCOM_TaskDep_voidfunc(odeSchedule.tasks, daeSchedule.tasks, allEquationsPlusWhen,type, name, &varDecls, simCode, extraFuncs, extraFuncsDecl, extraFuncsNamespace, useFlatArrayNotation); separator="\n" + let taskFuncs = function_HPCOM_TaskDep_voidfunc(odeSchedule.tasks, daeSchedule.tasks, zeroFuncSchedule.tasks, allEquationsPlusWhen,type, name, &varDecls, simCode, extraFuncs, extraFuncsDecl, extraFuncsNamespace, useFlatArrayNotation); separator="\n" << - //using type: <%type%> //void functions for functionhandling in tbb_nodes <%taskFuncs%> @@ -919,7 +1038,7 @@ template generateParallelEvaluate(list allEquationsPlusWhen, Absyn. { //Start #if TBB_INTERFACE_VERSION >= 8000 - _tbbArena.execute(_tbbArenaFunctor); + _tbbArena.execute(_tbbArenaFunctor); #else _tbbStartNode.try_put(tbb::flow::continue_msg()); _tbbGraph.wait_for_all(); @@ -976,18 +1095,43 @@ template generateLevelCodeForTask(list allEquationsPlusWhen, Task i << #pragma omp section { - <%function_HPCOM_Task(allEquationsPlusWhen, iTask, iType, "", &varDecls, simCode, extraFuncs, extraFuncsDecl, extraFuncsNamespace, useFlatArrayNotation)%> + <%taskCode(allEquationsPlusWhen, iTask, iType, "", &varDecls, simCode, extraFuncs, extraFuncsDecl, extraFuncsNamespace, useFlatArrayNotation)%> } >> end generateLevelCodeForTask; -template generateLevelFixedCodeForThread(list allEquationsPlusWhen, tuple>,list>> tasksOfLevels, Integer iThreadIdx, String iType, Text &varDecls, Absyn.Path name, SimCode simCode, Text& extraFuncs, Text& extraFuncsDecl, Text extraFuncsNamespace, Text &mainThreadCode, Boolean useFlatArrayNotation) +template generateLevelFixedCodeForThread(list allEquationsPlusWhen, tuple>,list>,list>> tasksOfLevels, Integer iThreadIdx, String iType, Text &varDecls, Absyn.Path name, SimCode simCode, Text& extraFuncs, Text& extraFuncsDecl, Text extraFuncsNamespace, Boolean useFlatArrayNotation) ::= match(tasksOfLevels) - case((odeTasksOfLevel, daeTasksOfLevel)) then + case((odeTasksOfLevel, daeTasksOfLevel, zeroFuncTasksOfLevel)) then let odeEqs = odeTasksOfLevel |> tasks hasindex levelIdx => generateLevelFixedCodeForThreadLevel(allEquationsPlusWhen, tasks, iThreadIdx, iType, levelIdx, &varDecls, simCode, extraFuncs, extraFuncsDecl, extraFuncsNamespace, useFlatArrayNotation); separator="\n" let daeEqs = daeTasksOfLevel |> tasks hasindex levelIdx => generateLevelFixedCodeForThreadLevel(allEquationsPlusWhen, tasks, iThreadIdx, iType, levelIdx, &varDecls, simCode, extraFuncs, extraFuncsDecl, extraFuncsNamespace, useFlatArrayNotation); separator="\n" - if (intGt(iThreadIdx, 0)) then + let zeroFuncEqs = zeroFuncTasksOfLevel |> tasks hasindex levelIdx => generateLevelFixedCodeForThreadLevel(allEquationsPlusWhen, tasks, iThreadIdx, iType, levelIdx, &varDecls, simCode, extraFuncs, extraFuncsDecl, extraFuncsNamespace, useFlatArrayNotation); separator="\n" + let &extraFuncsDecl += + << + void evaluateThreadFuncODE_<%iThreadIdx%>(); + void evaluateThreadFuncAll_<%iThreadIdx%>(); + void evaluateThreadFuncZeroFunc_<%iThreadIdx%>(); + void evaluateThreadFunc<%iThreadIdx%>(); + <%\n%> + >> + << + void <%lastIdentOfPath(name)%>::evaluateThreadFuncODE_<%iThreadIdx%>() + { + <%odeEqs%> + } + + void <%lastIdentOfPath(name)%>::evaluateThreadFuncAll_<%iThreadIdx%>() + { + <%daeEqs%> + } + + void <%lastIdentOfPath(name)%>::evaluateThreadFuncZeroFunc_<%iThreadIdx%>() + { + <%zeroFuncEqs%> + } + + <%if (intGt(iThreadIdx, 0)) then << void <%lastIdentOfPath(name)%>::evaluateThreadFunc<%iThreadIdx%>() { @@ -1008,24 +1152,21 @@ template generateLevelFixedCodeForThread(list allEquationsPlusWhen, break; } <%if boolNot(stringEq(getConfigString(PROFILING_LEVEL),"none")) then '<%generateMeasureTimeStartCode("valuesStart", 'evaluateODEThread<%iThreadIdx%>', "MEASURETIME_MODELFUNCTIONS")%>'%> - if(_evaluateODE) + if(_evaluateMode == 0) { - <%odeEqs%> + evaluateThreadFuncODE_<%iThreadIdx%>(); + } + else if(_evaluateMode < 0) + { + evaluateThreadFuncAll_<%iThreadIdx%>(); } else { - <%daeEqs%> + evaluateThreadFuncZeroFunc_<%iThreadIdx%>(); } <%if boolNot(stringEq(getConfigString(PROFILING_LEVEL),"none")) then << - //MeasureTime::getTimeValuesEnd(valuesEnd); - //valuesEnd->sub(valuesStart); - //valuesEnd->sub(MeasureTime::getOverhead()); - - //_measureTimeArrayLock.lock(); - //measureTimeArrayHpcom[0].sumMeasuredValues->add(valuesEnd); - //_measureTimeArrayLock.unlock(); <%generateMeasureTimeEndCode("valuesStart", "valuesEnd", 'measureTimeArrayHpcom[<%iThreadIdx%>]', 'evaluateODEThread<%iThreadIdx%>', "MEASURETIME_MODELFUNCTIONS")%> >>%> @@ -1039,29 +1180,14 @@ template generateLevelFixedCodeForThread(list allEquationsPlusWhen, >>%> } >> - else - let &mainThreadCode += - ' - _levelBarrier.wait(); - if(_evaluateODE) - { - <%odeEqs%> - } - else - { - <%daeEqs%> - } - _levelBarrier.wait(); - ' - << - - >> + %> + >> end generateLevelFixedCodeForThread; template generateLevelFixedCodeForThreadLevel(list allEquationsPlusWhen, list tasksOfLevel, Integer iThreadIdx, String iType, Integer iLevelIdx, Text &varDecls, SimCode simCode, Text& extraFuncs, Text& extraFuncsDecl, Text extraFuncsNamespace, Boolean useFlatArrayNotation) ::= - let tasks = tasksOfLevel |> t => function_HPCOM_Task(allEquationsPlusWhen, t, iType, "", varDecls, simCode, extraFuncs, extraFuncsDecl, extraFuncsNamespace, useFlatArrayNotation); separator="\n" + let tasks = tasksOfLevel |> t => taskCode(allEquationsPlusWhen, t, iType, "", varDecls, simCode, extraFuncs, extraFuncsDecl, extraFuncsNamespace, useFlatArrayNotation); separator="\n" << //Start of Level <%iLevelIdx%> <%if intEq(iThreadIdx, 0) then @@ -1105,7 +1231,7 @@ template function_HPCOM_TaskDep0(tuple> taskIn, list p => 't[<%p%>]'; separator = "," let taskDependencies = parents |> p => '<%p%>'; separator = "," let depIn = if intGt(listLength(parents),0) then 'depend(in:<%parentDependencies%>) ' else "" @@ -1119,14 +1245,16 @@ template function_HPCOM_TaskDep0(tuple> taskIn, list>> odeTasks, list>> daeTasks, String modelNamePrefixStr) +template generateTbbConstructorExtension(list>> odeTasks, list>> daeTasks, list>> zeroFuncTasks, String modelNamePrefixStr) ::= let odeNodesAndEdges = odeTasks |> t hasindex i fromindex 0 => generateTbbConstructorExtensionNodesAndEdges(t,i,"ODE",modelNamePrefixStr); separator="\n" let daeNodesAndEdges = daeTasks |> t hasindex i fromindex 0 => generateTbbConstructorExtensionNodesAndEdges(t,i,"DAE",modelNamePrefixStr); separator="\n" + let zeroFuncNodesAndEdges = zeroFuncTasks |> t hasindex i fromindex 0 => generateTbbConstructorExtensionNodesAndEdges(t,i,"ZeroFunc",modelNamePrefixStr); separator="\n" << tbb::flow::continue_node *tbb_task; <%odeNodesAndEdges%> <%daeNodesAndEdges%> + <%zeroFuncNodesAndEdges%> #if TBB_INTERFACE_VERSION >= 8000 _tbbArena = tbb::task_arena(<%getConfigInt(NUM_PROC)%>); _tbbArenaFunctor = TbbArenaFunctor(_tbbGraph,_tbbStartNode); @@ -1149,14 +1277,16 @@ template generateTbbConstructorExtensionNodesAndEdges(tuple> end match end generateTbbConstructorExtensionNodesAndEdges; -template function_HPCOM_TaskDep_voidfunc(list>> odeTasks, list>> daeTasks, list allEquationsPlusWhen, +template function_HPCOM_TaskDep_voidfunc(list>> odeTasks, list>> daeTasks, list>> zeroFuncTasks, list allEquationsPlusWhen, String iType, Absyn.Path name, Text &varDecls, SimCode simCode, Text& extraFuncs, Text& extraFuncsDecl, Text extraFuncsNamespace, Boolean useFlatArrayNotation) ::= let funcTasksOde = odeTasks |> t => function_HPCOM_TaskDep_voidfunc0(t,allEquationsPlusWhen,iType, "ODE", name, &varDecls, simCode, extraFuncs, extraFuncsDecl, extraFuncsNamespace, useFlatArrayNotation); separator="\n" let funcTasksDae = daeTasks |> t => function_HPCOM_TaskDep_voidfunc0(t,allEquationsPlusWhen,iType, "DAE", name, &varDecls, simCode, extraFuncs, extraFuncsDecl, extraFuncsNamespace, useFlatArrayNotation); separator="\n" + let funcTasksZeroFunc = zeroFuncTasks |> t => function_HPCOM_TaskDep_voidfunc0(t,allEquationsPlusWhen,iType, "ZeroFunc", name, &varDecls, simCode, extraFuncs, extraFuncsDecl, extraFuncsNamespace, useFlatArrayNotation); separator="\n" << <%funcTasksOde%> <%funcTasksDae%> + <%funcTasksZeroFunc%> >> end function_HPCOM_TaskDep_voidfunc; @@ -1165,7 +1295,7 @@ template function_HPCOM_TaskDep_voidfunc0(tuple> taskIn, list match taskIn case ((task as CALCTASK(__),parents)) then let &tempvarDecl = buffer "" /*BUFD*/ - let taskEqs = function_HPCOM_Task(allEquationsPlusWhen, task, iType, "", &tempvarDecl, simCode, extraFuncs, extraFuncsDecl, extraFuncsNamespace,useFlatArrayNotation); separator="\n" + let taskEqs = taskCode(allEquationsPlusWhen, task, iType, "", &tempvarDecl, simCode, extraFuncs, extraFuncsDecl, extraFuncsNamespace,useFlatArrayNotation); separator="\n" << void <%lastIdentOfPath(name)%>::task_func_<%funcSuffix%>_<%task.index%>() { @@ -1176,99 +1306,86 @@ template function_HPCOM_TaskDep_voidfunc0(tuple> taskIn, list end match end function_HPCOM_TaskDep_voidfunc0; -template function_HPCOM_Thread(list allEquationsPlusWhen, array> threadTasksOde, array> threadTasksDae, String iType,Text &varDecls, SimCode simCode, Text& extraFuncs, Text& extraFuncsDecl, Text extraFuncsNamespace, Boolean useFlatArrayNotation) +/* +template function_HPCOM_Thread(list allEquationsPlusWhen, array> threadTasksOde, array> threadTasksDae, array> threadTasksZeroFunc, String iType,Text &varDecls, SimCode simCode, Text& extraFuncs, Text& extraFuncsDecl, Text extraFuncsNamespace, Boolean useFlatArrayNotation) ::= - let odeEqs = arrayList(threadTasksOde) |> tt hasindex i0 => function_HPCOM_Thread0(allEquationsPlusWhen,tt,i0,iType,"_lockOde",&varDecls,simCode, extraFuncs, extraFuncsDecl, extraFuncsNamespace, useFlatArrayNotation); separator="\n" - let daeEqs = arrayList(threadTasksDae) |> tt hasindex i0 => function_HPCOM_Thread0(allEquationsPlusWhen,tt,i0,iType,"_lockDae",&varDecls,simCode, extraFuncs, extraFuncsDecl, extraFuncsNamespace, useFlatArrayNotation); separator="\n" + let odeEqs = arrayList(threadTasksOde) |> tt hasindex i0 => parallelThreadCodeWithSplit(allEquationsPlusWhen,tt,i0,iType,"_lockOde",&varDecls,simCode, extraFuncs, extraFuncsDecl, extraFuncsNamespace, "evaluateODE", useFlatArrayNotation); separator="\n" + let daeEqs = arrayList(threadTasksDae) |> tt hasindex i0 => parallelThreadCodeWithSplit(allEquationsPlusWhen,tt,i0,iType,"_lockDae",&varDecls,simCode, extraFuncs, extraFuncsDecl, extraFuncsNamespace, "evaluateAll", useFlatArrayNotation); separator="\n" + let zeroFuncEqs = arrayList(threadTasksDae) |> tt hasindex i0 => parallelThreadCodeWithSplit(allEquationsPlusWhen,tt,i0,iType,"_lockZeroFunc",&varDecls,simCode, extraFuncs, extraFuncsDecl, extraFuncsNamespace, "evaluateZeroFunc", useFlatArrayNotation); separator="\n" match iType - case ("openmp") then - let threadAssignLocksOde = arrayList(threadTasksOde) |> tt hasindex i0 fromindex 0 => function_HPCOM_assignThreadLocks(arrayGet(threadTasksOde, intAdd(i0, 1)), "_lockOde", i0, iType); separator="\n" - let threadReleaseLocksOde = arrayList(threadTasksOde) |> tt hasindex i0 fromindex 0 => function_HPCOM_releaseThreadLocks(arrayGet(threadTasksOde, intAdd(i0, 1)), "_lockOde", i0, iType); separator="\n" - let threadAssignLocksDae = arrayList(threadTasksOde) |> tt hasindex i0 fromindex 0 => function_HPCOM_assignThreadLocks(arrayGet(threadTasksDae, intAdd(i0, 1)), "_lockDae", i0, iType); separator="\n" - let threadReleaseLocksDae = arrayList(threadTasksOde) |> tt hasindex i0 fromindex 0 => function_HPCOM_releaseThreadLocks(arrayGet(threadTasksDae, intAdd(i0, 1)), "_lockDae", i0, iType); separator="\n" - - << - #pragma omp parallel num_threads(<%arrayLength(threadTasksOde)%>) - { - int threadNum = omp_get_thread_num(); - <%if boolNot(stringEq(getConfigString(PROFILING_LEVEL),"none")) then - << - MeasureTimeValues *measuredSchedulerStartValues = MeasureTime::getZeroValues(); - MeasureTimeValues *measuredSchedulerEndValues = MeasureTime::getZeroValues(); - >> - %> - if(_evaluateODE) - { - <%generateMeasureTimeStartCode("measuredSchedulerStartValues", "evaluateODE_threads", "MEASURETIME_MODELFUNCTIONS")%> - //Assign locks first - <%threadAssignLocksOde%> - #pragma omp barrier - <%odeEqs%> - //Release locks after calculation - #pragma omp barrier - <%threadReleaseLocksOde%> - <%generateMeasureTimeEndCode("measuredSchedulerStartValues", "measuredSchedulerEndValues", "measureTimeThreadArrayOdeHpcom[threadNum]", "evaluateODE_threads", "MEASURETIME_MODELFUNCTIONS")%> - } - else - { - <%generateMeasureTimeStartCode("measuredSchedulerStartValues", "evaluateDAE_threads", "MEASURETIME_MODELFUNCTIONS")%> - //Assign locks first - <%threadAssignLocksDae%> - #pragma omp barrier - <%daeEqs%> - //Release locks after calculation - #pragma omp barrier - <%threadReleaseLocksDae%> - <%generateMeasureTimeEndCode("measuredSchedulerStartValues", "measuredSchedulerEndValues", "measureTimeThreadArrayDaeHpcom[threadNum]", "evaluateDAE_threads", "MEASURETIME_MODELFUNCTIONS")%> - } - <%if boolNot(stringEq(getConfigString(PROFILING_LEVEL),"none")) then - << - delete measuredSchedulerStartValues; - delete measuredSchedulerEndValues; - >> - %> - } - >> case ("mpi") then << int world_rank; MPI_Comm_rank(MPI_COMM_WORLD, &world_rank); - if(_evaluateOde) + if(_evaluateMode == 0) { <%odeEqs%> } - else + else if(_evaluateMode < 0) { <%daeEqs%> } + else + { + <%zeroFuncEqs%> + } >> else << - if(_evaluateOde) + if(_evaluateMode == 0) { <%generateMeasureTimeStartCode("measuredSchedulerStartValues", "evaluateODE_threads", "MEASURETIME_MODELFUNCTIONS")%> <%odeEqs%> <%generateMeasureTimeEndCode("measuredSchedulerStartValues", "measuredSchedulerEndValues", "measureTimeThreadArrayOdeHpcom[threadNum]", "evaluateODE_threads", "MEASURETIME_MODELFUNCTIONS")%> } - else + else if(_evaluateMode < 0) { <%generateMeasureTimeStartCode("measuredSchedulerStartValues", "evaluateDAE_threads", "MEASURETIME_MODELFUNCTIONS")%> <%daeEqs%> <%generateMeasureTimeEndCode("measuredSchedulerStartValues", "measuredSchedulerEndValues", "measureTimeThreadArrayDaeHpcom[threadNum]", "evaluateDAE_threads", "MEASURETIME_MODELFUNCTIONS")%> } + else + { + <%generateMeasureTimeStartCode("measuredSchedulerStartValues", "evaluateZeroFunc_threads", "MEASURETIME_MODELFUNCTIONS")%> + <%zeroFuncEqs%> + <%generateMeasureTimeEndCode("measuredSchedulerStartValues", "measuredSchedulerEndValues", "measureTimeThreadArrayZeroFuncHpcom[threadNum]", "evaluateZeroFunc_threads", "MEASURETIME_MODELFUNCTIONS")%> + } >> end match end function_HPCOM_Thread; - -template generateThreadFunc(list allEquationsPlusWhen, list threadTasksOde, list threadTasksDae, String iType, Integer iThreadIdx, String modelNamePrefixStr, Text &varDecls, SimCode simCode, Text& extraFuncs, Text& extraFuncsDecl, Text extraFuncsNamespace, Text& mainThreadCode, Boolean useFlatArrayNotation) +*/ +template generateThreadFunc(list allEquationsPlusWhen, list threadTasksOde, list threadTasksDae, list threadTasksZeroFunc, String iType, Integer iThreadIdx, String modelNamePrefixStr, Text &varDecls, SimCode simCode, Text& extraFuncs, Text& extraFuncsDecl, Text extraFuncsNamespace, Text& mainThreadCode, Boolean useFlatArrayNotation) ::= let &varDeclsLoc = buffer "" /*BUFD*/ - let taskEqsOde = function_HPCOM_Thread0(allEquationsPlusWhen, threadTasksOde, iThreadIdx, iType, "_lockOde", &varDeclsLoc, simCode, extraFuncs, extraFuncsDecl, extraFuncsNamespace, useFlatArrayNotation); separator="\n" - let taskEqsDae = function_HPCOM_Thread0(allEquationsPlusWhen, threadTasksDae, iThreadIdx, iType, "_lockDae", &varDeclsLoc, simCode, extraFuncs, extraFuncsDecl, extraFuncsNamespace, useFlatArrayNotation); separator="\n" + let taskEqsOde = parallelThreadCode(allEquationsPlusWhen, threadTasksOde, iThreadIdx, iType, "_lockOde", &varDeclsLoc, simCode, extraFuncs, extraFuncsDecl, extraFuncsNamespace, "evaluateODE", useFlatArrayNotation); separator="\n" + let taskEqsDae = parallelThreadCode(allEquationsPlusWhen, threadTasksDae, iThreadIdx, iType, "_lockDae", &varDeclsLoc, simCode, extraFuncs, extraFuncsDecl, extraFuncsNamespace, "evaluateAll", useFlatArrayNotation); separator="\n" + let taskEqsZeroFunc = parallelThreadCode(allEquationsPlusWhen, threadTasksZeroFunc, iThreadIdx, iType, "_lockZeroFunc", &varDeclsLoc, simCode, extraFuncs, extraFuncsDecl, extraFuncsNamespace, "evaluateZeroFunc", useFlatArrayNotation); separator="\n" let assLock = assignLockByLockName(iThreadIdx, "th_lock", iType); separator="\n" let relLock = releaseLockByLockName(iThreadIdx, "th_lock1", iType); separator="\n" + let &extraFuncsDecl += + << + void evaluateThreadFuncODE_<%iThreadIdx%>(); + void evaluateThreadFuncAll_<%iThreadIdx%>(); + void evaluateThreadFuncZeroFunc_<%iThreadIdx%>(); + >> + if (intGt(iThreadIdx, 0)) then << + void <%modelNamePrefixStr%>::evaluateThreadFuncODE_<%iThreadIdx%>() + { + <%taskEqsOde%> + } + + void <%modelNamePrefixStr%>::evaluateThreadFuncAll_<%iThreadIdx%>() + { + <%taskEqsDae%> + } + + void <%modelNamePrefixStr%>::evaluateThreadFuncZeroFunc_<%iThreadIdx%>() + { + <%taskEqsZeroFunc%> + } + void <%modelNamePrefixStr%>::evaluateThreadFunc<%iThreadIdx%>() { #ifdef MEASURETIME_MODELFUNCTIONS @@ -1282,13 +1399,17 @@ template generateThreadFunc(list allEquationsPlusWhen, list t if(_terminateThreads) return; - if(_evaluateODE) + if(_evaluateMode == 0) { - <%taskEqsOde%> + evaluateThreadFuncODE_<%iThreadIdx%>(); + } + else if(_evaluateMode < 0) + { + evaluateThreadFuncAll_<%iThreadIdx%>(); } else { - <%taskEqsDae%> + evaluateThreadFuncZeroFunc_<%iThreadIdx%>(); } <%relLock%> } @@ -1297,20 +1418,39 @@ template generateThreadFunc(list allEquationsPlusWhen, list t else let &mainThreadCode += &varDeclsLoc let &mainThreadCode += - ' - #ifdef MEASURETIME_MODELFUNCTIONS - MeasureTimeValues *measuredSchedulerStartValues = measuredSchedulerStartValues_0; - MeasureTimeValues *measuredSchedulerEndValues = measuredSchedulerEndValues_0; - #endif //MEASURETIME_MODELFUNCTIONS - if(_evaluateODE) - { - <%taskEqsOde%> - } - else - { - <%taskEqsDae%> - }' + << + #ifdef MEASURETIME_MODELFUNCTIONS + MeasureTimeValues *measuredSchedulerStartValues = measuredSchedulerStartValues_0; + MeasureTimeValues *measuredSchedulerEndValues = measuredSchedulerEndValues_0; + #endif //MEASURETIME_MODELFUNCTIONS + if(_evaluateMode == 0) + { + evaluateThreadFuncODE_<%iThreadIdx%>(); + } + else if(_evaluateMode < 0) + { + evaluateThreadFuncAll_<%iThreadIdx%>(); + } + else + { + evaluateThreadFuncZeroFunc_<%iThreadIdx%>(); + } + >> << + void <%modelNamePrefixStr%>::evaluateThreadFuncODE_<%iThreadIdx%>() + { + <%taskEqsOde%> + } + + void <%modelNamePrefixStr%>::evaluateThreadFuncAll_<%iThreadIdx%>() + { + <%taskEqsDae%> + } + + void <%modelNamePrefixStr%>::evaluateThreadFuncZeroFunc_<%iThreadIdx%>() + { + <%taskEqsZeroFunc%> + } >> end generateThreadFunc; @@ -1346,33 +1486,52 @@ template function_HPCOM_releaseThreadLocks(list iThreadTasks, String iLock >> end function_HPCOM_releaseThreadLocks; -template function_HPCOM_Thread0(list allEquationsPlusWhen, list threadTaskList, Integer iThreadNum, - String iType, String lockPrefix, Text &varDecls, SimCode simCode, Text& extraFuncs, Text& extraFuncsDecl, Text extraFuncsNamespace, Boolean useFlatArrayNotation) +template parallelThreadCodeWithSplit(list allEquationsPlusWhen, list threadTaskList, Integer iThreadNum, Integer iMaxThreadNumber, + String iType, String lockPrefix, Text &varDecls, SimCode simCode, Text& extraFuncs, Text& extraFuncsDecl, + Text extraFuncsNamespace, String extraFunctionName, Boolean useFlatArrayNotation) ::= - let threadTasks = threadTaskList |> tt => function_HPCOM_Task(allEquationsPlusWhen,tt,iType,lockPrefix,&varDecls,simCode, extraFuncs, extraFuncsDecl, extraFuncsNamespace,useFlatArrayNotation); separator="\n" + let functionCalls = List.partition(threadTaskList, 100) |> tt hasindex i0 => parallelThreadCode(allEquationsPlusWhen,tt,i0,iType,lockPrefix,&varDecls,simCode, extraFuncs, extraFuncsDecl, extraFuncsNamespace, '<%extraFunctionName%>_Th<%iThreadNum%>', useFlatArrayNotation); separator="\n" match iType case ("openmp") then << - <%if intNe(iThreadNum, 0) then 'else ' else ''%>if(threadNum == <%iThreadNum%>) - { - <%threadTasks%> - } + <%if intEq(iThreadNum, 0) then 'switch(threadNum) <%\n%>{<%\n%>' else '' %>case <%iThreadNum%>: + <%functionCalls%> + break; + <%if intEq(iThreadNum, iMaxThreadNumber) then '<%\n%>}' else ''%> >> case ("mpi") then << if (world_rank == <%iThreadNum%>) { - <%threadTasks%> + <%functionCalls%> } >> else << - <%threadTasks%> + <%functionCalls%> >> end match -end function_HPCOM_Thread0; +end parallelThreadCodeWithSplit; + +template parallelThreadCode(list allEquationsPlusWhen, list threadTaskList, Integer iPartitionIndex, + String iType, String lockPrefix, Text &varDecls, SimCode simCode, Text& extraFuncs, Text& extraFuncsDecl, Text extraFuncsNamespace, String extraFunctionName, Boolean useFlatArrayNotation) +::= + let threadTasks = threadTaskList |> tt => taskCode(allEquationsPlusWhen,tt,iType,lockPrefix,&varDecls,simCode, extraFuncs, extraFuncsDecl, extraFuncsNamespace,useFlatArrayNotation); separator="\n" + let &extraFuncs += + << + void <%extraFuncsNamespace%>::<%extraFunctionName%>_<%iPartitionIndex%>() + { + <%threadTasks%> + }<%\n%><%\n%> + >> + let &extraFuncsDecl += 'void <%extraFunctionName%>_<%iPartitionIndex%>();' + + << + <%extraFunctionName%>_<%iPartitionIndex%>(); + >> +end parallelThreadCode; -template function_HPCOM_Task(list allEquationsPlusWhen, Task iTask, String iType, String lockPrefix, Text &varDecls, +template taskCode(list allEquationsPlusWhen, Task iTask, String iType, String lockPrefix, Text &varDecls, SimCode simCode, Text& extraFuncs, Text& extraFuncsDecl, Text extraFuncsNamespace, Boolean useFlatArrayNotation) ::= match iTask @@ -1403,7 +1562,7 @@ template function_HPCOM_Task(list allEquationsPlusWhen, Task iTask, <%relLck%> >> end match -end function_HPCOM_Task; +end taskCode; template equationNamesHPCOM_(Integer idx, list allEquationsPlusWhen, Context context, Text &varDecls, SimCode simCode, Text& extraFuncs, Text& extraFuncsDecl, Text extraFuncsNamespace, Boolean useFlatArrayNotation) ::= diff --git a/Compiler/Template/CodegenFMU.tpl b/Compiler/Template/CodegenFMU.tpl index becc820bfcd..13ef7b3918f 100644 --- a/Compiler/Template/CodegenFMU.tpl +++ b/Compiler/Template/CodegenFMU.tpl @@ -46,8 +46,10 @@ package CodegenFMU import interface SimCodeTV; +import interface SimCodeBackendTV; 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) +import CodegenCFunctions.*; import CodegenFMUCommon.*; import CodegenFMU1; import CodegenFMU2; diff --git a/Compiler/Template/CodegenFMU1.tpl b/Compiler/Template/CodegenFMU1.tpl index bd7be01981f..55f9e166548 100644 --- a/Compiler/Template/CodegenFMU1.tpl +++ b/Compiler/Template/CodegenFMU1.tpl @@ -46,6 +46,7 @@ package CodegenFMU1 import interface SimCodeTV; +import interface SimCodeBackendTV; 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) import CodegenFMUCommon.*; diff --git a/Compiler/Template/CodegenFMU2.tpl b/Compiler/Template/CodegenFMU2.tpl index 139dff799c9..6f96c47c768 100644 --- a/Compiler/Template/CodegenFMU2.tpl +++ b/Compiler/Template/CodegenFMU2.tpl @@ -46,6 +46,7 @@ package CodegenFMU2 import interface SimCodeTV; +import interface SimCodeBackendTV; 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) import CodegenFMUCommon.*; diff --git a/Compiler/Template/CodegenFMUCommon.tpl b/Compiler/Template/CodegenFMUCommon.tpl index b25ec4071f2..0f543211e89 100644 --- a/Compiler/Template/CodegenFMUCommon.tpl +++ b/Compiler/Template/CodegenFMUCommon.tpl @@ -46,8 +46,10 @@ package CodegenFMUCommon import interface SimCodeTV; +import interface SimCodeBackendTV; 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) +import CodegenCFunctions.*; template ModelExchange(SimCode simCode) "Generates ModelExchange code for ModelDescription file for FMU target." diff --git a/Compiler/Template/CodegenFMUCpp.tpl b/Compiler/Template/CodegenFMUCpp.tpl index 0a70d7c5903..cb705c37e3f 100644 --- a/Compiler/Template/CodegenFMUCpp.tpl +++ b/Compiler/Template/CodegenFMUCpp.tpl @@ -48,6 +48,7 @@ package CodegenFMUCpp import interface SimCodeTV; +import interface SimCodeBackendTV; import CodegenUtil.*; import CodegenCpp.*; //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) import CodegenFMU.*; diff --git a/Compiler/Template/CodegenQSS.tpl b/Compiler/Template/CodegenQSS.tpl index 20e0fbf99d2..531a497d914 100644 --- a/Compiler/Template/CodegenQSS.tpl +++ b/Compiler/Template/CodegenQSS.tpl @@ -51,8 +51,9 @@ package CodegenQSS import interface SimCodeTV; +import interface SimCodeQSSTV; import CodegenUtil.*; -import CodegenC.*; +import CodegenCFunctions.*; template translateModel(SimCode simCode,QSSinfo qssInfo) "Generates C code and Makefile for compiling and running a simulation of a @@ -443,7 +444,7 @@ void fsolve<%ls.index%>(<% /* Fill B */ <%ls.beqs |> exp hasindex i0 => 'gsl_vector_set(b<%ls.index%>,<%i0%>,<% - System.stringReplace(CodegenC.daeExp( + System.stringReplace(daeExp( BackendQSS.replaceVarsInputs(exp,BackendQSS.getRHSVars(ls.beqs,ls.vars,ls.simJac,states,disc,algs)), contextOther,&preExp,&varDecls,&auxFunctionIgnore),"$P","") %>);';separator=\n%> @@ -453,7 +454,7 @@ void fsolve<%ls.index%>(<% /* Fill A */ gsl_matrix_set_zero(A<%ls.index%>); <%ls.simJac |> (row, col, eq as SES_RESIDUAL(__)) => - 'gsl_matrix_set(A<%ls.index%>, <%row%>, <%col%>,<% System.stringReplace(CodegenC.daeExp( + 'gsl_matrix_set(A<%ls.index%>, <%row%>, <%col%>,<% System.stringReplace(daeExp( BackendQSS.replaceVarsInputs(eq.exp,BackendQSS.getRHSVars(ls.beqs,ls.vars,ls.simJac,states,disc,algs)), contextOther,&preExp,&varDecls,&auxFunctionIgnore),"$P","") %>);' ;separator="\n"%> diff --git a/Compiler/Template/Makefile.common b/Compiler/Template/Makefile.common index 70a00920270..cd07f0dd911 100644 --- a/Compiler/Template/Makefile.common +++ b/Compiler/Template/Makefile.common @@ -1,6 +1,6 @@ .PHONY : all -GENERATED_FILES=AbsynDumpTpl.mo CodegenUtil.mo CodegenC.mo CodegenFMUCommon.mo CodegenFMU.mo CodegenFMU1.mo CodegenFMU2.mo CodegenCSharp.mo CodegenQSS.mo CodegenCpp.mo CodegenCppHpcom.mo CodegenFMUCpp.mo CodegenCppInit.mo CodegenModelica.mo DAEDumpTpl.mo ExpressionDumpTpl.mo GraphvizDump.mo GraphMLDumpTpl.mo NFInstDumpTpl.mo SimCodeDump.mo Unparsing.mo SCodeDumpTpl.mo CodegenAdevs.mo CodegenSparseFMI.mo CodegenXML.mo CodegenJava.mo CodegenJS.mo TplCodegen.mo TaskSystemDump.mo GenerateAPIFunctionsTpl.mo VisualXMLTpl.mo +GENERATED_FILES=AbsynDumpTpl.mo CodegenUtil.mo CodegenC.mo CodegenCFunctions.mo CodegenFMUCommon.mo CodegenFMU.mo CodegenFMU1.mo CodegenFMU2.mo CodegenCSharp.mo CodegenQSS.mo CodegenCpp.mo CodegenCppHpcom.mo CodegenFMUCpp.mo CodegenCppInit.mo CodegenModelica.mo DAEDumpTpl.mo ExpressionDumpTpl.mo GraphvizDump.mo GraphMLDumpTpl.mo NFInstDumpTpl.mo SimCodeDump.mo Unparsing.mo SCodeDumpTpl.mo CodegenAdevs.mo CodegenSparseFMI.mo CodegenXML.mo CodegenJava.mo CodegenJS.mo TplCodegen.mo TaskSystemDump.mo GenerateAPIFunctionsTpl.mo VisualXMLTpl.mo all : $(GENERATED_FILES) @@ -24,7 +24,12 @@ CodegenUtil.mo : CodegenUtil.tpl SimCodeTV.mo $(OMC) $< > $@.log || (cat $@.log && false) @echo " " -CodegenC.mo : CodegenC.tpl SimCodeTV.mo CodegenUtil.tpl +CodegenC.mo : CodegenC.tpl CodegenCFunctions.tpl SimCodeTV.mo CodegenUtil.tpl + @echo " ** CodegenC template compilation ** " + $(OMC) $< > $@.log || (cat $@.log && false) + @echo " " + +CodegenCFunctions.mo : CodegenCFunctions.tpl SimCodeTV.mo CodegenUtil.tpl @echo " ** CodegenC template compilation ** " $(OMC) $< > $@.log || (cat $@.log && false) @echo " " @@ -35,19 +40,19 @@ CodegenCSharp.mo : CodegenCSharp.tpl SimCodeTV.mo @echo " " # FMU -CodegenFMUCommon.mo : CodegenFMUCommon.tpl SimCodeTV.mo CodegenC.tpl CodegenUtil.tpl +CodegenFMUCommon.mo : CodegenFMUCommon.tpl SimCodeTV.mo SimCodeBackendTV.mo CodegenC.tpl CodegenCFunctions.tpl CodegenUtil.tpl @echo " ** CodegenFMUCommon template compilation ** " $(OMC) $< > $@.log || (cat $@.log && false) @echo " " -CodegenFMU.mo : CodegenFMU.tpl CodegenFMUCommon.tpl CodegenFMUCommon.mo SimCodeTV.mo CodegenC.tpl CodegenUtil.tpl +CodegenFMU.mo : CodegenFMU.tpl CodegenFMUCommon.tpl CodegenFMUCommon.mo SimCodeTV.mo SimCodeBackendTV.mo CodegenC.tpl CodegenCFunctions.tpl CodegenUtil.tpl @echo " ** CodegenFMU template compilation ** " $(OMC) $< > $@.log || (cat $@.log && false) @echo " " -CodegenFMU1.mo : CodegenFMU1.tpl CodegenFMUCommon.tpl CodegenFMUCommon.mo SimCodeTV.mo CodegenC.tpl CodegenUtil.tpl +CodegenFMU1.mo : CodegenFMU1.tpl CodegenFMUCommon.tpl CodegenFMUCommon.mo SimCodeTV.mo SimCodeBackendTV.mo CodegenC.tpl CodegenUtil.tpl @echo " ** CodegenFMU1 template compilation ** " $(OMC) $< > $@.log || (cat $@.log && false) @echo " " -CodegenFMU2.mo : CodegenFMU2.tpl CodegenFMUCommon.tpl CodegenFMUCommon.mo SimCodeTV.mo CodegenC.tpl CodegenUtil.tpl +CodegenFMU2.mo : CodegenFMU2.tpl CodegenFMUCommon.tpl CodegenFMUCommon.mo SimCodeTV.mo SimCodeBackendTV.mo CodegenC.tpl CodegenUtil.tpl @echo " ** CodegenFMU2 template compilation ** " $(OMC) $< > $@.log || (cat $@.log && false) @echo " " @@ -77,7 +82,7 @@ SimCodeDump.mo : SimCodeDump.tpl SimCodeTV.mo CodegenUtil.tpl SCodeDumpTpl.tpl $(OMC) $< > $@.log || (cat $@.log && false) @echo " " -CodegenQSS.mo : CodegenQSS.tpl SimCodeTV.mo CodegenC.tpl CodegenUtil.tpl +CodegenQSS.mo : CodegenQSS.tpl SimCodeTV.mo SimCodeQSSTV.mo CodegenCFunctions.tpl CodegenUtil.tpl @echo " ** CodegenQSS template compilation ** " $(OMC) $< > $@.log || (cat $@.log && false) @echo " " @@ -87,12 +92,12 @@ CodegenCpp.mo : CodegenCpp.tpl SimCodeTV.mo CodegenUtil.tpl CodegenCppInit.tpl $(OMC) $< > $@.log || (cat $@.log && false) @echo " " -CodegenCppHpcom.mo : CodegenCppHpcom.tpl SimCodeTV.mo CodegenCpp.tpl CodegenUtil.tpl +CodegenCppHpcom.mo : CodegenCppHpcom.tpl SimCodeTV.mo SimCodeBackendTV.mo CodegenCpp.tpl CodegenUtil.tpl @echo " ** CodegenCppHpcom template compilation ** " $(OMC) $< > $@.log || (cat $@.log && false) @echo " " -CodegenFMUCpp.mo : CodegenFMUCpp.tpl SimCodeTV.mo CodegenC.tpl CodegenUtil.tpl CodegenCpp.tpl CodegenFMU.tpl +CodegenFMUCpp.mo : CodegenFMUCpp.tpl SimCodeTV.mo SimCodeBackendTV.mo CodegenC.tpl CodegenUtil.tpl CodegenCpp.tpl CodegenFMU.tpl @echo " ** CodegenFMUCpp template compilation ** " $(OMC) $< > $@.log || (cat $@.log && false) @echo " " @@ -107,7 +112,7 @@ ExpressionDumpTpl.mo : ExpressionDumpTpl.tpl ExpressionDumpTV.mo DAEDumpTpl.tpl $(OMC) $< > $@.log || (cat $@.log && false) @echo " " -GraphvizDump.mo : GraphvizDump.tpl +GraphvizDump.mo : GraphvizDump.tpl SimCodeTV.mo SimCodeBackendTV.mo @echo " ** GraphvizDump template compilation ** " $(OMC) $< > $@.log || (cat $@.log && false) @echo " " @@ -151,7 +156,7 @@ GenerateAPIFunctionsTpl.mo : GenerateAPIFunctionsTpl.tpl SimCodeTV.mo @echo " ** GenerateAPIFunctionsTpl template compilation ** " $(OMC) $< > $@.log || (cat $@.log && false) @echo " " - + VisualXMLTpl.mo : VisualXMLTpl.tpl VisualXMLTplTV.mo @echo " ** VisualXMLTpl template compilation ** " $(OMC) $< > $@.log || (cat $@.log && false) diff --git a/Compiler/Template/SimCodeBackendTV.mo b/Compiler/Template/SimCodeBackendTV.mo new file mode 100644 index 00000000000..95d9e4f33e5 --- /dev/null +++ b/Compiler/Template/SimCodeBackendTV.mo @@ -0,0 +1,277 @@ +interface package SimCodeBackendTV + +package BackendVariable + + function isStateVar + input BackendDAE.Var inVar; + output Boolean outBoolean; + end isStateVar; + +end BackendVariable; + + +package HpcOmSimCode + uniontype HpcOmData + record HPCOMDATA + Option> schedules; + Option hpcOmMemory; + end HPCOMDATA; + end HpcOmData; + + uniontype CommunicationInfo //stores more detailed information about a communication (edge) + record COMMUNICATION_INFO + list floatVars; //the float, int and boolean variables that have to be transfered + list intVars; + list boolVars; + end COMMUNICATION_INFO; + end CommunicationInfo; + + uniontype Task + record CALCTASK //Task which calculates something + Integer weighting; + Integer index; + Real calcTime; + Real timeFinished; + Integer threadIdx; + list eqIdc; + end CALCTASK; + record CALCTASK_LEVEL + list eqIdc; + list nodeIdc; + Option threadIdx; + end CALCTASK_LEVEL; + record DEPTASK + Task sourceTask; + Task targetTask; + Boolean outgoing; //true if the dependency is leading to the task of another thread + Integer id; + CommunicationInfo communicationInfo; + end DEPTASK; + end Task; + + uniontype TaskList + record PARALLELTASKLIST + list tasks; + end PARALLELTASKLIST; + record SERIALTASKLIST + list tasks; + end SERIALTASKLIST; + end TaskList; + + uniontype Schedule + record LEVELSCHEDULE + list tasksOfLevels; + Boolean useFixedAssignments; + end LEVELSCHEDULE; + record THREADSCHEDULE + array> threadTasks; + list outgoingDepTasks; + end THREADSCHEDULE; + record TASKDEPSCHEDULE + list>> tasks; + end TASKDEPSCHEDULE; + record EMPTYSCHEDULE + TaskList tasks; + end EMPTYSCHEDULE; + end Schedule; + + uniontype MemoryMap + record MEMORYMAP_ARRAY + Integer floatArraySize; + Integer intArraySize; + Integer boolArraySize; + end MEMORYMAP_ARRAY; + end MemoryMap; +end HpcOmSimCode; + +package HpcOmScheduler + function convertFixedLevelScheduleToTaskLists + input HpcOmSimCode.Schedule iOdeSchedule; + input HpcOmSimCode.Schedule iDaeSchedule; + input HpcOmSimCode.Schedule iZeroFuncSchedule; + input Integer iNumOfThreads; + output array>,list>,list>>> oThreadLevelTasks; + end convertFixedLevelScheduleToTaskLists; +end HpcOmScheduler; + +package HpcOmSimCodeMain + function getSimCodeEqByIndex + input list iEqs; + input Integer iIdx; + output SimCode.SimEqSystem oEq; + end getSimCodeEqByIndex; +end HpcOmSimCodeMain; + + +package FMI + uniontype Info + record INFO + String fmiVersion; + Integer fmiType; + String fmiModelName; + String fmiModelIdentifier; + String fmiGuid; + String fmiDescription; + String fmiGenerationTool; + String fmiGenerationDateAndTime; + String fmiVariableNamingConvention; + list fmiNumberOfContinuousStates; + list fmiNumberOfEventIndicators; + end INFO; + end Info; + + uniontype TypeDefinitions + record ENUMERATIONTYPE + String name; + String description; + String quantity; + Integer min; + Integer max; + list items; + end ENUMERATIONTYPE; + end TypeDefinitions; + + uniontype EnumerationItem + record ENUMERATIONITEM + String name; + String description; + end ENUMERATIONITEM; + end EnumerationItem; + + uniontype ExperimentAnnotation + record EXPERIMENTANNOTATION + Real fmiExperimentStartTime; + Real fmiExperimentStopTime; + Real fmiExperimentTolerance; + end EXPERIMENTANNOTATION; + end ExperimentAnnotation; + + uniontype ModelVariables + record REALVARIABLE + Integer instance; + String name; + String description; + String baseType; + String variability; + String causality; + Boolean hasStartValue; + Real startValue; + Boolean isFixed; + Real valueReference; + Integer x1Placement; + Integer x2Placement; + Integer y1Placement; + Integer y2Placement; + end REALVARIABLE; + + record INTEGERVARIABLE + Integer instance; + String name; + String description; + String baseType; + String variability; + String causality; + Boolean hasStartValue; + Integer startValue; + Boolean isFixed; + Real valueReference; + Integer x1Placement; + Integer x2Placement; + Integer y1Placement; + Integer y2Placement; + end INTEGERVARIABLE; + + record BOOLEANVARIABLE + Integer instance; + String name; + String description; + String baseType; + String variability; + String causality; + Boolean hasStartValue; + Boolean startValue; + Boolean isFixed; + Real valueReference; + Integer x1Placement; + Integer x2Placement; + Integer y1Placement; + Integer y2Placement; + end BOOLEANVARIABLE; + + record STRINGVARIABLE + Integer instance; + String name; + String description; + String baseType; + String variability; + String causality; + Boolean hasStartValue; + String startValue; + Boolean isFixed; + Real valueReference; + Integer x1Placement; + Integer x2Placement; + Integer y1Placement; + Integer y2Placement; + end STRINGVARIABLE; + + record ENUMERATIONVARIABLE + Integer instance; + String name; + String description; + String baseType; + String variability; + String causality; + Boolean hasStartValue; + Integer startValue; + Boolean isFixed; + Real valueReference; + Integer x1Placement; + Integer x2Placement; + Integer y1Placement; + Integer y2Placement; + end ENUMERATIONVARIABLE; + end ModelVariables; + + uniontype FmiImport + record FMIIMPORT + String platform; + String fmuFileName; + String fmuWorkingDirectory; + Integer fmiLogLevel; + Boolean fmiDebugOutput; + Option fmiContext; + Option fmiInstance; + Info fmiInfo; + list fmiTypeDefinitionsList; + ExperimentAnnotation fmiExperimentAnnotation; + Option fmiModelVariablesInstance; + list fmiModelVariablesList; + Boolean generateInputConnectors; + Boolean generateOutputConnectors; + end FMIIMPORT; + end FmiImport; + + function getFMIType + input Info inFMIInfo; + output String fmiType; + end getFMIType; + + function isFMIVersion20 "Checks if the FMI version is 2.0." + input String inFMUVersion; + 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 inTypeDefinitionsList; + input String inBaseType; + output String outEnumerationType; + end getEnumerationTypeFromTypes; +end FMI; + +end SimCodeBackendTV; diff --git a/Compiler/Template/SimCodeQSSTV.mo b/Compiler/Template/SimCodeQSSTV.mo new file mode 100644 index 00000000000..8971f30cce1 --- /dev/null +++ b/Compiler/Template/SimCodeQSSTV.mo @@ -0,0 +1,145 @@ +interface package SimCodeQSSTV + +package BackendQSS + uniontype QSSinfo "- equation indices in static blocks and DEVS structure" + record QSSINFO + list> stateVarIndex; + list stateVars; + list discreteAlgVars; + list algVars; + BackendDAE.EqSystems eqs; + list zcs; + Integer zc_offset; + end QSSINFO; + end QSSinfo; + + function getStateIndexList + input QSSinfo qssInfo; + output list> refs; + end getStateIndexList; + + function getStates + input QSSinfo qssInfo; + output list refs; + end getStates; + + function getDisc + input QSSinfo qssInfo; + output list refs; + end getDisc; + function replaceVars + input DAE.Exp exp; + input list states; + input list disc; + input list algs; + output DAE.Exp expout; + end replaceVars; + + function replaceCref + input DAE.ComponentRef cr; + input list states; + input list disc; + input list algs; + output String out; + end replaceCref; + + function getAlgs + input QSSinfo qssInfo; + output list refs; + end getAlgs; + + function negate + input DAE.Exp exp; + output DAE.Exp exp_out; + end negate; + + function getEqs + input QSSinfo qssInfo; + output BackendDAE.EquationArray eqs; + end getEqs; + + function generateHandler + input BackendDAE.EquationArray eqs; + input list handlers; + input list states; + input list disc; + input list algs; + input DAE.Exp condition; + input Boolean v; + input list zc_exps; + input Integer offset; + output String out; + end generateHandler; + + + function getRHSVars + input list beqs; + input list vars; + input list> simJac; + input list states; + input list disc; + input list algs; + output list out; + end getRHSVars; + + function getDiscRHSVars + input list beqs; + input list vars; + input list> simJac; + input list states; + input list disc; + input list algs; + output list out; + end getDiscRHSVars; + + + function generateDInit + input list disc; + //input list sample; + input SimCodeVar.SimVars vars; + input Integer acc; + input Integer total; + input Integer nWhenClause; + output String out; + end generateDInit; + + function generateExtraParams + input SimCode.SimEqSystem eq; + input SimCodeVar.SimVars vars; + output String s; + end generateExtraParams; + + function generateInitialParamEquations + input SimCode.SimEqSystem eq; + output String t; + end generateInitialParamEquations; + + function replaceVarsInputs + input DAE.Exp exp; + input list inp; + output DAE.Exp exp_out; + end replaceVarsInputs; + + function simpleWhens + input list i; + output list o; + end simpleWhens; + + function sampleWhens + input list i; + output list o; + end sampleWhens; + + function getZCOffset + input QSSinfo qssInfo; + output Integer o; + end getZCOffset; + + function getZCExps + input QSSinfo qssInfo; + output list exps; + end getZCExps; + +end BackendQSS; + +end SimCodeQSSTV; diff --git a/Compiler/Template/SimCodeTV.mo b/Compiler/Template/SimCodeTV.mo index 18250e489d6..9ec3bfd3543 100644 --- a/Compiler/Template/SimCodeTV.mo +++ b/Compiler/Template/SimCodeTV.mo @@ -731,11 +731,110 @@ package SimCode end SimCode; package SimCodeUtil + function appendLists + input list inEqn1; + input list inEqn2; + output list outEqn; + end appendLists; - function elementVars - input list ld; - output list vars; - end elementVars; + function functionInfo + input SimCode.Function fn; + output builtin.SourceInfo info; + end functionInfo; + + function countDynamicExternalFunctions + input list inFncLst; + output Integer outDynLoadFuncs; + end countDynamicExternalFunctions; + + function eqInfo + input SimCode.SimEqSystem eq; + output builtin.SourceInfo info; + end eqInfo; + + function dimsToAllIndexes + input DAE.Dimensions inDims; + output list> outIndexes; + end dimsToAllIndexes; + + function sortEqSystems + input list eqs; + output list outEqs; + end sortEqSystems; + + function getEnumerationTypes + input SimCodeVar.SimVars inVars; + output list outVars; + end getEnumerationTypes; + + function getFMIModelStructure + input SimCode.SimCode simCode; + input list jacobianMatrixes; + output SimCode.FmiModelStructure outFmiModelStructure; + end getFMIModelStructure; + + function getStateSimVarIndexFromIndex + input list inStateVars; + input Integer inIndex; + output Integer outVariableIndex; + end getStateSimVarIndexFromIndex; + + function getVariableIndex + input SimCodeVar.SimVar inVar; + output Integer outVariableIndex; + end getVariableIndex; + + function getMaxSimEqSystemIndex + input SimCode.SimCode simCode; + output Integer idxOut; + end getMaxSimEqSystemIndex; + + function translateSparsePatterSimVarInts + input list>> sparsePattern; + input SimCode.SimCode simCode; + output list>> outSparsePattern; + end translateSparsePatterSimVarInts; + + function translateColorsSimVarInts + input list> inColors; + input SimCode.SimCode simCode; + output list> outColors; + end translateColorsSimVarInts; + + function getDaeEqsNotPartOfOdeSystem + input SimCode.SimCode iSimCode; + output list oEqs; + end getDaeEqsNotPartOfOdeSystem; + + function getVarIndexListByMapping + input HashTableCrIListArray.HashTable iVarToArrayIndexMapping; + input DAE.ComponentRef iVarName; + input String iIndexForUndefinedReferences; + output list oVarIndexList; + end getVarIndexListByMapping; + + function isVarIndexListConsecutive + input HashTableCrIListArray.HashTable iVarToArrayIndexMapping; + input DAE.ComponentRef iVarName; + output Boolean oIsConsecutive; + end isVarIndexListConsecutive; +end SimCodeUtil; + +package SimCodeFunctionUtil + function varName + input SimCodeVar.SimVar var; + output DAE.ComponentRef cr; + end varName; + + function isParallelFunctionContext + input SimCode.Context context; + output Boolean s; + end isParallelFunctionContext; + + function createDAEString + input String inString; + output DAE.Exp outExp; + end createDAEString; function crefSubIsScalar input DAE.ComponentRef cref; @@ -753,24 +852,6 @@ package SimCodeUtil output Boolean isScalar; end crefIsScalar; - function buildCrefExpFromAsub - input DAE.Exp cref; - input list subs; - output DAE.Exp cRefOut; - end buildCrefExpFromAsub; - - function incrementInt - input Integer inInt; - input Integer increment; - output Integer outInt; - end incrementInt; - - function decrementInt - input Integer inInt; - input Integer decrement; - output Integer outInt; - end decrementInt; - function isProtected input SimCodeVar.SimVar simVar; output Boolean isProtected; @@ -830,110 +911,33 @@ package SimCodeUtil output DAE.Exp outExp; end createAssertforSqrt; - function appendLists - input list inEqn1; - input list inEqn2; - output list outEqn; - end appendLists; - - function createDAEString - input String inString; - output DAE.Exp outExp; - end createDAEString; + function elementVars + input list ld; + output list vars; + end elementVars; function isBoxedFunction input SimCode.Function fn; output Boolean b; end isBoxedFunction; - function functionInfo - input SimCode.Function fn; - output builtin.SourceInfo info; - end functionInfo; - - function twodigit - input Integer i; - output String s; - end twodigit; - - function countDynamicExternalFunctions - input list inFncLst; - output Integer outDynLoadFuncs; - end countDynamicExternalFunctions; - - function eqInfo - input SimCode.SimEqSystem eq; - output builtin.SourceInfo info; - end eqInfo; - - function varName - input SimCodeVar.SimVar var; - output DAE.ComponentRef cr; - end varName; - - function dimsToAllIndexes - input DAE.Dimensions inDims; - output list> outIndexes; - end dimsToAllIndexes; - - function sortEqSystems - input list eqs; - output list outEqs; - end sortEqSystems; - - function isParallelFunctionContext - input SimCode.Context context; - output Boolean s; - end isParallelFunctionContext; - - function getEnumerationTypes - input SimCodeVar.SimVars inVars; - output list outVars; - end getEnumerationTypes; - - function getFMIModelStructure - input SimCode.SimCode simCode; - input list jacobianMatrixes; - output SimCode.FmiModelStructure outFmiModelStructure; - end getFMIModelStructure; - - function getStateSimVarIndexFromIndex - input list inStateVars; - input Integer inIndex; - output Integer outVariableIndex; - end getStateSimVarIndexFromIndex; - - function getVariableIndex - input SimCodeVar.SimVar inVar; - output Integer outVariableIndex; - end getVariableIndex; - - function getMaxSimEqSystemIndex - input SimCode.SimCode simCode; - output Integer idxOut; - end getMaxSimEqSystemIndex; - - function translateSparsePatterSimVarInts - input list>> sparsePattern; - input SimCode.SimCode simCode; - output list>> outSparsePattern; - end translateSparsePatterSimVarInts; - - function translateColorsSimVarInts - input list> inColors; - input SimCode.SimCode simCode; - output list> outColors; - end translateColorsSimVarInts; + function incrementInt + input Integer inInt; + input Integer increment; + output Integer outInt; + end incrementInt; - function generateSubPalceholders - input DAE.ComponentRef cr; - output String outdef; - end generateSubPalceholders; + function decrementInt + input Integer inInt; + input Integer decrement; + output Integer outInt; + end decrementInt; - function getDaeEqsNotPartOfOdeSystem - input SimCode.SimCode iSimCode; - output list oEqs; - end getDaeEqsNotPartOfOdeSystem; + function buildCrefExpFromAsub + input DAE.Exp cref; + input list subs; + output DAE.Exp cRefOut; + end buildCrefExpFromAsub; function codegenResetTryThrowIndex end codegenResetTryThrowIndex; @@ -949,20 +953,17 @@ package SimCodeUtil output Integer i; end codegenPeekTryThrowIndex; - function getVarIndexListByMapping - input HashTableCrIListArray.HashTable iVarToArrayIndexMapping; - input DAE.ComponentRef iVarName; - input String iIndexForUndefinedReferences; - output list oVarIndexList; - end getVarIndexListByMapping; + function twodigit + input Integer i; + output String s; + end twodigit; - function isVarIndexListConsecutive - input HashTableCrIListArray.HashTable iVarToArrayIndexMapping; - input DAE.ComponentRef iVarName; - output Boolean oIsConsecutive; - end isVarIndexListConsecutive; -end SimCodeUtil; + function generateSubPalceholders + input DAE.ComponentRef cr; + output String outdef; + end generateSubPalceholders; +end SimCodeFunctionUtil; package BackendDAE @@ -3126,167 +3127,6 @@ package ValuesUtil end valueExp; end ValuesUtil; -package BackendQSS - uniontype QSSinfo "- equation indices in static blocks and DEVS structure" - record QSSINFO - list> stateVarIndex; - list stateVars; - list discreteAlgVars; - list algVars; - BackendDAE.EqSystems eqs; - list zcs; - Integer zc_offset; - end QSSINFO; - end QSSinfo; - - function getStateIndexList - input QSSinfo qssInfo; - output list> refs; - end getStateIndexList; - - function getStates - input QSSinfo qssInfo; - output list refs; - end getStates; - - function getDisc - input QSSinfo qssInfo; - output list refs; - end getDisc; - function replaceVars - input DAE.Exp exp; - input list states; - input list disc; - input list algs; - output DAE.Exp expout; - end replaceVars; - - function replaceCref - input DAE.ComponentRef cr; - input list states; - input list disc; - input list algs; - output String out; - end replaceCref; - - function getAlgs - input QSSinfo qssInfo; - output list refs; - end getAlgs; - - function negate - input DAE.Exp exp; - output DAE.Exp exp_out; - end negate; - - function getEqs - input QSSinfo qssInfo; - output BackendDAE.EquationArray eqs; - end getEqs; - - function generateHandler - input BackendDAE.EquationArray eqs; - input list handlers; - input list states; - input list disc; - input list algs; - input DAE.Exp condition; - input Boolean v; - input list zc_exps; - input Integer offset; - output String out; - end generateHandler; - - - function getRHSVars - input list beqs; - input list vars; - input list> simJac; - input list states; - input list disc; - input list algs; - output list out; - end getRHSVars; - - function getDiscRHSVars - input list beqs; - input list vars; - input list> simJac; - input list states; - input list disc; - input list algs; - output list out; - end getDiscRHSVars; - - - function generateDInit - input list disc; - //input list sample; - input SimCodeVar.SimVars vars; - input Integer acc; - input Integer total; - input Integer nWhenClause; - output String out; - end generateDInit; - - function generateExtraParams - input SimCode.SimEqSystem eq; - input SimCodeVar.SimVars vars; - output String s; - end generateExtraParams; - - function generateInitialParamEquations - input SimCode.SimEqSystem eq; - output String t; - end generateInitialParamEquations; - - function replaceVarsInputs - input DAE.Exp exp; - input list inp; - output DAE.Exp exp_out; - end replaceVarsInputs; - - function simpleWhens - input list i; - output list o; - end simpleWhens; - - function sampleWhens - input list i; - output list o; - end sampleWhens; - - function getZCOffset - input QSSinfo qssInfo; - output Integer o; - end getZCOffset; - - function getZCExps - input QSSinfo qssInfo; - output list exps; - end getZCExps; - -end BackendQSS; - -package BackendVariable - function varCref - input BackendDAE.Var inVar; - output DAE.ComponentRef outComponentRef; - end varCref; - - function isStateVar - input BackendDAE.Var inVar; - output Boolean outBoolean; - end isStateVar; - - function varIndex - input BackendDAE.Var inVar; - output Integer outInteger; - end varIndex; - - -end BackendVariable; - package DAEDump function ppStmtStr @@ -3349,268 +3189,6 @@ package Types end isArrayWithUnknownDimension; end Types; -package FMI - uniontype Info - record INFO - String fmiVersion; - Integer fmiType; - String fmiModelName; - String fmiModelIdentifier; - String fmiGuid; - String fmiDescription; - String fmiGenerationTool; - String fmiGenerationDateAndTime; - String fmiVariableNamingConvention; - list fmiNumberOfContinuousStates; - list fmiNumberOfEventIndicators; - end INFO; - end Info; - - uniontype TypeDefinitions - record ENUMERATIONTYPE - String name; - String description; - String quantity; - Integer min; - Integer max; - list items; - end ENUMERATIONTYPE; - end TypeDefinitions; - - uniontype EnumerationItem - record ENUMERATIONITEM - String name; - String description; - end ENUMERATIONITEM; - end EnumerationItem; - - uniontype ExperimentAnnotation - record EXPERIMENTANNOTATION - Real fmiExperimentStartTime; - Real fmiExperimentStopTime; - Real fmiExperimentTolerance; - end EXPERIMENTANNOTATION; - end ExperimentAnnotation; - - uniontype ModelVariables - record REALVARIABLE - Integer instance; - String name; - String description; - String baseType; - String variability; - String causality; - Boolean hasStartValue; - Real startValue; - Boolean isFixed; - Real valueReference; - Integer x1Placement; - Integer x2Placement; - Integer y1Placement; - Integer y2Placement; - end REALVARIABLE; - - record INTEGERVARIABLE - Integer instance; - String name; - String description; - String baseType; - String variability; - String causality; - Boolean hasStartValue; - Integer startValue; - Boolean isFixed; - Real valueReference; - Integer x1Placement; - Integer x2Placement; - Integer y1Placement; - Integer y2Placement; - end INTEGERVARIABLE; - - record BOOLEANVARIABLE - Integer instance; - String name; - String description; - String baseType; - String variability; - String causality; - Boolean hasStartValue; - Boolean startValue; - Boolean isFixed; - Real valueReference; - Integer x1Placement; - Integer x2Placement; - Integer y1Placement; - Integer y2Placement; - end BOOLEANVARIABLE; - - record STRINGVARIABLE - Integer instance; - String name; - String description; - String baseType; - String variability; - String causality; - Boolean hasStartValue; - String startValue; - Boolean isFixed; - Real valueReference; - Integer x1Placement; - Integer x2Placement; - Integer y1Placement; - Integer y2Placement; - end STRINGVARIABLE; - - record ENUMERATIONVARIABLE - Integer instance; - String name; - String description; - String baseType; - String variability; - String causality; - Boolean hasStartValue; - Integer startValue; - Boolean isFixed; - Real valueReference; - Integer x1Placement; - Integer x2Placement; - Integer y1Placement; - Integer y2Placement; - end ENUMERATIONVARIABLE; - end ModelVariables; - - uniontype FmiImport - record FMIIMPORT - String platform; - String fmuFileName; - String fmuWorkingDirectory; - Integer fmiLogLevel; - Boolean fmiDebugOutput; - Option fmiContext; - Option fmiInstance; - Info fmiInfo; - list fmiTypeDefinitionsList; - ExperimentAnnotation fmiExperimentAnnotation; - Option fmiModelVariablesInstance; - list fmiModelVariablesList; - Boolean generateInputConnectors; - Boolean generateOutputConnectors; - end FMIIMPORT; - end FmiImport; - - function getFMIType - input Info inFMIInfo; - output String fmiType; - end getFMIType; - - function isFMIVersion20 "Checks if the FMI version is 2.0." - input String inFMUVersion; - 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 inTypeDefinitionsList; - input String inBaseType; - output String outEnumerationType; - end getEnumerationTypeFromTypes; -end FMI; - -package HpcOmSimCodeMain - function getSimCodeEqByIndex - input list iEqs; - input Integer iIdx; - output SimCode.SimEqSystem oEq; - end getSimCodeEqByIndex; -end HpcOmSimCodeMain; - -package HpcOmSimCode - uniontype HpcOmData - record HPCOMDATA - Option> schedules; - Option hpcOmMemory; - end HPCOMDATA; - end HpcOmData; - - uniontype CommunicationInfo //stores more detailed information about a communication (edge) - record COMMUNICATION_INFO - list floatVars; //the float, int and boolean variables that have to be transfered - list intVars; - list boolVars; - end COMMUNICATION_INFO; - end CommunicationInfo; - - uniontype Task - record CALCTASK //Task which calculates something - Integer weighting; - Integer index; - Real calcTime; - Real timeFinished; - Integer threadIdx; - list eqIdc; - end CALCTASK; - record CALCTASK_LEVEL - list eqIdc; - list nodeIdc; - Option threadIdx; - end CALCTASK_LEVEL; - record DEPTASK - Task sourceTask; - Task targetTask; - Boolean outgoing; //true if the dependency is leading to the task of another thread - Integer id; - CommunicationInfo communicationInfo; - end DEPTASK; - end Task; - - uniontype TaskList - record PARALLELTASKLIST - list tasks; - end PARALLELTASKLIST; - record SERIALTASKLIST - list tasks; - end SERIALTASKLIST; - end TaskList; - - uniontype Schedule - record LEVELSCHEDULE - list tasksOfLevels; - Boolean useFixedAssignments; - end LEVELSCHEDULE; - record THREADSCHEDULE - array> threadTasks; - list outgoingDepTasks; - end THREADSCHEDULE; - record TASKDEPSCHEDULE - list>> tasks; - end TASKDEPSCHEDULE; - record EMPTYSCHEDULE - TaskList tasks; - end EMPTYSCHEDULE; - end Schedule; - - uniontype MemoryMap - record MEMORYMAP_ARRAY - Integer floatArraySize; - Integer intArraySize; - Integer boolArraySize; - end MEMORYMAP_ARRAY; - end MemoryMap; -end HpcOmSimCode; - -package HpcOmScheduler - function convertFixedLevelScheduleToTaskLists - input HpcOmSimCode.Schedule iOdeSchedule; - input HpcOmSimCode.Schedule iDaeSchedule; - input Integer iNumOfThreads; - output array>,list>>> oThreadLevelTasks; - end convertFixedLevelScheduleToTaskLists; -end HpcOmScheduler; - package HashTableCrIListArray type Key = DAE.ComponentRef; type Value = tuple, array>; diff --git a/Compiler/Util/Error.mo b/Compiler/Util/Error.mo index cb4f3335b52..a564bd0c46e 100644 --- a/Compiler/Util/Error.mo +++ b/Compiler/Util/Error.mo @@ -688,6 +688,8 @@ public constant Message EXT_LIBRARY_NOT_FOUND = MESSAGE(282, TRANSLATION(), WARN Util.gettext("Could not find library %s in either of:%s")); public constant Message EXT_LIBRARY_NOT_FOUND_DESPITE_COMPILATION_SUCCESS = MESSAGE(258, TRANSLATION(), WARNING(), Util.gettext("Could not find library %s despite compilation command %s in directory %s returning success.")); +public constant Message GENERATE_SEPARATE_CODE_DEPENDENCIES_FAILED_UNKNOWN_PACKAGE = MESSAGE(283, SCRIPTING(), ERROR(), + Util.gettext("Failed to get dependencies for package %s. %s contains an import to non-existing package %s.")); public constant Message UNBOUND_PARAMETER_WITH_START_VALUE_WARNING = MESSAGE(499, TRANSLATION(), WARNING(), Util.gettext("Parameter %s has no value, and is fixed during initialization (fixed=true), using available start value (start=%s) as default value.")); diff --git a/Compiler/Util/HashTable6.mo b/Compiler/Util/HashTable6.mo index 104a367ba5b..51de3bff021 100644 --- a/Compiler/Util/HashTable6.mo +++ b/Compiler/Util/HashTable6.mo @@ -45,7 +45,6 @@ public import BaseHashTable; public import DAE; protected import ComponentReference; protected import ExpressionDump; -protected import System; protected import Util; public type Key = tuple; diff --git a/Compiler/Util/HashTableCrToCrEqLst.mo b/Compiler/Util/HashTableCrToCrEqLst.mo index 9b9f6c6bfb3..665636f5c27 100644 --- a/Compiler/Util/HashTableCrToCrEqLst.mo +++ b/Compiler/Util/HashTableCrToCrEqLst.mo @@ -44,7 +44,6 @@ keyEqual - A comparison function between two keys, returns true if equal. public import BaseHashTable; public import DAE; public import BackendDAE; -public import System; protected import ComponentReference; protected import BackendDump; protected import List; @@ -122,1119 +121,3 @@ end printTupleComponentRefEqStr; annotation(__OpenModelica_Interface="backend"); end HashTableCrToCrEqLst; -/* - * This file is part of OpenModelica. - * - * Copyright (c) 1998-2014, Open Source Modelica Consortium (OSMC), - * c/o Linköpings universitet, Department of Computer and Information Science, - * SE-58183 Linköping, Sweden. - * - * All rights reserved. - * - * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF GPL VERSION 3 LICENSE OR - * THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.2. - * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES - * RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GPL VERSION 3, - * ACCORDING TO RECIPIENTS CHOICE. - * - * The OpenModelica software and the Open Source Modelica - * Consortium (OSMC) Public License (OSMC-PL) are obtained - * from OSMC, either from the above address, - * from the URLs: http://www.ida.liu.se/projects/OpenModelica or - * http://www.openmodelica.org, and in the OpenModelica distribution. - * GNU version 3 is obtained from: http://www.gnu.org/copyleft/gpl.html. - * - * This program is distributed WITHOUT ANY WARRANTY; without - * even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH - * IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL. - * - * See the full OSMC Public License conditions for more details. - * - */ - -encapsulated package HashTableCrToCrEqLst - -/* Below is the instance specific code. For each hashtable the user must define: - -Key - The key used to uniquely define elements in a hashtable -Value - The data to associate with each key -hashFunc - A function that maps a key to a positive integer. -keyEqual - A comparison function between two keys, returns true if equal. -*/ - -/* HashTable instance specific code */ - -public import BaseHashTable; -public import DAE; -public import BackendDAE; -public import System; -protected import ComponentReference; -protected import BackendDump; -protected import List; - -public type Key = DAE.ComponentRef; -public type Value = list>; - -public type HashTableCrefFunctionsType = tuple; -public type HashTable = tuple< - array>>, - tuple>>>, - Integer, - Integer, - HashTableCrefFunctionsType ->; - -partial function FuncHashCref - input Key cr; - input Integer mod; - output Integer res; -end FuncHashCref; - -partial function FuncCrefEqual - input Key cr1; - input Key cr2; - output Boolean res; -end FuncCrefEqual; - -partial function FuncCrefStr - input Key cr; - output String res; -end FuncCrefStr; - -partial function FuncExpStr - input Value exp; - output String res; -end FuncExpStr; - -public function emptyHashTable -" - Returns an empty HashTable. - Using the default bucketsize.. -" - output HashTable hashTable; -algorithm - hashTable := emptyHashTableSized(BaseHashTable.defaultBucketSize); -end emptyHashTable; - -public function emptyHashTableSized -"Returns an empty HashTable. - Using the bucketsize size." - input Integer size; - output HashTable hashTable; -algorithm - hashTable := BaseHashTable.emptyHashTableWork(size,(ComponentReference.hashComponentRefMod,ComponentReference.crefEqual,ComponentReference.printComponentRefStr,printTupleComponentRefEqListStr)); -end emptyHashTableSized; - -public function printTupleComponentRefEqListStr - input list> cr_eq_lst; - output String res; -algorithm - res := stringDelimitList(List.map(cr_eq_lst, printTupleComponentRefEqStr), ","); -end printTupleComponentRefEqListStr; - -public function printTupleComponentRefEqStr - input tuple cr_eq; - output String res; -protected - DAE.ComponentRef cr; - BackendDAE.Equation eq; -algorithm - (cr, eq) := cr_eq; - res := "{" + ComponentReference.printComponentRefStr(cr) + "," + BackendDump.equationString(eq) + "}"; -end printTupleComponentRefEqStr; - -annotation(__OpenModelica_Interface="backend"); -end HashTableCrToCrEqLst; -/* - * This file is part of OpenModelica. - * - * Copyright (c) 1998-2014, Open Source Modelica Consortium (OSMC), - * c/o Linköpings universitet, Department of Computer and Information Science, - * SE-58183 Linköping, Sweden. - * - * All rights reserved. - * - * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF GPL VERSION 3 LICENSE OR - * THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.2. - * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES - * RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GPL VERSION 3, - * ACCORDING TO RECIPIENTS CHOICE. - * - * The OpenModelica software and the Open Source Modelica - * Consortium (OSMC) Public License (OSMC-PL) are obtained - * from OSMC, either from the above address, - * from the URLs: http://www.ida.liu.se/projects/OpenModelica or - * http://www.openmodelica.org, and in the OpenModelica distribution. - * GNU version 3 is obtained from: http://www.gnu.org/copyleft/gpl.html. - * - * This program is distributed WITHOUT ANY WARRANTY; without - * even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH - * IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL. - * - * See the full OSMC Public License conditions for more details. - * - */ - -encapsulated package HashTableCrToCrEqLst - -/* Below is the instance specific code. For each hashtable the user must define: - -Key - The key used to uniquely define elements in a hashtable -Value - The data to associate with each key -hashFunc - A function that maps a key to a positive integer. -keyEqual - A comparison function between two keys, returns true if equal. -*/ - -/* HashTable instance specific code */ - -public import BaseHashTable; -public import DAE; -public import BackendDAE; -public import System; -protected import ComponentReference; -protected import BackendDump; -protected import List; - -public type Key = DAE.ComponentRef; -public type Value = list>; - -public type HashTableCrefFunctionsType = tuple; -public type HashTable = tuple< - array>>, - tuple>>>, - Integer, - Integer, - HashTableCrefFunctionsType ->; - -partial function FuncHashCref - input Key cr; - input Integer mod; - output Integer res; -end FuncHashCref; - -partial function FuncCrefEqual - input Key cr1; - input Key cr2; - output Boolean res; -end FuncCrefEqual; - -partial function FuncCrefStr - input Key cr; - output String res; -end FuncCrefStr; - -partial function FuncExpStr - input Value exp; - output String res; -end FuncExpStr; - -public function emptyHashTable -" - Returns an empty HashTable. - Using the default bucketsize.. -" - output HashTable hashTable; -algorithm - hashTable := emptyHashTableSized(BaseHashTable.defaultBucketSize); -end emptyHashTable; - -public function emptyHashTableSized -"Returns an empty HashTable. - Using the bucketsize size." - input Integer size; - output HashTable hashTable; -algorithm - hashTable := BaseHashTable.emptyHashTableWork(size,(ComponentReference.hashComponentRefMod,ComponentReference.crefEqual,ComponentReference.printComponentRefStr,printTupleComponentRefEqListStr)); -end emptyHashTableSized; - -public function printTupleComponentRefEqListStr - input list> cr_eq_lst; - output String res; -algorithm - res := stringDelimitList(List.map(cr_eq_lst, printTupleComponentRefEqStr), ","); -end printTupleComponentRefEqListStr; - -public function printTupleComponentRefEqStr - input tuple cr_eq; - output String res; -protected - DAE.ComponentRef cr; - BackendDAE.Equation eq; -algorithm - (cr, eq) := cr_eq; - res := "{" + ComponentReference.printComponentRefStr(cr) + "," + BackendDump.equationString(eq) + "}"; -end printTupleComponentRefEqStr; - -annotation(__OpenModelica_Interface="backend"); -end HashTableCrToCrEqLst; -/* - * This file is part of OpenModelica. - * - * Copyright (c) 1998-2014, Open Source Modelica Consortium (OSMC), - * c/o Linköpings universitet, Department of Computer and Information Science, - * SE-58183 Linköping, Sweden. - * - * All rights reserved. - * - * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF GPL VERSION 3 LICENSE OR - * THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.2. - * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES - * RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GPL VERSION 3, - * ACCORDING TO RECIPIENTS CHOICE. - * - * The OpenModelica software and the Open Source Modelica - * Consortium (OSMC) Public License (OSMC-PL) are obtained - * from OSMC, either from the above address, - * from the URLs: http://www.ida.liu.se/projects/OpenModelica or - * http://www.openmodelica.org, and in the OpenModelica distribution. - * GNU version 3 is obtained from: http://www.gnu.org/copyleft/gpl.html. - * - * This program is distributed WITHOUT ANY WARRANTY; without - * even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH - * IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL. - * - * See the full OSMC Public License conditions for more details. - * - */ - -encapsulated package HashTableCrToCrEqLst - -/* Below is the instance specific code. For each hashtable the user must define: - -Key - The key used to uniquely define elements in a hashtable -Value - The data to associate with each key -hashFunc - A function that maps a key to a positive integer. -keyEqual - A comparison function between two keys, returns true if equal. -*/ - -/* HashTable instance specific code */ - -public import BaseHashTable; -public import DAE; -public import BackendDAE; -public import System; -protected import ComponentReference; -protected import BackendDump; -protected import List; - -public type Key = DAE.ComponentRef; -public type Value = list>; - -public type HashTableCrefFunctionsType = tuple; -public type HashTable = tuple< - array>>, - tuple>>>, - Integer, - Integer, - HashTableCrefFunctionsType ->; - -partial function FuncHashCref - input Key cr; - input Integer mod; - output Integer res; -end FuncHashCref; - -partial function FuncCrefEqual - input Key cr1; - input Key cr2; - output Boolean res; -end FuncCrefEqual; - -partial function FuncCrefStr - input Key cr; - output String res; -end FuncCrefStr; - -partial function FuncExpStr - input Value exp; - output String res; -end FuncExpStr; - -public function emptyHashTable -" - Returns an empty HashTable. - Using the default bucketsize.. -" - output HashTable hashTable; -algorithm - hashTable := emptyHashTableSized(BaseHashTable.defaultBucketSize); -end emptyHashTable; - -public function emptyHashTableSized -"Returns an empty HashTable. - Using the bucketsize size." - input Integer size; - output HashTable hashTable; -algorithm - hashTable := BaseHashTable.emptyHashTableWork(size,(ComponentReference.hashComponentRefMod,ComponentReference.crefEqual,ComponentReference.printComponentRefStr,printTupleComponentRefEqListStr)); -end emptyHashTableSized; - -public function printTupleComponentRefEqListStr - input list> cr_eq_lst; - output String res; -algorithm - res := stringDelimitList(List.map(cr_eq_lst, printTupleComponentRefEqStr), ","); -end printTupleComponentRefEqListStr; - -public function printTupleComponentRefEqStr - input tuple cr_eq; - output String res; -protected - DAE.ComponentRef cr; - BackendDAE.Equation eq; -algorithm - (cr, eq) := cr_eq; - res := "{" + ComponentReference.printComponentRefStr(cr) + "," + BackendDump.equationString(eq) + "}"; -end printTupleComponentRefEqStr; - -annotation(__OpenModelica_Interface="backend"); -end HashTableCrToCrEqLst; -/* - * This file is part of OpenModelica. - * - * Copyright (c) 1998-2014, Open Source Modelica Consortium (OSMC), - * c/o Linköpings universitet, Department of Computer and Information Science, - * SE-58183 Linköping, Sweden. - * - * All rights reserved. - * - * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF GPL VERSION 3 LICENSE OR - * THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.2. - * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES - * RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GPL VERSION 3, - * ACCORDING TO RECIPIENTS CHOICE. - * - * The OpenModelica software and the Open Source Modelica - * Consortium (OSMC) Public License (OSMC-PL) are obtained - * from OSMC, either from the above address, - * from the URLs: http://www.ida.liu.se/projects/OpenModelica or - * http://www.openmodelica.org, and in the OpenModelica distribution. - * GNU version 3 is obtained from: http://www.gnu.org/copyleft/gpl.html. - * - * This program is distributed WITHOUT ANY WARRANTY; without - * even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH - * IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL. - * - * See the full OSMC Public License conditions for more details. - * - */ - -encapsulated package HashTableCrToCrEqLst - -/* Below is the instance specific code. For each hashtable the user must define: - -Key - The key used to uniquely define elements in a hashtable -Value - The data to associate with each key -hashFunc - A function that maps a key to a positive integer. -keyEqual - A comparison function between two keys, returns true if equal. -*/ - -/* HashTable instance specific code */ - -public import BaseHashTable; -public import DAE; -public import BackendDAE; -public import System; -protected import ComponentReference; -protected import BackendDump; -protected import List; - -public type Key = DAE.ComponentRef; -public type Value = list>; - -public type HashTableCrefFunctionsType = tuple; -public type HashTable = tuple< - array>>, - tuple>>>, - Integer, - Integer, - HashTableCrefFunctionsType ->; - -partial function FuncHashCref - input Key cr; - input Integer mod; - output Integer res; -end FuncHashCref; - -partial function FuncCrefEqual - input Key cr1; - input Key cr2; - output Boolean res; -end FuncCrefEqual; - -partial function FuncCrefStr - input Key cr; - output String res; -end FuncCrefStr; - -partial function FuncExpStr - input Value exp; - output String res; -end FuncExpStr; - -public function emptyHashTable -" - Returns an empty HashTable. - Using the default bucketsize.. -" - output HashTable hashTable; -algorithm - hashTable := emptyHashTableSized(BaseHashTable.defaultBucketSize); -end emptyHashTable; - -public function emptyHashTableSized -"Returns an empty HashTable. - Using the bucketsize size." - input Integer size; - output HashTable hashTable; -algorithm - hashTable := BaseHashTable.emptyHashTableWork(size,(ComponentReference.hashComponentRefMod,ComponentReference.crefEqual,ComponentReference.printComponentRefStr,printTupleComponentRefEqListStr)); -end emptyHashTableSized; - -public function printTupleComponentRefEqListStr - input list> cr_eq_lst; - output String res; -algorithm - res := stringDelimitList(List.map(cr_eq_lst, printTupleComponentRefEqStr), ","); -end printTupleComponentRefEqListStr; - -public function printTupleComponentRefEqStr - input tuple cr_eq; - output String res; -protected - DAE.ComponentRef cr; - BackendDAE.Equation eq; -algorithm - (cr, eq) := cr_eq; - res := "{" + ComponentReference.printComponentRefStr(cr) + "," + BackendDump.equationString(eq) + "}"; -end printTupleComponentRefEqStr; - -annotation(__OpenModelica_Interface="backend"); -end HashTableCrToCrEqLst; -/* - * This file is part of OpenModelica. - * - * Copyright (c) 1998-2014, Open Source Modelica Consortium (OSMC), - * c/o Linköpings universitet, Department of Computer and Information Science, - * SE-58183 Linköping, Sweden. - * - * All rights reserved. - * - * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF GPL VERSION 3 LICENSE OR - * THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.2. - * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES - * RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GPL VERSION 3, - * ACCORDING TO RECIPIENTS CHOICE. - * - * The OpenModelica software and the Open Source Modelica - * Consortium (OSMC) Public License (OSMC-PL) are obtained - * from OSMC, either from the above address, - * from the URLs: http://www.ida.liu.se/projects/OpenModelica or - * http://www.openmodelica.org, and in the OpenModelica distribution. - * GNU version 3 is obtained from: http://www.gnu.org/copyleft/gpl.html. - * - * This program is distributed WITHOUT ANY WARRANTY; without - * even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH - * IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL. - * - * See the full OSMC Public License conditions for more details. - * - */ - -encapsulated package HashTableCrToCrEqLst - -/* Below is the instance specific code. For each hashtable the user must define: - -Key - The key used to uniquely define elements in a hashtable -Value - The data to associate with each key -hashFunc - A function that maps a key to a positive integer. -keyEqual - A comparison function between two keys, returns true if equal. -*/ - -/* HashTable instance specific code */ - -public import BaseHashTable; -public import DAE; -public import BackendDAE; -public import System; -protected import ComponentReference; -protected import BackendDump; -protected import List; - -public type Key = DAE.ComponentRef; -public type Value = list>; - -public type HashTableCrefFunctionsType = tuple; -public type HashTable = tuple< - array>>, - tuple>>>, - Integer, - Integer, - HashTableCrefFunctionsType ->; - -partial function FuncHashCref - input Key cr; - input Integer mod; - output Integer res; -end FuncHashCref; - -partial function FuncCrefEqual - input Key cr1; - input Key cr2; - output Boolean res; -end FuncCrefEqual; - -partial function FuncCrefStr - input Key cr; - output String res; -end FuncCrefStr; - -partial function FuncExpStr - input Value exp; - output String res; -end FuncExpStr; - -public function emptyHashTable -" - Returns an empty HashTable. - Using the default bucketsize.. -" - output HashTable hashTable; -algorithm - hashTable := emptyHashTableSized(BaseHashTable.defaultBucketSize); -end emptyHashTable; - -public function emptyHashTableSized -"Returns an empty HashTable. - Using the bucketsize size." - input Integer size; - output HashTable hashTable; -algorithm - hashTable := BaseHashTable.emptyHashTableWork(size,(ComponentReference.hashComponentRefMod,ComponentReference.crefEqual,ComponentReference.printComponentRefStr,printTupleComponentRefEqListStr)); -end emptyHashTableSized; - -public function printTupleComponentRefEqListStr - input list> cr_eq_lst; - output String res; -algorithm - res := stringDelimitList(List.map(cr_eq_lst, printTupleComponentRefEqStr), ","); -end printTupleComponentRefEqListStr; - -public function printTupleComponentRefEqStr - input tuple cr_eq; - output String res; -protected - DAE.ComponentRef cr; - BackendDAE.Equation eq; -algorithm - (cr, eq) := cr_eq; - res := "{" + ComponentReference.printComponentRefStr(cr) + "," + BackendDump.equationString(eq) + "}"; -end printTupleComponentRefEqStr; - -annotation(__OpenModelica_Interface="backend"); -end HashTableCrToCrEqLst; -/* - * This file is part of OpenModelica. - * - * Copyright (c) 1998-2014, Open Source Modelica Consortium (OSMC), - * c/o Linköpings universitet, Department of Computer and Information Science, - * SE-58183 Linköping, Sweden. - * - * All rights reserved. - * - * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF GPL VERSION 3 LICENSE OR - * THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.2. - * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES - * RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GPL VERSION 3, - * ACCORDING TO RECIPIENTS CHOICE. - * - * The OpenModelica software and the Open Source Modelica - * Consortium (OSMC) Public License (OSMC-PL) are obtained - * from OSMC, either from the above address, - * from the URLs: http://www.ida.liu.se/projects/OpenModelica or - * http://www.openmodelica.org, and in the OpenModelica distribution. - * GNU version 3 is obtained from: http://www.gnu.org/copyleft/gpl.html. - * - * This program is distributed WITHOUT ANY WARRANTY; without - * even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH - * IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL. - * - * See the full OSMC Public License conditions for more details. - * - */ - -encapsulated package HashTableCrToCrEqLst - -/* Below is the instance specific code. For each hashtable the user must define: - -Key - The key used to uniquely define elements in a hashtable -Value - The data to associate with each key -hashFunc - A function that maps a key to a positive integer. -keyEqual - A comparison function between two keys, returns true if equal. -*/ - -/* HashTable instance specific code */ - -public import BaseHashTable; -public import DAE; -public import BackendDAE; -public import System; -protected import ComponentReference; -protected import BackendDump; -protected import List; - -public type Key = DAE.ComponentRef; -public type Value = list>; - -public type HashTableCrefFunctionsType = tuple; -public type HashTable = tuple< - array>>, - tuple>>>, - Integer, - Integer, - HashTableCrefFunctionsType ->; - -partial function FuncHashCref - input Key cr; - input Integer mod; - output Integer res; -end FuncHashCref; - -partial function FuncCrefEqual - input Key cr1; - input Key cr2; - output Boolean res; -end FuncCrefEqual; - -partial function FuncCrefStr - input Key cr; - output String res; -end FuncCrefStr; - -partial function FuncExpStr - input Value exp; - output String res; -end FuncExpStr; - -public function emptyHashTable -" - Returns an empty HashTable. - Using the default bucketsize.. -" - output HashTable hashTable; -algorithm - hashTable := emptyHashTableSized(BaseHashTable.defaultBucketSize); -end emptyHashTable; - -public function emptyHashTableSized -"Returns an empty HashTable. - Using the bucketsize size." - input Integer size; - output HashTable hashTable; -algorithm - hashTable := BaseHashTable.emptyHashTableWork(size,(ComponentReference.hashComponentRefMod,ComponentReference.crefEqual,ComponentReference.printComponentRefStr,printTupleComponentRefEqListStr)); -end emptyHashTableSized; - -public function printTupleComponentRefEqListStr - input list> cr_eq_lst; - output String res; -algorithm - res := stringDelimitList(List.map(cr_eq_lst, printTupleComponentRefEqStr), ","); -end printTupleComponentRefEqListStr; - -public function printTupleComponentRefEqStr - input tuple cr_eq; - output String res; -protected - DAE.ComponentRef cr; - BackendDAE.Equation eq; -algorithm - (cr, eq) := cr_eq; - res := "{" + ComponentReference.printComponentRefStr(cr) + "," + BackendDump.equationString(eq) + "}"; -end printTupleComponentRefEqStr; - -annotation(__OpenModelica_Interface="backend"); -end HashTableCrToCrEqLst; -/* - * This file is part of OpenModelica. - * - * Copyright (c) 1998-2014, Open Source Modelica Consortium (OSMC), - * c/o Linköpings universitet, Department of Computer and Information Science, - * SE-58183 Linköping, Sweden. - * - * All rights reserved. - * - * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF GPL VERSION 3 LICENSE OR - * THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.2. - * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES - * RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GPL VERSION 3, - * ACCORDING TO RECIPIENTS CHOICE. - * - * The OpenModelica software and the Open Source Modelica - * Consortium (OSMC) Public License (OSMC-PL) are obtained - * from OSMC, either from the above address, - * from the URLs: http://www.ida.liu.se/projects/OpenModelica or - * http://www.openmodelica.org, and in the OpenModelica distribution. - * GNU version 3 is obtained from: http://www.gnu.org/copyleft/gpl.html. - * - * This program is distributed WITHOUT ANY WARRANTY; without - * even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH - * IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL. - * - * See the full OSMC Public License conditions for more details. - * - */ - -encapsulated package HashTableCrToCrEqLst - -/* Below is the instance specific code. For each hashtable the user must define: - -Key - The key used to uniquely define elements in a hashtable -Value - The data to associate with each key -hashFunc - A function that maps a key to a positive integer. -keyEqual - A comparison function between two keys, returns true if equal. -*/ - -/* HashTable instance specific code */ - -public import BaseHashTable; -public import DAE; -public import BackendDAE; -public import System; -protected import ComponentReference; -protected import BackendDump; -protected import List; - -public type Key = DAE.ComponentRef; -public type Value = list>; - -public type HashTableCrefFunctionsType = tuple; -public type HashTable = tuple< - array>>, - tuple>>>, - Integer, - Integer, - HashTableCrefFunctionsType ->; - -partial function FuncHashCref - input Key cr; - input Integer mod; - output Integer res; -end FuncHashCref; - -partial function FuncCrefEqual - input Key cr1; - input Key cr2; - output Boolean res; -end FuncCrefEqual; - -partial function FuncCrefStr - input Key cr; - output String res; -end FuncCrefStr; - -partial function FuncExpStr - input Value exp; - output String res; -end FuncExpStr; - -public function emptyHashTable -" - Returns an empty HashTable. - Using the default bucketsize.. -" - output HashTable hashTable; -algorithm - hashTable := emptyHashTableSized(BaseHashTable.defaultBucketSize); -end emptyHashTable; - -public function emptyHashTableSized -"Returns an empty HashTable. - Using the bucketsize size." - input Integer size; - output HashTable hashTable; -algorithm - hashTable := BaseHashTable.emptyHashTableWork(size,(ComponentReference.hashComponentRefMod,ComponentReference.crefEqual,ComponentReference.printComponentRefStr,printTupleComponentRefEqListStr)); -end emptyHashTableSized; - -public function printTupleComponentRefEqListStr - input list> cr_eq_lst; - output String res; -algorithm - res := stringDelimitList(List.map(cr_eq_lst, printTupleComponentRefEqStr), ","); -end printTupleComponentRefEqListStr; - -public function printTupleComponentRefEqStr - input tuple cr_eq; - output String res; -protected - DAE.ComponentRef cr; - BackendDAE.Equation eq; -algorithm - (cr, eq) := cr_eq; - res := "{" + ComponentReference.printComponentRefStr(cr) + "," + BackendDump.equationString(eq) + "}"; -end printTupleComponentRefEqStr; - -annotation(__OpenModelica_Interface="backend"); -end HashTableCrToCrEqLst; -/* - * This file is part of OpenModelica. - * - * Copyright (c) 1998-2014, Open Source Modelica Consortium (OSMC), - * c/o Linköpings universitet, Department of Computer and Information Science, - * SE-58183 Linköping, Sweden. - * - * All rights reserved. - * - * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF GPL VERSION 3 LICENSE OR - * THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.2. - * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES - * RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GPL VERSION 3, - * ACCORDING TO RECIPIENTS CHOICE. - * - * The OpenModelica software and the Open Source Modelica - * Consortium (OSMC) Public License (OSMC-PL) are obtained - * from OSMC, either from the above address, - * from the URLs: http://www.ida.liu.se/projects/OpenModelica or - * http://www.openmodelica.org, and in the OpenModelica distribution. - * GNU version 3 is obtained from: http://www.gnu.org/copyleft/gpl.html. - * - * This program is distributed WITHOUT ANY WARRANTY; without - * even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH - * IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL. - * - * See the full OSMC Public License conditions for more details. - * - */ - -encapsulated package HashTableCrToCrEqLst - -/* Below is the instance specific code. For each hashtable the user must define: - -Key - The key used to uniquely define elements in a hashtable -Value - The data to associate with each key -hashFunc - A function that maps a key to a positive integer. -keyEqual - A comparison function between two keys, returns true if equal. -*/ - -/* HashTable instance specific code */ - -public import BaseHashTable; -public import DAE; -public import BackendDAE; -public import System; -protected import ComponentReference; -protected import BackendDump; -protected import List; - -public type Key = DAE.ComponentRef; -public type Value = list>; - -public type HashTableCrefFunctionsType = tuple; -public type HashTable = tuple< - array>>, - tuple>>>, - Integer, - Integer, - HashTableCrefFunctionsType ->; - -partial function FuncHashCref - input Key cr; - input Integer mod; - output Integer res; -end FuncHashCref; - -partial function FuncCrefEqual - input Key cr1; - input Key cr2; - output Boolean res; -end FuncCrefEqual; - -partial function FuncCrefStr - input Key cr; - output String res; -end FuncCrefStr; - -partial function FuncExpStr - input Value exp; - output String res; -end FuncExpStr; - -public function emptyHashTable -" - Returns an empty HashTable. - Using the default bucketsize.. -" - output HashTable hashTable; -algorithm - hashTable := emptyHashTableSized(BaseHashTable.defaultBucketSize); -end emptyHashTable; - -public function emptyHashTableSized -"Returns an empty HashTable. - Using the bucketsize size." - input Integer size; - output HashTable hashTable; -algorithm - hashTable := BaseHashTable.emptyHashTableWork(size,(ComponentReference.hashComponentRefMod,ComponentReference.crefEqual,ComponentReference.printComponentRefStr,printTupleComponentRefEqListStr)); -end emptyHashTableSized; - -public function printTupleComponentRefEqListStr - input list> cr_eq_lst; - output String res; -algorithm - res := stringDelimitList(List.map(cr_eq_lst, printTupleComponentRefEqStr), ","); -end printTupleComponentRefEqListStr; - -public function printTupleComponentRefEqStr - input tuple cr_eq; - output String res; -protected - DAE.ComponentRef cr; - BackendDAE.Equation eq; -algorithm - (cr, eq) := cr_eq; - res := "{" + ComponentReference.printComponentRefStr(cr) + "," + BackendDump.equationString(eq) + "}"; -end printTupleComponentRefEqStr; - -annotation(__OpenModelica_Interface="backend"); -end HashTableCrToCrEqLst; -/* - * This file is part of OpenModelica. - * - * Copyright (c) 1998-2014, Open Source Modelica Consortium (OSMC), - * c/o Linköpings universitet, Department of Computer and Information Science, - * SE-58183 Linköping, Sweden. - * - * All rights reserved. - * - * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF GPL VERSION 3 LICENSE OR - * THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.2. - * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES - * RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GPL VERSION 3, - * ACCORDING TO RECIPIENTS CHOICE. - * - * The OpenModelica software and the Open Source Modelica - * Consortium (OSMC) Public License (OSMC-PL) are obtained - * from OSMC, either from the above address, - * from the URLs: http://www.ida.liu.se/projects/OpenModelica or - * http://www.openmodelica.org, and in the OpenModelica distribution. - * GNU version 3 is obtained from: http://www.gnu.org/copyleft/gpl.html. - * - * This program is distributed WITHOUT ANY WARRANTY; without - * even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH - * IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL. - * - * See the full OSMC Public License conditions for more details. - * - */ - -encapsulated package HashTableCrToCrEqLst - -/* Below is the instance specific code. For each hashtable the user must define: - -Key - The key used to uniquely define elements in a hashtable -Value - The data to associate with each key -hashFunc - A function that maps a key to a positive integer. -keyEqual - A comparison function between two keys, returns true if equal. -*/ - -/* HashTable instance specific code */ - -public import BaseHashTable; -public import DAE; -public import BackendDAE; -public import System; -protected import ComponentReference; -protected import BackendDump; -protected import List; - -public type Key = DAE.ComponentRef; -public type Value = list>; - -public type HashTableCrefFunctionsType = tuple; -public type HashTable = tuple< - array>>, - tuple>>>, - Integer, - Integer, - HashTableCrefFunctionsType ->; - -partial function FuncHashCref - input Key cr; - input Integer mod; - output Integer res; -end FuncHashCref; - -partial function FuncCrefEqual - input Key cr1; - input Key cr2; - output Boolean res; -end FuncCrefEqual; - -partial function FuncCrefStr - input Key cr; - output String res; -end FuncCrefStr; - -partial function FuncExpStr - input Value exp; - output String res; -end FuncExpStr; - -public function emptyHashTable -" - Returns an empty HashTable. - Using the default bucketsize.. -" - output HashTable hashTable; -algorithm - hashTable := emptyHashTableSized(BaseHashTable.defaultBucketSize); -end emptyHashTable; - -public function emptyHashTableSized -"Returns an empty HashTable. - Using the bucketsize size." - input Integer size; - output HashTable hashTable; -algorithm - hashTable := BaseHashTable.emptyHashTableWork(size,(ComponentReference.hashComponentRefMod,ComponentReference.crefEqual,ComponentReference.printComponentRefStr,printTupleComponentRefEqListStr)); -end emptyHashTableSized; - -public function printTupleComponentRefEqListStr - input list> cr_eq_lst; - output String res; -algorithm - res := stringDelimitList(List.map(cr_eq_lst, printTupleComponentRefEqStr), ","); -end printTupleComponentRefEqListStr; - -public function printTupleComponentRefEqStr - input tuple cr_eq; - output String res; -protected - DAE.ComponentRef cr; - BackendDAE.Equation eq; -algorithm - (cr, eq) := cr_eq; - res := "{" + ComponentReference.printComponentRefStr(cr) + "," + BackendDump.equationString(eq) + "}"; -end printTupleComponentRefEqStr; - -annotation(__OpenModelica_Interface="backend"); -end HashTableCrToCrEqLst; \ No newline at end of file diff --git a/Compiler/Util/HashTableCrToExp.mo b/Compiler/Util/HashTableCrToExp.mo index 5b278edd76a..7f2e15afb22 100644 --- a/Compiler/Util/HashTableCrToExp.mo +++ b/Compiler/Util/HashTableCrToExp.mo @@ -44,7 +44,6 @@ public import BaseHashTable; public import DAE; public import System; protected import ComponentReference; -protected import Expression; protected import ExpressionDump; public type Key = DAE.ComponentRef; @@ -113,1038 +112,3 @@ end calcHashValue; annotation(__OpenModelica_Interface="frontend"); end HashTableCrToExp; -/* - * This file is part of OpenModelica. - * - * Copyright (c) 1998-2014, Open Source Modelica Consortium (OSMC), - * c/o Linköpings universitet, Department of Computer and Information Science, - * SE-58183 Linköping, Sweden. - * - * All rights reserved. - * - * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF GPL VERSION 3 LICENSE OR - * THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.2. - * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES - * RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GPL VERSION 3, - * ACCORDING TO RECIPIENTS CHOICE. - * - * The OpenModelica software and the Open Source Modelica - * Consortium (OSMC) Public License (OSMC-PL) are obtained - * from OSMC, either from the above address, - * from the URLs: http://www.ida.liu.se/projects/OpenModelica or - * http://www.openmodelica.org, and in the OpenModelica distribution. - * GNU version 3 is obtained from: http://www.gnu.org/copyleft/gpl.html. - * - * This program is distributed WITHOUT ANY WARRANTY; without - * even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH - * IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL. - * - * See the full OSMC Public License conditions for more details. - * - */ - -encapsulated package HashTableCrToExp -/* Below is the instance specific code. For each hashtable the user must define: - -Key - The key used to uniquely define elements in a hashtable -Value - The data to associate with each key -hashFunc - A function that maps a key to a positive integer. -keyEqual - A comparison function between two keys, returns true if equal. -*/ - -/* HashTable instance specific code */ - -public import BaseHashTable; -public import DAE; -public import System; -protected import ComponentReference; -protected import Expression; -protected import ExpressionDump; - -public type Key = DAE.ComponentRef; -public type Value = DAE.Exp; - -public type HashTableCrefFunctionsType = tuple; -public type HashTable = tuple< - array>>, - tuple>>>, - Integer, - Integer, - HashTableCrefFunctionsType ->; - -partial function FuncHashCref - input Key cr; - input Integer mod; - output Integer res; -end FuncHashCref; - -partial function FuncCrefEqual - input Key cr1; - input Key cr2; - output Boolean res; -end FuncCrefEqual; - -partial function FuncCrefStr - input Key cr; - output String res; -end FuncCrefStr; - -partial function FuncExpStr - input Value exp; - output String res; -end FuncExpStr; - -public function emptyHashTable -" - Returns an empty HashTable. - Using the default bucketsize.. -" - output HashTable hashTable; -algorithm - hashTable := emptyHashTableSized(BaseHashTable.defaultBucketSize); -end emptyHashTable; - -public function emptyHashTableSized -" - Returns an empty HashTable. - Using the bucketsize size. -" - input Integer size; - output HashTable hashTable; -algorithm - hashTable := BaseHashTable.emptyHashTableWork(size,(ComponentReference.hashComponentRefMod,ComponentReference.crefEqual,ComponentReference.printComponentRefStr,ExpressionDump.printExpStr)); - //hashTable := BaseHashTable.emptyHashTableWork(size,(calcHashValue,ComponentReference.crefEqual,ComponentReference.printComponentRefStr,ExpressionDump.printExpStr)); -end emptyHashTableSized; - -protected function calcHashValue - input DAE.ComponentRef cr; - input Integer imod; - output Integer value; -algorithm - value := System.stringHashDjb2Mod(ComponentReference.printComponentRefStr(cr),imod); -end calcHashValue; - -annotation(__OpenModelica_Interface="frontend"); -end HashTableCrToExp; -/* - * This file is part of OpenModelica. - * - * Copyright (c) 1998-2014, Open Source Modelica Consortium (OSMC), - * c/o Linköpings universitet, Department of Computer and Information Science, - * SE-58183 Linköping, Sweden. - * - * All rights reserved. - * - * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF GPL VERSION 3 LICENSE OR - * THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.2. - * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES - * RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GPL VERSION 3, - * ACCORDING TO RECIPIENTS CHOICE. - * - * The OpenModelica software and the Open Source Modelica - * Consortium (OSMC) Public License (OSMC-PL) are obtained - * from OSMC, either from the above address, - * from the URLs: http://www.ida.liu.se/projects/OpenModelica or - * http://www.openmodelica.org, and in the OpenModelica distribution. - * GNU version 3 is obtained from: http://www.gnu.org/copyleft/gpl.html. - * - * This program is distributed WITHOUT ANY WARRANTY; without - * even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH - * IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL. - * - * See the full OSMC Public License conditions for more details. - * - */ - -encapsulated package HashTableCrToExp -/* Below is the instance specific code. For each hashtable the user must define: - -Key - The key used to uniquely define elements in a hashtable -Value - The data to associate with each key -hashFunc - A function that maps a key to a positive integer. -keyEqual - A comparison function between two keys, returns true if equal. -*/ - -/* HashTable instance specific code */ - -public import BaseHashTable; -public import DAE; -public import System; -protected import ComponentReference; -protected import Expression; -protected import ExpressionDump; - -public type Key = DAE.ComponentRef; -public type Value = DAE.Exp; - -public type HashTableCrefFunctionsType = tuple; -public type HashTable = tuple< - array>>, - tuple>>>, - Integer, - Integer, - HashTableCrefFunctionsType ->; - -partial function FuncHashCref - input Key cr; - input Integer mod; - output Integer res; -end FuncHashCref; - -partial function FuncCrefEqual - input Key cr1; - input Key cr2; - output Boolean res; -end FuncCrefEqual; - -partial function FuncCrefStr - input Key cr; - output String res; -end FuncCrefStr; - -partial function FuncExpStr - input Value exp; - output String res; -end FuncExpStr; - -public function emptyHashTable -" - Returns an empty HashTable. - Using the default bucketsize.. -" - output HashTable hashTable; -algorithm - hashTable := emptyHashTableSized(BaseHashTable.defaultBucketSize); -end emptyHashTable; - -public function emptyHashTableSized -" - Returns an empty HashTable. - Using the bucketsize size. -" - input Integer size; - output HashTable hashTable; -algorithm - hashTable := BaseHashTable.emptyHashTableWork(size,(ComponentReference.hashComponentRefMod,ComponentReference.crefEqual,ComponentReference.printComponentRefStr,ExpressionDump.printExpStr)); - //hashTable := BaseHashTable.emptyHashTableWork(size,(calcHashValue,ComponentReference.crefEqual,ComponentReference.printComponentRefStr,ExpressionDump.printExpStr)); -end emptyHashTableSized; - -protected function calcHashValue - input DAE.ComponentRef cr; - input Integer imod; - output Integer value; -algorithm - value := System.stringHashDjb2Mod(ComponentReference.printComponentRefStr(cr),imod); -end calcHashValue; - -annotation(__OpenModelica_Interface="frontend"); -end HashTableCrToExp; -/* - * This file is part of OpenModelica. - * - * Copyright (c) 1998-2014, Open Source Modelica Consortium (OSMC), - * c/o Linköpings universitet, Department of Computer and Information Science, - * SE-58183 Linköping, Sweden. - * - * All rights reserved. - * - * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF GPL VERSION 3 LICENSE OR - * THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.2. - * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES - * RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GPL VERSION 3, - * ACCORDING TO RECIPIENTS CHOICE. - * - * The OpenModelica software and the Open Source Modelica - * Consortium (OSMC) Public License (OSMC-PL) are obtained - * from OSMC, either from the above address, - * from the URLs: http://www.ida.liu.se/projects/OpenModelica or - * http://www.openmodelica.org, and in the OpenModelica distribution. - * GNU version 3 is obtained from: http://www.gnu.org/copyleft/gpl.html. - * - * This program is distributed WITHOUT ANY WARRANTY; without - * even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH - * IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL. - * - * See the full OSMC Public License conditions for more details. - * - */ - -encapsulated package HashTableCrToExp -/* Below is the instance specific code. For each hashtable the user must define: - -Key - The key used to uniquely define elements in a hashtable -Value - The data to associate with each key -hashFunc - A function that maps a key to a positive integer. -keyEqual - A comparison function between two keys, returns true if equal. -*/ - -/* HashTable instance specific code */ - -public import BaseHashTable; -public import DAE; -public import System; -protected import ComponentReference; -protected import Expression; -protected import ExpressionDump; - -public type Key = DAE.ComponentRef; -public type Value = DAE.Exp; - -public type HashTableCrefFunctionsType = tuple; -public type HashTable = tuple< - array>>, - tuple>>>, - Integer, - Integer, - HashTableCrefFunctionsType ->; - -partial function FuncHashCref - input Key cr; - input Integer mod; - output Integer res; -end FuncHashCref; - -partial function FuncCrefEqual - input Key cr1; - input Key cr2; - output Boolean res; -end FuncCrefEqual; - -partial function FuncCrefStr - input Key cr; - output String res; -end FuncCrefStr; - -partial function FuncExpStr - input Value exp; - output String res; -end FuncExpStr; - -public function emptyHashTable -" - Returns an empty HashTable. - Using the default bucketsize.. -" - output HashTable hashTable; -algorithm - hashTable := emptyHashTableSized(BaseHashTable.defaultBucketSize); -end emptyHashTable; - -public function emptyHashTableSized -" - Returns an empty HashTable. - Using the bucketsize size. -" - input Integer size; - output HashTable hashTable; -algorithm - hashTable := BaseHashTable.emptyHashTableWork(size,(ComponentReference.hashComponentRefMod,ComponentReference.crefEqual,ComponentReference.printComponentRefStr,ExpressionDump.printExpStr)); - //hashTable := BaseHashTable.emptyHashTableWork(size,(calcHashValue,ComponentReference.crefEqual,ComponentReference.printComponentRefStr,ExpressionDump.printExpStr)); -end emptyHashTableSized; - -protected function calcHashValue - input DAE.ComponentRef cr; - input Integer imod; - output Integer value; -algorithm - value := System.stringHashDjb2Mod(ComponentReference.printComponentRefStr(cr),imod); -end calcHashValue; - -annotation(__OpenModelica_Interface="frontend"); -end HashTableCrToExp; -/* - * This file is part of OpenModelica. - * - * Copyright (c) 1998-2014, Open Source Modelica Consortium (OSMC), - * c/o Linköpings universitet, Department of Computer and Information Science, - * SE-58183 Linköping, Sweden. - * - * All rights reserved. - * - * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF GPL VERSION 3 LICENSE OR - * THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.2. - * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES - * RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GPL VERSION 3, - * ACCORDING TO RECIPIENTS CHOICE. - * - * The OpenModelica software and the Open Source Modelica - * Consortium (OSMC) Public License (OSMC-PL) are obtained - * from OSMC, either from the above address, - * from the URLs: http://www.ida.liu.se/projects/OpenModelica or - * http://www.openmodelica.org, and in the OpenModelica distribution. - * GNU version 3 is obtained from: http://www.gnu.org/copyleft/gpl.html. - * - * This program is distributed WITHOUT ANY WARRANTY; without - * even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH - * IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL. - * - * See the full OSMC Public License conditions for more details. - * - */ - -encapsulated package HashTableCrToExp -/* Below is the instance specific code. For each hashtable the user must define: - -Key - The key used to uniquely define elements in a hashtable -Value - The data to associate with each key -hashFunc - A function that maps a key to a positive integer. -keyEqual - A comparison function between two keys, returns true if equal. -*/ - -/* HashTable instance specific code */ - -public import BaseHashTable; -public import DAE; -public import System; -protected import ComponentReference; -protected import Expression; -protected import ExpressionDump; - -public type Key = DAE.ComponentRef; -public type Value = DAE.Exp; - -public type HashTableCrefFunctionsType = tuple; -public type HashTable = tuple< - array>>, - tuple>>>, - Integer, - Integer, - HashTableCrefFunctionsType ->; - -partial function FuncHashCref - input Key cr; - input Integer mod; - output Integer res; -end FuncHashCref; - -partial function FuncCrefEqual - input Key cr1; - input Key cr2; - output Boolean res; -end FuncCrefEqual; - -partial function FuncCrefStr - input Key cr; - output String res; -end FuncCrefStr; - -partial function FuncExpStr - input Value exp; - output String res; -end FuncExpStr; - -public function emptyHashTable -" - Returns an empty HashTable. - Using the default bucketsize.. -" - output HashTable hashTable; -algorithm - hashTable := emptyHashTableSized(BaseHashTable.defaultBucketSize); -end emptyHashTable; - -public function emptyHashTableSized -" - Returns an empty HashTable. - Using the bucketsize size. -" - input Integer size; - output HashTable hashTable; -algorithm - hashTable := BaseHashTable.emptyHashTableWork(size,(ComponentReference.hashComponentRefMod,ComponentReference.crefEqual,ComponentReference.printComponentRefStr,ExpressionDump.printExpStr)); - //hashTable := BaseHashTable.emptyHashTableWork(size,(calcHashValue,ComponentReference.crefEqual,ComponentReference.printComponentRefStr,ExpressionDump.printExpStr)); -end emptyHashTableSized; - -protected function calcHashValue - input DAE.ComponentRef cr; - input Integer imod; - output Integer value; -algorithm - value := System.stringHashDjb2Mod(ComponentReference.printComponentRefStr(cr),imod); -end calcHashValue; - -annotation(__OpenModelica_Interface="frontend"); -end HashTableCrToExp; -/* - * This file is part of OpenModelica. - * - * Copyright (c) 1998-2014, Open Source Modelica Consortium (OSMC), - * c/o Linköpings universitet, Department of Computer and Information Science, - * SE-58183 Linköping, Sweden. - * - * All rights reserved. - * - * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF GPL VERSION 3 LICENSE OR - * THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.2. - * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES - * RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GPL VERSION 3, - * ACCORDING TO RECIPIENTS CHOICE. - * - * The OpenModelica software and the Open Source Modelica - * Consortium (OSMC) Public License (OSMC-PL) are obtained - * from OSMC, either from the above address, - * from the URLs: http://www.ida.liu.se/projects/OpenModelica or - * http://www.openmodelica.org, and in the OpenModelica distribution. - * GNU version 3 is obtained from: http://www.gnu.org/copyleft/gpl.html. - * - * This program is distributed WITHOUT ANY WARRANTY; without - * even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH - * IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL. - * - * See the full OSMC Public License conditions for more details. - * - */ - -encapsulated package HashTableCrToExp -/* Below is the instance specific code. For each hashtable the user must define: - -Key - The key used to uniquely define elements in a hashtable -Value - The data to associate with each key -hashFunc - A function that maps a key to a positive integer. -keyEqual - A comparison function between two keys, returns true if equal. -*/ - -/* HashTable instance specific code */ - -public import BaseHashTable; -public import DAE; -public import System; -protected import ComponentReference; -protected import Expression; -protected import ExpressionDump; - -public type Key = DAE.ComponentRef; -public type Value = DAE.Exp; - -public type HashTableCrefFunctionsType = tuple; -public type HashTable = tuple< - array>>, - tuple>>>, - Integer, - Integer, - HashTableCrefFunctionsType ->; - -partial function FuncHashCref - input Key cr; - input Integer mod; - output Integer res; -end FuncHashCref; - -partial function FuncCrefEqual - input Key cr1; - input Key cr2; - output Boolean res; -end FuncCrefEqual; - -partial function FuncCrefStr - input Key cr; - output String res; -end FuncCrefStr; - -partial function FuncExpStr - input Value exp; - output String res; -end FuncExpStr; - -public function emptyHashTable -" - Returns an empty HashTable. - Using the default bucketsize.. -" - output HashTable hashTable; -algorithm - hashTable := emptyHashTableSized(BaseHashTable.defaultBucketSize); -end emptyHashTable; - -public function emptyHashTableSized -" - Returns an empty HashTable. - Using the bucketsize size. -" - input Integer size; - output HashTable hashTable; -algorithm - hashTable := BaseHashTable.emptyHashTableWork(size,(ComponentReference.hashComponentRefMod,ComponentReference.crefEqual,ComponentReference.printComponentRefStr,ExpressionDump.printExpStr)); - //hashTable := BaseHashTable.emptyHashTableWork(size,(calcHashValue,ComponentReference.crefEqual,ComponentReference.printComponentRefStr,ExpressionDump.printExpStr)); -end emptyHashTableSized; - -protected function calcHashValue - input DAE.ComponentRef cr; - input Integer imod; - output Integer value; -algorithm - value := System.stringHashDjb2Mod(ComponentReference.printComponentRefStr(cr),imod); -end calcHashValue; - -annotation(__OpenModelica_Interface="frontend"); -end HashTableCrToExp; -/* - * This file is part of OpenModelica. - * - * Copyright (c) 1998-2014, Open Source Modelica Consortium (OSMC), - * c/o Linköpings universitet, Department of Computer and Information Science, - * SE-58183 Linköping, Sweden. - * - * All rights reserved. - * - * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF GPL VERSION 3 LICENSE OR - * THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.2. - * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES - * RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GPL VERSION 3, - * ACCORDING TO RECIPIENTS CHOICE. - * - * The OpenModelica software and the Open Source Modelica - * Consortium (OSMC) Public License (OSMC-PL) are obtained - * from OSMC, either from the above address, - * from the URLs: http://www.ida.liu.se/projects/OpenModelica or - * http://www.openmodelica.org, and in the OpenModelica distribution. - * GNU version 3 is obtained from: http://www.gnu.org/copyleft/gpl.html. - * - * This program is distributed WITHOUT ANY WARRANTY; without - * even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH - * IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL. - * - * See the full OSMC Public License conditions for more details. - * - */ - -encapsulated package HashTableCrToExp -/* Below is the instance specific code. For each hashtable the user must define: - -Key - The key used to uniquely define elements in a hashtable -Value - The data to associate with each key -hashFunc - A function that maps a key to a positive integer. -keyEqual - A comparison function between two keys, returns true if equal. -*/ - -/* HashTable instance specific code */ - -public import BaseHashTable; -public import DAE; -public import System; -protected import ComponentReference; -protected import Expression; -protected import ExpressionDump; - -public type Key = DAE.ComponentRef; -public type Value = DAE.Exp; - -public type HashTableCrefFunctionsType = tuple; -public type HashTable = tuple< - array>>, - tuple>>>, - Integer, - Integer, - HashTableCrefFunctionsType ->; - -partial function FuncHashCref - input Key cr; - input Integer mod; - output Integer res; -end FuncHashCref; - -partial function FuncCrefEqual - input Key cr1; - input Key cr2; - output Boolean res; -end FuncCrefEqual; - -partial function FuncCrefStr - input Key cr; - output String res; -end FuncCrefStr; - -partial function FuncExpStr - input Value exp; - output String res; -end FuncExpStr; - -public function emptyHashTable -" - Returns an empty HashTable. - Using the default bucketsize.. -" - output HashTable hashTable; -algorithm - hashTable := emptyHashTableSized(BaseHashTable.defaultBucketSize); -end emptyHashTable; - -public function emptyHashTableSized -" - Returns an empty HashTable. - Using the bucketsize size. -" - input Integer size; - output HashTable hashTable; -algorithm - hashTable := BaseHashTable.emptyHashTableWork(size,(ComponentReference.hashComponentRefMod,ComponentReference.crefEqual,ComponentReference.printComponentRefStr,ExpressionDump.printExpStr)); - //hashTable := BaseHashTable.emptyHashTableWork(size,(calcHashValue,ComponentReference.crefEqual,ComponentReference.printComponentRefStr,ExpressionDump.printExpStr)); -end emptyHashTableSized; - -protected function calcHashValue - input DAE.ComponentRef cr; - input Integer imod; - output Integer value; -algorithm - value := System.stringHashDjb2Mod(ComponentReference.printComponentRefStr(cr),imod); -end calcHashValue; - -annotation(__OpenModelica_Interface="frontend"); -end HashTableCrToExp; -/* - * This file is part of OpenModelica. - * - * Copyright (c) 1998-2014, Open Source Modelica Consortium (OSMC), - * c/o Linköpings universitet, Department of Computer and Information Science, - * SE-58183 Linköping, Sweden. - * - * All rights reserved. - * - * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF GPL VERSION 3 LICENSE OR - * THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.2. - * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES - * RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GPL VERSION 3, - * ACCORDING TO RECIPIENTS CHOICE. - * - * The OpenModelica software and the Open Source Modelica - * Consortium (OSMC) Public License (OSMC-PL) are obtained - * from OSMC, either from the above address, - * from the URLs: http://www.ida.liu.se/projects/OpenModelica or - * http://www.openmodelica.org, and in the OpenModelica distribution. - * GNU version 3 is obtained from: http://www.gnu.org/copyleft/gpl.html. - * - * This program is distributed WITHOUT ANY WARRANTY; without - * even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH - * IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL. - * - * See the full OSMC Public License conditions for more details. - * - */ - -encapsulated package HashTableCrToExp -/* Below is the instance specific code. For each hashtable the user must define: - -Key - The key used to uniquely define elements in a hashtable -Value - The data to associate with each key -hashFunc - A function that maps a key to a positive integer. -keyEqual - A comparison function between two keys, returns true if equal. -*/ - -/* HashTable instance specific code */ - -public import BaseHashTable; -public import DAE; -public import System; -protected import ComponentReference; -protected import Expression; -protected import ExpressionDump; - -public type Key = DAE.ComponentRef; -public type Value = DAE.Exp; - -public type HashTableCrefFunctionsType = tuple; -public type HashTable = tuple< - array>>, - tuple>>>, - Integer, - Integer, - HashTableCrefFunctionsType ->; - -partial function FuncHashCref - input Key cr; - input Integer mod; - output Integer res; -end FuncHashCref; - -partial function FuncCrefEqual - input Key cr1; - input Key cr2; - output Boolean res; -end FuncCrefEqual; - -partial function FuncCrefStr - input Key cr; - output String res; -end FuncCrefStr; - -partial function FuncExpStr - input Value exp; - output String res; -end FuncExpStr; - -public function emptyHashTable -" - Returns an empty HashTable. - Using the default bucketsize.. -" - output HashTable hashTable; -algorithm - hashTable := emptyHashTableSized(BaseHashTable.defaultBucketSize); -end emptyHashTable; - -public function emptyHashTableSized -" - Returns an empty HashTable. - Using the bucketsize size. -" - input Integer size; - output HashTable hashTable; -algorithm - hashTable := BaseHashTable.emptyHashTableWork(size,(ComponentReference.hashComponentRefMod,ComponentReference.crefEqual,ComponentReference.printComponentRefStr,ExpressionDump.printExpStr)); - //hashTable := BaseHashTable.emptyHashTableWork(size,(calcHashValue,ComponentReference.crefEqual,ComponentReference.printComponentRefStr,ExpressionDump.printExpStr)); -end emptyHashTableSized; - -protected function calcHashValue - input DAE.ComponentRef cr; - input Integer imod; - output Integer value; -algorithm - value := System.stringHashDjb2Mod(ComponentReference.printComponentRefStr(cr),imod); -end calcHashValue; - -annotation(__OpenModelica_Interface="frontend"); -end HashTableCrToExp; -/* - * This file is part of OpenModelica. - * - * Copyright (c) 1998-2014, Open Source Modelica Consortium (OSMC), - * c/o Linköpings universitet, Department of Computer and Information Science, - * SE-58183 Linköping, Sweden. - * - * All rights reserved. - * - * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF GPL VERSION 3 LICENSE OR - * THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.2. - * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES - * RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GPL VERSION 3, - * ACCORDING TO RECIPIENTS CHOICE. - * - * The OpenModelica software and the Open Source Modelica - * Consortium (OSMC) Public License (OSMC-PL) are obtained - * from OSMC, either from the above address, - * from the URLs: http://www.ida.liu.se/projects/OpenModelica or - * http://www.openmodelica.org, and in the OpenModelica distribution. - * GNU version 3 is obtained from: http://www.gnu.org/copyleft/gpl.html. - * - * This program is distributed WITHOUT ANY WARRANTY; without - * even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH - * IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL. - * - * See the full OSMC Public License conditions for more details. - * - */ - -encapsulated package HashTableCrToExp -/* Below is the instance specific code. For each hashtable the user must define: - -Key - The key used to uniquely define elements in a hashtable -Value - The data to associate with each key -hashFunc - A function that maps a key to a positive integer. -keyEqual - A comparison function between two keys, returns true if equal. -*/ - -/* HashTable instance specific code */ - -public import BaseHashTable; -public import DAE; -public import System; -protected import ComponentReference; -protected import Expression; -protected import ExpressionDump; - -public type Key = DAE.ComponentRef; -public type Value = DAE.Exp; - -public type HashTableCrefFunctionsType = tuple; -public type HashTable = tuple< - array>>, - tuple>>>, - Integer, - Integer, - HashTableCrefFunctionsType ->; - -partial function FuncHashCref - input Key cr; - input Integer mod; - output Integer res; -end FuncHashCref; - -partial function FuncCrefEqual - input Key cr1; - input Key cr2; - output Boolean res; -end FuncCrefEqual; - -partial function FuncCrefStr - input Key cr; - output String res; -end FuncCrefStr; - -partial function FuncExpStr - input Value exp; - output String res; -end FuncExpStr; - -public function emptyHashTable -" - Returns an empty HashTable. - Using the default bucketsize.. -" - output HashTable hashTable; -algorithm - hashTable := emptyHashTableSized(BaseHashTable.defaultBucketSize); -end emptyHashTable; - -public function emptyHashTableSized -" - Returns an empty HashTable. - Using the bucketsize size. -" - input Integer size; - output HashTable hashTable; -algorithm - hashTable := BaseHashTable.emptyHashTableWork(size,(ComponentReference.hashComponentRefMod,ComponentReference.crefEqual,ComponentReference.printComponentRefStr,ExpressionDump.printExpStr)); - //hashTable := BaseHashTable.emptyHashTableWork(size,(calcHashValue,ComponentReference.crefEqual,ComponentReference.printComponentRefStr,ExpressionDump.printExpStr)); -end emptyHashTableSized; - -protected function calcHashValue - input DAE.ComponentRef cr; - input Integer imod; - output Integer value; -algorithm - value := System.stringHashDjb2Mod(ComponentReference.printComponentRefStr(cr),imod); -end calcHashValue; - -annotation(__OpenModelica_Interface="frontend"); -end HashTableCrToExp; -/* - * This file is part of OpenModelica. - * - * Copyright (c) 1998-2014, Open Source Modelica Consortium (OSMC), - * c/o Linköpings universitet, Department of Computer and Information Science, - * SE-58183 Linköping, Sweden. - * - * All rights reserved. - * - * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF GPL VERSION 3 LICENSE OR - * THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.2. - * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES - * RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GPL VERSION 3, - * ACCORDING TO RECIPIENTS CHOICE. - * - * The OpenModelica software and the Open Source Modelica - * Consortium (OSMC) Public License (OSMC-PL) are obtained - * from OSMC, either from the above address, - * from the URLs: http://www.ida.liu.se/projects/OpenModelica or - * http://www.openmodelica.org, and in the OpenModelica distribution. - * GNU version 3 is obtained from: http://www.gnu.org/copyleft/gpl.html. - * - * This program is distributed WITHOUT ANY WARRANTY; without - * even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH - * IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL. - * - * See the full OSMC Public License conditions for more details. - * - */ - -encapsulated package HashTableCrToExp -/* Below is the instance specific code. For each hashtable the user must define: - -Key - The key used to uniquely define elements in a hashtable -Value - The data to associate with each key -hashFunc - A function that maps a key to a positive integer. -keyEqual - A comparison function between two keys, returns true if equal. -*/ - -/* HashTable instance specific code */ - -public import BaseHashTable; -public import DAE; -public import System; -protected import ComponentReference; -protected import Expression; -protected import ExpressionDump; - -public type Key = DAE.ComponentRef; -public type Value = DAE.Exp; - -public type HashTableCrefFunctionsType = tuple; -public type HashTable = tuple< - array>>, - tuple>>>, - Integer, - Integer, - HashTableCrefFunctionsType ->; - -partial function FuncHashCref - input Key cr; - input Integer mod; - output Integer res; -end FuncHashCref; - -partial function FuncCrefEqual - input Key cr1; - input Key cr2; - output Boolean res; -end FuncCrefEqual; - -partial function FuncCrefStr - input Key cr; - output String res; -end FuncCrefStr; - -partial function FuncExpStr - input Value exp; - output String res; -end FuncExpStr; - -public function emptyHashTable -" - Returns an empty HashTable. - Using the default bucketsize.. -" - output HashTable hashTable; -algorithm - hashTable := emptyHashTableSized(BaseHashTable.defaultBucketSize); -end emptyHashTable; - -public function emptyHashTableSized -" - Returns an empty HashTable. - Using the bucketsize size. -" - input Integer size; - output HashTable hashTable; -algorithm - hashTable := BaseHashTable.emptyHashTableWork(size,(ComponentReference.hashComponentRefMod,ComponentReference.crefEqual,ComponentReference.printComponentRefStr,ExpressionDump.printExpStr)); - //hashTable := BaseHashTable.emptyHashTableWork(size,(calcHashValue,ComponentReference.crefEqual,ComponentReference.printComponentRefStr,ExpressionDump.printExpStr)); -end emptyHashTableSized; - -protected function calcHashValue - input DAE.ComponentRef cr; - input Integer imod; - output Integer value; -algorithm - value := System.stringHashDjb2Mod(ComponentReference.printComponentRefStr(cr),imod); -end calcHashValue; - -annotation(__OpenModelica_Interface="frontend"); -end HashTableCrToExp; \ No newline at end of file diff --git a/Compiler/Util/HashTableExpToIndexExp.mo b/Compiler/Util/HashTableExpToIndexExp.mo index 89e9415927a..66a2c73213d 100644 --- a/Compiler/Util/HashTableExpToIndexExp.mo +++ b/Compiler/Util/HashTableExpToIndexExp.mo @@ -44,7 +44,6 @@ keyEqual - A comparison function between two keys, returns true if equal. public import BaseHashTable; public import DAE; protected import Expression; -protected import List; protected import Util; public import ExpressionDump; diff --git a/Compiler/Util/HashTablePathToFunction.mo b/Compiler/Util/HashTablePathToFunction.mo index 9aeb3ad28c4..8fc9427d7a0 100644 --- a/Compiler/Util/HashTablePathToFunction.mo +++ b/Compiler/Util/HashTablePathToFunction.mo @@ -45,8 +45,6 @@ public import BaseHashTable; public import Absyn; public import NFInstTypes; -protected import System; - public type Key = Absyn.Path; public type Value = NFInstTypes.Function; diff --git a/Compiler/Util/HashTableStringToProgram.mo b/Compiler/Util/HashTableStringToProgram.mo index 642bd9bd7c0..01ef1c571d2 100644 --- a/Compiler/Util/HashTableStringToProgram.mo +++ b/Compiler/Util/HashTableStringToProgram.mo @@ -43,7 +43,6 @@ keyEqual - A comparison function between two keys, returns true if equal. public import Absyn; public import BaseHashTable; -protected import Dump; protected import Util; protected import System; diff --git a/Compiler/Util/HashTableUnitToString.mo b/Compiler/Util/HashTableUnitToString.mo index b3a815f692f..87254c80cb2 100644 --- a/Compiler/Util/HashTableUnitToString.mo +++ b/Compiler/Util/HashTableUnitToString.mo @@ -55,10 +55,7 @@ keyEqual - A comparison function between two keys, returns true if equal. /* HashTable instance specific code */ public import BaseHashTable; -public import System; public import Unit; -public import Util; - public type Key = Unit.Unit; public type Value = String; diff --git a/Compiler/Util/PriorityQueue.mo b/Compiler/Util/PriorityQueue.mo index 0e79dcf27bd..dc04fb01ab2 100644 --- a/Compiler/Util/PriorityQueue.mo +++ b/Compiler/Util/PriorityQueue.mo @@ -52,7 +52,6 @@ TODO: Implement insert() in O(1) time TODO: Implement meld() in O(1) time " -protected import List; public import SimCode; public diff --git a/Compiler/Util/SimulationResults.mo b/Compiler/Util/SimulationResults.mo index b2b86790570..d900eb073bd 100644 --- a/Compiler/Util/SimulationResults.mo +++ b/Compiler/Util/SimulationResults.mo @@ -38,7 +38,12 @@ encapsulated package SimulationResults " -public import Values; +import Values; + +protected + +import List; +import ValuesUtil; public function val input String filename; @@ -61,9 +66,24 @@ public function readDataset input String filename; input list vars; input Integer dimsize; - output list> outMatrix; - - external "C" outMatrix=SimulationResults_readDataset(filename,vars,dimsize) annotation(Library = "omcruntime"); + output Values.Value val; +protected + list> rvals; + list> vals; + list rows; + function readDataset_work + input String filename; + input list vars; + input Integer dimsize; + output list> outMatrix; + + external "C" outMatrix=SimulationResults_readDataset(filename,vars,dimsize) annotation(Library = "omcruntime"); + end readDataset_work; +algorithm + rvals := readDataset_work(filename,vars,dimsize); + vals := List.mapListReverse(rvals, ValuesUtil.makeReal); + rows := List.mapReverse(vals, ValuesUtil.makeArray); + val := ValuesUtil.makeArray(rows); end readDataset; public function readSimulationResultSize diff --git a/Compiler/Util/VisualXML.mo b/Compiler/Util/VisualXML.mo index 5756831d75b..cd63b60bf14 100644 --- a/Compiler/Util/VisualXML.mo +++ b/Compiler/Util/VisualXML.mo @@ -40,21 +40,22 @@ encapsulated package VisualXML " -protected import Absyn; -protected import Array; -protected import BackendDAE; -protected import BackendDAEUtil; -protected import BackendEquation; -protected import BackendVariable; -protected import ComponentReference; -protected import DAE; -protected import DAEUtil; -protected import ExpressionDump; -protected import ExpressionSolve; -protected import List; -protected import Util; -protected import Tpl; -protected import VisualXMLTpl; +protected + +import Absyn; +import BackendDAE; +import BackendDAEUtil; +import BackendEquation; +import BackendVariable; +import ComponentReference; +import DAE; +import DAEUtil; +import ExpressionDump; +import ExpressionSolve; +import List; +import Util; +import Tpl; +import VisualXMLTpl; //---------------------------- // Visualization types diff --git a/Compiler/boot/LoadCompilerSources.mos b/Compiler/boot/LoadCompilerSources.mos index 7b0a42c4dde..0d6238bad3b 100644 --- a/Compiler/boot/LoadCompilerSources.mos +++ b/Compiler/boot/LoadCompilerSources.mos @@ -3,7 +3,7 @@ // "FrontEnd"; if true then /* Suppress output */ setCommandLineOptions("+g=MetaModelica"); - files := { + alwaysfiles := { // "../Util/MessagePack.mo", // TODO: Add once we bootstrapped omc, maybe "../Util/File.mo", "../FrontEnd/Absyn.mo", @@ -12,7 +12,6 @@ if true then /* Suppress output */ "../FrontEnd/Builtin.mo", "../FrontEnd/CevalFunction.mo", "../FrontEnd/Ceval.mo", - "../FrontEnd/CheckModel.mo", "../FrontEnd/ClassInf.mo", "../FrontEnd/ClassLoader.mo", "../FrontEnd/ComponentReference.mo", @@ -23,7 +22,6 @@ if true then /* Suppress output */ "../FrontEnd/DAEDump.mo", "../FrontEnd/DAE.mo", "../FrontEnd/DAEUtil.mo", - "../FrontEnd/DumpGraphviz.mo", "../FrontEnd/Dump.mo", "../FrontEnd/ExpressionDump.mo", "../FrontEnd/Expression.mo", @@ -55,26 +53,25 @@ if true then /* Suppress output */ "../FrontEnd/SCodeDump.mo", "../FrontEnd/SCodeUtil.mo", "../FrontEnd/Static.mo", - "../FrontEnd/SCodeSimplify.mo", - "../FrontEnd/NFBuiltin.mo", + //"../FrontEnd/SCodeSimplify.mo", + //"../FrontEnd/NFBuiltin.mo", "../FrontEnd/NFConnect2.mo", //"../FrontEnd/NFConnectCheck.mo", //"../FrontEnd/NFConnectEquations.mo", //"../FrontEnd/NFConnectUtil2.mo", //"../FrontEnd/NFConnectionSets.mo", "../FrontEnd/NFEnv.mo", - "../FrontEnd/NFEnvAvlTree.mo", + //"../FrontEnd/NFEnvAvlTree.mo", "../FrontEnd/NFEnvExtends.mo", - // "../FrontEnd/NFEvalFunction.mo", + //"../FrontEnd/NFEvalFunction.mo", //"../FrontEnd/NFExpandableConnectors.mo", "../FrontEnd/NFFlatten.mo", "../FrontEnd/NFInst.mo", - "../FrontEnd/NFInstDump.mo", //"../FrontEnd/NFInstFlatten.mo", "../FrontEnd/NFInstPrefix.mo", //"../FrontEnd/NFInstSymbolTable.mo", "../FrontEnd/NFInstTypes.mo", - "../FrontEnd/NFInstTypesOld.mo", + //"../FrontEnd/NFInstTypesOld.mo", "../FrontEnd/NFInstUtil.mo", "../FrontEnd/NFLookup.mo", //"../FrontEnd/NFMod.mo", @@ -86,16 +83,14 @@ if true then /* Suppress output */ "../FrontEnd/NFSCodeFlatten.mo", "../FrontEnd/NFSCodeFlattenRedeclare.mo", "../FrontEnd/NFSCodeLookup.mo", - // "../FrontEnd/NFSCodeHashTable.mo", - "../FrontEnd/NFSCodeMod.mo", + //"../FrontEnd/NFSCodeHashTable.mo", + //"../FrontEnd/NFSCodeMod.mo", "../FrontEnd/NFSCodeCheck.mo", //"../FrontEnd/NFTypeCheck.mo", //"../FrontEnd/NFTyping.mo", - // "../FrontEnd/NFSCodeStatic.mo", + //"../FrontEnd/NFSCodeStatic.mo", "../FrontEnd/Types.mo", - "../FrontEnd/UnitAbsynBuilder.mo", "../FrontEnd/UnitAbsyn.mo", - "../FrontEnd/UnitChecker.mo", "../FrontEnd/UnitParserExt.mo", "../FrontEnd/Values.mo", "../FrontEnd/ValuesUtil.mo", @@ -107,9 +102,6 @@ if true then /* Suppress output */ "../FFrontEnd/FGraph.mo", "../FFrontEnd/FGraphBuild.mo", "../FFrontEnd/FGraphBuildEnv.mo", - "../FFrontEnd/FGraphDump.mo", - "../FFrontEnd/FGraphStream.mo", - "../FFrontEnd/FInst.mo", "../FFrontEnd/FLookup.mo", "../FFrontEnd/FMod.mo", "../FFrontEnd/FNode.mo", @@ -117,8 +109,108 @@ if true then /* Suppress output */ "../FFrontEnd/FTraverse.mo", "../FFrontEnd/FVisit.mo", - // "BackEnd"; + // "BackEnd"; "../BackEnd/BackendDAE.mo", + + // "SimCode"; + "../SimCode/HpcOmSimCode.mo", + "../SimCode/SimCode.mo", + "../SimCode/SimCodeFunction.mo", + "../SimCode/SimCodeFunctionUtil.mo", + "../SimCode/SimCodeVar.mo", + + // "Script"; + "../Script/CevalScript.mo", + "../Script/GlobalScript.mo", + "../Script/GlobalScriptDump.mo", + "../Script/GlobalScriptUtil.mo", + "../Script/StaticScript.mo", + "../Script/Interactive.mo", + + // "Template"; + "../Template/AbsynDumpTpl.mo", + "../Template/CodegenCFunctions.mo", + "../Template/CodegenUtil.mo", + "../Template/DAEDumpTpl.mo", + "../Template/ExpressionDumpTpl.mo", + "../Template/GenerateAPIFunctionsTpl.mo", + "../Template/SCodeDumpTpl.mo", + "../Template/TplAbsyn.mo", + "../Template/TplCodegen.mo", + "../Template/TplMain.mo", + "../Template/Tpl.mo", + "../Template/TplParser.mo", + "../Template/Unparsing.mo", + + // "Global"; + "../Global/Global.mo", + + // "Main"; + "../Main/Main.mo", + + // "Util"; + "../Util/Array.mo", + //"../Util/AvlTree.mo", + "../Util/AvlTreeString.mo", + "../Util/BaseHashTable.mo", + "../Util/BaseHashSet.mo", + "../Util/ClockIndexes.mo", + "../Util/Config.mo", + "../Util/Corba.mo", + //"../Util/Database.mo", + "../Util/Debug.mo", + "../Util/DynLoad.mo", + "../Util/ErrorExt.mo", + "../Util/Error.mo", + "../Util/Flags.mo", + "../Util/GC.mo", + "../Util/Graph.mo", + "../Util/GraphStream.mo", + "../Util/GraphStreamExt.mo", + "../Util/HashSet.mo", + "../Util/HashSetString.mo", + "../Util/HashTable2.mo", + "../Util/HashTable3.mo", + "../Util/HashTable5.mo", + "../Util/HashTableCG.mo", + "../Util/HashTableCrILst.mo", + "../Util/HashTableCrIListArray.mo", + "../Util/HashTable.mo", + "../Util/HashTableExpToIndex.mo", + //"../Util/HashTablePathToFunction.mo", + "../Util/HashTableStringToPath.mo", + "../Util/HashTableStringToProgram.mo", + "../Util/IOStreamExt.mo", + "../Util/IOStream.mo", + "../Util/Lapack.mo", + "../Util/List.mo", + "../Util/ModelicaExternalC.mo", + "../Util/Print.mo", + "../Util/PriorityQueue.mo", + // "../Util/Serializer.mo", + "../Util/Settings.mo", + "../Util/StringUtil.mo", + "../Util/Socket.mo", + "../Util/System.mo", + "../Util/Util.mo", + "../Util/VarTransform.mo" + }; + backendfiles := if OpenModelica.Scripting.getEnvironmentVar("OPENMODELICA_BACKEND_STUBS")<>"" then + { + "../Stubs/BackendDAECreate.mo", + "../Stubs/BackendDAEUtil.mo", + "../Stubs/CevalScriptBackend.mo", + "../Stubs/DumpGraphviz.mo", + "../Stubs/FGraphStream.mo", + "../Stubs/NFInstDump.mo", + "../Stubs/Refactor.mo", + "../Stubs/RewriteRules.mo", + "../Stubs/SimCodeMain.mo", + "../Stubs/SimCodeUtil.mo", + "../Stubs/UnitAbsynBuilder.mo", + "../Stubs/UnitChecker.mo" + } + else { "../BackEnd/BackendDAEFunc.mo", "../BackEnd/BackendDAECreate.mo", "../BackEnd/BackendDAEEXT.mo", @@ -169,144 +261,86 @@ if true then /* Suppress output */ "../BackEnd/Uncertainties.mo", "../BackEnd/UnitCheck.mo", "../BackEnd/Unit.mo", - "../BackEnd/Vectorization.mo", + "../BackEnd/Vectorization.mo", "../BackEnd/XMLDump.mo", - "../Lexers/LexerModelicaDiff.mo", + "../FFrontEnd/FGraphDump.mo", + "../FFrontEnd/FGraphStream.mo", + "../FFrontEnd/FInst.mo", - // "SimCode"; - "../SimCode/HpcOmSimCode.mo", - "../SimCode/HpcOmSimCodeMain.mo", - "../SimCode/SerializeModelInfo.mo", - "../SimCode/SimCode.mo", - "../SimCode/SimCodeMain.mo", - "../SimCode/SimCodeUtil.mo", - "../SimCode/SimCodeVar.mo", + "../FrontEnd/CheckModel.mo", + "../FrontEnd/DumpGraphviz.mo", + "../FrontEnd/NFInstDump.mo", + "../FrontEnd/UnitAbsynBuilder.mo", + "../FrontEnd/UnitChecker.mo", + + "../Lexers/LexerModelicaDiff.mo", - // "Script"; - "../Script/CevalScript.mo", - "../Script/GlobalScript.mo", - "../Script/GlobalScriptDump.mo", - "../Script/GlobalScriptUtil.mo", - "../Script/StaticScript.mo", - "../Script/Interactive.mo", "../Script/Refactor.mo", "../Script/RewriteRules.mo", "../Script/Figaro.mo", "../Script/BlockCallRewrite.mo", "../Script/OpenModelicaScriptingAPI.mo", - // "Template"; - "../Template/AbsynDumpTpl.mo", + "../Script/CevalScriptBackend.mo", + "../SimCode/HpcOmSimCodeMain.mo", + "../SimCode/SerializeModelInfo.mo", + "../SimCode/SimCodeMain.mo", + "../SimCode/SimCodeUtil.mo", + "../Template/CodegenAdevs.mo", "../Template/CodegenC.mo", "../Template/CodegenCpp.mo", "../Template/CodegenCppHpcom.mo", - "../Template/CodegenFMU.mo", - "../Template/CodegenFMU1.mo", - "../Template/CodegenFMU2.mo", - "../Template/CodegenFMUCommon.mo", - "../Template/CodegenFMUCpp.mo", "../Template/CodegenCppInit.mo", "../Template/CodegenCSharp.mo", + "../Template/CodegenFMU.mo", + "../Template/CodegenFMU1.mo", + "../Template/CodegenFMU2.mo", + "../Template/CodegenFMUCommon.mo", + "../Template/CodegenFMUCpp.mo", "../Template/CodegenJava.mo", "../Template/CodegenJS.mo", "../Template/CodegenModelica.mo", - "../Template/CodegenQSS.mo", "../Template/CodegenSparseFMI.mo", - "../Template/CodegenUtil.mo", + "../Template/CodegenQSS.mo", "../Template/CodegenXML.mo", - "../Template/DAEDumpTpl.mo", - "../Template/ExpressionDumpTpl.mo", - "../Template/GenerateAPIFunctionsTpl.mo", "../Template/GraphvizDump.mo", "../Template/GraphMLDumpTpl.mo", "../Template/NFInstDumpTpl.mo", - "../Template/SCodeDumpTpl.mo", "../Template/SimCodeDump.mo", "../Template/TaskSystemDump.mo", - "../Template/TplAbsyn.mo", - "../Template/TplCodegen.mo", - "../Template/TplMain.mo", - "../Template/Tpl.mo", - "../Template/TplParser.mo", - "../Template/Unparsing.mo", - "../Template/VisualXMLTpl.mo", - - // "Global"; - "../Global/Global.mo", + "../Template/VisualXMLTpl.mo", - // "Main"; - "../Main/Main.mo", - - // "Util"; - "../Util/Array.mo", - // "../Util/AvlTree.mo", - "../Util/AvlTreeString.mo", - "../Util/BaseHashTable.mo", - "../Util/BaseHashSet.mo", - "../Util/ClockIndexes.mo", - "../Util/Config.mo", - "../Util/Corba.mo", - // "../Util/Database.mo", - "../Util/Debug.mo", "../Util/DiffAlgorithm.mo", - "../Util/DynLoad.mo", - "../Util/ErrorExt.mo", - "../Util/Error.mo", - "../Util/Flags.mo", "../Util/FMI.mo", "../Util/FMIExt.mo", - "../Util/GC.mo", - "../Util/Graph.mo", "../Util/GraphML.mo", - "../Util/GraphStream.mo", - "../Util/GraphStreamExt.mo", - "../Util/HashSet.mo", - "../Util/HashSetString.mo", - "../Util/HashTable2.mo", - "../Util/HashTable3.mo", "../Util/HashTable4.mo", - "../Util/HashTable5.mo", - "../Util/HashTableCG.mo", - "../Util/HashTableCrILst.mo", - "../Util/HashTableCrIListArray.mo", "../Util/HashTableCrToExp.mo", - "../Util/HashTableCrToCrEqLst.mo", "../Util/HashTableExpToExp.mo", "../Util/HashTableCrIntToExp.mo", "../Util/HashTableExpToIndexExp.mo", "../Util/HashTableCrToExpSourceTpl.mo", - "../Util/HashTable.mo", - "../Util/HashTableExpToIndex.mo", - //"../Util/HashTablePathToFunction.mo", - "../Util/HashTableStringToPath.mo", - "../Util/HashTableStringToProgram.mo", - "../Util/HashTableStringToUnit.mo", + "../Util/HashTableCrToCrEqLst.mo", "../Util/HashTableCrToUnit.mo", + "../Util/HashTableStringToUnit.mo", "../Util/HashTableUnitToString.mo", - "../Util/IOStreamExt.mo", - "../Util/IOStream.mo", - "../Util/Lapack.mo", - "../Util/List.mo", - "../Util/ModelicaExternalC.mo", - "../Util/Print.mo", - "../Util/PriorityQueue.mo", - "../Util/Settings.mo", - "../Util/StringUtil.mo", "../Util/SimulationResults.mo", "../Util/TaskGraphResults.mo", - "../Util/Socket.mo", - "../Util/System.mo", - "../Util/Util.mo", - "../Util/VarTransform.mo", - "../Util/VisualXML.mo", - "../Util/Serializer.mo" + "../Util/VisualXML.mo" + }; + files := cat(1, alwaysfiles, backendfiles); LoadCompilerSourcesRes:= OpenModelica.Scripting.loadFiles(files,numThreads=min(5,OpenModelica.Scripting.numProcessors())); if not LoadCompilerSourcesRes then print("Failed to load compiler sources:\n"); print(getErrorString()); + for f in files loop + if not OpenModelica.Scripting.regularFileExists(f) then + print("File does not exist: " + f + "\n"); + end if; + end for; exit(1); end if; end if; diff --git a/Compiler/boot/MakeDepends.mos b/Compiler/boot/MakeDepends.mos index d4a63cbc62a..1786bc31c6f 100644 --- a/Compiler/boot/MakeDepends.mos +++ b/Compiler/boot/MakeDepends.mos @@ -5,263 +5,3 @@ if not generateSeparateCodeDependenciesMakefile("Makefile.depends",directory="$( exit(1); end if; exit(0); -/* -frontEndFiles := { - "Absyn", - "Algorithm", - "Builtin", - "CevalFunction", - "Ceval", - "CheckModel", - "ClassInf", - "ClassLoader", - "ComponentReference", - "ConnectionGraph", - "Connect", - "ConnectUtil", - "Constants", - "DAEDump", - "DAE", - "DAEUtil", - "DumpGraphviz", - "Dump", - "ExpressionDump", - "Expression", - "ExpressionSimplify", - "ExpressionSimplifyTypes", - "Graphviz", - "Inline", - "InnerOuter", - "Inst", - "InstVar", - "InstDAE", - "InstFunction", - "InstBinding", - "InstUtil", - "InstExtends", - "InstSection", - "InstTypes", - "Lookup", - "MetaUtil", - "MMath", - "Mod", - "OperatorOverloading", - "Parser", - "ParserExt", - "Patternm", - "Prefix", - "PrefixUtil", - "SCode", - "SCodeDump", - "SCodeUtil", - "Static", - "SCodeSimplify", - "NFBuiltin", - "NFConnect2", - "NFConnectCheck", - "NFConnectEquations", - "NFConnectUtil2", - "NFConnectionSets", - "NFEnv", - "NFEnvAvlTree", - "NFEnvExtends", - "NFExpandableConnectors", - "NFInst", - "NFInstDump", - "NFInstFlatten", - "NFInstPrefix", - "NFInstSymbolTable", - "NFInstTypes", - "NFInstTypesOld", - "NFInstUtil", - "NFLookup", - "NFMod", - "NFRedeclare", - "NFSCodeDependency", - "NFSCodeEnv", - "NFSCodeExpand", - "NFSCodeFlattenImports", - "NFSCodeFlatten", - "NFSCodeFlattenRedeclare", - "NFSCodeLookup", - "NFSCodeMod", - "NFSCodeCheck", - "NFTypeCheck", - "NFTyping", - "Types", - "UnitAbsynBuilder", - "UnitAbsyn", - "UnitChecker", - "UnitParserExt", - "Values", - "ValuesUtil", - "FBuiltin", - "FCore", - "FExpand", - "FGraph", - "FGraphBuild", - "FGraphBuildEnv", - "FGraphDump", - "FGraphStream", - "FInst", - "FLookup", - "FMod", - "FNode", - "FResolve", - "FTraverse", - "FVisit" -}; -backEndFiles := { - "SerializeModelInfo", // TODO: Add once we bootstrapped omc - "BackendDAE", - "BackendDAEFunc", - "BackendDAECreate", - "BackendDAEEXT", - "BackendDAEOptimize", - "BackendDAETransform", - "BackendDAEUtil", - "BackendDump", - "BackendEquation", - "BackendQSS", - "BackendVariable", - "BackendVarTransform", - "BinaryTree", - "BinaryTreeInt", - "Causalize", - "DAEQuery", - "Differentiate", - "DumpHTML", - "DynamicOptimization", - "EvaluateFunctions", - "EvaluateParameter", - "ExpressionSolve", - "FindZeroCrossings", - "HpcOmBenchmark", - "HpcOmBenchmarkExt", - "HpcOmEqSystems", - "HpcOmMemory", - "HpcOmScheduler", - "HpcOmSchedulerExt", - "HpcOmTaskGraph", - "IndexReduction", - "InlineArrayEquations", - "Initialization", - "Matching", - "MathematicaDump", - "OnRelaxation", - "OpenTURNS", - "RemoveSimpleEquations", - "ResolveLoops", - "SynchronousFeatures", - "Tearing", - "Uncertainties", - "UnitCheck", - "XMLDump", - "HpcOmSimCode", - "HpcOmSimCodeMain", - "SimCode", - "SimCodeMain", - "SimCodeUtil", - "SimCodeVar", - "AbsynDumpTpl", - "CodegenAdevs", - "CodegenC", - "CodegenCpp", - "CodegenCppHpcom", - "CodegenFMU", - "CodegenFMUCpp", - "CodegenCSharp", - "CodegenJava", - "CodegenJS", - "CodegenModelica", - "CodegenQSS", - "CodegenSparseFMI", - "CodegenUtil", - "CodegenXML", - "DAEDumpTpl", - "ExpressionDumpTpl", - "GraphvizDump", - "GraphMLDumpTpl", - "NFInstDumpTpl", - "SCodeDumpTpl", - "SimCodeDump", - "TaskSystemDump", - "TplAbsyn", - "TplCodegen", - "TplMain", - "Tpl", - "TplParser", - "Unparsing" -}; -utilFiles := { - "File", - "CevalScript", - "GlobalScript", - "StaticScript", - "Interactive", - "Refactor", - "RewriteRules", - "Figaro", - "BlockCallRewrite", - "Global", - "Main", - "AvlTreeString", - "BaseHashTable", - "BaseHashSet", - "Config", - "Corba", - "Debug", - "DynLoad", - "ErrorExt", - "Error", - "Flags", - "FMI", - "FMIExt", - "Graph", - "GraphML", - "GraphStream", - "GraphStreamExt", - "HashSet", - "HashSetString", - "HashTable2", - "HashTable3", - "HashTable4", - "HashTable5", - "HashTableCG", - "HashTableCrILst", - "HashTableCrIListArray", - "HashTableExpToExp", - "HashTableCrIntToExp", - "HashTableCrToExpSourceTpl", - "HashTable", - "HashTableExpToIndex", - "HashTablePathToFunction", - "HashTableStringToPath", - "IOStreamExt", - "IOStream", - "Lapack", - "List", - "ModelicaExternalC", - "Print", - "PriorityQueue", - "Settings", - "SimulationResults", - "TaskGraphResults", - "Socket", - "System", - "Util", - "VarTransform" -}; -packages := {typeNameString(cl) for cl in getClassNames(sort=true)}; -strs := sortStrings(cat(1, frontEndFiles, backEndFiles, utilFiles)); -if size(packages,1) <> size(strs,1) then - print("Could not determine if front-end packages call allowed packages since the number of packages differ"); - exit(1); -end if; -if not min(p==s threaded for p in packages, s in strs) then - print("Could not determine if front-end packages call allowed packages since the names of packages differ"); - exit (1); -end if; -getErrorString(); -checkFrontEndBackEndInterface(frontEndFiles=frontEndFiles,backendFiles=backendFiles,utilFiles=utilFiles); -*/ diff --git a/Compiler/boot/MakeSources.mos b/Compiler/boot/MakeSources.mos index 2ea69395b9c..f6ad4f20e93 100644 --- a/Compiler/boot/MakeSources.mos +++ b/Compiler/boot/MakeSources.mos @@ -15,7 +15,7 @@ ifeq ($(wildcard $(GEN_DIR)"+typeNameString(cl)+".deps),$(GEN_DIR)"+typeNameStri include $(GEN_DIR)"+typeNameString(cl)+".deps endif" for cl in getClassNames()) */ -); +);getErrorString(); loadString("within Absyn; /* So it is not listed by getClassNames() */ function delimit diff --git a/Compiler/boot/Makefile.common b/Compiler/boot/Makefile.common index 7d7100885dd..2699a738f20 100644 --- a/Compiler/boot/Makefile.common +++ b/Compiler/boot/Makefile.common @@ -42,12 +42,16 @@ bootstrap-from-tarball: $(PATCHES) # Patch _main.c to avoid a new tarball $(PATCH_SOURCES) cd build && for x in ../patches/*.patch; do patch -i "$$x" "`basename $$x | $(SED) 's/\([.][0-9]*\)\?[.]patch/.c/'`" || exit 1; done + # We have not compiled OpenModelicaScriptingAPI.mo yet + touch build/OpenModelicaScriptingAPI.h $(MAKE) -f $(defaultMakefileTarget) install INCLUDESOURCES=1 OMC=.omc @echo "Bootstrapping phase 1/3 completed" $(MAKE) -f $(defaultMakefileTarget) clean OMC=$(BOOTSTRAP_OMC) - $(MAKE) -f $(defaultMakefileTarget) generate-files-in-steps OMC=$(BOOTSTRAP_OMC) + OPENMODELICA_BACKEND_STUBS=1 $(MAKE) -f $(defaultMakefileTarget) generate-files-in-steps OMC=$(BOOTSTRAP_OMC) # Patch _main.c to avoid a new tarball $(PATCH_SOURCES) + # We have not compiled OpenModelicaScriptingAPI.mo yet + touch build/OpenModelicaScriptingAPI.h $(MAKE) -f $(defaultMakefileTarget) install INCLUDESOURCES=1 OMC=$(BOOTSTRAP_OMC) @echo "Bootstrapping phase 2/3 completed" $(MAKE) -f $(defaultMakefileTarget) clean OMC=$(BOOTSTRAP_OMC) @@ -58,12 +62,14 @@ bootstrap-from-tarball: $(PATCHES) bootstrap-from-compiled: make-separate -make-bootstrap-tarball: - rm -rf $(GEN_DIR) - $(MAKE) -f $(defaultMakefileTarget) generate-files-in-steps +make-bootstrap-tarball: clean + test ! -f Makefile.sources || rm Makefile.sources + test ! -f Makefile.depends || rm Makefile.depends + OPENMODELICA_BACKEND_STUBS=1 $(MAKE) -f $(defaultMakefileTarget) generate-files-in-steps rm -rf $(GEN_DIR)/*.mo $(GEN_DIR)/tmp $(GEN_DIR)/*.deps $(GEN_DIR)/*.mos $(GEN_DIR)/*.stamp - sed -i -e "s/^ *//" -e "/^[/][/]/d" -e "/^#line /d" -e "/^$$/d" -e "/^ *[/][*].*[*][/] *$$/d" $(GEN_DIR)/*.c $(GEN_DIR)/*.h - tar cJf bootstrap-sources.tar.xz $(GEN_DIR) Makefile.sources + sed -i -e "s/^ *//" -e "/^[/][/]/d" -e "/^#line /d" -e "s/ *[/][*].*[*][/]\([;)]\?\) *$$/\1/" -e "s/^ *[/][*].*[*][/]\(;\?\) */\1/" -e "/^ *$$/d" $(GEN_DIR)/*.c $(GEN_DIR)/*.h + tar cf bootstrap-sources.tar $(GEN_DIR) Makefile.sources + xz --best --force bootstrap-sources.tar templates: $(MAKE) -f $(defaultMakefileTarget) --no-print-directory -C $(TOP_DIR)/Compiler/Template diff --git a/Compiler/boot/find-unused-import.sh b/Compiler/boot/find-unused-import.sh new file mode 100755 index 00000000000..ed53f979199 --- /dev/null +++ b/Compiler/boot/find-unused-import.sh @@ -0,0 +1,24 @@ +#!/bin/bash + +for f in ../*/*.mo; do + case $f in + *Template*) + SKIP=1 + ;; + *susan_codegen*) + SKIP=1 + ;; + *) + SKIP= + ;; + esac + if test ! -z "$SKIP"; then + continue + fi + for i in `grep -o "import \+[A-Za-z0-9_]\+ *;" "$f" | cut -d" " -f2 | cut -d";" -f1`; do + if ! grep -q "$i[.]" "$f"; then + echo "Unused import $i in $f" + sed -i "/^[a-z]* *import \+$i *;/d" "$f" + fi + done +done diff --git a/SimulationRuntime/cpp/Core/SimController/CMakeLists.txt b/SimulationRuntime/cpp/Core/SimController/CMakeLists.txt index 0c740cd8298..a5af75d0d6a 100644 --- a/SimulationRuntime/cpp/Core/SimController/CMakeLists.txt +++ b/SimulationRuntime/cpp/Core/SimController/CMakeLists.txt @@ -8,8 +8,8 @@ set_target_properties(${SimControllerName}_static PROPERTIES COMPILE_DEFINITIONS install (TARGETS ${SimControllerName}_static DESTINATION ${LIBINSTALLEXT}) add_library(${SimControllerName} SHARED Configuration.cpp FactoryExport.cpp Initialization.cpp SimController.cpp SimManager.cpp) -target_link_libraries( ${SimControllerName} ${OMCFactoryName}_static ${ExtensionUtilitiesName} ${ModelicaUtilitiesName} ${Boost_LIBRARIES} ${CMAKE_DL_LIBS} ) -add_precompiled_header(${SimControllerName} Include/Core/Modelica.h ) +target_link_libraries( ${SimControllerName} ${OMCFactoryName}_static ${ExtensionUtilitiesName} ${ModelicaUtilitiesName} ${Boost_LIBRARIES} ${CMAKE_DL_LIBS}) +add_precompiled_header(${SimControllerName} Include/Core/Modelica.h) install (TARGETS ${SimControllerName} DESTINATION ${LIBINSTALLEXT}) if (UNIX) @@ -25,4 +25,4 @@ install (FILES ${CMAKE_SOURCE_DIR}/Include/Core/SimController/ISimData.h ${CMAKE_SOURCE_DIR}/Include/Core/SimController/SimManager.h ${CMAKE_SOURCE_DIR}/Include/Core/SimController/Configuration.h ${CMAKE_SOURCE_DIR}/Include/Core/SimController/Initialization.h -DESTINATION include/omc/cpp/Core/SimController) +DESTINATION include/omc/cpp/Core/SimController) \ No newline at end of file diff --git a/SimulationRuntime/cpp/Core/SimController/SimController.cpp b/SimulationRuntime/cpp/Core/SimController/SimController.cpp index b302c9176c1..24e0132dc07 100644 --- a/SimulationRuntime/cpp/Core/SimController/SimController.cpp +++ b/SimulationRuntime/cpp/Core/SimController/SimController.cpp @@ -277,7 +277,7 @@ void SimController::Start(SimSettings simsettings, string modelKey) boost::shared_ptr writeoutput_system = boost::dynamic_pointer_cast(mixedsystem); - if((global_settings->getOutputFormat()==BUFFER) && writeoutput_system) + if((global_settings->getOutputFormat()==OF_BUFFER) && writeoutput_system) { boost::shared_ptr simData = getSimData(modelKey).lock(); //get history object to query simulation results diff --git a/SimulationRuntime/cpp/Core/SimController/SimManager.cpp b/SimulationRuntime/cpp/Core/SimController/SimManager.cpp index 0a623c2d39f..7d8b16e3f1f 100644 --- a/SimulationRuntime/cpp/Core/SimController/SimManager.cpp +++ b/SimulationRuntime/cpp/Core/SimController/SimManager.cpp @@ -104,7 +104,7 @@ void SimManager::initialize() return; } - Logger::write("SimManager start init",INIT,DEBUG); + Logger::write("SimManager start init",LC_INIT,LL_DEBUG); // Flag für Endlossimulaton (wird gesetzt wenn Solver zurückkommt) _continueSimulation = true; @@ -121,7 +121,6 @@ void SimManager::initialize() //ex << error_id(SIMMANAGER); throw; } - _totStps = 0; _accStps = 0; _rejStps = 0; @@ -157,7 +156,7 @@ void SimManager::initialize() memset(_events, false, _dimZeroFunc * sizeof(bool)); } - Logger::write("SimManager assemble completed",INIT,DEBUG); + Logger::write("SimManager assemble completed",LC_INIT,LL_DEBUG); //#if defined(__TRICORE__) || defined(__vxworks) // Initialization for RT simulation if (_config->getGlobalSettings()->useEndlessSim()) @@ -259,24 +258,24 @@ void SimManager::runSimulation() #endif try { - Logger::write("SimManager: start simulation at t = " + boost::lexical_cast(_tStart),SOLV,INFO); + Logger::write("SimManager: start simulation at t = " + boost::lexical_cast(_tStart),LC_SOLV,LL_INFO); runSingleProcess(); // Zeit messen, Ausgabe der SimInfos ISolver::SOLVERSTATUS status = _solver->getSolverStatus(); if ((status & ISolver::DONE) || (status & ISolver::USER_STOP)) { - Logger::write("SimManager: simulation done at t = " + boost::lexical_cast(_tEnd),SOLV,INFO); - Logger::write("SimManager: number of steps = " + boost::lexical_cast(_totStps),SOLV,INFO); + Logger::write("SimManager: simulation done at t = " + boost::lexical_cast(_tEnd),LC_SOLV,LL_INFO); + Logger::write("SimManager: number of steps = " + boost::lexical_cast(_totStps),LC_SOLV,LL_INFO); writeProperties(); } } catch (std::exception & ex) { - Logger::write("SimManager: simulation finish with errors at t = " + boost::lexical_cast(_tEnd),SOLV,ERROR); - Logger::write("SimManager: number of steps = " + boost::lexical_cast(_totStps),SOLV,INFO); + Logger::write("SimManager: simulation finish with errors at t = " + boost::lexical_cast(_tEnd),LC_SOLV,LL_ERROR); + Logger::write("SimManager: number of steps = " + boost::lexical_cast(_totStps),LC_SOLV,LL_INFO); writeProperties(); - Logger::write("SimManager: error = " + boost::lexical_cast(ex.what()),SOLV,ERROR); + Logger::write("SimManager: error = " + boost::lexical_cast(ex.what()),LC_SOLV,LL_ERROR); //ex << error_id(SIMMANAGER); throw; } @@ -296,7 +295,7 @@ void SimManager::stopSimulation() void SimManager::writeProperties() { // decl for Logging - std::pair logM = Logger::getLogMode(SOLV, INFO); + std::pair logM = Logger::getLogMode(LC_SOLV, LL_INFO); Logger::write(boost::lexical_cast("computationTime"),logM); Logger::write(boost::lexical_cast("Geforderte Simulationszeit: ") + boost::lexical_cast(_tEnd),logM); @@ -548,7 +547,7 @@ void SimManager::runSingleProcess() _solverTask = ISolver::SOLVERCALL(_solverTask ^ ISolver::RECORDCALL); /* Logs temporarily disabled BOOST_LOG_SEV(simmgr_lg::get(), simmgr_normal) <<"Run single process." ; */ - Logger::write("SimManager: run single process",SOLV,DEBUG); + Logger::write("SimManager: run single process",LC_SOLV,LL_DEBUG); // Zeitinvervall speichern //_H =_tEnd - _tStart; diff --git a/SimulationRuntime/cpp/Core/SimulationSettings/GlobalSettings.cpp b/SimulationRuntime/cpp/Core/SimulationSettings/GlobalSettings.cpp index e41e5d4b2f7..5bb325f0010 100644 --- a/SimulationRuntime/cpp/Core/SimulationSettings/GlobalSettings.cpp +++ b/SimulationRuntime/cpp/Core/SimulationSettings/GlobalSettings.cpp @@ -19,8 +19,8 @@ GlobalSettings::GlobalSettings() , _selected_nonlin_solver("Newton") , _resultsfile_name("results.csv") , _endless_sim(false) - , _outputFormat(EMPTY) - , _outputPointType(ALL) + , _outputFormat(OF_EMPTY) + , _outputPointType(OPT_ALL) , _alarm_time(0) { } diff --git a/SimulationRuntime/cpp/Core/Solver/SolverDefaultImplementation.cpp b/SimulationRuntime/cpp/Core/Solver/SolverDefaultImplementation.cpp index 2c8a4f69776..695803281a2 100644 --- a/SimulationRuntime/cpp/Core/Solver/SolverDefaultImplementation.cpp +++ b/SimulationRuntime/cpp/Core/Solver/SolverDefaultImplementation.cpp @@ -111,7 +111,7 @@ void SolverDefaultImplementation::initialize() timeevent_system->setTime(_tCurrent); - if(_settings->getGlobalSettings()->getOutputPointType() != EMPTY2 && _settings->getGlobalSettings()->getOutputFormat() != EMPTY) + if(_settings->getGlobalSettings()->getOutputPointType() != OPT_EMPTY && _settings->getGlobalSettings()->getOutputFormat() != OF_EMPTY) writeoutput_system->writeOutput(IWriteOutput::HEAD_LINE); // Allocate array with values of zero functions @@ -192,7 +192,7 @@ void SolverDefaultImplementation::writeToFile(const int& stp, const double& t, c } #endif - if(_settings->getGlobalSettings()->getOutputFormat()!= EMPTY) + if(_settings->getGlobalSettings()->getOutputFormat()!= OF_EMPTY) { IWriteOutput* writeoutput_system = dynamic_cast(_system); @@ -222,4 +222,4 @@ void SolverDefaultImplementation::updateEventState() setZeroState(); // Upate status of events vector } } - /** @} */ // end of coreSolver \ No newline at end of file + /** @} */ // end of coreSolver diff --git a/SimulationRuntime/cpp/Core/Utils/extension/logger.cpp b/SimulationRuntime/cpp/Core/Utils/extension/logger.cpp index d2688e28dbf..caebef7b9f3 100644 --- a/SimulationRuntime/cpp/Core/Utils/extension/logger.cpp +++ b/SimulationRuntime/cpp/Core/Utils/extension/logger.cpp @@ -6,9 +6,10 @@ */ #include #include +#include #include -Logger* Logger::instance = 0; +Logger* Logger::instance = NULL; Logger::Logger(LogSettings settings, bool enabled) : _settings(settings), _isEnabled(enabled) { @@ -55,13 +56,13 @@ std::string Logger::getPrefix(LogCategory cat, LogLevel lvl) const { switch(lvl) { - case(DEBUG): + case(LL_DEBUG): return "DEBUG: "; - case(ERROR): + case(LL_ERROR): return "ERROR: "; - case(INFO): + case(LL_INFO): return "INFO: "; - case(WARNING): + case(LL_WARNING): return "WARNING: "; default: return ""; diff --git a/SimulationRuntime/cpp/FMU/CMakeLists.txt b/SimulationRuntime/cpp/FMU/CMakeLists.txt index 9e451fdbc52..d4d1de5c34e 100644 --- a/SimulationRuntime/cpp/FMU/CMakeLists.txt +++ b/SimulationRuntime/cpp/FMU/CMakeLists.txt @@ -31,6 +31,7 @@ install (FILES ${CMAKE_SOURCE_DIR}/Include/FMU/fmiModelFunctions.h ${CMAKE_SOURCE_DIR}/Include/FMU/FMUWrapper.h ${CMAKE_SOURCE_DIR}/Include/FMU/FMULibInterface.h ${CMAKE_SOURCE_DIR}/Include/FMU/IFMUInterface.h + ${CMAKE_SOURCE_DIR}/Include/FMU/FactoryExport.h DESTINATION include/omc/cpp/FMU) diff --git a/SimulationRuntime/cpp/FMU/FMULogger.cpp b/SimulationRuntime/cpp/FMU/FMULogger.cpp index 3bd3007f3d1..78b3295909e 100644 --- a/SimulationRuntime/cpp/FMU/FMULogger.cpp +++ b/SimulationRuntime/cpp/FMU/FMULogger.cpp @@ -25,14 +25,14 @@ void FMULogger::writeInternal(std::string errorMsg, LogCategory cat, LogLevel lv { switch(lvl) { - case(ERROR): + case(LL_ERROR): callbackLogger(component, instanceName, fmiError, "?", errorMsg.c_str()); break; - case(WARNING): + case(LL_WARNING): callbackLogger(component, instanceName, fmiWarning, "?", errorMsg.c_str()); break; - case(INFO): - case(DEBUG): + case(LL_INFO): + case(LL_DEBUG): callbackLogger(component, instanceName, fmiOK, "?", errorMsg.c_str()); break; default: diff --git a/SimulationRuntime/cpp/Include/Core/SimController/FactoryExport.h b/SimulationRuntime/cpp/Include/Core/SimController/FactoryExport.h new file mode 100644 index 00000000000..c2100b096ec --- /dev/null +++ b/SimulationRuntime/cpp/Include/Core/SimController/FactoryExport.h @@ -0,0 +1,15 @@ +#pragma once +/** @addtogroup coreSystem + * + * @{ + */ + +#if defined(__vxworks) || defined(__TRICORE__) || defined(RUNTIME_STATIC_LINKING) + #define BOOST_EXTENSION_LOGGER_DECL +#elif defined(OMC_BUILD) || defined(SIMSTER_BUILD) + #define BOOST_EXTENSION_LOGGER_DECL BOOST_EXTENSION_IMPORT_DECL +#else + error "operating system not supported" +#endif + +/** @} */ // end of coreSystem \ No newline at end of file diff --git a/SimulationRuntime/cpp/Include/Core/SimController/ISimController.h b/SimulationRuntime/cpp/Include/Core/SimController/ISimController.h index 92e2a2c53e0..853f7975a4c 100644 --- a/SimulationRuntime/cpp/Include/Core/SimController/ISimController.h +++ b/SimulationRuntime/cpp/Include/Core/SimController/ISimController.h @@ -3,20 +3,13 @@ * * @{ */ -/*includes removed for static linking not needed any more -#ifdef RUNTIME_STATIC_LINKING -#include -#include -#include -#include -#include -#include #include using std::string; #endif */ + struct SimSettings { string solver_name; diff --git a/SimulationRuntime/cpp/Include/Core/SimController/SimController.h b/SimulationRuntime/cpp/Include/Core/SimController/SimController.h index 4b23680a2d9..9246c11ebf0 100644 --- a/SimulationRuntime/cpp/Include/Core/SimController/SimController.h +++ b/SimulationRuntime/cpp/Include/Core/SimController/SimController.h @@ -3,15 +3,9 @@ * * @{ */ -#include "SimManager.h" -#include +#include #include -/*includes removed for static linking not needed any more -#ifdef RUNTIME_STATIC_LINKING -#include -#include -#endif -*/ + class SimController : public ISimController, public SimControllerPolicy { diff --git a/SimulationRuntime/cpp/Include/Core/SimController/SimManager.h b/SimulationRuntime/cpp/Include/Core/SimController/SimManager.h index 479ddb2bb9b..38b29028ff1 100644 --- a/SimulationRuntime/cpp/Include/Core/SimController/SimManager.h +++ b/SimulationRuntime/cpp/Include/Core/SimController/SimManager.h @@ -3,8 +3,9 @@ * * @{ */ -#include "Configuration.h" -#include "Initialization.h" +#include +#include +#include #include #ifdef RUNTIME_PROFILING diff --git a/SimulationRuntime/cpp/Include/Core/SimulationSettings/IGlobalSettings.h b/SimulationRuntime/cpp/Include/Core/SimulationSettings/IGlobalSettings.h index 37dcf2f34b8..815a2abf065 100644 --- a/SimulationRuntime/cpp/Include/Core/SimulationSettings/IGlobalSettings.h +++ b/SimulationRuntime/cpp/Include/Core/SimulationSettings/IGlobalSettings.h @@ -25,18 +25,18 @@ using std::string; #include -enum OutputFormat {CSV, MAT, BUFFER, EMPTY}; +enum OutputFormat {OF_CSV, OF_MAT, OF_BUFFER, OF_EMPTY}; -enum LogCategory {INIT = 0, NLS = 1, LS = 2, SOLV = 3, OUT = 4, EVT = 5, OTHER = 6, MOD = 7}; -enum LogLevel {ERROR = 0, WARNING = 1, INFO = 2, DEBUG = 3}; +enum LogCategory {LC_INIT = 0, LC_NLS = 1, LC_LS = 2, LC_SOLV = 3, LC_OUT = 4, LC_EVT = 5, LC_OTHER = 6, LC_MOD = 7}; +enum LogLevel {LL_ERROR = 0, LL_WARNING = 1, LL_INFO = 2, LL_DEBUG = 3}; struct LogSettings { std::vector modes; LogSettings() { - modes = std::vector(8,ERROR); + modes = std::vector(8,LL_ERROR); } void setAll(LogLevel l) @@ -46,7 +46,7 @@ struct LogSettings } }; -enum OutputPointType {ALL, STEP, EMPTY2}; +enum OutputPointType {OPT_ALL, OPT_STEP, OPT_EMPTY}; class IGlobalSettings { public: diff --git a/SimulationRuntime/cpp/Include/Core/System/FactoryExport.h b/SimulationRuntime/cpp/Include/Core/System/FactoryExport.h index c1c4bbe96c7..fd189466918 100644 --- a/SimulationRuntime/cpp/Include/Core/System/FactoryExport.h +++ b/SimulationRuntime/cpp/Include/Core/System/FactoryExport.h @@ -5,11 +5,13 @@ */ #if defined(__vxworks) || defined(__TRICORE__) || defined(RUNTIME_STATIC_LINKING) + #define BOOST_EXTENSION_LOGGER_DECL #define BOOST_EXTENSION_SYSTEM_DECL #define BOOST_EXTENSION_EVENTHANDLING_DECL #define BOOST_EXTENSION_ALGLOOPDEFAULTIMPL_DECL #define BOOST_EXTENSION_SIMVARS_DECL #elif defined(OMC_BUILD) || defined(SIMSTER_BUILD) + #define BOOST_EXTENSION_LOGGER_DECL BOOST_EXTENSION_IMPORT_DECL #define BOOST_EXTENSION_SYSTEM_DECL BOOST_EXTENSION_EXPORT_DECL #define BOOST_EXTENSION_EVENTHANDLING_DECL BOOST_EXTENSION_EXPORT_DECL #define BOOST_EXTENSION_ALGLOOPDEFAULTIMPL_DECL BOOST_EXTENSION_EXPORT_DECL diff --git a/SimulationRuntime/cpp/Include/Core/Utils/extension/FactoryExport.h b/SimulationRuntime/cpp/Include/Core/Utils/extension/FactoryExport.h new file mode 100644 index 00000000000..e1c0e7bd296 --- /dev/null +++ b/SimulationRuntime/cpp/Include/Core/Utils/extension/FactoryExport.h @@ -0,0 +1,15 @@ +#pragma once +/** @addtogroup coreSystem + * + * @{ + */ + +#if defined(__vxworks) || defined(__TRICORE__) || defined(RUNTIME_STATIC_LINKING) + #define BOOST_EXTENSION_LOGGER_DECL +#elif defined(OMC_BUILD) || defined(SIMSTER_BUILD) + #define BOOST_EXTENSION_LOGGER_DECL BOOST_EXTENSION_EXPORT_DECL +#else + error "operating system not supported" +#endif + +/** @} */ // end of coreSystem diff --git a/SimulationRuntime/cpp/Include/Core/Utils/extension/logger.hpp b/SimulationRuntime/cpp/Include/Core/Utils/extension/logger.hpp index c3a3872c287..c0121682863 100644 --- a/SimulationRuntime/cpp/Include/Core/Utils/extension/logger.hpp +++ b/SimulationRuntime/cpp/Include/Core/Utils/extension/logger.hpp @@ -10,7 +10,7 @@ #include -class BOOST_EXTENSION_EXPORT_DECL Logger +class BOOST_EXTENSION_LOGGER_DECL Logger { public: virtual ~Logger(); @@ -31,6 +31,11 @@ class BOOST_EXTENSION_EXPORT_DECL Logger instance = new Logger(settings, true); } + static void initialize() + { + initialize(LogSettings()); + } + static void write(std::string msg, LogCategory cat, LogLevel lvl) { getInstance()->writeInternal(msg, cat, lvl); @@ -79,6 +84,4 @@ class BOOST_EXTENSION_EXPORT_DECL Logger bool _isEnabled; }; - - #endif /* LOGGER_HPP_ */ diff --git a/SimulationRuntime/cpp/Include/FMU/FMUGlobalSettings.h b/SimulationRuntime/cpp/Include/FMU/FMUGlobalSettings.h index 10b80be113b..fbce7a666fd 100644 --- a/SimulationRuntime/cpp/Include/FMU/FMUGlobalSettings.h +++ b/SimulationRuntime/cpp/Include/FMU/FMUGlobalSettings.h @@ -27,10 +27,10 @@ class FMUGlobalSettings : public IGlobalSettings virtual bool getInfoOutput() { return false; } virtual void setInfoOutput(bool) {} virtual string getOutputPath() { return "./"; } - virtual OutputFormat getOutputFormat(){return EMPTY;} + virtual OutputFormat getOutputFormat(){return OF_EMPTY;} virtual LogSettings getLogSettings() {return LogSettings();} virtual void setLogSettings(LogSettings) {} - virtual OutputPointType getOutputPointType() { return ALL; }; + virtual OutputPointType getOutputPointType() { return OPT_ALL; }; virtual void setOutputPointType(OutputPointType) {}; virtual void setOutputFormat(OutputFormat) {} virtual void setOutputPath(string) {} diff --git a/SimulationRuntime/cpp/Include/FMU/FMULogger.h b/SimulationRuntime/cpp/Include/FMU/FMULogger.h index ab3340ff3a0..fe54f5d3dff 100644 --- a/SimulationRuntime/cpp/Include/FMU/FMULogger.h +++ b/SimulationRuntime/cpp/Include/FMU/FMULogger.h @@ -9,6 +9,7 @@ #define FMULOGGER_H_ #include +#include #include #include "fmiModelFunctions.h" diff --git a/SimulationRuntime/cpp/Include/FMU/FMUWrapper.h b/SimulationRuntime/cpp/Include/FMU/FMUWrapper.h index 7860c7ec5d4..32fe30e9ecf 100644 --- a/SimulationRuntime/cpp/Include/FMU/FMUWrapper.h +++ b/SimulationRuntime/cpp/Include/FMU/FMUWrapper.h @@ -66,11 +66,11 @@ class FMUWrapper : public IFMUInterface virtual fmiStatus setContinuousStates (const fmiReal states[], size_t nx) { - Logger::write("setContinuousStates called",OTHER,INFO); + Logger::write("setContinuousStates called",LC_OTHER,LL_INFO); // to set states do the folowing std::stringstream message; message << "Setting continuous states"; - Logger::write(message.str(),OTHER,INFO); + Logger::write(message.str(),LC_OTHER,LL_INFO); _model->setContinuousStates(states); _need_update = true; return fmiOK; @@ -144,13 +144,13 @@ class FMUWrapper : public IFMUInterface eventInfo.terminateSimulation = fmiFalse; eventInfo.upcomingTimeEvent = fmiFalse; //eventInfo.nextTimeEvent no need to set this for this model - Logger::write("Initialization completed",OTHER,INFO); + Logger::write("Initialization completed",LC_OTHER,LL_INFO); return fmiOK; } virtual fmiStatus getDerivatives (fmiReal derivatives[] , size_t nx) { - Logger::write("Try to get derivatives",OTHER,INFO); + Logger::write("Try to get derivatives",LC_OTHER,LL_INFO); updateModel(); _model->getRHS(derivatives); return fmiOK; diff --git a/SimulationRuntime/cpp/Include/FMU/FactoryExport.h b/SimulationRuntime/cpp/Include/FMU/FactoryExport.h new file mode 100644 index 00000000000..0ff0072d013 --- /dev/null +++ b/SimulationRuntime/cpp/Include/FMU/FactoryExport.h @@ -0,0 +1,15 @@ +#pragma once +/** @addtogroup coreSystem + * + * @{ + */ + +#if defined(__vxworks) || defined(__TRICORE__) || defined(RUNTIME_STATIC_LINKING) + #define BOOST_EXTENSION_LOGGER_DECL +#elif defined(OMC_BUILD) || defined(SIMSTER_BUILD) + #define BOOST_EXTENSION_LOGGER_DECL +#else + error "operating system not supported" +#endif + +/** @} */ // end of coreSystem diff --git a/SimulationRuntime/cpp/Include/FMU2/FMU2GlobalSettings.h b/SimulationRuntime/cpp/Include/FMU2/FMU2GlobalSettings.h index a5bdf888e28..ef6d7f84d4e 100644 --- a/SimulationRuntime/cpp/Include/FMU2/FMU2GlobalSettings.h +++ b/SimulationRuntime/cpp/Include/FMU2/FMU2GlobalSettings.h @@ -63,10 +63,10 @@ class FMU2GlobalSettings : public IGlobalSettings virtual bool getInfoOutput() { return false; } virtual void setInfoOutput(bool) {} virtual string getOutputPath() { return "./"; } - virtual OutputFormat getOutputFormat() { return EMPTY; } + virtual OutputFormat getOutputFormat() { return OF_EMPTY; } virtual LogSettings getLogSettings() { return LogSettings(); } virtual void setLogSettings(LogSettings) {} - virtual OutputPointType getOutputPointType() { return ALL; }; + virtual OutputPointType getOutputPointType() { return OPT_ALL; }; virtual void setOutputPointType(OutputPointType) {}; virtual void setOutputFormat(OutputFormat) {} virtual void setOutputPath(string) {} diff --git a/SimulationRuntime/cpp/Include/Solver/CVode/FactoryExport.h b/SimulationRuntime/cpp/Include/Solver/CVode/FactoryExport.h index 5286e17aa8d..f2b082c960b 100644 --- a/SimulationRuntime/cpp/Include/Solver/CVode/FactoryExport.h +++ b/SimulationRuntime/cpp/Include/Solver/CVode/FactoryExport.h @@ -9,14 +9,14 @@ #define BOOST_EXTENSION_SOLVERSETTINGS_DECL #elif defined(RUNTIME_STATIC_LINKING) && (defined(OMC_BUILD) || defined(SIMSTER_BUILD)) - +#define BOOST_EXTENSION_LOGGER_DECL #define BOOST_EXTENSION_SOLVER_DECL #define BOOST_EXTENSION_STATESELECT_DECL #define BOOST_EXTENSION_SOLVERSETTINGS_DECL #define BOOST_EXTENSION_MONITOR_DECL #elif defined(OMC_BUILD) || defined(SIMSTER_BUILD) - +#define BOOST_EXTENSION_LOGGER_DECL BOOST_EXTENSION_IMPORT_DECL #define BOOST_EXTENSION_SOLVER_DECL BOOST_EXTENSION_IMPORT_DECL #define BOOST_EXTENSION_STATESELECT_DECL BOOST_EXTENSION_IMPORT_DECL #define BOOST_EXTENSION_SOLVERSETTINGS_DECL BOOST_EXTENSION_IMPORT_DECL @@ -25,5 +25,3 @@ error "operating system not supported" #endif /** @} */ // end of solverCvode - - diff --git a/SimulationRuntime/cpp/Include/Solver/IDA/FactoryExport.h b/SimulationRuntime/cpp/Include/Solver/IDA/FactoryExport.h index e942698bfe9..fc8273ec5d6 100644 --- a/SimulationRuntime/cpp/Include/Solver/IDA/FactoryExport.h +++ b/SimulationRuntime/cpp/Include/Solver/IDA/FactoryExport.h @@ -8,7 +8,9 @@ #define BOOST_EXTENSION_STATESELECT_DECL #define BOOST_EXTENSION_SOLVERSETTINGS_DECL #define BOOST_EXTENSION_MONITOR_DECL + #define BOOST_EXTENSION_LOGGER_DECL #elif defined(OMC_BUILD) || defined(SIMSTER_BUILD) + #define BOOST_EXTENSION_LOGGER_DECL BOOST_EXTENSION_IMPORT_DECL #define BOOST_EXTENSION_SOLVER_DECL BOOST_EXTENSION_IMPORT_DECL #define BOOST_EXTENSION_STATESELECT_DECL BOOST_EXTENSION_IMPORT_DECL #define BOOST_EXTENSION_SOLVERSETTINGS_DECL BOOST_EXTENSION_IMPORT_DECL diff --git a/SimulationRuntime/cpp/Makefile.in b/SimulationRuntime/cpp/Makefile.in index 0dfdc7f32cc..74fcd51d76c 100644 --- a/SimulationRuntime/cpp/Makefile.in +++ b/SimulationRuntime/cpp/Makefile.in @@ -14,11 +14,15 @@ CXX=@CXX@ BOOST_STATIC_LINKING_COMMAND="-DBOOST_STATIC_LINKING=ON" BOOST_REALPATHS_COMMAND="-DUSE_BOOST_REALPATHS=ON" -PARALLEL_OUTPUT_COMMAND="-DUSE_PARALLEL_OUTPUT=ON" RUNTIME_PROFILING_COMMAND="-DRUNTIME_PROFILING=ON" SCOREP_COMMAND="-DUSE_SCOREP=ON" SCOREP_HOME="" +BUILD_DOC_COMMAND="-DBUILD_DOCUMENTATION=ON" + +#Experimental +PARALLEL_OUTPUT_COMMAND="-DPARALLEL_OUTPUT=ON" SUNDIALS_LAPACK_COMMAND="-DSUNDIALS_LAPACK=ON" + CMAKE_COMMANDS=CC="scorep --user --nocompiler gcc" CXX="scorep --user --nocompiler g++" CMAKE_ARGS=$(patsubst CMAKE_%, -D%, $(filter CMAKE_%, $(MAKEFLAGS))) @@ -29,21 +33,24 @@ endif ifneq ("$(BOOST_REALPATHS)","true") $(eval BOOST_REALPATHS_COMMAND=) endif -ifneq ("$(USE_PARALLEL_OUTPUT)","true") +ifneq ("$(PARALLEL_OUTPUT)","true") $(eval PARALLEL_OUTPUT_COMMAND=) endif ifneq ("$(RUNTIME_PROFILING)","true") $(eval RUNTIME_PROFILING_COMMAND=) endif -ifneq ("$(USE_SCOREP)","true") +ifneq ("$(SCOREP_SUPPORT)","true") $(eval CMAKE_COMMANDS=CC="@CC@" CXX="@CXX@" CFLAGS="@CFLAGS@" CXXFLAGS="@CXXFLAGS@") $(eval SCOREP_COMMAND=) endif -ifneq ("$(USE_SUNDIALS_LAPACK)","true") +ifneq ("$(SUNDIALS_LAPACK)","true") $(eval SUNDIALS_LAPACK_COMMAND=) +endif +ifneq ("$(BUILD_DOCUMENTATION)","true") + $(eval BUILD_DOC_COMMAND=) endif mkdir -p Build - cd ./Build && echo "change to Build" && $(CMAKE_COMMANDS) cmake $(BOOST_STATIC_LINKING_COMMAND) $(BOOST_REALPATHS_COMMAND) $(PARALLEL_OUTPUT_COMMAND) $(RUNTIME_PROFILING_COMMAND) $(SCOREP_COMMAND) $(SUNDIALS_LAPACK_COMMAND) -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX:PATH="$(OMBUILDDIR)" -DLIBINSTALLEXT=lib/@host_short@/omc/cpp -DSCOREP_HOME:STRING="$(SCOREP_HOME)" $(CMAKE_ARGS) ../ + cd ./Build && echo "change to Build" && $(CMAKE_COMMANDS) cmake $(BOOST_STATIC_LINKING_COMMAND) $(BOOST_REALPATHS_COMMAND) $(PARALLEL_OUTPUT_COMMAND) $(RUNTIME_PROFILING_COMMAND) $(SCOREP_COMMAND) $(SUNDIALS_LAPACK_COMMAND) -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX:PATH="$(OMBUILDDIR)" -DLIBINSTALLEXT=lib/@host_short@/omc/cpp -DSCOREP_HOME:STRING="$(SCOREP_HOME)" $(BUILD_DOC_COMMAND) $(CMAKE_ARGS) ../ $(MAKE) -C Build VERBOSE=1 install: runtimeCpp diff --git a/SimulationRuntime/cpp/Makefile.omdev.mingw b/SimulationRuntime/cpp/Makefile.omdev.mingw index 2979e4f9b09..0765c12e409 100644 --- a/SimulationRuntime/cpp/Makefile.omdev.mingw +++ b/SimulationRuntime/cpp/Makefile.omdev.mingw @@ -31,7 +31,7 @@ runtimeCPPmsvc: test -f """${VS100COMNTOOLS}/../../VC/vcvarsall.bat""" echo 'Build the cppRuntime with MSVC' - rm -rf build_msvc + #rm -rf build_msvc mkdir -p build_msvc echo call '"%VS100COMNTOOLS%\\..\\..\\VC\\vcvarsall.bat"' > build_msvc/build.bat #echo '%OMDEV%\\bin\\cmake\\bin\\cmake -DCMAKE_VERBOSE_MAKEFILE:Bool=ON -DCMAKE_BUILD_TYPE=$(BUILDTYPE) -DCMAKE_INSTALL_PREFIX=./tmp ../ -G "Visual Studio 10"' >> build_msvc/build.bat diff --git a/SimulationRuntime/cpp/PrecompiledHeader.cmake b/SimulationRuntime/cpp/PrecompiledHeader.cmake index c470d344a7f..1412a151555 100644 --- a/SimulationRuntime/cpp/PrecompiledHeader.cmake +++ b/SimulationRuntime/cpp/PrecompiledHeader.cmake @@ -155,7 +155,7 @@ IF("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STRE INSTALL(FILES "${_output}" DESTINATION include/omc/cpp/Core) SET(PCH_FILE "${_name}.gch") SET(H_FILE "${_name}") -ENDIF("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") +ENDIF("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel") IF("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") diff --git a/SimulationRuntime/cpp/README b/SimulationRuntime/cpp/README new file mode 100644 index 00000000000..bfdd3c76049 --- /dev/null +++ b/SimulationRuntime/cpp/README @@ -0,0 +1,71 @@ +Author: Marcus Walther 02.07.2015 + +============================ +BUILD THE SIMULATION RUNTIME +============================ +Building the c++ simulation runtime with OpenModelica is slightly different for +Linux/Mac and Windows. The following lines explain how to build the runtime with +it's default configuration. All commands should be executed in the +“superproject”-folder of OpenModelica, which contains the OMCompiler-folder. + + Linux/Mac: + configure --with-cppruntime + make omc + + Windows: + make -f Makefile.omdev.mingw runtimeCPPinstall + + (if the visual studio compiler should be used): + make -f Makefile.omdev.mingw runtimeCPPmsvcinstall + + +================================== +CONFIGURING THE SIMULATION RUNTIME +================================== +At the moment it's not possible to configure the behavior of the simulation +runtime with the autoconf-script of OpenModelica. Thus, it is necessary to +change to the source folder and pass some arguments to the Makefile. + + Linux/Mac/Windows: + cd OMCompiler/SimulationRuntime/cpp + +The following section explains the arguments that can be passed to the makefile. + + The boost static libraries can be used for the build, by passing the + BOOST_STATIC_LINKING argument to make. + + make [..] BOOST_STATIC_LINKING="true" + + Sometimes it's necessary to link boost against it's real path libraries. + This means for example, that instead of linking against “-lboost_system”, the + makefiles will link against “-lboost1.55_system”. + + make [..] BOOST_REALPATHS="true" + + If profiling informations for the runtime are required, they can be turned on + with the RUNTIME_PROFILING command. + + make [..] RUNTIME_PROFILING="true" + + Profiling can additionally be handled by Score-P. This gives the possibility + to use tracing besides profiling for performance analysis. Maybe it's + necessary to give the SCOREP_HOME directory to make as well. This is the + directory containing “include/scorep/SCOREP_User.h”. + + make [..] SCOREP_SUPPORT="true" SCOREP_HOME=”...” + + The doxygen documentation can be created the BUILD_DOCUMENTATION argument. + You can find further instructions and the code documentation in the generated + documents. + + make [..] BUILD_DOCUMENTATION="true" + + Simulation results can be written asynchronously with the help of boost + threads and a consumer producer algorithm (experimental). + + make [..] PARALLEL_OUTPUT="true" + + The sundials solver suite has additional lapack support. It can be used by + setting the SUNDIALS_LAPACK argument (experimental). + + make [..] SUNDIALS_LAPACK="true" \ No newline at end of file diff --git a/SimulationRuntime/cpp/SimCoreFactory/OMCFactory/OMCFactory.cpp b/SimulationRuntime/cpp/SimCoreFactory/OMCFactory/OMCFactory.cpp index 3b8caff79ff..925e918e2b6 100644 --- a/SimulationRuntime/cpp/SimCoreFactory/OMCFactory/OMCFactory.cpp +++ b/SimulationRuntime/cpp/SimCoreFactory/OMCFactory/OMCFactory.cpp @@ -55,10 +55,10 @@ SimSettings OMCFactory::readSimulationParameter(int argc, const char* argv[]) { int opt; int portnum; - std::map outputFormatMap = map_list_of("csv", CSV)("mat", MAT)("buffer", BUFFER)("empty", EMPTY); - std::map logCatMap = map_list_of("init", INIT)("nls", NLS)("ls",LS)("solv", SOLV)("output", OUT)("event",EVT)("modell",MOD)("other",OTHER); - std::map logLvlMap = map_list_of("error", ERROR)("warning", WARNING)("info", INFO)("debug", DEBUG); - std::map outputPointTypeMap = map_list_of("all", ALL)("step", STEP)("empty2",EMPTY2); + std::map outputFormatMap = map_list_of("csv", OF_CSV)("mat", OF_MAT)("buffer", OF_BUFFER)("empty", OF_EMPTY); + std::map logCatMap = map_list_of("init", LC_INIT)("nls", LC_NLS)("ls",LC_LS)("solv", LC_SOLV)("output", LC_OUT)("event",LC_EVT)("modell",LC_MOD)("other",LC_OTHER); + std::map logLvlMap = map_list_of("error", LL_ERROR)("warning", LL_WARNING)("info", LL_INFO)("debug", LL_DEBUG); + std::map outputPointTypeMap = map_list_of("all", OPT_ALL)("step", OPT_STEP)("empty", OPT_EMPTY); po::options_description desc("Allowed options"); desc.add_options() ("help", "produce help message") @@ -157,7 +157,7 @@ SimSettings OMCFactory::readSimulationParameter(int argc, const char* argv[]) //cout << "results file: " << vm["results-file"].as() << std::endl; outputFormat_str = vm["OutputFormat"].as(); outputFomat = outputFormatMap[outputFormat_str]; - if(!((outputFomat==CSV) || (outputFomat==EMPTY)||(outputFomat==BUFFER)||(outputFomat==MAT))) + if(!((outputFomat==OF_CSV) || (outputFomat==OF_EMPTY) || (outputFomat==OF_BUFFER) || (outputFomat==OF_MAT))) { std::string eception_msg = "The output format is not supported yet. Please use outputFormat=\"csv\" or outputFormat=\"empty\" or outputFormat=\"matlab\"in simulate command "; throw ModelicaSimulationError(MODEL_FACTORY,eception_msg.c_str()); diff --git a/SimulationRuntime/cpp/Solver/CVode/CVode.cpp b/SimulationRuntime/cpp/Solver/CVode/CVode.cpp index 04b33c1fd4f..0f58e15cda1 100644 --- a/SimulationRuntime/cpp/Solver/CVode/CVode.cpp +++ b/SimulationRuntime/cpp/Solver/CVode/CVode.cpp @@ -308,14 +308,14 @@ void Cvode::initialize() _cvode_initialized = true; - Logger::write("Cvode: initialized",SOLV,DEBUG); + Logger::write("Cvode: initialized",LC_SOLV,LL_DEBUG); } } void Cvode::solve(const SOLVERCALL action) { - bool writeEventOutput = (_settings->getGlobalSettings()->getOutputPointType() == ALL); - bool writeOutput = !(_settings->getGlobalSettings()->getOutputFormat() == EMPTY) && !(_settings->getGlobalSettings()->getOutputPointType() == EMPTY2); + bool writeEventOutput = (_settings->getGlobalSettings()->getOutputPointType() == OPT_ALL); + bool writeOutput = !(_settings->getGlobalSettings()->getOutputFormat() == OF_EMPTY) && !(_settings->getGlobalSettings()->getOutputPointType() == OPT_EMPTY); #ifdef RUNTIME_PROFILING MEASURETIME_REGION_DEFINE(cvodeSolveFunctionHandler, "solve"); @@ -454,8 +454,8 @@ void Cvode::CVodeCore() if (_idid < 0) throw ModelicaSimulationError(SOLVER,"CVode::ReInit"); - bool writeEventOutput = (_settings->getGlobalSettings()->getOutputPointType() == ALL); - bool writeOutput = !(_settings->getGlobalSettings()->getOutputFormat() == EMPTY) && !(_settings->getGlobalSettings()->getOutputPointType() == EMPTY2); + bool writeEventOutput = (_settings->getGlobalSettings()->getOutputPointType() == OPT_ALL); + bool writeOutput = !(_settings->getGlobalSettings()->getOutputFormat() == OF_EMPTY) && !(_settings->getGlobalSettings()->getOutputPointType() == OPT_EMPTY); while (_solverStatus & ISolver::CONTINUE && !_interrupt ) { @@ -939,13 +939,13 @@ void Cvode::writeSimulationInfo() flag = CVodeGetNonlinSolvStats(_cvodeMem, &nni, &ncfn); - Logger::write("Cvode: number steps = " + boost::lexical_cast(nst),SOLV,INFO); - Logger::write("Cvode: function evaluations 'f' = " + boost::lexical_cast(nfe),SOLV,INFO); - Logger::write("Cvode: error test failures 'netf' = " + boost::lexical_cast(netfS),SOLV,INFO); - Logger::write("Cvode: linear solver setups 'nsetups' = " + boost::lexical_cast(nsetups),SOLV,INFO); - Logger::write("Cvode: nonlinear iterations 'nni' = " + boost::lexical_cast(nni),SOLV,INFO); - Logger::write("Cvode: convergence failures 'ncfn' = " + boost::lexical_cast(ncfn),SOLV,INFO); - Logger::write("Cvode: number of evaluateODE calls 'eODE' = " + boost::lexical_cast(_numberOfOdeEvaluations),SOLV,INFO); + Logger::write("Cvode: number steps = " + boost::lexical_cast(nst),LC_SOLV,LL_INFO); + Logger::write("Cvode: function evaluations 'f' = " + boost::lexical_cast(nfe),LC_SOLV,LL_INFO); + Logger::write("Cvode: error test failures 'netf' = " + boost::lexical_cast(netfS),LC_SOLV,LL_INFO); + Logger::write("Cvode: linear solver setups 'nsetups' = " + boost::lexical_cast(nsetups),LC_SOLV,LL_INFO); + Logger::write("Cvode: nonlinear iterations 'nni' = " + boost::lexical_cast(nni),LC_SOLV,LL_INFO); + Logger::write("Cvode: convergence failures 'ncfn' = " + boost::lexical_cast(ncfn),LC_SOLV,LL_INFO); + Logger::write("Cvode: number of evaluateODE calls 'eODE' = " + boost::lexical_cast(_numberOfOdeEvaluations),LC_SOLV,LL_INFO); //// Solver //outputStream << "\nSolver: " << getName() diff --git a/SimulationRuntime/cpp/Solver/IDA/IDA.cpp b/SimulationRuntime/cpp/Solver/IDA/IDA.cpp index bbae0b86aa2..1e30735117e 100644 --- a/SimulationRuntime/cpp/Solver/IDA/IDA.cpp +++ b/SimulationRuntime/cpp/Solver/IDA/IDA.cpp @@ -282,8 +282,8 @@ void Ida::initialize() void Ida::solve(const SOLVERCALL action) { - bool writeEventOutput = (_settings->getGlobalSettings()->getOutputPointType() == ALL); - bool writeOutput = !(_settings->getGlobalSettings()->getOutputFormat() == EMPTY) && !(_settings->getGlobalSettings()->getOutputPointType() == EMPTY2); + bool writeEventOutput = (_settings->getGlobalSettings()->getOutputPointType() == OPT_ALL); + bool writeOutput = !(_settings->getGlobalSettings()->getOutputFormat() == OF_EMPTY) && !(_settings->getGlobalSettings()->getOutputPointType() == OPT_EMPTY); #ifdef RUNTIME_PROFILING MEASURETIME_REGION_DEFINE(idaSolveFunctionHandler, "solve"); @@ -422,8 +422,8 @@ void Ida::IDACore() if (_idid < 0) throw std::runtime_error("IDA::ReInit"); - bool writeEventOutput = (_settings->getGlobalSettings()->getOutputPointType() == ALL); - bool writeOutput = !(_settings->getGlobalSettings()->getOutputFormat() == EMPTY) && !(_settings->getGlobalSettings()->getOutputPointType() == EMPTY2); + bool writeEventOutput = (_settings->getGlobalSettings()->getOutputPointType() == OPT_ALL); + bool writeOutput = !(_settings->getGlobalSettings()->getOutputFormat() == OF_EMPTY) && !(_settings->getGlobalSettings()->getOutputPointType() == OPT_EMPTY); while (_solverStatus & ISolver::CONTINUE && !_interrupt ) { @@ -919,12 +919,12 @@ void Ida::writeSimulationInfo() flag = IDAGetNonlinSolvStats(_idaMem, &nni, &ncfn); - Logger::write("Cvode: number steps = " + boost::lexical_cast(nst),SOLV,INFO); - Logger::write("Cvode: function evaluations 'f' = " + boost::lexical_cast(nfe),SOLV,INFO); - Logger::write("Cvode: error test failures 'netf' = " + boost::lexical_cast(netfS),SOLV,INFO); - Logger::write("Cvode: linear solver setups 'nsetups' = " + boost::lexical_cast(nsetups),SOLV,INFO); - Logger::write("Cvode: nonlinear iterations 'nni' = " + boost::lexical_cast(nni),SOLV,INFO); - Logger::write("Cvode: convergence failures 'ncfn' = " + boost::lexical_cast(ncfn),SOLV,INFO); + Logger::write("Cvode: number steps = " + boost::lexical_cast(nst),LC_SOLV,LL_INFO); + Logger::write("Cvode: function evaluations 'f' = " + boost::lexical_cast(nfe),LC_SOLV,LL_INFO); + Logger::write("Cvode: error test failures 'netf' = " + boost::lexical_cast(netfS),LC_SOLV,LL_INFO); + Logger::write("Cvode: linear solver setups 'nsetups' = " + boost::lexical_cast(nsetups),LC_SOLV,LL_INFO); + Logger::write("Cvode: nonlinear iterations 'nni' = " + boost::lexical_cast(nni),LC_SOLV,LL_INFO); + Logger::write("Cvode: convergence failures 'ncfn' = " + boost::lexical_cast(ncfn),LC_SOLV,LL_INFO); } int Ida::check_flag(void *flagvalue, const char *funcname, int opt) diff --git a/common b/common index 51d5f523eff..5316bb36774 160000 --- a/common +++ b/common @@ -1 +1 @@ -Subproject commit 51d5f523effcb6c050c766e97f1c3b2ec9a4a50d +Subproject commit 5316bb3677448b8f387268052eaf6150a9209bba