Skip to content

Commit

Permalink
add Clock synchronous features to the new front-end (NF), ticket:5127
Browse files Browse the repository at this point in the history
- currently only Clock operators are supported, no clock variables
- change the ugly
  intGe(Flags.getConfigEnum(Flags.LANGUAGE_STANDARD), 33);
  to
  Config.synchronousFeaturesAllowed();
- unbox external function arguments if __OpenModelica_UnboxArguments is present
  so that previous polymorphic definition in NFModelicaBuiltin.mo works fine
- do not simplify sum and other builtin operators if nfScalarize flag is disabled

Belonging to [master]:
  - OpenModelica/OMCompiler#2664
  • Loading branch information
adrpo authored and OpenModelica-Hudson committed Sep 17, 2018
1 parent 92b7fbb commit 09518b9
Show file tree
Hide file tree
Showing 20 changed files with 381 additions and 37 deletions.
2 changes: 1 addition & 1 deletion Compiler/BackEnd/BackendDAECreate.mo
Expand Up @@ -434,7 +434,7 @@ algorithm
// when equations
case DAE.WHEN_EQUATION(condition = e, equations = dae_elts)
algorithm
if intGe(Flags.getConfigEnum(Flags.LANGUAGE_STANDARD), 33) and Types.isClockOrSubTypeClock(Expression.typeof(e)) then
if Config.synchronousFeaturesAllowed() and Types.isClockOrSubTypeClock(Expression.typeof(e)) then

(outEqns, outVars, eq_attrs) := createWhenClock(whenClkCnt, e, outEqns, outVars);
whenClkCnt := whenClkCnt + 1;
Expand Down
2 changes: 1 addition & 1 deletion Compiler/FrontEnd/Ceval.mo
Expand Up @@ -1115,7 +1115,7 @@ algorithm
/*
case "Clock"
equation
true = intGe(Flags.getConfigEnum(Flags.LANGUAGE_STANDARD), 33);
true = Config.synchronousFeaturesAllowed();
then cevalBuiltinClock; */
// MetaModelica type conversions
case "intString" guard Config.acceptMetaModelicaGrammar() then cevalIntString;
Expand Down
3 changes: 2 additions & 1 deletion Compiler/FrontEnd/ClassInf.mo
Expand Up @@ -49,6 +49,7 @@ encapsulated package ClassInf
public import SCode;
public import Absyn;

protected import Config;
protected import Debug;
protected import Error;
protected import Flags;
Expand Down Expand Up @@ -432,7 +433,7 @@ algorithm
// BTH
case (SCode.R_PREDEFINED_CLOCK(),p)
equation
true = intGe(Flags.getConfigEnum(Flags.LANGUAGE_STANDARD), 33);
true = Config.synchronousFeaturesAllowed();
then TYPE_CLOCK(p);
case (SCode.R_PREDEFINED_ENUMERATION(),p) then TYPE_ENUM(p);
/* Meta Modelica extensions */
Expand Down
4 changes: 2 additions & 2 deletions Compiler/FrontEnd/Inst.mo
Expand Up @@ -1189,7 +1189,7 @@ algorithm
// BTH
case "Clock"
equation
true = intGe(Flags.getConfigEnum(Flags.LANGUAGE_STANDARD), 33);
true = Config.synchronousFeaturesAllowed();
then DAE.T_CLOCK_DEFAULT;
end match;
end getBasicTypeType;
Expand All @@ -1206,7 +1206,7 @@ algorithm
// BTH
case "Clock"
equation
true = intGe(Flags.getConfigEnum(Flags.LANGUAGE_STANDARD), 33);
true = Config.synchronousFeaturesAllowed();
then getClockAttributeType;
end match;
end getBasicTypeAttrTyper;
Expand Down
5 changes: 3 additions & 2 deletions Compiler/FrontEnd/InstStateMachineUtil.mo
Expand Up @@ -38,6 +38,7 @@ encapsulated package InstStateMachineUtil

public import DAE;

protected import Config;
protected import Flags;
protected import List;
protected import ComponentReference;
Expand Down Expand Up @@ -949,7 +950,7 @@ algorithm
case SCode.EQUATION(eEquation = SCode.EQ_NORETCALL(exp = Absyn.CALL(function_ =
Absyn.CREF_IDENT(name = name))))
then (name == "transition" or name == "initialState") and
intGe(Flags.getConfigEnum(Flags.LANGUAGE_STANDARD), 33);
Config.synchronousFeaturesAllowed();

else false;
end match;
Expand All @@ -967,7 +968,7 @@ algorithm

