package lustre-v6

  1. Overview
  2. Docs
Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source

Source file l2lOptimIte.ml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
(** Time-stamp: <modified the 29/08/2019 (at 15:44) by Erwan Jahier> *)

open Lxm
open Lic
 
let dbg =  (Lv6Verbose.get_flag "oite")


(********************************************************************************)
(** The functions below accumulate 
   (1) the assertions
   (2) the new equations 
   (3) the fresh variables

*)

type acc = 
      Lic.var_info list           (* new local vars *)
    * Lic.eq_info srcflagged list (* equations *)
    * Lic.val_exp srcflagged list (* assertions *)

let new_var = FreshName.var_info

(********************************************************************************)
let  (is_memory_less_and_safe_val_exp : LicPrg.t -> Lic.val_exp -> bool) =
  fun licprg ve ->
    L2lCheckMemSafe.is_safe_val_exp       licprg ve &&
    L2lCheckMemSafe.is_memoryless_val_exp licprg ve

let (clock_of_cond: val_exp -> bool -> acc -> clock * acc) =
  fun ve b acc ->
    let ve_clk = match ve.ve_clk with [clk] -> clk | _ -> assert false in
    let b = if b then "true" else "false" in
    let cc = "Lustre", b in
    let lxm = Lic.lxm_of_val_exp ve in
    let cv,acc = match ve with
      | { ve_core= CallByPosLic({it=VAR_REF id;_},[]) ;_} -> id,acc
      | _ -> 
        let nv = new_var "clk__of_ite" Bool_type_eff ("dummy",ve_clk) in
        let eq = {src=lxm;it=[LeftVarLic (nv, lxm)], ve} in
        let v,eqs,ass = acc in
        let acc = nv::v,eq::eqs,ass in
          nv.var_name_eff, acc
    in
    On((cc,cv,Bool_type_eff), List.hd ve.ve_clk), acc


let  (val_exp_when_clk : Lic.val_exp -> Lic.clock -> Lic.val_exp) =
  fun ve clk ->
(* return "ve when clk" *)
    let lxm = Lic.lxm_of_val_exp ve in
    { ve with 
      ve_clk = List.map (fun _ -> clk) ve.ve_clk; (* *)
      ve_core = CallByPosLic({ src=lxm; it=Lic.WHEN clk },[ve]);
    }
      
let (gen_merge : Lxm.t -> Lic.val_exp -> Lic.val_exp -> Lic.val_exp -> acc ->
     Lic.val_exp_core * acc ) =
  fun lxm cond ve1 ve2 acc ->
    (* this is the core of the module *)
    let true_cst  = { it=Bool_const_eff true ; src = lxm } in
    let false_cst = { it=Bool_const_eff false; src = lxm } in
    let clk_true,acc  = clock_of_cond cond true  acc in
    let clk_false,acc = clock_of_cond cond false acc in
    let ve1 = val_exp_when_clk ve1 clk_true in
    let ve2 = val_exp_when_clk ve2 clk_false in
    Merge(cond, [(true_cst,  ve1); (false_cst, ve2)]), acc


let is_var_ref ve = 
  match ve.ve_core with 
    | CallByPosLic({it=VAR_REF _;_},[]) -> true 
    | _ -> false
      

(* All the remaining are admnistrative functions *)
   
let rec (do_eq : LicPrg.t -> Lic.eq_info srcflagged -> acc -> acc) =
  fun licprg { src = lxm_eq ; it = (left_list, ve) } acc -> 
    let ve, (nv,neqs,nass) = do_val_exp licprg ve acc in
    nv, { src = lxm_eq ; it = (left_list, ve) }::neqs, nass
      
