Source file actionsDeps.ml
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
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
(** Time-stamp: <modified the 21/03/2022 (at 11:43) by Erwan Jahier> *)
let dbg = (Lv6Verbose.get_flag "deps")
type action = Action.t
module OrderedAction = struct
type t = action
let compare = compare
end
(** Gère un ensemble d'actions uniques. *)
module Actions = Set.Make(OrderedAction)
module MapAction = Map.Make(OrderedAction)
(** maps an action to the set of actions that it depends on *)
type t = Actions.t MapAction.t
let empty: t = MapAction.empty
let (have_deps : t -> action -> bool) =
fun m a ->
MapAction.mem a m
let (remove_dep : t -> action -> t) =
fun deps a ->
Lv6Verbose.exe ~flag:dbg (fun () ->
Printf.printf " remove_deps(%s)\n%!" (Action.to_string a));
MapAction.remove a deps
let (find_deps: t -> action -> action list) =
fun m a ->
let res =
try Actions.elements (MapAction.find a m) with Not_found -> []
in
Lv6Verbose.exe ~flag:dbg (fun () ->
Printf.printf "find_deps(%s)='%s'\n%!" (Action.to_string a)
(String.concat "+" (List.map Action.to_string res)));
res
let rec (depends_on : t -> Action.t -> Action.t -> bool) =
fun m a1 a2 ->
try
let a1_deps = MapAction.find a1 m in
Actions.mem a2 a1_deps ||
Actions.exists (fun a1 -> depends_on m a1 a2) a1_deps
with
Not_found -> false
(** Ajoute une liste de dépendances à une action. *)
let add_deps: t -> action -> action list -> t =
fun m a -> function
| [] ->
Lv6Verbose.exe
~flag:dbg (fun () -> Printf.printf " add_deps(%s,[]) \n%!" (Action.to_string a));
m
| al ->
Lv6Verbose.exe
~flag:dbg (fun () -> Printf.printf "\n add_deps(%s,???)\n%!" (Action.to_string a));
let actions = try MapAction.find a m with Not_found -> Actions.empty in
let actions = List.fold_left (fun set a -> Actions.add a set) actions al in
Lv6Verbose.exe ~flag:dbg (fun () ->
Printf.printf " add_deps(%s,[%s])\n%!" (Action.to_string a)
(String.concat "+" (List.map Action.to_string al)));
MapAction.add a actions m
let (concat: t -> t -> t) =
fun m1 m2 ->
MapAction.fold (fun key value m -> add_deps m key (Actions.elements value)) m1 m2
let (generate_deps_from_step_policy:
Soc.precedence list -> (string * action) list -> t) =
fun precedences actions ->
let generate_deps_for_action: (t -> string * string list -> t) =
fun ad (action_name, actions_needed) ->
let main_action = snd (List.find (fun (n, _) -> n = action_name) actions) in
let deps =
List.map
(fun dep_name -> snd (List.find (fun (n, _) -> n = dep_name) actions))
actions_needed
in
add_deps ad main_action deps
in
List.fold_left (generate_deps_for_action) empty precedences
module VarMap = Map.Make(String)
(** A Data structure that maps a Soc.var_expr to all the
actions that needed to compute it.
It is used to know which actions impact which Soc.var_expr.
nb : you can have several actions associated to the same var_expr
when defining arrays or structures parts by parts. For instance
x[0]=42;
x[1]=1;
are two actions that define the var_expr "x"
*)
type var2actions_tbl = Actions.t VarMap.t
let var2actions k tbl =
let k = SocUtils.string_of_filter k in
let res = try VarMap.find k tbl with Not_found -> Actions.empty in
res
let rec (gen_parents : Soc.var_expr -> Soc.var_expr list) =
fun var ->
match var with
| Soc.Slice(ve,_,_,_,_,_)
| Soc.Field(ve,_,_)
| Soc.Index(ve,_,_) -> ve::(gen_parents ve)
| Soc.Var(_,_vt)
| Soc.Const(_,_vt) -> [var]
let rec (_get_top_var : Soc.var_expr -> Soc.var_expr) =
fun var ->
match var with
| Soc.Slice(ve,_,_,_,_,_)
| Soc.Field(ve,_,_)
| Soc.Index(ve,_,_) -> _get_top_var ve
| Soc.Var(_,_vt)
| Soc.Const(_,_vt) -> var
(** If x is a int^2, then
then actions such as a="x = y"
should produce the following dependancies :
x -> a
x[0] -> a
x[1] -> a
Hence, gen_children "x" produces "x[0]", and "x[1]"
*)
let rec (gen_children: Soc.var_expr -> Soc.var_expr list) =
fun v ->
match Soc.data_type_of_var_expr v with
| Data.Alpha _ | Data.Extern _ | Data.Enum _ | Data.String
| Data.Bool | Data.Int | Data.Real
-> [v]
| Data.Struct(_ident, ident_t_list) ->
List.fold_left
(fun acc (id,t) ->
let new_ve = Soc.Field(v,id,t) in
new_ve::((gen_children new_ve) @ acc)
)
[]
ident_t_list
| Data.Array(t,size) ->
let new_ve_list = ref [] in
for i=0 to size - 1 do
let new_ve = Soc.Index(v, i, t) in
new_ve_list := new_ve::((gen_children new_ve) @ !new_ve_list);
done;
!new_ve_list
| Data.Alias(_,_t) -> assert false
let nodupl l =
List.fold_left (fun acc x -> if List.mem x acc then acc else x::acc) [] l
let (get_var2actions_tbl : action list -> var2actions_tbl) =
fun al ->
let (tabulate_action : var2actions_tbl -> action -> var2actions_tbl) =
fun tbl action ->
let _, _, lhs, _, _lxm = action in
let (tabulate_output:var2actions_tbl -> Soc.var_expr -> var2actions_tbl) =
fun tbl output ->
let v = output in
let children = gen_children v in
let parents = gen_parents v in
let all = nodupl ((v::children)@parents) in
let tbl =
List.fold_left
(fun tbl cv ->
Lv6Verbose.exe ~flag:dbg (fun () ->
Printf.printf " var_add_deps: '%s' depends on '%s'\n%!"
(SocUtils.string_of_var_expr cv) (Action.to_string action));
let cv_actions = var2actions cv tbl in
VarMap.add (SocUtils.string_of_filter cv) (Actions.add action cv_actions) tbl)
tbl all
in
tbl
in
List.fold_left tabulate_output tbl lhs
in
List.fold_left tabulate_action VarMap.empty al
(** Returns the actions that depend on a set of vars, according to the content
of a table compute before
[actions_of_vars input_vars al] trouve toutes les actions de [al] qui
ont besoin d'être effectuées avant de pouvoir se servir de [input_vars]
comme entrée d'une autre action.
TODO: gérer les dépendances entre des filtres plus complexes,
comme par ex., l'utilisation d'un champ d'une structure.
*)
let (_actions_of_vars_old: Soc.var_expr list -> var2actions_tbl -> action list) =
fun vars tbl ->
let find_deps var = Actions.elements (var2actions var tbl) in
List.flatten (List.map find_deps vars)
let (actions_of_vars: Soc.var_expr list -> var2actions_tbl -> action list) =
fun vars tbl ->
let actions =
List.fold_left
(fun acc v -> Actions.union acc (var2actions v tbl))
Actions.empty
vars
in
let res = Actions.elements actions in
Lv6Verbose.exe
~flag:dbg (fun () ->
Printf.printf "actions_of_vars(%s)='%s'\n%!"
(String.concat "," (List.map SocUtils.string_of_var_expr vars))
(String.concat "+" (List.map Action.to_string res))
);
res
let string_of_actions: Actions.t -> string = fun s ->
let to_string a acc =
acc ^ "\n\t + '"^ (Action.to_string_msg a) ^ "'"
in
"" ^ (Actions.fold to_string s "") ^ ""
let string_of_var2actions_tbl: var2actions_tbl -> string =
fun s ->
let to_string key value acc =
let entry = Format.sprintf "%s depends on the following actions: %s"
key (string_of_actions value)
in
acc ^ entry ^ "\n"
in
"var2actions_tbl: {\n" ^ (VarMap.fold to_string s "") ^ "}"
let to_string: t -> string = fun m ->
let to_string key value acc =
let entry =
Format.sprintf "- '%s' depends on:%s"
(Action.to_string key)
(string_of_actions value)
in
acc ^ entry ^ "\n"
in
"dependencies between equations are: \n" ^ (MapAction.fold to_string m "") ^ ""
let build_data_deps_from_actions: (Lic.type_ -> Data.t) -> t -> action list -> t =
fun lic_to_data_type deps al ->
let tbl = get_var2actions_tbl al in
let pp_dbg () =
let al_str = List.map Action.to_string al in
print_string "\n ====> List of actions to be sorted:\n - ";
print_string (String.concat "\n - " al_str);
print_string "\n ====> List of previously computed dependencies:(\n ";
print_string (string_of_var2actions_tbl tbl);
print_string ")\n";
flush stdout
in
let deps =
Lv6Verbose.exe ~flag:dbg pp_dbg;
List.fold_left
(fun acc_deps action ->
let (clk, rhs, _, _,_) = action in
let dep_vars = match clk with
| Lic.BaseLic -> rhs
| Lic.ClockVar _int -> rhs
| Lic.On ((_cc,cv,ct),_) ->
(Soc.Var(cv, lic_to_data_type ct))::rhs
in
let action_deps = actions_of_vars dep_vars tbl in
if action_deps = [] then (
let dep_str = String.concat "," (List.map SocUtils.string_of_filter dep_vars) in
Lv6Verbose.exe
~flag:dbg (fun () ->
Printf.printf " No deps for %s (dep_vars=%s) \n%!" (Action.to_string action) dep_str);
acc_deps
)
else (
Lv6Verbose.exe ~flag:dbg (fun () ->
Printf.printf " %s depends on %s ==> calling add_deps\n" (Action.to_string action)
(String.concat " + " (List.map Action.to_string action_deps)));
add_deps acc_deps action action_deps
)
)
deps
al
in
deps