package lustre-v6

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

Source file soc2cStack.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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
(* Time-stamp: <modified the 06/03/2020 (at 13:36) by Erwan Jahier> *)

open Soc2cUtil
open Soc2cIdent
open Soc



let (mem_interface_out : Soc.t -> string -> bool) =
  fun soc id -> 
    let _,outs = soc.profile in
    List.mem_assoc id outs

let (not_an_array : Data.t -> bool) = function 
  | Data.Array(_,_) -> false | _ -> true


let (ve_not_an_array : Soc.var_expr -> bool) =
  fun v -> 
    match v with
      | Var(_,t) 
      | Const(_,t) 
      | Field(_,_,t) 
      | Index(_,_,t) -> not_an_array t 
      | Slice(_,_,_,_,_,_) -> false

let (ve_not_a_field : Soc.var_expr -> bool) =
  fun v -> 
    match v with
      | Var(_,_) 
      | Const(_,_) 
      | Index(_,_,_) 
      | Slice(_,_,_,_,_,_) -> true
      | Field(_,_,_t) -> false

(* exported : returns true if v is an output of soc *)
let rec (is_soc_output : Soc.var_expr -> Soc.t -> bool) =
  fun v soc -> 
    match v with
      | Var(n,t) -> List.mem (n,t) (snd soc.profile)
      | Const(_) -> false
      | Index(ve,_,_t) 
      | Field(ve,_,_t)
      | Slice(ve,_,_,_,_,_t) ->  is_soc_output ve soc
                                              
let (is_soc_output_and_not_a_struct : Soc.var_expr -> Soc.t -> bool) =
  fun v soc -> 
    match v with
      | Var(n,t) -> List.mem (n,t) (snd soc.profile)
      | Const(_) -> false
      | Index(_ve,_,_t) 
      | Field(_ve,_,_t)
      | Slice(_ve,_,_,_,_,_t) -> false (* is_soc_output_and_not_a_struct ve soc *)

