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
|
13
|
open Format
|
14
|
open Lustre_types
|
15
|
open Corelang
|
16
|
open Machine_code_types
|
17
|
open Machine_code_common
|
18
|
module Mpfr = Lustrec_mpfr
|
19
|
|
20
|
let pp_print_version fmt () =
|
21
|
fprintf
|
22
|
fmt
|
23
|
"/* @[<v>C code generated by %s@,\
|
24
|
Version number %s@,\
|
25
|
Code is %s compliant@,\
|
26
|
Using %s numbers */@,\
|
27
|
@]"
|
28
|
(Filename.basename Sys.executable_name)
|
29
|
Version.number
|
30
|
(if !Options.ansi then "ANSI C90" else "C99")
|
31
|
(if !Options.mpfr then "MPFR multi-precision"
|
32
|
else "(double) floating-point")
|
33
|
|
34
|
let protect_filename s = Str.global_replace (Str.regexp "\\.\\|\\ ") "_" s
|
35
|
|
36
|
let file_to_module_name basename =
|
37
|
let baseNAME = Ocaml_utils.uppercase basename in
|
38
|
let baseNAME = protect_filename baseNAME in
|
39
|
baseNAME
|
40
|
|
41
|
let pp_ptr fmt = fprintf fmt "*%s"
|
42
|
|
43
|
let reset_label = "Reset"
|
44
|
|
45
|
let pp_label fmt = fprintf fmt "%s:"
|
46
|
|
47
|
let var_is name v = v.var_id = name
|
48
|
|
49
|
let mk_local n m =
|
50
|
let used name =
|
51
|
let open List in
|
52
|
exists (var_is name) m.mstep.step_inputs
|
53
|
|| exists (var_is name) m.mstep.step_outputs
|
54
|
|| exists (var_is name) m.mstep.step_locals
|
55
|
|| exists (var_is name) m.mmemory
|
56
|
in
|
57
|
mk_new_name used n
|
58
|
|
59
|
(* Generation of a non-clashing name for the self memory variable (for step and
|
60
|
reset functions) *)
|
61
|
let mk_self = mk_local "self"
|
62
|
|
63
|
let mk_mem = mk_local "mem"
|
64
|
|
65
|
let mk_mem_c = mk_local "mem_c"
|
66
|
|
67
|
let mk_mem_in = mk_local "mem_in"
|
68
|
|
69
|
let mk_mem_out = mk_local "mem_out"
|
70
|
|
71
|
let mk_mem_in_c = mk_local "mem_in_c"
|
72
|
|
73
|
let mk_mem_out_c = mk_local "mem_out_c"
|
74
|
|
75
|
let mk_mem_reset = mk_local "mem_reset"
|
76
|
|
77
|
(* Generation of a non-clashing name for the instance variable of static
|
78
|
allocation macro *)
|
79
|
let mk_instance m =
|
80
|
let used name =
|
81
|
let open List in
|
82
|
exists (var_is name) m.mstep.step_inputs || exists (var_is name) m.mmemory
|
83
|
in
|
84
|
mk_new_name used "inst"
|
85
|
|
86
|
(* Generation of a non-clashing name for the attribute variable of static
|
87
|
allocation macro *)
|
88
|
let mk_attribute m =
|
89
|
let used name =
|
90
|
let open List in
|
91
|
exists (var_is name) m.mstep.step_inputs || exists (var_is name) m.mmemory
|
92
|
in
|
93
|
mk_new_name used "attr"
|
94
|
|
95
|
let mk_call_var_decl loc id =
|
96
|
{
|
97
|
var_id = id;
|
98
|
var_orig = false;
|
99
|
var_dec_type = mktyp Location.dummy Tydec_any;
|
100
|
var_dec_clock = mkclock Location.dummy Ckdec_any;
|
101
|
var_dec_const = false;
|
102
|
var_dec_value = None;
|
103
|
var_parent_nodeid = None;
|
104
|
var_type = Type_predef.type_arrow (Types.new_var ()) (Types.new_var ());
|
105
|
var_clock = Clocks.new_var true;
|
106
|
var_loc = loc;
|
107
|
var_is_contract = false;
|
108
|
}
|
109
|
|
110
|
(* counter for loop variable creation *)
|
111
|
let loop_cpt = ref (-1)
|
112
|
|
113
|
let reset_loop_counter () = loop_cpt := -1
|
114
|
|
115
|
let mk_loop_var m () =
|
116
|
let vars =
|
117
|
m.mstep.step_inputs @ m.mstep.step_outputs @ m.mstep.step_locals @ m.mmemory
|
118
|
in
|
119
|
let rec aux () =
|
120
|
incr loop_cpt;
|
121
|
let s = sprintf "__%s_%d" "i" !loop_cpt in
|
122
|
if List.exists (var_is s) vars then aux () else s
|
123
|
in
|
124
|
aux ()
|
125
|
|
126
|
(* let addr_cpt = ref (-1)
|
127
|
|
128
|
let reset_addr_counter () = addr_cpt := -1
|
129
|
|
130
|
let mk_addr_var m var = let vars = m.mmemory in let rec aux () = incr
|
131
|
addr_cpt; let s = Printf.sprintf "%s_%s_%d" var "addr" !addr_cpt in if
|
132
|
List.exists (fun v -> v.var_id = s) vars then aux () else s in aux () *)
|
133
|
let pp_global_init_name fmt id = fprintf fmt "%s_INIT" id
|
134
|
|
135
|
let pp_global_clear_name fmt id = fprintf fmt "%s_CLEAR" id
|
136
|
|
137
|
let pp_machine_memtype_name ?(ghost = false) fmt id =
|
138
|
fprintf fmt "struct %s_mem%s" id (if ghost then "_ghost" else "")
|
139
|
|
140
|
let pp_machine_decl ?(ghost = false) pp_var fmt (id, var) =
|
141
|
fprintf fmt "%a %a" (pp_machine_memtype_name ~ghost) id pp_var var
|
142
|
|
143
|
let pp_machine_decl' ?(ghost = false) fmt =
|
144
|
pp_machine_decl ~ghost pp_print_string fmt
|
145
|
|
146
|
let pp_machine_regtype_name fmt id = fprintf fmt "struct %s_reg" id
|
147
|
|
148
|
let pp_machine_alloc_name fmt id = fprintf fmt "%s_alloc" id
|
149
|
|
150
|
let pp_machine_dealloc_name fmt id = fprintf fmt "%s_dealloc" id
|
151
|
|
152
|
let pp_machine_static_declare_name ?(ghost = false) fmt id =
|
153
|
fprintf fmt "%s_DECLARE%s" id (if ghost then "_GHOST" else "")
|
154
|
|
155
|
let pp_machine_static_link_name ?(ghost = false) fmt id =
|
156
|
fprintf fmt "%s_LINK%s" id (if ghost then "_GHOST" else "")
|
157
|
|
158
|
let pp_machine_static_alloc_name ?(ghost = false) fmt id =
|
159
|
fprintf fmt "%s_ALLOC%s" id (if ghost then "_GHOST" else "")
|
160
|
|
161
|
let pp_machine_set_reset_name fmt id = fprintf fmt "%s_set_reset" id
|
162
|
|
163
|
let pp_machine_clear_reset_name fmt id = fprintf fmt "%s_clear_reset" id
|
164
|
|
165
|
let pp_machine_init_name fmt id = fprintf fmt "%s_init" id
|
166
|
|
167
|
let pp_machine_clear_name fmt id = fprintf fmt "%s_clear" id
|
168
|
|
169
|
let pp_machine_step_name fmt id = fprintf fmt "%s_step" id
|
170
|
|
171
|
let pp_mod pp_val v1 v2 fmt =
|
172
|
if !Options.integer_div_euclidean then
|
173
|
(* (a mod_C b) + (a mod_C b < 0 ? abs(b) : 0) *)
|
174
|
fprintf
|
175
|
fmt
|
176
|
"((%a %% %a) + ((%a %% %a) < 0?(abs(%a)):0))"
|
177
|
pp_val
|
178
|
v1
|
179
|
pp_val
|
180
|
v2
|
181
|
pp_val
|
182
|
v1
|
183
|
pp_val
|
184
|
v2
|
185
|
pp_val
|
186
|
v2
|
187
|
else
|
188
|
(* Regular behavior: printing a % *)
|
189
|
fprintf fmt "(%a %% %a)" pp_val v1 pp_val v2
|
190
|
|
191
|
let pp_div pp_val v1 v2 fmt =
|
192
|
if !Options.integer_div_euclidean then
|
193
|
(* (a - ((a mod_C b) + (a mod_C b < 0 ? abs(b) : 0))) div_C b *)
|
194
|
fprintf fmt "(%a - %t) / %a" pp_val v1 (pp_mod pp_val v1 v2) pp_val v2
|
195
|
else
|
196
|
(* Regular behavior: printing a / *)
|
197
|
fprintf fmt "(%a / %a)" pp_val v1 pp_val v2
|
198
|
|
199
|
let pp_basic_lib_fun is_int i pp_val fmt vl =
|
200
|
match i, vl with
|
201
|
(* | "ite", [v1; v2; v3] -> fprintf fmt "(%a?(%a):(%a))" pp_val v1 pp_val v2
|
202
|
pp_val v3 *)
|
203
|
| "uminus", [ v ] ->
|
204
|
fprintf fmt "(- %a)" pp_val v
|
205
|
| "not", [ v ] ->
|
206
|
fprintf fmt "(!%a)" pp_val v
|
207
|
| "impl", [ v1; v2 ] ->
|
208
|
fprintf fmt "(!%a || %a)" pp_val v1 pp_val v2
|
209
|
| "=", [ v1; v2 ] ->
|
210
|
fprintf fmt "(%a == %a)" pp_val v1 pp_val v2
|
211
|
| "mod", [ v1; v2 ] ->
|
212
|
if is_int then pp_mod pp_val v1 v2 fmt
|
213
|
else fprintf fmt "(%a %% %a)" pp_val v1 pp_val v2
|
214
|
| "equi", [ v1; v2 ] ->
|
215
|
fprintf fmt "(!%a == !%a)" pp_val v1 pp_val v2
|
216
|
| "xor", [ v1; v2 ] ->
|
217
|
fprintf fmt "(!%a != !%a)" pp_val v1 pp_val v2
|
218
|
| "/", [ v1; v2 ] ->
|
219
|
if is_int then pp_div pp_val v1 v2 fmt
|
220
|
else fprintf fmt "(%a / %a)" pp_val v1 pp_val v2
|
221
|
| _, [ v1; v2 ] ->
|
222
|
fprintf fmt "(%a %s %a)" pp_val v1 i pp_val v2
|
223
|
| _ ->
|
224
|
(* TODO: raise proper error *)
|
225
|
eprintf "internal error: C_backend_common.pp_basic_lib_fun %s@." i;
|
226
|
assert false
|
227
|
|
228
|
let rec pp_c_dimension fmt dim =
|
229
|
let open Dimension in
|
230
|
match dim.dim_desc with
|
231
|
| Dident id ->
|
232
|
fprintf fmt "%s" id
|
233
|
| Dint i ->
|
234
|
fprintf fmt "%d" i
|
235
|
| Dbool b ->
|
236
|
fprintf fmt "%B" b
|
237
|
| Dite (i, t, e) ->
|
238
|
fprintf
|
239
|
fmt
|
240
|
"((%a)?%a:%a)"
|
241
|
pp_c_dimension
|
242
|
i
|
243
|
pp_c_dimension
|
244
|
t
|
245
|
pp_c_dimension
|
246
|
e
|
247
|
| Dappl (f, args) ->
|
248
|
fprintf
|
249
|
fmt
|
250
|
"%a"
|
251
|
(pp_basic_lib_fun (Basic_library.is_numeric_operator f) f pp_c_dimension)
|
252
|
args
|
253
|
| Dlink dim' ->
|
254
|
fprintf fmt "%a" pp_c_dimension dim'
|
255
|
| Dvar ->
|
256
|
fprintf fmt "_%s" (Utils.name_of_dimension dim.dim_id)
|
257
|
| Dunivar ->
|
258
|
fprintf fmt "'%s" (Utils.name_of_dimension dim.dim_id)
|
259
|
|
260
|
let is_basic_c_type t =
|
261
|
Types.(is_int_type t || is_real_type t || is_bool_type t)
|
262
|
|
263
|
let pp_c_basic_type_desc t_desc =
|
264
|
if Types.is_bool_type t_desc then if !Options.cpp then "bool" else "_Bool"
|
265
|
else if Types.is_int_type t_desc then !Options.int_type
|
266
|
else if Types.is_real_type t_desc then
|
267
|
if !Options.mpfr then Mpfr.mpfr_t else !Options.real_type
|
268
|
else assert false
|
269
|
(* Not a basic C type. Do not handle arrays or pointers *)
|
270
|
|
271
|
let pp_basic_c_type ?(pp_c_basic_type_desc = pp_c_basic_type_desc) ?var_opt fmt
|
272
|
t =
|
273
|
match var_opt with
|
274
|
| Some v when Machine_types.is_exportable v ->
|
275
|
Machine_types.pp_c_var_type fmt v
|
276
|
| _ ->
|
277
|
fprintf fmt "%s" (pp_c_basic_type_desc t)
|
278
|
|
279
|
let pp_c_type ?(var_is_contract = false) ?pp_c_basic_type_desc ?var_opt var_id
|
280
|
fmt t =
|
281
|
let rec aux t pp_suffix =
|
282
|
if is_basic_c_type t then
|
283
|
fprintf
|
284
|
fmt
|
285
|
"%a %s%s%a"
|
286
|
(pp_basic_c_type ?pp_c_basic_type_desc ?var_opt)
|
287
|
t
|
288
|
(if var_is_contract then "\\ghost " else "")
|
289
|
var_id
|
290
|
pp_suffix
|
291
|
()
|
292
|
else
|
293
|
let open Types in
|
294
|
match (repr t).tdesc with
|
295
|
| Tclock t' ->
|
296
|
aux t' pp_suffix
|
297
|
| Tarray (d, t') ->
|
298
|
let pp_suffix' fmt () =
|
299
|
fprintf fmt "%a[%a]" pp_suffix () pp_c_dimension d
|
300
|
in
|
301
|
aux t' pp_suffix'
|
302
|
| Tstatic (_, t') ->
|
303
|
fprintf fmt "const ";
|
304
|
aux t' pp_suffix
|
305
|
| Tconst ty ->
|
306
|
fprintf fmt "%s %s" ty var_id
|
307
|
| Tarrow (_, _) ->
|
308
|
fprintf fmt "void (*%s)()" var_id
|
309
|
| _ ->
|
310
|
(* TODO: raise proper error *)
|
311
|
eprintf "internal error: C_backend_common.pp_c_type %a@." pp t;
|
312
|
assert false
|
313
|
in
|
314
|
aux t (fun _ () -> ())
|
315
|
|
316
|
(* let rec pp_c_initialize fmt t = match (Types.repr t).Types.tdesc with |
|
317
|
Types.Tint -> pp_print_string fmt "0" | Types.Tclock t' -> pp_c_initialize
|
318
|
fmt t' | Types.Tbool -> pp_print_string fmt "0" | Types.Treal when not
|
319
|
!Options.mpfr -> pp_print_string fmt "0." | Types.Tarray (d, t') when
|
320
|
Dimension.is_dimension_const d -> fprintf fmt "{%a}" (Utils.fprintf_list
|
321
|
~sep:"," (fun fmt _ -> pp_c_initialize fmt t')) (Utils.duplicate 0
|
322
|
(Dimension.size_const_dimension d)) | _ -> assert false *)
|
323
|
let pp_c_tag fmt t =
|
324
|
pp_print_string
|
325
|
fmt
|
326
|
(if t = tag_true then "1" else if t = tag_false then "0" else t)
|
327
|
|
328
|
(* Prints a constant value *)
|
329
|
let rec pp_c_const fmt c =
|
330
|
match c with
|
331
|
| Const_int i ->
|
332
|
pp_print_int fmt i
|
333
|
| Const_real r ->
|
334
|
Real.pp fmt r
|
335
|
(* | Const_float r -> pp_print_float fmt r *)
|
336
|
| Const_tag t ->
|
337
|
pp_c_tag fmt t
|
338
|
| Const_array ca ->
|
339
|
pp_print_braced pp_c_const fmt ca
|
340
|
| Const_struct fl ->
|
341
|
pp_print_braced (fun fmt (_, c) -> pp_c_const fmt c) fmt fl
|
342
|
| Const_string _ | Const_modeid _ ->
|
343
|
assert false
|
344
|
(* string occurs in annotations not in C *)
|
345
|
|
346
|
let reset_flag_name = "_reset"
|
347
|
|
348
|
let pp_reset_flag ?(indirect = true) pp_stru fmt stru =
|
349
|
fprintf
|
350
|
fmt
|
351
|
"%a%s%s"
|
352
|
pp_stru
|
353
|
stru
|
354
|
(if indirect then "->" else ".")
|
355
|
reset_flag_name
|
356
|
|
357
|
let pp_reset_flag' ?indirect fmt = pp_reset_flag ?indirect pp_print_string fmt
|
358
|
|
359
|
let pp_reset_assign self fmt b =
|
360
|
fprintf
|
361
|
fmt
|
362
|
"%a = %i;"
|
363
|
(pp_reset_flag' ~indirect:true)
|
364
|
self
|
365
|
(if b then 1 else 0)
|
366
|
|
367
|
(* Prints a value expression [v], with internal function calls only. [pp_var] is
|
368
|
a printer for variables (typically [pp_c_var_read]), but an offset suffix may
|
369
|
be added for array variables *)
|
370
|
let rec pp_c_val m self pp_var fmt v =
|
371
|
let pp_c_val = pp_c_val m self pp_var in
|
372
|
match v.value_desc with
|
373
|
| Cst c ->
|
374
|
pp_c_const fmt c
|
375
|
| Array vl ->
|
376
|
pp_print_braced pp_c_val fmt vl
|
377
|
| Access (t, i) ->
|
378
|
fprintf fmt "%a[%a]" pp_c_val t pp_c_val i
|
379
|
| Power (v, _) ->
|
380
|
(* TODO: raise proper error *)
|
381
|
eprintf
|
382
|
"internal error: C_backend_common.pp_c_val %a@."
|
383
|
(Machine_code_common.pp_val m)
|
384
|
v;
|
385
|
assert false
|
386
|
| Var v ->
|
387
|
if Machine_code_common.is_memory m v then
|
388
|
(* array memory vars are represented by an indirection to a local var
|
389
|
* with the right type, in order to avoid casting everywhere. *)
|
390
|
if
|
391
|
Types.is_array_type v.var_type
|
392
|
&& not (Types.is_real_type v.var_type && !Options.mpfr)
|
393
|
then fprintf fmt "%a" pp_var v
|
394
|
else fprintf fmt "%s->_reg.%a" self pp_var v
|
395
|
else pp_var fmt v
|
396
|
| Fun (n, vl) ->
|
397
|
pp_basic_lib_fun (Types.is_int_type v.value_type) n pp_c_val fmt vl
|
398
|
| ResetFlag ->
|
399
|
pp_reset_flag' fmt self
|
400
|
|
401
|
(* Access to the value of a variable: - if it's not a scalar output, then its
|
402
|
name is enough - otherwise, dereference it (it has been declared as a
|
403
|
pointer, despite its scalar Lustre type) - moreover, dereference memory array
|
404
|
variables. *)
|
405
|
let pp_c_var_read ?(test_output = true) m fmt id =
|
406
|
(* mpfr_t is a static array, not treated as general arrays *)
|
407
|
if Types.is_address_type id.var_type then
|
408
|
if
|
409
|
Machine_code_common.is_memory m id
|
410
|
&& not (Types.is_real_type id.var_type && !Options.mpfr)
|
411
|
then fprintf fmt "(*%s)" id.var_id
|
412
|
else fprintf fmt "%s" id.var_id
|
413
|
else if test_output && Machine_code_common.is_output m id then
|
414
|
fprintf fmt "*%s" id.var_id
|
415
|
else fprintf fmt "%s" id.var_id
|
416
|
|
417
|
(* Addressable value of a variable, the one that is passed around in calls: - if
|
418
|
it's not a scalar non-output, then its name is enough - otherwise, reference
|
419
|
it (it must be passed as a pointer, despite its scalar Lustre type) *)
|
420
|
let pp_c_var_write m fmt id =
|
421
|
if Types.is_address_type id.var_type then fprintf fmt "%s" id.var_id
|
422
|
else if Machine_code_common.is_output m id then fprintf fmt "%s" id.var_id
|
423
|
else fprintf fmt "&%s" id.var_id
|
424
|
|
425
|
(* Declaration of an input variable: - if its type is array/matrix/etc, then
|
426
|
declare it as a mere pointer, in order to cope with unknown/parametric array
|
427
|
dimensions, as it is the case for generics *)
|
428
|
let pp_c_decl_input_var fmt id =
|
429
|
if !Options.ansi && Types.is_address_type id.var_type then
|
430
|
pp_c_type
|
431
|
~var_opt:id
|
432
|
(sprintf "(*%s)" id.var_id)
|
433
|
fmt
|
434
|
(Types.array_base_type id.var_type)
|
435
|
else pp_c_type ~var_opt:id id.var_id fmt id.var_type
|
436
|
|
437
|
(* Declaration of an output variable: - if its type is scalar, then pass its
|
438
|
address - if its type is array/matrix/struct/etc, then declare it as a mere
|
439
|
pointer, in order to cope with unknown/parametric array dimensions, as it is
|
440
|
the case for generics *)
|
441
|
let pp_c_decl_output_var fmt id =
|
442
|
if (not !Options.ansi) && Types.is_address_type id.var_type then
|
443
|
pp_c_type
|
444
|
~var_is_contract:id.var_is_contract
|
445
|
~var_opt:id
|
446
|
id.var_id
|
447
|
fmt
|
448
|
id.var_type
|
449
|
else
|
450
|
pp_c_type
|
451
|
~var_is_contract:id.var_is_contract
|
452
|
~var_opt:id
|
453
|
(sprintf "(*%s)" id.var_id)
|
454
|
fmt
|
455
|
(Types.array_base_type id.var_type)
|
456
|
|
457
|
(* Declaration of a local/mem variable: - if it's an array/matrix/etc, its
|
458
|
size(s) should be known in order to statically allocate memory, so we print
|
459
|
the full type *)
|
460
|
let pp_c_decl_local_var ?pp_c_basic_type_desc m fmt id =
|
461
|
if id.var_dec_const then
|
462
|
fprintf
|
463
|
fmt
|
464
|
"%a = %a"
|
465
|
(pp_c_type ?pp_c_basic_type_desc ~var_opt:id id.var_id)
|
466
|
id.var_type
|
467
|
(pp_c_val m "" (pp_c_var_read m))
|
468
|
(Machine_code_common.get_const_assign m id)
|
469
|
else
|
470
|
fprintf
|
471
|
fmt
|
472
|
"%a"
|
473
|
(pp_c_type ?pp_c_basic_type_desc ~var_opt:id id.var_id)
|
474
|
id.var_type
|
475
|
|
476
|
(* Declaration of a struct variable: - if it's an array/matrix/etc, we declare
|
477
|
it as a pointer *)
|
478
|
let pp_c_decl_struct_var fmt id =
|
479
|
if Types.is_array_type id.var_type then
|
480
|
pp_c_type
|
481
|
(sprintf "(*%s)" id.var_id)
|
482
|
fmt
|
483
|
(Types.array_base_type id.var_type)
|
484
|
else pp_c_type id.var_id fmt id.var_type
|
485
|
|
486
|
let pp_c_decl_instance_var ?(ghost = false) fmt (name, (node, _)) =
|
487
|
fprintf
|
488
|
fmt
|
489
|
"%a %s%s"
|
490
|
(pp_machine_memtype_name ~ghost)
|
491
|
(node_name node)
|
492
|
(if ghost then "" else "*")
|
493
|
name
|
494
|
|
495
|
(* let pp_c_checks self fmt m =
|
496
|
* pp_print_list
|
497
|
* (fun fmt (loc, check) ->
|
498
|
* fprintf fmt
|
499
|
* "@[<v>%a@,assert (%a);@]"
|
500
|
* Location.pp_c_loc loc
|
501
|
* (pp_c_val m self (pp_c_var_read m)) check)
|
502
|
* fmt
|
503
|
* m.mstep.step_checks *)
|
504
|
|
505
|
let has_c_prototype funname dependencies =
|
506
|
(* We select the last imported node with the name funname. The order of
|
507
|
evaluation of dependencies should be compatible with overloading. (Not
|
508
|
checked yet) *)
|
509
|
let imported_node_opt =
|
510
|
List.fold_left
|
511
|
(fun res dep ->
|
512
|
match res with
|
513
|
| Some _ ->
|
514
|
res
|
515
|
| None ->
|
516
|
let decls = dep.content in
|
517
|
let matched t =
|
518
|
match t.top_decl_desc with
|
519
|
| ImportedNode nd ->
|
520
|
nd.nodei_id = funname
|
521
|
| _ ->
|
522
|
false
|
523
|
in
|
524
|
if List.exists matched decls then
|
525
|
match (List.find matched decls).top_decl_desc with
|
526
|
| ImportedNode nd ->
|
527
|
Some nd
|
528
|
| _ ->
|
529
|
assert false
|
530
|
else None)
|
531
|
None
|
532
|
dependencies
|
533
|
in
|
534
|
match imported_node_opt with
|
535
|
| None ->
|
536
|
false
|
537
|
| Some nd -> (
|
538
|
match nd.nodei_prototype with Some "C" -> true | _ -> false)
|
539
|
|
540
|
(* Computes the depth to which multi-dimension array assignments should be
|
541
|
expanded. It equals the maximum number of nested static array constructions
|
542
|
accessible from root [v]. *)
|
543
|
let rec expansion_depth v =
|
544
|
match v.value_desc with
|
545
|
| Cst cst ->
|
546
|
expansion_depth_cst cst
|
547
|
| Var _ ->
|
548
|
0
|
549
|
| Fun (_, vl) ->
|
550
|
List.fold_right (fun v -> max (expansion_depth v)) vl 0
|
551
|
| Array vl ->
|
552
|
1 + List.fold_right (fun v -> max (expansion_depth v)) vl 0
|
553
|
| Access (v, _) ->
|
554
|
max 0 (expansion_depth v - 1)
|
555
|
| Power _ ->
|
556
|
0 (*1 + expansion_depth v*)
|
557
|
| ResetFlag ->
|
558
|
0
|
559
|
|
560
|
and expansion_depth_cst c =
|
561
|
match c with
|
562
|
| Const_array cl ->
|
563
|
1 + List.fold_right (fun c -> max (expansion_depth_cst c)) cl 0
|
564
|
| _ ->
|
565
|
0
|
566
|
|
567
|
type loop_index = LVar of ident | LInt of int ref | LAcc of value_t
|
568
|
|
569
|
(* let rec value_offsets v offsets = match v, offsets with | _ , [] -> v | Power
|
570
|
(v, n) , _ :: q -> value_offsets v q | Array vl , LInt r :: q ->
|
571
|
value_offsets (List.nth vl !r) q | Cst (Const_array cl) , LInt r :: q ->
|
572
|
value_offsets (Cst (List.nth cl !r)) q | Fun (f, vl) , _ -> Fun (f, List.map
|
573
|
(fun v -> value_offsets v offsets) vl) | _ , LInt r :: q -> value_offsets
|
574
|
(Access (v, Cst (Const_int !r))) q | _ , LVar i :: q -> value_offsets (Access
|
575
|
(v, Var i)) q *)
|
576
|
(* Computes the list of nested loop variables together with their dimension
|
577
|
bounds.
|
578
|
* - LInt r stands for loop expansion (no loop variable, but int loop
|
579
|
index)
|
580
|
* - LVar v stands for loop variable v *)
|
581
|
let rec mk_loop_variables m ty depth =
|
582
|
match (Types.repr ty).Types.tdesc, depth with
|
583
|
| Types.Tarray (d, ty'), 0 ->
|
584
|
let v = mk_loop_var m () in
|
585
|
(d, LVar v) :: mk_loop_variables m ty' 0
|
586
|
| Types.Tarray (d, ty'), _ ->
|
587
|
let r = ref (-1) in
|
588
|
(d, LInt r) :: mk_loop_variables m ty' (depth - 1)
|
589
|
| _, 0 ->
|
590
|
[]
|
591
|
| _ ->
|
592
|
assert false
|
593
|
|
594
|
let reorder_loop_variables loop_vars =
|
595
|
let int_loops, var_loops =
|
596
|
List.partition (function _, LInt _ -> true | _ -> false) loop_vars
|
597
|
in
|
598
|
var_loops @ int_loops
|
599
|
|
600
|
(* Prints a one loop variable suffix for arrays *)
|
601
|
let pp_loop_var pp_val fmt lv =
|
602
|
match snd lv with
|
603
|
| LVar v ->
|
604
|
fprintf fmt "[%s]" v
|
605
|
| LInt r ->
|
606
|
fprintf fmt "[%d]" !r
|
607
|
| LAcc i ->
|
608
|
fprintf fmt "[%a]" pp_val i
|
609
|
|
610
|
(* Prints a suffix of loop variables for arrays *)
|
611
|
let pp_suffix pp_val =
|
612
|
pp_print_list ~pp_sep:pp_print_nothing (pp_loop_var pp_val)
|
613
|
|
614
|
let rec is_const_index v =
|
615
|
match v.value_desc with
|
616
|
| Cst (Const_int _) ->
|
617
|
true
|
618
|
| Fun (_, vl) ->
|
619
|
List.for_all is_const_index vl
|
620
|
| _ ->
|
621
|
false
|
622
|
|
623
|
(* Prints a value expression [v], with internal function calls only. [pp_var] is
|
624
|
a printer for variables (typically [pp_c_var_read]), but an offset suffix may
|
625
|
be added for array variables *)
|
626
|
(* Prints a constant value before a suffix (needs casting) *)
|
627
|
let rec pp_c_const_suffix var_type fmt c =
|
628
|
match c with
|
629
|
| Const_int i ->
|
630
|
pp_print_int fmt i
|
631
|
| Const_real r ->
|
632
|
Real.pp fmt r
|
633
|
| Const_tag t ->
|
634
|
pp_c_tag fmt t
|
635
|
| Const_array ca ->
|
636
|
let var_type = Types.array_element_type var_type in
|
637
|
fprintf
|
638
|
fmt
|
639
|
"(%a[])%a"
|
640
|
(pp_c_type "")
|
641
|
var_type
|
642
|
(pp_print_braced (pp_c_const_suffix var_type))
|
643
|
ca
|
644
|
| Const_struct fl ->
|
645
|
pp_print_braced
|
646
|
(fun fmt (f, c) ->
|
647
|
(pp_c_const_suffix (Types.struct_field_type var_type f)) fmt c)
|
648
|
fmt
|
649
|
fl
|
650
|
| Const_string _ | Const_modeid _ ->
|
651
|
assert false
|
652
|
(* string occurs in annotations not in C *)
|
653
|
|
654
|
(* Prints a [value] of type [var_type] indexed by the suffix list [loop_vars] *)
|
655
|
let rec pp_value_suffix ?(indirect = true) m self var_type loop_vars pp_var fmt
|
656
|
value =
|
657
|
(*eprintf "pp_value_suffix: %a %a %a@." Types.pp var_type Machine_code.pp_val
|
658
|
value pp_suffix loop_vars;*)
|
659
|
let pp_suffix =
|
660
|
pp_suffix (pp_value_suffix ~indirect m self var_type [] pp_var)
|
661
|
in
|
662
|
match loop_vars, value.value_desc with
|
663
|
| (x, LAcc i) :: q, _ when is_const_index i ->
|
664
|
let r = ref (Dimension.size_const (dimension_of_value i)) in
|
665
|
pp_value_suffix
|
666
|
~indirect
|
667
|
m
|
668
|
self
|
669
|
var_type
|
670
|
((x, LInt r) :: q)
|
671
|
pp_var
|
672
|
fmt
|
673
|
value
|
674
|
| (_, LInt r) :: q, Cst (Const_array cl) ->
|
675
|
let var_type = Types.array_element_type var_type in
|
676
|
pp_value_suffix
|
677
|
~indirect
|
678
|
m
|
679
|
self
|
680
|
var_type
|
681
|
q
|
682
|
pp_var
|
683
|
fmt
|
684
|
(mk_val (Cst (List.nth cl !r)) Type_predef.type_int)
|
685
|
| (_, LInt r) :: q, Array vl ->
|
686
|
let var_type = Types.array_element_type var_type in
|
687
|
pp_value_suffix ~indirect m self var_type q pp_var fmt (List.nth vl !r)
|
688
|
| loop_var :: q, Array vl ->
|
689
|
let var_type = Types.array_element_type var_type in
|
690
|
fprintf
|
691
|
fmt
|
692
|
"(%a[])%a%a"
|
693
|
(pp_c_type "")
|
694
|
var_type
|
695
|
(pp_print_braced (pp_value_suffix ~indirect m self var_type q pp_var))
|
696
|
vl
|
697
|
pp_suffix
|
698
|
[ loop_var ]
|
699
|
| [], Array vl ->
|
700
|
let var_type = Types.array_element_type var_type in
|
701
|
fprintf
|
702
|
fmt
|
703
|
"(%a[])%a"
|
704
|
(pp_c_type "")
|
705
|
var_type
|
706
|
(pp_print_braced (pp_value_suffix ~indirect m self var_type [] pp_var))
|
707
|
vl
|
708
|
| _ :: q, Power (v, _) ->
|
709
|
pp_value_suffix ~indirect m self var_type q pp_var fmt v
|
710
|
| _, Fun (n, vl) ->
|
711
|
pp_basic_lib_fun
|
712
|
(Types.is_int_type value.value_type)
|
713
|
n
|
714
|
(pp_value_suffix ~indirect m self var_type loop_vars pp_var)
|
715
|
fmt
|
716
|
vl
|
717
|
| _, Access (v, i) ->
|
718
|
let var_type = Type_predef.type_array (Dimension.mkdim_var ()) var_type in
|
719
|
pp_value_suffix
|
720
|
m
|
721
|
self
|
722
|
var_type
|
723
|
((Dimension.mkdim_var (), LAcc i) :: loop_vars)
|
724
|
pp_var
|
725
|
fmt
|
726
|
v
|
727
|
| _, Var v ->
|
728
|
if is_memory m v then
|
729
|
(* array memory vars are represented by an indirection to a local var with
|
730
|
the right type, in order to avoid casting everywhere. *)
|
731
|
if Types.is_array_type v.var_type then
|
732
|
fprintf fmt "%a%a" pp_var v pp_suffix loop_vars
|
733
|
else
|
734
|
fprintf
|
735
|
fmt
|
736
|
"%s%s_reg.%a%a"
|
737
|
self
|
738
|
(if indirect then "->" else ".")
|
739
|
pp_var
|
740
|
v
|
741
|
pp_suffix
|
742
|
loop_vars
|
743
|
else if is_reset_flag v then
|
744
|
fprintf
|
745
|
fmt
|
746
|
"%s%s%a%a"
|
747
|
self
|
748
|
(if indirect then "->" else ".")
|
749
|
pp_var
|
750
|
v
|
751
|
pp_suffix
|
752
|
loop_vars
|
753
|
else fprintf fmt "%a%a" pp_var v pp_suffix loop_vars
|
754
|
| _, Cst cst ->
|
755
|
pp_c_const_suffix var_type fmt cst
|
756
|
| _, ResetFlag ->
|
757
|
pp_reset_flag' fmt self
|
758
|
| _, _ ->
|
759
|
eprintf
|
760
|
"internal error: C_backend_common.pp_value_suffix %a %a %a@."
|
761
|
Types.pp
|
762
|
var_type
|
763
|
(pp_val m)
|
764
|
value
|
765
|
pp_suffix
|
766
|
loop_vars;
|
767
|
assert false
|
768
|
|
769
|
(********************************************************************************************)
|
770
|
(* Struct Printing functions *)
|
771
|
(********************************************************************************************)
|
772
|
|
773
|
(* let pp_registers_struct fmt m =
|
774
|
* pp_print_braced
|
775
|
* ~pp_prologue:(fun fmt () ->
|
776
|
* fprintf fmt "@[%a " pp_machine_regtype_name m.mname.node_id)
|
777
|
* ~pp_open_box:pp_open_vbox0
|
778
|
* ~pp_sep:pp_print_semicolon
|
779
|
* ~pp_eol:pp_print_semicolon
|
780
|
* ~pp_epilogue:(fun fmt () -> pp_print_string fmt "@] _reg;")
|
781
|
* pp_c_decl_struct_var
|
782
|
* fmt m.mmemory *)
|
783
|
|
784
|
let pp_machine_struct ?(ghost = false) fmt m =
|
785
|
if not (fst (Machine_code_common.get_stateless_status m)) then
|
786
|
(* Define struct *)
|
787
|
fprintf
|
788
|
fmt
|
789
|
"@[<v 2>%a {@,_Bool _reset;%a%a@]@,};"
|
790
|
(pp_machine_memtype_name ~ghost)
|
791
|
m.mname.node_id
|
792
|
(if ghost && not m.mis_contract then
|
793
|
fun fmt -> function
|
794
|
| [] ->
|
795
|
pp_print_nothing fmt ()
|
796
|
| _ ->
|
797
|
fprintf fmt "@,%a _reg;" pp_machine_regtype_name m.mname.node_id
|
798
|
else
|
799
|
pp_print_list
|
800
|
~pp_open_box:pp_open_vbox0
|
801
|
~pp_prologue:(fun fmt () ->
|
802
|
fprintf fmt "@,@[%a {" pp_machine_regtype_name m.mname.node_id)
|
803
|
~pp_sep:pp_print_semicolon
|
804
|
~pp_eol:pp_print_semicolon'
|
805
|
~pp_epilogue:(fun fmt () -> fprintf fmt "}@] _reg;")
|
806
|
pp_c_decl_struct_var)
|
807
|
m.mmemory
|
808
|
(pp_print_list
|
809
|
~pp_open_box:pp_open_vbox0
|
810
|
~pp_prologue:pp_print_cut
|
811
|
~pp_sep:pp_print_semicolon
|
812
|
~pp_eol:pp_print_semicolon'
|
813
|
(pp_c_decl_instance_var ~ghost))
|
814
|
m.minstances
|
815
|
|
816
|
(********************************************************************************************)
|
817
|
(* Prototype Printing functions *)
|
818
|
(********************************************************************************************)
|
819
|
|
820
|
let pp_global_init_prototype fmt baseNAME =
|
821
|
fprintf fmt "void %a ()" pp_global_init_name baseNAME
|
822
|
|
823
|
let pp_global_clear_prototype fmt baseNAME =
|
824
|
fprintf fmt "void %a ()" pp_global_clear_name baseNAME
|
825
|
|
826
|
let pp_alloc_prototype fmt (name, static) =
|
827
|
fprintf
|
828
|
fmt
|
829
|
"%a * %a %a"
|
830
|
(pp_machine_memtype_name ~ghost:false)
|
831
|
name
|
832
|
pp_machine_alloc_name
|
833
|
name
|
834
|
(pp_print_parenthesized pp_c_decl_input_var)
|
835
|
static
|
836
|
|
837
|
let pp_dealloc_prototype fmt name =
|
838
|
fprintf
|
839
|
fmt
|
840
|
"void %a (%a * _alloc)"
|
841
|
pp_machine_dealloc_name
|
842
|
name
|
843
|
(pp_machine_memtype_name ~ghost:false)
|
844
|
name
|
845
|
|
846
|
module type MODIFIERS_GHOST_PROTO = sig
|
847
|
val pp_ghost_parameters :
|
848
|
?cut:bool ->
|
849
|
formatter ->
|
850
|
(string * (formatter -> string -> unit)) list ->
|
851
|
unit
|
852
|
end
|
853
|
|
854
|
module EmptyGhostProto : MODIFIERS_GHOST_PROTO = struct
|
855
|
let pp_ghost_parameters ?cut _ _ = ignore cut
|
856
|
end
|
857
|
|
858
|
module Protos (Mod : MODIFIERS_GHOST_PROTO) = struct
|
859
|
let pp_mem_ghost name fmt mem =
|
860
|
pp_machine_decl
|
861
|
~ghost:true
|
862
|
(fun fmt mem -> fprintf fmt "\\ghost %a" pp_ptr mem)
|
863
|
fmt
|
864
|
(name, mem)
|
865
|
|
866
|
let pp_clear_reset_prototype self mem fmt (name, static) =
|
867
|
fprintf
|
868
|
fmt
|
869
|
"@[<v>void %a (%a%a *%s)%a@]"
|
870
|
pp_machine_clear_reset_name
|
871
|
name
|
872
|
(pp_comma_list ~pp_eol:pp_print_comma pp_c_decl_input_var)
|
873
|
static
|
874
|
(pp_machine_memtype_name ~ghost:false)
|
875
|
name
|
876
|
self
|
877
|
(Mod.pp_ghost_parameters ~cut:true)
|
878
|
[ mem, pp_mem_ghost name ]
|
879
|
|
880
|
let pp_set_reset_prototype self mem fmt (name, static) =
|
881
|
fprintf
|
882
|
fmt
|
883
|
"@[<v>void %a (%a%a *%s)%a@]"
|
884
|
pp_machine_set_reset_name
|
885
|
name
|
886
|
(pp_comma_list ~pp_eol:pp_print_comma pp_c_decl_input_var)
|
887
|
static
|
888
|
(pp_machine_memtype_name ~ghost:false)
|
889
|
name
|
890
|
self
|
891
|
(Mod.pp_ghost_parameters ~cut:true)
|
892
|
[ mem, pp_mem_ghost name ]
|
893
|
|
894
|
let pp_step_prototype self mem fmt (name, inputs, outputs) =
|
895
|
fprintf
|
896
|
fmt
|
897
|
"@[<v>void %a (@[<v>%a%a%a *%s@])%a@]"
|
898
|
pp_machine_step_name
|
899
|
name
|
900
|
(pp_comma_list pp_c_decl_input_var)
|
901
|
inputs
|
902
|
(pp_comma_list
|
903
|
~pp_prologue:pp_print_comma
|
904
|
~pp_eol:pp_print_comma
|
905
|
~pp_epilogue:pp_print_cut
|
906
|
pp_c_decl_output_var)
|
907
|
outputs
|
908
|
(pp_machine_memtype_name ~ghost:false)
|
909
|
name
|
910
|
self
|
911
|
(Mod.pp_ghost_parameters ~cut:true)
|
912
|
[ mem, pp_mem_ghost name ]
|
913
|
|
914
|
let pp_init_prototype self fmt (name, static) =
|
915
|
fprintf
|
916
|
fmt
|
917
|
"void %a (%a%a *%s)"
|
918
|
pp_machine_init_name
|
919
|
name
|
920
|
(pp_comma_list ~pp_eol:pp_print_comma pp_c_decl_input_var)
|
921
|
static
|
922
|
(pp_machine_memtype_name ~ghost:false)
|
923
|
name
|
924
|
self
|
925
|
|
926
|
let pp_clear_prototype self fmt (name, static) =
|
927
|
fprintf
|
928
|
fmt
|
929
|
"void %a (%a%a *%s)"
|
930
|
pp_machine_clear_name
|
931
|
name
|
932
|
(pp_comma_list ~pp_eol:pp_print_comma pp_c_decl_input_var)
|
933
|
static
|
934
|
(pp_machine_memtype_name ~ghost:false)
|
935
|
name
|
936
|
self
|
937
|
|
938
|
let pp_stateless_prototype fmt (name, inputs, outputs) =
|
939
|
fprintf
|
940
|
fmt
|
941
|
"void %a (@[<v>%a%a@])"
|
942
|
pp_machine_step_name
|
943
|
name
|
944
|
(pp_comma_list pp_c_decl_input_var)
|
945
|
inputs
|
946
|
(pp_comma_list ~pp_prologue:pp_print_comma pp_c_decl_output_var)
|
947
|
outputs
|
948
|
end
|
949
|
|
950
|
let pp_import_prototype fmt dep = fprintf fmt "#include \"%s.h\"" dep.name
|
951
|
|
952
|
let pp_import_alloc_prototype fmt dep =
|
953
|
if dep.is_stateful then fprintf fmt "#include \"%s_alloc.h\"" dep.name
|
954
|
|
955
|
let pp_c_var m self pp_var fmt var =
|
956
|
pp_c_val m self pp_var fmt (Machine_code_common.mk_val (Var var) var.var_type)
|
957
|
|
958
|
let pp_array_suffix =
|
959
|
pp_print_list ~pp_sep:pp_print_nothing (fun fmt v -> fprintf fmt "[%s]" v)
|
960
|
|
961
|
let mpfr_vars vars =
|
962
|
if !Options.mpfr then
|
963
|
List.filter
|
964
|
(fun v -> Types.(is_real_type (array_base_type v.var_type)))
|
965
|
vars
|
966
|
else []
|
967
|
|
968
|
let mpfr_consts consts =
|
969
|
if !Options.mpfr then
|
970
|
List.filter
|
971
|
(fun c -> Types.(is_real_type (array_base_type c.const_type)))
|
972
|
consts
|
973
|
else []
|
974
|
|
975
|
(* type directed initialization: useless wrt the lustre compilation model,
|
976
|
except for MPFR injection, where values are dynamically allocated *)
|
977
|
let pp_initialize m self pp_var fmt var =
|
978
|
let rec aux indices fmt typ =
|
979
|
if Types.is_array_type typ then
|
980
|
let dim = Types.array_type_dimension typ in
|
981
|
let idx = mk_loop_var m () in
|
982
|
fprintf
|
983
|
fmt
|
984
|
"@[<v 2>{@,int %s;@,for(%s=0;%s<%a;%s++)@,%a @]@,}"
|
985
|
idx
|
986
|
idx
|
987
|
idx
|
988
|
pp_c_dimension
|
989
|
dim
|
990
|
idx
|
991
|
(aux (idx :: indices))
|
992
|
(Types.array_element_type typ)
|
993
|
else
|
994
|
let indices = List.rev indices in
|
995
|
let pp_var_suffix fmt var =
|
996
|
fprintf fmt "%a%a" (pp_c_var m self pp_var) var pp_array_suffix indices
|
997
|
in
|
998
|
Mpfr.pp_inject_init pp_var_suffix fmt var
|
999
|
in
|
1000
|
reset_loop_counter ();
|
1001
|
aux [] fmt var.var_type
|
1002
|
|
1003
|
(* type directed clear: useless wrt the lustre compilation model, except for
|
1004
|
MPFR injection, where values are dynamically allocated *)
|
1005
|
let pp_clear m self pp_var fmt var =
|
1006
|
let rec aux indices fmt typ =
|
1007
|
if Types.is_array_type typ then
|
1008
|
let dim = Types.array_type_dimension typ in
|
1009
|
let idx = mk_loop_var m () in
|
1010
|
fprintf
|
1011
|
fmt
|
1012
|
"@[<v 2>{@,int %s;@,for(%s=0;%s<%a;%s++)@,%a @]@,}"
|
1013
|
idx
|
1014
|
idx
|
1015
|
idx
|
1016
|
pp_c_dimension
|
1017
|
dim
|
1018
|
idx
|
1019
|
(aux (idx :: indices))
|
1020
|
(Types.array_element_type typ)
|
1021
|
else
|
1022
|
let indices = List.rev indices in
|
1023
|
let pp_var_suffix fmt var =
|
1024
|
fprintf fmt "%a%a" (pp_c_var m self pp_var) var pp_array_suffix indices
|
1025
|
in
|
1026
|
Mpfr.pp_inject_clear pp_var_suffix fmt var
|
1027
|
in
|
1028
|
reset_loop_counter ();
|
1029
|
aux [] fmt var.var_type
|
1030
|
|
1031
|
(*** Common functions for main ***)
|
1032
|
|
1033
|
let pp_file file_suffix fmt (typ, arg) =
|
1034
|
fprintf
|
1035
|
fmt
|
1036
|
"@[<v 2>if (traces) {@,fprintf(f_%s, \"%%%s\\n\", %s);@,fflush(f_%s);@]@,}"
|
1037
|
file_suffix
|
1038
|
typ
|
1039
|
arg
|
1040
|
file_suffix
|
1041
|
|
1042
|
let pp_put_var fmt file_suffix name var_type var_id =
|
1043
|
let opt = !Options.c_main_options in
|
1044
|
let pp_file fmt =
|
1045
|
if opt then fprintf fmt "@,%a" (pp_file ("out" ^ file_suffix))
|
1046
|
else pp_print_nothing fmt
|
1047
|
in
|
1048
|
let unclocked_t = Types.unclock_type var_type in
|
1049
|
fprintf
|
1050
|
fmt
|
1051
|
"@[<v>%a@]"
|
1052
|
(fun fmt () ->
|
1053
|
if Types.is_int_type unclocked_t then
|
1054
|
fprintf fmt "_put_int(\"%s\", %s);%a" name var_id pp_file ("d", var_id)
|
1055
|
else if Types.is_bool_type unclocked_t then
|
1056
|
fprintf fmt "_put_bool(\"%s\", %s);%a" name var_id pp_file ("i", var_id)
|
1057
|
else if Types.is_real_type unclocked_t then
|
1058
|
if !Options.mpfr then
|
1059
|
fprintf
|
1060
|
fmt
|
1061
|
"_put_double(\"%s\", mpfr_get_d(%s, %s), %i);%a"
|
1062
|
name
|
1063
|
var_id
|
1064
|
(Mpfr.mpfr_rnd ())
|
1065
|
!Options.print_prec_double
|
1066
|
pp_file
|
1067
|
( ".*f",
|
1068
|
string_of_int !Options.print_prec_double
|
1069
|
^ ", mpfr_get_d(" ^ var_id ^ ", MPFR_RNDN)" )
|
1070
|
else
|
1071
|
fprintf
|
1072
|
fmt
|
1073
|
"_put_double(\"%s\", %s, %i);%a"
|
1074
|
name
|
1075
|
var_id
|
1076
|
!Options.print_prec_double
|
1077
|
pp_file
|
1078
|
(".*f", string_of_int !Options.print_prec_double ^ ", " ^ var_id)
|
1079
|
else (
|
1080
|
eprintf
|
1081
|
"Impossible to print the _put_xx for type %a@.@?"
|
1082
|
Types.pp
|
1083
|
var_type;
|
1084
|
assert false))
|
1085
|
()
|
1086
|
|
1087
|
let pp_file_decl fmt inout idx =
|
1088
|
let idx = idx + 1 in
|
1089
|
(* we start from 1: in1, in2, ... *)
|
1090
|
fprintf fmt "FILE *f_%s%i;" inout idx
|
1091
|
|
1092
|
let pp_file_open fmt inout idx =
|
1093
|
let idx = idx + 1 in
|
1094
|
(* we start from 1: in1, in2, ... *)
|
1095
|
fprintf
|
1096
|
fmt
|
1097
|
"@[<v>const char* cst_char_suffix_%s%i = \"_simu.%s%i\";@,\
|
1098
|
size_t l%s%i = strlen(dir) + strlen(prefix) + \
|
1099
|
strlen(cst_char_suffix_%s%i);@,\
|
1100
|
char* f_%s%i_name = malloc((l%s%i+2) * sizeof(char));@,\
|
1101
|
strcpy (f_%s%i_name, dir);@,\
|
1102
|
strcat(f_%s%i_name, \"/\");@,\
|
1103
|
strcat(f_%s%i_name, prefix);@,\
|
1104
|
strcat(f_%s%i_name, cst_char_suffix_%s%i);@,\
|
1105
|
f_%s%i = fopen(f_%s%i_name, \"w\");@,\
|
1106
|
free(f_%s%i_name);@]"
|
1107
|
inout
|
1108
|
idx
|
1109
|
inout
|
1110
|
idx
|
1111
|
inout
|
1112
|
idx
|
1113
|
inout
|
1114
|
idx
|
1115
|
inout
|
1116
|
idx
|
1117
|
inout
|
1118
|
idx
|
1119
|
inout
|
1120
|
idx
|
1121
|
inout
|
1122
|
idx
|
1123
|
inout
|
1124
|
idx
|
1125
|
inout
|
1126
|
idx
|
1127
|
inout
|
1128
|
idx
|
1129
|
inout
|
1130
|
idx
|
1131
|
inout
|
1132
|
idx
|
1133
|
inout
|
1134
|
idx;
|
1135
|
"f_" ^ inout ^ string_of_int idx
|
1136
|
|
1137
|
let pp_basic_assign pp_var fmt typ var_name value =
|
1138
|
if Types.is_real_type typ && !Options.mpfr then
|
1139
|
Mpfr.pp_inject_assign pp_var fmt (var_name, value)
|
1140
|
else fprintf fmt "%a = %a;" pp_var var_name pp_var value
|
1141
|
|
1142
|
(* type_directed assignment: array vs. statically sized type - [var_type]: type
|
1143
|
of variable to be assigned - [var_name]: name of variable to be assigned -
|
1144
|
[value]: assigned value - [pp_var]: printer for variables *)
|
1145
|
let pp_assign m self pp_var fmt (var, value) =
|
1146
|
let depth = expansion_depth value in
|
1147
|
let var_type = var.var_type in
|
1148
|
let var = mk_val (Var var) var_type in
|
1149
|
(*eprintf "pp_assign %a %a %a %d@." Types.pp var_type pp_val var_name pp_val
|
1150
|
value depth;*)
|
1151
|
let loop_vars = mk_loop_variables m var_type depth in
|
1152
|
let reordered_loop_vars = reorder_loop_variables loop_vars in
|
1153
|
let rec aux typ fmt vars =
|
1154
|
match vars with
|
1155
|
| [] ->
|
1156
|
pp_basic_assign
|
1157
|
(pp_value_suffix m self var_type loop_vars pp_var)
|
1158
|
fmt
|
1159
|
typ
|
1160
|
var
|
1161
|
value
|
1162
|
| (d, LVar i) :: q ->
|
1163
|
let typ' = Types.array_element_type typ in
|
1164
|
(*eprintf "pp_aux %a %s@." Dimension.pp_dimension d i;*)
|
1165
|
fprintf
|
1166
|
fmt
|
1167
|
"@[<v 2>{@,int %s;@,for(%s=0;%s<%a;%s++)@,%a @]@,}"
|
1168
|
i
|
1169
|
i
|
1170
|
i
|
1171
|
pp_c_dimension
|
1172
|
d
|
1173
|
i
|
1174
|
(aux typ')
|
1175
|
q
|
1176
|
| (d, LInt r) :: q ->
|
1177
|
(*eprintf "pp_aux %a %d@." Dimension.pp_dimension d (!r);*)
|
1178
|
let typ' = Types.array_element_type typ in
|
1179
|
let szl = Utils.enumerate (Dimension.size_const d) in
|
1180
|
fprintf
|
1181
|
fmt
|
1182
|
"@[<v 2>{@,%a@]@,}"
|
1183
|
(pp_print_list (fun fmt i ->
|
1184
|
r := i;
|
1185
|
aux typ' fmt q))
|
1186
|
szl
|
1187
|
| _ ->
|
1188
|
assert false
|
1189
|
in
|
1190
|
reset_loop_counter ();
|
1191
|
(*reset_addr_counter ();*)
|
1192
|
aux var_type fmt reordered_loop_vars
|
1193
|
(*eprintf "end pp_assign@.";*)
|
1194
|
|
1195
|
let rec pp_static_val pp_var fmt v =
|
1196
|
match v.value_desc with
|
1197
|
| Cst c ->
|
1198
|
pp_c_const fmt c
|
1199
|
| Var v ->
|
1200
|
pp_var fmt v
|
1201
|
| Fun (n, vl) ->
|
1202
|
pp_basic_lib_fun
|
1203
|
(Types.is_int_type v.value_type)
|
1204
|
n
|
1205
|
(pp_static_val pp_var)
|
1206
|
fmt
|
1207
|
vl
|
1208
|
| _ ->
|
1209
|
(* TODO: raise proper error *)
|
1210
|
eprintf "Internal error: C_backend_common.pp_static_val";
|
1211
|
assert false
|
1212
|
|
1213
|
let concat x y =
|
1214
|
x ^ "##" ^ y
|
1215
|
|
1216
|
let pp_constant_decl (m, attr, inst) pp_var fmt v =
|
1217
|
fprintf
|
1218
|
fmt
|
1219
|
"%s %a = %a"
|
1220
|
attr
|
1221
|
(pp_c_type (concat inst v.var_id))
|
1222
|
v.var_type
|
1223
|
(pp_static_val pp_var)
|
1224
|
(get_const_assign m v)
|
1225
|
|
1226
|
let pp_var inst const_locals fmt v =
|
1227
|
pp_print_string fmt (if List.mem v const_locals then concat inst v.var_id else v.var_id)
|
1228
|
|
1229
|
let pp_static_constant_decl ((_, _, inst) as macro) fmt const_locals =
|
1230
|
pp_print_list
|
1231
|
~pp_open_box:pp_open_vbox0
|
1232
|
~pp_sep:(pp_print_endcut ";\\")
|
1233
|
~pp_eol:(pp_print_endcut ";\\")
|
1234
|
(pp_constant_decl macro (pp_var inst const_locals))
|
1235
|
fmt
|
1236
|
const_locals
|
1237
|
|
1238
|
let pp_static_declare_instance ?(ghost = false) (m, attr, inst) const_locals fmt
|
1239
|
(i, (n, static)) =
|
1240
|
let values = List.map (value_of_dimension m) static in
|
1241
|
fprintf
|
1242
|
fmt
|
1243
|
"@[<h>%a(%s, %a%s)@]"
|
1244
|
(pp_machine_static_declare_name ~ghost)
|
1245
|
(node_name n)
|
1246
|
attr
|
1247
|
(pp_print_list
|
1248
|
~pp_open_box:pp_open_hbox
|
1249
|
~pp_sep:pp_print_comma
|
1250
|
~pp_eol:pp_print_comma
|
1251
|
(pp_static_val (pp_var inst const_locals)))
|
1252
|
values
|
1253
|
i
|
1254
|
|
1255
|
let pp_static_declare_macro ?(ghost = false) fmt ((m, attr, inst) as macro) =
|
1256
|
let const_locals =
|
1257
|
List.filter (fun vdecl -> vdecl.var_dec_const) m.mstep.step_locals
|
1258
|
in
|
1259
|
let array_mem =
|
1260
|
List.filter (fun v -> Types.is_array_type v.var_type) m.mmemory
|
1261
|
in
|
1262
|
fprintf
|
1263
|
fmt
|
1264
|
"@[<v 2>@[<h>#define %a(%s, %a%s)\\@]@,\
|
1265
|
@[<h>%a%s %a %s;\\@]@,\
|
1266
|
%a%a;@]"
|
1267
|
(pp_machine_static_declare_name ~ghost)
|
1268
|
m.mname.node_id
|
1269
|
attr
|
1270
|
(pp_print_list
|
1271
|
~pp_open_box:pp_open_hbox
|
1272
|
~pp_sep:pp_print_comma
|
1273
|
~pp_eol:pp_print_comma
|
1274
|
(pp_c_var_read m))
|
1275
|
m.mstatic
|
1276
|
inst
|
1277
|
(* constants *)
|
1278
|
(pp_static_constant_decl macro)
|
1279
|
const_locals
|
1280
|
attr
|
1281
|
(pp_machine_memtype_name ~ghost)
|
1282
|
m.mname.node_id
|
1283
|
inst
|
1284
|
(pp_print_list
|
1285
|
~pp_open_box:pp_open_vbox0
|
1286
|
~pp_sep:(pp_print_endcut ";\\")
|
1287
|
~pp_eol:(pp_print_endcut ";\\")
|
1288
|
(pp_c_decl_local_var m))
|
1289
|
array_mem
|
1290
|
(pp_print_list
|
1291
|
~pp_open_box:pp_open_vbox0
|
1292
|
~pp_sep:(pp_print_endcut ";\\")
|
1293
|
(fun fmt (i', m') ->
|
1294
|
let path = concat inst ("_" ^ i') in
|
1295
|
pp_static_declare_instance ~ghost macro const_locals fmt (path, m')))
|
1296
|
m.minstances
|
1297
|
|
1298
|
let pp_static_link_instance ?(ghost = false) fmt (i, (m, _)) =
|
1299
|
fprintf fmt "%a(%s)" (pp_machine_static_link_name ~ghost) (node_name m) i
|
1300
|
|
1301
|
(* Allocation of a node struct: - if node memory is an array/matrix/etc, we cast
|
1302
|
it to a pointer (see pp_registers_struct) *)
|
1303
|
let pp_static_link_macro ?(ghost = false) fmt (m, _, inst) =
|
1304
|
let array_mem =
|
1305
|
List.filter (fun v -> Types.is_array_type v.var_type) m.mmemory
|
1306
|
in
|
1307
|
fprintf
|
1308
|
fmt
|
1309
|
"@[<v>@[<v 2>#define %a(%s) do {\\@,\
|
1310
|
@[<h>%a%a;\\@]@]@,} while (0)@]"
|
1311
|
(pp_machine_static_link_name ~ghost)
|
1312
|
m.mname.node_id
|
1313
|
inst
|
1314
|
(pp_print_list
|
1315
|
~pp_open_box:pp_open_vbox0
|
1316
|
~pp_sep:(pp_print_endcut ";\\")
|
1317
|
~pp_eol:(pp_print_endcut ";\\")
|
1318
|
(fun fmt v ->
|
1319
|
fprintf
|
1320
|
fmt
|
1321
|
"%s._reg.%s = (%a*) &%s"
|
1322
|
inst
|
1323
|
v.var_id
|
1324
|
(fun fmt v -> pp_c_type "" fmt (Types.array_base_type v.var_type))
|
1325
|
v
|
1326
|
v.var_id))
|
1327
|
array_mem
|
1328
|
(pp_print_list
|
1329
|
~pp_open_box:pp_open_vbox0
|
1330
|
~pp_sep:(pp_print_endcut ";\\")
|
1331
|
(fun fmt (i', m') ->
|
1332
|
let path = concat inst ("_" ^ i') in
|
1333
|
fprintf
|
1334
|
fmt
|
1335
|
"%a;\\@,%s.%s = %s%s"
|
1336
|
(pp_static_link_instance ~ghost)
|
1337
|
(path, m')
|
1338
|
inst
|
1339
|
i'
|
1340
|
(if ghost then "" else "&")
|
1341
|
path))
|
1342
|
m.minstances
|
1343
|
|
1344
|
let pp_static_alloc_macro ?(ghost = false) fmt (m, attr, inst) =
|
1345
|
fprintf
|
1346
|
fmt
|
1347
|
"@[<v>@[<v 2>@[<h>#define %a(%s, %a%s)\\@]@,\
|
1348
|
@[<h>%a(%s, %a%s);\\@]@,\
|
1349
|
@[<h>%a(%s);@]@]@]"
|
1350
|
(pp_machine_static_alloc_name ~ghost)
|
1351
|
m.mname.node_id
|
1352
|
attr
|
1353
|
(pp_print_list
|
1354
|
~pp_open_box:pp_open_hbox
|
1355
|
~pp_sep:pp_print_comma
|
1356
|
~pp_eol:pp_print_comma
|
1357
|
(pp_c_var_read m))
|
1358
|
m.mstatic
|
1359
|
inst
|
1360
|
(pp_machine_static_declare_name ~ghost)
|
1361
|
m.mname.node_id
|
1362
|
attr
|
1363
|
(pp_print_list
|
1364
|
~pp_open_box:pp_open_hbox
|
1365
|
~pp_sep:pp_print_comma
|
1366
|
~pp_eol:pp_print_comma
|
1367
|
(pp_c_var_read m))
|
1368
|
m.mstatic
|
1369
|
inst
|
1370
|
(pp_machine_static_link_name ~ghost)
|
1371
|
m.mname.node_id
|
1372
|
inst
|
1373
|
|
1374
|
(* Local Variables: *)
|
1375
|
(* compile-command:"make -C ../../.." *)
|
1376
|
(* End: *)
|