Revision 4c945dde
Added by Pierre-Loïc Garoche over 1 year ago
src/tools/tiny/tiny_tube.ml | ||
---|---|---|
1 |
(* |
|
2 |
TODO: |
|
3 |
|
|
4 |
- export du tube sur la tete de boucle: |
|
5 |
- par exemple un tube par dimension en 2d: temps x valeur |
|
6 |
- en sage ? en gnuplot? en tikz? |
|
7 |
- deux facon de visualiser le partitionnement |
|
8 |
- si on choisi un tube 2d, par exemple la variable x, on doit pouvoir visualiser le split du tube en fonction d'une variable booleenne. Par exemple on choisi b1 et on voit deux couleurs sur le tube de x. Ou on se restreint a b1 true ou b1 false |
|
9 |
- on doit aussi pouvoir afficher globalement pour une variable booleen le split. On choisi par exemple b1 de facon gloable et tous les tubes sont raffines en b1 true / b1 false / b1 both / b1 split enfin pour avoir deux plots separes. |
|
10 |
|
|
11 |
- par exemple un csv |
|
12 |
nb_temps, x_min, x_max, y_min, y_max, b1_true_x_min, b1_true_x_max, b1_true_y_min, b1_true_y_max, .... |
|
13 |
|
|
14 |
|
|
15 |
- |
|
16 |
- export de l'ast en latex avec des instructions tikz puis ensuite l'affichage des elements abstraits a chaque point de programme pour les articles. On peut desactiver ou activer les domaines grace aux options |
|
17 |
|
|
18 |
*) |
|
19 |
|
|
20 |
|
|
21 |
let pp_var fmt ((n,t),ctx) = |
|
22 |
(* Tiny.Ast.Var.pp_ fmt v *) |
|
23 |
match ctx with |
|
24 |
| None -> |
|
25 |
Format.fprintf fmt "%s" n |
|
26 |
| Some ((bv, _),b) -> |
|
27 |
Format.fprintf fmt "%s __ %s = %b" n bv b |
|
28 |
|
|
29 |
|
|
30 |
let pp_bound fmt b = Tiny.Scalar.pp fmt b |
|
31 |
|
|
32 |
module type S = |
|
33 |
sig |
|
34 |
module Results: Tiny.Analyze.Results |
|
35 |
val list: (int * Results.Dom.t) list |
|
36 |
val bounds: ((Tiny.Ast.Var.t * (Tiny.Ast.Var.t * bool) option) * (Tiny.Scalar.t * Tiny.Scalar.t)) list |
|
37 |
end |
|
38 |
|
|
39 |
let process env ast results = |
|
40 |
let module Results = (val results: Tiny.Analyze.Results) in |
|
41 |
let module Dom = Results.Dom in |
|
42 |
let module PrintResults = Tiny.PrintResults.Make (Dom) in |
|
43 |
let m = Results.results in |
|
44 |
|
|
45 |
let while_loc = Tiny.Ast.get_main_while_loc ast in |
|
46 |
let list = PrintResults.get_unrolled_info m while_loc in |
|
47 |
let join = |
|
48 |
match list with |
|
49 |
| [] -> Dom.bottom env |
|
50 |
| (_,hd)::tl -> List.fold_left (fun accu (_,e) -> Dom.join accu e) hd tl |
|
51 |
in |
|
52 |
let bounds = Dom.to_bounds join in |
|
53 |
let module M = struct |
|
54 |
module Results = Results |
|
55 |
module PrintResults = PrintResults |
|
56 |
let list = list |
|
57 |
let bounds = bounds |
|
58 |
end |
|
59 |
in |
|
60 |
(module M: S) |
|
61 |
(* |
|
62 |
let build f_header f_content env ast results = |
|
63 |
let module Results = (val results: Tiny.Analyze.Results) in |
|
64 |
let module Dom = Results.Dom in |
|
65 |
let module PrintResults = Tiny.PrintResults.Make (Dom) in |
|
66 |
let m = Results.results in |
|
67 |
|
|
68 |
let while_loc = Tiny.Ast.get_main_while_loc ast in |
|
69 |
let list = PrintResults.get_unrolled_info m while_loc in |
|
70 |
let join = |
|
71 |
match list with |
|
72 |
| [] -> Dom.bottom env |
|
73 |
| (_,hd)::tl -> List.fold_left (fun accu (_,e) -> Dom.join accu e) hd tl |
|
74 |
in |
|
75 |
let bounds = Dom.to_bounds join in |
|
76 |
f_header bounds; |
|
77 |
f_content list |
|
78 |
*) |
|
79 |
|
|
80 |
let pp_bounds fmt bounds = |
|
81 |
List.iter (fun ((v,ctx) as x, (min, max)) -> |
|
82 |
|
|
83 |
Format.fprintf fmt |
|
84 |
"%a in %a,%a@." |
|
85 |
pp_var x |
|
86 |
pp_bound min |
|
87 |
pp_bound max) |
|
88 |
bounds |
|
89 |
|
|
90 |
let pp env ast results fmt = |
|
91 |
let m = process env ast results in |
|
92 |
let module M = (val m: S) in |
|
93 |
pp_bounds fmt M.bounds; |
|
94 |
Format.fprintf fmt "Tube: %i@." (List.length M.list); |
|
95 |
List.iter (fun (idx, elem) -> |
|
96 |
Format.fprintf fmt "%i -> %a@." idx M.Results.Dom.fprint elem) M.list |
|
97 |
|
|
98 |
let export env ast results fmt = |
|
99 |
let m = process env ast results in |
|
100 |
let module M = (val m: S) in |
|
101 |
List.iter (fun (x, (min, max)) -> |
|
102 |
Format.fprintf fmt |
|
103 |
"%a in %a,%a@." |
|
104 |
pp_var x |
|
105 |
pp_bound min |
|
106 |
pp_bound max) |
|
107 |
M.bounds; |
|
108 |
Format.fprintf fmt "Tube: %i@." (List.length M.list); |
|
109 |
List.iter (fun (idx, elem) -> |
|
110 |
Format.fprintf fmt |
|
111 |
"%i -> %a@." |
|
112 |
idx |
|
113 |
pp_bounds (M.Results.Dom.to_bounds elem) |
|
114 |
) M.list |
|
115 |
|
|
116 |
let export_to_wide_csv env ast results fmt = |
|
117 |
let m = process env ast results in |
|
118 |
let module M = (val m: S) in |
|
119 |
let bounds = List.map (fun (idx, elem) -> idx, M.Results.Dom.to_bounds elem) M.list in |
|
120 |
(* Gather all variable ids *) |
|
121 |
let module VarIdSet = Set.Make ( |
|
122 |
struct |
|
123 |
type t = Tiny.Ast.Var.t * (Tiny.Ast.Var.t * bool) option |
|
124 |
let compare = compare |
|
125 |
end) |
|
126 |
in |
|
127 |
let var_ids = List.fold_left ( |
|
128 |
fun accu (_, bounds) -> |
|
129 |
List.fold_left (fun accu (vctx, _) -> VarIdSet.add vctx accu) accu bounds |
|
130 |
) VarIdSet.empty bounds |
|
131 |
in |
|
132 |
let ordered_list = VarIdSet.elements var_ids in |
|
133 |
Format.fprintf fmt "timestep,%a@." |
|
134 |
(Utils.fprintf_list ~sep:"," |
|
135 |
(fun fmt ((n,_),ctx) -> |
|
136 |
let pp fmt = |
|
137 |
match ctx with |
|
138 |
None -> |
|
139 |
Format.fprintf fmt "%s" n |
|
140 |
| Some ((bn,_),b) -> |
|
141 |
Format.fprintf fmt "%s_//%s_eq_%b" n bn b |
|
142 |
in |
|
143 |
Format.fprintf fmt "%t_min,%t_max" pp pp |
|
144 |
)) |
|
145 |
ordered_list; |
|
146 |
Format.fprintf fmt "%a@." |
|
147 |
(Utils.fprintf_list ~sep:"@." |
|
148 |
(fun fmt (idx, bounds_idx) -> |
|
149 |
Format.fprintf fmt "@[<h 0>%i, %a@]" |
|
150 |
idx |
|
151 |
(Utils.fprintf_list ~sep:", " |
|
152 |
(fun fmt (min_, max_) -> |
|
153 |
let pp_bound fmt b = match b with |
|
154 |
| None -> Format.fprintf fmt "," |
|
155 |
| Some b -> Tiny.Scalar.pp fmt b |
|
156 |
in |
|
157 |
Format.fprintf fmt "%a, %a" pp_bound min_ pp_bound max_)) |
|
158 |
(List.map (fun v -> if List.mem_assoc v bounds_idx then |
|
159 |
let min_, max_ = List.assoc v bounds_idx in |
|
160 |
Some min_, Some max_ |
|
161 |
else |
|
162 |
None, None |
|
163 |
) ordered_list) |
|
164 |
)) |
|
165 |
bounds; |
|
166 |
() |
|
167 |
|
|
168 |
|
|
169 |
let export_to_csv env ast results fmt = |
|
170 |
let m = process env ast results in |
|
171 |
let module M = (val m: S) in |
|
172 |
let bounds = List.map (fun (idx, elem) -> |
|
173 |
idx, |
|
174 |
try M.Results.Dom.to_bounds elem with Tiny.Relational.BotEnv -> Format.eprintf "Issues exporting env %a to bounds: bottom!@." M.Results.Dom.fprint elem; assert false |
|
175 |
) M.list |
|
176 |
in |
|
177 |
(* Gather all variable ids *) |
|
178 |
let pp_vctx fmt ((n,t), ctx ) = |
|
179 |
match ctx with |
|
180 |
| None -> Format.fprintf fmt "%s,%a,," n (Tiny.Ast.pp_base_type) t |
|
181 |
| Some ((bname,_ (* type should be bool *) ), bval) -> |
|
182 |
Format.fprintf fmt "%s,%a,%s,%b" n (Tiny.Ast.pp_base_type) t bname bval |
|
183 |
in |
|
184 |
let pp_bound fmt (min_, max_) = |
|
185 |
Format.fprintf fmt "%a,%a" Tiny.Scalar.pp min_ Tiny.Scalar.pp max_ |
|
186 |
in |
|
187 |
Format.fprintf fmt "timestep,varid,type,boolpart,boolval,min,max@."; |
|
188 |
Utils.fprintf_list ~sep:"@." ( |
|
189 |
fun fmt (idx, idx_bounds) -> |
|
190 |
Utils.fprintf_list ~sep:"@." (fun fmt (vctx, vctx_bound) -> |
|
191 |
Format.fprintf fmt "%i,%a,%a" idx pp_vctx vctx pp_bound vctx_bound |
|
192 |
) fmt idx_bounds |
|
193 |
) fmt bounds |
|
194 |
|
|
195 |
|
src/tools/tiny/tiny_utils.ml | ||
---|---|---|
26 | 26 |
expr_type = Ast.BoolT } |
27 | 27 |
|
28 | 28 |
let cst_num loc t q = |
29 |
let s = Q.to_string q in |
|
30 |
let s = if t = Tiny.Ast.RealT && Z.equal (Q.den q) Z.one then s ^ "." |
|
31 |
else s in |
|
29 | 32 |
{ Ast.expr_desc = |
30 |
Ast.Cst(q, Q.to_string q);
|
|
33 |
Ast.Cst(q, s);
|
|
31 | 34 |
expr_loc = loc; |
32 | 35 |
expr_type = t } |
33 | 36 |
|
... | ... | |
91 | 94 |
| ">=", [v1;v2] -> |
92 | 95 |
Ast.Cond (build (Ast.Binop (Ast.Minus, v1, v2)) t_arg, Ast.Loose) |
93 | 96 |
| "uminus", [v1] -> Ast.Binop (Ast.Minus, cst_num loc t_arg Q.zero, v1) |
94 |
| "=", [v1;v2] -> Ast.Binop (Ast.Eq, v1, v2) |
|
97 |
(* | "=", [v1;v2] when v1.xxxtype != BoolT (\* if arguments are numerical then basic comparison *\) |
|
98 |
* Ast.Cond (build (Ast.Binop (Ast.Minus, v1, v2)) t_arg, Ast.Loose) |
|
99 |
* Ast.Binop (Ast.Eq, v1, v2) *) |
|
100 |
| "=", [v1;v2] |
|
95 | 101 |
| "equi", [v1;v2] -> Ast.Binop (Ast.Eq, v1, v2) |
96 | 102 |
|
97 | 103 |
| "!=", [v1;v2] -> Ast.Unop (Ast.Not, build (Ast.Binop (Ast.Eq, v1, v2)) Ast.BoolT) |
98 | 104 |
| "not", [v1] -> Ast.Unop (Ast.Not, v1) |
99 | 105 |
| "&&", [v1;v2] -> Ast.Binop (Ast.And, v1, v2) |
100 | 106 |
| "||", [v1;v2] -> Ast.Binop (Ast.Or, v1, v2) |
107 |
| "impl", [v1;v2] -> |
|
108 |
let neg_v1 = Ast.neg_guard v1 in |
|
109 |
Ast.Binop (Ast.Or, neg_v1, v2) |
|
101 | 110 |
|
102 | 111 |
| _ -> Format.eprintf "No tiny translation for operator %s@.@?" op; assert false |
103 | 112 |
) |
... | ... | |
210 | 219 |
) |
211 | 220 |
| name, _ -> |
212 | 221 |
( |
213 |
Format.eprintf "No tiny translation for node call %s@.@?" name; |
|
222 |
Format.eprintf "No tiny translation for stateful node call %s@.@?" name;
|
|
214 | 223 |
assert false |
215 | 224 |
) |
216 | 225 |
else ( |
217 |
Format.eprintf "No tiny translation for node call %s@.@?" id;
|
|
226 |
Format.eprintf "No tiny translation for function call %s@.@?" id;
|
|
218 | 227 |
assert false |
219 | 228 |
) |
220 | 229 |
| MReset id |
... | ... | |
228 | 237 |
let min, max = |
229 | 238 |
match bounds_opt with |
230 | 239 |
Some (min,max) -> min, max |
231 |
| None -> (Q.of_int (-1), "-1"), (Q.of_int 1, "1") |
|
240 |
| None -> |
|
241 |
let one, minus_one = |
|
242 |
match Types.is_real_type v.Lustre_types.var_type with |
|
243 |
| true -> "1.", "-1." |
|
244 |
| false -> "1", "-1" |
|
245 |
|
|
246 |
in |
|
247 |
(Q.of_int (-1), minus_one), (Q.of_int 1, one) |
|
232 | 248 |
in |
233 | 249 |
let range = { |
234 | 250 |
Ast.expr_desc = Ast.Rand (min,max); |
src/tools/tiny/tiny_verifier.ml | ||
---|---|---|
5 | 5 |
let descending = ref 1 |
6 | 6 |
let unrolling = ref 0 |
7 | 7 |
let output = ref false |
8 |
|
|
8 |
let reachtube = ref false (* used to produce a list of set iterates *) |
|
9 | 9 |
|
10 | 10 |
let quiet () = Tiny.Report.verbosity := 0 |
11 | 11 |
let report = Tiny_utils.report |
... | ... | |
55 | 55 |
(* TODO: deal woth contracts, asserts, ... *) |
56 | 56 |
let bounds_inputs = [] in |
57 | 57 |
let ast = Tiny_utils.machine_to_ast bounds_inputs m in |
58 |
let mems = m.mmemory in
|
|
58 |
(* let mems = m.mmemory in *)
|
|
59 | 59 |
if !output then ( |
60 | 60 |
let destname = !Options.dest_dir ^ "/" ^ basename ^ "_" ^ node_name ^ ".tiny" in |
61 | 61 |
report ~level:2 (fun fmt -> Format.fprintf fmt "Exporting resulting tiny source as %s@ " destname); |
... | ... | |
64 | 64 |
Format.fprintf fmt "%a@." Tiny.Ast.Var.Set.pp env; |
65 | 65 |
Format.fprintf fmt "%a@." Tiny.Ast.fprint_stm ast; |
66 | 66 |
close_out out; |
67 |
|
|
68 |
|
|
67 |
|
|
68 |
|
|
69 | 69 |
); |
70 | 70 |
report ~level:1 (fun fmt -> Format.fprintf fmt "%a@." Tiny.Ast.fprint_stm ast); |
71 | 71 |
|
72 | 72 |
let dom = |
73 |
let open Tiny.Load_domains in |
|
74 |
prepare_domains (List.map get_domain !domains) |
|
75 |
in |
|
76 |
let results = Tiny.Analyze.analyze dom !descending !unrolling env ast in |
|
77 |
let module Results = (val results: Tiny.Analyze.Results) in |
|
78 |
let module Dom = Results.Dom in |
|
79 |
let module PrintResults = Tiny.PrintResults.Make (Dom) in |
|
80 |
let m = Results.results in |
|
81 |
(* if !Tiny.Report.verbosity > 1 then *) |
|
82 |
report ~level:1 (PrintResults.print m env ast) |
|
83 |
(* no !output_file *); |
|
84 |
(* else PrintResults.print_invariants m ast !output_file *) |
|
73 |
let open Tiny.Load_domains in |
|
74 |
prepare_domains (List.map get_domain !domains) |
|
75 |
in |
|
76 |
let results = Tiny.Analyze.analyze |
|
77 |
dom |
|
78 |
(not !reachtube) (* when this argument is false, a |
|
79 |
simulation is performed*) |
|
80 |
!descending |
|
81 |
!unrolling |
|
82 |
env |
|
83 |
ast |
|
84 |
in |
|
85 |
(* if !Tiny.Report.verbosity > 1 then *) |
|
86 |
if !reachtube then ( |
|
87 |
(* Print preamble *) |
|
88 |
report ~level:1 (Tiny_tube.export_to_csv env ast results); |
|
89 |
(* We produce in a folder: the csv file, the tiny file *) |
|
90 |
let destname = !Options.dest_dir ^ "/" ^ basename ^ "_" ^ node_name ^ ".csv" in |
|
91 |
report ~level:1 (fun fmt -> Format.fprintf fmt "Exporting resulting tube as %s@ " destname); |
|
92 |
let out = open_out destname in |
|
93 |
let fmt = Format.formatter_of_out_channel out in |
|
94 |
Format.fprintf fmt "%t@." (Tiny_tube.export_to_csv env ast results); |
|
95 |
close_out out; |
|
96 |
|
|
97 |
) |
|
98 |
else |
|
99 |
let module Results = (val results: Tiny.Analyze.Results) in |
|
100 |
let module Dom = Results.Dom in |
|
101 |
let module PrintResults = Tiny.PrintResults.Make (Dom) in |
|
102 |
let m = Results.results in |
|
103 |
report ~level:1 (PrintResults.print m env ast) |
|
104 |
(* no !output_file *); |
|
105 |
(* else PrintResults.print_invariants m ast !output_file *) |
|
85 | 106 |
|
86 |
() |
|
107 |
()
|
|
87 | 108 |
|
88 | 109 |
|
89 | 110 |
module Verifier = |
90 | 111 |
(struct |
91 | 112 |
include VerifierType.Default |
113 |
|
|
114 |
(* Enforce global inline from top node *) |
|
115 |
let get_normalization_params () = |
|
116 |
Options.global_inline := true; |
|
117 |
get_normalization_params () |
|
118 |
|
|
92 | 119 |
let name = "tiny" |
93 | 120 |
let options = |
94 | 121 |
[ |
... | ... | |
128 | 155 |
* is reached (default is 1)"); *) |
129 | 156 |
("-unrolling", Arg.Set_int unrolling, |
130 | 157 |
"<n> Unroll loops <n> times before computing fixpoint (default is 0)"); |
158 |
("-reachtube", Arg.Int (fun n -> unrolling :=n; reachtube:=true), |
|
159 |
"<n> Unroll main loop <n> times to compute finite horizon analysis (default is invariant, with 0)"); |
|
131 | 160 |
("-output", Arg.Set output, |
132 | 161 |
"<n> Export resulting tiny file as <name>_<mainnode>.tiny"); |
133 | 162 |
(* (\* ("-u", Arg.Set_int unrolling, |
Also available in: Unified diff
Improved tiny backend