Project

General

Profile

« Previous | Next » 

Revision f0195e96

Added by Pierre-Loïc Garoche over 3 years ago

- Primitive Tiny backend
- Renamed Mpfr to lustrec_mpfr
- Introduced dependency in Zarith. Trying to move away from Num

View differences:

configure.ac
78 78

  
79 79
# Seal
80 80
AC_MSG_CHECKING(seal library (optional))
81
AS_IF([ocamlfind query seal >/dev/null 2>&1; echo 1],
81
AS_IF([ocamlfind query seal >/dev/null 2>&1],
82 82
    [seal=yes; AC_MSG_RESULT(yes)],[seal=no; AC_MSG_RESULT(no)],
83 83
)
84 84
AS_IF([test "x$seal" = "xyes"], [
85 85
   AC_SUBST(LUSTREV_SEAL, "(module Seal_verifier.Verifier : VerifierType.S);")
86
   AC_SUBST(LUSTREV_SEAL_TAG, "") # <**/*>: package(seal)")
86
   AC_SUBST(LUSTREV_SEAL_TAG, "<**/*>: package(seal)")
87
])
88

  
89
# Tiny
90
AC_MSG_CHECKING(tiny library (optional))
91
AS_IF([ocamlfind query tiny >/dev/null 2>&1],
92
    [tiny=yes; AC_MSG_RESULT(yes)],[tiny=no; AC_MSG_RESULT(no)],
93
)
94
AS_IF([test "x$tiny" = "xyes"], [
95
 dnl   AC_SUBST(LUSTREV_TINY_TAG, "<**/*>: package(apron.boxMPQ), package(apron.octMPQ), package(apron.polkaMPQ), package(tiny)")
87 96
])
88 97

  
89 98
# z3 (optional)
......
125 134
])
126 135

  
127 136

  
128
# Tiny
129
AC_MSG_CHECKING(tiny library (optional))
130
AS_IF([ocamlfind query tiny >/dev/null 2>&1],
131
    [tiny=yes; AC_MSG_RESULT(yes)],[tiny=no; AC_MSG_RESULT(no)],
132
)
137
dnl # Tiny
138
dnl AC_MSG_CHECKING(tiny library (optional))
139
dnl AS_IF([ocamlfind query tiny >/dev/null 2>&1],
140
dnl     [tiny=yes; AC_MSG_RESULT(yes)],[tiny=no; AC_MSG_RESULT(no)],
141
dnl )
133 142
AS_IF([test "x$tiny" = "xyes"], [
134 143
   AC_SUBST(LUSTREV_TINY, "(module Tiny_verifier.Verifier : VerifierType.S);")
135
   AC_SUBST(LUSTREV_TINY_TAG, "<**/*>: package(tiny)")
144
   AC_SUBST(LUSTREV_TINY_TAG, ["<**/*>: package(apron.boxMPQ), package(apron.octMPQ), package(apron.polkaMPQ), package(tiny)"])
136 145
])
137 146

  
138 147
# Salsa
src/_tags.in
25 25
"tools/stateflow/json-parser": include
26 26
"tools/importer": include
27 27
"tools/seal": include
28
"tools/tiny": include
28 29

  
29 30
# svn
30 31
<**/.svn>: -traverse
......
36 37
<**/*verifier.native> or <**/*.ml{,i}> : package(yojson)
37 38

  
38 39
<**/*.native>                   : use_str
39
<**/main_lustre_compiler.native>: use_unix
40
<**/main_lustre_testgen.native> : use_unix
41
<**/main_lustre_verifier.native> : use_unix
42
<**/sf_sem.native>              : use_unix
40
<**/main_lustre_compiler.native>: package(unix)
41
<**/main_lustre_testgen.native> : package(unix)
42
<**/main_lustre_verifier.native> : package(unix)
43
<**/sf_sem.native>              : package(unix)
43 44
<**/*>                          : package(num)
45
<**/*>                          : package(zarith)
44 46
<**/*.ml>                       : package(logs)
45 47
<**/*.native>                   : package(logs)
46 48
<**/json_parser.ml>             : package(yojson)
src/backends/C/c_backend_common.ml
14 14
open Corelang
15 15
open Machine_code_types
16 16
(*open Machine_code_common*)
17

  
17
module Mpfr = Lustrec_mpfr
18 18

  
19 19
let print_version fmt =
20 20
  Format.fprintf fmt 
src/compiler_stages.ml
2 2
open Utils
3 3
open Compiler_common
4 4
open Lustre_types
5
module Mpfr = Lustrec_mpfr
5 6

  
6 7
exception StopPhase1 of program_t
7 8

  
src/machine_code_common.mli
22 22

  
23 23
val get_node_def: string -> Machine_code_types.machine_t -> Lustre_types.node_desc
24 24
val join_guards_list: Machine_code_types.instr_t list -> Machine_code_types.instr_t list
25
val machine_vars: Machine_code_types.machine_t -> Lustre_types.var_decl list
src/main_lustre_compiler.ml
52 52
    if !Options.mpfr &&
53 53
         extension = ".lus" (* trying to avoid the injection of the module for lusi files *) 
54 54
    then
55
      Mpfr.mpfr_module::prog
55
      Lustrec_mpfr.mpfr_module::prog
56 56
    else
57 57
      prog
58 58
  in
src/optimize_machine.ml
16 16
open Causality
17 17
open Machine_code_common
18 18
open Dimension
19
module Mpfr = Lustrec_mpfr
19 20

  
20 21

  
21 22
let pp_elim m fmt elim =
src/plugins/mpfr/lustrec_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 Lustre_types
14
open Machine_code_types
15
open Corelang
16
open Normalization
17
open Machine_code_common
18

  
19
let report = Log.report ~plugin:"MPFR"
20
           
21
let mpfr_module = mktop (Open(false, "mpfr_lustre"))
22
let cpt_fresh = ref 0
23
  