case DAE.NORETCALL(exp = DAE.CALL(path = Absyn.IDENT(name)))
then (name == "transition" or name == "initialState") and
intGe(Flags.getConfigEnum(Flags.LANGUAGE_STANDARD), 33);
Config.synchronousFeaturesAllowed();

else false;
end match;
Expand Down
16 changes: 8 additions & 8 deletions Compiler/FrontEnd/InstUtil.mo
Expand Up @@ -643,7 +643,7 @@ algorithm
// BTH
case (_, _, SCode.CLASS(name = "Clock"))
equation
true = intGe(Flags.getConfigEnum(Flags.LANGUAGE_STANDARD), 33);
true = Config.synchronousFeaturesAllowed();
then ();

// anything else, check for equality!
Expand All @@ -665,7 +665,7 @@ algorithm
case("String") then true;
case("Boolean") then true;
// BTH
case("Clock") then intGe(Flags.getConfigEnum(Flags.LANGUAGE_STANDARD), 33);
case("Clock") then Config.synchronousFeaturesAllowed();
else false;
end match;
end isBuiltInClass;
Expand Down Expand Up @@ -857,7 +857,7 @@ algorithm
//BTH same as above but extended with Clock type if Flags.SYNCHRONOUS_FEATURES == true
case (_, _, _, r, {SCode.EXTENDS(baseClassPath=Absyn.IDENT(id))})
equation
true = intGe(Flags.getConfigEnum(Flags.LANGUAGE_STANDARD), 33);
true = Config.synchronousFeaturesAllowed();
true = listMember(r, {SCode.R_TYPE(), SCode.R_CONNECTOR(false), SCode.R_CONNECTOR(true)});
true = listMember(id, {"Real", "Integer", "Boolean", "String", "Clock"});
then ();
Expand Down Expand Up @@ -896,12 +896,12 @@ protected
list<SCode.Restriction> rstLst;
algorithm
// BTH add Clock type to both lists if Flags.SYNCHRONOUS_FEATURES == true
strLst := if intGe(Flags.getConfigEnum(Flags.LANGUAGE_STANDARD), 33)
strLst := if Config.synchronousFeaturesAllowed()
then {"Real", "Integer", "String", "Boolean", "Clock"}
else {"Real", "Integer", "String", "Boolean"};
b1 := listMember(childName, strLst);

rstLst := if intGe(Flags.getConfigEnum(Flags.LANGUAGE_STANDARD), 33)
rstLst := if Config.synchronousFeaturesAllowed()
then {SCode.R_TYPE(), SCode.R_PREDEFINED_INTEGER(), SCode.R_PREDEFINED_REAL(), SCode.R_PREDEFINED_STRING(), SCode.R_PREDEFINED_BOOLEAN(), SCode.R_PREDEFINED_CLOCK()}
else {SCode.R_TYPE(), SCode.R_PREDEFINED_INTEGER(), SCode.R_PREDEFINED_REAL(), SCode.R_PREDEFINED_STRING(), SCode.R_PREDEFINED_BOOLEAN()};
b2 := listMember(childRestriction, rstLst);
Expand Down Expand Up @@ -3304,7 +3304,7 @@ algorithm
// BTH
case (cache, _, _, _, cl as SCode.CLASS(name = "Clock"), _, _)
equation
true = intGe(Flags.getConfigEnum(Flags.LANGUAGE_STANDARD), 33);
true = Config.synchronousFeaturesAllowed();
then (cache,{},cl,DAE.NOMOD());

