Project

General

Profile

Download (29.4 KB) Statistics
| Branch: | Tag: | Revision:
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.Format
13
open Lustre_types
14
open Corelang
15
open Machine_code_types
16
open Machine_code_common
17
module Mpfr = Lustrec_mpfr
18

    
19
let pp_print_version fmt () =
20
  fprintf fmt
21
    "/* @[<v>\
22
     C code generated by %s@,\
23
     Version number %s@,\
24
     Code is %s compliant@,\
25
     Using %s numbers */@,\
26
     @]"
27
    (Filename.basename Sys.executable_name) 
28
    Version.number 
29
    (if !Options.ansi then "ANSI C90" else "C99")
30
    (if !Options.mpfr then "MPFR multi-precision" else "(double) floating-point")
31

    
32
let protect_filename s =
33
  Str.global_replace (Str.regexp "\\.\\|\\ ") "_" s
34

    
35
let file_to_module_name basename =
36
  let baseNAME = Ocaml_utils.uppercase basename in
37
  let baseNAME = protect_filename baseNAME in
38
  baseNAME
39

    
40
let var_is name v =
41
  v.var_id = name
42

    
43
let mk_local n m =
44
  let used name =
45
    let open List in
46
    exists (var_is name) m.mstep.step_inputs
47
    || exists (var_is name) m.mstep.step_outputs
48
    || exists (var_is name) m.mstep.step_locals
49
    || exists (var_is name) m.mmemory in
50
  mk_new_name used n
51

    
52
(* Generation of a non-clashing name for the self memory variable (for step and reset functions) *)
53
let mk_self = mk_local "self"
54

    
55
let mk_mem = mk_local "mem"
56
let mk_mem_in = mk_local "mem_in"
57
let mk_mem_out = mk_local "mem_out"
58

    
59
(* Generation of a non-clashing name for the instance variable of static allocation macro *)
60
let mk_instance m =
61
  let used name =
62
    let open List in
63
    exists (var_is name) m.mstep.step_inputs
64
    || exists (var_is name) m.mmemory in
65
  mk_new_name used "inst"
66

    
67
(* Generation of a non-clashing name for the attribute variable of static allocation macro *)
68
let mk_attribute m =
69
  let used name =
70
    let open List in
71
    exists (var_is name) m.mstep.step_inputs
72
    || exists (var_is name) m.mmemory in
73
  mk_new_name used "attr"
74

    
75
let mk_call_var_decl loc id =
76
  { var_id = id;
77
    var_orig = false;
78
    var_dec_type = mktyp Location.dummy_loc Tydec_any;
79
    var_dec_clock = mkclock Location.dummy_loc Ckdec_any;
80
    var_dec_const = false;
81
    var_dec_value = None;
82
    var_parent_nodeid = None;
83
    var_type = Type_predef.type_arrow (Types.new_var ()) (Types.new_var ());
84
    var_clock = Clocks.new_var true;
85
    var_loc = loc }
86

    
87
(* counter for loop variable creation *)
88
let loop_cpt = ref (-1)
89

    
90
let reset_loop_counter () =
91
 loop_cpt := -1
92

    
93
let mk_loop_var m () =
94
  let vars = m.mstep.step_inputs
95
             @ m.mstep.step_outputs
96
             @ m.mstep.step_locals
97
             @ m.mmemory in
98
  let rec aux () =
99
    incr loop_cpt;
100
    let s = sprintf "__%s_%d" "i" !loop_cpt in
101
    if List.exists (var_is s) vars then aux () else s
102
  in aux ()
103
(*
104
let addr_cpt = ref (-1)
105

    
106
let reset_addr_counter () =
107
 addr_cpt := -1
108

    
109
let mk_addr_var m var =
110
  let vars = m.mmemory in
111
  let rec aux () =
112
    incr addr_cpt;
113
    let s = Printf.sprintf "%s_%s_%d" var "addr" !addr_cpt in
114
    if List.exists (fun v -> v.var_id = s) vars then aux () else s
115
  in aux ()
116
*)
117
let pp_global_init_name fmt id = fprintf fmt "%s_INIT" id
118
let pp_global_clear_name fmt id = fprintf fmt "%s_CLEAR" id
119
let pp_machine_memtype_name ?(ghost=false) fmt id =
120
  fprintf fmt "struct %s_mem%s" id (if ghost then "_ghost" else "")
121
let pp_machine_regtype_name fmt id = fprintf fmt "struct %s_reg" id
122
let pp_machine_alloc_name fmt id = fprintf fmt "%s_alloc" id
123
let pp_machine_dealloc_name fmt id = fprintf fmt "%s_dealloc" id
124
let pp_machine_static_declare_name fmt id = fprintf fmt "%s_DECLARE" id
125
let pp_machine_static_link_name fmt id = fprintf fmt "%s_LINK" id
126
let pp_machine_static_alloc_name fmt id = fprintf fmt "%s_ALLOC" id
127
let pp_machine_reset_name fmt id = fprintf fmt "%s_reset" id
128
let pp_machine_init_name fmt id = fprintf fmt "%s_init" id
129
let pp_machine_clear_name fmt id = fprintf fmt "%s_clear" id
130
let pp_machine_step_name fmt id = fprintf fmt "%s_step" id
131

    
132
let pp_mod pp_val v1 v2 fmt =
133
  if !Options.integer_div_euclidean then