and (do_val_exp: LicPrg.t -> val_exp -> acc -> val_exp * acc) =
  fun licprg ve acc ->
    let ve_core, acc =
      match ve.ve_core with
        | Merge(ce,cl) -> (
          let cl,acc = 
            List.fold_left
              (fun (ncl,acc) (c, ve) -> 
                let ve, acc = do_val_exp licprg ve acc in
                ((c, ve)::ncl), acc
              ) 
              ([],acc) 
              cl 
          in
          Merge(ce,cl),acc
        )
        | CallByNameLic(op, fl) -> (
          let fl,acc = List.fold_left
            (fun (nfl,acc) (id,ve) -> 
              let nf, acc = do_val_exp licprg ve acc in
              ((id,nf)::nfl), acc
            ) 
            ([],acc) 
            fl 
          in
          CallByNameLic(op, fl), acc
        )
        | CallByPosLic (op, vel) -> (
          let vel, acc = List.fold_left
            (fun (vel,acc) ve -> 
              let ve, acc = do_val_exp licprg ve acc in
              (ve::vel), acc
            )
            ([],acc) 
            (List.rev vel)
          in          
	       match op.it with
            | CALL({src=_if_lxm; it=("Lustre","if"),[]}) 
            | PREDEF_CALL({src=_if_lxm; it=("Lustre","if"),[]}) -> (
              match vel with
                | [ cond ; ve1; ve2] -> 
                  if is_memory_less_and_safe_val_exp licprg ve1 &&  
                    is_memory_less_and_safe_val_exp licprg ve2 &&
                    is_var_ref cond (* exclude "if true then ..." from this optim *)
                  then 
                    gen_merge op.src cond ve1 ve2 acc
                  else
                    CallByPosLic(op, vel), acc
                | _ -> assert false (* SNO *)
            )
            | _ -> CallByPosLic(op, vel), acc
	     )
    in 
    { ve with ve_core = ve_core },acc

and (do_val_exp_flag:  LicPrg.t -> val_exp srcflagged -> acc -> val_exp srcflagged * acc) =
  fun licprg ve_f acc -> 
    let ve, acc = do_val_exp licprg ve_f.it acc in
    { ve_f with it = ve }, acc

and (do_node : LicPrg.t -> Lic.node_exp -> Lic.node_exp) =
  fun licprg n -> 
    match n.def_eff with
      | ExternLic | MetaOpLic | AbstractLic _ -> n
      | BodyLic b ->
        let acc = List.fold_left 
          (fun acc eq -> do_eq licprg eq acc) 
          ([],[],[]) 
          (List.rev b.eqs_eff)
        in
        let acc = List.fold_left 
          (fun acc ve -> 
            let ve,(nv,neq,nass) = do_val_exp_flag licprg ve acc in
            (nv,neq,ve::nass)
          )
          acc
          b.asserts_eff 
        in
        let (nv,neqs,nass) = acc in
        let nlocs = match n.loclist_eff with
          | None -> nv (* SNO, but eats no bread *)
          | Some v -> List.rev_append nv v
        in
        { n with 
          def_eff = BodyLic  { 
            eqs_eff = neqs; 
            asserts_eff = nass;
          };
          loclist_eff = Some nlocs;
        }

(* exported *)
let (doit : LicPrg.t -> LicPrg.t) =
  fun inprg -> 
    let outprg = LicPrg.empty in
  (* types and constants do not change *)
    let outprg = LicPrg.fold_types  LicPrg.add_type  inprg outprg in
    let outprg = LicPrg.fold_consts LicPrg.add_const inprg outprg in
  (* transform nodes *)
    let (doit_node : Lic.node_key -> Lic.node_exp -> LicPrg.t -> LicPrg.t) = 
      fun nk ne outprg -> 
        Lv6Verbose.exe ~flag:dbg (fun() -> Printf.printf "#DBG: L2lOptimIte '%s'\n"
            (Lic.string_of_node_key nk));
        let ne = do_node inprg ne in
        LicPrg.add_node nk ne outprg
    in
    let outprg = LicPrg.fold_nodes doit_node inprg outprg in
    outprg
OCaml

Innovation. Community. Security.