Project

General

Profile

Download (14 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
13
open Lustre_types
14
open Machine_code_types
15
open Machine_code_common
16
open Format
17
open C_backend_common
18
module Mpfr = Lustrec_mpfr
19

    
20
module type MODIFIERS_MAINSRC = sig
21
  val pp_declare_ghost_state : formatter -> ident -> unit
22

    
23
  val pp_ghost_state_parameter : formatter -> unit -> unit
24

    
25
  val pp_main_spec : formatter -> unit
26

    
27
  val pp_main_loop_invariants :
28
    ident -> machine_t list -> formatter -> machine_t -> unit
29
end
30

    
31
module EmptyMod = struct
32
  let pp_declare_ghost_state _ _ = ()
33

    
34
  let pp_ghost_state_parameter _ _ = ()
35

    
36
  let pp_main_spec _ = ()
37

    
38
  let pp_main_loop_invariants _ _ _ _ = ()
39
end
40

    
41
module Main (Mod : MODIFIERS_MAINSRC) = struct
42
  (********************************************************************************************)
43
  (* Main related functions *)
44
  (********************************************************************************************)
45

    
46
  let pp_c_main_var_input fmt id = fprintf fmt "%s" id.var_id
47

    
48
  let pp_c_main_var_output fmt id =
49
    if Types.is_address_type id.var_type then fprintf fmt "%s" id.var_id
50
    else fprintf fmt "&%s" id.var_id
51

    
52
  let pp_put_output fmt id o' o =
53
    let suff = string_of_int (id + 1) in
54
    pp_put_var fmt suff o'.var_id o.var_type o.var_id
55

    
56
  let pp_main_inout_declaration fmt m =
57
    let opt = !Options.c_main_options in
58
    fprintf
59
      fmt
60
      "/* Declaration of inputs/outputs variables */@,%a%a%a"
61
      (pp_print_list_i ~pp_open_box:pp_open_vbox0 (fun fmt idx v ->
62
           fprintf
63
             fmt
64
             "%a; %a"
65
             (pp_c_type v.var_id)
66
             v.var_type
67
             (if opt then fun fmt () -> pp_file_decl fmt "in" idx
68
             else pp_print_nothing)
69
             ()))
70
      m.mstep.step_inputs
71
      (pp_print_list_i
72
         ~pp_open_box:pp_open_vbox0
73
         ~pp_prologue:pp_print_cut
74
         (fun fmt idx v ->
75
           fprintf
76
             fmt
77
             "%a; %a"
78
             (pp_c_type v.var_id)
79
             v.var_type
80
             (if opt then fun fmt () -> pp_file_decl fmt "out" idx
81
             else pp_print_nothing)
82
             ()))
83
      m.mstep.step_outputs
84
      (if opt then fun fmt () ->
85
       fprintf
86
         fmt
87
         "@,@[<v 2>if (traces) {@,%a%a@]@,}"
88
         (pp_print_list_i ~pp_epilogue:pp_print_cut (fun fmt idx _ ->
89
              ignore (pp_file_open fmt "in" idx)))
90
         m.mstep.step_inputs
91
         (pp_print_list_i (fun fmt idx _ -> ignore (pp_file_open fmt "out" idx)))
92
         m.mstep.step_outputs
93
      else pp_print_nothing)
94
      ()
95

    
96
  let pp_main_memory_allocation mname main_mem fmt m =
97
    if not (fst (get_stateless_status m)) then
98
      fprintf
99
        fmt
100
        "@[<v>/* Main memory allocation */@,\
101
         %a@,\
102
         %a@,\
103
         /* Initialize the main memory */@,\
104
         %a(%s)%a;@]"
105
        (fun fmt () ->
106
          if !Options.static_mem && !Options.main_node <> "" then
107
            fprintf
108
              fmt
109
              "%a(,main_mem);"
110
              (fun x -> pp_machine_static_alloc_name x)
111
              mname
112
          else
113
            fprintf
114
              fmt
115
              "%a *main_mem = %a();"
116
              (pp_machine_memtype_name ~ghost:false)
117
              mname
118
              pp_machine_alloc_name
119
              mname)
120
        ()
121
        Mod.pp_declare_ghost_state
122
        mname
123
        pp_machine_set_reset_name
124
        mname
125
        main_mem
126
        Mod.pp_ghost_state_parameter
127
        ()
128

    
129
  let pp_global_initialize fmt basename =
130
    let mNAME = file_to_module_name basename in
131
    fprintf
132
      fmt