134
    (* (a mod_C b) + (a mod_C b < 0 ? abs(b) : 0) *)
135
    fprintf fmt "((%a %% %a) + ((%a %% %a) < 0?(abs(%a)):0))"
136
      pp_val v1 pp_val v2
137
      pp_val v1 pp_val v2
138
      pp_val v2
139
  else (* Regular behavior: printing a % *)
140
    fprintf fmt "(%a %% %a)" pp_val v1 pp_val v2
141

    
142
let pp_div pp_val v1 v2 fmt =
143
  if !Options.integer_div_euclidean then
144
    (* (a - ((a mod_C b) + (a mod_C b < 0 ? abs(b) : 0))) div_C b *)
145
    fprintf fmt "(%a - %t) / %a"
146
      pp_val v1
147
      (pp_mod pp_val v1 v2)
148
      pp_val v2
149
  else (* Regular behavior: printing a / *)
150
    fprintf fmt "(%a / %a)" pp_val v1 pp_val v2
151
  
152
let pp_basic_lib_fun is_int i pp_val fmt vl =
153
  match i, vl with
154
  (*  | "ite", [v1; v2; v3] -> fprintf fmt "(%a?(%a):(%a))" pp_val v1 pp_val v2 pp_val v3 *)
155
  | "uminus", [v] ->
156
    fprintf fmt "(- %a)" pp_val v
157
  | "not", [v] ->
158
    fprintf fmt "(!%a)" pp_val v
159
  | "impl", [v1; v2] ->
160
    fprintf fmt "(!%a || %a)" pp_val v1 pp_val v2
161
  | "=", [v1; v2] ->
162
    fprintf fmt "(%a == %a)" pp_val v1 pp_val v2
163
  | "mod", [v1; v2] ->
164
     if is_int then
165
       pp_mod pp_val v1 v2 fmt 
166
     else
167
       fprintf fmt "(%a %% %a)" pp_val v1 pp_val v2
168
  | "equi", [v1; v2] ->
169
    fprintf fmt "(!%a == !%a)" pp_val v1 pp_val v2
170
  | "xor", [v1; v2] ->
171
    fprintf fmt "(!%a != !%a)" pp_val v1 pp_val v2
172
  | "/", [v1; v2] ->
173
     if is_int then
174
       pp_div pp_val v1 v2 fmt
175
     else
176
       fprintf fmt "(%a / %a)" pp_val v1 pp_val v2
177
  | _, [v1; v2] ->
178
    fprintf fmt "(%a %s %a)" pp_val v1 i pp_val v2
179
  | _ ->
180
    (* TODO: raise proper error *)
181
    eprintf "internal error: Basic_library.pp_c %s@." i;
182
    assert false
183

    
184
let rec pp_c_dimension fmt dim =
185
  let open Dimension in
186
  match dim.dim_desc with
187
  | Dident id ->
188
    fprintf fmt "%s" id
189
  | Dint i ->
190
    fprintf fmt "%d" i
191
  | Dbool b ->
192
    fprintf fmt "%B" b
193
  | Dite (i, t, e) ->
194
    fprintf fmt "((%a)?%a:%a)"
195
      pp_c_dimension i pp_c_dimension t pp_c_dimension e
196
  | Dappl (f, args) ->
197
    fprintf fmt "%a"
198
      (pp_basic_lib_fun (Basic_library.is_numeric_operator f) f pp_c_dimension)
199
      args
200
  | Dlink dim' ->
201
    fprintf fmt "%a" pp_c_dimension dim'
202
  | Dvar ->
203
    fprintf fmt "_%s" (Utils.name_of_dimension dim.dim_id)
204
  | Dunivar ->
205
    fprintf fmt "'%s" (Utils.name_of_dimension dim.dim_id)
206

    
207
let is_basic_c_type t =
208
  Types.(is_int_type t || is_real_type t || is_bool_type t)
209

    
210
let pp_c_basic_type_desc t_desc =
211
  if Types.is_bool_type t_desc then
212
    if !Options.cpp then "bool" else "_Bool"
213
  else if Types.is_int_type t_desc then !Options.int_type
214
  else if Types.is_real_type t_desc then
215
    if !Options.mpfr then Mpfr.mpfr_t else !Options.real_type
216
  else
217
    assert false (* Not a basic C type. Do not handle arrays or pointers *)
218

    
219
let pp_basic_c_type ?(var_opt=None) fmt t =
220
  match var_opt with
221
  | Some v when Machine_types.is_exportable v ->
222
     Machine_types.pp_c_var_type fmt v
