diff --git a/Makefile b/Makefile index df88731e0ec84f0b81930c0d914adb420c615be2..3ca5f4ca0ed5bb76c425d90379d93bcf1d3bcfd4 100644 --- a/Makefile +++ b/Makefile @@ -34,6 +34,20 @@ ifeq ($(HOSTTYPE),cygwin) CFLAGS=-mno-cygwin endif +SOC_SOURCES = \ + $(OBJDIR)/soc.ml \ + $(OBJDIR)/socUtils.mli \ + $(OBJDIR)/socUtils.ml \ + $(OBJDIR)/socPredef.mli \ + $(OBJDIR)/socPredef.ml \ + $(OBJDIR)/toposort.mli \ + $(OBJDIR)/toposort.ml \ + $(OBJDIR)/actionsDeps.mli \ + $(OBJDIR)/actionsDeps.ml \ + $(OBJDIR)/lic2soc.mli \ + $(OBJDIR)/lic2soc.ml + + SOURCES = \ $(OBJDIR)/version.ml \ $(OBJDIR)/verbose.mli \ @@ -69,6 +83,7 @@ SOURCES = \ $(OBJDIR)/licDump.ml \ $(OBJDIR)/licPrg.mli \ $(OBJDIR)/licPrg.ml \ + $(SOC_SOURCES) \ $(OBJDIR)/unifyType.mli \ $(OBJDIR)/unifyType.ml \ $(OBJDIR)/unifyClock.mli \ diff --git a/src/actionsDeps.ml b/src/actionsDeps.ml new file mode 100644 index 0000000000000000000000000000000000000000..316877e259309b0a398d7f0d5998b33bdab40a05 --- /dev/null +++ b/src/actionsDeps.ml @@ -0,0 +1,214 @@ +(** Time-stamp: <modified the 21/02/2013 (at 11:12) by Erwan Jahier> *) + + +(* exported *) +type inputs = Soc.var_expr list +type outputs = Soc.var_expr list +type action = Lic.clock * inputs * outputs * Soc.atomic_operation * Lxm.t + + +(*********************************************************************************) +let string_of_action: (action -> string) = + fun (c, i, o, p, lxm) -> + (* Version surchargée de Soc.string_of_operation pour afficher les "=" *) + let string_of_operation = function + | Soc.Assign -> "" + | op -> SocUtils.string_of_operation op + in + let string_of_params p = String.concat ", " (List.map SocUtils.string_of_filter p) in + if o = [] then + Format.sprintf "%s(%s)" + (string_of_operation p) + (string_of_params i) + else + Format.sprintf "%s = %s(%s) on %s" + (string_of_params o) + (string_of_operation p) + (string_of_params i) + (Lic.string_of_clock c) + +let string_of_action_simple: (action -> string) = + fun (c, i, o, p,_) -> + (* Version surchargée de SocUtils.string_of_operation : l'objectif est d'afficher, + en cas de cycle combinatoire, un message d'erreur que parle le plus possible + à l'utilisateur qui a programmé en V6... Pour cela le mieux (je pense) est + simplement de rendre la variable sur laquelle porte +*) + let string_of_operation = function + | Soc.Assign -> "" + | op -> SocUtils.string_of_operation op + in + let string_of_params p = String.concat ", " (List.map SocUtils.string_of_filter p) in + if o = [] then + Format.sprintf "%s(%s)" + (string_of_operation p) + (string_of_params i) + else + Format.sprintf "%s = %s(%s)" + (string_of_params o) + (string_of_operation p) + (string_of_params i) + + +(*********************************************************************************) +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 *) +(* exported *) +type t = Actions.t MapAction.t + +(* exported *) +let empty: t = MapAction.empty + +(* exported *) +let (find_deps: t -> action -> action list) = + fun m a -> + try Actions.elements (MapAction.find a m) with Not_found -> [] + +(*********************************************************************************) +(** Ajoute une liste de dépendances à une action. *) +let add_deps: t -> action -> action list -> t = fun m a -> function + | [] -> m + | al -> + 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 + MapAction.add a actions m + +(* exported *) +let (concat: t -> t -> t) = + fun m1 m2 -> + MapAction.fold (fun key value m -> add_deps m key (Actions.elements value)) m1 m2 + +(*********************************************************************************) +(* exported *) +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 OrderedSocVar = struct + type t = Soc.var_expr + let compare = compare +end +module VarMap = Map.Make(OrderedSocVar) + +(** A Data structure that maps a Soc.var_expr to all the + actions that use that variable in outputs. + + It is used to know which actions impact which outputs. +*) +type var2actions_tbl = Actions.t VarMap.t + + +(** TODO jb: On a peut-être pas besoin de stocker les actions dans des set, il + devrait n'y avoir qu'une seule action pour chaque sortie en théorie (?) +*) +let (get_var2actions_tbl : action list -> var2actions_tbl) = + fun al -> + let (tabulate_action : var2actions_tbl -> action -> var2actions_tbl) = + fun tbl action -> + let _, _, outputs, _, lxm = action in + let (tabulate_output:var2actions_tbl -> Soc.var_expr -> var2actions_tbl) = + fun tbl output -> + let tabulate_action = try VarMap.find output tbl + with Not_found -> Actions.empty + in + VarMap.add output (Actions.add action tabulate_action) tbl + in + List.fold_left tabulate_output tbl outputs + in + List.fold_left tabulate_action VarMap.empty al + + +(** Returns the actions that depends on a set of vars. + + [find_input_deps 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 nécessite + d'avoir initialisé la structure parente. +*) +let rec (find_input_deps: Soc.var_expr list -> var2actions_tbl -> action list) = + fun input_vars tbl -> + let find_deps i = + try Actions.elements (VarMap.find i tbl) + with Not_found -> [] + in + List.flatten (List.map find_deps input_vars) + +(*********************************************************************************) + +(* exported *) +let build_data_deps_from_actions: t -> action list -> t = + fun deps al -> + let tbl = get_var2actions_tbl al in + let deps = + List.fold_left + (fun acc_deps action -> + let (_, inputs, _, _,_) = action in + let deps = find_input_deps inputs tbl in + if deps = [] then acc_deps else add_deps acc_deps action deps + ) + deps + al + in + deps + + + +(*********************************************************************************) +(*********************************************************************************) +(*********************************************************************************) + +(* Some Printers to ease the debugging *) +(** Printer pour [Actions.t] *) +let string_of_actions: Actions.t -> string = fun s -> + let to_string a acc = + acc ^ (string_of_action a) ^ " ; " + in + "Actions(" ^ (Actions.fold to_string s "") ^ ")" + +let to_string: t -> string = fun m -> + let to_string key value acc = + let entry = + Format.sprintf "%s \n depends on « %s »" + (string_of_action key) + (string_of_actions value) + in + acc ^ entry ^ "\n" + in + "ActionsDeps{\n" ^ (MapAction.fold to_string m "") ^ "}" + +let string_of_var2actions_tbl: var2actions_tbl -> string = + fun s -> + let to_string key value acc = + let entry = Format.sprintf "%s => %s" (SocUtils.string_of_filter key) + (string_of_actions value) + in + acc ^ entry ^ "\n" + in + "FilterAction{\n" ^ (VarMap.fold to_string s "") ^ "}" + +(*********************************************************************************) diff --git a/src/actionsDeps.mli b/src/actionsDeps.mli new file mode 100644 index 0000000000000000000000000000000000000000..696133601a8ece664d8bd13cb0ed02c3500d7ba2 --- /dev/null +++ b/src/actionsDeps.mli @@ -0,0 +1,48 @@ +(** Time-stamp: <modified the 21/02/2013 (at 11:11) by Erwan Jahier> *) + +(** Compute dependencies between actions *) + + +type t + +val empty : t + +(** Linear in the size of the first parameter *) +val concat: t -> t -> t + + +(** An action is an intermediary data type that is used to translate expressions + into [Soc.gao]. It is basically a clocked Soc.atomic_operation with arguments. + + The idea is that each expression is translated into one or several actions. + And those clocks are then translated into guards, so that each action is + translated into a gao. + + A more natural Module to define that type in would have been Soc, but that + module is meant to be shared with other front-ends (e.g., lucid-synchrone), + and I prefer that module not to depend on + - such a cutting (expr -> action -> gao) + - The [Eff.clock] name (could have been a module parameter though). + *) + +type inputs = Soc.var_expr list +type outputs = Soc.var_expr list +type action = Lic.clock * inputs * outputs * Soc.atomic_operation * Lxm.t + +val string_of_action_simple: action -> string + + +(** Compute the action dependencies that comes from the I/O. + + Construit des dépendances entre les actions en reliant les entrées et + les sorties de ces actions. +*) +val build_data_deps_from_actions: t -> action list -> t + +(** Use the dependency constraints that come from the SOC (e.g., 'get' before 'set' + in memory SOC). +*) +val generate_deps_from_step_policy: Soc.precedence list -> (string * action) list -> t + +(** Returns the list of actions that depends on the action in argument. *) +val find_deps: t -> action -> action list diff --git a/src/compile.ml b/src/compile.ml index ca8b7a79f5583fa465ace814bf0a93e5dc3f0a23..0c47a64da0df262920552573936f8b667b22c247 100644 --- a/src/compile.ml +++ b/src/compile.ml @@ -1,4 +1,4 @@ -(* Time-stamp: <modified the 13/02/2013 (at 14:56) by Erwan Jahier> *) +(* Time-stamp: <modified the 25/02/2013 (at 18:13) by Erwan Jahier> *) open Lxm open Errors @@ -68,5 +68,11 @@ let (doit : AstV6.pack_or_model list -> Ident.idref option -> LicPrg.t) = (* Currently only works in this mode *) if !Global.ec then L2lCheckLoops.doit zelic; L2lCheckOutputs.doit zelic; + + (* XXX just to see if it compiles *) +(* let zesoc = Lic2soc.f zelic in *) + +(* SocUtils.output true "xxx" zesoc; *) + zelic diff --git a/src/errors.ml b/src/errors.ml index 3f1ff667c6c87a01cda9297eb2bd3761acab494b..9179d3f889f1ab485f7c24211f77eb8b9a34e36a 100644 --- a/src/errors.ml +++ b/src/errors.ml @@ -1,4 +1,4 @@ -(* Time-stamp: <modified the 12/02/2013 (at 18:23) by Erwan Jahier> *) +(* Time-stamp: <modified the 25/02/2013 (at 17:09) by Erwan Jahier> *) (** *) diff --git a/src/lic.ml b/src/lic.ml index 83516cfbf77e538033637ef37e87249613c21ac5..b8f404512766a4cbce90fecf23e8b0676ced2dff 100644 --- a/src/lic.ml +++ b/src/lic.ml @@ -1,4 +1,4 @@ -(* Time-stamp: <modified the 13/02/2013 (at 15:58) by Erwan Jahier> *) +(* Time-stamp: <modified the 20/02/2013 (at 11:19) by Erwan Jahier> *) (** Define the Data Structure representing Compiled programs. *) @@ -163,6 +163,8 @@ and val_exp_core = (by_name_op srcflagged * (Ident.t srcflagged * val_exp) list) | Merge of Ident.t srcflagged * (const srcflagged * val_exp) list + + and by_name_op = | STRUCT of Ident.long | STRUCT_with of Ident.long * Ident.t (* XXX devrait etre une expression !!! *) @@ -420,8 +422,7 @@ let ident_of_type = function | Struct_type_eff (id, _) -> id | TypeVar Any -> Ident.out_of_pack "any" | (TypeVar AnyNum) -> Ident.out_of_pack "anynum" - | _ -> assert false - + | Array_type_eff(_,_) -> assert false (****************************************************************************) (* Utilitaires liés aux node_key *) diff --git a/src/lic2soc.ml b/src/lic2soc.ml new file mode 100644 index 0000000000000000000000000000000000000000..8abe38f30bd85ec1c0b8f31c0622fb3f3aafdc0f --- /dev/null +++ b/src/lic2soc.ml @@ -0,0 +1,628 @@ +(** Time-stamp: <modified the 25/02/2013 (at 18:09) by Erwan Jahier> *) + +open Lxm +open Lic + +type action = ActionsDeps.action + +(* Raised when a soc that haven't been translated yet is used in + another soc during the translation *) +exception Undef_soc of Lic.node_key + +(*********************************************************************************) +(** Informations liées au contexte de traduction. *) +type ctx = { + prg : LicPrg.t; + last_temp_var : int; + last_mem : int; + locals : Soc.var list; +} + +let create_context: (LicPrg.t -> ctx) = + fun prg -> + { + prg = prg; + last_temp_var = 0; + last_mem = 0; + locals = []; + } + +let rec lic_to_soc_type: (Lic.type_ -> Soc.var_type) = + function + | Lic.Bool_type_eff -> Soc.Bool + | Lic.Int_type_eff -> Soc.Int + | Lic.Real_type_eff -> Soc.Real + | Lic.External_type_eff s -> Soc.Extern (Ident.string_of_long s) + | Lic.Enum_type_eff (id, l) -> ( + Soc.Enum(Ident.string_of_long id, List.map Ident.string_of_long l) + ) + | Lic.Struct_type_eff (id, fl) -> ( + let trans_field (id,(t,_)) = (* fde_value is ignored. Good idea? *) + Ident.to_string id, lic_to_soc_type t + in + let id = Ident.string_of_long id in + Soc.Struct(id, List.map trans_field fl) + ) + | Lic.Array_type_eff(ty,i) -> Soc.Array(lic_to_soc_type ty,i) + | Lic.Abstract_type_eff (id, _) -> assert false + | Lic.TypeVar Lic.Any -> assert false + | Lic.TypeVar Lic.AnyNum -> assert false + + +(*********************************************************************************) +(** Renomme une variable définie par l'utilisateur. + + On veut éviter de créer des variables temporaires portant le même nom que + celles définies par l'utilisateur. Donc on renomme simplement celles de + l'utilisateur, c'est le plus simple. + +XXX obselete ? +Mieux vaudrait utiliser le meme mechanisme que celui utilisé +actuellement lors des l2l*.ml +??? +*) +let rename_user_var: (string -> string) = fun s -> + let prefix = "_" in + let suffix = "" in + prefix ^ s ^ suffix + +let is_predefined_const: string -> Lic.type_ option = + function + | "true" | "false" -> Some Lic.Bool_type_eff + | _ -> None + +(*********************************************************************************) +(* Returns the list of indexes represented by the slice *) +let (slice_info_to_index_list : Lic.slice_info -> int list) = + fun si -> + let (f,l,s) = (si.Lic.se_first, si.Lic.se_last, si.Lic.se_step) in + let rec aux f = + if f>l && s > 0 || f<l && s <0 then [] else + f::(aux (f+s)) + in + aux f + +let rec get_leaf: (LicPrg.t -> Lic.val_exp -> Soc.var_expr list option) = + fun licprg val_exp -> + let v = val_exp.Lic.ve_core in + let type_ = val_exp.Lic.ve_typ in + match v with + | Lic.CallByNameLic(by_name_op_flg,fl) -> assert false + | Lic.Merge(c_flg, cl) -> assert false + | Lic.CallByPosLic (by_pos_op_flg, val_exp_list) -> ( + match by_pos_op_flg.it with + | Lic.PREDEF_CALL _ -> assert false (* todo *) + | Lic.VAR_REF name -> + let type_ = (List.hd type_) in + let translation = + match is_predefined_const name with + | Some type_ -> Soc.Const(name, lic_to_soc_type type_) + | None -> Soc.Var(rename_user_var name, lic_to_soc_type type_) + in + Some [translation] + | Lic.CONST_REF l -> ( + let type_ = lic_to_soc_type (List.hd type_) in + Some [Soc.Const(Ident.string_of_long l, type_)] + ) + | Lic.STRUCT_ACCESS(field) -> ( + let expr = match val_exp_list with [e] -> e | _ -> assert false in + let type_ = lic_to_soc_type (List.hd type_) in + let filter_expr = match get_leaf licprg expr with + | Some [f] -> f + | None -> assert false + | _ -> assert false + in + Some [Soc.Field(filter_expr, field, type_)] + ) + | Lic.ARRAY_ACCES i -> ( + let expr = match val_exp_list with [e] -> e | _ -> assert false in + let type_ = lic_to_soc_type (List.hd type_) in + let filter_expr = match get_leaf licprg expr with + | Some [f] -> f + | None -> assert false (* should not happen, since the expression should be a leaf *) + | _ -> assert false (* We should get only ONE filter, otherwise it doesn't make any + sense *) + in + Some [Soc.Index(filter_expr, i, type_)] + ) + | Lic.TUPLE -> ( + let var_values = List.map (get_leaf licprg) val_exp_list in + let del_some = function | None -> assert false | Some x -> x in + Some (List.flatten (List.map del_some var_values)) + ) + | Lic.ARRAY_SLICE si -> ( + let id = match val_exp_list with + | [{Lic.ve_core=Lic.CallByPosLic({it=Lic.VAR_REF id},[])}] -> id + | _ -> assert false + in + let type_elt_ref,type_ref = + match type_ with + | [Lic.Array_type_eff(t,i)] -> + let t_soc = lic_to_soc_type t in + t_soc, Soc.Array(t_soc,i) + | _ -> assert false (* should not occur *) + in + let index_list = slice_info_to_index_list si in + let exploded_array = + (* val_exp is a var ident (t) of type array; we want to gen the list + t[i1], ...,t[in], where the index are specified by the slice + *) + List.map + (fun i -> Soc.Index(Soc.Const(id, type_ref), i, type_elt_ref)) + index_list + in + Some(exploded_array) + ) + | Lic.CALL _ + | Lic.PRE + | Lic.ARROW + | Lic.FBY + | Lic.CURRENT + | Lic.WHEN(_) + | Lic.CONCAT + | Lic.HAT _ + | Lic.ARRAY + -> None + ) +(** Traduction d'une partie gauche d'équation en filtre d'accès soc. *) +let rec filter_of_left_part: (LicPrg.t -> Lic.left -> Soc.var_expr list) = + fun licprg lp -> + let type_ = Lic.type_of_left lp in + match lp with + | Lic.LeftVarLic (vi, _lxm) -> ( + [Soc.Var (rename_user_var vi.Lic.var_name_eff, lic_to_soc_type vi.Lic.var_type_eff)] + ) + | Lic.LeftFieldLic(lp,field,t) -> ( + let lpl = filter_of_left_part licprg lp in + List.map (fun lp -> Soc.Field(lp, field, lic_to_soc_type t)) lpl + ) + | Lic.LeftArrayLic(lp,index,t) -> ( + let lpl = filter_of_left_part licprg lp in + List.map (fun lp -> Soc.Index(lp, index, lic_to_soc_type t (* type_ ? *))) lpl + ) + | Lic.LeftSliceLic(lp,si,t) -> ( + (* we expand left part slices *) + let lpl = filter_of_left_part licprg lp in + let index_list = slice_info_to_index_list si in + List.flatten (List.map ( + fun lp -> List.map (fun index -> Soc.Index(lp, index, lic_to_soc_type t)) index_list) lpl) + ) + +(*********************************************************************************) +let rec (gao_of_action: action -> Soc.gao) = + fun (ck, il, ol, op, lxm) -> + let rec unpack_clock = function + | Lic.BaseLic -> Soc.Call (ol, op, il) + | Lic.ClockVar i -> assert false + | Lic.On((c, value), inner_clock) -> +(* let inner_clock = match inner_clock_opt with *) +(* | Some x -> x *) +(* | None -> *) +(* (* TODO? Retreive the clock of c *) *) +(* Errors.internal lxm; *) +(* assert false *) +(* in *) + Soc.Case (Ident.string_of_idref c, [value, [unpack_clock inner_clock]] ) + in + unpack_clock ck + +(* Construit une méthode à partir des informations données *) +let build_meth: Lxm.t -> string -> Lic.node_exp -> Soc.var list -> + action list -> Soc.step_method = + fun lxm name node locals actions -> + (* Converti les entrées/sorties d'un noeud en index + d'entrées/sorties du composant *) + let convert_node_interface = fun l -> + fst (List.fold_left (fun (a, i) _ -> a @ [i], i+1) ([], 0) l) + in + { + Soc.socm_name = name; + Soc.socm_inputs = convert_node_interface node.Lic.inlist_eff; + Soc.socm_outputs = convert_node_interface node.Lic.outlist_eff; + Soc.socm_impl = + Some (locals, List.map gao_of_action actions) + } + +let (lic_to_soc_var : Lic.var_info -> Soc.var) = + fun vi -> + vi.Lic.var_name_eff, lic_to_soc_type vi.Lic.var_type_eff + +let component_profile_of_node: Lic.node_exp -> Soc.var list * Soc.var list = + fun n -> + let inputs = List.map lic_to_soc_var n.Lic.inlist_eff in + let outputs = List.map lic_to_soc_var n.Lic.outlist_eff in + inputs, outputs + + +let (val_exp_to_filter: LicPrg.t -> Lic.val_exp -> Soc.var_expr) = + fun licprg val_exp -> + let v = val_exp.Lic.ve_core in + let type_ = val_exp.Lic.ve_typ in + match v with + | CallByNameLic(by_name_op_flg,fl) -> assert false + | Merge(c_flg, cl) -> assert false + | CallByPosLic (by_pos_op_flg, val_exp_list) -> ( + match by_pos_op_flg.it with + | VAR_REF name -> + let type_ = (List.hd type_) in + let translation = + match is_predefined_const name with + | Some type_ -> Soc.Const(name, lic_to_soc_type type_) + | None -> Soc.Var(rename_user_var name, lic_to_soc_type type_) + in + translation + | CONST_REF l -> ( + let type_ = lic_to_soc_type (List.hd type_) in + Soc.Const(Ident.string_of_long l, type_) + ) + | STRUCT_ACCESS(field) -> ( + let expr = match val_exp_list with [e] -> e | _ -> assert false in + let type_ = match type_ with [t] -> lic_to_soc_type t | _ -> assert false in + let filter_expr = match get_leaf licprg expr with + | Some [f] -> f + | None -> assert false + | _ -> assert false + in + Soc.Field(filter_expr, field, type_) + ) + | ARRAY_ACCES i -> ( + let expr = match val_exp_list with [e] -> e | _ -> assert false in + let type_ = lic_to_soc_type (List.hd type_) in + let filter_expr = match get_leaf licprg expr with + | Some [f] -> f + | None -> assert false + | _ -> assert false + in + Soc.Index(filter_expr, i, type_) + ) + | PREDEF_CALL _ + | CALL _ + | PRE + | ARROW + | FBY + | CURRENT + | WHEN(_) + | TUPLE + | CONCAT + | HAT _ + | ARRAY + | ARRAY_SLICE _ -> + let lxm = by_pos_op_flg.src in + let msg = (Lxm.details lxm) ^ + ": only one operator per equation is allowed.\n" + in + raise (Errors.Global_error msg) + ) + +(*********************************************************************************) +type memory = Soc.memory * action list (* mémoire + initialisation *) + +(** Créé une opération à partir d'un nom de méthode d'un composant. *) +let component_meth_to_operation: + Soc.component -> string -> memory option -> Soc.atomic_operation = + fun comp func_name -> function + | None -> + let (node_name,_,_) = comp.Soc.socc_key in + Soc.Procedure (node_name ^ "_" ^ func_name) + | Some (m, _) -> Soc.Method(m, func_name) + +(* Créé une action concernant un appel de procédure ou de méthode. *) +let (action_of_method: Lxm.t -> Soc.component -> Lic.clock -> Soc.var_expr list -> + Soc.var_expr list -> memory option -> Soc.step_method -> action) = + fun lxm c clk il ol mem m -> + let nth i l = + try List.nth l i + with _ -> + print_string ( + "\n*** Cannot get the " ^ (string_of_int (i+1)) ^ + "th element of a list of size " ^ (string_of_int (List.length l))^"\n"); + flush stdout; + assert false + in + let inputs = List.map (fun i -> nth i il) m.Soc.socm_inputs in + let outputs = List.map (fun i -> nth i ol) m.Soc.socm_outputs in + let call_action = component_meth_to_operation c m.Soc.socm_name mem in + (clk, inputs, outputs, call_action, lxm) + +(** Créé un nouveau nom pour une mémoire. *) +let create_new_memory: (ctx -> ctx * string) = fun ctx -> + let prefix = "m" in + let suffix = "" in + let make id = Format.sprintf "%s%d%s" prefix id suffix in + let new_ctx = {ctx with last_mem = ctx.last_mem + 1 } in + new_ctx, make new_ctx.last_mem + + (** Créé une nouvelle mémoire pour être utilisée dans un composant. + + Pendant la traduction d'un opérateur, on s'apercoit que cet opérateur + dispose d'une mémoire. + Il faut donc qu'on créé une mémoire représentant ce composant (issue de la + traduction de cet opérateur), afin de garder son état dans le composant + résultant de ce noeud. *) +let create_memory_from_component: (ctx -> Soc.component -> ctx * Soc.memory) = + fun ctx c -> + let ctx, mem_name = create_new_memory ctx in + ctx, Soc.CompMem(mem_name, c.Soc.socc_key) + +let (make_memory : Lxm.t -> Lic.clock -> ctx -> Soc.component -> + Soc.var_expr list -> Soc.var_expr list -> ctx * memory option) = + fun lxm clk ctx component inputs lpl -> + match component.Soc.socc_memories with + | [] -> ctx, None + | _ -> + let ctx, m = create_memory_from_component ctx component in + let init_actions = match component.Soc.socc_init with + | Some i -> [action_of_method lxm component clk inputs lpl (Some (m, [])) i] + | None -> assert false + (* memory component do have a memory... *) + in + ctx, Some(m, init_actions) + +(*********************************************************************************) +(** Transforme une expression en action(s), et retourne la liste des variables + créées pour stocker le résultat du calcul de cette expression. + + Ces nouvelles variables serviront d'entrées pour l'expression parente. +*) +type e2a_acc = ctx * action list * Soc.var_expr list * memory list * ActionsDeps.t + +module NkMap = Map.Make( + struct + type t = Lic.node_key + let compare = compare + end +) + + +type comp_tbl = Soc.component NkMap.t + +let rec (actions_of_expression_acc: Lxm.t -> comp_tbl -> + Lic.clock -> Soc.var_expr list -> e2a_acc -> Lic.val_exp -> e2a_acc) = + fun lxm comp_tbl clk lpl acc expr -> + let (ctx, al, iol, ml, deps) = acc in + match get_leaf ctx.prg expr with + | Some names -> + (* expr est déjà une feuille (un ident ou une constante), RAF. *) + let action = clk, names, lpl, Soc.Assign,lxm in + (ctx, action::al, iol@names, ml, deps) + | None -> ( + let v = expr.Lic.ve_core in + match v with + | CallByNameLic(by_name_op_flg,fl) -> ( + (* Pas de composant pour les structures non plus. On se + contente d'éclater la structure en autant d'égalités + que nécessaire. *) + let lxm = by_name_op_flg.src in + let filter_to_field filter field ftype = + let ftype = match ftype with [x] -> x | _ -> assert false in + let filter = match filter with [x] -> x | _ -> assert false in + Soc.Field(filter, field, lic_to_soc_type ftype) + in + let actions = + List.map + (fun (fn, fv) -> + let ft = fv.ve_typ in + let fv = val_exp_to_filter ctx.prg fv in + (clk, + [fv], + [filter_to_field lpl fn.it ft], + Soc.Assign, + lxm + ) + ) + fl + in + ctx, actions@al, iol, ml, deps + ) + | Merge(c_flg, cl) -> assert false + | CallByPosLic (by_pos_op_flg, val_exp_list) -> ( + match by_pos_op_flg.it with + (* handled via get_leaf *) + | Lic.ARRAY_SLICE _ | Lic.VAR_REF _ | Lic.CONST_REF _ + | Lic.ARRAY_ACCES _ | Lic.STRUCT_ACCESS _ | Lic.TUPLE + -> assert false + | Lic.WHEN ck -> (assert false +(* (* L'opérateur when n'est pas un composant, il modifie *) +(* simplement les conditions de traitement des expressions. *) *) +(* let ctx, actions, inputs, mems, deps = *) +(* actions_of_expression_list comp_tbl clk lpl acc val_exp_list *) +(* in *) +(* let new_clock = *) +(* match ck with *) +(* | AstCore.Base -> CE_base *) +(* | AstCore.NamedClock {it=(cc,cv)} -> *) +(* CE_clock(name, value, clk) *) +(* Clocking.clock_eff_of_clock_exp ctx.prg ck *) +(* in *) +(* let ctx, outputs, actions_reclocked = *) +(* match actions with *) +(* | [] -> *) +(* (* L'expression du when est une feuille, on créé quand *) +(* même une nouvelle action pour clocker la feuille. *) *) +(* ctx, lpl, [new_clock, inputs, lpl, Soc.Assign, lxm] *) +(* | _ -> *) +(* ctx, inputs, *) +(* (* Remplacement de l'horloge des actions de l'expression *) +(* par la nouvelle horloge issue du `when`. *) *) +(* List.map *) +(* (fun (_, i,o,op,lxm) -> new_clock,i,o,op,lxm) *) +(* actions *) +(* in *) +(* ctx, actions_reclocked, outputs, mems, deps *) + ) + | PREDEF_CALL _ | CALL _ | PRE | ARROW | FBY | CURRENT | CONCAT + | HAT _ | ARRAY -> ( + (* build the component of "expr" *) + let component : Soc.component = + let args_types : Soc.var_type list = + List.map lic_to_soc_type + (List.flatten (List.map (fun ve -> ve.ve_typ) val_exp_list)) + in + match + SocPredef.component_interface_of_pos_op lxm by_pos_op_flg.it args_types + with + | SocPredef.SC soc -> soc + | SocPredef.Undef nk -> + try NkMap.find nk comp_tbl + with Not_found -> raise (Undef_soc nk) + in + (* Use that component to build the corresponding + - actions + - memories + - action dependances + *) + let inputs : Soc.var_expr list = + List.map (val_exp_to_filter ctx.prg) val_exp_list in + let ctx, mem_opt = make_memory lxm clk ctx component inputs lpl in + let actions = + let m2act = action_of_method lxm component clk inputs lpl mem_opt in + List.map m2act component.Soc.socc_step + in + let dependances : ActionsDeps.t = + let (prefixed_actions : (Soc.ident * action) list) = List.map2 + (fun s a -> s.Soc.socm_name,a) component.Soc.socc_step actions + in + ActionsDeps.generate_deps_from_step_policy + component.Soc.socc_precedences prefixed_actions + in + let mem = match mem_opt with Some m -> [m] | None -> [] in + (ctx, actions, lpl, mem, dependances) + ) + ) + ) + + + + +(** Traduction d'une liste d'expressions. *) +and (actions_of_expression_list: Lxm.t -> comp_tbl -> Lic.clock -> Soc.var_expr list -> + e2a_acc -> Lic.val_exp list -> e2a_acc) = + fun lxm comp_tbl clk lpl expr_list acc -> + List.fold_left (actions_of_expression_acc lxm comp_tbl clk lpl) expr_list acc + + +let (actions_of_expression : Lxm.t -> comp_tbl -> ctx -> Lic.clock -> Soc.var_expr list -> + Lic.val_exp -> e2a_acc) = + fun lxm comp_tbl ctx clk lpl expr -> + let acc0 = (ctx, [], [], [], ActionsDeps.empty) in + actions_of_expression_acc lxm comp_tbl clk lpl acc0 expr + +(*********************************************************************************) + (** Traduction d'une équation complète. + + On traduit d'abord l'expression de l'équation, puis on fait une égalité + entre les variables issues de la traduction de l'expression et la partie + gauche de l'équation. *) +let (actions_of_equation: Lxm.t -> comp_tbl -> ctx -> Lic.eq_info -> + ctx * action list * memory list * ActionsDeps.t) = + fun lxm comp_tbl ctx (left_part, right_part) -> + let clk = right_part.ve_clk in + let clk = match clk with [clk] -> clk | _ -> assert false in + let left_loc = List.map (filter_of_left_part ctx.prg) left_part in + let left_loc = List.flatten left_loc in + let ctx, actions, _, memories, deps = + actions_of_expression lxm comp_tbl ctx clk left_loc right_part + in +(* let final_action = clk_l, inputs, left_loc, Soc.Identity in *) +(* let deps = add deps final_action actions in *) + ctx, actions, memories, deps + + + +(*********************************************************************************) +(** Traduit un noeud en composant Soc. *) +let rec (component_of_node: LicPrg.t -> Lic.node_exp -> comp_tbl -> ctx * Soc.component) = + fun licprg node comp_tbl -> + match node.Lic.def_eff with + | ExternLic -> assert false + | MetaOpLic node_key -> assert false + | AbstractLic None -> assert false (* None if extern in the provide part *) + | AbstractLic (Some node_exp) -> component_of_node licprg node_exp comp_tbl + | BodyLic b -> + + let lxm = node.lxm in + let ctx = create_context licprg in + let ctx, actions, mems, deps = + (* on itere sur la liste des équations *) + List.fold_left + (fun (c, a, m, d) eq -> + let nc, na, nm, nd = actions_of_equation eq.src comp_tbl c eq.it in + nc, a @ na, m @ nm, (ActionsDeps.concat nd d) + ) + (ctx, [], [], ActionsDeps.empty) + b.eqs_eff + + in + (* Construction des dépendances entre les expressions *) + let all_deps = ActionsDeps.build_data_deps_from_actions deps actions in + let actions = + try Toposort.f + ActionsDeps.string_of_action_simple actions (ActionsDeps.find_deps all_deps) + with Toposort.DependencyCycle(x,l) -> + let msg = "A combinational cycle been detected "^ + (Lxm.details lxm)^": \n "^x^"\n "^(String.concat "\n " l) + in + raise (Errors.Global_error msg) + in + let (locals: Soc.var list) = + match node.Lic.loclist_eff with + | None -> [] + | Some l -> List.map (lic_to_soc_var) l + in + let meth = build_meth lxm "step" node (locals @ ctx.locals) actions in + let profile = component_profile_of_node node in + let memories, init_actions = List.split mems in + let init_meth = match init_actions with + | [] -> None + | actions -> Some (build_meth lxm "init" node [] (List.flatten actions)) + in + let io_list = node.Lic.inlist_eff @ node.Lic.outlist_eff in + let io_type = List.map (fun vi -> lic_to_soc_type vi.var_type_eff) io_list in + let comp = { + Soc.socc_key = fst (fst node.Lic.node_key_eff), io_type, None; + Soc.socc_profile = profile; + Soc.socc_memories = memories; + Soc.socc_init = init_meth; + Soc.socc_step = [meth]; + Soc.socc_precedences = []; (* TODO pour l'instant, on ne gère qu'une + seule méthode *) + } + in + ctx, comp + + +(*********************************************************************************) +open Soc + +(* exported *) +let f: (LicPrg.t -> Soc.component list) = + fun prog -> + let rec (process_node:Lic.node_key -> Lic.node_exp -> comp_tbl -> comp_tbl) = + fun nk node acc_comp -> + let name = (* Lic.string_of_node_key *) nk in + if NkMap.mem name acc_comp then acc_comp else + (match SocPredef.of_node_key name with + | SocPredef.SC soc -> NkMap.add name soc acc_comp + | SocPredef.Undef nk -> + try + (match LicPrg.find_node prog nk with + | None -> assert false + | Some node_def -> + let _, soc = component_of_node prog node_def acc_comp in + NkMap.add name soc acc_comp + ) + with + | Undef_soc n_ukn -> + (* Il manque une dépendance, on essaie de + la traduire puis de retraduire le noeud courant. *) + (match LicPrg.find_node prog n_ukn with + | None -> assert false + | Some node_ukn -> + let comps = process_node n_ukn node_ukn acc_comp in + process_node name node comps + ) + ) + in + let soc_string_map = LicPrg.fold_nodes process_node prog NkMap.empty in + let soc_list = NkMap.fold (fun n soc acc -> soc::acc) soc_string_map [] in + soc_list diff --git a/src/lic2soc.mli b/src/lic2soc.mli new file mode 100644 index 0000000000000000000000000000000000000000..6f43c3fa46cb5fd7d616b781a010a5e56770d0a0 --- /dev/null +++ b/src/lic2soc.mli @@ -0,0 +1,3 @@ +(** Time-stamp: <modified the 20/02/2013 (at 10:50) by Erwan Jahier> *) + +val f: LicPrg.t -> Soc.component list diff --git a/src/soc.ml b/src/soc.ml new file mode 100644 index 0000000000000000000000000000000000000000..491cbdb61eedb3604da2e68ef63526e2efeedde1 --- /dev/null +++ b/src/soc.ml @@ -0,0 +1,64 @@ +(** Synchronous Object Component *) + +(* Just a string because : + - it's more ocamldebug-friendly + - Name clashing issues ougth to have been fixed before + *) +type ident = string + +type var_type = + | Bool | Int | Real + | Extern of ident + | Enum of (ident * ident list) + | Struct of ident * (ident * var_type) list + | Array of (var_type * int) + | Alpha of int + +type var = ident * var_type + +type component_key = + ident * + var_type list * (* I/O type list *) + (int * int * int) option (* to deal with slices (useful?) *) + +type memory = + | CompMem of ident * component_key (* Memory name * instanciated component key *) + | VarMem of var + +(* Variable denotation *) +type var_expr = + | Var of ident * var_type + | Const of ident * var_type (* useful? *) + | Field of var_expr * ident * var_type + | Index of var_expr * int * var_type + +type atomic_operation = + | Assign (* Wire *) + | Method of memory * ident (* step call *) + | Procedure of ident (* memoryless method made explicit *) + +(* Guarded Atomic Operation *) +type gao = + | Case of ident * (ident * gao list) list + | Call of var_expr list * atomic_operation * var_expr list + (* outputs * op * inputs *) + +type step_method = { + socm_name : ident; + socm_inputs : int list; + socm_outputs : int list; + socm_impl : (var list * gao list) option; (* local vars + body *) +} + +type precedence = ident * ident list +(* maps a step method name with the list of step methods that should + be called _before_ in the current step *) + +type component = { + socc_key : component_key; + socc_profile : var list * var list; + socc_memories : memory list; + socc_init : step_method option; + socc_step : step_method list; + socc_precedences : precedence list; +} diff --git a/src/socPredef.ml b/src/socPredef.ml new file mode 100644 index 0000000000000000000000000000000000000000..9ed70a02f26f83bebcd55ce92ccb10b2a44c5b00 --- /dev/null +++ b/src/socPredef.ml @@ -0,0 +1,523 @@ +(* Time-stamp: <modified the 21/02/2013 (at 11:10) by Erwan Jahier> *) + +(** Synchronous Object Code for Predefined operators. *) + +let finish_me lxm + = print_string ("\nsocPref.ml:"^(Lxm.details lxm)^" -> finish me!\n") + + +open Soc + +(* Some aliases *) +let b = Soc.Bool +let i = Soc.Int +let r = Soc.Real +let alpha = Soc.Alpha 0 + +let bb = ["x", b], ["z", b] +let ii = ["x", i], ["z", i] +let rr = ["x", r], ["z", r] +let ri = ["r", r], ["i", i] +let ir = ["i", i], ["r", r ] +let aa = ["x", alpha], ["z", alpha] + +let bbb = ["x", b; "y", b], ["z", b] +let iii = ["x", i; "y", i], ["z", i] +let rrr = ["x", r; "y", r], ["z", r] +let rrb = ["x", r; "y", r], ["z", b] +let iib = ["x", i; "y", i], ["z", b] +let aaa = ["i", alpha; "x", alpha], ["z", alpha] + + +let step11 = { (* a useful alias again *) + socm_name = "step"; + socm_inputs = [0]; + socm_outputs = [0]; + socm_impl = None; +} +let step21 = { (* a useful alias again *) + socm_name = "step"; + socm_inputs = [0;1]; + socm_outputs = [0]; + socm_impl = None; +} + +(* used to build predef soc with no memory *) +let make_soc key profile steps = { + socc_key = key; + socc_profile = profile; + socc_memories = []; + socc_init = None; + socc_precedences = []; + socc_step = steps; + } + + +type soc_comp_opt = SC of Soc.component | Undef of Lic.node_key + +(* exported *) +let of_node_key : Lic.node_key -> soc_comp_opt = + fun nk -> + match fst nk with + | "Lustre","mod" -> SC (make_soc ("mod", [], None) ii [step11]) + | "Lustre","iuminus" -> SC (make_soc ("iuminus", [], None) ii [step11]) + | "Lustre","ruminus" -> SC (make_soc ("ruminus", [], None) rr [step11]) + | "Lustre","not" -> SC (make_soc ("not", [], None) bb [step11]) + | "Lustre","real2int" -> SC (make_soc ("real2int", [], None) ri [step11]) + | "Lustre","int2real" -> SC (make_soc ("int2real", [], None) ir [step11]) + + | "Lustre","iplus" -> SC (make_soc ("iplus", [], None) iii [step21]) + | "Lustre","rplus" -> SC (make_soc ("rplus", [], None) rrr [step21]) + | "Lustre","itimes" -> SC (make_soc ("itimes", [], None) iii [step21]) + | "Lustre","rtimes" -> SC (make_soc ("rtimes", [], None) rrr [step21]) + | "Lustre","idiv" -> SC (make_soc ("idiv", [], None) iii [step21]) + | "Lustre","rdiv" -> SC (make_soc ("rdiv", [], None) rrr [step21]) + | "Lustre","iminus" -> SC (make_soc ("iminus", [], None) iii [step21]) + | "Lustre","rminus" -> SC (make_soc ("rminus", [], None) rrr [step21]) + + | "Lustre","ilt" -> SC (make_soc ("ilt", [], None) iib [step21]) + | "Lustre","rlt" -> SC (make_soc ("rlt", [], None) rrb [step21]) + | "Lustre","igt" -> SC (make_soc ("igt", [], None) iib [step21]) + | "Lustre","rgt" -> SC (make_soc ("rgt", [], None) rrb [step21]) + | "Lustre","ilte" -> SC (make_soc ("ilte", [], None) iib [step21]) + | "Lustre","rlte" -> SC (make_soc ("rlte", [], None) rrb [step21]) + | "Lustre","igte" -> SC (make_soc ("igte", [], None) iib [step21]) + | "Lustre","rgte" -> SC (make_soc ("rgte", [], None) rrb [step21]) + + | "Lustre","and" -> SC (make_soc ("and", [], None) bbb [step21]) + | "Lustre","beq" -> SC (make_soc ("beq", [], None) bbb [step21]) + | "Lustre","ieq" -> SC (make_soc ("ieq", [], None) iib [step21]) + | "Lustre","req" -> SC (make_soc ("req", [], None) rrb [step21]) + | "Lustre","neq" -> SC (make_soc ("neq", [], None) bbb [step21]) + | "Lustre","or" -> SC (make_soc ("or", [], None) bbb [step21]) + | "Lustre","xor" -> SC (make_soc ("xor", [], None) bbb [step21]) + | "Lustre","impl" -> SC (make_soc ("impl", [], None) bbb [step21]) + + | "Lustre","current" -> SC (make_soc ("current", [alpha], None) aa [step11]) + + | "Lustre","fby" -> SC { + socc_key = "fby", [alpha], None; + socc_profile = aaa; + socc_memories = [VarMem("m", alpha)]; + socc_step = [ + { + socm_name = "get"; + socm_inputs = []; + socm_outputs = [0]; + socm_impl = None; + }; + { + socm_name = "set"; + socm_inputs = [1]; + socm_outputs = []; + socm_impl = None + }; + ]; + socc_precedences = ["set", ["get"]]; + socc_init = Some { + socm_name = "init"; + socm_inputs = [0] ; + socm_outputs = []; + socm_impl = None; + }; + } + + | "Lustre","pre" -> SC { + socc_key = "pre", [alpha], None; + socc_profile = aa; + socc_memories = [VarMem("m", alpha)]; + socc_step = [ + { + socm_name = "get"; + socm_inputs = []; + socm_outputs = [0]; + socm_impl = None; + }; + { + socm_name = "set"; + socm_inputs = [0]; + socm_outputs = []; + socm_impl = None + }; + ]; + socc_precedences = ["set", ["get"]]; + socc_init = Some { + socm_name = "init"; + socm_inputs = [] ; (* XXX ??? *) + socm_outputs = []; + socm_impl = None; + }; + } + | "Lustre","arrow" -> SC { + socc_key = "arrow", [alpha], None; + socc_profile = aaa; + socc_memories = []; + socc_step = [ + { + socm_name = "step"; + socm_inputs = [1]; + socm_outputs = [0]; + socm_impl = None; + }; + ]; + socc_precedences = []; + socc_init = Some { + socm_name = "init"; + socm_inputs = [0]; + socm_outputs = []; + socm_impl = None; + }; + } + + | "Lustre","if" -> SC { + socc_key = "if", [alpha], None; + socc_profile = ( + ["c", b ; "x", alpha; "y", alpha], + ["z", alpha] + ); + socc_memories = []; + socc_init = None; + socc_precedences = []; + socc_step = [ + { + socm_name = "step"; + socm_inputs = [0; 1; 2]; + socm_outputs = [0]; + socm_impl = None; + } + ]; + } + | _ -> Undef nk + + +(** Instancie un composant polymorphe avec un type concret. *) +let instanciate_component: component -> Soc.var_type -> component = + fun c concrete_type -> + let new_profile = + List.map (fun (n, i) -> n, concrete_type) (fst c.socc_profile), + List.map (fun (n, i) -> n, concrete_type) (snd c.socc_profile) + in + let (key1, key2, key3) = c.socc_key in + let new_key = (key1, List.map (fun _ -> concrete_type) key2, key3) in + let new_memories = + List.map + (function | VarMem(n, t) -> VarMem(n, concrete_type) | _ -> assert false) + c.socc_memories + in + { + c with + socc_key = new_key; + socc_profile = new_profile; + socc_memories = new_memories; + } + + +(* + XXX Faut-il definir une version générique des composants tranches ? + + Je les ai défini directement via "make_slice_component", ce qui + n'est pas homogene avec la facon dont sont traités les autres + composants génériques style 'fby'. + + Le truc, c'est que je ne sais pas trop quoi mettre dans la version + générique, et comme celle-ci est destinée à être instanciée... En + effet, le type de sortie des composants tranche depend de la + slice_info passé en parametre lors de l'instanciation des composant + génériques. Je pourrais mettre un type alpha, mais je trouve ca + idiot, alors je ne le fais pas... + + Une autre solution pour rendre ce traitement homogene serait de ne + pas passer par une version générique pour les composants fby et + consort. A voir. + + idem pour "x^n" (Hat_n). +*) + +let make_slice_component: Lic.slice_info -> Soc.var_type -> component = + fun si t -> + let (f,l,step) = (si.Lic.se_first, si.Lic.se_last,si.Lic.se_step) in + let sub_array_type = + match t with + | Soc.Array(t_elt,size) -> + let slice_size = 1+abs( (l - f) / step) in + Soc.Array(t_elt, slice_size) + | _ -> assert false + in + { + socc_key = ("array_slice", [t], Some (f, l, step)); + socc_profile = (["t", t], ["st", sub_array_type ]); + socc_memories = []; + socc_step = [ + { + socm_name = "step"; + socm_inputs = [0]; + socm_outputs = [0]; + socm_impl = None; + }; + ]; + socc_precedences = []; + socc_init = None; + } + + +let make_array_component: int -> Soc.var_type -> component = + fun i t -> + let array_type = + match t with + | Soc.Alpha _ -> assert false + | t -> Soc.Array(t,i) + in + { + socc_key = ("hat", [array_type], None); + socc_profile = (["t", t], ["st", array_type]); + socc_memories = []; + socc_step = [ + { + socm_name = "step"; + socm_inputs = [0]; + socm_outputs = [0]; + socm_impl = None; + }; + ]; + socc_precedences = []; + socc_init = None; + } + + + +let component_interface_of_predef: + Lxm.t -> AstPredef.op -> Soc.var_type list -> soc_comp_opt = + fun lxm op types -> + match (op, types) with + | AstPredef.IPLUS_n, [Int; Int] -> of_node_key (("Lustre","iplus"), []) + | AstPredef.PLUS_n, [Int; Int] -> of_node_key (("Lustre","iplus"), []) + | AstPredef.PLUS_n, [Real; Real] -> of_node_key (("Lustre","rplus"), []) + | AstPredef.RPLUS_n, [Real; Real] -> of_node_key (("Lustre","rplus"), []) + | AstPredef.ITIMES_n,[Int; Int] -> of_node_key (("Lustre","itimes"), []) + | AstPredef.TIMES_n, [Int; Int] -> of_node_key (("Lustre","itimes"), []) + | AstPredef.TIMES_n, [Real; Real] -> of_node_key (("Lustre","rtimes"), []) + | AstPredef.RTIMES_n,[Real; Real] -> of_node_key (("Lustre","rtimes"), []) + | AstPredef.ISLASH_n,[Int; Int] -> of_node_key (("Lustre","idiv"), []) + | AstPredef.SLASH_n, [Int; Int] -> of_node_key (("Lustre","idiv"), []) + | AstPredef.DIV_n, [Int; Int] -> of_node_key (("Lustre","idiv"), []) + | AstPredef.MOD_n, [Int;Int] -> of_node_key (("Lustre","mod"), []) + | AstPredef.SLASH_n, [Real; Real] -> of_node_key (("Lustre","rdiv"), []) + | AstPredef.RSLASH_n,[Real; Real] -> of_node_key (("Lustre","rdiv"), []) + | AstPredef.MINUS_n, [Int; Int] -> of_node_key (("Lustre","iminus"), []) + | AstPredef.IMINUS_n,[Int; Int] -> of_node_key (("Lustre","iminus"), []) + | AstPredef.MINUS_n, [Real; Real] -> of_node_key (("Lustre","rminus"), []) + | AstPredef.RMINUS_n,[Real; Real] -> of_node_key (("Lustre","rminus"), []) + | AstPredef.UMINUS_n,[Int] -> of_node_key (("Lustre","iuminus"), []) + | AstPredef.IUMINUS_n, [Int] -> of_node_key (("Lustre","iuminus"), []) + | AstPredef.UMINUS_n, [Real] -> of_node_key (("Lustre","ruminus"), []) + | AstPredef.RUMINUS_n, [Real] -> of_node_key (("Lustre","ruminus"), []) + | AstPredef.LT_n, [Int; Int] -> of_node_key (("Lustre","ilt"), []) + | AstPredef.LT_n, [Real; Real] -> of_node_key (("Lustre","rlt"), []) + | AstPredef.GT_n, [Int; Int] -> of_node_key (("Lustre","igt"), []) + | AstPredef.GT_n, [Real; Real] -> of_node_key (("Lustre","rgt"), []) + | AstPredef.LTE_n, [Int; Int] -> of_node_key (("Lustre","ilte"), []) + | AstPredef.LTE_n, [Real; Real] -> of_node_key (("Lustre","rlte"), []) + | AstPredef.GTE_n, [Int; Int] -> of_node_key (("Lustre","igte"), []) + | AstPredef.GTE_n, [Real; Real] -> of_node_key (("Lustre","rgte"), []) + | AstPredef.AND_n, [Bool; Bool] -> of_node_key (("Lustre","and"), []) + | AstPredef.OR_n, [Bool; Bool] -> of_node_key (("Lustre","or"), []) + | AstPredef.XOR_n, [Bool; Bool] -> of_node_key (("Lustre","xor"), []) + | AstPredef.IMPL_n, [Bool; Bool] -> of_node_key (("Lustre","impl"), []) + | AstPredef.EQ_n, [Bool; Bool] -> of_node_key (("Lustre","beq"), []) + | AstPredef.EQ_n, [Int; Int] -> of_node_key (("Lustre","ieq"), []) + | AstPredef.EQ_n, [Real; Real] -> of_node_key (("Lustre","req"), []) + | AstPredef.NEQ_n, [Bool; Bool] -> of_node_key (("Lustre","neq"), []) + | AstPredef.NOT_n, [Bool] -> of_node_key (("Lustre","not"), []) + + | AstPredef.TRUE_n, [] -> finish_me lxm ; assert false (* todo *) + | AstPredef.FALSE_n, [] -> finish_me lxm ; assert false (* todo *) + | AstPredef.RCONST_n _, [] -> finish_me lxm ; assert false (* todo *) + | AstPredef.ICONST_n _, [] -> finish_me lxm ; assert false (* todo *) + | AstPredef.REAL2INT_n, [Real] -> finish_me lxm ; assert false (* todo *) + | AstPredef.INT2REAL_n, [Int] -> finish_me lxm ; assert false (* todo *) + | AstPredef.NOR_n, _ -> finish_me lxm ; assert false (* todo *) + | AstPredef.DIESE_n, _ -> finish_me lxm ; assert false (* todo *) + | AstPredef.IF_n, _ -> + let concrete_type = List.nth types 0 in + (match of_node_key (("Lustre","if"), []) with + | SC comp -> SC(instanciate_component comp concrete_type) + | Undef _ -> assert false + ) + + (* « incorrect lic » *) + | AstPredef.IUMINUS_n, _ -> assert false + | AstPredef.IMINUS_n, _ -> assert false + | AstPredef.RUMINUS_n, _ -> assert false + | AstPredef.RMINUS_n, _ -> assert false + | AstPredef.TRUE_n, _ -> assert false + | AstPredef.FALSE_n, _ -> assert false + | AstPredef.RCONST_n _, _ -> assert false + | AstPredef.ICONST_n _, _ -> assert false + | AstPredef.REAL2INT_n, _ -> assert false + | AstPredef.INT2REAL_n, _ -> assert false + | AstPredef.PLUS_n, _ -> assert false + | AstPredef.IPLUS_n, _ -> assert false + | AstPredef.RPLUS_n, _ -> assert false + | AstPredef.TIMES_n, _ -> assert false + | AstPredef.ITIMES_n, _ -> assert false + | AstPredef.RTIMES_n, _ -> assert false + | AstPredef.DIV_n, _ -> assert false + | AstPredef.MOD_n, _ -> assert false + | AstPredef.SLASH_n, _ -> assert false + | AstPredef.ISLASH_n, _ -> assert false + | AstPredef.RSLASH_n, _ -> assert false + | AstPredef.MINUS_n, _ -> assert false + | AstPredef.UMINUS_n, _ -> assert false + | AstPredef.GT_n, _ -> assert false + | AstPredef.LT_n, _ -> assert false + | AstPredef.LTE_n, _ -> assert false + | AstPredef.GTE_n, _ -> assert false + | AstPredef.AND_n, _ -> assert false + | AstPredef.OR_n, _ -> assert false + | AstPredef.XOR_n, _ -> assert false + | AstPredef.IMPL_n, _ -> assert false + | AstPredef.EQ_n, _ -> assert false + | AstPredef.NEQ_n, _ -> assert false + | AstPredef.NOT_n, _ -> assert false + + +let (component_interface_of_pos_op: + Lxm.t -> Lic.by_pos_op -> Soc.var_type list -> soc_comp_opt) = + fun lxm op types -> + match (op, types) with + | Lic.PREDEF_CALL op, _ -> component_interface_of_predef lxm op types + + | Lic.CALL op, _ -> assert false (* XXX todo *) + + | Lic.FBY, _ -> + let concrete_type = List.nth types 0 in + (match of_node_key (("Lustre","fby"), []) with + | SC comp -> SC(instanciate_component comp concrete_type) + | Undef _ -> assert false + ) + | Lic.PRE, _ -> + let concrete_type = List.nth types 0 in + (match of_node_key (("Lustre","pre"), []) with + | SC comp -> SC(instanciate_component comp concrete_type) + | Undef _ -> assert false + ) + | Lic.CURRENT, _ -> + let concrete_type = List.nth types 0 in + (match of_node_key (("Lustre","current"), []) with + | SC comp -> SC(instanciate_component comp concrete_type) + | Undef _ -> assert false + ) + | Lic.ARROW, _ -> + let concrete_type = List.nth types 0 in + (match of_node_key (("Lustre","arrow"), []) with + | SC comp -> SC(instanciate_component comp concrete_type) + | Undef _ -> assert false + ) + | Lic.HAT i,_ -> + let elt_type = List.nth types 0 in + SC(make_array_component i elt_type) + + | Lic.ARRAY, _-> finish_me lxm ; assert false + | Lic.CONCAT ,_-> finish_me lxm ; assert false + + (* Those are not components *) + | Lic.ARRAY_SLICE sinfo,_ -> assert false + + | Lic.VAR_REF _, _ -> assert false + | Lic.CONST_REF _, _ -> assert false + | Lic.STRUCT_ACCESS _, _ -> assert false + | Lic.WHEN _, _ -> assert false + | Lic.TUPLE, _ -> assert false + | Lic.ARRAY_ACCES _, _ -> assert false + + +(* +21/02/2013 : ai-je vraiment besoin de ca maintenant que les metaop ont été encapsulé +dans des noeuds ? bon, je garde quelque temps en commentaire au cas ou... + | Lic.Fill(node,size), _ + | Lic.FillRed(node,size), _ + | Lic.Red(node,size), _ -> + (match of_node_key node with + | Undef name -> Undef name + (* Given + - a node n of type + tau * tau_1 * ... * tau_n -> tau * teta_1 * ... * teta_l + - a integer c + + the red expression has the profile: + tau * tau_1^c * ... * tau_n^c -> tau * teta_1^c * ... * teta_l^c + *) + | SC c -> + let arrayse l = + let exp (id,t) = + match t with + | Soc.Alpha _ -> assert false + | t -> id, Soc.Array(t,size) + in + match l with + | [] -> assert false + | (id,t)::tail ->(id, t):: (List.map exp tail) + in + SC { + (* XXX la clef devrait contenir le node et la taille ? + + Les composants iterateurs ne meritent ils pas un traitement + specifique ? + Ce que je veux, c'est + - y mettre toute l'information necessaire pour pouvoir generer + la boucle for qui va bien, + - garder une forme synthetique qui permette de faire des + analyses et de la vérification + + *) + socc_key = ("fillred" ^ node ^ (string_of_int size), [], None); + socc_profile = + (arrayse (fst c.socc_profile), arrayse (snd c.socc_profile)); + socc_memories = c.socc_memories; + socc_step = c.socc_step; + (* XXX non ! le probleme, c'est que cette methode step + doit être fabriquée à partir de la methode step + du noeud itéré, et que je n'ai rien pour exprimer + ce genre de truc pour l'instant. + *) + socc_precedences = []; + socc_init = c.socc_init; (* XXX non ! *) + } + ) + | Lic.Map(node,size), _ -> + (match of_node_key node with + | Undef name -> Undef name + | SC c -> + (* Given + - a node n of type: tau_1 * ... * tau_n -> teta_1 * ... * teta_l + - an integer c + + The profile of map is: + tau_1^c * ... * tau_n^c -> teta_1^c * ... * teta_l^c + *) + let arrayse l = + let exp (id,t) = + match t with + | Soc.Alpha _ -> assert false + | t -> id, Soc.Array(t,size) + in + (List.map exp l) + in + SC { + socc_key = ("map" ^ node ^ (string_of_int size), [], None); + socc_profile = + (arrayse (fst c.socc_profile), arrayse (snd c.socc_profile)); + socc_memories = c.socc_memories; + socc_step = c.socc_step; (* XXX non ! *) + socc_precedences = []; + socc_init = c.socc_init; + } + ) + | Lic.BoolRed(i,j,k), _ -> Errors.finish_me lxm ; assert false + + (* Cas particulier du boolred *) + | Lic.DIESE, _-> Errors.finish_me lxm ; assert false + | Lic.NOR ,_-> Errors.finish_me lxm ; assert false + + + *) diff --git a/src/socPredef.mli b/src/socPredef.mli new file mode 100644 index 0000000000000000000000000000000000000000..0e8b5f642dec7cb97fa17b77b7a6ee762306a09a --- /dev/null +++ b/src/socPredef.mli @@ -0,0 +1,19 @@ +(* Time-stamp: <modified the 21/02/2013 (at 10:19) by Erwan Jahier> *) + +(** Synchronous Object Code for Predefined operators. *) + +type soc_comp_opt = SC of Soc.component | Undef of Lic.node_key + +val of_node_key : Lic.node_key -> soc_comp_opt + +(** Associe un opérateur Lustre et le type de ses opérandes à un SOC + et sa fonction de typage. + + Le type des opérandes permet de traiter les opérateurs surchargés. +*) + +val component_interface_of_pos_op: + Lxm.t -> Lic.by_pos_op -> Soc.var_type list -> soc_comp_opt + + + diff --git a/src/socUtils.ml b/src/socUtils.ml new file mode 100644 index 0000000000000000000000000000000000000000..ccc341546c2e0d644b9759cba72c37b1511fc2a6 --- /dev/null +++ b/src/socUtils.ml @@ -0,0 +1,361 @@ +(** Time-stamp: <modified the 30/06/2009 (at 11:45) by Erwan Jahier> *) + + +open Soc + + +(** Donne toute les méthodes d'un composant. + + C'est la liste des méthodes du composant, et la méthode d'initialisation le + cas échéant. *) +let get_all_methods: component -> step_method list = fun c -> + match c.socc_init with + | None -> c.socc_step + | Some m -> m :: c.socc_step + +(** Fonctions de représentation des objets LOC. *) + +(** Aliases *) +let str_ff = Format.str_formatter +let flush_str_ff = Format.flush_str_formatter +let fprintf = Format.fprintf + +(** Encapsule l'appel à une fonction avec formatter pour sortir une string. *) +let call_fun_ff: ((Format.formatter -> unit) -> string) = fun f -> + let b = Buffer.create 50 in + let ff = Format.formatter_of_buffer b in + f ff; + Format.pp_print_flush ff (); + let s = Buffer.contents b in + Buffer.reset b; + s + +(* Type *) +let rec string_of_type_ref_ff: (Soc.var_type -> Format.formatter -> unit) = fun v ff -> + let str = + match v with + | Soc.Bool -> "bool" + | Soc.Int -> "int" + | Soc.Real-> "real" + | Soc.Extern s -> s ^ "(*extern*)" + | Soc.Enum (s, sl) -> "enum " ^ s ^ " {" ^ (String.concat ", " sl) ^ "}" + | Soc.Struct (sid,_) -> sid ^ "(*struct*)" + | Soc.Array (ty, sz) -> Printf.sprintf "%s^%d" (string_of_type_ref ty) sz + | Soc.Alpha nb -> + (* On génère des "types" à la Caml : 'a, 'b, 'c, etc. *) + let a_value = Char.code('a') in + let z_value = Char.code('z') in + let str = + if (nb >= 0 && nb <= (z_value - a_value)) then + ("'" ^ (Char.escaped (Char.chr(a_value + nb)))) + else + ("'a" ^ (string_of_int nb)) + in + str + in + fprintf ff "%s" str + +and string_of_type_ref: (Soc.var_type -> string) = fun v -> + call_fun_ff (string_of_type_ref_ff v) + + +(* Clé de composant *) +let string_of_component_key_ff: (Soc.component_key -> Format.formatter -> unit) = + fun (id, types, si_opt) ff -> + (match types with + | [] -> fprintf ff "%s" id + | _ -> fprintf ff "(%s)%s" + (String.concat " * " (List.map string_of_type_ref types)) id); + (match si_opt with + | None -> () + | Some(f,l,step) -> fprintf ff "[%d .. %d step %d]" f l step) + +let string_of_component_key: (Soc.component_key -> string) = fun v -> + call_fun_ff (string_of_component_key_ff v) + + +(* Variable *) +let string_of_var_ff: (Soc.var -> Format.formatter -> unit) = fun (id, type_) ff -> + fprintf ff "%s: %s" id (string_of_type_ref type_) + +let string_of_var: (Soc.var -> string) = fun v -> + call_fun_ff (string_of_var_ff v) + + +(* Mémoire *) +let string_of_memory_ff: (memory -> Format.formatter -> unit) = fun v ff -> + let name = match v with + | CompMem(id, _) -> id + | VarMem v -> string_of_var v + in + fprintf ff "%s" name + +let string_of_memory: (memory -> string) = fun v -> + call_fun_ff (string_of_memory_ff v) + +(* Déclaration d'une mémoire *) +let string_of_memory_decl_ff: (memory -> Format.formatter -> unit) = fun v ff -> match v with + | CompMem(id, key) -> fprintf ff "%s : %s" id (string_of_component_key key) + | VarMem v -> fprintf ff "%s" (string_of_var v) + +let string_of_memory_decl: (memory -> string) = fun v -> + call_fun_ff (string_of_memory_decl_ff v) + + +(* Opération *) +let string_of_operation_ff: (atomic_operation -> Format.formatter -> unit) = fun v ff -> match v with + | Assign -> () (* On suppose qu'il est déjà affiché dans string_of_gao *) + | Method(obj, meth) -> fprintf ff "%s.%s" (string_of_memory obj) meth + | Procedure proc -> fprintf ff "%s" proc + +let string_of_operation: (atomic_operation -> string) = fun v -> + call_fun_ff (string_of_operation_ff v) + + +(* Filtre d'accès *) +let rec string_of_filter_ff: (Soc.var_expr -> Format.formatter -> unit) = + fun v ff -> match v with + | Const(id, _) + | Var (id,_) -> fprintf ff "%s" id + | Field(f, id,_) -> string_of_filter_ff f ff; fprintf ff ".%s" id + | Index(f, index,_) -> string_of_filter_ff f ff; fprintf ff "[%d]" index + +let string_of_filter: (Soc.var_expr -> string) = fun v -> + call_fun_ff (string_of_filter_ff v) + +(* Code *) +let rec string_of_gao_ff: (gao -> Format.formatter -> unit) = fun v ff -> match v with + | Case (ck, cases) -> + let string_of_case: (ident * gao list -> unit) = fun (id, c) -> + fprintf ff "@[case %s:@[" id; + string_of_gaos_list_ff c ff; + fprintf ff "@]@]" + in + fprintf ff "switch(%s) {" ck; + List.iter string_of_case cases; + fprintf ff "}" + + | Call(dests, op, srcs) -> + let _ = + match dests with + | [] -> () (* pas de destinations, on affiche pas de "=" *) + | _ -> + let dests = String.concat ", " (List.map string_of_filter dests) in + fprintf ff "%s = " dests + in + let srcs = String.concat ", " (List.map string_of_filter srcs) in + string_of_operation_ff op ff; + fprintf ff "(%s)" srcs; + +and string_of_gaos_list_ff: (gao list -> Format.formatter -> unit) = fun gaos ff -> + List.iter ( + fun c -> + fprintf ff "@["; + string_of_gao_ff c ff; + fprintf ff ";@]@," + ) gaos + +let string_of_gao: (gao -> string) = fun v -> + call_fun_ff (string_of_gao_ff v) + +let string_of_gaos_list: (gao list -> string) = fun v -> + call_fun_ff (string_of_gaos_list_ff v) + + +(* Profil de méthode *) +let string_interface_of_method_ff: (component -> step_method -> Format.formatter -> unit) = fun c m ff -> + let string_var_from_index: (Soc.var list -> int -> string) = fun vl i -> + string_of_var (List.nth vl i) + in + fprintf ff "%s(%s) -> (%s)" + m.socm_name + (String.concat "; " (List.map (string_var_from_index (fst c.socc_profile)) m.socm_inputs)) + (String.concat "; " (List.map (string_var_from_index (snd c.socc_profile)) m.socm_outputs)) + + +let string_interface_of_method: (component -> step_method -> string) = fun c m -> + call_fun_ff (string_interface_of_method_ff c m) + + +(* Méthode complète *) +let string_of_method_ff: (component -> step_method -> Format.formatter -> unit) = fun c m ff -> + + fprintf ff "@[<v>@[<v 2>"; + string_interface_of_method_ff c m ff; + + match m.socm_impl with + | None -> fprintf ff "@]@]" + | Some i -> + let locals, gaos = i in + fprintf ff ": {@;"; + fprintf ff "@[<v>-- locals vars@;"; + List.iter ( + fun v -> + string_of_var_ff v ff; + fprintf ff ";@,"; + ) locals; + fprintf ff "@]@;@[<v>-- code@;"; + string_of_gaos_list_ff gaos ff; + fprintf ff "@]@]@ }@]" + +let string_of_method: (component -> step_method -> string) = fun c m -> + call_fun_ff (string_of_method_ff c m) + + +(* Ordre des méthodes *) +let string_of_precedence_ff: (string * string list -> Format.formatter -> unit) = fun (m, needs) ff -> + fprintf ff "%s < [%s]" m (String.concat "; " needs) + +let string_of_precedence: (string * string list -> string) = fun v -> + call_fun_ff (string_of_precedence_ff v) + + +(** Profile d'un composant *) +let string_of_profile_ff: Soc.var list * Soc.var list -> Format.formatter -> unit = fun (ins, outs) ff -> + fprintf ff "profile: @[(%s) ->@ (%s)@]" + (String.concat "; " (List.map string_of_var ins)) + (String.concat "; " (List.map string_of_var outs)) + +let string_of_profile: Soc.var list * Soc.var list -> string = fun profile -> + call_fun_ff (string_of_profile_ff profile) + + +(* Convertion des éléments d'un composant *) +(* Convertion du profil ... *) +let string_of_component_profile_ff: (component -> Format.formatter -> unit) = fun comp ff -> + string_of_profile_ff comp.socc_profile ff + +let string_of_component_profile: (component -> string) = fun comp -> + call_fun_ff (string_of_component_profile_ff comp) + +(* ... des contraintes *) +let string_of_comp_constraints_ff: (component -> Format.formatter -> unit) = fun comp ff -> + fprintf ff "constraints: @["; + match comp.socc_precedences with + | [] -> fprintf ff "[]@]" + | _ -> + fprintf ff "%s@]" + (String.concat "; " (List.map string_of_precedence comp.socc_precedences)) + +let string_of_component_factory_ff: ( + component -> Format.formatter -> + (component -> step_method -> Format.formatter -> unit) -> (* Formatage des méthodes *) + (memory -> Format.formatter -> unit) option -> (* Formatage des mémoires *) + unit +) = fun comp ff format_meth format_mem -> + let display_mem () = + match format_mem with + | None -> () + | Some f -> ( + fprintf ff "@[<v 2>memories:@,"; + List.iter ( + fun m -> + f m ff; + fprintf ff ";@," + ) comp.socc_memories + ) + in + let display_init () = + match comp.socc_init with + | None -> fprintf ff "@[<v 2>init: -@]" + | Some m -> ( + fprintf ff "@[<v 2>init:@,"; + format_meth comp m ff; + fprintf ff "@]" + ) + in + + fprintf ff "@[<v>@[<v 2>component "; + string_of_component_key_ff comp.socc_key ff; + fprintf ff ":@,@[<v>"; + + string_of_component_profile_ff comp ff; + fprintf ff "@]@,@[<v>"; + + display_mem(); + fprintf ff "@]@,@[<v>"; + + string_of_comp_constraints_ff comp ff; + fprintf ff "@]@,@[<v>"; + + display_init(); + fprintf ff "@]@,@[<v>"; + + fprintf ff "@[<v 2>steps:@,"; + List.iter ( + fun s -> + fprintf ff "@["; + format_meth comp s ff; + fprintf ff "@]@," + ) comp.socc_step; + + fprintf ff "@]@]@]@]@." + + +(* Interface d'un composant *) +let string_interface_of_component_ff: (component -> Format.formatter -> unit) = fun comp ff -> + string_of_component_factory_ff comp ff + string_interface_of_method_ff + None + +let string_interface_of_component: (component -> string) = fun v -> + call_fun_ff (string_interface_of_component_ff v) + + +(* Composant complet *) +let string_of_component_ff: (component -> Format.formatter -> unit) = fun comp ff -> + string_of_component_factory_ff comp ff + string_of_method_ff + (Some string_of_memory_decl_ff) + +let string_of_component: (component -> string) = fun v -> + call_fun_ff (string_of_component_ff v) + + +let dump_entete oc = + let time = Unix.localtime (Unix.time ()) in + let sys_call, _ = Array.fold_left + (fun (acc,i) x -> + if 70 < i + (String.length x) then + acc ^ "\n--\t\t" ^ x, String.length ("\n--\t\t" ^ x) + else + acc ^ " " ^ x , (i+1+(String.length x)) + ) + ("",0) + Sys.argv + and + date = ( + (string_of_int time.Unix.tm_mday) ^ "/" ^ + (string_of_int (time.Unix.tm_mon+1)) ^ "/" ^ + (string_of_int (1900+time.Unix.tm_year)) + ) + and time_str = ( + (string_of_int time.Unix.tm_hour) ^ ":" ^ + (if time.Unix.tm_min < 10 then "0" else "") ^ + (string_of_int time.Unix.tm_min) ^ ":" ^ + (if time.Unix.tm_sec < 10 then "0" else "") ^ + (string_of_int time.Unix.tm_sec) + ) + (* and user = Unix.getlogin () *) + and hostname = Unix.gethostname () + in + output_string oc + ("-- This file was generated by "^Sys.argv.(0)^" version " ^ Version.str ^ + ".\n--\t" ^ sys_call ^ " +-- on " ^ hostname ^ + (* "by "^ user ^ *) + " the " ^ date ^ " at " ^ time_str ^ "\n\n"); + flush oc + + +let output: (bool -> string -> component list -> unit) = + fun no_header pkg_name components -> + let header = "Package '" ^ pkg_name ^ "' :" in + let deco = (String.make (String.length header) '=') in + + if no_header then () else dump_entete stdout ; + print_string (deco ^ "\n" ^ header ^ "\n" ^ deco ^ "\n" ^ "\n"); + print_string ( + String.concat "\n\n" (List.map string_of_component components) + ); + flush stdout diff --git a/src/socUtils.mli b/src/socUtils.mli new file mode 100644 index 0000000000000000000000000000000000000000..3ce0371a8d490394c9933c24db82a3e9451dd8b2 --- /dev/null +++ b/src/socUtils.mli @@ -0,0 +1,42 @@ +(** Time-stamp: <modified the 25/02/2013 (at 18:03) by Erwan Jahier> *) + + +(** Donne toute les méthodes d'un composant. *) +val get_all_methods: Soc.component -> Soc.step_method list + + +(** Fonctions de représentation des objets SOC. *) +val string_of_type_ref : Soc.var_type -> string +val string_of_component_key : Soc.component_key -> string +val string_of_var : Soc.var -> string +val string_of_memory : Soc.memory -> string +val string_of_operation : Soc.atomic_operation -> string +val string_of_gao : Soc.gao -> string +val string_of_gaos_list : Soc.gao list -> string +val string_of_filter : Soc.var_expr -> string +val string_of_method : Soc.component -> Soc.step_method -> string +val string_interface_of_method : Soc.component -> Soc.step_method -> string +val string_of_precedence : Soc.precedence -> string +val string_of_profile : Soc.var list * Soc.var list -> string +val string_interface_of_component : Soc.component -> string +val string_of_component : Soc.component -> string + +val string_of_type_ref_ff : Soc.var_type -> Format.formatter -> unit +val string_of_component_key_ff : Soc.component_key -> Format.formatter -> unit +val string_of_var_ff : Soc.var -> Format.formatter -> unit +val string_of_memory_ff : Soc.memory -> Format.formatter -> unit +val string_of_operation_ff : Soc.atomic_operation -> Format.formatter -> unit +val string_of_filter_ff : Soc.var_expr -> Format.formatter -> unit +val string_of_gao_ff : Soc.gao -> Format.formatter -> unit +val string_of_method_ff : Soc.component -> Soc.step_method -> Format.formatter -> unit +val string_interface_of_method_ff : Soc.component -> Soc.step_method -> Format.formatter -> unit +val string_of_precedence_ff : string * string list -> Format.formatter -> unit +val string_of_profile_ff : Soc.var list * Soc.var list -> Format.formatter -> unit +val string_interface_of_component_ff : Soc.component -> Format.formatter -> unit +val string_of_component_ff : Soc.component -> Format.formatter -> unit + + +(** [output header_flag pack_name] dumps the soc list into a + file. [header_flag] states whether or not headers (comment) + should be printed *) +val output: bool -> string -> Soc.component list -> unit diff --git a/src/toposort.ml b/src/toposort.ml new file mode 100644 index 0000000000000000000000000000000000000000..d1a72796edbdc504943425af05010d6538c8b6e3 --- /dev/null +++ b/src/toposort.ml @@ -0,0 +1,39 @@ +(** See documentation in the .mli *) + + +exception DependencyCycle of string * string list + +(** Do the actual topological sort. + + This function takes several parameters : + @param acc this is the accumulator, which contains already sorted values + @param in_process contains values which are currently being processed (to detect cyclic dependencies) + @param to_sort this is the list to sort + @param dep_fun gives dependencies for a specific value from to_sort list *) +let rec topological_sort_acc: + ('a -> string) -> 'a list -> 'a list -> 'a list -> ('a -> 'a list) -> 'a list = + fun a2str acc in_process to_sort dep_fun -> match to_sort with + | [] -> acc + | x::tl -> + if List.mem x in_process then + (* If this element is already marked as being processed, it must be + a cyclic dependency *) + raise (DependencyCycle(a2str x, List.map a2str in_process)) + + else if List.mem x acc then + (* If the element is already in the accumulator, it means + we've already sorted it. *) + topological_sort_acc a2str acc in_process tl dep_fun + + else + (* Else, we compute the dependencies for this value *) + let dependencies = dep_fun x in + let dependencies_sorted = + topological_sort_acc a2str acc (x :: in_process) dependencies dep_fun + in + let acc = dependencies_sorted @ [x] in + topological_sort_acc a2str acc in_process tl dep_fun + + +let f: ('a -> string) -> 'a list -> ('a -> 'a list) -> 'a list = + fun a2str to_sort dep_fun -> topological_sort_acc a2str [] [] to_sort dep_fun diff --git a/src/toposort.mli b/src/toposort.mli new file mode 100644 index 0000000000000000000000000000000000000000..c517d2f03529b2928fd824f08b7b9fe750517e63 --- /dev/null +++ b/src/toposort.mli @@ -0,0 +1,14 @@ +(** This module contains various tools used thorough the compiler. *) + +(** [topolocical_sort printer l dep_fun] does a topological sort on + the list [l], using the function [f] to find dependency in some + user-specific structure for each elements of [l], and recursively + for each dependencies found. + + The dependency structure is unknown to this function, since [dep_fun] is + the interface between each other. + + Throws a DependencyCycle exception a if cyclic dependency is found. *) +val f : ('a -> string) -> 'a list -> ('a -> 'a list) -> 'a list + +exception DependencyCycle of string * string list diff --git a/test/lus2lic.sum b/test/lus2lic.sum index 322c9529e8636708911c2b488e9e7c69c59881a0..3d235b104811e9e8d596f43333abaa528885ae6b 100644 --- a/test/lus2lic.sum +++ b/test/lus2lic.sum @@ -1,4 +1,4 @@ -Test Run By jahier on Wed Feb 13 14:16:05 2013 +Test Run By jahier on Mon Feb 25 18:13:41 2013 Native configuration is i686-pc-linux-gnu === lus2lic tests === diff --git a/test/lus2lic.time b/test/lus2lic.time index dfafd0d5f66e96dd46ecf60b6e57e68a094e9177..76997001418c69fdba5c738b15d75c03a8b0ec06 100644 --- a/test/lus2lic.time +++ b/test/lus2lic.time @@ -1,2 +1,2 @@ -testcase ./lus2lic.tests/non-reg.exp completed in 23 seconds +testcase ./lus2lic.tests/non-reg.exp completed in 24 seconds testcase ./lus2lic.tests/progression.exp completed in 0 seconds