From 6d72b4b68a44e806c1bc45165cf0b8d6bff5e9b7 Mon Sep 17 00:00:00 2001 From: Peter Aronsson Date: Fri, 18 Nov 2005 12:38:07 +0000 Subject: [PATCH] Standard math functions in Modelica.Math are not evaluated instead of compiled and run in Ceval.rml git-svn-id: https://openmodelica.org/svn/OpenModelica/trunk@1975 f25d12d1-65f4-0310-ae8a-bbce733d8d8e --- Compiler/Ceval.rml | 173 ++++++++++++++++++++++++------- Compiler/SimCodegen.rml | 21 +++- Compiler/Static.rml | 9 ++ Compiler/System.rml | 41 ++++++++ Compiler/runtime/systemimpl.c | 43 ++++++++ Compiler/winruntime/systemimpl.c | 43 ++++++++ 6 files changed, 293 insertions(+), 37 deletions(-) diff --git a/Compiler/Ceval.rml b/Compiler/Ceval.rml index f72235a7e42..e0bc19bd774 100644 --- a/Compiler/Ceval.rml +++ b/Compiler/Ceval.rml @@ -91,7 +91,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. bool, (*impl*) Msg) => Exp.Subscript list - + + relation is_known_external_func:( string, string option) => () end @@ -319,49 +320,18 @@ end => (Values.REAL(resr),st'') - - (* FIXME: disabled calling of functions during ceval for now. Some - * functions call other functions, which must be generated together in - * order that compilation works *) - (* - axiom ceval (env, e as Exp.CALL(funcpath,expl,_,builtin as false),impl as false,st as NONE,_) => fail - *) - - (* Call functions in non-interactive mode. *) + (* Call functions *) (* FIXME: functions are always generated. Put back the check and write another rule for the false case that generates the function *) rule ceval_list(env,expl,impl,st,msg) => vallst & ceval_call_function (env,e,vallst,msg) => newval ------------------------------------------------------- - ceval (env, e as Exp.CALL(funcpath,expl,_,builtin as false),impl as false,st as NONE,_,msg) => (newval,st) - - (* ceval (env, e as Exp.CALL(funcpath,expl,_,_),false,st as SOME(Interactive.SYMBOLTABLE(_,_,_,_,cflist)),_) => (newval,st) - *) - - - (* FIXME: Fix this in order to allow calling of constant-marked function - * calls. One should call the function as if we were in interactive - * mode, and put the result instead of the function call *) - - (* + ceval (env, e as Exp.CALL(funcpath,expl,_,builtin),impl,st,_,msg) + => (newval,st) - rule Print.print_buf "# Can't call builtin functions at compile time\n" & - Print.print_buf " expression: " & Exp.print_exp e & Print.print_buf "\n" - ------------------------------------------------------- - ceval (env, e as Exp.CALL(_,_,_,builtin as true),impl as false,NONE,_) => fail - *) - - rule Print.print_buf "# Can't call functions at compile time\n" & - Print.print_buf " expression: " & Exp.print_exp e & Print.print_buf "\n" - ------------------------------------------------------- - ceval (env, e as Exp.CALL(_,_,_,_),impl as false,NONE,_,MSG) => fail axiom ceval (env, e as Exp.CALL(_,_,_,_),impl as false,NONE,_,NO_MSG) => fail - rule (* Print.print_buf "implicit evaluation of function calls without symbol table, exp: " & - Exp.print_exp e & Print.print_buf "\n" *) - ------------------------------------------- - ceval(env, e as Exp.CALL(_,_,_,_),impl as true,NONE,_,_) => fail rule ceval_interactive_functions(env,e,st,msg) => (value,st) ------------------------------------- @@ -720,7 +690,14 @@ relation ceval_call_function : (Env.Env, Values.Value list, (* input parameter values*) Msg) (* Should error messages be printed. *) => Values.Value (* resulting value *) = - + (* External functions that are "known" should be evaluated without + * compilation, e.g. all math functions *) + rule ceval_known_external_funcs(env,funcpath,vallst,msg) => newval + ------------------------------------------------------- + ceval_call_function (env, e as Exp.CALL(funcpath,expl,_,builtin), + vallst,msg) => newval + + (* Call functions in non-interactive mode. *) (* FIXME: functions are always generated. Put back the check and write another rule for the false case that generates the function *) @@ -744,6 +721,130 @@ relation ceval_call_function : (Env.Env, end + +(** relation: ceval_known_external_funcs + ** + ** Evaluates external functions that are known, e.g. all math functions. + **) +relation ceval_known_external_funcs: (Env.Env, + Absyn.Path, + Values.Value list, + Msg) => Values.Value = + + rule Lookup.lookup_class(env,funcpath,false) => (cdef,env') & + let SCode.CLASS(fid,_,_,SCode.R_EXT_FUNCTION,SCode.PARTS(_,_,_,_,_,extdecl)) = cdef & + let SOME(Absyn.EXTERNALDECL(id,lan,out,args,_)) = extdecl & + is_known_external_func(fid,id) & + ceval_known_external_funcs2(fid,id,vals,msg) => res + ----------------------------- + ceval_known_external_funcs(env,funcpath,vals,msg) => res +end + +(** relation is_known_external_func + ** + ** Succeds if external function name is "known", i.e. no compilation + ** required. +**) + +relation is_known_external_func:( SCode.Ident, Absyn.Ident option) => () = + + axiom is_known_external_func("acos",SOME("acos")) + axiom is_known_external_func("asin",SOME("asin")) + axiom is_known_external_func("atan",SOME("atan")) + axiom is_known_external_func("atan2",SOME("atan2")) + axiom is_known_external_func("cos",SOME("cos")) + axiom is_known_external_func("cosh",SOME("cosh")) + axiom is_known_external_func("exp",SOME("exp")) + axiom is_known_external_func("log",SOME("log")) + axiom is_known_external_func("log10",SOME("log10")) + axiom is_known_external_func("sin",SOME("sin")) + axiom is_known_external_func("sinh",SOME("sinh")) + axiom is_known_external_func("tan",SOME("tan")) + axiom is_known_external_func("tanh",SOME("tanh")) +end + + +(** relation: ceval_known_external_funcs2 + ** author: PA + ** + ** Helper relation to ceval_known_external_funcs, does the evaluation. + **) + +relation ceval_known_external_funcs2: (SCode.Ident, + Absyn.Ident option, + Values.Value list, + Msg) => Values.Value = + + rule System.acos rv => rv' + -------------------------- + ceval_known_external_funcs2("acos",SOME("acos"),[Values.REAL(rv)],_) + => Values.REAL(rv') + + rule System.asin rv => rv' + -------------------------- + ceval_known_external_funcs2("asin",SOME("asin"),[Values.REAL(rv)],_) + => Values.REAL(rv') + + rule System.atan(rv) => rv' + -------------------------- + ceval_known_external_funcs2("atan",SOME("atan"),[Values.REAL(rv)],_) + => Values.REAL(rv') + + rule System.atan2(rv1,rv2) => rv' + -------------------------- + ceval_known_external_funcs2("atan2",SOME("atan2"),[Values.REAL(rv1), + Values.REAL(rv2) + ],_) + => Values.REAL(rv') + + rule real_cos(rv) => rv' + -------------------------- + ceval_known_external_funcs2("cos",SOME("cos"),[Values.REAL(rv)],_) + => Values.REAL(rv') + + rule System.cosh(rv) => rv' + -------------------------- + ceval_known_external_funcs2("cosh",SOME("cosh"),[Values.REAL(rv)],_) + => Values.REAL(rv') + + rule real_exp(rv) => rv' + -------------------------- + ceval_known_external_funcs2("exp",SOME("exp"),[Values.REAL(rv)],_) + => Values.REAL(rv') + + rule System.log(rv) => rv' + -------------------------- + ceval_known_external_funcs2("log",SOME("log"),[Values.REAL(rv)],_) + => Values.REAL(rv') + + rule System.log10(rv) => rv' + -------------------------- + ceval_known_external_funcs2("log10",SOME("log10"),[Values.REAL(rv)],_) + => Values.REAL(rv') + + rule real_sin(rv) => rv' + -------------------------- + ceval_known_external_funcs2("sin",SOME("sin"),[Values.REAL(rv)],_) + => Values.REAL(rv') + + rule System.sinh(rv) => rv' + -------------------------- + ceval_known_external_funcs2("sinh",SOME("sinh"),[Values.REAL(rv)],_) + => Values.REAL(rv') + + rule real_sin rv => sv & + real_cos rv => cv & + real_div(sv,cv) => rv' + -------------------------- + ceval_known_external_funcs2("tan",SOME("tan"),[Values.REAL(rv)],_) + => Values.REAL(rv') + + rule System.tanh(rv) => rv' + -------------------------- + ceval_known_external_funcs2("tanh",SOME("tanh"),[Values.REAL(rv)],_) + => Values.REAL(rv') +end + (** relation: ceval_function ** ** For constant evaluation of functions returning a single value. For now only diff --git a/Compiler/SimCodegen.rml b/Compiler/SimCodegen.rml index 2eb6b3b1923..e090cba2bfb 100644 --- a/Compiler/SimCodegen.rml +++ b/Compiler/SimCodegen.rml @@ -2030,7 +2030,7 @@ relation generate_init_data2:(DAELow.DAELow, array_list(nyarr3) => ny_lst & array_list(nparr3) => np_lst & Util.list_flatten([nx_lst,nxd_lst,ny_lst,np_lst]) => whole_lst & - Util.string_delimit_list(whole_lst,"\n") => res + Util.string_delimit_list_no_empty(whole_lst,"\n") => res ----------------------------- generate_init_data2(DAELow.DAELOW(vars,knvars,_,_,initeqn,alg,_),nx,ny,np) => res @@ -2339,6 +2339,15 @@ relation generate_zero_crossing2: (DAELow.ZeroCrossing list, int, -------------------------------------------------- generate_zero_crossing2((zc as DAELow.ZERO_CROSSING(_,eql,_))::xs, index,dae,dlow,ass1,ass2,blocks,helpVarInfo) => (res1,res2) + + rule dump_zero_crossing_str zc => zc_str & + Util.string_append_list(["Internal Error generating zero crossing :", + zc_str,"\n"]) => res & + Print.print_error_buf res + ------------------------ + generate_zero_crossing2((zc as DAELow.ZERO_CROSSING(_,eql,_))::xs, + index,dae,dlow,ass1,ass2,blocks,helpVarInfo) + => fail end @@ -2357,6 +2366,12 @@ relation dump_zero_crossing_str: (DAELow.ZeroCrossing) => string = ---------------------------------------- dump_zero_crossing_str (DAELow.ZERO_CROSSING(Exp.CALL(Absyn.IDENT("sample"),[start,interval],_,_),_,_)) => zc_str + rule print_exp_cpp_str(e) => e_str & + Util.string_append_list(["/*Unknown zero crossing: ",e_str," */"]) + => zc_str + ------------------- + dump_zero_crossing_str (DAELow.ZERO_CROSSING(e,_,_)) => zc_str + end relation isZeroCrossingAffectingHelpVar: ((int * Exp.Exp * int), (int * DAELow.DAELow)) => bool = @@ -2381,6 +2396,10 @@ relation build_help_var_assignments: ( (int * Exp.Exp * int) list ) => string = string_append(res1,res2) => res -------------------------------------------------- build_help_var_assignments((helpVarIndex, e,_)::rest) => res + + rule Print.print_error_buf "Internal Error, build_help_var_assignments failed\n" + -------------------------------------------------- + build_help_var_assignments(_) => fail end relation print_zero_crossing_op_str: (Exp.Operator) => string = diff --git a/Compiler/Static.rml b/Compiler/Static.rml index f541cbe2c25..54f9f47f670 100644 --- a/Compiler/Static.rml +++ b/Compiler/Static.rml @@ -3315,6 +3315,15 @@ relation generate_compiled_function: (Env.Env, Absyn.ComponentRef, Exp.Exp, Type ----------------------------------------------- generate_compiled_function(env,fn,e,prop,SOME(st as Interactive.SYMBOLTABLE(p,_,_,_,cflist))) => SOME(st) + (* Don not compile if is "known" external function, e.g. math lib.*) + rule Absyn.cref_to_path(fn) => path & + Lookup.lookup_class(env,path,false) => (cdef,env') & + let SCode.CLASS(fid,_,_,SCode.R_EXT_FUNCTION,SCode.PARTS(_,_,_,_,_,extdecl)) = cdef & + let SOME(Absyn.EXTERNALDECL(id,lan,out,args,_)) = extdecl & + Ceval.is_known_external_func(fid,id) + ---------------------------------- + generate_compiled_function(env,fn,e,prop,st) => st + rule Debug.fprintln("sei", "generate_compiled_function: start2") & Absyn.cref_to_path(fn) => path & is_function_in_cflist (cflist, path) => false & diff --git a/Compiler/System.rml b/Compiler/System.rml index 12277f2c3c6..74cce7e059d 100644 --- a/Compiler/System.rml +++ b/Compiler/System.rml @@ -301,6 +301,47 @@ relation acos: real => real relation atan: real => real +(** relation: atan2 + ** + ** Arctan2 is not defined in rml. + **) + +relation atan2: (real,real) => real + +(** relation: cosh + ** + ** Cosh is not defined in rml. + **) + +relation cosh: real => real + +(** relation: log + ** + ** log is not defined in rml. + **) + +relation log: real => real + +(** relation: log10 + ** + ** log10 is not defined in rml. + **) + +relation log10: real => real + +(** relation: sinh + ** + ** sinh is not defined in rml. + **) + +relation sinh: real => real + +(** relation: tanh + ** + ** tanh is not defined in rml. + **) + +relation tanh: real => real (** relation get_classnames_for_simulation ** this returns a list of classnames that are in the diff --git a/Compiler/runtime/systemimpl.c b/Compiler/runtime/systemimpl.c index 632cd5ef21c..1b9a560284b 100644 --- a/Compiler/runtime/systemimpl.c +++ b/Compiler/runtime/systemimpl.c @@ -967,6 +967,49 @@ RML_BEGIN_LABEL(System__atan) } RML_END_LABEL +RML_BEGIN_LABEL(System__atan2) +{ + rmlA0 = rml_prim_mkreal(atan2(rml_prim_get_real(rmlA0), + rml_prim_get_real(rmlA1))); + RML_TAILCALLK(rmlSC); +} +RML_END_LABEL + +RML_BEGIN_LABEL(System__cosh) +{ + rmlA0 = rml_prim_mkreal(cosh(rml_prim_get_real(rmlA0))); + RML_TAILCALLK(rmlSC); +} +RML_END_LABEL + +RML_BEGIN_LABEL(System__log) +{ + rmlA0 = rml_prim_mkreal(log(rml_prim_get_real(rmlA0))); + RML_TAILCALLK(rmlSC); +} +RML_END_LABEL + +RML_BEGIN_LABEL(System__log10) +{ + rmlA0 = rml_prim_mkreal(log10(rml_prim_get_real(rmlA0))); + RML_TAILCALLK(rmlSC); +} +RML_END_LABEL + +RML_BEGIN_LABEL(System__sinh) +{ + rmlA0 = rml_prim_mkreal(sinh(rml_prim_get_real(rmlA0))); + RML_TAILCALLK(rmlSC); +} +RML_END_LABEL + +RML_BEGIN_LABEL(System__tanh) +{ + rmlA0 = rml_prim_mkreal(tanh(rml_prim_get_real(rmlA0))); + RML_TAILCALLK(rmlSC); +} +RML_END_LABEL + float next_realelt(float *arr) { static int curpos; diff --git a/Compiler/winruntime/systemimpl.c b/Compiler/winruntime/systemimpl.c index 541ef12f9b9..bcba7853e6f 100755 --- a/Compiler/winruntime/systemimpl.c +++ b/Compiler/winruntime/systemimpl.c @@ -965,6 +965,49 @@ RML_BEGIN_LABEL(System__atan) } RML_END_LABEL +RML_BEGIN_LABEL(System__atan2) +{ + rmlA0 = rml_prim_mkreal(atan2(rml_prim_get_real(rmlA0), + rml_prim_get_real(rmlA1))); + RML_TAILCALLK(rmlSC); +} +RML_END_LABEL + +RML_BEGIN_LABEL(System__cosh) +{ + rmlA0 = rml_prim_mkreal(cosh(rml_prim_get_real(rmlA0))); + RML_TAILCALLK(rmlSC); +} +RML_END_LABEL + +RML_BEGIN_LABEL(System__log) +{ + rmlA0 = rml_prim_mkreal(log(rml_prim_get_real(rmlA0))); + RML_TAILCALLK(rmlSC); +} +RML_END_LABEL + +RML_BEGIN_LABEL(System__log10) +{ + rmlA0 = rml_prim_mkreal(log10(rml_prim_get_real(rmlA0))); + RML_TAILCALLK(rmlSC); +} +RML_END_LABEL + +RML_BEGIN_LABEL(System__sinh) +{ + rmlA0 = rml_prim_mkreal(sinh(rml_prim_get_real(rmlA0))); + RML_TAILCALLK(rmlSC); +} +RML_END_LABEL + +RML_BEGIN_LABEL(System__tanh) +{ + rmlA0 = rml_prim_mkreal(tanh(rml_prim_get_real(rmlA0))); + RML_TAILCALLK(rmlSC); +} +RML_END_LABEL + float next_realelt(float *arr) { static int curpos;