Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
(* Time-stamp: <modified the 28/07/2022 (at 10:49) by Erwan Jahier> *)
(* Author: Antony Zahran *)
open Printf
open Types
let variables = ref [];;
let channels = ref [];;
let main = {name = ""; ctx_type = ""; ctx_new = ""; var_in = []; var_out = []; ch_in = []; ch_out = []};;
let nodes = ref [];;
let instances = ref [];;
(** saves the data from the Yaml parser into references of type Types.t *)
(* converts a `Float list into a int list *)
let (intlist : Yaml.value list -> int list) =
fun l ->
let (yv_to_int : Yaml.value -> int) = fun y ->
match y with
|`Float f -> int_of_float f
|_ -> assert false
in List.map yv_to_int l
;;
let (save_variable_attributes : Types.variable -> (string * Yaml.value) -> unit) =
fun v (key, value) ->
match key, value with
|"id", `Float _f -> ()
|"name", `String s -> v.name <- s
|"type", `String s -> v.var_type <- s
|_ -> assert false
let (save_variables : Yaml.value -> unit) = fun x ->
let v = {name = ""; var_type = ""}::[]
in
match x with
|`O l ->
List.iter (save_variable_attributes (List.hd v)) l;
variables := !variables @ v
|_ -> assert false
let (save_channels : Yaml.value -> unit) = fun x ->
match x with
|`Float f -> channels := !channels @ [int_of_float f]
|_ -> assert false
let (save_main : (string * Yaml.value) -> unit) =
fun (key, value) ->
match key, value with
|"name", `String s -> main.name <- s
|"ctx_type", `String s -> main.ctx_type <- s
|"ctx_new", `String s -> main.ctx_new <- s
|"var_in", `A l -> main.var_in <- List.map (List.nth !variables) (intlist l)
|"var_out", `A l -> main.var_out <- List.map (List.nth !variables) (intlist l)
|"ch_in", `A l -> main.ch_in <- intlist l
|"ch_out", `A l -> main.ch_out <- intlist l
|_ -> assert false
let (save_node_attributes : Types.node -> (string * Yaml.value) -> unit) =
fun n (key, value) ->
match key, value with
|"id", `Float _f -> ()
|"file_name", `String s -> n.file_name <- s
|"fct_name", `String s -> n.fct_name <- s
|"ctx", `Bool b -> n.ctx <- b
|"ctx_tab", `String s -> n.ctx_tab <- s
|_ -> assert false
let (save_nodes : Yaml.value -> unit) = fun x ->
let n = {file_name = ""; fct_name = ""; ctx = false; ctx_tab = ""}::[] in
match x with
|`O l ->
List.iter (save_node_attributes (List.hd n)) l;
nodes := !nodes @ n
|_ -> assert false
let (save_instance_attributes : Types.instance -> (string * Yaml.value) -> unit) =
fun i (key, value) ->
match key, value with
|"id", `Float f -> i.id <- int_of_float f
|"node", `Float f -> i.node <- List.nth !nodes (int_of_float f)
|"var_in", `A l -> i.var_in <- List.map (List.nth !variables) (intlist l)
|"var_out", `A l -> i.var_out <- List.map (List.nth !variables) (intlist l)
|"ch_in", `A l -> i.ch_in <- intlist l
|"ch_out", `A l -> i.ch_out <- intlist l
|_ -> assert false
let (save_instances : Yaml.value -> unit) = fun x ->
let i = {id = 0; node = List.nth !nodes 0; var_in = []; var_out = []; ch_in = []; ch_out = []}::[]
in
match x with
|`O l ->
List.iter (save_instance_attributes (List.hd i)) l;
instances := !instances @ i
|_ -> assert false
let (save_data2 : (string * Yaml.value) -> unit) =
fun (key, value) ->
match key, value with
|"variables", `A l -> List.iter save_variables l
|"channels" , `A l -> List.iter save_channels l
|"main" , `O l -> List.iter save_main l
|"nodes", `A l -> List.iter save_nodes l
|"instances", `A l -> List.iter save_instances l
|_ -> ()
let (save_data : Yaml.value -> unit) = fun x ->
match x with
|`O l -> List.iter save_data2 l
|_ -> assert false
let yaml_file = ref ""
let main () =
if (Array.length Sys.argv) <= 1 then (
Arg.usage MainArgs.speclist MainArgs.usage; flush stdout; exit 2
) else (
try Arg.parse MainArgs.speclist (fun s -> yaml_file := s) MainArgs.usage
with
| Failure(e) -> print_string e; flush stdout; flush stderr; exit 2
| e -> print_string (Printexc.to_string e); flush stdout; exit 2
);
let yaml = Yaml_unix.of_file_exn Fpath.(v !yaml_file) in
save_data yaml;
(* creates the .c file *)
let cfile = open_out (main.name ^ "_pthread.c") in
(* includes *)
fprintf cfile "#include <stdio.h>\n";
fprintf cfile "#include <stdlib.h>\n";
fprintf cfile "#include <string.h>\n";
fprintf cfile "#include <stdbool.h>\n";
fprintf cfile "#include <pthread.h>\n";
fprintf cfile "#include <semaphore.h>\n";
fprintf cfile "#include <errno.h>\n";
fprintf cfile "#include \"%s.h\"\n" main.name;
fprintf cfile "#include \"%s_loop_io.h\"\n" main.name;
fprintf cfile "\n";
(* semaphores macro *)
fprintf cfile "/* Initialize the semaphore with the given count. */\n";
fprintf cfile "#define SEM_INIT(sem, v, max_v) sem_init(&(sem), 0, (v))\n";
fprintf cfile "/* wait for the semaphore to be active (i.e. equal to 1) and then decrement it by one. */\n";
fprintf cfile "#define SEM_WAIT(sem) while (sem_wait(&sem) != 0 && errno == EINTR) continue\n";
fprintf cfile "/* make the semaphore active (i.e. equal to 1) */\n";
fprintf cfile "#define SEM_SIGNAL(sem) sem_post(&(sem))\n";
fprintf cfile "\n";
(* variables declaration *)
fprintf cfile "/* Declare variables */\n";
List.iter (fun x -> fprintf cfile "%s %s;\n" x.var_type x.name) !variables;
fprintf cfile "\n";
(* semaphores declaration *)
fprintf cfile "/* Declare semaphores */\n";
List.iter (fun x -> fprintf cfile "sem_t channel%i;\n" x) !channels;
fprintf cfile "\n";
(* ctx declaration *)
fprintf cfile "/* Declare context */\n";
fprintf cfile "%s* ctx;\n" main.ctx_type;
fprintf cfile "\n";
(* instance loops *)
fprintf cfile "/* Instance loops */\n";
let print_instance_loop instance =
fprintf cfile "void loop_%s%i() {\n" instance.node.file_name instance.id;
fprintf cfile " while(true) {\n";
List.iter (fprintf cfile " SEM_WAIT(channel%i);\n") instance.ch_in;
fprintf cfile " %s(" instance.node.fct_name;
fprintf cfile "%s" (List.hd instance.var_in).name;
List.iter (fun (x:variable) -> fprintf cfile ", %s" x.name) (List.tl instance.var_in);
List.iter (fun (x:variable) -> fprintf cfile ", &%s" x.name) instance.var_out;
if instance.node.ctx then fprintf cfile ", &ctx->%s[%i]" instance.node.ctx_tab instance.id;
fprintf cfile ");\n";
List.iter (fprintf cfile " SEM_SIGNAL(channel%i);\n") instance.ch_out;
fprintf cfile " }\n";
fprintf cfile "}\n";
fprintf cfile "\n";
in
List.iter print_instance_loop !instances;
(* main function *)
fprintf cfile "/* Main function */\n";
fprintf cfile "void main() {
int _s = 0;\n";
fprintf cfile " /* Initialize context */\n";
fprintf cfile " ctx = %s(NULL);\n" main.ctx_new;
fprintf cfile "\n";
fprintf cfile " /* Initialize semaphores */\n";
List.iter (fprintf cfile " SEM_INIT(channel%i, 0, 1);\n") !channels;
fprintf cfile " \n";
fprintf cfile " /* Declare pthreads */\n";
List.iter (fun x -> fprintf cfile " pthread_t pt_%s%i;\n" x.node.file_name x.id) !instances;
fprintf cfile " \n";
fprintf cfile " /* Initialize pthreads */\n";
List.iter (fun x -> fprintf cfile " pthread_create(&pt_%s%i, NULL, loop_%s%i, NULL);\n" x.node.file_name x.id x.node.file_name x.id) !instances;
fprintf cfile " \n";
(* main loop *)
fprintf cfile "print_rif_declaration();\n";
output_string cfile " /* Main loop */
while(true) {
if (ISATTY) printf(\"#step \\%d \\n\", _s+1);
else if(_s) printf(\"\\n\");
fflush(stdout);
++_s;\n";
fprintf cfile " get_inputs(ctx";
List.iter (fun (x:variable) -> fprintf cfile ", &%s" x.name) main.var_in;
fprintf cfile ");\n";
List.iter (fprintf cfile " SEM_SIGNAL(channel%i);\n") main.ch_in;
List.iter (fprintf cfile " SEM_WAIT(channel%i);\n") main.ch_out;
fprintf cfile " print_outputs(%s" (List.hd main.var_out).name;
List.iter (fun (x:variable) -> fprintf cfile ", %s" x.name) (List.tl main.var_out);
fprintf cfile ");\n";
fprintf cfile " }\n";
fprintf cfile " \n";
List.iter (fun x -> fprintf cfile " pthread_join(&pt_%s%i, NULL);\n" x.node.file_name x.id) !instances;
fprintf cfile "}\n";
fprintf cfile "\n"
;;
let _ = main ()