123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322(** Time-stamp: <modified the 06/03/2020 (at 13:32) by Erwan Jahier> *)letdbg=(Lv6Verbose.get_flag"deps")typeaction=Action.t(*********************************************************************************)moduleOrderedAction=structtypet=actionletcompare=compareend(** Gère un ensemble d'actions uniques. *)moduleActions=Set.Make(OrderedAction)moduleMapAction=Map.Make(OrderedAction)(** maps an action to the set of actions that it depends on *)(* exported *)typet=Actions.tMapAction.t(* exported *)letempty:t=MapAction.empty(* exported *)let(have_deps:t->action->bool)=funma->MapAction.memam(* exported *)let(remove_dep:t->action->t)=fundepsa->MapAction.removeadeps(* exported *)let(find_deps:t->action->actionlist)=funma->tryActions.elements(MapAction.findam)withNot_found->[]letrec(depends_on:t->Action.t->Action.t->bool)=funma1a2->tryleta1_deps=MapAction.finda1minActions.mema2a1_deps||(* XXX should I compute the closure of the deps once for all ? *)Actions.exists(funa1->depends_onma1a2)a1_depswithNot_found->false(*********************************************************************************)(** Ajoute une liste de dépendances à une action. *)letadd_deps:t->action->actionlist->t=funma->function|[]->m|al->letactions=tryMapAction.findamwithNot_found->Actions.emptyinletactions=List.fold_left(funseta->Actions.addaset)actionsalinMapAction.addaactionsm(* exported *)let(concat:t->t->t)=funm1m2->MapAction.fold(funkeyvaluem->add_depsmkey(Actions.elementsvalue))m1m2(*********************************************************************************)(* exported *)let(generate_deps_from_step_policy:Soc.precedencelist->(string*action)list->t)=funprecedencesactions->letgenerate_deps_for_action:(t->string*stringlist->t)=funad(action_name,actions_needed)->letmain_action=snd(List.find(fun(n,_)->n=action_name)actions)inletdeps=List.map(fundep_name->snd(List.find(fun(n,_)->n=dep_name)actions))actions_neededinadd_depsadmain_actiondepsinList.fold_left(generate_deps_for_action)emptyprecedences(*********************************************************************************)moduleOrderedSocVar=structtypet=Soc.var_exprletcompare=compareendmoduleVarMap=Map.Make(OrderedSocVar)(** A Data structure that maps a Soc.var_expr to all the
actions that needed to compute it.
It is used to know which actions impact which Soc.var_expr.
nb : you can have several actions associated to the same var_expr
when defining arrays or structures parts by parts. For instance
x[0]=42;
x[1]=1;
are two actions that define the var_expr "x"
*)typevar2actions_tbl=Actions.tVarMap.tletvar2actionsktbl=tryVarMap.findktblwithNot_found->Actions.emptyletrec(gen_parents:Soc.var_expr->Soc.var_exprlist)=funvar->(* if var = t.[2].field, then it returns [t.[2].field; t.[2] ; t] *)matchvarwith|Soc.Slice(ve,_,_,_,_,_)|Soc.Field(ve,_,_)|Soc.Index(ve,_,_)->ve::(gen_parentsve)|Soc.Var(_,_vt)|Soc.Const(_,_vt)->[var]letrec(_get_top_var:Soc.var_expr->Soc.var_expr)=funvar->(* if var = t.[2].field, then it returns (also) t.[2] and t *)matchvarwith|Soc.Slice(ve,_,_,_,_,_)|Soc.Field(ve,_,_)|Soc.Index(ve,_,_)->_get_top_varve|Soc.Var(_,_vt)|Soc.Const(_,_vt)->var(** If x is a int^2, then
then actions such as a="x = y"
should produce the following dependancies :
x -> a
x[0] -> a
x[1] -> a
Hence, gen_children "x" produces "x[0]", and "x[1]"
*)letrec(gen_children:Soc.var_expr->Soc.var_exprlist)=funv->matchSoc.data_type_of_var_exprvwith|Data.Alpha_|Data.Extern_|Data.Enum_|Data.String|Data.Bool|Data.Int|Data.Real->[v]|Data.Struct(_ident,ident_t_list)->List.fold_left(funacc(id,t)->letnew_ve=Soc.Field(v,id,t)innew_ve::((gen_childrennew_ve)@acc))[]ident_t_list|Data.Array(t,size)->letnew_ve_list=ref[]infori=0tosize-1doletnew_ve=Soc.Index(v,i,t)innew_ve_list:=new_ve::((gen_childrennew_ve)@!new_ve_list);done;!new_ve_list|Data.Alias(_,_t)->assertfalse(* sno ? *)letnodupll=List.fold_left(funaccx->ifList.memxaccthenaccelsex::acc)[]llet(get_var2actions_tbl:actionlist->var2actions_tbl)=funal->let(tabulate_action:var2actions_tbl->action->var2actions_tbl)=funtblaction->let_,_,lhs,_,_lxm=actioninlet(tabulate_output:var2actions_tbl->Soc.var_expr->var2actions_tbl)=funtbloutput->letv=(* get_top_var *)outputin(* for x of type t^2^2 *)letchildren=gen_childrenvin(* children(x[0]) = [x[0][0];x[0][1]] *)letparents=gen_parentsvin(* and parents(x[0]) = [x] *)letall=nodupl((v::children)@parents)inlettbl=(* add the current action as a dep of v and its children and its parents *)List.fold_left(funtblcv->letcv_actions=var2actionscvtblinVarMap.addcv(Actions.addactioncv_actions)tbl)tblallintblinList.fold_lefttabulate_outputtbllhsinList.fold_lefttabulate_actionVarMap.emptyal(** Returns the actions that depend on a set of vars, according to the content
of a table compute before
[actions_of_vars input_vars al] trouve toutes les actions de [al] qui
ont besoin d'être effectuées avant de pouvoir se servir de [input_vars]
comme entrée d'une autre action.
TODO: gérer les dépendances entre des filtres plus complexes,
comme par ex., l'utilisation d'un champ d'une structure.
*)let(_actions_of_vars_old:Soc.var_exprlist->var2actions_tbl->actionlist)=funvarstbl->letfind_depsvar=Actions.elements(var2actionsvartbl)in(* let vars = List.flatten (List.map gen_parents vars) in *)(* let vars = List.fold_left (* remove duplicates *) *)(* (fun acc x -> if List.mem x acc then acc else x::acc) [] vars *)(* in *)List.flatten(List.mapfind_depsvars)let(actions_of_vars:Soc.var_exprlist->var2actions_tbl->actionlist)=funvarstbl->letactions=List.fold_left(funaccv->Actions.unionacc(var2actionsvtbl))Actions.emptyvarsinActions.elementsactions(*********************************************************************************)(* Some Printers to ease the debugging *)letstring_of_actions:Actions.t->string=funs->letto_stringaacc=acc^"\n\t + '"^(Action.to_stringa)^"'"in""^(Actions.foldto_strings"")^""letstring_of_var2actions_tbl:var2actions_tbl->string=funs->letto_stringkeyvalueacc=letentry=Format.sprintf"%s depends on the following actions: %s"(SocUtils.string_of_filterkey)(string_of_actionsvalue)inacc^entry^"\n"in"var2actions_tbl: {\n"^(VarMap.foldto_strings"")^"}"letto_string:t->string=funm->letto_stringkeyvalueacc=letentry=Format.sprintf"- '%s' depends on:%s"(Action.to_stringkey)(string_of_actionsvalue)inacc^entry^"\n"in"dependencies between equations are: \n"^(MapAction.foldto_stringm"")^""(*
let (add_parents : var2actions_tbl -> var2actions_tbl) =
fun tbl ->
let f var actions acc =
let pvars = gen_parents var in
List.folf_left
(fun acc pvar ->
let pactions = try var2actions pvar acc with Not_found -> Actions.empty in
)
acc pvars
in
VarMap.fold f tbl tbl
*)(* It's useless to close this ; toposort will do it
let rec close : t -> t =
fun deps ->
let f action actions acc =
Actions.fold
(fun a acc ->
let a_actions = MapAction.find a acc in
let new_actions = Actions.union actions a_actions in
MapAction.add action new_actions acc
)
actions acc
in
let new_deps = MapAction.fold f deps deps in
if deps = new_deps (* use MapAction.equal ? *)
then deps else close new_deps
*)(*********************************************************************************)(* exported *)letbuild_data_deps_from_actions:(Lic.type_->Data.t)->t->actionlist->t=funlic_to_data_typedepsal->lettbl=get_var2actions_tblalin(* let tbl = add_parents tbl in *)letpp_dbg()=letal_str=List.mapAction.to_stringalinprint_string"\n ====> List of actions to be sorted:\n";print_string(String.concat"\n "al_str);print_string"\n ====> List of computed dependencies:\n";print_string(string_of_var2actions_tbltbl);flushstdoutinletdeps=Lv6Verbose.exe~flag:dbgpp_dbg;List.fold_left(funacc_depsaction->let(clk,rhs,_,_,_)=actioninletdep_vars=matchclkwith|Lic.BaseLic->rhs|Lic.ClockVar_int->rhs|Lic.On((_cc,cv,ct),_)->(* The guard should be computed before the guarded expression *)(Soc.Var(cv,lic_to_data_typect))::rhsinletdeps=actions_of_varsdep_varstblinifdeps=[]then(letrhs_str=String.concat","(List.mapSocUtils.string_of_filterrhs)inLv6Verbose.exe~flag:dbg(fun()->print_string("\n====> No deps for "^rhs_str));acc_deps)elseadd_depsacc_depsactiondeps)depsalin(* let deps = close deps in *)deps