Skip to content

Commit 16f643d

Browse files
authored
Simplify --exposeLocalIOs and conform to Modelica standard (#10599) (#12385)
* Simplify --exposeLocalIOs and conform to Modelica standard (#10599) (#12303) Add top-level variables for unconnected local IOs. Only NFFlatten.mo and NFConnectEquations.mo are extended. Untouch backend as well as NFFlatModel.mo and NFVariable.mo. * Use quoted names for variables introduced with --exposeLocalIOs (#12348) This way the newly introduced global variables keep the name of the previously exposed local variables, besides quotes. See #10599 and #12346. * Treat components in top-level connectors with --exposeLocalIOs (#10599) (#12384) Identify top-level IOs using the same function removeNonTopLevelDirection that will be called later on.
1 parent aa27cc1 commit 16f643d

File tree

8 files changed

+231
-98
lines changed

8 files changed

+231
-98
lines changed

OMCompiler/Compiler/BackEnd/BackendDAECreate.mo

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1589,12 +1589,7 @@ algorithm
15891589
else
15901590
algorithm
15911591
/* Consider toplevel inputs as known unless they are protected. Ticket #5591 */
1592-
/* Consider all inputs known with flag --nonStdExposeLocalIOs > 0 unless they are protected */
1593-
if Flags.getConfigInt(Flags.EXPOSE_LOCAL_IOS) == 0 then
1594-
false := DAEUtil.topLevelInput(inComponentRef, inVarDirection, inConnectorType, protection);
1595-
else
1596-
false := DAEUtil.varDirectionEqual(inVarDirection, DAE.INPUT()) and not DAEUtil.boolVarVisibility(protection);
1597-
end if;
1592+
false := DAEUtil.topLevelInput(inComponentRef, inVarDirection, inConnectorType, protection);
15981593
then
15991594
match (inVarKind, inType)
16001595
case (DAE.VARIABLE(), DAE.T_BOOL()) then BackendDAE.DISCRETE();
@@ -1622,11 +1617,7 @@ algorithm
16221617
case DAE.CONST() then BackendDAE.CONST();
16231618
case DAE.VARIABLE()
16241619
equation
1625-
if Flags.getConfigInt(Flags.EXPOSE_LOCAL_IOS) == 0 then
1626-
true = DAEUtil.topLevelInput(componentRef, varDirection, connectorType, visibility);
1627-
else
1628-
true = DAEUtil.varDirectionEqual(varDirection, DAE.INPUT()) and not DAEUtil.boolVarVisibility(visibility);
1629-
end if;
1620+
true = DAEUtil.topLevelInput(componentRef, varDirection, connectorType, visibility);
16301621
then
16311622
BackendDAE.VARIABLE();
16321623
// adrpo: topLevelInput might fail!

OMCompiler/Compiler/BackEnd/BackendVariable.mo

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2027,15 +2027,15 @@ end getVarKindForVar;
20272027

20282028
public function isVarOnTopLevelAndOutput "has the DAE.VarDirection = OUTPUT
20292029
Don't check for top level here as this is done by NFConvertDAE.makeDAEVar.
2030-
Otherwise the list of model variables may contradict with model structure, e.g. with --nonStdExposeLocalIOs."
2030+
Otherwise the list of model variables may contradict with model structure."
20312031
input BackendDAE.Var inVar;
20322032
//output Boolean outBoolean = DAEUtil.topLevelOutput(inVar.varName, inVar.varDirection, inVar.connectorType);
20332033
output Boolean outBoolean = isOutputVar(inVar);
20342034
end isVarOnTopLevelAndOutput;
20352035

20362036
public function isVarOnTopLevelAndInput "has the DAE.VarDirection = INPUT
20372037
Don't check for top level here as this is done by NFConvertDAE.makeDAEVar.
2038-
Otherwise the list of model variables may contradict with model structure, e.g. with --nonStdExposeLocalIOs."
2038+
Otherwise the list of model variables may contradict with model structure."
20392039
input BackendDAE.Var inVar;
20402040
//output Boolean outBoolean = DAEUtil.topLevelInput(inVar.varName, inVar.varDirection, inVar.connectorType);
20412041
output Boolean outBoolean = isInput(inVar);

OMCompiler/Compiler/NFFrontEnd/NFConnectEquations.mo

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ algorithm
212212
if Connector.variability(c1) > Variability.PARAMETER then
213213
equations := list(makeEqualityEquation(c1.name, c1.source, c2.name, c2.source)
214214
for c2 in listRest(elements));
215-
// collect inputs and outputs that are inside in connections if --nonStdExposeLocalIOs > 0
215+
// collect inputs and outputs that are inside in connections if --exposeLocalIOs > 0
216216
// strip array indices so that the variables will be found later
217217
if Flags.getConfigInt(Flags.EXPOSE_LOCAL_IOS) > 0 then
218218
for c in elements loop

OMCompiler/Compiler/NFFrontEnd/NFFlatModel.mo

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1045,16 +1045,13 @@ public
10451045

10461046
function removeNonTopLevelDirections
10471047
input output FlatModel flatModel;
1048-
protected
1049-
Integer expose_local_ios;
10501048
algorithm
10511049
// Keep the declared directions if --useLocalDirection=true has been set.
10521050
if Flags.getConfigBool(Flags.USE_LOCAL_DIRECTION) then
10531051
return;
10541052
end if;
10551053

1056-
expose_local_ios := Flags.getConfigInt(Flags.EXPOSE_LOCAL_IOS);
1057-
flatModel.variables := list(Variable.removeNonTopLevelDirection(v, expose_local_ios) for v in flatModel.variables);
1054+
flatModel.variables := list(Variable.removeNonTopLevelDirection(v) for v in flatModel.variables);
10581055
end removeNonTopLevelDirections;
10591056

10601057
annotation(__OpenModelica_Interface="frontend");

OMCompiler/Compiler/NFFrontEnd/NFFlatten.mo

Lines changed: 59 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ import Face = NFConnector.Face;
7979
import System;
8080
import ComplexType = NFComplexType;
8181
import NFInstNode.CachedData;
82-
import NFPrefixes.{Direction, Variability, Visibility, Purity, Parallelism};
82+
import NFPrefixes.{ConnectorType, Direction, Variability, Visibility, Purity, Parallelism};
8383
import Variable = NFVariable;
8484
import ElementSource;
8585
import Ceval = NFCeval;
@@ -2183,13 +2183,15 @@ function resolveConnections
21832183
input FlattenSettings settings;
21842184
protected
21852185
Connections conns;
2186-
list<Equation> conn_eql, ec_eql;
2186+
list<Equation> conn_eql, ec_eql, tlio_eql;
2187+
list<Variable> tlio_vars;
21872188
ConnectionSets.Sets csets;
21882189
array<list<Connector>> csets_array;
21892190
CardinalityTable.Table ctable;
21902191
Connections.BrokenEdges broken = {};
21912192
UnorderedMap<ComponentRef, Variable> vars;
21922193
UnorderedSet<ComponentRef> connectedLocalIOs;
2194+
Integer exposeLocalIOs;
21932195
algorithm
21942196
vars := UnorderedMap.new<Variable>(ComponentRef.hash, ComponentRef.isEqual,
21952197
listLength(flatModel.variables));
@@ -2240,9 +2242,12 @@ algorithm
22402242
// add the equations to the flat model
22412243
flatModel.equations := listAppend(conn_eql, flatModel.equations);
22422244

2243-
// remove input and output prefixes from local IOs that are determined through connect equations
2244-
if Flags.getConfigInt(Flags.EXPOSE_LOCAL_IOS) > 0 then
2245-
flatModel.variables := list(stripInputOutputForConnected(v, connectedLocalIOs) for v in flatModel.variables);
2245+
// add top-level IOs for unconnected local IOs
2246+
exposeLocalIOs := Flags.getConfigInt(Flags.EXPOSE_LOCAL_IOS);
2247+
if exposeLocalIOs > 0 then
2248+
(tlio_vars, tlio_eql) := generateTopLevelIOs(vars, connectedLocalIOs, exposeLocalIOs);
2249+
flatModel.variables := List.append_reverse(flatModel.variables, tlio_vars);
2250+
flatModel.equations := List.append_reverse(flatModel.equations, tlio_eql);
22462251
end if;
22472252

22482253
// Evaluate any connection operators if they're used.
@@ -2253,18 +2258,56 @@ algorithm
22532258
execStat(getInstanceName());
22542259
end resolveConnections;
22552260

2256-
function stripInputOutputForConnected
2257-
"remove input and output prefixes if variable appears in connectedIOs"
2258-
input output Variable v;
2259-
input UnorderedSet<ComponentRef> connectedIOs;
2261+
function generateTopLevelIOs
2262+
"generate top-level inputs and outputs for public unconnected local input and output connectors"
2263+
input UnorderedMap<ComponentRef, Variable> variables;
2264+
input UnorderedSet<ComponentRef> connectedLocalIOs;
2265+
input Integer exposeLocalIOs;
2266+
output list<Variable> tlio_vars;
2267+
output list<Equation> tlio_eql;
22602268
protected
2261-
Attributes attributes = v.attributes;
2262-
algorithm
2263-
if UnorderedSet.contains(v.name, connectedIOs) then
2264-
attributes.direction := Direction.NONE;
2265-
v.attributes := attributes;
2266-
end if;
2267-
end stripInputOutputForConnected;
2269+
Attributes attributes;
2270+
Variable tlio_var;
2271+
ComponentRef cref;
2272+
String name;
2273+
InstNode tlio_node;
2274+
Integer level;
2275+
algorithm
2276+
tlio_vars := {};
2277+
tlio_eql := {};
2278+
for variable in UnorderedMap.valueList(variables) loop
2279+
level := ComponentRef.depth(variable.name) - 1;
2280+
attributes := variable.attributes;
2281+
if 0 < level and level <= exposeLocalIOs and
2282+
variable.visibility == Visibility.PUBLIC and
2283+
attributes.connectorType <> ConnectorType.NON_CONNECTOR and
2284+
(attributes.direction == Direction.INPUT or attributes.direction == Direction.OUTPUT) and
2285+
not UnorderedSet.contains(variable.name, connectedLocalIOs)
2286+
then
2287+
// add a new variable and equation if removeNonTopLevelDirection removes the direction
2288+
tlio_var := Variable.removeNonTopLevelDirection(variable);
2289+
attributes := tlio_var.attributes;
2290+
if attributes.direction == Direction.NONE then
2291+
tlio_var := variable; // same attributes like start, unit
2292+
tlio_var.name := ComponentRef.combineSubscripts(tlio_var.name);
2293+
tlio_var.binding := UNBOUND(); // value is defined with tlio_eql
2294+
// find new name in global scope, starting with quoted identifier
2295+
cref := tlio_var.name;
2296+
name := stringDelimitList(ComponentRef.toString_impl(cref, {}), ".");
2297+
while UnorderedMap.contains(tlio_var.name, variables) loop
2298+
tlio_node := InstNode.NAME_NODE(Util.makeQuotedIdentifier(name));
2299+
tlio_var.name := match cref case ComponentRef.CREF() then
2300+
ComponentRef.CREF(tlio_node, cref.subscripts, cref.ty, cref.origin, ComponentRef.EMPTY());
2301+
end match;
2302+
name := name + "_" "append underscore until name is unique";
2303+
end while;
2304+
tlio_vars := tlio_var :: tlio_vars;
2305+
tlio_eql := Equation.makeCrefEquality(variable.name, tlio_var.name,
2306+
InstNode.EMPTY_NODE(), ElementSource.createElementSource(variable.info)) :: tlio_eql;
2307+
end if;
2308+
end if;
2309+
end for;
2310+
end generateTopLevelIOs;
22682311

22692312
function evaluateConnectionOperators
22702313
input output FlatModel flatModel;

OMCompiler/Compiler/NFFrontEnd/NFVariable.mo

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -417,11 +417,8 @@ public
417417
function removeNonTopLevelDirection
418418
"Removes input/output prefixes from a variable that's not a top-level
419419
component, a component in a top-level connector, or a component in a
420-
top-level input component. exposeLocalIOs can be used to keep the direction
421-
for variables at lower levels as well, where 0 means top-level, 1 the level
422-
below that, and so on."
420+
top-level input component."
423421
input output Variable var;
424-
input Integer exposeLocalIOs;
425422
protected
426423
ComponentRef rest_name;
427424
InstNode node;
@@ -431,13 +428,6 @@ public
431428
return;
432429
end if;
433430

434-
if exposeLocalIOs > 0 and
435-
var.attributes.connectorType <> ConnectorType.NON_CONNECTOR and
436-
var.visibility == Visibility.PUBLIC and
437-
ComponentRef.depth(var.name) < exposeLocalIOs then
438-
return;
439-
end if;
440-
441431
rest_name := ComponentRef.rest(var.name);
442432
while not ComponentRef.isEmpty(rest_name) loop
443433
node := ComponentRef.node(rest_name);

OMCompiler/Compiler/Util/Flags.mo

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1444,11 +1444,11 @@ constant ConfigFlag FRONTEND_INLINE = CONFIG_FLAG(151, "frontendInline",
14441444
NONE(), EXTERNAL(), BOOL_FLAG(false), NONE(),
14451445
Gettext.gettext("Enables inlining of functions in the frontend."));
14461446

1447-
constant ConfigFlag EXPOSE_LOCAL_IOS = CONFIG_FLAG(152, "nonStdExposeLocalIOs",
1447+
constant ConfigFlag EXPOSE_LOCAL_IOS = CONFIG_FLAG(152, "exposeLocalIOs",
14481448
NONE(), EXTERNAL(), INT_FLAG(0), NONE(),
1449-
Gettext.gettext("Keeps input/output prefixes for unconnected input/output connectors at requested levels, provided they are public, " +
1449+
Gettext.gettext("Introduces top-level inputs/outputs for unconnected input/output connectors at requested levels, provided they are public, " +
14501450
"0 meaning top-level (standard Modelica), 1 inputs/outputs of top-level components, >1 going deeper. " +
1451-
"This flag is particularly useful for FMI export. It extends the Modelica standard when exposing local inputs."));
1451+
"This flag is particularly useful for FMI export."));
14521452

14531453
function getFlags
14541454
"Loads the flags with getGlobalRoot. Assumes flags have been loaded."

0 commit comments

Comments
 (0)