133
      "/* Initialize global constants */@,%a();"
134
      pp_global_init_name
135
      mNAME
136

    
137
  let pp_global_clear fmt basename =
138
    let mNAME = file_to_module_name basename in
139
    fprintf fmt "/* Clear global constants */@,%a();" pp_global_clear_name mNAME
140

    
141
  let pp_main_initialize mname main_mem fmt m =
142
    let inputs = mpfr_vars m.mstep.step_inputs in
143
    let outputs = mpfr_vars m.mstep.step_outputs in
144
    if not (fst (get_stateless_status m)) then
145
      fprintf
146
        fmt
147
        "/* Initialize inputs, outputs and memories */@,%a%a%a(%s);"
148
        (pp_print_list
149
           ~pp_open_box:pp_open_vbox0
150
           ~pp_eol:pp_print_cut
151
           (pp_initialize m main_mem (pp_c_var_read m)))
152
        inputs
153
        (pp_print_list
154
           ~pp_open_box:pp_open_vbox0
155
           ~pp_eol:pp_print_cut
156
           (pp_initialize m main_mem (pp_c_var_read m)))
157
        outputs
158
        pp_machine_init_name
159
        mname
160
        main_mem
161
    else
162
      fprintf
163
        fmt
164
        "/* Initialize inputs and outputs */@,%a%a@ "
165
        (pp_print_list
166
           ~pp_open_box:pp_open_vbox0
167
           ~pp_eol:pp_print_cut
168
           (pp_initialize m main_mem (pp_c_var_read m)))
169
        inputs
170
        (pp_print_list
171
           ~pp_open_box:pp_open_vbox0
172
           (pp_initialize m main_mem (pp_c_var_read m)))
173
        outputs
174

    
175
  let pp_main_clear mname main_mem fmt m =
176
    let inputs = mpfr_vars m.mstep.step_inputs in
177
    let outputs = mpfr_vars m.mstep.step_outputs in
178
    if not (fst (get_stateless_status m)) then
179
      fprintf
180
        fmt
181
        "@[<v>/* Clear inputs, outputs and memories */@,%a%a%a(%s);@]"
182
        (pp_print_list
183
           ~pp_open_box:pp_open_vbox0
184
           ~pp_eol:pp_print_cut
185
           (pp_clear m main_mem (pp_c_var_read m)))
186
        inputs
187
        (pp_print_list
188
           ~pp_open_box:pp_open_vbox0
189
           ~pp_eol:pp_print_cut
190
           (pp_clear m main_mem (pp_c_var_read m)))
191
        outputs
192
        pp_machine_clear_name
193
        mname
194
        main_mem
195
    else
196
      fprintf
197
        fmt
198
        "@[<v>/* Clear inputs and outputs */@,%a%a@]"
199
        (pp_print_list
200
           ~pp_open_box:pp_open_vbox0
201
           ~pp_eol:pp_print_cut
202
           (pp_clear m main_mem (pp_c_var_read m)))
203
        inputs
204
        (pp_print_list
205
           ~pp_open_box:pp_open_vbox0
206
           (pp_clear m main_mem (pp_c_var_read m)))
207
        outputs
208

    
209
  let pp_get_input fmt id v' v =
210
    let opt = !Options.c_main_options in
211
    let pp_file fmt =
212
      if opt then fprintf fmt "@,%a" (pp_file ("in" ^ string_of_int (id + 1)))
213
      else pp_print_nothing fmt
214
    in
215
    let unclocked_t = Types.unclock_type v.var_type in
216
    fprintf
217
      fmt
218
      "@[<v>%a@]"