case (cache, _, _, _, cl as SCode.CLASS(restriction = SCode.R_RECORD(_),
Expand Down Expand Up @@ -7378,15 +7378,15 @@ algorithm
// you cannot redeclare a basic type, only the properties and the binding, i.e.
// redeclare constant Boolean standardOrderComponents = true
case DAE.REDECL(element = SCode.COMPONENT(typeSpec=Absyn.TPATH(path=path))) equation
true = intGe(Flags.getConfigEnum(Flags.LANGUAGE_STANDARD), 33);
true = Config.synchronousFeaturesAllowed();

name = Absyn.pathFirstIdent(path);
// BTH
true = listMember(name, {"Real", "Integer", "Boolean", "String", "Clock"});
then true;

case DAE.REDECL(element = SCode.COMPONENT(typeSpec=Absyn.TPATH(path=path))) equation
false = intGe(Flags.getConfigEnum(Flags.LANGUAGE_STANDARD), 33);
false = Config.synchronousFeaturesAllowed();

name = Absyn.pathFirstIdent(path);
// BTH
Expand Down
3 changes: 2 additions & 1 deletion Compiler/FrontEnd/NFSCodeLookup.mo
Expand Up @@ -45,6 +45,7 @@ public import NFInstPrefix;
public import SCode;
public import NFSCodeEnv;

protected import Config;
protected import Debug;
protected import NFEnvExtends;
protected import Flags;
Expand Down Expand Up @@ -1266,7 +1267,7 @@ algorithm
case "ExternalObject" then BUILTIN_EXTERNALOBJECT;
case "Clock"
equation
true = intGe(Flags.getConfigEnum(Flags.LANGUAGE_STANDARD), 33);
true = Config.synchronousFeaturesAllowed();
then BUILTIN_CLOCK;
case "$RealType" then BUILTIN_REALTYPE_ITEM;
case "$IntegerType" then BUILTIN_INTEGERTYPE_ITEM;
Expand Down
20 changes: 10 additions & 10 deletions Compiler/FrontEnd/Static.mo
Expand Up @@ -6520,43 +6520,43 @@ algorithm
case "DynamicSelect" then elabBuiltinDynamicSelect;
case "Clock"
equation
true = intGe(Flags.getConfigEnum(Flags.LANGUAGE_STANDARD), 33);
true = Config.synchronousFeaturesAllowed();
then elabBuiltinClock;
case "hold"
equation
true = intGe(Flags.getConfigEnum(Flags.LANGUAGE_STANDARD), 33);
true = Config.synchronousFeaturesAllowed();
then elabBuiltinHold;
case "shiftSample"
equation
true = intGe(Flags.getConfigEnum(Flags.LANGUAGE_STANDARD), 33);
true = Config.synchronousFeaturesAllowed();
then elabBuiltinShiftSample;
case "backSample"
equation
true = intGe(Flags.getConfigEnum(Flags.LANGUAGE_STANDARD), 33);
true = Config.synchronousFeaturesAllowed();
then elabBuiltinBackSample;
case "noClock"
equation
true = intGe(Flags.getConfigEnum(Flags.LANGUAGE_STANDARD), 33);
true = Config.synchronousFeaturesAllowed();
then elabBuiltinNoClock;
case "transition"
equation
true = intGe(Flags.getConfigEnum(Flags.LANGUAGE_STANDARD), 33);
true = Config.synchronousFeaturesAllowed();
then elabBuiltinTransition;
case "initialState"
equation
true = intGe(Flags.getConfigEnum(Flags.LANGUAGE_STANDARD), 33);
true = Config.synchronousFeaturesAllowed();
then elabBuiltinInitialState;
case "activeState"
equation
true = intGe(Flags.getConfigEnum(Flags.LANGUAGE_STANDARD), 33);
true = Config.synchronousFeaturesAllowed();
then elabBuiltinActiveState;
case "ticksInState"
equation
true = intGe(Flags.getConfigEnum(Flags.LANGUAGE_STANDARD), 33);
true = Config.synchronousFeaturesAllowed();
then elabBuiltinTicksInState;
case "timeInState"
equation
true = intGe(Flags.getConfigEnum(Flags.LANGUAGE_STANDARD), 33);
true = Config.synchronousFeaturesAllowed();
then elabBuiltinTimeInState;
case "sourceInfo"
equation
Expand Down
36 changes: 36 additions & 0 deletions Compiler/NFFrontEnd/NFBuiltin.mo
Expand Up @@ -105,6 +105,11 @@ encapsulated package Elements
SCode.PARTS({}, {}, {}, {}, {}, {}, {}, NONE()),
SCode.noComment, Absyn.dummyInfo);

constant SCode.Element CLOCK = SCode.CLASS("Clock",
SCode.defaultPrefixes, SCode.NOT_ENCAPSULATED(), SCode.NOT_PARTIAL(), SCode.R_PREDEFINED_CLOCK(),
SCode.PARTS({}, {}, {}, {}, {}, {}, {}, NONE()),
SCode.noComment, Absyn.dummyInfo) "the Clock type";

end Elements;

// An empty InstNode cache for the builtin types. This should really be an empty
Expand Down Expand Up @@ -315,6 +320,37 @@ constant Expression ASSERTIONLEVEL_ERROR = Expression.ENUM_LITERAL(
constant Expression ASSERTIONLEVEL_WARNING = Expression.ENUM_LITERAL(
ASSERTIONLEVEL_TYPE, "error", 2);

// Lookup tree for Clock. Generated by makeBuiltinLookupTree.
constant LookupTree.Tree CLOCK_LOOKUP_TREE = LookupTree.Tree.NODE(
key = "quantity", value = LookupTree.Entry.COMPONENT(index = 1), height = 2,
left = LookupTree.Tree.LEAF(
key = "fixed", value = LookupTree.Entry.COMPONENT(index = 3)),
right = LookupTree.Tree.LEAF(
key = "start", value = LookupTree.Entry.COMPONENT(index = 2)));

constant ClassTree CLOCK_CLASS_TREE = ClassTree.FLAT_TREE(
CLOCK_LOOKUP_TREE,
listArrayLiteral({}),
listArrayLiteral({
InstNode.COMPONENT_NODE("quantity", Visibility.PUBLIC,
Pointer.createImmutable(Component.TYPE_ATTRIBUTE(Type.STRING(), Modifier.NOMOD())), InstNode.EMPTY_NODE()),
InstNode.COMPONENT_NODE("start", Visibility.PUBLIC,
Pointer.createImmutable(Component.TYPE_ATTRIBUTE(Type.CLOCK(), Modifier.NOMOD())), InstNode.EMPTY_NODE()),
InstNode.COMPONENT_NODE("fixed", Visibility.PUBLIC,
Pointer.createImmutable(Component.TYPE_ATTRIBUTE(Type.CLOCK(), Modifier.NOMOD())), InstNode.EMPTY_NODE())
}),
listArray({}), // TODO: #4895: This should be listArrayLiteral too, but causes compilation issues.
DuplicateTree.EMPTY());

constant InstNode CLOCK_NODE = InstNode.CLASS_NODE("Clock",
Elements.CLOCK, Visibility.PUBLIC,
Pointer.createImmutable(
Class.PARTIAL_BUILTIN(Type.CLOCK(), CLOCK_CLASS_TREE, Modifier.NOMOD(), Restriction.CLOCK())),
EMPTY_NODE_CACHE, InstNode.EMPTY_NODE(), InstNodeType.BUILTIN_CLASS());

constant ComponentRef CLOCK_CREF =
ComponentRef.CREF(CLOCK_NODE, {}, Type.CLOCK(), Origin.CREF, ComponentRef.EMPTY());

constant InstNode TIME =
InstNode.COMPONENT_NODE("time",
Visibility.PUBLIC,
Expand Down
99 changes: 99 additions & 0 deletions Compiler/NFFrontEnd/NFBuiltinCall.mo
Expand Up @@ -40,6 +40,7 @@ encapsulated package NFBuiltinCall
import Type = NFType;

protected
import Config;
import Ceval = NFCeval;
import ComponentRef = NFComponentRef;
import Dimension = NFDimension;
Expand Down Expand Up @@ -132,6 +133,18 @@ public
case "transpose" then typeTransposeCall(call, origin, info);
case "vector" then typeVectorCall(call, origin, info);
case "zeros" then typeZerosOnesCall("zeros", call, origin, info);
case "Clock" guard Config.synchronousFeaturesAllowed() then typeClockCall(call, origin, info);
/*
case "hold" guard Config.synchronousFeaturesAllowed() then typeHoldCall(call, origin, info);
case "shiftSample" guard Config.synchronousFeaturesAllowed() then typeShiftSampleCall(call, origin, info);
case "backSample" guard Config.synchronousFeaturesAllowed() then typeBackSampleCall(call, origin, info);
case "noClock" guard Config.synchronousFeaturesAllowed() then typeNoClockCall(call, origin, info);
case "transition" guard Config.synchronousFeaturesAllowed() then typeTransitionCall(call, origin, info);
case "initialState" guard Config.synchronousFeaturesAllowed() then typeInitialStateCall(call, origin, info);
case "activeState" guard Config.synchronousFeaturesAllowed() then typeActiveStateCall(call, origin, info);
case "ticksInState" guard Config.synchronousFeaturesAllowed() then typeTicksInStateCall(call, origin, info);
case "timeInState" guard Config.synchronousFeaturesAllowed() then typeTimeInStateCall(call, origin, info);
*/
else
algorithm
Error.assertion(false, getInstanceName() + " got unhandled builtin function: " + Call.toString(call), sourceInfo());
Expand Down Expand Up @@ -1600,5 +1613,91 @@ protected
result := Expression.STRING(Absyn.pathString(InstNode.scopePath(scope, includeRoot = true)));
end typeGetInstanceName;

function typeClockCall
input Call call;
input ExpOrigin.Type origin;
input SourceInfo info;
output Expression callExp;
output Type outType;
output Variability var;
protected
Type arg_ty;
list<TypedArg> args;
list<TypedNamedArg> named_args;
Call ty_call;
Expression e, e1, e2;
Type t, t1, t2;
Variability v, v1, v2;
algorithm
ty_call as Call.ARG_TYPED_CALL(_, args, named_args) := Call.typeNormalCall(call, origin, info);
(callExp, outType, var) := match(args, named_args)
// Clock() - inferred clock
case ({}, {})
then (Expression.CLKCONST(Expression.ClockKind.INFERRED_CLOCK()), Type.CLOCK(), Variability.PARAMETER);
// Clock(intervalCounter) - integer clock
case ({(e, Type.INTEGER(), v)}, {})
then (Expression.CLKCONST(Expression.INTEGER_CLOCK(e, Expression.INTEGER(1))), Type.CLOCK(), Variability.PARAMETER);
// Clock(intervalCounter, resolution) - integer clock
case ({(e, Type.INTEGER(), v), (e1, Type.REAL(), v1)}, {})
algorithm
e2 := Ceval.evalExp(e1);
Error.assertionOrAddSourceMessage(Expression.integerValue(e2) >= 1,
Error.WRONG_VALUE_OF_ARG, {"Clock", "resolution", Expression.toString(e2), ">= 1"}, info);
then
(Expression.CLKCONST(Expression.INTEGER_CLOCK(e, e2)), Type.CLOCK(), Variability.PARAMETER);
// Clock(intervalCounter, resolution=expression) - integer clock
case ({(e, Type.INTEGER(), v)}, {("resolution", e1, Type.REAL(), v1)})
algorithm
e2 := Ceval.evalExp(e1);
Error.assertionOrAddSourceMessage(Expression.integerValue(e2) >= 1,
Error.WRONG_VALUE_OF_ARG, {"Clock", "resolution", Expression.toString(e2), ">= 1"}, info);
then
(Expression.CLKCONST(Expression.INTEGER_CLOCK(e, e2)), Type.CLOCK(), Variability.PARAMETER);
// Clock(interval) - real clock
case ({(e, Type.REAL(), v)}, {})
then
(Expression.CLKCONST(Expression.REAL_CLOCK(e)), Type.CLOCK(), Variability.PARAMETER);
// Clock(condition) - boolean clock
case ({(e, Type.BOOLEAN(), v)}, {})
then
(Expression.CLKCONST(Expression.BOOLEAN_CLOCK(e, Expression.REAL(0.0))), Type.CLOCK(), Variability.PARAMETER);
// Clock(condition, startInterval) - boolean clock
case ({(e, Type.BOOLEAN(), v), (e1, Type.REAL(), v1)}, {})
algorithm
e2 := Ceval.evalExp(e1);
Error.assertionOrAddSourceMessage(Expression.realValue(e2) > 0.0,
Error.WRONG_VALUE_OF_ARG, {"Clock", "startInterval", Expression.toString(e2), "> 0.0"}, info);
then
(Expression.CLKCONST(Expression.BOOLEAN_CLOCK(e, e2)), Type.CLOCK(), Variability.PARAMETER);
// Clock(condition, startInterval=expression) - boolean clock
case ({(e, Type.BOOLEAN(), v)}, {("startInterval", e1, Type.REAL(), v1)})
algorithm
e2 := Ceval.evalExp(e1);
Error.assertionOrAddSourceMessage(Expression.realValue(e2) > 0.0,
Error.WRONG_VALUE_OF_ARG, {"Clock", "startInterval", Expression.toString(e2), "> 0.0"}, info);
then
(Expression.CLKCONST(Expression.BOOLEAN_CLOCK(e, e2)), Type.CLOCK(), Variability.PARAMETER);
// Clock(c, solverMethod) - solver clock
case ({(e, Type.CLOCK(), v), (e1, Type.STRING(), v1)}, {})
algorithm
e2 := Ceval.evalExp(e1);
then
(Expression.CLKCONST(Expression.SOLVER_CLOCK(e, e2)), Type.CLOCK(), Variability.PARAMETER);

// Clock(c, solverMethod=string) - solver clock
case ({(e, Type.CLOCK(), v)}, {("solverMethod", e1, Type.STRING(), v1)})
algorithm
e2 := Ceval.evalExp(e1);
then
(Expression.CLKCONST(Expression.SOLVER_CLOCK(e, e2)), Type.CLOCK(), Variability.PARAMETER);

else
algorithm
Error.addSourceMessage(Error.WRONG_TYPE_OR_NO_OF_ARGS, {Call.toString(call), "<NO COMPONENT>"}, info);
then
fail();
end match;
end typeClockCall;

annotation(__OpenModelica_Interface="frontend");
end NFBuiltinCall;

0 comments on commit 09518b9

Please sign in to comment.