let rec (string_of_var_expr: Soc.t -> Soc.var_expr -> string) = 
  fun soc var -> match var with
    | Const("true", _) -> "_true"
    | Const("false", _) -> "_false"
    | Const(id, _) -> id2s id
    | Var ("_memory",_)   -> (* Clutch! it's not an interface var... *) "ctx->_memory" 
    | Var (id,_t)   -> id2s id
    | Field(f, id,_) -> 
      if is_soc_output_and_not_a_struct f soc
      then Printf.sprintf "%s->%s" (string_of_var_expr soc f) (id2s id) 
      else Printf.sprintf "%s.%s"  (string_of_var_expr soc f) (id2s id) 
    | Index(f, index,_) -> Printf.sprintf "%s[%i]" (string_of_var_expr soc f) index
    | Slice(_f,_fi,_la,_st,_wi,_vt) -> assert false (* should not occur *)


(* exported *) 
let rec (gen_assign : Data.t  -> string -> string -> string) =
  fun t vi vo -> 
    let t_str = Soc2cUtil.data_type_to_c t "" in
    match t with
      | Data.Alias(_,t) -> gen_assign t vi vo
      | Data.Enum _  
      | Data.Struct(_) (* should I rather use memcpy for struct? *)
      | Data.Bool | Data.Int | Data.Real -> Printf.sprintf "  %s = %s;\n" vi vo
      | Data.Alpha(_) (* dead code ? *) 
      | Data.String 
      | Data.Array(_) -> 
        let t_str_short = Soc2cIdent.type_to_short_string t in
        Printf.sprintf "  _assign_%s(%s, %s, sizeof(%s));\n" t_str_short vi vo t_str

      | Data.Extern (id) -> 
        Printf.sprintf "  _assign_%s(%s, %s, sizeof(%s));\n" (id2s id) vi vo t_str
      

let (gen_assign_var_expr : Soc.t -> Soc.var_expr -> Soc.var_expr -> string) =
fun soc vo vi -> 
  match vo,vi  with
    | Slice _, _  | _, Slice _ ->  assert false
    | _,_ -> 
      let left = string_of_var_expr soc vo in
      let left = if is_soc_output_and_not_a_struct vo soc && ve_not_an_array vo && ve_not_a_field vo
        then "*"^left else left  
      in
      let vi_str = string_of_var_expr soc vi in
      let vi_str = 
        if is_soc_output_and_not_a_struct vi soc && ve_not_an_array vi then "*"^vi_str else vi_str
      in
      gen_assign (Soc.data_type_of_var_expr vo) left vi_str 


let (step_name : Soc.key -> string -> string) =
  fun sk sm -> 
    let str = Printf.sprintf "%s_%s" (Soc2cIdent.get_soc_name sk) sm in
    (* Printf.printf " XXX step_name(%s)=%s\n" (SocUtils.string_of_soc_key sk) str; *)
    (* flush stdout; *)
    (id2s str)

let (ctx_var : var_kind -> Soc.t -> Lv6Id.t -> string) =
  fun _opt soc id -> 
    if mem_interface_out soc id then 
      Printf.sprintf "*%s" (id2s id)
    else 
      Printf.sprintf "%s" (id2s id)

let (list_split : 'a list -> int -> 'a list * 'a list) =
  fun l s ->
    let rec aux s l acc =
      match s,l with
        | 0, _ -> List.rev acc,l
        | _, x::l -> aux (s-1) l (x::acc)
        | _, [] -> assert false
    in 
    aux s l []

let _ = assert (list_split [1;2;3;4;5;6] 3 = ([1;2;3],[4;5;6]))

let (inline_soc: Soc.t -> Soc.t -> Soc.var_expr list -> Soc.var_expr list ->
     string option) =
  fun soc called_soc vel_out vel_in -> 
    let called_soc_name,_,_ = called_soc.key in 
    match called_soc_name with
      (* those soc are inlined. Currently we only inline ite because
         of its polymorphism. Simple arith operators (+,-,*,/,etc.)
         should be inlined too. *)
      | "Lustre::if" ->
        let c,vel_in= match vel_in with [] -> assert false | c::l -> c,l in
        let s = (List.length vel_out) in
        let vel_in_t, vel_in_e = list_split vel_in s in
        let lt = List.map2 (gen_assign_var_expr soc) vel_out vel_in_t in
        let le = List.map2 (gen_assign_var_expr soc) vel_out vel_in_e in
        let ptr_indir = if is_soc_output_and_not_a_struct c soc then "*" else "" in
        let str = "   if ("^ ptr_indir^string_of_var_expr soc c ^" == _true) {\n   "^
          (String.concat "   " lt)^ "   } else {\n   "^
          (String.concat "   " le)^ "   }\n"
        in
        Some str

      | _  ->
        try
          if 
            Lv6MainArgs.global_opt.Lv6MainArgs.gen_c_inline_predef 
            && Soc2cPredef.is_call_supported called_soc.key 
          then
            let vel_in_str = List.map (string_of_var_expr soc) vel_in in
            let vel_in = List.map2
              (fun v s -> if is_soc_output_and_not_a_struct v soc  && ve_not_an_array v 
                then "*"^s else s) vel_in vel_in_str
            in

            let vel_out_str = List.map (string_of_var_expr soc) vel_out in
            let vel_out = List.map2
              (fun v s -> if is_soc_output_and_not_a_struct v soc && ve_not_an_array v 
                then "*"^s else s) vel_out vel_out_str
            in
            Some (Soc2cPredef.gen_call called_soc.key soc vel_out vel_in)
          else 
            None
        with Not_found -> 
(*           Printf.eprintf "won't inline %s\n" called_soc_name; *)
          None
(* exported *) 
let (inlined_soc : Soc.key -> bool) =
  fun key ->
    let soc_name,_,_ = key in
    soc_name = "Lustre::if" || Soc2cPredef.is_call_supported key 


(* exported *)
let (gen_step_call : Soc.t -> Soc.t -> Soc.var_expr list -> Soc.var_expr list ->
     string -> string -> string -> string) =
  fun soc called_soc vel_out vel_in _ctx sname step_arg ->
    match inline_soc soc called_soc vel_out vel_in with
    | Some str -> str
    | None ->
      let vel_in_str = List.map (string_of_var_expr soc) vel_in in
      let vel_in =
        List.map2 (fun v s -> if is_soc_output_and_not_a_struct v soc && ve_not_an_array v 
                    then "*"^s else s) vel_in vel_in_str
      in
      let vel_out_str = List.map (string_of_var_expr soc) vel_out in
      let vel_out =
        List.map2 
          (fun v s -> 
             if (not (is_soc_output_and_not_a_struct v soc) && ve_not_an_array v )
             then "&"^s 
             else s) 
          vel_out vel_out_str
      in
      let step_arg = if step_arg = "" then [] else [step_arg] in
      let step_arg = String.concat "," (vel_in@vel_out@step_arg) in
      let str = Printf.sprintf "  %s(%s); \n" (step_name called_soc.key sname) step_arg in
      str

(* exported *) 
let (typedef_of_soc : Soc.t -> string) =
  fun soc -> 
    if inlined_soc soc.key then ""  (* don't generate code if inlined *) else
      if SocUtils.is_memory_less soc then "" else
    let ctx_name = get_ctx_name soc.key in
    let ctx_name_type = ctx_name^"_type" in    
    let str = Printf.sprintf  "/* %s */\ntypedef struct {\n" ctx_name in
    let str = str ^
      (match soc.memory with
        | No_mem -> ""
        | Mem t ->  Printf.sprintf "   /*Memory cell*/\n   %s ;\n" 
          (id2s (Soc2cUtil.data_type_to_c t "_memory"))
        | Mem_hidden -> ""
      )
    in
    let str =  str ^ (if soc.instances <> [] then  "   /*INSTANCES*/\n" else "") in
    let il, _get_index = Soc2cInstances.to_array soc.instances in
    let string_of_instance (sk,i) = 
      let n = get_ctx_name sk in
      Printf.sprintf "   %s_type %s_tab[%d];\n" n n i
    in
    let str = List.fold_left (fun acc inst -> acc^(string_of_instance inst)) str il in
    let str = Printf.sprintf  "%s} %s;\n\n" str ctx_name_type in
    str

(* exported *)
(* for soc of type (int * int -> int), it generates something like 

"void step(int, int, int*, soc_ctx_type* );",
"void step(int x, int y, int* res, soc_ctx_type* ctx){"

*) 
let (get_step_prototype : Soc.step_method -> Soc.t -> string * string * string) =
  fun sm soc ->
    let sname = step_name soc.key sm.name in
    let inputs, outputs = soc.Soc.profile in
    let inputs  = SocUtils.filter_step_params sm.Soc.idx_ins  inputs in
    let outputs = SocUtils.filter_step_params sm.Soc.idx_outs outputs in
    let to_param_decl is_an_output (_id,dt) = 
      match is_an_output, dt with
        | true, Data.Array(_,_) -> Soc2cUtil.data_type_to_c dt "" ^"/*out*/" 
        (* arrays are already pointers... *)
        | false, _ -> Soc2cUtil.data_type_to_c dt ""
        | true,  _ -> Soc2cUtil.data_type_to_c dt "*"
    in
    let to_param out (id,dt) = 
      match out, dt with
        | true, Data.Array(_,_) -> Soc2cUtil.data_type_to_c dt id ^"/*out*/"
        | false, _ -> Soc2cUtil.data_type_to_c dt id
        | true,  _ -> Soc2cUtil.data_type_to_c dt ("*"^id)
    in
    let in_params = List.map (to_param false) inputs in
    let out_params = List.map (to_param true) outputs in
    let in_params_decl = List.map (to_param_decl false) inputs in
    let out_params_decl = List.map (to_param_decl true) outputs in
    let params = String.concat "," (in_params@out_params) in
    let params_decl = String.concat "," (in_params_decl@out_params_decl) in
    let ctype = match inputs with
      | (_,t)::_ -> 
         Printf.sprintf "sizeof(%s)" (Soc2cUtil.data_type_to_c t "")
      | [] ->  "" (* soc without intputs won't need this output *)
    in
    if SocUtils.is_memory_less soc then
      Printf.sprintf "void %s(%s);\n" sname params_decl,
      Printf.sprintf "void %s(%s){\n" sname params,
      ctype
    else 
      let ctx = Printf.sprintf "%s_type* ctx" (get_ctx_name soc.key)  in
      let ctx_decl = Printf.sprintf "%s_type*" (get_ctx_name soc.key) in
      Printf.sprintf "void %s(%s,%s);\n" sname params_decl ctx_decl,
      Printf.sprintf "void %s(%s,%s){" sname params ctx,
      ctype