Revision 94c457b7
Added by Pierre-Loïc Garoche over 6 years ago
src/plugins/salsa/machine_salsa_opt.ml | ||
---|---|---|
1 | 1 |
|
2 | 2 |
(* We try to avoid opening modules here *) |
3 |
module ST = Salsa.SalsaTypes
|
|
3 |
module ST = Salsa.Types |
|
4 | 4 |
module SDT = SalsaDatatypes |
5 | 5 |
module LT = LustreSpec |
6 | 6 |
module MC = Machine_code |
... | ... | |
118 | 118 |
| LT.Access _ |
119 | 119 |
| LT.Power _ -> assert false |
120 | 120 |
and opt_num_expr ranges formalEnv e = |
121 |
(* if debug then Format.eprintf "Optimizing expression %a with Salsa@ " MC.pp_val e; *)
|
|
121 |
(* if !debug then Format.eprintf "Optimizing expression %a with Salsa@ " MC.pp_val e; *)
|
|
122 | 122 |
let fresh_id = "toto" in (* TODO more meaningful name *) |
123 | 123 |
(* Convert expression *) |
124 | 124 |
(* List.iter (fun (l,c) -> Format.eprintf "%s -> %a@ " l Printers.pp_const c) constEnv; *) |
125 |
let e_salsa : Salsa.SalsaTypes.expression = value_t2salsa_expr constEnv e in
|
|
125 |
let e_salsa : Salsa.Types.expression = value_t2salsa_expr constEnv e in |
|
126 | 126 |
(* Format.eprintf "apres deplaige constantes ok%a @." MC.pp_val (salsa_expr2value_t vars_env [](\* constEnv *\) e_salsa) ; *) |
127 | 127 |
|
128 | 128 |
(* Convert formalEnv *) |
129 |
(* if debug then Format.eprintf "Formal env is [%a]@ " FormalEnv.pp formalEnv; *) |
|
129 |
(* if !debug then Format.eprintf "Formal env is [%a]@ " FormalEnv.pp formalEnv; *)
|
|
130 | 130 |
let formalEnv_salsa = |
131 | 131 |
FormalEnv.fold (fun id expr accu -> |
132 | 132 |
(id, value_t2salsa_expr constEnv expr)::accu |
133 | 133 |
) formalEnv [] in |
134 |
(* if debug then Format.eprintf "Formal env converted to salsa@ "; *) |
|
134 |
(* if !debug then Format.eprintf "Formal env converted to salsa@ "; *)
|
|
135 | 135 |
(* Substitute all occurences of variables by their definition in env *) |
136 |
let (e_salsa: Salsa.SalsaTypes.expression), _ =
|
|
136 |
let (e_salsa: Salsa.Types.expression), _ = |
|
137 | 137 |
Salsa.Rewrite.substVars |
138 | 138 |
e_salsa |
139 | 139 |
formalEnv_salsa |
140 | 140 |
0 (* TODO: Nasrine, what is this integer value for ? *) |
141 | 141 |
in |
142 |
(* if debug then Format.eprintf "Substituted def in expr@ "; *) |
|
142 |
(* if !debug then Format.eprintf "Substituted def in expr@ "; *)
|
|
143 | 143 |
let abstractEnv = Hashtbl.fold |
144 | 144 |
(fun id value accu -> (id,value)::accu) |
145 | 145 |
ranges |
... | ... | |
150 | 150 |
valEnv2ExprEnv remplce les paires id, abstractVal par id, Cst itv - on |
151 | 151 |
garde evalPartExpr remplace les variables e qui sont dans env par la cst |
152 | 152 |
- on garde *) |
153 |
(* if debug then Format.eprintf "avant avant eval part@ "; *) |
|
153 |
(* if !debug then Format.eprintf "avant avant eval part@ "; *)
|
|
154 | 154 |
(* Format.eprintf "avant evalpart: %a@." MC.pp_val (salsa_expr2value_t vars_env constEnv e_salsa); *) |
155 | 155 |
let e_salsa = |
156 |
Salsa.Float.evalPartExpr
|
|
156 |
Salsa.Analyzer.evalPartExpr
|
|
157 | 157 |
e_salsa |
158 |
(Salsa.Float.valEnv2ExprEnv abstractEnv) |
|
159 |
([] (* no blacklisted variables *)) |
|
158 |
(Salsa.Analyzer.valEnv2ExprEnv abstractEnv) |
|
159 |
([] (* no blacklisted variables *)) |
|
160 |
([] (* no arrays *)) |
|
160 | 161 |
in |
161 | 162 |
(* Format.eprintf "apres evalpart: %a@." MC.pp_val (salsa_expr2value_t vars_env constEnv e_salsa); *) |
162 | 163 |
(* Checking if we have all necessary information *) |
163 | 164 |
|
164 |
let free_vars = get_salsa_free_vars vars_env constEnv abstractEnv e_salsa in |
|
165 |
|
|
165 |
let free_vars = get_salsa_free_vars vars_env constEnv abstractEnv e_salsa in |
|
166 | 166 |
if Vars.cardinal free_vars > 0 then ( |
167 |
Format.eprintf "Warning: unbounded free vars (%a) in expression %a. We do not optimize it.@ "
|
|
167 |
Log.report ~level:2 (fun fmt -> Format.fprintf fmt "Warning: unbounded free vars (%a) in expression %a. We do not optimize it.@ "
|
|
168 | 168 |
Vars.pp (Vars.fold (fun v accu -> let v' = {v with LT.var_id = nodename ^ "." ^ v.LT.var_id } in Vars.add v' accu) free_vars Vars.empty) |
169 |
MC.pp_val (salsa_expr2value_t vars_env constEnv e_salsa); |
|
170 |
if debug then Format.eprintf "Some free vars, not optimizing@."; |
|
169 |
MC.pp_val (salsa_expr2value_t vars_env constEnv e_salsa));
|
|
170 |
if !debug then Format.eprintf "Some free vars, not optimizing@.";
|
|
171 | 171 |
let new_e = try salsa_expr2value_t vars_env constEnv e_salsa with Not_found -> assert false in |
172 | 172 |
new_e, None |
173 | 173 |
) |
174 | 174 |
else ( |
175 |
|
|
175 | 176 |
try |
176 |
if debug then |
|
177 |
if !debug then
|
|
177 | 178 |
Format.eprintf "Analyzing expression %a with env: @[<v>%a@ @]@ " |
178 | 179 |
MC.pp_val (salsa_expr2value_t vars_env constEnv e_salsa) |
179 | 180 |
(Utils.fprintf_list ~sep:",@ "(fun fmt (l,r) -> Format.fprintf fmt "%s -> %a" l FloatIntSalsa.pp r)) abstractEnv |
180 | 181 |
; |
181 |
|
|
182 |
|
|
182 | 183 |
let new_e_salsa, e_val = |
183 | 184 |
Salsa.MainEPEG.transformExpression fresh_id e_salsa abstractEnv |
184 | 185 |
in |
185 | 186 |
let new_e = try salsa_expr2value_t vars_env constEnv new_e_salsa with Not_found -> assert false in |
186 |
if debug then Format.eprintf "@ @[<v>old: %a@ new: %a@ range: %a@]" MC.pp_val e MC.pp_val new_e RangesInt.pp_val e_val; |
|
187 |
if !debug then Format.eprintf "@ @[<v>old: %a@ new: %a@ range: %a@]" MC.pp_val e MC.pp_val new_e RangesInt.pp_val e_val;
|
|
187 | 188 |
new_e, Some e_val |
188 | 189 |
with Not_found -> assert false |
189 | 190 |
| Salsa.Epeg_types.EPEGError _ -> ( |
... | ... | |
195 | 196 |
|
196 | 197 |
|
197 | 198 |
in |
198 |
if debug then |
|
199 |
if !debug then
|
|
199 | 200 |
Format.eprintf "@[<v 2>Optimizing expression %a in environment %a and ranges %a@ " |
200 | 201 |
MC.pp_val e |
201 | 202 |
FormalEnv.pp formalEnv |
... | ... | |
216 | 217 |
(FormalEnv.get_sort_fun formalEnv) |
217 | 218 |
(Vars.elements vars_to_print) |
218 | 219 |
in |
219 |
Format.eprintf "Printing vars in the following order: [%a]@ " (Utils.fprintf_list ~sep:", " Printers.pp_var) ordered_vars ; |
|
220 |
if !debug then Format.eprintf "Printing vars in the following order: [%a]@ " (Utils.fprintf_list ~sep:", " Printers.pp_var) ordered_vars ;
|
|
220 | 221 |
List.fold_right ( |
221 | 222 |
fun v (accu_instr, accu_ranges) -> |
222 |
if debug then Format.eprintf "Printing assign for variable %s@ " v.LT.var_id; |
|
223 |
if !debug then Format.eprintf "Printing assign for variable %s@ " v.LT.var_id;
|
|
223 | 224 |
try |
224 | 225 |
(* Obtaining unfold expression of v in formalEnv *) |
225 | 226 |
let v_def = FormalEnv.get_def formalEnv v in |
... | ... | |
243 | 244 |
(* Main recursive function: modify the instructions list while preserving the |
244 | 245 |
order of assigns for state variables. Returns a quintuple: (new_instrs, |
245 | 246 |
ranges, formalEnv, printed_vars, and remaining vars to be printed) *) |
246 |
let rec rewrite_instrs nodename constEnv vars_env m instrs ranges formalEnv printed_vars vars_to_print = |
|
247 |
let rec rewrite_instrs nodename constEnv vars_env m instrs ranges formalEnv printed_vars vars_to_print = |
|
248 |
Format.eprintf "Rewrite intrs :%a@." Machine_code.pp_instrs instrs; |
|
247 | 249 |
let assign_vars = assign_vars nodename constEnv vars_env in |
248 |
(* if debug then ( *) |
|
250 |
(* if !debug then ( *)
|
|
249 | 251 |
(* Format.eprintf "------------@ "; *) |
250 | 252 |
(* Format.eprintf "Current printed_vars: [%a]@ " Vars.pp printed_vars; *) |
251 | 253 |
(* Format.eprintf "Formal env is [%a]@ " FormalEnv.pp formalEnv; *) |
... | ... | |
254 | 256 |
| [] -> |
255 | 257 |
(* End of instruction list: we produce the definition of each variable that |
256 | 258 |
appears in vars_to_print. Each of them should be defined in formalEnv *) |
257 |
if debug then Format.eprintf "Producing definitions %a@ " Vars.pp vars_to_print; |
|
259 |
if !debug then Format.eprintf "Producing definitions %a@ " Vars.pp vars_to_print;
|
|
258 | 260 |
let instrs, ranges' = assign_vars printed_vars ranges formalEnv vars_to_print in |
259 | 261 |
instrs, |
260 | 262 |
ranges', |
... | ... | |
266 | 268 |
(* We reformulate hd_instr, producing or not a fresh instruction, updating |
267 | 269 |
formalEnv, possibly ranges and vars_to_print *) |
268 | 270 |
begin |
271 |
Format.eprintf "Hdlist@."; |
|
269 | 272 |
let hd_instrs, ranges, formalEnv, printed_vars, vars_to_print = |
270 | 273 |
match Corelang.get_instr_desc hd_instr with |
271 | 274 |
| LT.MLocalAssign(vd,vt) when Types.is_real_type vd.LT.var_type && not (Vars.mem vd vars_to_print) -> |
275 |
Format.eprintf "local assign@."; |
|
272 | 276 |
(* LocalAssign are injected into formalEnv *) |
273 |
(* if debug then Format.eprintf "Registering local assign %a@ " MC.pp_instr hd_instr; *) |
|
274 |
if debug then Format.eprintf "%a@ " MC.pp_instr hd_instr; |
|
277 |
(* if !debug then Format.eprintf "Registering local assign %a@ " MC.pp_instr hd_instr; *)
|
|
278 |
if !debug then Format.eprintf "%a@ " MC.pp_instr hd_instr;
|
|
275 | 279 |
let formalEnv' = FormalEnv.def formalEnv vd vt in (* formelEnv updated with vd = vt *) |
276 | 280 |
[], (* no instr generated *) |
277 | 281 |
ranges, (* no new range computed *) |
... | ... | |
280 | 284 |
vars_to_print (* no more or less variables to print *) |
281 | 285 |
|
282 | 286 |
| LT.MLocalAssign(vd,vt) when Types.is_real_type vd.LT.var_type && Vars.mem vd vars_to_print -> |
287 |
Format.eprintf "local assign 2@."; |
|
283 | 288 |
|
284 |
(* if debug then Format.eprintf "Registering and producing state assign %a@ " MC.pp_instr hd_instr; *) |
|
285 |
(* if debug then Format.eprintf "Registering and producing state assign %a@ " MC.pp_instr hd_instr; *) |
|
286 |
if debug then ( |
|
289 |
(* if !debug then Format.eprintf "Registering and producing state assign %a@ " MC.pp_instr hd_instr; *)
|
|
290 |
(* if !debug then Format.eprintf "Registering and producing state assign %a@ " MC.pp_instr hd_instr; *)
|
|
291 |
if !debug then (
|
|
287 | 292 |
Format.eprintf "%a@]@ " MC.pp_instr hd_instr; |
288 | 293 |
Format.eprintf "Selected var %a: producing expression@ " Printers.pp_var vd; |
289 | 294 |
); |
290 |
let formalEnv' = FormalEnv.def formalEnv vd vt in (* formelEnv updated with vd = vt *)
|
|
295 |
let formalEnv' = FormalEnv.def formalEnv vd vt in (* formelEnv updated with vd = vt *)
|
|
291 | 296 |
let instrs', ranges' = (* printing vd = optimized vt *) |
292 | 297 |
assign_vars printed_vars ranges formalEnv' (Vars.singleton vd) |
293 | 298 |
in |
... | ... | |
298 | 303 |
Vars.remove vd vars_to_print (* removed vd from variables to print *) |
299 | 304 |
|
300 | 305 |
| LT.MStateAssign(vd,vt) when Types.is_real_type vd.LT.var_type && Vars.mem vd vars_to_print -> |
306 |
Format.eprintf "state assign@."; |
|
301 | 307 |
|
302 | 308 |
(* StateAssign are produced since they are required by the function. We still |
303 | 309 |
keep their definition in the formalEnv in case it can optimize later |
304 | 310 |
outputs. vd is removed from remaining vars_to_print *) |
305 |
(* if debug then Format.eprintf "Registering and producing state assign %a@ " MC.pp_instr hd_instr; *) |
|
306 |
if debug then ( |
|
311 |
(* if !debug then Format.eprintf "Registering and producing state assign %a@ " MC.pp_instr hd_instr; *)
|
|
312 |
if !debug then (
|
|
307 | 313 |
Format.eprintf "%a@]@ " MC.pp_instr hd_instr; |
308 | 314 |
Format.eprintf "State assign %a: producing expression@ " Printers.pp_var vd; |
309 | 315 |
); |
... | ... | |
317 | 323 |
Vars.add vd printed_vars, (* adding vd to new printed vars *) |
318 | 324 |
Vars.remove vd vars_to_print (* removed vd from variables to print *) |
319 | 325 |
|
320 |
| (LT.MLocalAssign(vd,vt) | LT.MStateAssign(vd,vt)) -> |
|
326 |
| (LT.MLocalAssign(vd,vt) | LT.MStateAssign(vd,vt)) -> |
|
327 |
Format.eprintf "other assign@."; |
|
328 |
|
|
321 | 329 |
(* We have to produce the instruction. But we may have to produce as |
322 | 330 |
well its dependencies *) |
323 | 331 |
let required_vars = get_expr_real_vars vt in |
... | ... | |
327 | 335 |
variables *) |
328 | 336 |
let prefix_instr, ranges = |
329 | 337 |
assign_vars printed_vars ranges formalEnv required_vars in |
338 |
|
|
330 | 339 |
let vt', _ = optimize_expr nodename constEnv (Vars.union required_vars printed_vars) vars_env ranges formalEnv vt in |
331 | 340 |
let new_instr = |
332 | 341 |
match Corelang.get_instr_desc hd_instr with |
... | ... | |
342 | 351 |
Vars.diff vars_to_print written_vars (* removed vd + dependencies from |
343 | 352 |
variables to print *) |
344 | 353 |
|
345 |
| LT.MStep(vdl,id,vtl) -> |
|
346 |
if debug then Format.eprintf "Call to a node %a@ " MC.pp_instr hd_instr; |
|
354 |
| LT.MStep(vdl,id,vtl) -> |
|
355 |
Format.eprintf "step@."; |
|
356 |
|
|
357 |
if !debug then Format.eprintf "Call to a node %a@ " MC.pp_instr hd_instr; |
|
347 | 358 |
(* Call of an external function. Input expressions have to be |
348 | 359 |
optimized, their free variables produced. A fresh range has to be |
349 | 360 |
computed for each output variable in vdl. Output of the function |
... | ... | |
359 | 370 |
else |
360 | 371 |
fun_types node |
361 | 372 |
in |
362 |
if debug then Format.eprintf "@[<v 2>... optimizing arguments@ "; |
|
373 |
if !debug then Format.eprintf "@[<v 2>... optimizing arguments@ ";
|
|
363 | 374 |
let vtl', vtl_ranges = List.fold_right2 ( |
364 | 375 |
fun e typ_e (exprl, range_l)-> |
365 | 376 |
if Types.is_real_type typ_e then |
... | ... | |
369 | 380 |
e::exprl, None::range_l |
370 | 381 |
) vtl tin ([], []) |
371 | 382 |
in |
372 |
if debug then Format.eprintf "... done@ @]@ "; |
|
383 |
if !debug then Format.eprintf "... done@ @]@ ";
|
|
373 | 384 |
let required_vars = |
374 | 385 |
List.fold_left2 |
375 | 386 |
(fun accu e typ_e -> |
... | ... | |
381 | 392 |
Vars.empty |
382 | 393 |
vtl' tin |
383 | 394 |
in |
384 |
if debug then Format.eprintf "Required vars: [%a]@ Printed vars: [%a]@ Remaining required vars: [%a]@ " |
|
395 |
if !debug then Format.eprintf "Required vars: [%a]@ Printed vars: [%a]@ Remaining required vars: [%a]@ "
|
|
385 | 396 |
Vars.pp required_vars |
386 | 397 |
Vars.pp printed_vars |
387 | 398 |
Vars.pp (Vars.diff required_vars printed_vars) |
... | ... | |
398 | 409 |
Vars.union written_vars printed_vars, (* adding vdl to new printed vars *) |
399 | 410 |
Vars.diff vars_to_print written_vars |
400 | 411 |
|
401 |
| LT.MBranch(vt, branches) -> |
|
412 |
| LT.MBranch(vt, branches) -> |
|
413 |
|
|
402 | 414 |
(* Required variables to compute vt are introduced. |
403 | 415 |
Then each branch is refactored specifically |
404 | 416 |
*) |
405 |
if debug then Format.eprintf "Branching %a@ " MC.pp_instr hd_instr; |
|
417 |
if !debug then Format.eprintf "Branching %a@ " MC.pp_instr hd_instr;
|
|
406 | 418 |
let required_vars = get_expr_real_vars vt in |
407 | 419 |
let required_vars = Vars.diff required_vars printed_vars in (* remove |
408 | 420 |
already |
... | ... | |
416 | 428 |
let vt', _ = optimize_expr nodename constEnv printed_vars vars_env ranges formalEnv vt in |
417 | 429 |
|
418 | 430 |
let read_vars_tl = get_read_vars tl_instrs in |
419 |
if debug then Format.eprintf "@[<v 2>Dealing with branches@ "; |
|
431 |
if !debug then Format.eprintf "@[<v 2>Dealing with branches@ ";
|
|
420 | 432 |
let branches', written_vars, merged_ranges = List.fold_right ( |
421 | 433 |
fun (b_l, b_instrs) (new_branches, written_vars, merged_ranges) -> |
422 | 434 |
let b_write_vars = get_written_vars b_instrs in |
... | ... | |
439 | 451 |
RangesInt.merge merged_ranges b_ranges |
440 | 452 |
|
441 | 453 |
) branches ([], required_vars, ranges) in |
442 |
if debug then Format.eprintf "dealing with branches done@ @]@ "; |
|
454 |
if !debug then Format.eprintf "dealing with branches done@ @]@ ";
|
|
443 | 455 |
prefix_instr@[Corelang.update_instr_desc hd_instr (LT.MBranch(vt', branches'))], |
444 | 456 |
merged_ranges, (* Only step functions call within branches |
445 | 457 |
may have produced new ranges. We merge this data by |
... | ... | |
453 | 465 |
|
454 | 466 |
|
455 | 467 |
| LT.MReset(_) | LT.MNoReset _ | LT.MComment _ -> |
456 |
if debug then Format.eprintf "Untouched %a (non real)@ " MC.pp_instr hd_instr; |
|
468 |
if !debug then Format.eprintf "Untouched %a (non real)@ " MC.pp_instr hd_instr;
|
|
457 | 469 |
|
458 | 470 |
(* Untouched instruction *) |
459 | 471 |
[ hd_instr ], (* unmodified instr *) |
... | ... | |
463 | 475 |
vars_to_print (* no more or less variables to print *) |
464 | 476 |
|
465 | 477 |
in |
478 |
Format.eprintf "cic@."; |
|
466 | 479 |
let tl_instrs, ranges, formalEnv, printed_vars, vars_to_print = |
467 | 480 |
rewrite_instrs |
468 | 481 |
nodename |
... | ... | |
475 | 488 |
printed_vars |
476 | 489 |
vars_to_print |
477 | 490 |
in |
491 |
Format.eprintf "la@."; |
|
478 | 492 |
hd_instrs @ tl_instrs, |
479 | 493 |
ranges, |
480 | 494 |
formalEnv, |
... | ... | |
508 | 522 |
let get_cst e = match e.LT.expr_desc with |
509 | 523 |
| LT.Expr_const (LT.Const_real (c,e,s)) -> |
510 | 524 |
(* calculer la valeur c * 10^e *) |
511 |
Num.float_of_num (Num.div_num c (Num.power_num (Num.num_of_int 10) (Num.num_of_int e)))
|
|
525 |
Num.div_num c (Num.power_num (Num.num_of_int 10) (Num.num_of_int e))
|
|
512 | 526 |
| _ -> |
513 | 527 |
Format.eprintf |
514 | 528 |
"Invalid scala range: %a. It should be a pair of constant floats.@." |
... | ... | |
516 | 530 |
assert false |
517 | 531 |
in |
518 | 532 |
let minv, maxv = get_cst minv, get_cst maxv in |
519 |
if debug then Format.eprintf "variable %s in [%f, %f]@ " v minv maxv;
|
|
520 |
RangesInt.enlarge ranges v (Salsa.SalsaTypes.I(minv, maxv),Salsa.SalsaTypes.J(0.,0.))
|
|
533 |
if !debug then Format.eprintf "variable %s in [%s, %s]@ " v (Num.string_of_num minv) (Num.string_of_num maxv);
|
|
534 |
RangesInt.enlarge ranges v (Salsa.Float.Domain.nnew minv maxv)
|
|
521 | 535 |
) |
522 | 536 |
| _ -> |
523 | 537 |
Format.eprintf |
... | ... | |
536 | 550 |
) |
537 | 551 |
in |
538 | 552 |
(* TODO: should be at least step output + may be memories *) |
539 |
let vars_env = compute_vars_env m in |
|
540 | 553 |
|
541 |
if debug then Format.eprintf "@[<v 2>Registering node equations@ "; |
|
554 |
let vars_env = compute_vars_env m in |
|
555 |
if !debug then Format.eprintf "@[<v 2>Registering node equations@ "; |
|
542 | 556 |
let new_instrs, _, _, printed_vars, _ = |
543 | 557 |
rewrite_instrs |
544 | 558 |
m.MC.mname.LT.node_id |
... | ... | |
567 | 581 |
{ s with MC.step_instrs = new_instrs; MC.step_locals = locals } (* we have also to modify local variables to declare new vars *) |
568 | 582 |
|
569 | 583 |
|
570 |
let machine_t2machine_t_optimized_by_salsa constEnv mt =
|
|
584 |
let machine_t2machine_t_optimized_by_salsa constEnv mt = |
|
571 | 585 |
try |
572 |
if debug then Format.eprintf "@[<v 8>[salsa] Optimizing machine %s@ " mt.MC.mname.LT.node_id; |
|
586 |
if !debug then Format.eprintf "@[<v 8>[salsa] Optimizing machine %s@ " mt.MC.mname.LT.node_id;
|
|
573 | 587 |
let new_step = salsaStep constEnv mt mt.MC.mstep in |
574 |
if debug then Format.eprintf "@]@ "; |
|
588 |
if !debug then Format.eprintf "@]@ ";
|
|
575 | 589 |
{ mt with MC.mstep = new_step } |
576 | 590 |
|
577 | 591 |
|
Also available in: Unified diff
Updated Salsa plugin to latest version of Salsa.
Some issues wrt machine type features.
Work in progress