Project

General

Profile

Download (22 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
(* Generation of a non-clashing name for the self memory variable (for step and reset functions) *)
44
let mk_self m =
45
  let used name =
46
    let open List in
47
    exists (var_is name) m.mstep.step_inputs
48
    || exists (var_is name) m.mstep.step_outputs
49
    || exists (var_is name) m.mstep.step_locals
50
    || exists (var_is name) m.mmemory in
51
  mk_new_name used "self"
52

    
53
(* Generation of a non-clashing name for the instance variable of static allocation macro *)
54
let mk_instance m =
55
  let used name =
56
    let open List in
57
    exists (var_is name) m.mstep.step_inputs
58
    || exists (var_is name) m.mmemory in
59
  mk_new_name used "inst"
60

    
61
(* Generation of a non-clashing name for the attribute variable of static allocation macro *)
62
let mk_attribute m =
63
  let used name =
64
    let open List in
65
    exists (var_is name) m.mstep.step_inputs
66
    || exists (var_is name) m.mmemory in
67
  mk_new_name used "attr"
68

    
69
let mk_call_var_decl loc id =
70
  { var_id = id;
71
    var_orig = false;
72
    var_dec_type = mktyp Location.dummy_loc Tydec_any;
73
    var_dec_clock = mkclock Location.dummy_loc Ckdec_any;
74
    var_dec_const = false;
75
    var_dec_value = None;
76
    var_parent_nodeid = None;
77
    var_type = Type_predef.type_arrow (Types.new_var ()) (Types.new_var ());
78
    var_clock = Clocks.new_var true;
79
    var_loc = loc }
80

    
81
(* counter for loop variable creation *)
82
let loop_cpt = ref (-1)
83

    
84
let reset_loop_counter () =
85
 loop_cpt := -1
86

    
87
let mk_loop_var m () =
88
  let vars = m.mstep.step_inputs
89
             @ m.mstep.step_outputs
90
             @ m.mstep.step_locals
91
             @ m.mmemory in
92
  let rec aux () =
93
    incr loop_cpt;
94
    let s = sprintf "__%s_%d" "i" !loop_cpt in
95
    if List.exists (var_is s) vars then aux () else s
96
  in aux ()
97
(*
98
let addr_cpt = ref (-1)
99

    
100
let reset_addr_counter () =
101
 addr_cpt := -1
102

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

    
125
let pp_mod pp_val v1 v2 fmt =
126
  if !Options.integer_div_euclidean then
127
    (* (a mod_C b) + (a mod_C b < 0 ? abs(b) : 0) *)
128
    fprintf fmt "((%a %% %a) + ((%a %% %a) < 0?(abs(%a)):0))"
129
      pp_val v1 pp_val v2
130
      pp_val v1 pp_val v2
131
      pp_val v2
132
  else (* Regular behavior: printing a % *)
133
    fprintf fmt "(%a %% %a)" pp_val v1 pp_val v2
134

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

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

    
200
let is_basic_c_type t =
201
  Types.(is_int_type t || is_real_type t || is_bool_type t)
202

    
203
let pp_c_basic_type_desc t_desc =
204
  if Types.is_bool_type t_desc then
205
    if !Options.cpp then "bool" else "_Bool"
206
  else if Types.is_int_type t_desc then !Options.int_type
207
  else if Types.is_real_type t_desc then
208
    if !Options.mpfr then Mpfr.mpfr_t else !Options.real_type
209
  else
210
    assert false (* Not a basic C type. Do not handle arrays or pointers *)
211

    
212
let pp_basic_c_type ?(var_opt=None) fmt t =
213
  match var_opt with
214
  | Some v when Machine_types.is_exportable v ->
215
     Machine_types.pp_c_var_type fmt v
216
  | _ ->
217
     fprintf fmt "%s" (pp_c_basic_type_desc t)
218

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

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

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

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

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

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

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

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

    
391
(* Declaration of a struct variable:
392
   - if it's an array/matrix/etc, we declare it as a pointer
393
*)
394
let pp_c_decl_struct_var fmt id =
395
  if Types.is_array_type id.var_type
396
  then
397
    pp_c_type (sprintf "(*%s)" id.var_id) fmt
398
      (Types.array_base_type id.var_type)
399
  else
400
    pp_c_type id.var_id  fmt id.var_type
401

    
402
let pp_c_decl_instance_var fmt (name, (node, _)) =
403
  fprintf fmt "%a *%s" pp_machine_memtype_name (node_name node) name
404

    
405
(* let pp_c_checks self fmt m =
406
 *   pp_print_list
407
 *     (fun fmt (loc, check) ->
408
 *        fprintf fmt
409
 *          "@[<v>%a@,assert (%a);@]"
410
 *          Location.pp_c_loc loc
411
 *          (pp_c_val m self (pp_c_var_read m)) check)
412
 *     fmt
413
 *     m.mstep.step_checks *)
414

    
415
(********************************************************************************************)
416
(*                       Struct Printing functions                                          *)
417
(********************************************************************************************)
418

    
419
(* let pp_registers_struct fmt m =
420
 *   pp_print_braced
421
 *     ~pp_prologue:(fun fmt () ->
422
 *         fprintf fmt "@[%a " pp_machine_regtype_name m.mname.node_id)
423
 *     ~pp_open_box:pp_open_vbox0
424
 *     ~pp_sep:pp_print_semicolon
425
 *     ~pp_eol:pp_print_semicolon
426
 *     ~pp_epilogue:(fun fmt () -> pp_print_string fmt "@] _reg;")
427
 *     pp_c_decl_struct_var
428
 *     fmt m.mmemory *)
429

    
430
let print_machine_struct fmt m =
431
  if not (fst (Machine_code_common.get_stateless_status m)) then
432
    (* Define struct *)
433
    fprintf fmt "@[<v 2>%a {%a%a@]@,};"
434
      pp_machine_memtype_name m.mname.node_id
435
      (pp_print_list
436
         ~pp_open_box:pp_open_vbox0
437
         ~pp_prologue:(fun fmt () ->
438
             fprintf fmt "@,@[%a {" pp_machine_regtype_name m.mname.node_id)
439
         ~pp_sep:pp_print_semicolon
440
         ~pp_eol:pp_print_semicolon'
441
         ~pp_epilogue:(fun fmt () -> fprintf fmt "}@] _reg;")
442
         pp_c_decl_struct_var)
443
      m.mmemory
444
      (pp_print_list
445
         ~pp_prologue:pp_print_cut
446
         ~pp_sep:pp_print_semicolon
447
         ~pp_eol:pp_print_semicolon'
448
         pp_c_decl_instance_var)
449
      m.minstances
450

    
451
(********************************************************************************************)
452
(*                      Prototype Printing functions                                        *)
453
(********************************************************************************************)
454

    
455
let print_global_init_prototype fmt baseNAME =
456
  fprintf fmt "void %a ()"
457
    pp_global_init_name baseNAME
458

    
459
let print_global_clear_prototype fmt baseNAME =
460
  fprintf fmt "void %a ()"
461
    pp_global_clear_name baseNAME
462

    
463
let print_alloc_prototype fmt (name, static) =
464
  fprintf fmt "%a * %a %a"
465
    pp_machine_memtype_name name
466
    pp_machine_alloc_name name
467
    (pp_print_parenthesized pp_c_decl_input_var) static
468

    
469
let print_dealloc_prototype fmt name =
470
  fprintf fmt "void %a (%a * _alloc)"
471
    pp_machine_dealloc_name name
472
    pp_machine_memtype_name name
473
    
474
let print_reset_prototype self fmt (name, static) =
475
  fprintf fmt "void %a (%a%a *%s)"
476
    pp_machine_reset_name name
477
    (pp_print_list ~pp_sep:pp_print_comma ~pp_eol:pp_print_comma
478
       pp_c_decl_input_var) static
479
    pp_machine_memtype_name name
480
    self
481

    
482
let print_init_prototype self fmt (name, static) =
483
  fprintf fmt "void %a (%a%a *%s)"
484
    pp_machine_init_name name
485
    (pp_print_list ~pp_sep:pp_print_comma ~pp_eol:pp_print_comma
486
       pp_c_decl_input_var) static
487
    pp_machine_memtype_name name
488
    self
489

    
490
let print_clear_prototype self fmt (name, static) =
491
  fprintf fmt "void %a (%a%a *%s)"
492
    pp_machine_clear_name name
493
    (pp_print_list ~pp_sep:pp_print_comma ~pp_eol:pp_print_comma
494
       pp_c_decl_input_var) static
495
    pp_machine_memtype_name name
496
    self
497

    
498
let print_stateless_prototype fmt (name, inputs, outputs) =
499
  fprintf fmt "void %a (@[<v>%a%a@])"
500
    pp_machine_step_name name
501
    (pp_print_list ~pp_sep:pp_print_comma ~pp_eol:pp_print_comma
502
       ~pp_epilogue:pp_print_cut pp_c_decl_input_var) inputs
503
    (pp_print_list ~pp_sep:pp_print_comma pp_c_decl_output_var) outputs
504

    
505
let print_step_prototype self fmt (name, inputs, outputs) =
506
  fprintf fmt "void %a (@[<v>%a%a%a *%s@])"
507
    pp_machine_step_name name
508
    (pp_print_list ~pp_sep:pp_print_comma ~pp_eol:pp_print_comma
509
       ~pp_epilogue:pp_print_cut pp_c_decl_input_var) inputs
510
    (pp_print_list ~pp_sep:pp_print_comma ~pp_eol:pp_print_comma
511
       ~pp_epilogue:pp_print_cut pp_c_decl_output_var) outputs
512
    pp_machine_memtype_name name
513
    self
514

    
515
let print_import_prototype fmt dep =
516
  fprintf fmt "#include \"%s.h\"" dep.name
517

    
518
let print_import_alloc_prototype fmt dep =
519
  if dep.is_stateful then
520
    fprintf fmt "#include \"%s_alloc.h\"" dep.name
521

    
522
let pp_c_var m self pp_var fmt var =
523
    pp_c_val m self pp_var fmt (Machine_code_common.mk_val (Var var) var.var_type)
524

    
525
let pp_array_suffix =
526
  pp_print_list ~pp_sep:pp_print_nothing (fun fmt v -> fprintf fmt "[%s]" v)
527

    
528
let mpfr_vars vars =
529
  if !Options.mpfr then
530
    List.filter (fun v -> Types.(is_real_type (array_base_type v.var_type))) vars
531
  else []
532

    
533
let mpfr_consts consts =
534
  if !Options.mpfr then
535
    List.filter (fun c -> Types.(is_real_type (array_base_type c.const_type))) consts
536
  else []
537

    
538
(* type directed initialization: useless wrt the lustre compilation model,
539
   except for MPFR injection, where values are dynamically allocated
540
*)
541
let pp_initialize m self pp_var fmt var =
542
  let rec aux indices fmt typ =
543
    if Types.is_array_type typ
544
    then
545
      let dim = Types.array_type_dimension typ in
546
      let idx = mk_loop_var m () in
547
      fprintf fmt "@[<v 2>{@,int %s;@,for(%s=0;%s<%a;%s++)@,%a @]@,}"
548
        idx idx idx pp_c_dimension dim idx
549
        (aux (idx::indices)) (Types.array_element_type typ)
550
    else
551
      let indices = List.rev indices in
552
      let pp_var_suffix fmt var =
553
        fprintf fmt "%a%a" (pp_c_var m self pp_var) var pp_array_suffix indices in
554
      Mpfr.pp_inject_init pp_var_suffix fmt var
555
  in
556
  reset_loop_counter ();
557
  aux [] fmt var.var_type
558

    
559
(* type directed clear: useless wrt the lustre compilation model,
560
   except for MPFR injection, where values are dynamically allocated
561
*)
562
let pp_clear m self pp_var fmt var =
563
  let rec aux indices fmt typ =
564
    if Types.is_array_type typ
565
    then
566
      let dim = Types.array_type_dimension typ in
567
      let idx = mk_loop_var m () in
568
      fprintf fmt "@[<v 2>{@,int %s;@,for(%s=0;%s<%a;%s++)@,%a @]@,}"
569
        idx idx idx pp_c_dimension dim idx
570
        (aux (idx::indices)) (Types.array_element_type typ)
571
    else
572
      let indices = List.rev indices in
573
      let pp_var_suffix fmt var =
574
        fprintf fmt "%a%a" (pp_c_var m self pp_var) var pp_array_suffix indices in
575
      Mpfr.pp_inject_clear pp_var_suffix fmt var
576
  in
577
  reset_loop_counter ();
578
  aux [] fmt var.var_type
579

    
580
  (*** Common functions for main ***)
581

    
582
let pp_print_file file_suffix fmt (typ, arg) =
583
  fprintf fmt
584
    "@[<v 2>if (traces) {@,\
585
     fprintf(f_%s, \"%%%s\\n\", %s);@,\
586
     fflush(f_%s);@]@,\
587
     }"
588
    file_suffix typ arg
589
    file_suffix
590
  
591
let print_put_var fmt file_suffix name var_type var_id =
592
  let pp_file = pp_print_file ("out" ^ file_suffix) in
593
  let unclocked_t = Types.unclock_type var_type in
594
  fprintf fmt "@[<v>%a@]"
595
    (fun fmt () ->
596
       if Types.is_int_type unclocked_t then
597
         fprintf fmt "_put_int(\"%s\", %s);@,%a"
598
           name var_id
599
           pp_file ("d", var_id)
600
       else if Types.is_bool_type unclocked_t then
601
         fprintf fmt "_put_bool(\"%s\", %s);@,%a"
602
           name var_id
603
           pp_file ("i", var_id)
604
       else if Types.is_real_type unclocked_t then
605
         if !Options.mpfr then
606
           fprintf fmt "_put_double(\"%s\", mpfr_get_d(%s, %s), %i);@,%a"
607
             name var_id (Mpfr.mpfr_rnd ()) !Options.print_prec_double
608
             pp_file (".*f",
609
                      string_of_int !Options.print_prec_double
610
                      ^ ", mpfr_get_d(" ^ var_id ^ ", MPFR_RNDN)")
611
         else
612
           fprintf fmt "_put_double(\"%s\", %s, %i);@,%a"
613
             name var_id !Options.print_prec_double
614
             pp_file (".*f",
615
                      string_of_int !Options.print_prec_double ^ ", " ^ var_id)
616
       else begin
617
         eprintf "Impossible to print the _put_xx for type %a@.@?"
618
           Types.print_ty var_type;
619
         assert false
620
       end) ()
621

    
622
let pp_file_decl fmt inout idx =
623
  let idx = idx + 1 in (* we start from 1: in1, in2, ... *)
624
  fprintf fmt "FILE *f_%s%i;" inout idx
625

    
626
let pp_file_open fmt inout idx =
627
  let idx = idx + 1 in (* we start from 1: in1, in2, ... *)
628
  fprintf fmt
629
    "@[<v>const char* cst_char_suffix_%s%i = \"_simu.%s%i\";@,\
630
     size_t l%s%i = strlen(dir) + strlen(prefix) + strlen(cst_char_suffix_%s%i);@,\
631
     char* f_%s%i_name = malloc((l%s%i+2) * sizeof(char));@,\
632
     strcpy (f_%s%i_name, dir);@,\
633
     strcat(f_%s%i_name, \"/\");@,\
634
     strcat(f_%s%i_name, prefix);@,\
635
     strcat(f_%s%i_name, cst_char_suffix_%s%i);@,\
636
     f_%s%i = fopen(f_%s%i_name, \"w\");@,\
637
     free(f_%s%i_name);\
638
     @]"
639
    inout idx inout idx
640
    inout idx inout idx
641
    inout idx inout idx
642
    inout idx
643
    inout idx
644
    inout idx
645
    inout idx inout idx
646
    inout idx inout idx
647
    inout idx;
648
  "f_" ^ inout ^ string_of_int idx
649

    
650

    
651
(* Local Variables: *)
652
(* compile-command:"make -C ../../.." *)
653
(* End: *)
(3-3/10)