24
let mpfr_rnd () = "MPFR_RNDN"
25

  
26
let mpfr_prec () = !Options.mpfr_prec
27

  
28
let inject_id = "MPFRId"
29

  
30
let inject_copy_id = "mpfr_set"
31

  
32
let inject_real_id = "mpfr_set_flt"
33

  
34
let inject_init_id = "mpfr_init2"
35

  
36
let inject_clear_id = "mpfr_clear"
37

  
38
let mpfr_t = "mpfr_t"
39

  
40
let unfoldable_value value =
41
  not (Types.is_real_type value.value_type && is_const_value value)
42

  
43
let inject_id_id expr =
44
  let e = mkpredef_call expr.expr_loc inject_id [expr] in
45
  { e with
46
    expr_type = Type_predef.type_real;
47
    expr_clock = expr.expr_clock;
48
  }
49

  
50
let pp_inject_real pp_var pp_val fmt var value =
51
  Format.fprintf fmt "%s(%a, %a, %s);"
52
    inject_real_id
53
    pp_var var
54
    pp_val value
55
    (mpfr_rnd ())
56

  
57
let inject_assign expr =
58
  let e = mkpredef_call expr.expr_loc inject_copy_id [expr] in
59
  { e with
60
    expr_type = Type_predef.type_real;
61
    expr_clock = expr.expr_clock;
62
  }
63

  
64
let pp_inject_copy pp_var fmt var value =
65
  Format.fprintf fmt "%s(%a, %a, %s);"
66
    inject_copy_id
67
    pp_var var
68
    pp_var value
69
    (mpfr_rnd ())
70

  
71
let rec pp_inject_assign pp_var fmt var value =
72
  if is_const_value value
73
  then
74
    pp_inject_real pp_var pp_var fmt var value
75
  else
76
    pp_inject_copy pp_var fmt var value
77

  
78
let pp_inject_init pp_var fmt var =
79
  Format.fprintf fmt "%s(%a, %i);"
80
    inject_init_id
81
    pp_var var
82
    (mpfr_prec ())
83

  
84
let pp_inject_clear pp_var fmt var =
85
  Format.fprintf fmt "%s(%a);"
86
    inject_clear_id
87
    pp_var var
88

  
89
let base_inject_op id =
90
  match id with
91
  | "+"      -> "MPFRPlus"
92
  | "-"      -> "MPFRMinus"
93
  | "*"      -> "MPFRTimes"
94
  | "/"      -> "MPFRDiv"
95
  | "uminus" -> "MPFRUminus"
96
  | "<="     -> "MPFRLe"
97
  | "<"      -> "MPFRLt"
98
  | ">="     -> "MPFRGe"
99
  | ">"      -> "MPFRGt"
100
  | "="      -> "MPFREq"
101
  | "!="     -> "MPFRNeq"
102
  (* Conv functions *)
103
  | "int_to_real" -> "MPFRint_to_real"
104
  | "real_to_int" -> "MPFRreal_to_int"
105
  | "_floor" -> "MPFRfloor"        
106
  | "_ceil" -> "MPFRceil"        
107
  | "_round" -> "MPFRround"        
108
  | "_Floor" -> "MPFRFloor"        
109
  | "_Ceiling" -> "MPFRCeiling"        
110
  | "_Round" -> "MPFRRound"        
111
       
112
  (* Math library functions *)
113
  | "acos" -> "MPFRacos"
114
  | "acosh" -> "MPFRacosh"
115
  | "asin" -> "MPFRasin"
116
  | "asinh" -> "MPFRasinh"
117
  | "atan" -> "MPFRatan"
118
  | "atan2" -> "MPFRatan2"
119
  | "atanh" -> "MPFRatanh"
120
  | "cbrt" -> "MPFRcbrt"
121
  | "cos" -> "MPFRcos"
122
  | "cosh" -> "MPFRcosh"
123
  | "ceil" -> "MPFRceil"
124
  | "erf" -> "MPFRerf"
125
  | "exp" -> "MPFRexp"
126
  | "fabs" -> "MPFRfabs"
127
  | "floor" -> "MPFRfloor"
128
  | "fmod" -> "MPFRfmod"
129
  | "log" -> "MPFRlog"
130
  | "log10" -> "MPFRlog10"
131
  | "pow" -> "MPFRpow"
132
  | "round" -> "MPFRround"
133
  | "sin" -> "MPFRsin"
134
  | "sinh" -> "MPFRsinh"
135
  | "sqrt" -> "MPFRsqrt"
136
  | "trunc" -> "MPFRtrunc"
137
  | "tan" -> "MPFRtan"
138
  | _        -> raise Not_found
139

  
140
let inject_op id =
141
  report ~level:3 (fun fmt -> Format.fprintf fmt "trying to inject mpfr into function %s@." id);
142
  try
143
    base_inject_op id
144
  with Not_found -> id
145

  
146
let homomorphic_funs =
147
  List.fold_right (fun id res -> try base_inject_op id :: res with Not_found -> res) Basic_library.internal_funs []
148

  
149
let is_homomorphic_fun id =
150
  List.mem id homomorphic_funs
151

  
152
let inject_call expr =
153
  match expr.expr_desc with
154
  | Expr_appl (id, args, None) when not (Basic_library.is_expr_internal_fun expr) ->
155
    { expr with expr_desc = Expr_appl (inject_op id, args, None) }
156
  | _ -> expr
157

  
158
let expr_of_const_array expr =
159
  match expr.expr_desc with
160
  | Expr_const (Const_array cl) ->
161
    let typ = Types.array_element_type expr.expr_type in
162
    let expr_of_const c =
163
      { expr_desc = Expr_const c;
164
	expr_type = typ;
165
	expr_clock = expr.expr_clock;
166
	expr_loc = expr.expr_loc;
167
	expr_delay = Delay.new_var ();
168
	expr_annot = None;
169
	expr_tag = new_tag ();
170
      }