219
      (fun fmt () ->
220
        if Types.is_int_type unclocked_t then
221
          fprintf
222
            fmt
223
            "%s = _get_int(\"%s\");%a"
224
            v.var_id
225
            v'.var_id
226
            pp_file
227
            ("d", v.var_id)
228
        else if Types.is_bool_type unclocked_t then
229
          fprintf
230
            fmt
231
            "%s = _get_bool(\"%s\");%a"
232
            v.var_id
233
            v'.var_id
234
            pp_file
235
            ("i", v.var_id)
236
        else if Types.is_real_type unclocked_t then
237
          if !Options.mpfr then
238
            fprintf
239
              fmt
240
              "double %s_tmp = _get_double(\"%s\");%a@,\
241
               mpfr_set_d(%s, %s_tmp, %i);"
242
              v.var_id
243
              v'.var_id
244
              pp_file
245
              ("f", v.var_id ^ "_tmp")
246
              v.var_id
247
              v.var_id
248
              (Mpfr.mpfr_prec ())
249
          else
250
            fprintf
251
              fmt
252
              "%s = _get_double(\"%s\");%a"
253
              v.var_id
254
              v'.var_id
255
              pp_file
256
              ("f", v.var_id)
257
        else (
258
          Global.main_node := !Options.main_node;
259
          eprintf
260
            "Code generation error: %a%a@."
261
            Error.pp
262
            Error.Main_wrong_kind
263
            Location.pp
264
            v'.var_loc;
265
          raise (Error.Error (v'.var_loc, Error.Main_wrong_kind))))
266
      ()
267

    
268
  let pp_main_call mname self fmt m inputs outputs =
269
    let pp_inputs =
270
      pp_print_list
271
        ~pp_sep:pp_print_comma
272
        ~pp_eol:pp_print_comma
273
        (pp_c_val m self pp_c_main_var_input)
274
    in
275
    let pp_outputs ?pp_eol fmt x =
276
      pp_print_list ~pp_sep:pp_print_comma ?pp_eol pp_c_main_var_output fmt x
277
    in
278
    if fst (get_stateless_status m) then
279
      fprintf
280
        fmt
281
        "%a(%a%a);"
282
        pp_machine_step_name
283
        mname
284
        pp_inputs
285
        inputs
286
        (pp_outputs ~pp_eol:pp_print_nothing)
287
        outputs
288
    else
289
      fprintf
290
        fmt
291
        "%a(%a%a%s)%a;"
292
        pp_machine_step_name
293
        mname
294
        pp_inputs
295
        inputs
296
        (pp_outputs ~pp_eol:pp_print_comma)
297
        outputs
298
        self
299
        Mod.pp_ghost_state_parameter
300
        ()
301

    
302
  let pp_main_loop mname main_mem machines fmt m =
303
    let opt = !Options.c_main_options in
304
    let input_values =
305
      List.map (fun v -> mk_val (Var v) v.var_type) m.mstep.step_inputs
306
    in
307
    fprintf
308
      fmt
309
      "ISATTY = isatty(0);@,\
310
       @,\
311
       /* Infinite loop */@,\
312
       %a@[<v 2>while(1){@,\
313
       fflush(stdout);@,\
314
       %a%a%a%a@]@,\
315
       }"
316
      (Mod.pp_main_loop_invariants main_mem machines)
317
      m
318
      (if opt then fun fmt () ->
319
       fprintf
320
         fmt
321
         "@[<v 2>if (traces) {@,%a%a@]@,}@,"
322
         (pp_print_list_i
323
            ~pp_open_box:pp_open_vbox0
324
            ~pp_epilogue:pp_print_cut
325
            (fun fmt idx _ -> fprintf fmt "fflush(f_in%i);" (idx + 1)))
326
         m.mstep.step_inputs
327
         (pp_print_list_i ~pp_open_box:pp_open_vbox0 (fun fmt idx _ ->
328
              fprintf fmt "fflush(f_out%i);" (idx + 1)))
329
         m.mstep.step_outputs
330
      else pp_print_nothing)
331
      ()
332
      (pp_print_list_i2
333
         ~pp_open_box:pp_open_vbox0
334
         ~pp_epilogue:pp_print_cut
335
         pp_get_input)
336
      (m.mname.node_inputs, m.mstep.step_inputs)
337
      (fun fmt () ->
338
        pp_main_call mname main_mem fmt m input_values m.mstep.step_outputs)
339
      ()
340
      (pp_print_list_i2
341
         ~pp_open_box:pp_open_vbox0
342
         ~pp_prologue:pp_print_cut
343
         pp_put_output)
344
      (m.mname.node_outputs, m.mstep.step_outputs)
345

    
346
  let pp_usage fmt () =
347
    fprintf
348
      fmt
349
      "@[<v 2>void usage(char *argv[]) {@,\
350
       printf(\"Usage: %%s\\n\", argv[0]);@,\
351
       printf(\" -t: produce trace files for input/output flows\\n\");@,\
352
       printf(\" -d<dir>: directory containing traces (default: \
353
       _traces)\\n\");@,\
354
       printf(\" -p<prefix>: prefix_simu.scope<id> (default: file_node)\\n\");@,\
355
       exit (8);@]@,\
356
       }@,\
357
       @,"
358

    
359
  let pp_options fmt name =
360
    fprintf
361
      fmt
362
      "@[<v>int traces = 0;@,\
363
       char* prefix = \"%s\";@,\
364
       char* dir = \".\";@,\
365
       @[<v 2>while ((argc > 1) && (argv[1][0] == '-')) {@,\
366
       @[<v 2>switch (argv[1][1]) {@,\
367
       @[<v 2>case 't':@,\
368
       traces = 1;@,\
369
       break;@,\
370
       @]@,\
371
       @[<v 2>case 'd':@,\
372
       dir = &argv[1][2];@,\
373
       break;@,\
374
       @]@,\
375
       @[<v 2>case 'p':@,\
376
       prefix = &argv[1][2];@,\
377
       break;@,\
378
       @]@,\
379
       @[<v 2>default:@,\
380
       printf(\"Wrong Argument: %%s\\n\", argv[1]);@,\
381
       usage(argv);@]@]@,\
382
       }@,\
383
       ++argv;@,\
384
       --argc;@]@,\
385
       }@]@,\
386
       @,"
387
      name
388

    
389
  let pp_main_code machines fmt (basename, m) =
390
    let opt = !Options.c_main_options in
391
    let mname = m.mname.node_id in
392
    (* TODO: find a proper way to shorthen long names. This causes segfault in
393
       the binary when trying to fprintf in them *)
394
    let mname =
395
      if String.length mname > 50 then string_of_int (Hashtbl.hash mname)
396
      else mname
397
    in
398
    let main_mem =
399
      if !Options.static_mem && !Options.main_node <> "" then "&main_mem"
400
      else "main_mem"
401
    in
402

    
403
    fprintf
404
      fmt
405
      "@[<v>%a%t@[<v 2>int main (%a) {@,\
406
       %a%a@,\
407
       %a@,\
408
       %a@,\
409
       %a@,\
410
       %a@,\
411
       %a@,\
412
       %areturn 1;@]@,\
413
       }@]@."
414
      (if opt then pp_usage else pp_print_nothing)
415
      ()
416
      Mod.pp_main_spec
417
      (if opt then pp_print_string else pp_print_nothing)
418
      "int argc, char *argv[]"
419
      (if opt then pp_options else pp_print_nothing)
420
      (basename ^ "_" ^ mname)
421
      pp_main_inout_declaration
422
      m
423
      (Plugins.c_backend_main_loop_body_prefix basename mname)
424
      ()
425
      (pp_main_memory_allocation mname main_mem)
426
      m
427
      (fun fmt () ->
428
        if !Options.mpfr then
429
          fprintf
430
            fmt
431
            "@[<v>%a@,%a@]@,"
432
            pp_global_initialize
433
            basename
434
            (pp_main_initialize mname main_mem)
435
            m)
436
      ()
437
      (pp_main_loop mname main_mem machines)
438
      m
439
      Plugins.c_backend_main_loop_body_suffix
440
      ()
441
      (fun fmt () ->
442
        if !Options.mpfr then
443
          fprintf
444
            fmt
445
            "@[<v>%a@,%a@]@,"
446
            (pp_main_clear mname main_mem)
447
            m
448
            pp_global_clear
449
            basename)
450
      ()
451

    
452
  let pp_main_header fmt () =
453
    fprintf
454
      fmt
455
      "@[<v>#include <stdio.h>@,#include <unistd.h>@,%a@]"
456
      (fun fmt () ->
457
        fprintf
458
          fmt
459
          (if !Options.cpp then "#include \"%s/io_frontend.hpp\""
460
          else "#include <string.h>@,#include \"%s/io_frontend.h\"")
461
          (Options_management.core_dependency "io_frontend"))
462
      ()
463

    
464
  let pp_main_c main_fmt main_machine basename _prog machines _dependencies =
465
    fprintf
466
      main_fmt
467
      "@[<v>%a@,\
468
       #include <stdlib.h>@,\
469
       #include <assert.h>@,\
470
       %a@,\
471
       @,\
472
       %a@,\
473
       %a\n\
474
      \       @]@."
475
      pp_main_header
476
      ()
477
      pp_import_alloc_prototype
478
      {
479
        local = true;
480
        name = basename;
481
        content = [];
482
        is_stateful = true (* assuming it is stateful*);
483
      }
484
      (* Print the svn version number and the supported C standard (C90 or
485
         C99) *)
486
      pp_print_version
487
      ()
488
      (pp_main_code machines)
489
      (basename, main_machine)
490
end
491

    
492
(* Local Variables: *)
493
(* compile-command:"make -C ../../.." *)
494
(* End: *)
(9-9/18)