From 9f0cb452cbf9c583b3a9ee583e8cb92ee7a53b13 Mon Sep 17 00:00:00 2001 From: perost Date: Tue, 23 Nov 2021 17:26:20 +0100 Subject: [PATCH] Add flag --dumpFlatModel (#8204) - Add flag --dumpFlatModel that can be used to dump the flat model at chosen stages of the frontend. - Remove old flag -d=nfDumpFlat which is superseded by the new flag. - Remove FrontEnd/NFInstUtil.mo since it's barely used, and only by the old frontend which already has equivalent functions. - Add NFFrontEnd/NFInstUtil.mo and move some of the utility functions in NFInst to it, which includes functions for dumping the flat model. --- .../.cmake/meta_modelica_source_list.cmake | 2 +- OMCompiler/Compiler/FrontEnd/InstSection.mo | 5 +- OMCompiler/Compiler/FrontEnd/InstVar.mo | 5 +- OMCompiler/Compiler/FrontEnd/NFInstUtil.mo | 240 ------------------ OMCompiler/Compiler/NFFrontEnd/NFFlatModel.mo | 28 +- OMCompiler/Compiler/NFFrontEnd/NFFlatten.mo | 3 + OMCompiler/Compiler/NFFrontEnd/NFInst.mo | 114 +-------- OMCompiler/Compiler/NFFrontEnd/NFInstUtil.mo | 172 +++++++++++++ OMCompiler/Compiler/NFFrontEnd/NFTypeCheck.mo | 1 - OMCompiler/Compiler/NFFrontEnd/NFTyping.mo | 1 - OMCompiler/Compiler/Script/NFApi.mo | 1 - OMCompiler/Compiler/Util/Flags.mo | 28 +- OMCompiler/Compiler/Util/FlagsUtil.mo | 4 +- .../Compiler/boot/LoadCompilerSources.mos | 2 +- .../modelica/scodeinst/DumpFlatModel1.mo | 167 ++++++++++++ .../flattening/modelica/scodeinst/Makefile | 1 + .../bootstrapping/LoadCompilerSources.mos | 1 - 17 files changed, 401 insertions(+), 374 deletions(-) delete mode 100644 OMCompiler/Compiler/FrontEnd/NFInstUtil.mo create mode 100644 OMCompiler/Compiler/NFFrontEnd/NFInstUtil.mo create mode 100644 testsuite/flattening/modelica/scodeinst/DumpFlatModel1.mo diff --git a/OMCompiler/Compiler/.cmake/meta_modelica_source_list.cmake b/OMCompiler/Compiler/.cmake/meta_modelica_source_list.cmake index 31cf88e666b..2fff388d2c6 100644 --- a/OMCompiler/Compiler/.cmake/meta_modelica_source_list.cmake +++ b/OMCompiler/Compiler/.cmake/meta_modelica_source_list.cmake @@ -44,7 +44,6 @@ set(OMC_MM_ALWAYS_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/FrontEnd/MMath.mo ${CMAKE_CURRENT_SOURCE_DIR}/FrontEnd/Mod.mo # Remember: Only files needed for compiling MetaModelica - ${CMAKE_CURRENT_SOURCE_DIR}/FrontEnd/NFInstUtil.mo ${CMAKE_CURRENT_SOURCE_DIR}/FrontEnd/OperatorOverloading.mo ${CMAKE_CURRENT_SOURCE_DIR}/FrontEnd/Parser.mo ${CMAKE_CURRENT_SOURCE_DIR}/FrontEnd/ParserExt.mo @@ -333,6 +332,7 @@ set(OMC_MM_BACKEND_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/NFFrontEnd/NFInstContext.mo ${CMAKE_CURRENT_SOURCE_DIR}/NFFrontEnd/NFInst.mo ${CMAKE_CURRENT_SOURCE_DIR}/NFFrontEnd/NFInstNode.mo + ${CMAKE_CURRENT_SOURCE_DIR}/NFFrontEnd/NFInstUtil.mo ${CMAKE_CURRENT_SOURCE_DIR}/NFFrontEnd/NFLookup.mo ${CMAKE_CURRENT_SOURCE_DIR}/NFFrontEnd/NFLookupState.mo ${CMAKE_CURRENT_SOURCE_DIR}/NFFrontEnd/NFLookupTree.mo diff --git a/OMCompiler/Compiler/FrontEnd/InstSection.mo b/OMCompiler/Compiler/FrontEnd/InstSection.mo index 48a6453999f..a26ba3e5379 100644 --- a/OMCompiler/Compiler/FrontEnd/InstSection.mo +++ b/OMCompiler/Compiler/FrontEnd/InstSection.mo @@ -69,7 +69,6 @@ protected import InstDAE; protected import InstFunction; protected import InstTypes; protected import InstUtil; -protected import NFInstUtil; protected import List; protected import Lookup; protected import Patternm; @@ -4240,8 +4239,8 @@ algorithm crefExp1 = Expression.crefExp(c1_1); crefExp2 = Expression.crefExp(c2_1); // Evaluate constant crefs away - const1 = NFInstUtil.toConst(vt1); - const2 = NFInstUtil.toConst(vt2); + const1 = Types.variabilityToConst(vt1); + const2 = Types.variabilityToConst(vt2); (cache, crefExp1) = Ceval.cevalIfConstant(cache, env, crefExp1, DAE.PROP(t1,const1), true, info); (cache, crefExp2) = Ceval.cevalIfConstant(cache, env, crefExp2, DAE.PROP(t2,const2), true, info); diff --git a/OMCompiler/Compiler/FrontEnd/InstVar.mo b/OMCompiler/Compiler/FrontEnd/InstVar.mo index 51e0ca5b55b..4c973451be9 100644 --- a/OMCompiler/Compiler/FrontEnd/InstVar.mo +++ b/OMCompiler/Compiler/FrontEnd/InstVar.mo @@ -70,7 +70,6 @@ protected import Types; protected import PrefixUtil; protected import List; protected import ComponentReference; -protected import NFInstUtil; protected import UnitAbsynBuilder; protected import Flags; protected import Expression; @@ -599,7 +598,7 @@ algorithm source := ElementSource.createElementSource(inInfo, FGraph.getScopePath(inEnv), inPrefix); (outCache, outDae) := addArrayVarEquation(outCache, inEnv, outIH, inState, - outDae, outType, mod, NFInstUtil.toConst(SCodeUtil.attrVariability(attr)), + outDae, outType, mod, Types.variabilityToConst(SCodeUtil.attrVariability(attr)), inPrefix, inName, source); outCache := InstFunction.addRecordConstructorFunction(outCache, inEnv, Types.arrayElementType(outType), SCodeUtil.elementInfo(inClass)); @@ -1163,7 +1162,7 @@ algorithm mod = if not listEmpty(inSubscripts) and not SCodeUtil.isParameterOrConst(vt) and not ClassInf.isFunctionOrRecord(inState) and not Types.isComplexType(Types.arrayElementType(ty)) and not Types.isExternalObject(Types.arrayElementType(ty)) and not Config.scalarizeBindings() then DAE.NOMOD() else inMod; - opt_binding = InstBinding.makeVariableBinding(ty, mod, NFInstUtil.toConst(vt), inPrefix, inName); + opt_binding = InstBinding.makeVariableBinding(ty, mod, Types.variabilityToConst(vt), inPrefix, inName); start = InstBinding.instStartBindingExp(inMod /* Yup, let's keep the start-binding. It seems sane. */, ty, vt); // Propagate the final prefix from the modifier. //fin = InstUtil.propagateModFinal(mod, fin); diff --git a/OMCompiler/Compiler/FrontEnd/NFInstUtil.mo b/OMCompiler/Compiler/FrontEnd/NFInstUtil.mo deleted file mode 100644 index f94ac803239..00000000000 --- a/OMCompiler/Compiler/FrontEnd/NFInstUtil.mo +++ /dev/null @@ -1,240 +0,0 @@ -/* - * 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 NFInstUtil -" file: NFInstUtil.mo - package: NFInstUtil - description: Utility functions for NFInstTypes. - - - Utility functions for operating on the types in NFInstTypes. -" - -public import DAE; -public import SCode; -public import Absyn; - -function daeToSCodeConnectorType - input DAE.ConnectorType inConnectorType; - output SCode.ConnectorType outConnectorType; -algorithm - outConnectorType := match(inConnectorType) - case DAE.NON_CONNECTOR() then SCode.POTENTIAL(); - case DAE.POTENTIAL() then SCode.POTENTIAL(); - case DAE.FLOW() then SCode.FLOW(); - case DAE.STREAM() then SCode.STREAM(); - end match; -end daeToSCodeConnectorType; - -function daeToSCodeParallelism - input DAE.VarParallelism inParallelism; - output SCode.Parallelism outParallelism; -algorithm - outParallelism := match(inParallelism) - case DAE.PARGLOBAL() then SCode.PARGLOBAL(); - case DAE.PARLOCAL() then SCode.PARLOCAL(); - case DAE.NON_PARALLEL() then SCode.NON_PARALLEL(); - end match; -end daeToSCodeParallelism; - -function daeToSCodeVariability - input DAE.VarKind inVariability; - output SCode.Variability outVariability; -algorithm - outVariability := match(inVariability) - case DAE.VARIABLE() then SCode.VAR(); - case DAE.DISCRETE() then SCode.DISCRETE(); - case DAE.PARAM() then SCode.PARAM(); - case DAE.CONST() then SCode.CONST(); - end match; -end daeToSCodeVariability; - -function daeToAbsynDirection - input DAE.VarDirection inDirection; - output Absyn.Direction outDirection; -algorithm - outDirection := match(inDirection) - case DAE.BIDIR() then Absyn.BIDIR(); - case DAE.INPUT() then Absyn.INPUT(); - case DAE.OUTPUT() then Absyn.OUTPUT(); - end match; -end daeToAbsynDirection; - -function daeToAbsynInnerOuter - input DAE.VarInnerOuter inInnerOuter; - output Absyn.InnerOuter outInnerOuter; -algorithm - outInnerOuter := match(inInnerOuter) - case DAE.INNER() then Absyn.INNER(); - case DAE.INNER_OUTER() then Absyn.INNER_OUTER(); - case DAE.OUTER() then Absyn.OUTER(); - case DAE.NOT_INNER_OUTER() then Absyn.NOT_INNER_OUTER(); - end match; -end daeToAbsynInnerOuter; - -function daeToSCodeVisibility - input DAE.VarVisibility inVisibility; - output SCode.Visibility outVisibility; -algorithm - outVisibility := match(inVisibility) - case DAE.PUBLIC() then SCode.PUBLIC(); - case DAE.PROTECTED() then SCode.PROTECTED(); - end match; -end daeToSCodeVisibility; - -function translateConnectorType - input SCode.ConnectorType inConnectorType; - output DAE.ConnectorType outConnectorType; -algorithm - outConnectorType := match(inConnectorType) - case SCode.FLOW() then DAE.FLOW(); - case SCode.STREAM() then DAE.STREAM(NONE()); - else DAE.NON_CONNECTOR(); - end match; -end translateConnectorType; - -function translateParallelism - 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 translateParallelism; - -function translateVariability - input SCode.Variability inVariability; - output DAE.VarKind outVariability; -algorithm - outVariability := match(inVariability) - case SCode.VAR() then DAE.VARIABLE(); - case SCode.PARAM() then DAE.PARAM(); - case SCode.CONST() then DAE.CONST(); - case SCode.DISCRETE() then DAE.DISCRETE(); - end match; -end translateVariability; - -function translateDirection - input Absyn.Direction inDirection; - output DAE.VarDirection outDirection; -algorithm - outDirection := match(inDirection) - case Absyn.BIDIR() then DAE.BIDIR(); - case Absyn.OUTPUT() then DAE.OUTPUT(); - case Absyn.INPUT() then DAE.INPUT(); - end match; -end translateDirection; - -function translateInnerOuter - input Absyn.InnerOuter inInnerOuter; - output DAE.VarInnerOuter outInnerOuter; -algorithm - outInnerOuter := match(inInnerOuter) - case Absyn.INNER() then DAE.INNER(); - case Absyn.INNER_OUTER() then DAE.INNER_OUTER(); - case Absyn.OUTER() then DAE.OUTER(); - case Absyn.NOT_INNER_OUTER() then DAE.NOT_INNER_OUTER(); - end match; -end translateInnerOuter; - -function translateVisibility - input SCode.Visibility inVisibility; - output DAE.VarVisibility outVisibility; -algorithm - outVisibility := match(inVisibility) - case SCode.PUBLIC() then DAE.PUBLIC(); - else DAE.PROTECTED(); - end match; -end translateVisibility; - -function toConst - "Translates SCode.Variability to DAE.Const" - input SCode.Variability inVar; - output DAE.Const outConst; -algorithm - outConst := match inVar - case SCode.CONST() then DAE.C_CONST(); - case SCode.PARAM() then DAE.C_PARAM(); - else DAE.C_VAR(); - end match; -end toConst; - -function variabilityAnd - "Returns the most variable of two VarKinds." - input DAE.VarKind var1; - input DAE.VarKind var2; - output DAE.VarKind var; -algorithm - var := match (var1, var2) - case (DAE.VarKind.VARIABLE(), _) then var1; - case (_, DAE.VarKind.VARIABLE()) then var2; - case (DAE.VarKind.DISCRETE(), _) then var1; - case (_, DAE.VarKind.DISCRETE()) then var2; - case (DAE.VarKind.PARAM(), _) then var1; - case (_, DAE.VarKind.PARAM()) then var2; - else var1; - end match; -end variabilityAnd; - -function variabilityOr - "Returns the least variable of two VarKinds." - input DAE.VarKind var1; - input DAE.VarKind var2; - output DAE.VarKind var; -algorithm - var := match (var1, var2) - case (DAE.VarKind.CONST(), _) then var1; - case (_, DAE.VarKind.CONST()) then var2; - case (DAE.VarKind.PARAM(), _) then var1; - case (_, DAE.VarKind.PARAM()) then var2; - case (DAE.VarKind.DISCRETE(), _) then var1; - case (_, DAE.VarKind.DISCRETE()) then var2; - else var1; - end match; -end variabilityOr; - -function variabilityString - input DAE.VarKind var; - output String string; -algorithm - string := match var - case DAE.VarKind.CONST() then "constant"; - case DAE.VarKind.PARAM() then "parameter"; - case DAE.VarKind.DISCRETE() then "discrete"; - case DAE.VarKind.VARIABLE() then "continuous"; - end match; -end variabilityString; - - -annotation(__OpenModelica_Interface="frontend"); -end NFInstUtil; diff --git a/OMCompiler/Compiler/NFFrontEnd/NFFlatModel.mo b/OMCompiler/Compiler/NFFrontEnd/NFFlatModel.mo index 1388a7f475e..24b9f04e0d6 100644 --- a/OMCompiler/Compiler/NFFrontEnd/NFFlatModel.mo +++ b/OMCompiler/Compiler/NFFrontEnd/NFFlatModel.mo @@ -113,12 +113,33 @@ public function toString input FlatModel flatModel; input Boolean printBindingTypes = false; - output String str; + output String str = IOStream.string(toStream(flatModel, printBindingTypes)); + end toString; + + function printString + input FlatModel flatModel; + input Boolean printBindingTypes = false; protected IOStream.IOStream s; + algorithm + s := toStream(flatModel, printBindingTypes); + IOStream.print(s, IOStream.stdOutput); + end printString; + + function toStream + input FlatModel flatModel; + input Boolean printBindingTypes = false; + output IOStream.IOStream s; algorithm s := IOStream.create(getInstanceName(), IOStream.IOStreamType.LIST()); + s := appendStream(flatModel, printBindingTypes, s); + end toStream; + function appendStream + input FlatModel flatModel; + input Boolean printBindingTypes = false; + input output IOStream.IOStream s; + algorithm s := IOStream.append(s, "class " + flatModel.name + "\n"); for v in flatModel.variables loop @@ -151,10 +172,7 @@ public end for; s := IOStream.append(s, "end " + flatModel.name + ";\n"); - - str := IOStream.string(s); - IOStream.delete(s); - end toString; + end appendStream; function toFlatString "Returns a string containing the flat Modelica representation of the given model." diff --git a/OMCompiler/Compiler/NFFrontEnd/NFFlatten.mo b/OMCompiler/Compiler/NFFrontEnd/NFFlatten.mo index 30acd5bb086..9b580e3bce7 100644 --- a/OMCompiler/Compiler/NFFrontEnd/NFFlatten.mo +++ b/OMCompiler/Compiler/NFFrontEnd/NFFlatten.mo @@ -95,6 +95,7 @@ import UnorderedMap; import UnorderedSet; import Inline = NFInline; import ExpandExp = NFExpandExp; +import InstUtil = NFInstUtil; public type FunctionTree = FunctionTreeImpl.Tree; @@ -181,12 +182,14 @@ algorithm end match; execStat(getInstanceName()); + InstUtil.dumpFlatModelDebug("flatten", flatModel); if settings.arrayConnect then flatModel := resolveArrayConnections(flatModel); else flatModel := resolveConnections(flatModel, deleted_vars); end if; + InstUtil.dumpFlatModelDebug("connections", flatModel); end flatten; function collectFunctions diff --git a/OMCompiler/Compiler/NFFrontEnd/NFInst.mo b/OMCompiler/Compiler/NFFrontEnd/NFInst.mo index 861a8748262..15b0cc28cba 100644 --- a/OMCompiler/Compiler/NFFrontEnd/NFInst.mo +++ b/OMCompiler/Compiler/NFFrontEnd/NFInst.mo @@ -169,6 +169,7 @@ algorithm // Flatten the model and evaluate constants in it. flatModel := Flatten.flatten(inst_cls, name); flatModel := EvalConstants.evaluate(flatModel); + InstUtil.dumpFlatModelDebug("eval", flatModel); // Do unit checking flatModel := UnitCheck.checkUnits(flatModel); @@ -184,10 +185,11 @@ algorithm // Collect a tree of all functions that are still used in the flat model. functions := Flatten.collectFunctions(flatModel); - // Dump the flat model to a stream if dumpFlat = true. - flatString := if dumpFlat then dumpFlatModel(flatModel, functions) else ""; + // Dump the flat model to a string if dumpFlat = true. + flatString := if dumpFlat then InstUtil.dumpFlatModel(flatModel, functions) else ""; - printStructuralParameters(flatModel); + InstUtil.dumpFlatModelDebug("simplify", flatModel, functions); + InstUtil.printStructuralParameters(flatModel); // Scalarize array components in the flat model. if Flags.isSet(Flags.NF_SCALARIZE) then @@ -197,17 +199,11 @@ algorithm flatModel.variables := List.filterOnFalse(flatModel.variables, Variable.isEmptyArray); end if; - flatModel := FlatModel.mapExp(flatModel, replaceEmptyArrays); + flatModel := InstUtil.replaceEmptyArrays(flatModel); + InstUtil.dumpFlatModelDebug("scalarize", flatModel, functions); VerifyModel.verify(flatModel); - - if Flags.isSet(Flags.COMBINE_SUBSCRIPTS) then - flatModel := FlatModel.mapExp(flatModel, combineSubscripts); - end if; - - if Flags.isSet(Flags.NF_DUMP_FLAT) then - print("FlatModel:\n" + FlatModel.toString(flatModel) + "\n"); - end if; + flatModel := InstUtil.combineSubscripts(flatModel); //(var_count, eq_count) := CheckModel.checkModel(flatModel); //print(name + " has " + String(var_count) + " variable(s) and " + String(eq_count) + " equation(s).\n"); @@ -3743,99 +3739,5 @@ algorithm end if; end checkPartialClass; -function combineSubscripts - input output Expression exp; -protected - function traverser - input output Expression exp; - algorithm - () := match exp - case Expression.CREF() - algorithm - exp.cref := ComponentRef.combineSubscripts(exp.cref); - then - (); - - else (); - end match; - end traverser; -algorithm - exp := Expression.map(exp, traverser); -end combineSubscripts; - -function printStructuralParameters - input FlatModel flatModel; -protected - list params; - list names; -algorithm - if Flags.isSet(Flags.PRINT_STRUCTURAL) then - params := list(v for v guard Variable.isStructural(v) in flatModel.variables); - - if not listEmpty(params) then - names := list(ComponentRef.toString(v.name) for v in params); - Error.addMessage(Error.NOTIFY_FRONTEND_STRUCTURAL_PARAMETERS, - {stringDelimitList(names, ", ")}); - end if; - end if; -end printStructuralParameters; - -function dumpFlatModel - input FlatModel flatModel; - input FunctionTree functions; - output String str; -protected - FlatModel flat_model = flatModel; -algorithm - if Flags.isSet(Flags.COMBINE_SUBSCRIPTS) then - flat_model := FlatModel.mapExp(flat_model, combineSubscripts); - end if; - - str := FlatModel.toFlatString(flat_model, FunctionTree.listValues(functions)); -end dumpFlatModel; - -function replaceEmptyArrays - "Variables with 0-dimensions are not present in the flat model, so replace - any cref that refers to such a variable with an empty array expression." - input output Expression exp; -protected - function traverser - input Expression exp; - output Expression outExp; - protected - ComponentRef cref; - list subs; - Type ty; - algorithm - outExp := match exp - case Expression.CREF(cref = cref) - guard ComponentRef.isEmptyArray(cref) - algorithm - if ComponentRef.hasSubscripts(cref) then - cref := ComponentRef.fillSubscripts(cref); - cref := ComponentRef.replaceWholeSubscripts(cref); - subs := ComponentRef.subscriptsAllFlat(cref); - cref := ComponentRef.stripSubscriptsAll(cref); - ty := ComponentRef.getSubscriptedType(cref); - else - subs := {}; - ty := exp.ty; - end if; - - outExp := Expression.makeDefaultValue(ty); - - if not listEmpty(subs) then - outExp := Expression.SUBSCRIPTED_EXP(outExp, subs, exp.ty, false); - end if; - then - outExp; - - else exp; - end match; - end traverser; -algorithm - exp := Expression.map(exp, traverser); -end replaceEmptyArrays; - annotation(__OpenModelica_Interface="frontend"); end NFInst; diff --git a/OMCompiler/Compiler/NFFrontEnd/NFInstUtil.mo b/OMCompiler/Compiler/NFFrontEnd/NFInstUtil.mo new file mode 100644 index 00000000000..296f77685ce --- /dev/null +++ b/OMCompiler/Compiler/NFFrontEnd/NFInstUtil.mo @@ -0,0 +1,172 @@ +/* + * This file is part of OpenModelica. + * + * Copyright (c) 1998-CurrentYear, Linköping University, + * 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 + * AND THIS OSMC PUBLIC LICENSE (OSMC-PL). + * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES RECIPIENT'S + * ACCEPTANCE OF THE OSMC PUBLIC LICENSE. + * + * The OpenModelica software and the Open Source Modelica + * Consortium (OSMC) Public License (OSMC-PL) are obtained + * from Linköping University, 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 NFInstUtil + import ComponentRef = NFComponentRef; + import Expression = NFExpression; + import FlatModel = NFFlatModel; + import NFFlatten.FunctionTree; + import NFFunction.Function; + import Subscript = NFSubscript; + import Type = NFType; + import Variable = NFVariable; + +protected + import Flags; + +public + function dumpFlatModelDebug + input String stage; + input FlatModel flatModel; + input FunctionTree functions = FunctionTree.new(); + protected + FlatModel flat_model = flatModel; + algorithm + if Flags.isConfigFlagSet(Flags.DUMP_FLAT_MODEL, stage) or + Flags.isConfigFlagSet(Flags.DUMP_FLAT_MODEL, "all") then + flat_model := combineSubscripts(flatModel); + + print("########################################\n"); + print(stage); + print("\n########################################\n\n"); + + FlatModel.printString(flat_model); + print("\n"); + end if; + end dumpFlatModelDebug; + + function combineSubscripts + input output FlatModel flatModel; + algorithm + if Flags.isSet(Flags.COMBINE_SUBSCRIPTS) then + flatModel := FlatModel.mapExp(flatModel, combineSubscriptsExp); + end if; + end combineSubscripts; + + function combineSubscriptsExp + input output Expression exp; + protected + function traverser + input output Expression exp; + algorithm + () := match exp + case Expression.CREF() + algorithm + exp.cref := ComponentRef.combineSubscripts(exp.cref); + then + (); + + else (); + end match; + end traverser; + algorithm + exp := Expression.map(exp, traverser); + end combineSubscriptsExp; + + function printStructuralParameters + input FlatModel flatModel; + protected + list params; + list names; + algorithm + if Flags.isSet(Flags.PRINT_STRUCTURAL) then + params := list(v for v guard Variable.isStructural(v) in flatModel.variables); + + if not listEmpty(params) then + names := list(ComponentRef.toString(v.name) for v in params); + Error.addMessage(Error.NOTIFY_FRONTEND_STRUCTURAL_PARAMETERS, + {stringDelimitList(names, ", ")}); + end if; + end if; + end printStructuralParameters; + + function dumpFlatModel + input FlatModel flatModel; + input FunctionTree functions; + output String str; + protected + FlatModel flat_model; + algorithm + flat_model := combineSubscripts(flatModel); + str := FlatModel.toFlatString(flat_model, FunctionTree.listValues(functions)); + end dumpFlatModel; + + function replaceEmptyArrays + input output FlatModel flatModel; + algorithm + flatModel := FlatModel.mapExp(flatModel, replaceEmptyArraysExp); + end replaceEmptyArrays; + + function replaceEmptyArraysExp + "Variables with 0-dimensions are not present in the flat model, so replace + any cref that refers to such a variable with an empty array expression." + input output Expression exp; + protected + function traverser + input Expression exp; + output Expression outExp; + protected + ComponentRef cref; + list subs; + Type ty; + algorithm + outExp := match exp + case Expression.CREF(cref = cref) + guard ComponentRef.isEmptyArray(cref) + algorithm + if ComponentRef.hasSubscripts(cref) then + cref := ComponentRef.fillSubscripts(cref); + cref := ComponentRef.replaceWholeSubscripts(cref); + subs := ComponentRef.subscriptsAllFlat(cref); + cref := ComponentRef.stripSubscriptsAll(cref); + ty := ComponentRef.getSubscriptedType(cref); + else + subs := {}; + ty := exp.ty; + end if; + + outExp := Expression.makeDefaultValue(ty); + + if not listEmpty(subs) then + outExp := Expression.SUBSCRIPTED_EXP(outExp, subs, exp.ty, false); + end if; + then + outExp; + + else exp; + end match; + end traverser; + algorithm + exp := Expression.map(exp, traverser); + end replaceEmptyArraysExp; + +annotation(__OpenModelica_Interface="frontend"); +end NFInstUtil; diff --git a/OMCompiler/Compiler/NFFrontEnd/NFTypeCheck.mo b/OMCompiler/Compiler/NFFrontEnd/NFTypeCheck.mo index c6485910e0d..f439d5b4bb7 100644 --- a/OMCompiler/Compiler/NFFrontEnd/NFTypeCheck.mo +++ b/OMCompiler/Compiler/NFFrontEnd/NFTypeCheck.mo @@ -57,7 +57,6 @@ import Operator = NFOperator; import Type = NFType; import Class = NFClass; import ClassTree = NFClassTree; -import InstUtil = NFInstUtil; import Prefixes = NFPrefixes; import Restriction = NFRestriction; import ComplexType = NFComplexType; diff --git a/OMCompiler/Compiler/NFFrontEnd/NFTyping.mo b/OMCompiler/Compiler/NFFrontEnd/NFTyping.mo index 3588a139013..d61ad24aaac 100644 --- a/OMCompiler/Compiler/NFFrontEnd/NFTyping.mo +++ b/OMCompiler/Compiler/NFFrontEnd/NFTyping.mo @@ -65,7 +65,6 @@ import ComponentRef = NFComponentRef; import Config; import Origin = NFComponentRef.Origin; import ExecStat.execStat; -import InstUtil = NFInstUtil; import Lookup = NFLookup; import MatchKind = NFTypeCheck.MatchKind; import Call = NFCall; diff --git a/OMCompiler/Compiler/Script/NFApi.mo b/OMCompiler/Compiler/Script/NFApi.mo index d7b416ea6cd..b84464440e5 100644 --- a/OMCompiler/Compiler/Script/NFApi.mo +++ b/OMCompiler/Compiler/Script/NFApi.mo @@ -77,7 +77,6 @@ import FlagsUtil; import FlatModel = NFFlatModel; import Flatten = NFFlatten; import Global; -import InstUtil = NFInstUtil; import Interactive; import InteractiveUtil; import List; diff --git a/OMCompiler/Compiler/Util/Flags.mo b/OMCompiler/Compiler/Util/Flags.mo index 1911f62ae11..31ff53e2eab 100644 --- a/OMCompiler/Compiler/Util/Flags.mo +++ b/OMCompiler/Compiler/Util/Flags.mo @@ -531,21 +531,19 @@ constant DebugFlag DUMP_ASSC = DEBUG_FLAG(179, "dumpASSC", false, Gettext.gettext("Dumps the conversion process of analytical to structural singularities.")); constant DebugFlag SPLIT_CONSTANT_PARTS_SYMJAC = DEBUG_FLAG(180, "symJacConstantSplit", false, Gettext.gettext("Generates all symbolic Jacobians with splitted constant parts.")); -constant DebugFlag NF_DUMP_FLAT = DEBUG_FLAG(181, "nfDumpFlat", false, - Gettext.gettext("Dumps the flat model structure before generating the DAE.")); -constant DebugFlag DUMP_FORCE_FMI_ATTRIBUTES = DEBUG_FLAG(182, "force-fmi-attributes", false, +constant DebugFlag DUMP_FORCE_FMI_ATTRIBUTES = DEBUG_FLAG(181, "force-fmi-attributes", false, Gettext.gettext("Force to export all fmi attributes to the modelDescription.xml, including those which have default values")); -constant DebugFlag DUMP_DATARECONCILIATION = DEBUG_FLAG(183, "dataReconciliation", false, +constant DebugFlag DUMP_DATARECONCILIATION = DEBUG_FLAG(182, "dataReconciliation", false, Gettext.gettext("Dumps all the dataReconciliation extraction algorithm procedure")); -constant DebugFlag ARRAY_CONNECT = DEBUG_FLAG(184, "arrayConnect", false, +constant DebugFlag ARRAY_CONNECT = DEBUG_FLAG(183, "arrayConnect", false, Gettext.gettext("Use experimental array connection handler.")); -constant DebugFlag COMBINE_SUBSCRIPTS = DEBUG_FLAG(185, "combineSubscripts", false, +constant DebugFlag COMBINE_SUBSCRIPTS = DEBUG_FLAG(184, "combineSubscripts", false, Gettext.gettext("Move all subscripts to the end of component references.")); -constant DebugFlag ZMQ_LISTEN_TO_ALL = DEBUG_FLAG(186, "zmqDangerousAcceptConnectionsFromAnywhere", false, +constant DebugFlag ZMQ_LISTEN_TO_ALL = DEBUG_FLAG(185, "zmqDangerousAcceptConnectionsFromAnywhere", false, Gettext.gettext("When opening a zmq connection, listen on all interfaces instead of only connections from 127.0.0.1.")); -constant DebugFlag DUMP_CONVERSION_RULES = DEBUG_FLAG(187, "dumpConversionRules", false, +constant DebugFlag DUMP_CONVERSION_RULES = DEBUG_FLAG(186, "dumpConversionRules", false, Gettext.gettext("Dumps the rules when converting a package using a conversion script.")); -constant DebugFlag PRINT_RECORD_TYPES = DEBUG_FLAG(188, "printRecordTypes", false, +constant DebugFlag PRINT_RECORD_TYPES = DEBUG_FLAG(187, "printRecordTypes", false, Gettext.gettext("Prints out record types as part of the flat code.")); public @@ -1388,6 +1386,18 @@ constant ConfigFlag TEARING_ALWAYS_DERIVATIVES = CONFIG_FLAG(148, "tearingAlways NONE(), EXTERNAL(), BOOL_FLAG(false), NONE(), Gettext.gettext("Always choose state derivatives as iteration variables in strong components.")); +constant ConfigFlag DUMP_FLAT_MODEL = CONFIG_FLAG(149, "dumpFlatModel", + NONE(), EXTERNAL(), STRING_LIST_FLAG({}), + SOME(STRING_DESC_OPTION({ + ("flatten", Gettext.gettext("After flattening but before connection handling.")), + ("connections", Gettext.gettext("After connection handling.")), + ("eval", Gettext.gettext("After evaluating constants.")), + ("simplify", Gettext.gettext("After model simplification.")), + ("scalarize", Gettext.gettext("After scalarizing arrays.")), + ("all", Gettext.gettext("Dump after every stage.")) + })), + Gettext.gettext("Dumps the flat model at the given stages of the frontend.")); + function getFlags "Loads the flags with getGlobalRoot. Assumes flags have been loaded." input Boolean initialize = true; diff --git a/OMCompiler/Compiler/Util/FlagsUtil.mo b/OMCompiler/Compiler/Util/FlagsUtil.mo index 44c9562d242..f593a48c3a2 100644 --- a/OMCompiler/Compiler/Util/FlagsUtil.mo +++ b/OMCompiler/Compiler/Util/FlagsUtil.mo @@ -237,7 +237,6 @@ constant list allDebugFlags = { Flags.DUMP_JL, Flags.DUMP_ASSC, Flags.SPLIT_CONSTANT_PARTS_SYMJAC, - Flags.NF_DUMP_FLAT, Flags.DUMP_FORCE_FMI_ATTRIBUTES, Flags.DUMP_DATARECONCILIATION, Flags.ARRAY_CONNECT, @@ -399,7 +398,8 @@ constant list allConfigFlags = { Flags.ALLOW_NON_STANDARD_MODELICA, Flags.EXPORT_CLOCKS_IN_MODELDESCRIPTION, Flags.LINK_TYPE, - Flags.TEARING_ALWAYS_DERIVATIVES + Flags.TEARING_ALWAYS_DERIVATIVES, + Flags.DUMP_FLAT_MODEL }; public function new diff --git a/OMCompiler/Compiler/boot/LoadCompilerSources.mos b/OMCompiler/Compiler/boot/LoadCompilerSources.mos index 19c6fd13939..6ac9ecd07da 100644 --- a/OMCompiler/Compiler/boot/LoadCompilerSources.mos +++ b/OMCompiler/Compiler/boot/LoadCompilerSources.mos @@ -50,7 +50,6 @@ if true then /* Suppress output */ "../FrontEnd/MMath.mo", "../FrontEnd/Mod.mo", // Remember: Only files needed for compiling MetaModelica - "../FrontEnd/NFInstUtil.mo", "../FrontEnd/OperatorOverloading.mo", "../FrontEnd/Parser.mo", "../FrontEnd/ParserExt.mo", @@ -367,6 +366,7 @@ if true then /* Suppress output */ "../NFFrontEnd/NFInstContext.mo", "../NFFrontEnd/NFInst.mo", "../NFFrontEnd/NFInstNode.mo", + "../NFFrontEnd/NFInstUtil.mo", "../NFFrontEnd/NFLookup.mo", "../NFFrontEnd/NFLookupState.mo", "../NFFrontEnd/NFLookupTree.mo", diff --git a/testsuite/flattening/modelica/scodeinst/DumpFlatModel1.mo b/testsuite/flattening/modelica/scodeinst/DumpFlatModel1.mo new file mode 100644 index 00000000000..5283673721c --- /dev/null +++ b/testsuite/flattening/modelica/scodeinst/DumpFlatModel1.mo @@ -0,0 +1,167 @@ +// name: DumpFlatModel1 +// keywords: +// status: correct +// cflags: -d=newInst --dumpFlatModel=all +// + +model A + Real x[3] = {1, 2, 3}; + Real y[3]; +equation + for i loop + y[i] = x[i]; + end for; +end A; + +model DumpFlatModel1 + A a1; + A a2(x = {4, 5, 6}); +algorithm + a1.x := ones(size(a1.x, 1)); +end DumpFlatModel1; + +// Result: +// ######################################## +// flatten +// ######################################## +// +// class DumpFlatModel1 +// Real[3] a1.x; +// Real[3] a1.y; +// Real[3] a2.x; +// Real[3] a2.y; +// equation +// a1.x = {1.0, 2.0, 3.0}; +// a1.y[1] = a1.x[1]; +// a1.y[2] = a1.x[2]; +// a1.y[3] = a1.x[3]; +// a2.x = {4.0, 5.0, 6.0}; +// a2.y[1] = a2.x[1]; +// a2.y[2] = a2.x[2]; +// a2.y[3] = a2.x[3]; +// algorithm +// a1.x := fill(1.0, 3); +// end DumpFlatModel1; +// +// ######################################## +// connections +// ######################################## +// +// class DumpFlatModel1 +// Real[3] a1.x; +// Real[3] a1.y; +// Real[3] a2.x; +// Real[3] a2.y; +// equation +// a1.x = {1.0, 2.0, 3.0}; +// a1.y[1] = a1.x[1]; +// a1.y[2] = a1.x[2]; +// a1.y[3] = a1.x[3]; +// a2.x = {4.0, 5.0, 6.0}; +// a2.y[1] = a2.x[1]; +// a2.y[2] = a2.x[2]; +// a2.y[3] = a2.x[3]; +// algorithm +// a1.x := fill(1.0, 3); +// end DumpFlatModel1; +// +// ######################################## +// eval +// ######################################## +// +// class DumpFlatModel1 +// Real[3] a1.x; +// Real[3] a1.y; +// Real[3] a2.x; +// Real[3] a2.y; +// equation +// a1.x = {1.0, 2.0, 3.0}; +// a1.y[1] = a1.x[1]; +// a1.y[2] = a1.x[2]; +// a1.y[3] = a1.x[3]; +// a2.x = {4.0, 5.0, 6.0}; +// a2.y[1] = a2.x[1]; +// a2.y[2] = a2.x[2]; +// a2.y[3] = a2.x[3]; +// algorithm +// a1.x := fill(1.0, 3); +// end DumpFlatModel1; +// +// ######################################## +// simplify +// ######################################## +// +// class DumpFlatModel1 +// Real[3] a1.x; +// Real[3] a1.y; +// Real[3] a2.x; +// Real[3] a2.y; +// equation +// a1.x = {1.0, 2.0, 3.0}; +// a1.y[1] = a1.x[1]; +// a1.y[2] = a1.x[2]; +// a1.y[3] = a1.x[3]; +// a2.x = {4.0, 5.0, 6.0}; +// a2.y[1] = a2.x[1]; +// a2.y[2] = a2.x[2]; +// a2.y[3] = a2.x[3]; +// algorithm +// a1.x := {1.0, 1.0, 1.0}; +// end DumpFlatModel1; +// +// ######################################## +// scalarize +// ######################################## +// +// class DumpFlatModel1 +// Real a1.x[1]; +// Real a1.x[2]; +// Real a1.x[3]; +// Real a1.y[1]; +// Real a1.y[2]; +// Real a1.y[3]; +// Real a2.x[1]; +// Real a2.x[2]; +// Real a2.x[3]; +// Real a2.y[1]; +// Real a2.y[2]; +// Real a2.y[3]; +// equation +// a1.x = {1.0, 2.0, 3.0}; +// a1.y[1] = a1.x[1]; +// a1.y[2] = a1.x[2]; +// a1.y[3] = a1.x[3]; +// a2.x = {4.0, 5.0, 6.0}; +// a2.y[1] = a2.x[1]; +// a2.y[2] = a2.x[2]; +// a2.y[3] = a2.x[3]; +// algorithm +// a1.x := {1.0, 1.0, 1.0}; +// end DumpFlatModel1; +// +// class DumpFlatModel1 +// Real a1.x[1]; +// Real a1.x[2]; +// Real a1.x[3]; +// Real a1.y[1]; +// Real a1.y[2]; +// Real a1.y[3]; +// Real a2.x[1]; +// Real a2.x[2]; +// Real a2.x[3]; +// Real a2.y[1]; +// Real a2.y[2]; +// Real a2.y[3]; +// equation +// a1.x = {1.0, 2.0, 3.0}; +// a1.y[1] = a1.x[1]; +// a1.y[2] = a1.x[2]; +// a1.y[3] = a1.x[3]; +// a2.x = {4.0, 5.0, 6.0}; +// a2.y[1] = a2.x[1]; +// a2.y[2] = a2.x[2]; +// a2.y[3] = a2.x[3]; +// algorithm +// a1.x := {1.0, 1.0, 1.0}; +// end DumpFlatModel1; +// endResult diff --git a/testsuite/flattening/modelica/scodeinst/Makefile b/testsuite/flattening/modelica/scodeinst/Makefile index ab2d834369a..ba6edc97485 100644 --- a/testsuite/flattening/modelica/scodeinst/Makefile +++ b/testsuite/flattening/modelica/scodeinst/Makefile @@ -331,6 +331,7 @@ dim19.mo \ dim7.mo \ dim8.mo \ DerivedRootClass1.mo \ +DumpFlatModel1.mo \ DuplicateElements1.mo \ DuplicateElements2.mo \ DuplicateElements3.mo \ diff --git a/testsuite/openmodelica/bootstrapping/LoadCompilerSources.mos b/testsuite/openmodelica/bootstrapping/LoadCompilerSources.mos index 480ddfcbfe5..3968d86bbc7 100644 --- a/testsuite/openmodelica/bootstrapping/LoadCompilerSources.mos +++ b/testsuite/openmodelica/bootstrapping/LoadCompilerSources.mos @@ -47,7 +47,6 @@ if true then /* Suppress output */ prefixPath + "FrontEnd/NFEnvExtends.mo", prefixPath + "FrontEnd/NFInstPrefix.mo", prefixPath + "FrontEnd/NFInstTypes.mo", - prefixPath + "FrontEnd/NFInstUtil.mo", prefixPath + "FrontEnd/NFSCodeCheck.mo", prefixPath + "FrontEnd/NFSCodeDependency.mo", prefixPath + "FrontEnd/NFSCodeEnv.mo",