171
    in { expr with expr_desc = Expr_array (List.map expr_of_const cl) }
172
  | _                           -> assert false
173

  
174
(* inject_<foo> : defs * used vars -> <foo> -> (updated defs * updated vars) * normalized <foo> *)
175
let rec inject_list alias node inject_element defvars elist =
176
  List.fold_right
177
    (fun t (defvars, qlist) ->
178
      let defvars, norm_t = inject_element alias node defvars t in
179
      (defvars, norm_t :: qlist)
180
    ) elist (defvars, [])
181

  
182
let rec inject_expr ?(alias=true) node defvars expr =
183
let res =
184
  match expr.expr_desc with
185
  | Expr_const (Const_real _)  -> mk_expr_alias_opt alias node defvars expr
186
  | Expr_const (Const_array _) -> inject_expr ~alias:alias node defvars (expr_of_const_array expr)
187
  | Expr_const (Const_struct _) -> assert false
188
  | Expr_ident _
189
  | Expr_const _  -> defvars, expr
190
  | Expr_array elist ->
191
    let defvars, norm_elist = inject_list alias node (fun _ -> inject_expr ~alias:true) defvars elist in
192
    let norm_expr = { expr with expr_desc = Expr_array norm_elist } in
193
    defvars, norm_expr
194
  | Expr_power (e1, d) ->
195
    let defvars, norm_e1 = inject_expr node defvars e1 in
196
    let norm_expr = { expr with expr_desc = Expr_power (norm_e1, d) } in
197
    defvars, norm_expr
198
  | Expr_access (e1, d) ->
199
    let defvars, norm_e1 = inject_expr node defvars e1 in
200
    let norm_expr = { expr with expr_desc = Expr_access (norm_e1, d) } in
201
    defvars, norm_expr
202
  | Expr_tuple elist -> 
203
    let defvars, norm_elist =
204
      inject_list alias node (fun alias -> inject_expr ~alias:alias) defvars elist in
205
    let norm_expr = { expr with expr_desc = Expr_tuple norm_elist } in
206
    defvars, norm_expr
207
  | Expr_appl (id, args, r) ->
208
    let defvars, norm_args = inject_expr node defvars args in
209
    let norm_expr = { expr with expr_desc = Expr_appl (id, norm_args, r) } in
210
    mk_expr_alias_opt alias node defvars (inject_call norm_expr)
211
  | Expr_arrow _ -> defvars, expr
212
  | Expr_pre e ->
213
    let defvars, norm_e = inject_expr node defvars e in
214
    let norm_expr = { expr with expr_desc = Expr_pre norm_e } in
215
    defvars, norm_expr
216
  | Expr_fby (e1, e2) ->
217
    let defvars, norm_e1 = inject_expr node defvars e1 in
218
    let defvars, norm_e2 = inject_expr node defvars e2 in
219
    let norm_expr = { expr with expr_desc = Expr_fby (norm_e1, norm_e2) } in
220
    defvars, norm_expr
221
  | Expr_when (e, c, l) ->
222
    let defvars, norm_e = inject_expr node defvars e in
223
    let norm_expr = { expr with expr_desc = Expr_when (norm_e, c, l) } in
224
    defvars, norm_expr
225
  | Expr_ite (c, t, e) ->
226
    let defvars, norm_c = inject_expr node defvars c in
227
    let defvars, norm_t = inject_expr node defvars t in
228
    let defvars, norm_e = inject_expr node defvars e in
229
    let norm_expr = { expr with expr_desc = Expr_ite (norm_c, norm_t, norm_e) } in
230
    defvars, norm_expr
231
  | Expr_merge (c, hl) ->
232
    let defvars, norm_hl = inject_branches node defvars hl in
233
    let norm_expr = { expr with expr_desc = Expr_merge (c, norm_hl) } in
234
    defvars, norm_expr
235
in
236
(*Format.eprintf "inject_expr %B %a = %a@." alias Printers.pp_expr expr Printers.pp_expr (snd res);*)
237
res
238

  
239
and inject_branches node defvars hl =
240
 List.fold_right
241
   (fun (t, h) (defvars, norm_q) ->
242
     let (defvars, norm_h) = inject_expr node defvars h in
243
     defvars, (t, norm_h) :: norm_q
244
   )
245
   hl (defvars, [])
246

  
247

  
248
let rec inject_eq node defvars eq =
249
  let (defs', vars'), norm_rhs = inject_expr ~alias:false node defvars eq.eq_rhs in
250
  let norm_eq = { eq with eq_rhs = norm_rhs } in
251
  norm_eq::defs', vars'
252

  
253
(* let inject_eexpr ee =
254
 *   { ee with eexpr_qfexpr = inject_expr ee.eexpr_qfexpr }
255
 *   
256
 * let inject_spec s =
257
 *   { s with
258
 *     assume = List.map inject_eexpr s.assume;
259
 *     guarantees = List.map inject_eexpr s.guarantees;
260
 *     modes = List.map (fun m ->
261
 *                 { m with
262
 *                   require = List.map inject_eexpr m.require;
263
 *                   ensure = List.map inject_eexpr m.ensure
264
 *                 }
265
 *               ) s.modes
266
 *   } *)
267
  
268
(** normalize_node node returns a normalized node, 
269
    ie. 
270
    - updated locals
271
    - new equations
272
    - 
273
*)
274
let inject_node node = 
275
  cpt_fresh := 0;
276
  let inputs_outputs = node.node_inputs@node.node_outputs in
277
  let norm_ctx = (node.node_id, get_node_vars node) in
278
  let is_local v =
279
    List.for_all ((!=) v) inputs_outputs in
280
  let orig_vars = inputs_outputs@node.node_locals in
281
  let defs, vars =
282
    let eqs, auts = get_node_eqs node in
283
    if auts != [] then assert false; (* Automata should be expanded by now. *)
