1
|
(* ----------------------------------------------------------------------------
|
2
|
* SchedMCore - A MultiCore Scheduling Framework
|
3
|
* Copyright (C) 2009-2011, ONERA, Toulouse, FRANCE - LIFL, Lille, FRANCE
|
4
|
*
|
5
|
* This file is part of Prelude
|
6
|
*
|
7
|
* Prelude is free software; you can redistribute it and/or
|
8
|
* modify it under the terms of the GNU Lesser General Public License
|
9
|
* as published by the Free Software Foundation ; either version 2 of
|
10
|
* the License, or (at your option) any later version.
|
11
|
*
|
12
|
* Prelude is distributed in the hope that it will be useful, but
|
13
|
* WITHOUT ANY WARRANTY ; without even the implied warranty of
|
14
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
15
|
* Lesser General Public License for more details.
|
16
|
*
|
17
|
* You should have received a copy of the GNU Lesser General Public
|
18
|
* License along with this program ; if not, write to the Free Software
|
19
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
20
|
* USA
|
21
|
*---------------------------------------------------------------------------- *)
|
22
|
|
23
|
(** Clocks definitions and a few utility functions on clocks. *)
|
24
|
open Utils
|
25
|
open Format
|
26
|
|
27
|
(* Clock type sets, for subtyping. *)
|
28
|
type clock_set =
|
29
|
CSet_all
|
30
|
| CSet_pck of int*rat
|
31
|
|
32
|
(* Clock carriers basically correspond to the "c" in "x when c" *)
|
33
|
type carrier_desc =
|
34
|
| Carry_const of ident
|
35
|
| Carry_name
|
36
|
| Carry_var
|
37
|
| Carry_link of carrier_expr
|
38
|
|
39
|
(* Carriers are scoped, to detect clock extrusion. In other words, we
|
40
|
check the scope of a clock carrier before generalizing it. *)
|
41
|
and carrier_expr =
|
42
|
{mutable carrier_desc: carrier_desc;
|
43
|
mutable carrier_scoped: bool;
|
44
|
carrier_id: int}
|
45
|
|
46
|
type clock_expr =
|
47
|
{mutable cdesc: clock_desc;
|
48
|
mutable cscoped: bool;
|
49
|
cid: int}
|
50
|
|
51
|
(* pck stands for periodic clock. Easier not to separate pck from other clocks *)
|
52
|
and clock_desc =
|
53
|
| Carrow of clock_expr * clock_expr
|
54
|
| Ctuple of clock_expr list
|
55
|
| Con of clock_expr * carrier_expr * ident
|
56
|
| Pck_up of clock_expr * int
|
57
|
| Pck_down of clock_expr * int
|
58
|
| Pck_phase of clock_expr * rat
|
59
|
| Pck_const of int * rat
|
60
|
| Cvar of clock_set (* Monomorphic clock variable *)
|
61
|
| Cunivar of clock_set (* Polymorphic clock variable *)
|
62
|
| Clink of clock_expr (* During unification, make links instead of substitutions *)
|
63
|
| Ccarrying of carrier_expr * clock_expr
|
64
|
|
65
|
type error =
|
66
|
| Clock_clash of clock_expr * clock_expr
|
67
|
| Not_pck
|
68
|
| Clock_set_mismatch of clock_expr * clock_set
|
69
|
| Cannot_be_polymorphic of clock_expr
|
70
|
| Invalid_imported_clock of clock_expr
|
71
|
| Invalid_const of clock_expr
|
72
|
| Factor_zero
|
73
|
| Carrier_mismatch of carrier_expr * carrier_expr
|
74
|
| Carrier_extrusion of clock_expr * carrier_expr
|
75
|
| Clock_extrusion of clock_expr * clock_expr
|
76
|
|
77
|
exception Unify of clock_expr * clock_expr
|
78
|
exception Subsume of clock_expr * clock_set
|
79
|
exception Mismatch of carrier_expr * carrier_expr
|
80
|
exception Scope_carrier of carrier_expr
|
81
|
exception Scope_clock of clock_expr
|
82
|
exception Error of Location.t * error
|
83
|
|
84
|
let new_id = ref (-1)
|
85
|
|
86
|
let new_ck desc scoped =
|
87
|
incr new_id; {cdesc=desc; cid = !new_id; cscoped = scoped}
|
88
|
|
89
|
let new_var scoped =
|
90
|
new_ck (Cvar CSet_all) scoped
|
91
|
|
92
|
let new_univar () =
|
93
|
new_ck (Cunivar CSet_all) false
|
94
|
|
95
|
let new_carrier_id = ref (-1)
|
96
|
|
97
|
let new_carrier desc scoped =
|
98
|
incr new_carrier_id; {carrier_desc = desc;
|
99
|
carrier_id = !new_carrier_id;
|
100
|
carrier_scoped = scoped}
|
101
|
|
102
|
let new_carrier_name () =
|
103
|
new_carrier Carry_name true
|
104
|
|
105
|
let rec repr =
|
106
|
function
|
107
|
{cdesc=Clink ck'} ->
|
108
|
repr ck'
|
109
|
| ck -> ck
|
110
|
|
111
|
let rec carrier_repr =
|
112
|
function {carrier_desc = Carry_link cr'} -> carrier_repr cr'
|
113
|
| cr -> cr
|
114
|
|
115
|
(** Splits [ck] into the [lhs,rhs] of an arrow clock. Expects an arrow clock
|
116
|
(ensured by language syntax) *)
|
117
|
let split_arrow ck =
|
118
|
match (repr ck).cdesc with
|
119
|
| Carrow (cin,cout) -> cin,cout
|
120
|
(* Functions are not first order, I don't think the var case
|
121
|
needs to be considered here *)
|
122
|
| _ -> failwith "Internal error: not an arrow clock"
|
123
|
|
124
|
let get_carrier_name ck =
|
125
|
match (repr ck).cdesc with
|
126
|
| Ccarrying (cr, _) -> Some cr
|
127
|
| _ -> None
|
128
|
|
129
|
let uncarrier ck =
|
130
|
match ck.cdesc with
|
131
|
| Ccarrying (_, ck') -> ck'
|
132
|
| _ -> ck
|
133
|
|
134
|
(* Removes all links in a clock. Only used for clocks
|
135
|
simplification though. *)
|
136
|
let rec deep_repr ck =
|
137
|
match ck.cdesc with
|
138
|
| Carrow (ck1,ck2) ->
|
139
|
new_ck (Carrow (deep_repr ck1, deep_repr ck2)) ck.cscoped
|
140
|
| Ctuple cl ->
|
141
|
new_ck (Ctuple (List.map deep_repr cl)) ck.cscoped
|
142
|
| Con (ck', c, l) ->
|
143
|
new_ck (Con (deep_repr ck', c, l)) ck.cscoped
|
144
|
| Pck_up (ck',k) ->
|
145
|
new_ck (Pck_up (deep_repr ck',k)) ck.cscoped
|
146
|
| Pck_down (ck',k) ->
|
147
|
new_ck (Pck_down (deep_repr ck',k)) ck.cscoped
|
148
|
| Pck_phase (ck',q) ->
|
149
|
new_ck (Pck_phase (deep_repr ck',q)) ck.cscoped
|
150
|
| Pck_const (_,_) | Cvar _ | Cunivar _ -> ck
|
151
|
| Clink ck' -> deep_repr ck'
|
152
|
| Ccarrying (cr,ck') -> new_ck (Ccarrying (cr, deep_repr ck')) ck.cscoped
|
153
|
|
154
|
(** Splits ck into the [lhs,rhs] of an arrow clock. Expects an arrow clock
|
155
|
(ensured by language syntax) *)
|
156
|
let split_arrow ck =
|
157
|
match (repr ck).cdesc with
|
158
|
| Carrow (cin,cout) -> cin,cout
|
159
|
| _ -> failwith "Internal error: not an arrow clock"
|
160
|
|
161
|
(** Returns the clock corresponding to a clock list. *)
|
162
|
let clock_of_clock_list ckl =
|
163
|
if (List.length ckl) > 1 then
|
164
|
new_ck (Ctuple ckl) true
|
165
|
else
|
166
|
List.hd ckl
|
167
|
|
168
|
let clock_list_of_clock ck =
|
169
|
match (repr ck).cdesc with
|
170
|
| Ctuple cl -> cl
|
171
|
| _ -> [ck]
|
172
|
|
173
|
let clock_of_impnode_clock ck =
|
174
|
let ck = repr ck in
|
175
|
match ck.cdesc with
|
176
|
| Carrow _ | Clink _ | Cvar _ | Cunivar _ ->
|
177
|
failwith "internal error clock_of_impnode_clock"
|
178
|
| Ctuple cklist -> List.hd cklist
|
179
|
| Con (_,_,_) | Pck_up (_,_) | Pck_down (_,_) | Pck_phase (_,_)
|
180
|
| Pck_const (_,_) | Ccarrying (_,_) -> ck
|
181
|
|
182
|
(** [intersect set1 set2] returns the intersection of clock subsets
|
183
|
[set1] and [set2]. *)
|
184
|
let intersect set1 set2 =
|
185
|
match set1,set2 with
|
186
|
| CSet_all,_ -> set2
|
187
|
| _,CSet_all -> set1
|
188
|
| CSet_pck (k,q), CSet_pck (k',q') ->
|
189
|
let k'',q'' = lcm k k',max_rat q q' in
|
190
|
CSet_pck (k'',q'')
|
191
|
|
192
|
(** [can_be_pck ck] returns true if [ck] "may be" a pclock (the uncertainty is
|
193
|
due to clock variables) *)
|
194
|
let rec can_be_pck ck =
|
195
|
match (repr ck).cdesc with
|
196
|
| Pck_up (_,_) | Pck_down (_,_) | Pck_phase (_,_) | Pck_const (_,_)
|
197
|
| Cvar _ | Cunivar _ ->
|
198
|
true
|
199
|
| Ccarrying (_,ck') -> can_be_pck ck
|
200
|
| _ -> false
|
201
|
|
202
|
(** [is_concrete_pck ck] returns true if [ck] is a concrete [pck] (pck
|
203
|
transformations applied to a pck constant) *)
|
204
|
let rec is_concrete_pck ck =
|
205
|
match ck.cdesc with
|
206
|
| Carrow (_,_) | Ctuple _ | Con (_,_,_)
|
207
|
| Cvar _ | Cunivar _ -> false
|
208
|
| Pck_up (ck',_) | Pck_down (ck',_) -> is_concrete_pck ck'
|
209
|
| Pck_phase (ck',_) -> is_concrete_pck ck'
|
210
|
| Pck_const (_,_) -> true
|
211
|
| Clink ck' -> is_concrete_pck ck'
|
212
|
| Ccarrying (_,ck') -> false
|
213
|
|
214
|
(** [is_polymorphic ck] returns true if [ck] is polymorphic. *)
|
215
|
let rec is_polymorphic ck =
|
216
|
match ck.cdesc with
|
217
|
| Cvar _ | Pck_const (_,_) -> false
|
218
|
| Carrow (ck1,ck2) -> (is_polymorphic ck1) || (is_polymorphic ck2)
|
219
|
| Ctuple ckl -> List.exists (fun c -> is_polymorphic c) ckl
|
220
|
| Con (ck',_,_) -> is_polymorphic ck'
|
221
|
| Pck_up (ck',_) | Pck_down (ck',_) -> is_polymorphic ck'
|
222
|
| Pck_phase (ck',_) -> is_polymorphic ck'
|
223
|
| Cunivar _ -> true
|
224
|
| Clink ck' -> is_polymorphic ck'
|
225
|
| Ccarrying (_,ck') -> is_polymorphic ck'
|
226
|
|
227
|
(** [constrained_vars_of_clock ck] returns the clock variables subject
|
228
|
to sub-typing constraints appearing in clock [ck]. Removes duplicates *)
|
229
|
(* Used mainly for debug, non-linear complexity. *)
|
230
|
let rec constrained_vars_of_clock ck =
|
231
|
let rec aux vars ck =
|
232
|
match ck.cdesc with
|
233
|
| Pck_const (_,_) ->
|
234
|
vars
|
235
|
| Cvar cset ->
|
236
|
begin
|
237
|
match cset with
|
238
|
| CSet_all -> vars
|
239
|
| _ ->
|
240
|
list_union [ck] vars
|
241
|
end
|
242
|
| Carrow (ck1,ck2) ->
|
243
|
let l = aux vars ck1 in
|
244
|
aux l ck2
|
245
|
| Ctuple ckl ->
|
246
|
List.fold_left
|
247
|
(fun acc ck' -> aux acc ck')
|
248
|
vars ckl
|
249
|
| Con (ck',_,_) -> aux vars ck'
|
250
|
| Pck_up (ck',_) | Pck_down (ck',_) -> aux vars ck'
|
251
|
| Pck_phase (ck',_) -> aux vars ck'
|
252
|
| Cunivar cset ->
|
253
|
begin
|
254
|
match cset with
|
255
|
| CSet_all -> vars
|
256
|
| _ -> list_union [ck] vars
|
257
|
end
|
258
|
| Clink ck' -> aux vars ck'
|
259
|
| Ccarrying (_,ck') -> aux vars ck'
|
260
|
in
|
261
|
aux [] ck
|
262
|
|
263
|
let print_ckset fmt s =
|
264
|
match s with
|
265
|
| CSet_all -> ()
|
266
|
| CSet_pck (k,q) ->
|
267
|
let (a,b) = simplify_rat q in
|
268
|
if k = 1 && a = 0 then
|
269
|
fprintf fmt "<:P"
|
270
|
else
|
271
|
fprintf fmt "<:P_(%i,%a)" k print_rat (a,b)
|
272
|
|
273
|
let rec print_carrier fmt cr =
|
274
|
(* (if cr.carrier_scoped then fprintf fmt "[%t]" else fprintf fmt "%t") (fun fmt -> *)
|
275
|
match cr.carrier_desc with
|
276
|
| Carry_const id -> fprintf fmt "%s" id
|
277
|
| Carry_name ->
|
278
|
fprintf fmt "_%s" (name_of_carrier cr.carrier_id)
|
279
|
| Carry_var ->
|
280
|
fprintf fmt "'%s" (name_of_carrier cr.carrier_id)
|
281
|
| Carry_link cr' ->
|
282
|
print_carrier fmt cr'
|
283
|
|
284
|
(* Simple pretty-printing, performs no simplifications. Linear
|
285
|
complexity. For debug mainly. *)
|
286
|
let rec print_ck_long fmt ck =
|
287
|
match ck.cdesc with
|
288
|
| Carrow (ck1,ck2) ->
|
289
|
fprintf fmt "%a->%a" print_ck_long ck1 print_ck_long ck2
|
290
|
| Ctuple cklist ->
|
291
|
fprintf fmt "(%a)"
|
292
|
(fprintf_list ~sep:" * " print_ck_long) cklist
|
293
|
| Con (ck,c,l) ->
|
294
|
fprintf fmt "%a on %s(%a)" print_ck_long ck l print_carrier c
|
295
|
| Pck_up (ck,k) ->
|
296
|
fprintf fmt "%a*^%i" print_ck_long ck k
|
297
|
| Pck_down (ck,k) ->
|
298
|
fprintf fmt "%a/^%i" print_ck_long ck k
|
299
|
| Pck_phase (ck,q) ->
|
300
|
fprintf fmt "%a~>%a" print_ck_long ck print_rat (simplify_rat q)
|
301
|
| Pck_const (n,p) ->
|
302
|
fprintf fmt "(%i,%a)" n print_rat (simplify_rat p)
|
303
|
| Cvar cset ->
|
304
|
fprintf fmt "'_%i%a" ck.cid print_ckset cset
|
305
|
| Cunivar cset ->
|
306
|
fprintf fmt "'%i%a" ck.cid print_ckset cset
|
307
|
| Clink ck' ->
|
308
|
fprintf fmt "link %a" print_ck_long ck'
|
309
|
| Ccarrying (cr,ck') ->
|
310
|
fprintf fmt "(%a:%a)" print_carrier cr print_ck_long ck'
|
311
|
|
312
|
(** [period ck] returns the period of [ck]. Expects a constant pclock
|
313
|
expression belonging to the correct clock set. *)
|
314
|
let rec period ck =
|
315
|
let rec aux ck =
|
316
|
match ck.cdesc with
|
317
|
| Carrow (_,_) | Ctuple _ | Con (_,_,_)
|
318
|
| Cvar _ | Cunivar _ ->
|
319
|
failwith "internal error: can only compute period of const pck"
|
320
|
| Pck_up (ck',k) ->
|
321
|
(aux ck')/.(float_of_int k)
|
322
|
| Pck_down (ck',k) ->
|
323
|
(float_of_int k)*.(aux ck')
|
324
|
| Pck_phase (ck',_) ->
|
325
|
aux ck'
|
326
|
| Pck_const (n,_) ->
|
327
|
float_of_int n
|
328
|
| Clink ck' -> aux ck'
|
329
|
| Ccarrying (_,ck') -> aux ck'
|
330
|
in
|
331
|
int_of_float (aux ck)
|
332
|
|
333
|
(** [phase ck] returns the phase of [ck]. It is not expressed as a
|
334
|
fraction of the period, but instead as an amount of time. Expects a
|
335
|
constant expression belonging to the correct P_k *)
|
336
|
let phase ck =
|
337
|
let rec aux ck =
|
338
|
match ck.cdesc with
|
339
|
| Carrow (_,_) | Ctuple _ | Con (_,_,_)
|
340
|
| Cvar _ | Cunivar _ ->
|
341
|
failwith "internal error: can only compute phase of const pck"
|
342
|
| Pck_up (ck',_) ->
|
343
|
aux ck'
|
344
|
| Pck_down (ck',k) ->
|
345
|
aux ck'
|
346
|
| Pck_phase (ck',(a,b)) ->
|
347
|
let n = period ck' in
|
348
|
let (a',b') = aux ck' in
|
349
|
sum_rat (a',b') (n*a,b)
|
350
|
| Pck_const (n,(a,b)) ->
|
351
|
(n*a,b)
|
352
|
| Clink ck' -> aux ck'
|
353
|
| Ccarrying (_,ck') -> aux ck'
|
354
|
in
|
355
|
let (a,b) = aux ck in
|
356
|
simplify_rat (a,b)
|
357
|
|
358
|
(* Returns the pck clock parent of a clock *)
|
359
|
let rec pclock_parent ck =
|
360
|
match (repr ck).cdesc with
|
361
|
| Con (ck',_,_) | Clink ck' | Ccarrying (_,ck') ->
|
362
|
pclock_parent ck'
|
363
|
| Pck_up _ | Pck_down _ | Pck_phase _ | Pck_const _ | Cvar _ | Cunivar _ -> ck
|
364
|
| Carrow _ | Ctuple _ -> failwith "Internal error pclock_parent"
|
365
|
|
366
|
(** [normalize pck] returns the normal form of clock [pck]. *)
|
367
|
let normalize pck =
|
368
|
let changed = ref true in
|
369
|
let rec aux pck =
|
370
|
match pck.cdesc with
|
371
|
| Pck_up ({cdesc=Pck_up (pck',k')},k) ->
|
372
|
changed:=true;
|
373
|
new_ck (Pck_up (aux pck',k*k')) pck.cscoped
|
374
|
| Pck_up ({cdesc=Pck_down (pck',k')},k) ->
|
375
|
changed:=true;
|
376
|
new_ck (Pck_down (new_ck (Pck_up (aux pck',k)) pck.cscoped,k')) pck.cscoped
|
377
|
| Pck_up ({cdesc=Pck_phase (pck',(a,b))},k) ->
|
378
|
changed:=true;
|
379
|
new_ck (Pck_phase (new_ck (Pck_up (aux pck',k)) pck.cscoped,(a*k,b))) pck.cscoped
|
380
|
| Pck_down ({cdesc=Pck_down (pck',k')},k) ->
|
381
|
changed:=true;
|
382
|
new_ck (Pck_down (aux pck',k*k')) pck.cscoped
|
383
|
| Pck_down ({cdesc=Pck_phase (pck',(a,b))},k) ->
|
384
|
changed:=true;
|
385
|
new_ck (Pck_phase (new_ck (Pck_down (aux pck',k)) pck.cscoped,(a,b*k))) pck.cscoped
|
386
|
| Pck_phase ({cdesc=Pck_phase (pck',(a',b'))},(a,b)) ->
|
387
|
changed:=true;
|
388
|
let (a'',b'') = sum_rat (a,b) (a',b') in
|
389
|
new_ck (Pck_phase (aux pck',(a'',b''))) pck.cscoped
|
390
|
| Pck_up (pck',k') ->
|
391
|
new_ck (Pck_up (aux pck',k')) pck.cscoped
|
392
|
| Pck_down (pck',k') ->
|
393
|
new_ck (Pck_down (aux pck',k')) pck.cscoped
|
394
|
| Pck_phase (pck',k') ->
|
395
|
new_ck (Pck_phase (aux pck',k')) pck.cscoped
|
396
|
| Ccarrying (cr,ck') ->
|
397
|
new_ck (Ccarrying (cr, aux ck')) pck.cscoped
|
398
|
| _ -> pck
|
399
|
in
|
400
|
let nf=ref pck in
|
401
|
while !changed do
|
402
|
changed:=false;
|
403
|
nf:=aux !nf
|
404
|
done;
|
405
|
!nf
|
406
|
|
407
|
(** [canonize pck] reduces transformations of [pck] and removes
|
408
|
identity transformations. Expects a normalized periodic clock ! *)
|
409
|
let canonize pck =
|
410
|
let rec remove_id_trans pck =
|
411
|
match pck.cdesc with
|
412
|
| Pck_up (pck',1) | Pck_down (pck',1) | Pck_phase (pck',(0,_)) ->
|
413
|
remove_id_trans pck'
|
414
|
| _ -> pck
|
415
|
in
|
416
|
let pck =
|
417
|
match pck.cdesc with
|
418
|
| Pck_phase ({cdesc=Pck_down ({cdesc=Pck_up (v,k)},k')},k'') ->
|
419
|
let gcd = gcd k k' in
|
420
|
new_ck (Pck_phase
|
421
|
(new_ck (Pck_down
|
422
|
(new_ck (Pck_up (v,k/gcd)) pck.cscoped,k'/gcd))
|
423
|
pck.cscoped,k''))
|
424
|
pck.cscoped
|
425
|
| Pck_down ({cdesc=Pck_up (v,k)},k') ->
|
426
|
let gcd = gcd k k' in
|
427
|
new_ck (Pck_down (new_ck (Pck_up (v,k/gcd)) pck.cscoped,k'/gcd)) pck.cscoped
|
428
|
| _ -> pck
|
429
|
in
|
430
|
remove_id_trans pck
|
431
|
|
432
|
(** [simplify pck] applies pclocks simplifications to [pck] *)
|
433
|
let simplify pck =
|
434
|
if (is_concrete_pck pck) then
|
435
|
let n = period pck in
|
436
|
let (a,b) = phase pck in
|
437
|
let phase' = simplify_rat (a,b*n) in
|
438
|
new_ck (Pck_const (n,phase')) pck.cscoped
|
439
|
else
|
440
|
let pck' = deep_repr pck in
|
441
|
let nf_pck = normalize pck' in
|
442
|
canonize nf_pck
|
443
|
|
444
|
let print_cvar fmt cvar =
|
445
|
match cvar.cdesc with
|
446
|
| Cvar cset ->
|
447
|
(*
|
448
|
if cvar.cscoped
|
449
|
then
|
450
|
fprintf fmt "['_%s%a]"
|
451
|
(name_of_type cvar.cid)
|
452
|
print_ckset cset
|
453
|
else
|
454
|
*)
|
455
|
fprintf fmt "'_%s%a"
|
456
|
(name_of_type cvar.cid)
|
457
|
print_ckset cset
|
458
|
| Cunivar cset ->
|
459
|
(*
|
460
|
if cvar.cscoped
|
461
|
then
|
462
|
fprintf fmt "['%s%a]"
|
463
|
(name_of_type cvar.cid)
|
464
|
print_ckset cset
|
465
|
else
|
466
|
*)
|
467
|
fprintf fmt "'%s%a"
|
468
|
(name_of_type cvar.cid)
|
469
|
print_ckset cset
|
470
|
| _ -> failwith "Internal error print_cvar"
|
471
|
|
472
|
(* Nice pretty-printing. Simplifies expressions before printing them. Non-linear
|
473
|
complexity. *)
|
474
|
let print_ck fmt ck =
|
475
|
let rec aux fmt ck =
|
476
|
let ck = simplify ck in
|
477
|
match ck.cdesc with
|
478
|
| Carrow (ck1,ck2) ->
|
479
|
fprintf fmt "%a->%a" aux ck1 aux ck2
|
480
|
| Ctuple cklist ->
|
481
|
fprintf fmt "(%a)"
|
482
|
(fprintf_list ~sep:" * " aux) cklist
|
483
|
| Con (ck,c,l) ->
|
484
|
fprintf fmt "%a on %s(%a)" aux ck l print_carrier c
|
485
|
| Pck_up (ck,k) ->
|
486
|
fprintf fmt "%a*.%i" aux ck k
|
487
|
| Pck_down (ck,k) ->
|
488
|
fprintf fmt "%a/.%i" aux ck k
|
489
|
| Pck_phase (ck,q) ->
|
490
|
fprintf fmt "%a->.%a" aux ck print_rat (simplify_rat q)
|
491
|
| Pck_const (n,p) ->
|
492
|
fprintf fmt "(%i,%a)" n print_rat (simplify_rat p)
|
493
|
| Cvar cset ->
|
494
|
(*
|
495
|
if ck.cscoped
|
496
|
then
|
497
|
fprintf fmt "['_%s]" (name_of_type ck.cid)
|
498
|
else
|
499
|
*)
|
500
|
fprintf fmt "'_%s" (name_of_type ck.cid)
|
501
|
| Cunivar cset ->
|
502
|
(*
|
503
|
if ck.cscoped
|
504
|
then
|
505
|
fprintf fmt "['%s]" (name_of_type ck.cid)
|
506
|
else
|
507
|
*)
|
508
|
fprintf fmt "'%s" (name_of_type ck.cid)
|
509
|
| Clink ck' ->
|
510
|
aux fmt ck'
|
511
|
| Ccarrying (cr,ck') ->
|
512
|
fprintf fmt "(%a:%a)" print_carrier cr aux ck'
|
513
|
in
|
514
|
let cvars = constrained_vars_of_clock ck in
|
515
|
aux fmt ck;
|
516
|
if cvars <> [] then
|
517
|
fprintf fmt " (where %a)"
|
518
|
(fprintf_list ~sep:", " print_cvar) cvars
|
519
|
|
520
|
(* prints only the Con components of a clock, useful for printing nodes *)
|
521
|
let rec print_ck_suffix fmt ck =
|
522
|
let ck = simplify ck in
|
523
|
match ck.cdesc with
|
524
|
| Carrow _
|
525
|
| Ctuple _
|
526
|
| Cvar _
|
527
|
| Cunivar _ -> ()
|
528
|
| Con (ck,c,l) ->
|
529
|
fprintf fmt "%a when %s(%a)" print_ck_suffix ck l print_carrier c
|
530
|
| Clink ck' ->
|
531
|
print_ck_suffix fmt ck'
|
532
|
| Ccarrying (cr,ck') ->
|
533
|
fprintf fmt "%a" print_ck_suffix ck'
|
534
|
| _ -> assert false
|
535
|
|
536
|
let pp_error fmt = function
|
537
|
| Clock_clash (ck1,ck2) ->
|
538
|
reset_names ();
|
539
|
fprintf fmt "Expected clock %a, got clock %a@."
|
540
|
print_ck ck1
|
541
|
print_ck ck2
|
542
|
| Not_pck ->
|
543
|
fprintf fmt "The clock of this expression must be periodic@."
|
544
|
| Carrier_mismatch (cr1, cr2) ->
|
545
|
fprintf fmt "Name clash. Expected clock %a, got clock %a@."
|
546
|
print_carrier cr1
|
547
|
print_carrier cr2
|
548
|
| Clock_set_mismatch (ck,cset) ->
|
549
|
reset_names ();
|
550
|
fprintf fmt "Clock %a is not included in clock set %a@."
|
551
|
print_ck ck
|
552
|
print_ckset cset
|
553
|
| Cannot_be_polymorphic ck ->
|
554
|
reset_names ();
|
555
|
fprintf fmt "The main node cannot have a polymorphic clock: %a@."
|
556
|
print_ck ck
|
557
|
| Invalid_imported_clock ck ->
|
558
|
reset_names ();
|
559
|
fprintf fmt "Not a valid imported node clock: %a@."
|
560
|
print_ck ck
|
561
|
| Invalid_const ck ->
|
562
|
reset_names ();
|
563
|
fprintf fmt "Clock %a is not a valid periodic clock@."
|
564
|
print_ck ck;
|
565
|
| Factor_zero ->
|
566
|
fprintf fmt "Cannot apply clock transformation with factor 0@."
|
567
|
| Carrier_extrusion (ck,cr) ->
|
568
|
fprintf fmt "This node has clock@.%a@.It is invalid as %a escapes its scope@."
|
569
|
print_ck ck
|
570
|
print_carrier cr
|
571
|
| Clock_extrusion (ck_node,ck) ->
|
572
|
fprintf fmt "This node has clock@.%a@.It is invalid as %a escapes its scope@."
|
573
|
print_ck ck_node
|
574
|
print_ck ck
|
575
|
|
576
|
let uneval const cr =
|
577
|
(*Format.printf "uneval %s %a@." const print_carrier cr;*)
|
578
|
let cr = carrier_repr cr in
|
579
|
match cr.carrier_desc with
|
580
|
| Carry_var -> cr.carrier_desc <- Carry_const const
|
581
|
| _ -> assert false
|
582
|
|
583
|
(* Local Variables: *)
|
584
|
(* compile-command:"make -C .." *)
|
585
|
(* End: *)
|