223
  | _ ->
224
     fprintf fmt "%s" (pp_c_basic_type_desc t)
225

    
226
let pp_c_type ?var_opt var_id fmt t =
227
  let rec aux t pp_suffix =
228
    if is_basic_c_type  t then
229
       fprintf fmt "%a %s%a"
230
         (pp_basic_c_type ~var_opt) t
231
         var_id
232
         pp_suffix ()
233
    else
234
      let open Types in
235
      match (repr t).tdesc with
236
      | Tclock t' ->
237
        aux t' pp_suffix
238
      | Tarray (d, t')  ->
239
        let pp_suffix' fmt () =
240
          fprintf fmt "%a[%a]" pp_suffix () pp_c_dimension d in
241
        aux t' pp_suffix'
242
      | Tstatic (_, t') ->
243
        fprintf fmt "const "; aux t' pp_suffix
244
      | Tconst ty ->
245
        fprintf fmt "%s %s" ty var_id
246
      | Tarrow (_, _) ->
247
        fprintf fmt "void (*%s)()" var_id
248
      | _ ->
249
        (* TODO: raise proper error *)
250
        eprintf "internal error: C_backend_common.pp_c_type %a@." print_ty t;
251
        assert false
252
  in aux t (fun _ () -> ())
253
(*
254
let rec pp_c_initialize fmt t = 
255
  match (Types.repr t).Types.tdesc with
256
  | Types.Tint -> pp_print_string fmt "0"
257
  | Types.Tclock t' -> pp_c_initialize fmt t'
258
  | Types.Tbool -> pp_print_string fmt "0" 
259
  | Types.Treal when not !Options.mpfr -> pp_print_string fmt "0."
260
  | Types.Tarray (d, t') when Dimension.is_dimension_const d ->
261
    fprintf fmt "{%a}"
262
      (Utils.fprintf_list ~sep:"," (fun fmt _ -> pp_c_initialize fmt t'))
263
      (Utils.duplicate 0 (Dimension.size_const_dimension d))
264
  | _ -> assert false
265
 *)
266
let pp_c_tag fmt t =
267
  pp_print_string fmt
268
    (if t = tag_true then "1" else if t = tag_false then "0" else t)
269

    
270
(* Prints a constant value *)
271
let rec pp_c_const fmt c =
272
  match c with
273
  | Const_int i ->
274
    pp_print_int fmt i
275
  | Const_real r ->
276
    Real.pp fmt r
277
  (* | Const_float r   -> pp_print_float fmt r *)
278
  | Const_tag t ->
279
    pp_c_tag fmt t
280
  | Const_array ca ->
281
    pp_print_braced pp_c_const fmt ca
282
  | Const_struct fl ->
283
    pp_print_braced (fun fmt (_, c) -> pp_c_const fmt c) fmt fl
284
  | Const_string _
285
  | Const_modeid _ -> assert false (* string occurs in annotations not in C *)
286

    
287
                  
288
(* Prints a value expression [v], with internal function calls only.
289
   [pp_var] is a printer for variables (typically [pp_c_var_read]),
290
   but an offset suffix may be added for array variables
291
*)
292
let rec pp_c_val m self pp_var fmt v =
293
  let pp_c_val = pp_c_val m self pp_var in
294
  match v.value_desc with
295
  | Cst c ->
296
    pp_c_const fmt c
297
  | Array vl ->
298
    pp_print_braced pp_c_val fmt vl
299
  | Access (t, i) ->
300
    fprintf fmt "%a[%a]" pp_c_val t pp_c_val i
301
  | Power (v, _) ->
302
    (* TODO: raise proper error *)
303
    eprintf "internal error: C_backend_common.pp_c_val %a@."
304
      (Machine_code_common.pp_val m) v;
305
    assert false
306
  | Var v ->
307
     if Machine_code_common.is_memory m v then
308
       (* array memory vars are represented by an indirection to a local var
309
        *  with the right type, in order to avoid casting everywhere. *)
310
       if Types.is_array_type v.var_type
311
       && not (Types.is_real_type v.var_type && !Options.mpfr)
312
       then fprintf fmt "%a" pp_var v
313
       else fprintf fmt "%s->_reg.%a" self pp_var v
314
     else
315
       pp_var fmt v
316
  | Fun (n, vl) ->
317
    pp_basic_lib_fun (Types.is_int_type v.value_type) n pp_c_val fmt vl
318

    
319
(* Access to the value of a variable:
320
   - if it's not a scalar output, then its name is enough
321
   - otherwise, dereference it (it has been declared as a pointer,
322
     despite its scalar Lustre type)
323
   - moreover, dereference memory array variables.
324
*)
325
let pp_c_var_read m fmt id =
326
  (* mpfr_t is a static array, not treated as general arrays *)
327
  if Types.is_address_type id.var_type
328
  then
329
    if Machine_code_common.is_memory m id
330
    && not (Types.is_real_type id.var_type && !Options.mpfr)
331
    then fprintf fmt "(*%s)" id.var_id
332
    else fprintf fmt "%s" id.var_id
333
  else
334
    if Machine_code_common.is_output m id
335
    then fprintf fmt "*%s" id.var_id
336
    else fprintf fmt "%s" id.var_id
337

    
338
(* Addressable value of a variable, the one that is passed around in calls:
339
   - if it's not a scalar non-output, then its name is enough
340
   - otherwise, reference it (it must be passed as a pointer,
341
     despite its scalar Lustre type)
342
*)
343
let pp_c_var_write m fmt id =
344
  if Types.is_address_type id.var_type
345
  then
346
    fprintf fmt "%s" id.var_id
347
  else
348
    if Machine_code_common.is_output m id
349
    then
350
      fprintf fmt "%s" id.var_id
351
    else
352
      fprintf fmt "&%s" id.var_id
353

    
354
(* Declaration of an input variable:
355
   - if its type is array/matrix/etc, then declare it as a mere pointer,
356
     in order to cope with unknown/parametric array dimensions, 
357
     as it is the case for generics
358
*)
359
let pp_c_decl_input_var fmt id =
360
  if !Options.ansi && Types.is_address_type id.var_type
361
  then
362
    pp_c_type ~var_opt:id (sprintf "(*%s)" id.var_id) fmt
363
      (Types.array_base_type id.var_type)
364
  else
365
    pp_c_type ~var_opt:id id.var_id fmt id.var_type
366

    
367
(* Declaration of an output variable:
368
   - if its type is scalar, then pass its address
369
   - if its type is array/matrix/struct/etc, then declare it as a mere pointer,
370
     in order to cope with unknown/parametric array dimensions, 
371
     as it is the case for generics
372
*)
373
let pp_c_decl_output_var fmt id =
374
  if (not !Options.ansi) && Types.is_address_type id.var_type
375
  then
376
    pp_c_type ~var_opt:id id.var_id fmt id.var_type
377
  else
378
    pp_c_type ~var_opt:id (sprintf "(*%s)" id.var_id) fmt
379
      (Types.array_base_type id.var_type)
380

    
381
(* Declaration of a local/mem variable:
382
   - if it's an array/matrix/etc, its size(s) should be
383
     known in order to statically allocate memory, 
384
     so we print the full type
385
*)
386
let pp_c_decl_local_var m fmt id =
387
  if id.var_dec_const
388
  then
389
    fprintf fmt "%a = %a"
390
      (pp_c_type ~var_opt:id id.var_id)
391
      id.var_type
392
      (pp_c_val m "" (pp_c_var_read m))
393
      (Machine_code_common.get_const_assign m id)
394
  else
395
    fprintf fmt "%a"
396
      (pp_c_type ~var_opt:id id.var_id) id.var_type
397

    
398
(* Declaration of a struct variable:
399
   - if it's an array/matrix/etc, we declare it as a pointer
400
*)
401
let pp_c_decl_struct_var fmt id =
402
  if Types.is_array_type id.var_type
403
  then
404
    pp_c_type (sprintf "(*%s)" id.var_id) fmt
405
      (Types.array_base_type id.var_type)
406
  else
407
    pp_c_type id.var_id  fmt id.var_type
408

    
409
let pp_c_decl_instance_var ?(ghost=false) fmt (name, (node, _)) =
410
  fprintf fmt "%a %s%s"
411
    (pp_machine_memtype_name ~ghost) (node_name node)
412
    (if ghost then "" else "*")
413
    name
414

    
415
(* let pp_c_checks self fmt m =
416
 *   pp_print_list
417
 *     (fun fmt (loc, check) ->
418
 *        fprintf fmt
419
 *          "@[<v>%a@,assert (%a);@]"
420
 *          Location.pp_c_loc loc
421
 *          (pp_c_val m self (pp_c_var_read m)) check)
422
 *     fmt
423
 *     m.mstep.step_checks *)
424

    
425
let has_c_prototype funname dependencies =
426
  (* We select the last imported node with the name funname.
427
     The order of evaluation of dependencies should be
428
     compatible with overloading. (Not checked yet) *)
429
  let imported_node_opt =
430
    List.fold_left
431
      (fun res dep ->
432
         match res with
433
         | Some _ -> res
434
         | None ->
435
           let decls = dep.content in
436
           let matched = fun t -> match t.top_decl_desc with
437
             | ImportedNode nd -> nd.nodei_id = funname
438
             | _ -> false
439
           in
440
           if List.exists matched decls then
441
             match (List.find matched decls).top_decl_desc with
442
             | ImportedNode nd -> Some nd
443
             | _ -> assert false
444
           else
445
             None) None dependencies in
446
  match imported_node_opt with
447
  | None -> false
448
  | Some nd -> (match nd.nodei_prototype with Some "C" -> true | _ -> false)
449

    
450
(* Computes the depth to which multi-dimension array assignments should be expanded.
451
   It equals the maximum number of nested static array constructions accessible from root [v].
452
*)
453
let rec expansion_depth v =
454
  match v.value_desc with
455
  | Cst cst -> expansion_depth_cst cst
456
  | Var _ -> 0
457
  | Fun (_, vl) -> List.fold_right (fun v -> max (expansion_depth v)) vl 0
458
  | Array vl    -> 1 + List.fold_right (fun v -> max (expansion_depth v)) vl 0
459
  | Access (v, _) -> max 0 (expansion_depth v - 1)
460
  | Power _  -> 0 (*1 + expansion_depth v*)
461
and expansion_depth_cst c =
462
  match c with
463
  | Const_array cl ->
464
    1 + List.fold_right (fun c -> max (expansion_depth_cst c)) cl 0
465
  | _ -> 0
466

    
467
type loop_index = LVar of ident | LInt of int ref | LAcc of value_t
468
(*
469
let rec value_offsets v offsets =
470
 match v, offsets with
471
 | _                        , []          -> v
472
 | Power (v, n)             , _ :: q      -> value_offsets v q
473
 | Array vl                 , LInt r :: q -> value_offsets (List.nth vl !r) q
474
 | Cst (Const_array cl)     , LInt r :: q -> value_offsets (Cst (List.nth cl !r)) q
475
 | Fun (f, vl)              , _           -> Fun (f, List.map (fun v -> value_offsets v offsets) vl)
476
 | _                        , LInt r :: q -> value_offsets (Access (v, Cst (Const_int !r))) q
477
 | _                        , LVar i :: q -> value_offsets (Access (v, Var i)) q
478
*)
479
(* Computes the list of nested loop variables together with their dimension bounds.
480
   - LInt r stands for loop expansion (no loop variable, but int loop index)
481
   - LVar v stands for loop variable v
482
*)
483
let rec mk_loop_variables m ty depth =
484
  match (Types.repr ty).Types.tdesc, depth with
485
  | Types.Tarray (d, ty'), 0 ->
486
    let v = mk_loop_var m () in
487
    (d, LVar v) :: mk_loop_variables m ty' 0
488
  | Types.Tarray (d, ty'), _ ->
489
    let r = ref (-1) in
490
    (d, LInt r) :: mk_loop_variables m ty' (depth - 1)
491
  | _, 0 -> []
492
  | _ -> assert false
493

    
494
let reorder_loop_variables loop_vars =
495
  let (int_loops, var_loops) =
496
    List.partition (function (_, LInt _) -> true | _ -> false) loop_vars
497
  in
498
  var_loops @ int_loops
499

    
500
(* Prints a one loop variable suffix for arrays *)
501
let pp_loop_var pp_val fmt lv =
502
  match snd lv with
503
  | LVar v -> fprintf fmt "[%s]" v
504
  | LInt r -> fprintf fmt "[%d]" !r
505
  | LAcc i -> fprintf fmt "[%a]" pp_val i
506

    
507
(* Prints a suffix of loop variables for arrays *)
508
let pp_suffix pp_val =
509
  pp_print_list ~pp_sep:pp_print_nothing (pp_loop_var pp_val)
510

    
511
let rec is_const_index v =
512
  match v.value_desc with
513
  | Cst (Const_int _) -> true
514
  | Fun (_, vl)       -> List.for_all is_const_index vl
515
  | _                 -> false
516

    
517
(* Prints a value expression [v], with internal function calls only.
518
   [pp_var] is a printer for variables (typically [pp_c_var_read]),
519
   but an offset suffix may be added for array variables
520
*)
521
(* Prints a constant value before a suffix (needs casting) *)
522
let rec pp_c_const_suffix var_type fmt c =
523
  match c with
524
  | Const_int i ->
525
    pp_print_int fmt i
526
  | Const_real r ->
527
    Real.pp fmt r
528
  | Const_tag t ->
529
    pp_c_tag fmt t
530
  | Const_array ca ->
531
    let var_type = Types.array_element_type var_type in
532
    fprintf fmt "(%a[])%a"
533
      (pp_c_type "") var_type
534
      (pp_print_braced (pp_c_const_suffix var_type)) ca
535
  | Const_struct fl ->
536
    pp_print_braced
537
      (fun fmt (f, c) ->
538
         (pp_c_const_suffix (Types.struct_field_type var_type f)) fmt c)
539
      fmt fl
540
  | Const_string _
541
  | Const_modeid _ -> assert false (* string occurs in annotations not in C *)
542

    
543
(* Prints a [value] of type [var_type] indexed by the suffix list [loop_vars] *)
544
let rec pp_value_suffix ?(indirect=true) m self var_type loop_vars pp_var fmt value =
545
  (*eprintf "pp_value_suffix: %a %a %a@." Types.print_ty var_type Machine_code.pp_val value pp_suffix loop_vars;*)
546
  let pp_suffix = pp_suffix (pp_value_suffix ~indirect m self var_type [] pp_var) in
547
  match loop_vars, value.value_desc with
548
  | (x, LAcc i) :: q, _ when is_const_index i ->
549
    let r = ref (Dimension.size_const_dimension (dimension_of_value i)) in
550
    pp_value_suffix ~indirect m self var_type ((x, LInt r)::q) pp_var fmt value
551
  | (_, LInt r) :: q, Cst (Const_array cl) ->
552
    let var_type = Types.array_element_type var_type in
553
    pp_value_suffix ~indirect m self var_type q pp_var fmt
554
      (mk_val (Cst (List.nth cl !r)) Type_predef.type_int)
555
  | (_, LInt r) :: q, Array vl ->
556
    let var_type = Types.array_element_type var_type in
557
    pp_value_suffix ~indirect m self var_type q pp_var fmt (List.nth vl !r)
558
  | loop_var :: q, Array vl      ->
559
    let var_type = Types.array_element_type var_type in
560
    fprintf fmt "(%a[])%a%a"
561
      (pp_c_type "") var_type
562
      (pp_print_braced (pp_value_suffix ~indirect m self var_type q pp_var)) vl
563
      pp_suffix [loop_var]
564
  | [], Array vl      ->
565
    let var_type = Types.array_element_type var_type in
566
    fprintf fmt "(%a[])%a"
567
      (pp_c_type "") var_type
568
      (pp_print_braced (pp_value_suffix ~indirect m self var_type [] pp_var)) vl
569
  | _ :: q, Power (v, _)  ->
570
    pp_value_suffix ~indirect m self var_type q pp_var fmt v
571
  | _, Fun (n, vl)   ->
572
    pp_basic_lib_fun (Types.is_int_type value.value_type) n
573
      (pp_value_suffix ~indirect m self var_type loop_vars pp_var) fmt vl
574
  | _, Access (v, i) ->
575
    let var_type = Type_predef.type_array (Dimension.mkdim_var ()) var_type in
576
    pp_value_suffix m self var_type
577
      ((Dimension.mkdim_var (), LAcc i) :: loop_vars) pp_var fmt v
578
  | _, Var v ->
579
    if is_memory m v then
580
      (* array memory vars are represented by an indirection to a local var with the right type,
581
         in order to avoid casting everywhere. *)
582
      if Types.is_array_type v.var_type
583
      then fprintf fmt "%a%a" pp_var v pp_suffix loop_vars
584
      else fprintf fmt "%s%s_reg.%a%a"
585
          self (if indirect then "->" else ".") pp_var v pp_suffix loop_vars
586
    else
587
      fprintf fmt "%a%a" pp_var v pp_suffix loop_vars
588
  | _, Cst cst ->
589
    pp_c_const_suffix var_type fmt cst
590
  | _, _ ->
591
    eprintf "internal error: C_backend_src.pp_value_suffix %a %a %a@."
592
      Types.print_ty var_type (pp_val m) value pp_suffix loop_vars;
593
    assert false
594

    
595
(********************************************************************************************)
596
(*                       Struct Printing functions                                          *)
597
(********************************************************************************************)
598

    
599
(* let pp_registers_struct fmt m =
600
 *   pp_print_braced
601
 *     ~pp_prologue:(fun fmt () ->
602
 *         fprintf fmt "@[%a " pp_machine_regtype_name m.mname.node_id)
603
 *     ~pp_open_box:pp_open_vbox0
604
 *     ~pp_sep:pp_print_semicolon
605
 *     ~pp_eol:pp_print_semicolon
606
 *     ~pp_epilogue:(fun fmt () -> pp_print_string fmt "@] _reg;")
607
 *     pp_c_decl_struct_var
608
 *     fmt m.mmemory *)
609

    
610
let print_machine_struct ?(ghost=false) fmt m =
611
  if not (fst (Machine_code_common.get_stateless_status m)) then
612
    (* Define struct *)
613
    fprintf fmt "@[<v 2>%a {%a%a@]@,};"
614
      (pp_machine_memtype_name ~ghost) m.mname.node_id
615
      (if ghost then
616
         (fun fmt -> function
617
            | [] -> pp_print_nothing fmt ()
618
            | _ -> fprintf fmt "@,%a _reg;"
619
                     pp_machine_regtype_name m.mname.node_id)
620
       else
621
         pp_print_list
622
           ~pp_open_box:pp_open_vbox0
623
           ~pp_prologue:(fun fmt () ->
624
               fprintf fmt "@,@[%a {" pp_machine_regtype_name m.mname.node_id)
625
           ~pp_sep:pp_print_semicolon
626
           ~pp_eol:pp_print_semicolon'
627
           ~pp_epilogue:(fun fmt () -> fprintf fmt "}@] _reg;")
628
           pp_c_decl_struct_var)
629
      m.mmemory
630
      (pp_print_list
631
         ~pp_open_box:pp_open_vbox0
632
         ~pp_prologue:pp_print_cut
633
         ~pp_sep:pp_print_semicolon
634
         ~pp_eol:pp_print_semicolon'
635
         (pp_c_decl_instance_var ~ghost))
636
      m.minstances
637

    
638
(********************************************************************************************)
639
(*                      Prototype Printing functions                                        *)
640
(********************************************************************************************)
641

    
642
let print_global_init_prototype fmt baseNAME =
643
  fprintf fmt "void %a ()"
644
    pp_global_init_name baseNAME
645

    
646
let print_global_clear_prototype fmt baseNAME =
647
  fprintf fmt "void %a ()"
648
    pp_global_clear_name baseNAME
649

    
650
let print_alloc_prototype fmt (name, static) =
651
  fprintf fmt "%a * %a %a"
652
    (pp_machine_memtype_name ~ghost:false) name
653
    pp_machine_alloc_name name
654
    (pp_print_parenthesized pp_c_decl_input_var) static
655

    
656
let print_dealloc_prototype fmt name =
657
  fprintf fmt "void %a (%a * _alloc)"
658
    pp_machine_dealloc_name name
659
    (pp_machine_memtype_name ~ghost:false) name
660

    
661
let print_reset_prototype self fmt (name, static) =
662
  fprintf fmt "void %a (%a%a *%s)"
663
    pp_machine_reset_name name
664
    (pp_print_list ~pp_sep:pp_print_comma ~pp_eol:pp_print_comma
665
       pp_c_decl_input_var) static
666
    (pp_machine_memtype_name ~ghost:false) name
667
    self
668

    
669
let print_init_prototype self fmt (name, static) =
670
  fprintf fmt "void %a (%a%a *%s)"
671
    pp_machine_init_name name
672
    (pp_print_list ~pp_sep:pp_print_comma ~pp_eol:pp_print_comma
673
       pp_c_decl_input_var) static
674
    (pp_machine_memtype_name ~ghost:false) name
675
    self
676

    
677
let print_clear_prototype self fmt (name, static) =
678
  fprintf fmt "void %a (%a%a *%s)"
679
    pp_machine_clear_name name
680
    (pp_print_list ~pp_sep:pp_print_comma ~pp_eol:pp_print_comma
681
       pp_c_decl_input_var) static
682
    (pp_machine_memtype_name ~ghost:false) name
683
    self
684

    
685
let print_stateless_prototype fmt (name, inputs, outputs) =
686
  fprintf fmt "void %a (@[<v>%a%a@])"
687
    pp_machine_step_name name
688
    (pp_print_list ~pp_sep:pp_print_comma ~pp_eol:pp_print_comma
689
       ~pp_epilogue:pp_print_cut pp_c_decl_input_var) inputs
690
    (pp_print_list ~pp_sep:pp_print_comma pp_c_decl_output_var) outputs
691

    
692
let print_step_prototype self fmt (name, inputs, outputs) =
693
  fprintf fmt "void %a (@[<v>%a%a%a *%s@])"
694
    pp_machine_step_name name
695
    (pp_print_list ~pp_sep:pp_print_comma ~pp_eol:pp_print_comma
696
       ~pp_epilogue:pp_print_cut pp_c_decl_input_var) inputs
697
    (pp_print_list ~pp_sep:pp_print_comma ~pp_eol:pp_print_comma
698
       ~pp_epilogue:pp_print_cut pp_c_decl_output_var) outputs
699
    (pp_machine_memtype_name ~ghost:false) name
700
    self
701

    
702
let print_import_prototype fmt dep =
703
  fprintf fmt "#include \"%s.h\"" dep.name
704

    
705
let print_import_alloc_prototype fmt dep =
706
  if dep.is_stateful then
707
    fprintf fmt "#include \"%s_alloc.h\"" dep.name
708

    
709
let pp_c_var m self pp_var fmt var =
710
    pp_c_val m self pp_var fmt (Machine_code_common.mk_val (Var var) var.var_type)
711

    
712
let pp_array_suffix =
713
  pp_print_list ~pp_sep:pp_print_nothing (fun fmt v -> fprintf fmt "[%s]" v)
714

    
715
let mpfr_vars vars =
716
  if !Options.mpfr then
717
    List.filter (fun v -> Types.(is_real_type (array_base_type v.var_type))) vars
718
  else []
719

    
720
let mpfr_consts consts =
721
  if !Options.mpfr then
722
    List.filter (fun c -> Types.(is_real_type (array_base_type c.const_type))) consts
723
  else []
724

    
725
(* type directed initialization: useless wrt the lustre compilation model,
726
   except for MPFR injection, where values are dynamically allocated
727
*)
728
let pp_initialize m self pp_var fmt var =
729
  let rec aux indices fmt typ =
730
    if Types.is_array_type typ
731
    then
732
      let dim = Types.array_type_dimension typ in
733
      let idx = mk_loop_var m () in
734
      fprintf fmt "@[<v 2>{@,int %s;@,for(%s=0;%s<%a;%s++)@,%a @]@,}"
735
        idx idx idx pp_c_dimension dim idx
736
        (aux (idx::indices)) (Types.array_element_type typ)
737
    else
738
      let indices = List.rev indices in
739
      let pp_var_suffix fmt var =
740
        fprintf fmt "%a%a" (pp_c_var m self pp_var) var pp_array_suffix indices in
741
      Mpfr.pp_inject_init pp_var_suffix fmt var
742
  in
743
  reset_loop_counter ();
744
  aux [] fmt var.var_type
745

    
746
(* type directed clear: useless wrt the lustre compilation model,
747
   except for MPFR injection, where values are dynamically allocated
748
*)
749
let pp_clear m self pp_var fmt var =
750
  let rec aux indices fmt typ =
751
    if Types.is_array_type typ
752
    then
753
      let dim = Types.array_type_dimension typ in
754
      let idx = mk_loop_var m () in
755
      fprintf fmt "@[<v 2>{@,int %s;@,for(%s=0;%s<%a;%s++)@,%a @]@,}"
756
        idx idx idx pp_c_dimension dim idx
757
        (aux (idx::indices)) (Types.array_element_type typ)
758
    else
759
      let indices = List.rev indices in
760
      let pp_var_suffix fmt var =
761
        fprintf fmt "%a%a" (pp_c_var m self pp_var) var pp_array_suffix indices in
762
      Mpfr.pp_inject_clear pp_var_suffix fmt var
763
  in
764
  reset_loop_counter ();
765
  aux [] fmt var.var_type
766

    
767
  (*** Common functions for main ***)
768

    
769
let pp_print_file file_suffix fmt (typ, arg) =
770
  fprintf fmt
771
    "@[<v 2>if (traces) {@,\
772
     fprintf(f_%s, \"%%%s\\n\", %s);@,\
773
     fflush(f_%s);@]@,\
774
     }"
775
    file_suffix typ arg
776
    file_suffix
777
  
778
let print_put_var fmt file_suffix name var_type var_id =
779
  let pp_file = pp_print_file ("out" ^ file_suffix) in
780
  let unclocked_t = Types.unclock_type var_type in
781
  fprintf fmt "@[<v>%a@]"
782
    (fun fmt () ->
783
       if Types.is_int_type unclocked_t then
784
         fprintf fmt "_put_int(\"%s\", %s);@,%a"
785
           name var_id
786
           pp_file ("d", var_id)
787
       else if Types.is_bool_type unclocked_t then
788
         fprintf fmt "_put_bool(\"%s\", %s);@,%a"
789
           name var_id
790
           pp_file ("i", var_id)
791
       else if Types.is_real_type unclocked_t then
792
         if !Options.mpfr then
793
           fprintf fmt "_put_double(\"%s\", mpfr_get_d(%s, %s), %i);@,%a"
794
             name var_id (Mpfr.mpfr_rnd ()) !Options.print_prec_double
795
             pp_file (".*f",
796
                      string_of_int !Options.print_prec_double
797
                      ^ ", mpfr_get_d(" ^ var_id ^ ", MPFR_RNDN)")
798
         else
799
           fprintf fmt "_put_double(\"%s\", %s, %i);@,%a"
800
             name var_id !Options.print_prec_double
801
             pp_file (".*f",
802
                      string_of_int !Options.print_prec_double ^ ", " ^ var_id)
803
       else begin
804
         eprintf "Impossible to print the _put_xx for type %a@.@?"
805
           Types.print_ty var_type;
806
         assert false
807
       end) ()
808

    
809
let pp_file_decl fmt inout idx =
810
  let idx = idx + 1 in (* we start from 1: in1, in2, ... *)
811
  fprintf fmt "FILE *f_%s%i;" inout idx
812

    
813
let pp_file_open fmt inout idx =
814
  let idx = idx + 1 in (* we start from 1: in1, in2, ... *)
815
  fprintf fmt
816
    "@[<v>const char* cst_char_suffix_%s%i = \"_simu.%s%i\";@,\
817
     size_t l%s%i = strlen(dir) + strlen(prefix) + strlen(cst_char_suffix_%s%i);@,\
818
     char* f_%s%i_name = malloc((l%s%i+2) * sizeof(char));@,\
819
     strcpy (f_%s%i_name, dir);@,\
820
     strcat(f_%s%i_name, \"/\");@,\
821
     strcat(f_%s%i_name, prefix);@,\
822
     strcat(f_%s%i_name, cst_char_suffix_%s%i);@,\
823
     f_%s%i = fopen(f_%s%i_name, \"w\");@,\
824
     free(f_%s%i_name);\
825
     @]"
826
    inout idx inout idx
827
    inout idx inout idx
828
    inout idx inout idx
829
    inout idx
830
    inout idx
831
    inout idx
832
    inout idx inout idx
833
    inout idx inout idx
834
    inout idx;
835
  "f_" ^ inout ^ string_of_int idx
836

    
837

    
838
(* Local Variables: *)
839
(* compile-command:"make -C ../../.." *)
840
(* End: *)
(3-3/10)