284
    List.fold_left (inject_eq norm_ctx) ([], orig_vars) eqs in
285
  (* Normalize the asserts *)
286
  let vars, assert_defs, asserts = 
287
    List.fold_left (
288
    fun (vars, def_accu, assert_accu) assert_ ->
289
      let assert_expr = assert_.assert_expr in
290
      let (defs, vars'), expr = 
291
	inject_expr 
292
	  ~alias:false 
293
	  norm_ctx 
294
	  ([], vars) (* defvar only contains vars *)
295
	  assert_expr
296
      in
297
      vars', defs@def_accu, {assert_ with assert_expr = expr}::assert_accu
298
    ) (vars, [], []) node.node_asserts in
299
  let new_locals = List.filter is_local vars in
300
  (* Compute traceability info: 
301
     - gather newly bound variables
302
     - compute the associated expression without aliases     
303
  *)
304
  (* let diff_vars = List.filter (fun v -> not (List.mem v node.node_locals)) new_locals in *)
305
  (* See comment below
306
   *  let spec = match node.node_spec with
307
   *   | None -> None
308
   *   | Some spec -> Some (inject_spec spec)
309
   * in *)
310
  let node =
311
  { node with 
312
    node_locals = new_locals; 
313
    node_stmts = List.map (fun eq -> Eq eq) (defs @ assert_defs);
314
    (* Incomplete work: TODO. Do we have to inject MPFR code here?
315
       Does it make sense for annotations? For me, only if we produce
316
       C code for annotations. Otherwise the various verification
317
       backend should have their own understanding, but would not
318
       necessarily require this additional normalization. *)
319
    (* 
320
       node_spec = spec;
321
       node_annot = List.map (fun ann -> {ann with
322
           annots = List.map (fun (ids, ee) -> ids, inject_eexpr ee) ann.annots}
323
         ) node.node_annot *)
324
  }
325
  in ((*Printers.pp_node Format.err_formatter node;*) node)
326

  
327
let inject_decl decl =
328
  match decl.top_decl_desc with
329
  | Node nd ->
330
    {decl with top_decl_desc = Node (inject_node nd)}
331
  | Include _ | Open _ | ImportedNode _ | Const _ | TypeDef _ -> decl
332
  
333
let inject_prog decls = 
334
  List.map inject_decl decls
335

  
336

  
337
(* Local Variables: *)
338
(* compile-command:"make -C .." *)
339
(* End: *)
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 Lustre_types
14
open Machine_code_types
15
open Corelang
16
open Normalization
17
open Machine_code_common
18

  
19
let report = Log.report ~plugin:"MPFR"
20
           
21
let mpfr_module = mktop (Open(false, "mpfr_lustre"))
22
let cpt_fresh = ref 0
23
  
24
let mpfr_rnd () = "MPFR_RNDN"
25

  
26
let mpfr_prec () = !Options.mpfr_prec
27

  
28
let inject_id = "MPFRId"
29

  
30
let inject_copy_id = "mpfr_set"
31

  
32
let inject_real_id = "mpfr_set_flt"
33

  
34
let inject_init_id = "mpfr_init2"
35

  
36
let inject_clear_id = "mpfr_clear"
37

  
38
let mpfr_t = "mpfr_t"
39

  
40
let unfoldable_value value =
41
  not (Types.is_real_type value.value_type && is_const_value value)
42

  
43
let inject_id_id expr =
44
  let e = mkpredef_call expr.expr_loc inject_id [expr] in
45
  { e with
46
    expr_type = Type_predef.type_real;
47
    expr_clock = expr.expr_clock;
48
  }
49

  
50
let pp_inject_real pp_var pp_val fmt var value =
51
  Format.fprintf fmt "%s(%a, %a, %s);"
52
    inject_real_id
53
    pp_var var
54
    pp_val value
55
    (mpfr_rnd ())
56

  
57
let inject_assign expr =
58
  let e = mkpredef_call expr.expr_loc inject_copy_id [expr] in
59
  { e with
60
    expr_type = Type_predef.type_real;
61
    expr_clock = expr.expr_clock;
62
  }
63

  
64
let pp_inject_copy pp_var fmt var value =
65
  Format.fprintf fmt "%s(%a, %a, %s);"
66
    inject_copy_id
67
    pp_var var
68
    pp_var value
69
    (mpfr_rnd ())
70

  
71
let rec pp_inject_assign pp_var fmt var value =
72
  if is_const_value value
73
  then
74
    pp_inject_real pp_var pp_var fmt var value
75
  else
76
    pp_inject_copy pp_var fmt var value
77

  
78
let pp_inject_init pp_var fmt var =
79
  Format.fprintf fmt "%s(%a, %i);"
80
    inject_init_id
81
    pp_var var
82
    (mpfr_prec ())
83

  
84
let pp_inject_clear pp_var fmt var =
85
  Format.fprintf fmt "%s(%a);"
86
    inject_clear_id
87
    pp_var var
88

  
89
let base_inject_op id =
90
  match id with
91
  | "+"      -> "MPFRPlus"
92
  | "-"      -> "MPFRMinus"
93
  | "*"      -> "MPFRTimes"
94
  | "/"      -> "MPFRDiv"
95
  | "uminus" -> "MPFRUminus"
96
  | "<="     -> "MPFRLe"
97
  | "<"      -> "MPFRLt"
98
  | ">="     -> "MPFRGe"
99
  | ">"      -> "MPFRGt"
100
  | "="      -> "MPFREq"
101
  | "!="     -> "MPFRNeq"
102
  (* Conv functions *)
103
  | "int_to_real" -> "MPFRint_to_real"
104
  | "real_to_int" -> "MPFRreal_to_int"
105
  | "_floor" -> "MPFRfloor"        
106
  | "_ceil" -> "MPFRceil"        
107
  | "_round" -> "MPFRround"        
108
  | "_Floor" -> "MPFRFloor"        
109
  | "_Ceiling" -> "MPFRCeiling"        
110
  | "_Round" -> "MPFRRound"        
111
       
112
  (* Math library functions *)
113
  | "acos" -> "MPFRacos"
114
  | "acosh" -> "MPFRacosh"
115
  | "asin" -> "MPFRasin"
116
  | "asinh" -> "MPFRasinh"
117
  | "atan" -> "MPFRatan"
118
  | "atan2" -> "MPFRatan2"
119
  | "atanh" -> "MPFRatanh"
120
  | "cbrt" -> "MPFRcbrt"
121
  | "cos" -> "MPFRcos"
122
  | "cosh" -> "MPFRcosh"
123
  | "ceil" -> "MPFRceil"
124
  | "erf" -> "MPFRerf"
125
  | "exp" -> "MPFRexp"
126
  | "fabs" -> "MPFRfabs"
127
  | "floor" -> "MPFRfloor"
128
  | "fmod" -> "MPFRfmod"
129
  | "log" -> "MPFRlog"
130
  | "log10" -> "MPFRlog10"
131
  | "pow" -> "MPFRpow"
132
  | "round" -> "MPFRround"
133
  | "sin" -> "MPFRsin"
134
  | "sinh" -> "MPFRsinh"
135
  | "sqrt" -> "MPFRsqrt"
136
  | "trunc" -> "MPFRtrunc"
137
  | "tan" -> "MPFRtan"
138
  | _        -> raise Not_found
139

  
140
let inject_op id =
141
  report ~level:3 (fun fmt -> Format.fprintf fmt "trying to inject mpfr into function %s@." id);
142
  try
143
    base_inject_op id
144
  with Not_found -> id
145

  
146
let homomorphic_funs =
147
  List.fold_right (fun id res -> try base_inject_op id :: res with Not_found -> res) Basic_library.internal_funs []
148

  
149
let is_homomorphic_fun id =
150
  List.mem id homomorphic_funs
151

  
152
let inject_call expr =
153
  match expr.expr_desc with
154
  | Expr_appl (id, args, None) when not (Basic_library.is_expr_internal_fun expr) ->
155
    { expr with expr_desc = Expr_appl (inject_op id, args, None) }
156
  | _ -> expr
157

  
158
let expr_of_const_array expr =
159
  match expr.expr_desc with
160
  | Expr_const (Const_array cl) ->
161
    let typ = Types.array_element_type expr.expr_type in
162
    let expr_of_const c =
163
      { expr_desc = Expr_const c;
164
	expr_type = typ;
165
	expr_clock = expr.expr_clock;
166
	expr_loc = expr.expr_loc;
167
	expr_delay = Delay.new_var ();
168
	expr_annot = None;
169
	expr_tag = new_tag ();
170
      }
171
    in { expr with expr_desc = Expr_array (List.map expr_of_const cl) }
172
  | _                           -> assert false
173

  
174
(* inject_<foo> : defs * used vars -> <foo> -> (updated defs * updated vars) * normalized <foo> *)
175
let rec inject_list alias node inject_element defvars elist =
176
  List.fold_right
177
    (fun t (defvars, qlist) ->
178
      let defvars, norm_t = inject_element alias node defvars t in
179
      (defvars, norm_t :: qlist)
180
    ) elist (defvars, [])
181

  
182
let rec inject_expr ?(alias=true) node defvars expr =
183
let res =
184
  match expr.expr_desc with
185
  | Expr_const (Const_real _)  -> mk_expr_alias_opt alias node defvars expr
186
  | Expr_const (Const_array _) -> inject_expr ~alias:alias node defvars (expr_of_const_array expr)
187
  | Expr_const (Const_struct _) -> assert false
188
  | Expr_ident _
189
  | Expr_const _  -> defvars, expr
190
  | Expr_array elist ->
191
    let defvars, norm_elist = inject_list alias node (fun _ -> inject_expr ~alias:true) defvars elist in
192
    let norm_expr = { expr with expr_desc = Expr_array norm_elist } in
193
    defvars, norm_expr
194
  | Expr_power (e1, d) ->
195
    let defvars, norm_e1 = inject_expr node defvars e1 in
196
    let norm_expr = { expr with expr_desc = Expr_power (norm_e1, d) } in
197
    defvars, norm_expr
198
  | Expr_access (e1, d) ->
199
    let defvars, norm_e1 = inject_expr node defvars e1 in
200
    let norm_expr = { expr with expr_desc = Expr_access (norm_e1, d) } in
201
    defvars, norm_expr
202
  | Expr_tuple elist -> 
203
    let defvars, norm_elist =
204
      inject_list alias node (fun alias -> inject_expr ~alias:alias) defvars elist in
205
    let norm_expr = { expr with expr_desc = Expr_tuple norm_elist } in
206
    defvars, norm_expr
207
  | Expr_appl (id, args, r) ->
208
    let defvars, norm_args = inject_expr node defvars args in
209
    let norm_expr = { expr with expr_desc = Expr_appl (id, norm_args, r) } in
210
    mk_expr_alias_opt alias node defvars (inject_call norm_expr)
211
  | Expr_arrow _ -> defvars, expr
212
  | Expr_pre e ->
213
    let defvars, norm_e = inject_expr node defvars e in
214
    let norm_expr = { expr with expr_desc = Expr_pre norm_e } in
215
    defvars, norm_expr
216
  | Expr_fby (e1, e2) ->
217
    let defvars, norm_e1 = inject_expr node defvars e1 in
218
    let defvars, norm_e2 = inject_expr node defvars e2 in
219
    let norm_expr = { expr with expr_desc = Expr_fby (norm_e1, norm_e2) } in
220
    defvars, norm_expr
221
  | Expr_when (e, c, l) ->
222
    let defvars, norm_e = inject_expr node defvars e in
223
    let norm_expr = { expr with expr_desc = Expr_when (norm_e, c, l) } in
224
    defvars, norm_expr
225
  | Expr_ite (c, t, e) ->
226
    let defvars, norm_c = inject_expr node defvars c in
227
    let defvars, norm_t = inject_expr node defvars t in
228
    let defvars, norm_e = inject_expr node defvars e in
229
    let norm_expr = { expr with expr_desc = Expr_ite (norm_c, norm_t, norm_e) } in
230
    defvars, norm_expr
231
  | Expr_merge (c, hl) ->
232
    let defvars, norm_hl = inject_branches node defvars hl in
233
    let norm_expr = { expr with expr_desc = Expr_merge (c, norm_hl) } in
234
    defvars, norm_expr
235
in
236
(*Format.eprintf "inject_expr %B %a = %a@." alias Printers.pp_expr expr Printers.pp_expr (snd res);*)
237
res
238

  
239
and inject_branches node defvars hl =
240
 List.fold_right
241
   (fun (t, h) (defvars, norm_q) ->
242
     let (defvars, norm_h) = inject_expr node defvars h in
243
     defvars, (t, norm_h) :: norm_q
244
   )
245
   hl (defvars, [])
246

  
247

  
248
let rec inject_eq node defvars eq =
249
  let (defs', vars'), norm_rhs = inject_expr ~alias:false node defvars eq.eq_rhs in
250
  let norm_eq = { eq with eq_rhs = norm_rhs } in
251
  norm_eq::defs', vars'
252

  
253
(* let inject_eexpr ee =
254
 *   { ee with eexpr_qfexpr = inject_expr ee.eexpr_qfexpr }
255
 *   
256
 * let inject_spec s =
257
 *   { s with
258
 *     assume = List.map inject_eexpr s.assume;
259
 *     guarantees = List.map inject_eexpr s.guarantees;
260
 *     modes = List.map (fun m ->
261
 *                 { m with
262
 *                   require = List.map inject_eexpr m.require;
263
 *                   ensure = List.map inject_eexpr m.ensure
264
 *                 }
265
 *               ) s.modes
266
 *   } *)
267
  
268
(** normalize_node node returns a normalized node, 
269
    ie. 
270
    - updated locals
271
    - new equations
272
    - 
273
*)
274
let inject_node node = 
275
  cpt_fresh := 0;
276
  let inputs_outputs = node.node_inputs@node.node_outputs in
277
  let norm_ctx = (node.node_id, get_node_vars node) in
278
  let is_local v =
279
    List.for_all ((!=) v) inputs_outputs in
280
  let orig_vars = inputs_outputs@node.node_locals in
281
  let defs, vars =
282
    let eqs, auts = get_node_eqs node in
283
    if auts != [] then assert false; (* Automata should be expanded by now. *)
284
    List.fold_left (inject_eq norm_ctx) ([], orig_vars) eqs in
285
  (* Normalize the asserts *)
286
  let vars, assert_defs, asserts = 
287
    List.fold_left (
288
    fun (vars, def_accu, assert_accu) assert_ ->
289
      let assert_expr = assert_.assert_expr in
290
      let (defs, vars'), expr = 
291
	inject_expr 
292
	  ~alias:false 
293
	  norm_ctx 
294
	  ([], vars) (* defvar only contains vars *)
295
	  assert_expr
296
      in
297
      vars', defs@def_accu, {assert_ with assert_expr = expr}::assert_accu
298
    ) (vars, [], []) node.node_asserts in
299
  let new_locals = List.filter is_local vars in
300
  (* Compute traceability info: 
301
     - gather newly bound variables
302
     - compute the associated expression without aliases     
303
  *)
304
  (* let diff_vars = List.filter (fun v -> not (List.mem v node.node_locals)) new_locals in *)
305
  (* See comment below
306
   *  let spec = match node.node_spec with
307
   *   | None -> None
308
   *   | Some spec -> Some (inject_spec spec)
309
   * in *)
310
  let node =
311
  { node with 
312
    node_locals = new_locals; 
313
    node_stmts = List.map (fun eq -> Eq eq) (defs @ assert_defs);
314
    (* Incomplete work: TODO. Do we have to inject MPFR code here?
315
       Does it make sense for annotations? For me, only if we produce
316
       C code for annotations. Otherwise the various verification
317
       backend should have their own understanding, but would not
318
       necessarily require this additional normalization. *)
319
    (* 
320
       node_spec = spec;
321
       node_annot = List.map (fun ann -> {ann with
322
           annots = List.map (fun (ids, ee) -> ids, inject_eexpr ee) ann.annots}
323
         ) node.node_annot *)
324
  }
325
  in ((*Printers.pp_node Format.err_formatter node;*) node)
326

  
327
let inject_decl decl =
328
  match decl.top_decl_desc with
329
  | Node nd ->
330
    {decl with top_decl_desc = Node (inject_node nd)}
331
  | Include _ | Open _ | ImportedNode _ | Const _ | TypeDef _ -> decl
332
  
333
let inject_prog decls = 
334
  List.map inject_decl decls
335

  
336

  
337
(* Local Variables: *)
338
(* compile-command:"make -C .." *)
339
(* End: *)
src/real.ml
16 16
  let num_10 = Num.num_of_int 10 in
17 17
  Num.(c // (num_10 **/ (num_of_int e)))
18 18

  
19
let rec to_q (c, e, s) =
20
  if e = 0 then
21
        Q.of_string (Num.string_of_num c)
22
  else
23
    if e > 0 then Q.div (to_q (c,e-1,s)) (Q.of_int 10)
24
    else (* if exp<0 then *)
25
      Q.mul
26
        (to_q (c,e+1,s))
27
        (Q.of_int 10)
28

  
19 29
let to_string (_, _, s) = s
20 30
                        
21 31
let eq r1 r2 =
src/real.mli
18 18
val diseq: t -> t -> bool
19 19
  
20 20
val to_num: t -> Num.num
21
val to_q: t -> Q.t
21 22
val to_string: t -> string
22 23
val eq: t -> t -> bool
23 24
val zero: t
src/tools/tiny/tiny_utils.ml
1

  
2
module Ast = Tiny.Ast
3

  
4

  
5
let lloc_to_tloc loc = Tiny.Location.dummy (*TODO*)
6
                     
7
let tloc_to_lloc loc = Location.dummy_loc (*TODO*)
8

  
9
                     
10
let ltyp_to_ttyp t =
11
  if Types.is_real_type t then Tiny.Ast.RealT
12
  else if Types.is_int_type t then Tiny.Ast.IntT
13
  else if Types.is_bool_type t then Tiny.Ast.BoolT
14
  else assert false (* not covered yet *)
15

  
16
let cst_bool loc b =
17
  { Ast.expr_desc =
18
      if b then
19
        Ast.Cst(Q.of_int 1, "true")
20
      else
21
        Ast.Cst(Q.of_int 0, "false");
22
    expr_loc = loc;
23
    expr_type = Ast.BoolT }
24
  
25
let rec real_to_q man exp =
26
  if exp = 0 then
27
        Q.of_string (Num.string_of_num man)
28
  else
29
    if exp > 0 then Q.div (real_to_q man (exp-1)) (Q.of_int 10)
30
    else (* if exp<0 then *)
31
      Q.mul
32
        (real_to_q man (exp+1))
33
        (Q.of_int 10)
34

  
35
let instr_loc i =
36
  match i.Machine_code_types.lustre_eq with
37
  | None -> Tiny.Location.dummy
38
  | Some eq -> lloc_to_tloc eq.eq_loc
39
             
40
let rec lval_to_texpr loc _val =
41
  let build d v =
42
      Ast.{ expr_desc = d;
43
            expr_loc = loc;
44
            expr_type = v }
45
  in
46
  let new_desc =
47
    match _val.Machine_code_types.value_desc with
48
  | Machine_code_types.Cst cst -> (
49
    match cst with
50
      Lustre_types.Const_int n -> Ast.Cst (Q.of_int n, string_of_int n)
51
    | Const_real r -> Ast.Cst (Real.to_q r, Real.to_string r) 
52
      | _ -> assert false
53
  )
54
     
55
  | Var v -> Ast.Var (v.var_id)
56
  | Fun (op, vl) ->
57
     let t_arg = match vl with
58
       | hd::_ -> ltyp_to_ttyp hd.value_type
59
       | _ -> assert false
60
     in
61
     (
62
       match op, List.map (lval_to_texpr loc) vl with
63
       | "+", [v1;v2] -> Ast.Binop (Ast.Plus, v1, v2)
64
       | "-", [v1;v2] -> Ast.Binop (Ast.Minus, v1, v2)
65
       | "*", [v1;v2] -> Ast.Binop (Ast.Times, v1, v2)
66
       | "/", [v1;v2] -> Ast.Binop (Ast.Div, v1, v2)
67
       | "<", [v1;v2] ->
68
          Ast.Cond (build (Ast.Binop (Ast.Minus, v2, v1)) t_arg, Ast.Strict)
69
       | "<=", [v1;v2] ->
70
          Ast.Cond (build(Ast.Binop (Ast.Minus, v2, v1)) t_arg, Ast.Loose)
71
       | ">", [v1;v2] ->
72
          Ast.Cond (build(Ast.Binop (Ast.Minus, v1, v2)) t_arg, Ast.Strict)
73
       | ">=", [v1;v2] ->
74
          Ast.Cond (build (Ast.Binop (Ast.Minus, v1, v2)) t_arg, Ast.Loose)
75
       | "=", [v1;v2] ->
76
          Ast.Cond (build (Ast.Binop (Ast.Minus, v2, v1)) t_arg, Ast.Zero)
77
       | "!=", [v1;v2] ->
78
          Ast.Cond (build (Ast.Binop (Ast.Minus, v2, v1)) t_arg, Ast.NonZero)
79
       | _ -> Format.eprintf "No tiny translation for operator %s@.@?" op; assert false    
80
  )
81
  | _ -> assert false (* no array. access or power *)
82
  in
83
  build new_desc (ltyp_to_ttyp _val.value_type)
84

  
85
  
86
let machine_body_to_ast init m =
87
  let init_var = ref None in
88
  let rec guarded_expr_to_stm loc te guarded_instrs =
89
    match guarded_instrs with
90
    | [] -> assert false
91
    | [_,il] -> instrl_to_stm il
92
    | (label, il)::tl ->
93
       let stmt = instrl_to_stm il in
94
       let guard= match label with
95
           "true" -> te
96
         | "false" -> Ast.neg_guard te
97
         | _ -> assert false (* TODO: don't deal with non boolean
98
                                guards. Could just treturn true and
99
                                over-approximate behavior *)
100
       in
101
       if (match !init_var, te.Ast.expr_desc with
102
           | Some v, Var v2 -> v = v2
103
           | _ -> false) then 
104
         instrl_to_stm (
105
             if init then
106
               (List.assoc "true" guarded_instrs)
107
             else
108
               (List.assoc "false" guarded_instrs)
109
           )
110
       else
111
         Ast.Ite (loc, guard, stmt, guarded_expr_to_stm loc te tl)
112
  and instr_to_stm i =
113
    let loc = instr_loc i in
114
    match i.instr_desc with
115
    | MLocalAssign (v, e) | MStateAssign (v, e) ->
116
       Ast.Asn (loc, v.var_id, (lval_to_texpr loc) e)
117
    | MBranch (e, guarded_instrs) -> (
118
      let te = lval_to_texpr loc e in
119
      guarded_expr_to_stm loc te guarded_instrs
120
    )
121
    | MStep (ol, id, args) ->
122
       if List.mem_assoc id m.Machine_code_types.minstances then
123
         let fun_name, _ = List.assoc id m.minstances in
124
         match Corelang.node_name fun_name, ol with
125
         | "_arrow", [o] -> (
126
           init_var := Some o.var_id;
127
           Ast.Nop (loc);
128
             (* Ast.Asn (loc, o.var_id, 
129
              *        { expr_desc =              if init then Ast.Cst(Q.of_int 1, "true") else Ast.Cst(Q.of_int 0, "false");
130
              *          expr_loc = loc;
131
              *          expr_type = Ast.BoolT }
132
              * ) *)
133
         )
134
         | name, _ -> 
135
            (
136
              Format.eprintf "No tiny translation for node call  %s@.@?" name;
137
              assert false
138
            )
139
       else (
140
         Format.eprintf "No tiny translation for node call  %s@.@?" id;
141
         assert false
142
       )
143
    | MReset id
144
      | MNoReset id -> assert false (* no more calls or functions, ie. no reset *)
145
    | MComment s 
146
      | MSpec s -> assert false
147
  and instrl_to_stm il =
148
    match il with
149
      [] -> assert false
150
    | [i] -> instr_to_stm i
151
    | i::il ->
152
       let i' = instr_to_stm i in
153
       Ast.Seq (instr_loc i, i', (instrl_to_stm il))
154
  in
155
  instrl_to_stm m.Machine_code_types.mstep.step_instrs 
156

  
157
let read_var loc bounds_opt v =
158
  let min, max =
159
    match bounds_opt with
160
      Some (min,max) -> min, max
161
    | None -> (Q.of_int (-1), "-1"), (Q.of_int 1, "1")
162
  in
163
  let range = {
164
      Ast.expr_desc = Ast.Rand (min,max);
165
      expr_loc = loc;
166
      expr_type = ltyp_to_ttyp (v.Lustre_types.var_type)
167
    }
168
  in
169
  Ast.Asn (loc, v.var_id, range)
170
  
171
let rec read_vars loc bounds_inputs vl =
172
  match vl with
173
    [] -> Ast.Nop loc
174
  | [v] -> read_var
175
             loc
176
             (if List.mem_assoc v.Lustre_types.var_id bounds_inputs then
177
                Some (List.assoc v.Lustre_types.var_id bounds_inputs)
178
              else
179
                None)
180
             v
181
  | v::tl ->
182
     Ast.Seq (loc,
183
              read_var
184
                loc
185
                (if List.mem_assoc v.Lustre_types.var_id bounds_inputs then
186
                   Some (List.assoc v.Lustre_types.var_id bounds_inputs)
187
                 else
188
                   None)
189
                v,
190
              read_vars loc bounds_inputs tl
191
       )
192
  
193
let machine_to_ast bounds_input m =
194
  let loc = Tiny.Location.dummy in
195
  let read_vars = read_vars loc bounds_input m.Machine_code_types.mstep.step_inputs in
196
  let ast_loop_first = machine_body_to_ast true m in
197
  let ast_loop_run = machine_body_to_ast false m in
198
  let ast_loop_body = Ast.Seq (loc, read_vars, ast_loop_run) in
199
  let loop = Ast.While(loc, cst_bool loc true, ast_loop_body) in
200
  Ast.Seq (loc, read_vars, (Ast.Seq (loc, ast_loop_first, loop)))
201
  
202
let machine_to_env m =
203
  
204
    List.fold_left (fun accu v ->
205
      let typ =
206
        ltyp_to_ttyp (v.Lustre_types.var_type)
207
      in
208
      Ast.VarSet.add (v.var_id, typ) accu)
209
    Ast.VarSet.empty
210
    (Machine_code_common.machine_vars m)
211

  
src/tools/tiny/tiny_verifier.ml
1

  
2
let active = ref false
3
let tiny_debug = ref false
4

  
5
    
6
let tiny_run ~basename prog machines =
7
  let node_name =
8
    match !Options.main_node with
9
    | "" -> (
10
      Format.eprintf "Tiny verifier requires a main node.@.";
11
      Format.eprintf "@[<v 2>Available ones are:@ %a@]@.@?"
12
        (Utils.fprintf_list ~sep:"@ "
13
           (fun fmt m ->
14
             Format.fprintf fmt "%s" m.Machine_code_types.mname.node_id
15
           )
16
        )
17
        machines; 
18
      exit 1
19
    )
20
    | s -> ( (* should have been addessed before *)
21
      match Machine_code_common.get_machine_opt machines s with
22
      | None -> begin
23
          Global.main_node := s;
24
          Format.eprintf "Code generation error: %a@." Error.pp_error_msg Error.Main_not_found;
25
          raise (Error.Error (Location.dummy_loc, Error.Main_not_found))
26
        end
27
      | Some _ -> s
28
    )
29
  in
30
  let m = Machine_code_common.get_machine machines node_name in
31
  let env = (* We add each variables of the node the Tiny env *)
32
    Tiny_utils.machine_to_env m in
33
  let nd = m.mname in
34
  (* Building preamble with some bounds on inputs *)
35
  (* TODO: deal woth contracts, asserts, ... *)
36
  let bounds_inputs = [] in
37
  let ast = Tiny_utils.machine_to_ast bounds_inputs m in
38
  let mems = m.mmemory in
39
  
40
   Format.printf "%a@." Tiny.Ast.fprint_stm ast; 
41

  
42
  ()
43
  
44
  
45
module Verifier =
46
  (struct
47
    include VerifierType.Default
48
    let name = "tiny"
49
    let options =
50
      [
51
        "-debug", Arg.Set tiny_debug, "tiny debug"
52
      ]
53
      
54
    let activate () =
55
      active := true;
56
      (* Options.global_inline := true;
57
       * Options.optimization := 0;
58
       * Options.const_unfold := true; *)
59
      ()
60
      
61
    let is_active () = !active
62
    let run = tiny_run
63
            
64
            
65
  end: VerifierType.S)
66
    

Also available in: Unified diff