2010-06-27 17:24:31 +02:00
|
|
|
open Minils
|
2010-07-16 09:58:56 +02:00
|
|
|
open Mls_mapfold
|
2010-06-27 17:24:31 +02:00
|
|
|
open Mls_printer
|
|
|
|
open Location
|
|
|
|
open Names
|
2010-07-23 19:45:19 +02:00
|
|
|
open Idents
|
2010-06-27 17:24:31 +02:00
|
|
|
open Signature
|
|
|
|
open Static
|
|
|
|
open Types
|
2010-07-23 22:06:06 +02:00
|
|
|
open Clocks
|
2010-06-27 17:24:31 +02:00
|
|
|
open Misc
|
|
|
|
|
|
|
|
(** Error Kind *)
|
2010-06-30 17:20:56 +02:00
|
|
|
type err_kind = | Enot_static_exp
|
2010-06-27 17:24:31 +02:00
|
|
|
|
2011-04-18 16:09:07 +02:00
|
|
|
let err_message exp ?(loc=exp.e_loc) = function
|
2010-06-30 17:20:56 +02:00
|
|
|
| Enot_static_exp ->
|
2010-09-14 09:39:02 +02:00
|
|
|
Format.eprintf "%aThe expression %a should be a static_exp.@."
|
|
|
|
print_location loc
|
2010-07-01 20:00:46 +02:00
|
|
|
print_exp exp;
|
2010-09-15 09:38:52 +02:00
|
|
|
raise Errors.Error
|
2010-06-27 17:24:31 +02:00
|
|
|
|
2010-06-30 17:20:56 +02:00
|
|
|
let rec static_exp_of_exp e =
|
2010-06-29 11:18:50 +02:00
|
|
|
match e.e_desc with
|
2011-04-14 18:06:54 +02:00
|
|
|
| Eextvalue w -> (match w.w_desc with
|
|
|
|
| Wconst se -> se
|
2011-04-18 16:09:07 +02:00
|
|
|
| _ -> err_message e Enot_static_exp)
|
|
|
|
| _ -> err_message e Enot_static_exp
|
2010-06-27 17:24:31 +02:00
|
|
|
|
|
|
|
(** @return the list of bounds of an array type*)
|
2010-06-29 11:18:50 +02:00
|
|
|
let rec bounds_list ty =
|
2010-07-28 09:53:16 +02:00
|
|
|
match Modules.unalias_type ty with
|
2010-06-27 17:24:31 +02:00
|
|
|
| Tarray(ty, n) -> n::(bounds_list ty)
|
|
|
|
| _ -> []
|
|
|
|
|
|
|
|
(** @return the [var_dec] object corresponding to the name [n]
|
|
|
|
in a list of [var_dec]. *)
|
|
|
|
let rec vd_find n = function
|
2011-04-20 19:23:35 +02:00
|
|
|
| [] -> (*Format.eprintf "Not found var %s@." (name n);*) raise Not_found
|
2010-06-29 11:18:50 +02:00
|
|
|
| vd::l ->
|
2010-06-27 17:24:31 +02:00
|
|
|
if vd.v_ident = n then vd else vd_find n l
|
|
|
|
|
2010-06-29 11:18:50 +02:00
|
|
|
(** @return whether an object of name [n] belongs to
|
2010-06-27 17:24:31 +02:00
|
|
|
a list of [var_dec]. *)
|
|
|
|
let rec vd_mem n = function
|
|
|
|
| [] -> false
|
|
|
|
| vd::l -> vd.v_ident = n or (vd_mem n l)
|
|
|
|
|
2011-04-27 14:28:45 +02:00
|
|
|
|
2010-06-27 17:24:31 +02:00
|
|
|
(** @return whether [ty] corresponds to a record type. *)
|
|
|
|
let is_record_type ty = match ty with
|
|
|
|
| Tid n ->
|
2010-09-09 00:35:06 +02:00
|
|
|
(match Modules.find_type n with
|
2010-09-10 11:47:11 +02:00
|
|
|
| Tstruct _ -> true
|
2010-09-09 00:35:06 +02:00
|
|
|
| _ -> false)
|
2010-06-27 17:24:31 +02:00
|
|
|
| _ -> false
|
|
|
|
|
2010-06-30 10:22:31 +02:00
|
|
|
let is_op = function
|
2011-02-07 14:24:17 +01:00
|
|
|
| { qual = Pervasives; name = _ } -> true | _ -> false
|
2011-04-18 15:38:42 +02:00
|
|
|
|
2011-04-20 11:19:18 +02:00
|
|
|
let pat_from_dec_list decs =
|
|
|
|
Etuplepat (List.map (fun vd -> Evarpat vd.v_ident) decs)
|
|
|
|
|
|
|
|
let tuple_from_dec_list decs =
|
|
|
|
let aux vd =
|
2011-09-07 17:51:31 +02:00
|
|
|
mk_extvalue ~clock:vd.v_clock ~ty:vd.v_type ~linearity:vd.v_linearity (Wvar vd.v_ident)
|
2011-04-20 11:19:18 +02:00
|
|
|
in
|
|
|
|
Eapp(mk_app Earray, List.map aux decs, None)
|
|
|
|
|
2010-06-27 17:24:31 +02:00
|
|
|
module Vars =
|
|
|
|
struct
|
2010-07-14 02:31:31 +02:00
|
|
|
let add x acc = if List.mem x acc then acc else x :: acc
|
2010-06-27 17:24:31 +02:00
|
|
|
|
|
|
|
let rec vars_pat acc = function
|
|
|
|
| Evarpat x -> x :: acc
|
|
|
|
| Etuplepat pat_list -> List.fold_left vars_pat acc pat_list
|
|
|
|
|
2011-04-18 15:38:42 +02:00
|
|
|
let def acc { eq_lhs = pat } = vars_pat acc pat
|
|
|
|
|
2010-06-27 17:24:31 +02:00
|
|
|
let rec vars_ck acc = function
|
2010-09-14 09:39:02 +02:00
|
|
|
| Con(_, _, n) -> add n acc
|
2010-06-27 17:24:31 +02:00
|
|
|
| Cbase | Cvar { contents = Cindex _ } -> acc
|
|
|
|
| Cvar { contents = Clink ck } -> vars_ck acc ck
|
2011-06-09 14:38:58 +02:00
|
|
|
|
2011-05-09 19:32:12 +02:00
|
|
|
let rec vars_ct acc = function
|
|
|
|
| Ck ck -> vars_ck acc ck
|
|
|
|
| Cprod c_l -> List.fold_left vars_ct acc c_l
|
|
|
|
|
2011-04-18 15:38:42 +02:00
|
|
|
let read_extvalue read_funs (is_left, acc_init) w =
|
|
|
|
(* recursive call *)
|
|
|
|
let _,(_, acc) = Mls_mapfold.extvalue read_funs (is_left, acc_init) w in
|
|
|
|
let acc = match w.w_desc with
|
|
|
|
| Wvar x | Wwhen(_, _, x) ->
|
|
|
|
add x acc
|
|
|
|
| _ -> acc
|
|
|
|
in
|
|
|
|
w, (is_left, vars_ck acc w.w_ck)
|
|
|
|
|
2010-07-15 11:57:47 +02:00
|
|
|
let read_exp read_funs (is_left, acc_init) e =
|
2010-07-14 02:31:31 +02:00
|
|
|
(* recursive call *)
|
2010-07-15 11:57:47 +02:00
|
|
|
let _,(_, acc) = Mls_mapfold.exp read_funs (is_left, acc_init) e in
|
2011-04-14 18:06:54 +02:00
|
|
|
|
2010-07-14 02:31:31 +02:00
|
|
|
(* special cases *)
|
|
|
|
let acc = match e.e_desc with
|
2011-04-18 15:38:42 +02:00
|
|
|
| Emerge(x,_)
|
2011-03-21 17:22:03 +01:00
|
|
|
| Eapp(_, _, Some x) | Eiterator (_, _, _, _, _, Some x) ->
|
2010-07-14 02:31:31 +02:00
|
|
|
add x acc
|
|
|
|
| Efby(_, e) ->
|
2010-07-15 11:57:47 +02:00
|
|
|
if is_left then
|
|
|
|
(* do not consider variables to the right
|
|
|
|
of the fby, only clocks*)
|
2011-04-18 15:38:42 +02:00
|
|
|
vars_ck acc_init e.w_ck
|
2010-07-15 11:57:47 +02:00
|
|
|
else acc
|
2010-07-14 02:31:31 +02:00
|
|
|
| _ -> acc
|
2010-06-27 17:24:31 +02:00
|
|
|
in
|
2011-05-09 19:32:12 +02:00
|
|
|
e, (is_left, vars_ct acc e.e_ct)
|
2010-07-14 02:31:31 +02:00
|
|
|
|
|
|
|
let read_exp is_left acc e =
|
|
|
|
let _, (_, acc) =
|
|
|
|
Mls_mapfold.exp_it
|
2011-04-18 15:38:42 +02:00
|
|
|
{ Mls_mapfold.defaults with
|
|
|
|
Mls_mapfold.exp = read_exp;
|
|
|
|
Mls_mapfold.extvalue = read_extvalue }
|
|
|
|
(is_left, acc) e in
|
|
|
|
acc
|
|
|
|
|
|
|
|
let read_extvalue is_left acc e =
|
|
|
|
let _, (_, acc) =
|
|
|
|
Mls_mapfold.extvalue_it
|
|
|
|
{ Mls_mapfold.defaults with Mls_mapfold.extvalue = read_extvalue }
|
2010-07-14 02:31:31 +02:00
|
|
|
(is_left, acc) e in
|
|
|
|
acc
|
2010-06-27 17:24:31 +02:00
|
|
|
|
|
|
|
let rec remove x = function
|
|
|
|
| [] -> []
|
|
|
|
| y :: l -> if x = y then l else y :: remove x l
|
|
|
|
|
2010-07-14 02:31:31 +02:00
|
|
|
let read is_left { eq_lhs = pat; eq_rhs = e } = match pat, e.e_desc with
|
|
|
|
| Evarpat(n), Efby(_, e1) ->
|
|
|
|
if is_left
|
2011-04-18 15:38:42 +02:00
|
|
|
then remove n (read_extvalue is_left [] e1)
|
|
|
|
else read_extvalue is_left [] e1
|
2010-07-14 02:31:31 +02:00
|
|
|
| _ -> read_exp is_left [] e
|
2010-06-27 17:24:31 +02:00
|
|
|
|
|
|
|
let antidep { eq_rhs = e } =
|
|
|
|
match e.e_desc with Efby _ -> true | _ -> false
|
|
|
|
|
2011-05-09 19:32:12 +02:00
|
|
|
let clock { eq_rhs = e } = e.e_base_ck
|
2010-06-27 17:24:31 +02:00
|
|
|
|
|
|
|
let head ck =
|
|
|
|
let rec headrec ck l =
|
|
|
|
match ck with
|
2011-05-23 09:24:57 +02:00
|
|
|
| Cbase
|
|
|
|
| Cvar { contents = Cindex _ } -> l
|
2010-09-14 09:39:02 +02:00
|
|
|
| Con(ck, _, n) -> headrec ck (n :: l)
|
2010-06-29 11:18:50 +02:00
|
|
|
| Cvar { contents = Clink ck } -> headrec ck l
|
2010-06-27 17:24:31 +02:00
|
|
|
in
|
2010-06-29 11:18:50 +02:00
|
|
|
headrec ck []
|
2010-06-27 17:24:31 +02:00
|
|
|
|
2010-06-29 11:18:50 +02:00
|
|
|
(** Returns a list of memory vars (x in x = v fby e)
|
2010-06-27 17:24:31 +02:00
|
|
|
appearing in an equation. *)
|
2010-07-14 02:31:31 +02:00
|
|
|
let memory_vars ({ eq_lhs = _; eq_rhs = e } as eq) = match e.e_desc with
|
|
|
|
| Efby(_, _) -> def [] eq
|
|
|
|
| _ -> []
|
2011-09-07 14:14:59 +02:00
|
|
|
|
|
|
|
let linear_read e =
|
|
|
|
let extvalue funs acc w = match w.w_desc with
|
|
|
|
| Wvar x ->
|
|
|
|
let w, acc = Mls_mapfold.extvalue funs acc w in
|
|
|
|
let acc =
|
|
|
|
(match w.w_linearity with
|
|
|
|
| Linearity.Lat _ -> add x acc
|
|
|
|
| _ -> acc)
|
|
|
|
in
|
|
|
|
w, acc
|
|
|
|
| _ -> Mls_mapfold.extvalue funs acc w
|
|
|
|
in
|
|
|
|
let funs = { Mls_mapfold.defaults with extvalue = extvalue } in
|
|
|
|
let _, acc = Mls_mapfold.exp_it funs [] e in
|
|
|
|
acc
|
2010-06-27 17:24:31 +02:00
|
|
|
end
|
|
|
|
|
2011-01-24 16:07:26 +01:00
|
|
|
(* Assumes normal form, all fby are solo rhs *)
|
2010-07-16 09:58:56 +02:00
|
|
|
let node_memory_vars n =
|
2010-09-14 09:39:02 +02:00
|
|
|
let eq _ acc ({ eq_lhs = pat; eq_rhs = e } as eq) =
|
2011-04-20 11:19:18 +02:00
|
|
|
match pat, e.e_desc with
|
|
|
|
| Evarpat x, Efby(_, _) ->
|
|
|
|
let acc = (x, e.e_ty) :: acc in
|
|
|
|
eq, acc
|
|
|
|
| _, _ -> eq, acc
|
2010-07-16 09:58:56 +02:00
|
|
|
in
|
|
|
|
let funs = { Mls_mapfold.defaults with eq = eq } in
|
|
|
|
let _, acc = node_dec_it funs [] n in
|
|
|
|
acc
|
2010-06-27 17:24:31 +02:00
|
|
|
|
|
|
|
(* data-flow dependences. pre-dependences are discarded *)
|
|
|
|
module DataFlowDep = Dep.Make
|
|
|
|
(struct
|
|
|
|
type equation = eq
|
|
|
|
let read eq = Vars.read true eq
|
2011-09-07 14:14:59 +02:00
|
|
|
let linear_read eq = Vars.linear_read eq.eq_rhs
|
2010-06-27 17:24:31 +02:00
|
|
|
let def = Vars.def
|
|
|
|
let antidep = Vars.antidep
|
|
|
|
end)
|
|
|
|
|
|
|
|
(* all dependences between variables *)
|
|
|
|
module AllDep = Dep.Make
|
|
|
|
(struct
|
|
|
|
type equation = eq
|
|
|
|
let read eq = Vars.read false eq
|
2011-09-07 14:14:59 +02:00
|
|
|
let linear_read eq = Vars.linear_read eq.eq_rhs
|
2010-06-27 17:24:31 +02:00
|
|
|
let def = Vars.def
|
2010-09-14 09:39:02 +02:00
|
|
|
let antidep _ = false
|
2010-06-27 17:24:31 +02:00
|
|
|
end)
|
2010-09-30 21:44:18 +02:00
|
|
|
|
|
|
|
let eq_find id = List.find (fun eq -> List.mem id (Vars.def [] eq))
|
2011-04-18 15:38:42 +02:00
|
|
|
|
2011-05-09 19:32:12 +02:00
|
|
|
let ident_list_of_pat pat =
|
|
|
|
let rec f acc pat = match pat with
|
|
|
|
| Evarpat id -> id::acc
|
2011-05-18 09:59:21 +02:00
|
|
|
| Etuplepat pat_l -> List.fold_left f acc pat_l
|
2011-05-09 19:32:12 +02:00
|
|
|
in
|
2011-05-18 09:59:21 +02:00
|
|
|
List.rev (f [] pat)
|
2011-10-03 11:43:50 +02:00
|
|
|
|
|
|
|
let remove_eqs_from_node nd ids =
|
|
|
|
let walk_vd vd vd_list = if IdentSet.mem vd.v_ident ids then vd_list else vd :: vd_list in
|
|
|
|
let walk_eq eq eq_list =
|
|
|
|
let defs = ident_list_of_pat eq.eq_lhs in
|
|
|
|
if List.for_all (fun v -> IdentSet.mem v ids) defs then eq_list else eq :: eq_list
|
|
|
|
in
|
|
|
|
let vd_list = List.fold_right walk_vd nd.n_local [] in
|
|
|
|
let eq_list = List.fold_right walk_eq nd.n_equs [] in
|
|
|
|
{ nd with n_local = vd_list; n_equs = eq_list; }
|