Revision f6acf47b
Added by Pierre-Loïc Garoche over 7 years ago
configure.ac | ||
---|---|---|
7 | 7 |
|
8 | 8 |
AC_CONFIG_SRCDIR([src/main_lustre_compiler.ml]) |
9 | 9 |
|
10 |
AC_PATH_PROG([OCAMLC],[ocamlc],[:]) |
|
11 |
AC_MSG_CHECKING(OCaml version) |
|
12 |
ocamlc_version=`$OCAMLC -v | grep version | rev| cut -d \ -f 1 | rev` |
|
13 |
major=`echo $ocamlc_version | cut -d . -f 1` |
|
14 |
minor=`echo $ocamlc_version | cut -d . -f 2` |
|
15 |
if (test "$major" -lt 3 -a "$minor" -lt 12 ); then |
|
16 |
AC_MSG_ERROR([Ocaml version must be at least 3.12. You have version $ocamlc_version]) |
|
17 |
fi |
|
18 |
AC_MSG_RESULT(valid ocaml version detected: $ocamlc_version) |
|
19 |
|
|
20 |
AC_PATH_PROG([OCAMLBUILD],[ocamlbuild],[:]) |
|
21 |
|
|
22 |
|
|
10 | 23 |
# default prefix is /usr/local |
11 | 24 |
AC_PREFIX_DEFAULT(/usr/local) |
12 | 25 |
|
26 |
# Checking libs |
|
27 |
|
|
13 | 28 |
AC_ARG_WITH([ocamlgraph-path], |
14 | 29 |
[AS_HELP_STRING([--ocamlgraph-path], |
15 | 30 |
[specify the path of ocamlgraph library. graph.cmxa should be in ocamlgraph-path @<:@default=$(ocamlfind query ocamlgraph)@:>@])], |
... | ... | |
23 | 38 |
) |
24 | 39 |
AC_SUBST(OCAMLGRAPH_PATH) |
25 | 40 |
|
26 |
|
|
27 |
AC_PATH_PROG([OCAMLC],[ocamlc],[:]) |
|
28 |
AC_MSG_CHECKING(OCaml version) |
|
29 |
ocamlc_version=`$OCAMLC -v | grep version | rev| cut -d \ -f 1 | rev` |
|
30 |
major=`echo $ocamlc_version | cut -d . -f 1` |
|
31 |
minor=`echo $ocamlc_version | cut -d . -f 2` |
|
32 |
if (test "$major" -lt 3 -a "$minor" -lt 11 ); then |
|
33 |
AC_MSG_ERROR([Ocaml version must be at least 3.11. You have version $ocamlc_version]) |
|
34 |
fi |
|
35 |
AC_MSG_RESULT(valid ocaml version detected: $ocamlc_version) |
|
36 |
|
|
37 |
AC_PATH_PROG([OCAMLBUILD],[ocamlbuild],[:]) |
|
38 |
|
|
39 |
|
|
40 |
# Checking libs |
|
41 |
|
|
42 |
# Checks for libraries. OCamlgraph |
|
43 | 41 |
AC_MSG_CHECKING(ocamlgraph library) |
44 |
ocamlgraph_lib=`find $OCAMLGRAPH_PATH -iname graph.cmxa | grep -m 1 -o "graph.cmxa"` |
|
42 |
ocamlgraph_lib=`find $OCAMLGRAPH_PATH -iname graph.cmxa -nowarn | grep -m 1 -o "graph.cmxa"`
|
|
45 | 43 |
if (test "x$ocamlgraph_lib" = xgraph.cmxa ); then |
46 |
ocamlgraph_lib_full=`find $OCAMLGRAPH_PATH -iname graph.cmxa | grep -m 1 "graph.cmxa"` |
|
47 |
AC_MSG_RESULT(library detected: $ocamlgraph_lib_full )
|
|
48 |
else |
|
44 |
ocamlgraph_lib_full=`find $OCAMLGRAPH_PATH -iname graph.cmxa -nowarn | grep -m 1 "graph.cmxa"`
|
|
45 |
AC_MSG_RESULT($ocamlgraph_lib_full ) |
|
46 |
else
|
|
49 | 47 |
AC_MSG_ERROR([ocamlgraph library not installed in $OCAMLGRAPH_PATH]) |
50 | 48 |
fi |
51 | 49 |
|
50 |
AC_CHECK_LIB(gmp, __gmpz_init, |
|
51 |
[gmp=yes], |
|
52 |
[AC_MSG_RESULT([GNU MP not found]) |
|
53 |
gmp=no]) |
|
54 |
|
|
55 |
AC_CHECK_LIB(mpfr, mpfr_add, [mpfr=yes], |
|
56 |
[AC_MSG_RESULT( |
|
57 |
[MPFR not found]) |
|
58 |
mpfr=no]) |
|
59 |
|
|
52 | 60 |
|
53 | 61 |
# Workaround to solve an issue with ocamlbuild and C libraries. |
54 | 62 |
# oCFLAGS="$CFLAGS" |
... | ... | |
86 | 94 |
# Instanciation |
87 | 95 |
AC_CONFIG_FILES([Makefile |
88 | 96 |
src/Makefile |
89 |
src/myocamlbuild.ml
|
|
97 |
src/myocamlbuild.ml
|
|
90 | 98 |
src/version.ml]) |
91 | 99 |
|
92 | 100 |
AC_OUTPUT |
93 | 101 |
|
94 | 102 |
|
95 | 103 |
# summary |
96 |
dnl AC_MSG_NOTICE(******** Configuration ********) |
|
104 |
AC_MSG_NOTICE(******** Configuration ********) |
|
105 |
AC_MSG_NOTICE(bin path: $prefix/bin) |
|
106 |
AC_MSG_NOTICE(include path: $prefix/include) |
|
107 |
AC_MSG_NOTICE(******** Plugins ********) |
|
108 |
|
|
109 |
if (test "x$gmp" = xyes -a "x$mpfr" = xyes ); then |
|
110 |
AC_MSG_NOTICE([-mpfr option enable]) |
|
111 |
|
|
112 |
else |
|
113 |
AC_MSG_WARN([MPFR option cannot be activated. Requires GMP and MPFR libs]) |
|
114 |
|
|
115 |
fi |
|
116 |
|
|
117 |
AC_MSG_NOTICE |
|
118 |
AC_MSG_NOTICE(******** Configuration ********) |
|
119 |
AC_MSG_NOTICE(******** Configuration ********) |
|
120 |
|
src/_tags | ||
---|---|---|
2 | 2 |
"backends/Horn": include |
3 | 3 |
"plugins/salsa": include |
4 | 4 |
"plugins/scopes": include |
5 |
"plugins/mpfr": include |
|
5 | 6 |
<**/.svn>: -traverse |
6 | 7 |
<**/.svn>: not_hygienic |
7 | 8 |
"main_lustre_compiler.native": use_graph |
src/backends/C/c_backend_main.ml | ||
---|---|---|
139 | 139 |
print_main_memory_allocation mname main_mem fmt m; |
140 | 140 |
print_main_initialize mname main_mem fmt m; |
141 | 141 |
print_main_loop mname main_mem fmt m; |
142 |
if Scopes.Plugin.is_active () then |
|
143 |
begin |
|
144 |
fprintf fmt "@ %t" Scopes.Plugin.pp |
|
145 |
end; |
|
142 |
|
|
143 |
Plugins.c_backend_main_loop_body_suffix fmt (); |
|
146 | 144 |
fprintf fmt "@]@ }@ @ "; |
147 | 145 |
print_main_clear mname main_mem fmt m; |
148 | 146 |
fprintf fmt "@ return 1;"; |
src/global.ml | ||
---|---|---|
3 | 3 |
let basename = ref "" |
4 | 4 |
let main_node = ref "" |
5 | 5 |
|
6 |
|
|
6 | 7 |
module TypeEnv = |
7 | 8 |
struct |
8 | 9 |
let lookup_value ident = Env.lookup_value !type_env ident |
src/main_lustre_compiler.ml | ||
---|---|---|
112 | 112 |
in |
113 | 113 |
|
114 | 114 |
(* Checking stateless/stateful status *) |
115 |
if Scopes.Plugin.is_active () then
|
|
115 |
if Plugins.check_force_stateful () then
|
|
116 | 116 |
force_stateful_decls prog |
117 | 117 |
else |
118 | 118 |
check_stateless_decls prog; |
... | ... | |
275 | 275 |
in |
276 | 276 |
|
277 | 277 |
(* Salsa optimize machine code *) |
278 |
let machine_code = |
|
279 |
if !Options.salsa_enabled then |
|
280 |
begin |
|
281 |
check_main (); |
|
282 |
Log.report ~level:1 (fun fmt -> fprintf fmt ".. salsa machines optimization (phase 3)@ "); |
|
283 |
(* Selecting float constants for Salsa *) |
|
284 |
let constEnv = List.fold_left ( |
|
285 |
fun accu c_topdecl -> |
|
286 |
match c_topdecl.top_decl_desc with |
|
287 |
| Const c when Types.is_real_type c.const_type -> |
|
288 |
(c.const_id, c.const_value) :: accu |
|
289 |
| _ -> accu |
|
290 |
) [] (Corelang.get_consts prog) |
|
291 |
in |
|
292 |
List.map |
|
293 |
(Machine_salsa_opt.machine_t2machine_t_optimized_by_salsa constEnv) |
|
294 |
machine_code |
|
295 |
end |
|
296 |
else |
|
297 |
machine_code |
|
298 |
in |
|
299 | 278 |
Log.report ~level:3 (fun fmt -> fprintf fmt "@[<v 2>@ %a@]@ " |
300 | 279 |
(Utils.fprintf_list ~sep:"@ " Machine_code.pp_machine) |
301 | 280 |
machine_code); |
... | ... | |
391 | 370 |
let machine_code = |
392 | 371 |
stage2 prog |
393 | 372 |
in |
394 |
if Scopes.Plugin.show_scopes () then |
|
395 |
begin |
|
396 |
let all_scopes = Scopes.compute_scopes prog !Options.main_node in |
|
397 |
(* Printing scopes *) |
|
398 |
if !Options.verbose_level >= 1 then |
|
399 |
Format.printf "Possible scopes are:@ "; |
|
400 |
Format.printf "@[<v>%a@ @]@.@?" Scopes.print_scopes all_scopes; |
|
401 |
exit 0 |
|
402 |
|
|
403 |
end; |
|
404 | 373 |
|
405 |
let machine_code = |
|
406 |
if Scopes.Plugin.is_active () then |
|
407 |
Scopes.Plugin.process_scopes !Options.main_node prog machine_code |
|
408 |
else |
|
409 |
machine_code |
|
410 |
in |
|
374 |
let machine_code = Plugins.refine_machine_code prog machine_code in |
|
411 | 375 |
|
412 | 376 |
stage3 prog machine_code dependencies basename; |
413 | 377 |
begin |
... | ... | |
443 | 407 |
try |
444 | 408 |
Printexc.record_backtrace true; |
445 | 409 |
|
446 |
let options = Options.options @ |
|
447 |
List.flatten ( |
|
448 |
List.map Options.plugin_opt [ |
|
449 |
Scopes.Plugin.name, Scopes.Plugin.activate, Scopes.Plugin.options |
|
450 |
] |
|
451 |
) |
|
452 |
in |
|
410 |
let options = Options.options @ (Plugins.options ()) in |
|
453 | 411 |
|
454 | 412 |
Arg.parse options anonymous usage |
455 | 413 |
with |
src/mpfr.ml | ||
---|---|---|
1 |
(********************************************************************) |
|
2 |
(* *) |
|
3 |
(* The LustreC compiler toolset / The LustreC Development Team *) |
|
4 |
(* Copyright 2012 - -- ONERA - CNRS - INPT *) |
|
5 |
(* *) |
|
6 |
(* LustreC is free software, distributed WITHOUT ANY WARRANTY *) |
|
7 |
(* under the terms of the GNU Lesser General Public License *) |
|
8 |
(* version 2.1. *) |
|
9 |
(* *) |
|
10 |
(********************************************************************) |
|
11 |
|
|
12 |
open Utils |
|
13 |
open LustreSpec |
|
14 |
open Corelang |
|
15 |
open Normalization |
|
16 |
open Machine_code |
|
17 |
|
|
18 |
let mpfr_module = mktop (Open(false, "mpfr_lustre")) |
|
19 |
|
|
20 |
let mpfr_rnd () = "MPFR_RNDN" |
|
21 |
|
|
22 |
let mpfr_prec () = !Options.mpfr_prec |
|
23 |
|
|
24 |
let inject_id = "MPFRId" |
|
25 |
|
|
26 |
let inject_copy_id = "mpfr_set" |
|
27 |
|
|
28 |
let inject_real_id = "mpfr_set_flt" |
|
29 |
|
|
30 |
let inject_init_id = "mpfr_init2" |
|
31 |
|
|
32 |
let inject_clear_id = "mpfr_clear" |
|
33 |
|
|
34 |
let mpfr_t = "mpfr_t" |
|
35 |
|
|
36 |
let unfoldable_value value = |
|
37 |
not (Types.is_real_type value.value_type && is_const_value value) |
|
38 |
|
|
39 |
let inject_id_id expr = |
|
40 |
let e = mkpredef_call expr.expr_loc inject_id [expr] in |
|
41 |
{ e with |
|
42 |
expr_type = Type_predef.type_real; |
|
43 |
expr_clock = expr.expr_clock; |
|
44 |
} |
|
45 |
|
|
46 |
let pp_inject_real pp_var fmt var value = |
|
47 |
Format.fprintf fmt "%s(%a, %a, %s);" |
|
48 |
inject_real_id |
|
49 |
pp_var var |
|
50 |
pp_var value |
|
51 |
(mpfr_rnd ()) |
|
52 |
|
|
53 |
let inject_assign expr = |
|
54 |
let e = mkpredef_call expr.expr_loc inject_copy_id [expr] in |
|
55 |
{ e with |
|
56 |
expr_type = Type_predef.type_real; |
|
57 |
expr_clock = expr.expr_clock; |
|
58 |
} |
|
59 |
|
|
60 |
let pp_inject_copy pp_var fmt var value = |
|
61 |
Format.fprintf fmt "%s(%a, %a, %s);" |
|
62 |
inject_copy_id |
|
63 |
pp_var var |
|
64 |
pp_var value |
|
65 |
(mpfr_rnd ()) |
|
66 |
|
|
67 |
let rec pp_inject_assign pp_var fmt var value = |
|
68 |
if is_const_value value |
|
69 |
then |
|
70 |
pp_inject_real pp_var fmt var value |
|
71 |
else |
|
72 |
pp_inject_copy pp_var fmt var value |
|
73 |
|
|
74 |
let pp_inject_init pp_var fmt var = |
|
75 |
Format.fprintf fmt "%s(%a, %i);" |
|
76 |
inject_init_id |
|
77 |
pp_var var |
|
78 |
(mpfr_prec ()) |
|
79 |
|
|
80 |
let pp_inject_clear pp_var fmt var = |
|
81 |
Format.fprintf fmt "%s(%a);" |
|
82 |
inject_clear_id |
|
83 |
pp_var var |
|
84 |
|
|
85 |
let base_inject_op id = |
|
86 |
match id with |
|
87 |
| "+" -> "MPFRPlus" |
|
88 |
| "-" -> "MPFRMinus" |
|
89 |
| "*" -> "MPFRTimes" |
|
90 |
| "/" -> "MPFRDiv" |
|
91 |
| "uminus" -> "MPFRUminus" |
|
92 |
| "<=" -> "MPFRLe" |
|
93 |
| "<" -> "MPFRLt" |
|
94 |
| ">=" -> "MPFRGe" |
|
95 |
| ">" -> "MPFRGt" |
|
96 |
| "=" -> "MPFREq" |
|
97 |
| "!=" -> "MPFRNeq" |
|
98 |
| _ -> raise Not_found |
|
99 |
|
|
100 |
let inject_op id = |
|
101 |
try |
|
102 |
base_inject_op id |
|
103 |
with Not_found -> id |
|
104 |
|
|
105 |
let homomorphic_funs = |
|
106 |
List.fold_right (fun id res -> try base_inject_op id :: res with Not_found -> res) Basic_library.internal_funs [] |
|
107 |
|
|
108 |
let is_homomorphic_fun id = |
|
109 |
List.mem id homomorphic_funs |
|
110 |
|
|
111 |
let inject_call expr = |
|
112 |
match expr.expr_desc with |
|
113 |
| Expr_appl (id, args, None) when not (Basic_library.is_expr_internal_fun expr) -> |
|
114 |
{ expr with expr_desc = Expr_appl (inject_op id, args, None) } |
|
115 |
| _ -> expr |
|
116 |
|
|
117 |
let expr_of_const_array expr = |
|
118 |
match expr.expr_desc with |
|
119 |
| Expr_const (Const_array cl) -> |
|
120 |
let typ = Types.array_element_type expr.expr_type in |
|
121 |
let expr_of_const c = |
|
122 |
{ expr_desc = Expr_const c; |
|
123 |
expr_type = typ; |
|
124 |
expr_clock = expr.expr_clock; |
|
125 |
expr_loc = expr.expr_loc; |
|
126 |
expr_delay = Delay.new_var (); |
|
127 |
expr_annot = None; |
|
128 |
expr_tag = new_tag (); |
|
129 |
} |
|
130 |
in { expr with expr_desc = Expr_array (List.map expr_of_const cl) } |
|
131 |
| _ -> assert false |
|
132 |
|
|
133 |
(* inject_<foo> : defs * used vars -> <foo> -> (updated defs * updated vars) * normalized <foo> *) |
|
134 |
let rec inject_list alias node inject_element defvars elist = |
|
135 |
List.fold_right |
|
136 |
(fun t (defvars, qlist) -> |
|
137 |
let defvars, norm_t = inject_element alias node defvars t in |
|
138 |
(defvars, norm_t :: qlist) |
|
139 |
) elist (defvars, []) |
|
140 |
|
|
141 |
let rec inject_expr ?(alias=true) node defvars expr = |
|
142 |
let res= |
|
143 |
match expr.expr_desc with |
|
144 |
| Expr_const (Const_real _) -> mk_expr_alias_opt alias node defvars expr |
|
145 |
| Expr_const (Const_array _) -> inject_expr ~alias:alias node defvars (expr_of_const_array expr) |
|
146 |
| Expr_const (Const_struct _) -> assert false |
|
147 |
| Expr_ident _ |
|
148 |
| Expr_const _ -> defvars, expr |
|
149 |
| Expr_array elist -> |
|
150 |
let defvars, norm_elist = inject_list alias node (fun _ -> inject_expr ~alias:true) defvars elist in |
|
151 |
let norm_expr = { expr with expr_desc = Expr_array norm_elist } in |
|
152 |
defvars, norm_expr |
|
153 |
| Expr_power (e1, d) -> |
|
154 |
let defvars, norm_e1 = inject_expr node defvars e1 in |
|
155 |
let norm_expr = { expr with expr_desc = Expr_power (norm_e1, d) } in |
|
156 |
defvars, norm_expr |
|
157 |
| Expr_access (e1, d) -> |
|
158 |
let defvars, norm_e1 = inject_expr node defvars e1 in |
|
159 |
let norm_expr = { expr with expr_desc = Expr_access (norm_e1, d) } in |
|
160 |
defvars, norm_expr |
|
161 |
| Expr_tuple elist -> |
|
162 |
let defvars, norm_elist = |
|
163 |
inject_list alias node (fun alias -> inject_expr ~alias:alias) defvars elist in |
|
164 |
let norm_expr = { expr with expr_desc = Expr_tuple norm_elist } in |
|
165 |
defvars, norm_expr |
|
166 |
| Expr_appl (id, args, r) -> |
|
167 |
let defvars, norm_args = inject_expr node defvars args in |
|
168 |
let norm_expr = { expr with expr_desc = Expr_appl (id, norm_args, r) } in |
|
169 |
mk_expr_alias_opt alias node defvars (inject_call norm_expr) |
|
170 |
| Expr_arrow _ -> defvars, expr |
|
171 |
| Expr_pre e -> |
|
172 |
let defvars, norm_e = inject_expr node defvars e in |
|
173 |
let norm_expr = { expr with expr_desc = Expr_pre norm_e } in |
|
174 |
defvars, norm_expr |
|
175 |
| Expr_fby (e1, e2) -> |
|
176 |
let defvars, norm_e1 = inject_expr node defvars e1 in |
|
177 |
let defvars, norm_e2 = inject_expr node defvars e2 in |
|
178 |
let norm_expr = { expr with expr_desc = Expr_fby (norm_e1, norm_e2) } in |
|
179 |
defvars, norm_expr |
|
180 |
| Expr_when (e, c, l) -> |
|
181 |
let defvars, norm_e = inject_expr node defvars e in |
|
182 |
let norm_expr = { expr with expr_desc = Expr_when (norm_e, c, l) } in |
|
183 |
defvars, norm_expr |
|
184 |
| Expr_ite (c, t, e) -> |
|
185 |
let defvars, norm_c = inject_expr node defvars c in |
|
186 |
let defvars, norm_t = inject_expr node defvars t in |
|
187 |
let defvars, norm_e = inject_expr node defvars e in |
|
188 |
let norm_expr = { expr with expr_desc = Expr_ite (norm_c, norm_t, norm_e) } in |
|
189 |
defvars, norm_expr |
|
190 |
| Expr_merge (c, hl) -> |
|
191 |
let defvars, norm_hl = inject_branches node defvars hl in |
|
192 |
let norm_expr = { expr with expr_desc = Expr_merge (c, norm_hl) } in |
|
193 |
defvars, norm_expr |
|
194 |
in |
|
195 |
(*Format.eprintf "inject_expr %B %a = %a@." alias Printers.pp_expr expr Printers.pp_expr (snd res);*) |
|
196 |
res |
|
197 |
|
|
198 |
and inject_branches node defvars hl = |
|
199 |
List.fold_right |
|
200 |
(fun (t, h) (defvars, norm_q) -> |
|
201 |
let (defvars, norm_h) = inject_expr node defvars h in |
|
202 |
defvars, (t, norm_h) :: norm_q |
|
203 |
) |
|
204 |
hl (defvars, []) |
|
205 |
|
|
206 |
|
|
207 |
let rec inject_eq node defvars eq = |
|
208 |
let (defs', vars'), norm_rhs = inject_expr ~alias:false node defvars eq.eq_rhs in |
|
209 |
let norm_eq = { eq with eq_rhs = norm_rhs } in |
|
210 |
norm_eq::defs', vars' |
|
211 |
|
|
212 |
(** normalize_node node returns a normalized node, |
|
213 |
ie. |
|
214 |
- updated locals |
|
215 |
- new equations |
|
216 |
- |
|
217 |
*) |
|
218 |
let inject_node node = |
|
219 |
cpt_fresh := 0; |
|
220 |
let inputs_outputs = node.node_inputs@node.node_outputs in |
|
221 |
let is_local v = |
|
222 |
List.for_all ((!=) v) inputs_outputs in |
|
223 |
let orig_vars = inputs_outputs@node.node_locals in |
|
224 |
let defs, vars = |
|
225 |
List.fold_left (inject_eq node) ([], orig_vars) (get_node_eqs node) in |
|
226 |
(* Normalize the asserts *) |
|
227 |
let vars, assert_defs, asserts = |
|
228 |
List.fold_left ( |
|
229 |
fun (vars, def_accu, assert_accu) assert_ -> |
|
230 |
let assert_expr = assert_.assert_expr in |
|
231 |
let (defs, vars'), expr = |
|
232 |
inject_expr |
|
233 |
~alias:false |
|
234 |
node |
|
235 |
([], vars) (* defvar only contains vars *) |
|
236 |
assert_expr |
|
237 |
in |
|
238 |
vars', defs@def_accu, {assert_ with assert_expr = expr}::assert_accu |
|
239 |
) (vars, [], []) node.node_asserts in |
|
240 |
let new_locals = List.filter is_local vars in |
|
241 |
(* Compute traceability info: |
|
242 |
- gather newly bound variables |
|
243 |
- compute the associated expression without aliases |
|
244 |
*) |
|
245 |
(* let diff_vars = List.filter (fun v -> not (List.mem v node.node_locals)) new_locals in *) |
|
246 |
let node = |
|
247 |
{ node with |
|
248 |
node_locals = new_locals; |
|
249 |
node_stmts = List.map (fun eq -> Eq eq) (defs @ assert_defs); |
|
250 |
} |
|
251 |
in ((*Printers.pp_node Format.err_formatter node;*) node) |
|
252 |
|
|
253 |
let inject_decl decl = |
|
254 |
match decl.top_decl_desc with |
|
255 |
| Node nd -> |
|
256 |
{decl with top_decl_desc = Node (inject_node nd)} |
|
257 |
| Open _ | ImportedNode _ | Const _ | TypeDef _ -> decl |
|
258 |
|
|
259 |
let inject_prog decls = |
|
260 |
List.map inject_decl decls |
|
261 |
|
|
262 |
|
|
263 |
(* Local Variables: *) |
|
264 |
(* compile-command:"make -C .." *) |
|
265 |
(* End: *) |
src/options.ml | ||
---|---|---|
41 | 41 |
let horn_cex = ref false |
42 | 42 |
let horn_queries = ref false |
43 | 43 |
|
44 |
let salsa_enabled = ref false |
|
45 | 44 |
|
46 | 45 |
let set_mpfr prec = |
47 | 46 |
if prec > 0 then ( |
48 | 47 |
mpfr := true; |
49 | 48 |
mpfr_prec := prec; |
50 |
salsa_enabled := false; (* We deactivate salsa *)
|
|
49 |
(* salsa_enabled := false; (* We deactivate salsa *) TODO *)
|
|
51 | 50 |
) |
52 | 51 |
else |
53 | 52 |
failwith "mpfr requires a positive integer" |
... | ... | |
69 | 68 |
"-horn-traces", Arg.Unit (fun () -> output := "horn"; horntraces:=true), "produce traceability file for Horn backend. Enable the horn backend."; |
70 | 69 |
"-horn-cex", Arg.Unit (fun () -> output := "horn"; horn_cex:=true), "generate cex enumeration. Enable the horn backend (work in progress)"; |
71 | 70 |
"-horn-queries", Arg.Unit (fun () -> output := "horn"; horn_queries:=true), "generate queries in generated Horn file. Enable the horn backend (work in progress)"; |
72 |
"-salsa", Arg.Set salsa_enabled, "activate Salsa optimization <default>"; |
|
73 |
"-no-salsa", Arg.Clear salsa_enabled, "deactivate Salsa optimization"; |
|
74 | 71 |
"-print_reuse", Arg.Set print_reuse, "prints variable reuse policy"; |
75 | 72 |
"-lustre", Arg.Unit (fun () -> output := "lustre"), "generates Lustre output, performing all active optimizations"; |
76 | 73 |
"-inline", Arg.Unit (fun () -> global_inline := true; const_unfold := true), "inline all node calls (require a main node). Implies constant unfolding"; |
src/pluginType.ml | ||
---|---|---|
1 |
module type PluginType = |
|
2 |
sig |
|
3 |
val name: string |
|
4 |
val activate: unit -> unit |
|
5 |
val options: (string * Arg.spec * string) list |
|
6 |
val check_force_stateful : unit -> bool |
|
7 |
val refine_machine_code: LustreSpec.top_decl list -> |
|
8 |
Machine_code.machine_t list -> Machine_code.machine_t list |
|
9 |
val c_backend_main_loop_body_suffix : Format.formatter -> unit -> unit |
|
10 |
end |
|
11 |
|
|
12 |
module Default = |
|
13 |
struct |
|
14 |
let check_force_stateful () = false |
|
15 |
let refine_machine_code prog machines = machines |
|
16 |
let c_backend_main_loop_body_suffix fmt () = () |
|
17 |
end |
src/plugins.ml | ||
---|---|---|
1 | 1 |
open LustreSpec |
2 | 2 |
|
3 |
module type PluginType = |
|
4 |
sig |
|
3 |
let plugins = |
|
4 |
[ |
|
5 |
(module Scopes.Plugin : PluginType.PluginType); |
|
6 |
(module Salsa_plugin.Plugin : PluginType.PluginType) |
|
7 |
] |
|
5 | 8 |
|
6 |
end |
|
7 | 9 |
|
10 |
let options () = |
|
11 |
List.flatten ( |
|
12 |
List.map Options.plugin_opt ( |
|
13 |
List.map (fun m -> |
|
14 |
let module M = (val m : PluginType.PluginType) in |
|
15 |
(M.name, M.activate, M.options) |
|
16 |
) plugins |
|
17 |
)) |
|
8 | 18 |
|
19 |
let check_force_stateful () = |
|
20 |
List.exists (fun m -> |
|
21 |
let module M = (val m : PluginType.PluginType) in |
|
22 |
M.check_force_stateful () |
|
23 |
) plugins |
|
24 |
|
|
25 |
let refine_machine_code prog machine_code = |
|
26 |
List.fold_left (fun accu m -> |
|
27 |
let module M = (val m : PluginType.PluginType) in |
|
28 |
M.refine_machine_code prog accu |
|
29 |
) machine_code plugins |
|
30 |
|
|
31 |
|
|
32 |
let c_backend_main_loop_body_suffix fmt () = |
|
33 |
List.iter (fun (m: (module PluginType.PluginType)) -> |
|
34 |
let module M = (val m : PluginType.PluginType) in |
|
35 |
M.c_backend_main_loop_body_suffix fmt ()) plugins |
|
36 |
|
|
37 |
(* Specific treatment of annotations when inlining, specific of declared plugins *) |
|
9 | 38 |
|
10 | 39 |
let inline_annots rename_var_fun annot_list = |
11 | 40 |
List.map ( |
src/plugins/mpfr/mpfr.ml | ||
---|---|---|
1 |
(********************************************************************) |
|
2 |
(* *) |
|
3 |
(* The LustreC compiler toolset / The LustreC Development Team *) |
|
4 |
(* Copyright 2012 - -- ONERA - CNRS - INPT *) |
|
5 |
(* *) |
|
6 |
(* LustreC is free software, distributed WITHOUT ANY WARRANTY *) |
|
7 |
(* under the terms of the GNU Lesser General Public License *) |
|
8 |
(* version 2.1. *) |
|
9 |
(* *) |
|
10 |
(********************************************************************) |
|
11 |
|
|
12 |
open Utils |
|
13 |
open LustreSpec |
|
14 |
open Corelang |
|
15 |
open Normalization |
|
16 |
open Machine_code |
|
17 |
|
|
18 |
let mpfr_module = mktop (Open(false, "mpfr_lustre")) |
|
19 |
|
|
20 |
let mpfr_rnd () = "MPFR_RNDN" |
|
21 |
|
|
22 |
let mpfr_prec () = !Options.mpfr_prec |
|
23 |
|
|
24 |
let inject_id = "MPFRId" |
|
25 |
|
|
26 |
let inject_copy_id = "mpfr_set" |
|
27 |
|
|
28 |
let inject_real_id = "mpfr_set_flt" |
|
29 |
|
|
30 |
let inject_init_id = "mpfr_init2" |
|
31 |
|
|
32 |
let inject_clear_id = "mpfr_clear" |
|
33 |
|
|
34 |
let mpfr_t = "mpfr_t" |
|
35 |
|
|
36 |
let unfoldable_value value = |
|
37 |
not (Types.is_real_type value.value_type && is_const_value value) |
|
38 |
|
|
39 |
let inject_id_id expr = |
|
40 |
let e = mkpredef_call expr.expr_loc inject_id [expr] in |
|
41 |
{ e with |
|
42 |
expr_type = Type_predef.type_real; |
|
43 |
expr_clock = expr.expr_clock; |
|
44 |
} |
|
45 |
|
|
46 |
let pp_inject_real pp_var fmt var value = |
|
47 |
Format.fprintf fmt "%s(%a, %a, %s);" |
|
48 |
inject_real_id |
|
49 |
pp_var var |
|
50 |
pp_var value |
|
51 |
(mpfr_rnd ()) |
|
52 |
|
|
53 |
let inject_assign expr = |
|
54 |
let e = mkpredef_call expr.expr_loc inject_copy_id [expr] in |
|
55 |
{ e with |
|
56 |
expr_type = Type_predef.type_real; |
|
57 |
expr_clock = expr.expr_clock; |
|
58 |
} |
|
59 |
|
|
60 |
let pp_inject_copy pp_var fmt var value = |
|
61 |
Format.fprintf fmt "%s(%a, %a, %s);" |
|
62 |
inject_copy_id |
|
63 |
pp_var var |
|
64 |
pp_var value |
|
65 |
(mpfr_rnd ()) |
|
66 |
|
|
67 |
let rec pp_inject_assign pp_var fmt var value = |
|
68 |
if is_const_value value |
|
69 |
then |
|
70 |
pp_inject_real pp_var fmt var value |
|
71 |
else |
|
72 |
pp_inject_copy pp_var fmt var value |
|
73 |
|
|
74 |
let pp_inject_init pp_var fmt var = |
|
75 |
Format.fprintf fmt "%s(%a, %i);" |
|
76 |
inject_init_id |
|
77 |
pp_var var |
|
78 |
(mpfr_prec ()) |
|
79 |
|
|
80 |
let pp_inject_clear pp_var fmt var = |
|
81 |
Format.fprintf fmt "%s(%a);" |
|
82 |
inject_clear_id |
|
83 |
pp_var var |
|
84 |
|
|
85 |
let base_inject_op id = |
|
86 |
match id with |
|
87 |
| "+" -> "MPFRPlus" |
|
88 |
| "-" -> "MPFRMinus" |
|
89 |
| "*" -> "MPFRTimes" |
|
90 |
| "/" -> "MPFRDiv" |
|
91 |
| "uminus" -> "MPFRUminus" |
|
92 |
| "<=" -> "MPFRLe" |
|
93 |
| "<" -> "MPFRLt" |
|
94 |
| ">=" -> "MPFRGe" |
|
95 |
| ">" -> "MPFRGt" |
|
96 |
| "=" -> "MPFREq" |
|
97 |
| "!=" -> "MPFRNeq" |
|
98 |
| _ -> raise Not_found |
|
99 |
|
|
100 |
let inject_op id = |
|
101 |
try |
|
102 |
base_inject_op id |
|
103 |
with Not_found -> id |
|
104 |
|
|
105 |
let homomorphic_funs = |
|
106 |
List.fold_right (fun id res -> try base_inject_op id :: res with Not_found -> res) Basic_library.internal_funs [] |
|
107 |
|
|
108 |
let is_homomorphic_fun id = |
|
109 |
List.mem id homomorphic_funs |
|
110 |
|
|
111 |
let inject_call expr = |
|
112 |
match expr.expr_desc with |
|
113 |
| Expr_appl (id, args, None) when not (Basic_library.is_expr_internal_fun expr) -> |
|
114 |
{ expr with expr_desc = Expr_appl (inject_op id, args, None) } |
|
115 |
| _ -> expr |
|
116 |
|
|
117 |
let expr_of_const_array expr = |
|
118 |
match expr.expr_desc with |
|
119 |
| Expr_const (Const_array cl) -> |
|
120 |
let typ = Types.array_element_type expr.expr_type in |
|
121 |
let expr_of_const c = |
|
122 |
{ expr_desc = Expr_const c; |
|
123 |
expr_type = typ; |
|
124 |
expr_clock = expr.expr_clock; |
|
125 |
expr_loc = expr.expr_loc; |
|
126 |
expr_delay = Delay.new_var (); |
|
127 |
expr_annot = None; |
|
128 |
expr_tag = new_tag (); |
|
129 |
} |
|
130 |
in { expr with expr_desc = Expr_array (List.map expr_of_const cl) } |
|
131 |
| _ -> assert false |
|
132 |
|
|
133 |
(* inject_<foo> : defs * used vars -> <foo> -> (updated defs * updated vars) * normalized <foo> *) |
|
134 |
let rec inject_list alias node inject_element defvars elist = |
|
135 |
List.fold_right |
|
136 |
(fun t (defvars, qlist) -> |
|
137 |
let defvars, norm_t = inject_element alias node defvars t in |
|
138 |
(defvars, norm_t :: qlist) |
|
139 |
) elist (defvars, []) |
|
140 |
|
|
141 |
let rec inject_expr ?(alias=true) node defvars expr = |
|
142 |
let res= |
|
143 |
match expr.expr_desc with |
|
144 |
| Expr_const (Const_real _) -> mk_expr_alias_opt alias node defvars expr |
|
145 |
| Expr_const (Const_array _) -> inject_expr ~alias:alias node defvars (expr_of_const_array expr) |
|
146 |
| Expr_const (Const_struct _) -> assert false |
|
147 |
| Expr_ident _ |
|
148 |
| Expr_const _ -> defvars, expr |
|
149 |
| Expr_array elist -> |
|
150 |
let defvars, norm_elist = inject_list alias node (fun _ -> inject_expr ~alias:true) defvars elist in |
|
151 |
let norm_expr = { expr with expr_desc = Expr_array norm_elist } in |
|
152 |
defvars, norm_expr |
|
153 |
| Expr_power (e1, d) -> |
|
154 |
let defvars, norm_e1 = inject_expr node defvars e1 in |
|
155 |
let norm_expr = { expr with expr_desc = Expr_power (norm_e1, d) } in |
|
156 |
defvars, norm_expr |
|
157 |
| Expr_access (e1, d) -> |
|
158 |
let defvars, norm_e1 = inject_expr node defvars e1 in |
|
159 |
let norm_expr = { expr with expr_desc = Expr_access (norm_e1, d) } in |
|
160 |
defvars, norm_expr |
|
161 |
| Expr_tuple elist -> |
|
162 |
let defvars, norm_elist = |
|
163 |
inject_list alias node (fun alias -> inject_expr ~alias:alias) defvars elist in |
|
164 |
let norm_expr = { expr with expr_desc = Expr_tuple norm_elist } in |
|
165 |
defvars, norm_expr |
|
166 |
| Expr_appl (id, args, r) -> |
|
167 |
let defvars, norm_args = inject_expr node defvars args in |
|
168 |
let norm_expr = { expr with expr_desc = Expr_appl (id, norm_args, r) } in |
|
169 |
mk_expr_alias_opt alias node defvars (inject_call norm_expr) |
|
170 |
| Expr_arrow _ -> defvars, expr |
|
171 |
| Expr_pre e -> |
|
172 |
let defvars, norm_e = inject_expr node defvars e in |
|
173 |
let norm_expr = { expr with expr_desc = Expr_pre norm_e } in |
|
174 |
defvars, norm_expr |
|
175 |
| Expr_fby (e1, e2) -> |
|
176 |
let defvars, norm_e1 = inject_expr node defvars e1 in |
|
177 |
let defvars, norm_e2 = inject_expr node defvars e2 in |
|
178 |
let norm_expr = { expr with expr_desc = Expr_fby (norm_e1, norm_e2) } in |
|
179 |
defvars, norm_expr |
|
180 |
| Expr_when (e, c, l) -> |
|
181 |
let defvars, norm_e = inject_expr node defvars e in |
|
182 |
let norm_expr = { expr with expr_desc = Expr_when (norm_e, c, l) } in |
|
183 |
defvars, norm_expr |
|
184 |
| Expr_ite (c, t, e) -> |
|
185 |
let defvars, norm_c = inject_expr node defvars c in |
|
186 |
let defvars, norm_t = inject_expr node defvars t in |
|
187 |
let defvars, norm_e = inject_expr node defvars e in |
|
188 |
let norm_expr = { expr with expr_desc = Expr_ite (norm_c, norm_t, norm_e) } in |
|
189 |
defvars, norm_expr |
|
190 |
| Expr_merge (c, hl) -> |
|
191 |
let defvars, norm_hl = inject_branches node defvars hl in |
|
192 |
let norm_expr = { expr with expr_desc = Expr_merge (c, norm_hl) } in |
|
193 |
defvars, norm_expr |
|
194 |
in |
|
195 |
(*Format.eprintf "inject_expr %B %a = %a@." alias Printers.pp_expr expr Printers.pp_expr (snd res);*) |
|
196 |
res |
|
197 |
|
|
198 |
and inject_branches node defvars hl = |
|
199 |
List.fold_right |
|
200 |
(fun (t, h) (defvars, norm_q) -> |
|
201 |
let (defvars, norm_h) = inject_expr node defvars h in |
|
202 |
defvars, (t, norm_h) :: norm_q |
|
203 |
) |
|
204 |
hl (defvars, []) |
|
205 |
|
|
206 |
|
|
207 |
let rec inject_eq node defvars eq = |
|
208 |
let (defs', vars'), norm_rhs = inject_expr ~alias:false node defvars eq.eq_rhs in |
|
209 |
let norm_eq = { eq with eq_rhs = norm_rhs } in |
|
210 |
norm_eq::defs', vars' |
|
211 |
|
|
212 |
(** normalize_node node returns a normalized node, |
|
213 |
ie. |
|
214 |
- updated locals |
|
215 |
- new equations |
|
216 |
- |
|
217 |
*) |
|
218 |
let inject_node node = |
|
219 |
cpt_fresh := 0; |
|
220 |
let inputs_outputs = node.node_inputs@node.node_outputs in |
|
221 |
let is_local v = |
|
222 |
List.for_all ((!=) v) inputs_outputs in |
|
223 |
let orig_vars = inputs_outputs@node.node_locals in |
|
224 |
let defs, vars = |
|
225 |
List.fold_left (inject_eq node) ([], orig_vars) (get_node_eqs node) in |
|
226 |
(* Normalize the asserts *) |
|
227 |
let vars, assert_defs, asserts = |
|
228 |
List.fold_left ( |
|
229 |
fun (vars, def_accu, assert_accu) assert_ -> |
|
230 |
let assert_expr = assert_.assert_expr in |
|
231 |
let (defs, vars'), expr = |
|
232 |
inject_expr |
|
233 |
~alias:false |
|
234 |
node |
|
235 |
([], vars) (* defvar only contains vars *) |
|
236 |
assert_expr |
|
237 |
in |
|
238 |
vars', defs@def_accu, {assert_ with assert_expr = expr}::assert_accu |
|
239 |
) (vars, [], []) node.node_asserts in |
|
240 |
let new_locals = List.filter is_local vars in |
|
241 |
(* Compute traceability info: |
|
242 |
- gather newly bound variables |
|
243 |
- compute the associated expression without aliases |
|
244 |
*) |
|
245 |
(* let diff_vars = List.filter (fun v -> not (List.mem v node.node_locals)) new_locals in *) |
|
246 |
let node = |
|
247 |
{ node with |
|
248 |
node_locals = new_locals; |
|
249 |
node_stmts = List.map (fun eq -> Eq eq) (defs @ assert_defs); |
|
250 |
} |
|
251 |
in ((*Printers.pp_node Format.err_formatter node;*) node) |
|
252 |
|
|
253 |
let inject_decl decl = |
|
254 |
match decl.top_decl_desc with |
|
255 |
| Node nd -> |
|
256 |
{decl with top_decl_desc = Node (inject_node nd)} |
|
257 |
| Open _ | ImportedNode _ | Const _ | TypeDef _ -> decl |
|
258 |
|
|
259 |
let inject_prog decls = |
|
260 |
List.map inject_decl decls |
|
261 |
|
|
262 |
|
|
263 |
(* Local Variables: *) |
|
264 |
(* compile-command:"make -C .." *) |
|
265 |
(* End: *) |
src/plugins/salsa/salsa_plugin.ml | ||
---|---|---|
1 |
open Format |
|
2 |
open LustreSpec |
|
3 |
|
|
4 |
let salsa_enabled = ref false |
|
5 |
(* "-salsa", Arg.Set salsa_enabled, "activate Salsa optimization <default>"; *) |
|
6 |
(* "-no-salsa", Arg.Clear salsa_enabled, "deactivate Salsa optimization"; *) |
|
7 |
|
|
8 |
|
|
9 |
module Plugin = |
|
10 |
(struct |
|
11 |
include PluginType.Default |
|
12 |
let name = "salsa" |
|
13 |
|
|
14 |
let options = [ |
|
15 |
|
|
16 |
] |
|
17 |
|
|
18 |
let activate () = salsa_enabled := true |
|
19 |
|
|
20 |
let refine_machine_code prog machine_code = |
|
21 |
if !salsa_enabled then |
|
22 |
begin |
|
23 |
Compiler_common.check_main (); |
|
24 |
Log.report ~level:1 (fun fmt -> fprintf fmt ".. salsa machines optimization (phase 3)@ "); |
|
25 |
(* Selecting float constants for Salsa *) |
|
26 |
let constEnv = List.fold_left ( |
|
27 |
fun accu c_topdecl -> |
|
28 |
match c_topdecl.top_decl_desc with |
|
29 |
| Const c when Types.is_real_type c.const_type -> |
|
30 |
(c.const_id, c.const_value) :: accu |
|
31 |
| _ -> accu |
|
32 |
) [] (Corelang.get_consts prog) |
|
33 |
in |
|
34 |
List.map |
|
35 |
(Machine_salsa_opt.machine_t2machine_t_optimized_by_salsa constEnv) |
|
36 |
machine_code |
|
37 |
end |
|
38 |
else |
|
39 |
machine_code |
|
40 |
|
|
41 |
|
|
42 |
end: PluginType.PluginType) |
src/plugins/scopes/scopes.ml | ||
---|---|---|
227 | 227 |
} |
228 | 228 |
|
229 | 229 |
|
230 |
module Plugin = |
|
230 |
module Plugin : PluginType.PluginType =
|
|
231 | 231 |
struct |
232 | 232 |
let name = "scopes" |
233 | 233 |
let is_active () = |
... | ... | |
250 | 250 |
let activate () = |
251 | 251 |
option_scopes := true; |
252 | 252 |
Options.optimization := 0; (* no optimization *) |
253 |
Options.salsa_enabled := false; (* No salsa *) |
|
253 |
|
|
254 |
(* Options.salsa_enabled := false; (\* No salsa *\) TODO *) |
|
254 | 255 |
() |
255 | 256 |
|
256 | 257 |
let rec is_valid_path path nodename prog machines = |
... | ... | |
312 | 313 |
|
313 | 314 |
let pp fmt = pp_scopes fmt !scopes_map |
314 | 315 |
|
316 |
let check_force_stateful () = true |
|
317 |
|
|
318 |
let refine_machine_code prog machine_code = |
|
319 |
if show_scopes () then |
|
320 |
begin |
|
321 |
let all_scopes = compute_scopes prog !Options.main_node in |
|
322 |
(* Printing scopes *) |
|
323 |
if !Options.verbose_level >= 1 then |
|
324 |
Format.printf "Possible scopes are:@ "; |
|
325 |
Format.printf "@[<v>%a@ @]@.@?" print_scopes all_scopes; |
|
326 |
exit 0 |
|
327 |
end; |
|
328 |
if is_active () then |
|
329 |
process_scopes !Options.main_node prog machine_code |
|
330 |
else |
|
331 |
machine_code |
|
332 |
|
|
333 |
|
|
334 |
|
|
335 |
let c_backend_main_loop_body_suffix fmt () = |
|
336 |
if is_active () then |
|
337 |
begin |
|
338 |
Format.fprintf fmt "@ %t" pp |
|
339 |
end; |
|
340 |
|
|
315 | 341 |
end |
316 | 342 |
|
317 | 343 |
(* Local Variables: *) |
Also available in: Unified diff
Plugin based framework