Skip to content
Snippets Groups Projects
  • Erwan Jahier's avatar
    55efeade
    lic2soc: factorize some Soc.gao tests · 55efeade
    Erwan Jahier authored
    For the time being, we simple try to factorise out the test of
    consecutive gao that holds on the same clock.
    
    ps : also fix a pb (infinite loop in SortActions.topo_sort)
    introduced in the previous change that, for a strange reason
    (Makefile issue), was not catched by the test (almost all test were
    failing !!).
    
    pps : it actually seems to break quite a lot of test, but its my test
    script that wrong ! since version 527 (we are 534), the compiler used
    to perform the test in the tmp dirs is not upadated ! (well it is,
    but on the wrong machine...).
    
    I commit this change still as it introduces no more test failures.
    55efeade
    History
    lic2soc: factorize some Soc.gao tests
    Erwan Jahier authored
    For the time being, we simple try to factorise out the test of
    consecutive gao that holds on the same clock.
    
    ps : also fix a pb (infinite loop in SortActions.topo_sort)
    introduced in the previous change that, for a strange reason
    (Makefile issue), was not catched by the test (almost all test were
    failing !!).
    
    pps : it actually seems to break quite a lot of test, but its my test
    script that wrong ! since version 527 (we are 534), the compiler used
    to perform the test in the tmp dirs is not upadated ! (well it is,
    but on the wrong machine...).
    
    I commit this change still as it introduces no more test failures.
sortActions.ml 5.50 KiB
(** Time-stamp: <modified the 07/10/2014 (at 16:21) by Erwan Jahier> *)

(** topological sort of actions (that may optimize test openning) *)

open ActionsDeps

(*********************************************************************************)
module OrderedAction = struct
  type t = ActionsDeps.action
  let compare = compare
end
module MapAction = Map.Make(OrderedAction)


type color = Grey | Black (* in process | done *)
type color_table = color MapAction.t

exception DependencyCycle of action * action list
(* exception DependencyCycle of Soc.var_expr list *)

let (grey_actions : color_table -> ActionsDeps.action list) =
  fun ct -> 
    MapAction.fold
      (fun action color acc -> if color=Grey then action::acc else acc) ct []

let rec (visit : ActionsDeps.t -> color_table -> ActionsDeps.action -> color_table) =
  fun succ_t color_t n ->
    if not (ActionsDeps.have_deps succ_t n) then MapAction.add n Black color_t else
      let color_t =
	     List.fold_left
	       (fun color_t nt -> 
	         try
	           match MapAction.find nt color_t with
		          | Grey -> raise (DependencyCycle (n, grey_actions color_t))
		          | Black -> color_t
	         with 
		          (* The node [nt] is white *)
		          Not_found -> visit succ_t color_t nt
	       ) 
	       (MapAction.add n Grey color_t)
	       (ActionsDeps.find_deps succ_t n)
      in
	   MapAction.add n Black color_t

(* TEDLT *)
let (check_there_is_no_cycle : ActionsDeps.action list -> ActionsDeps.t -> unit) =
  fun actions t -> 
    List.iter (fun action -> ignore(visit t MapAction.empty action)) actions


let (topo_sort : ActionsDeps.action list -> ActionsDeps.t -> ActionsDeps.action list) =
  fun actions stbl -> 
    let visited_init = 
      List.fold_left (fun acc x -> MapAction.add x false acc) MapAction.empty actions 
    in
    let rec f (acc:action list) (l:action list) (stbl:t) (visited:bool MapAction.t) = 
      (* The graph contains no cycle! *)
      match l with
	     | [] -> List.rev acc
	     | x::tail -> 
	       if (try MapAction.find x visited with Not_found -> assert false)
	       then 
	         f acc tail stbl visited 
          else 
              let x_succ = ActionsDeps.find_deps stbl x in
              if x_succ = [] then
	             f (x::acc) tail stbl (MapAction.add x true visited)
              else
	             f acc (x_succ @ l) (ActionsDeps.remove_dep stbl x) visited
    in
    check_there_is_no_cycle actions stbl;
    f [] actions stbl visited_init

(*********************************************************************************)
(* From actions to gaos, optimizing test openning *)

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 -> (* should not occur ?*)
        Soc.Call (ol, op, il)
      | Lic.On((value, cvar, _ctyp), inner_clock) ->
(*         let inner_clock = match inner_clock_opt with *)
(*           | Some x -> x *)
(*           | None ->  *)
(*                 (* TODO? Retreive the clock of c *) *)
(*             Lv6errors.internal lxm; *)
(*             assert false  *)
(*         in *)
        Soc.Case (cvar, [Ident.string_of_long2 value, [unpack_clock inner_clock]] )
    in
    unpack_clock ck

(*********************************************************************************)
(* [my_assoc x l] returns the elt associated to x in l plus l without (x,elt) *)
let my_assoc x l = 
  let rec aux acc = function
  | [] -> None
  | (a,b)::l -> if compare a x = 0 then Some(b,List.rev_append acc l) else aux ((a,b)::acc) l
  in 
  aux [] l

(* Simple optimisation : when 2 consecutive gao holds on the same clock, we
   try to factorize them out.
*)
let (optimize_test_openning: Soc.gao list -> ActionsDeps.t -> Soc.gao list) =
  fun gaol deps ->
    let rec aux acc gaol = match gaol with 
      | []  -> List.rev acc
      | [a] -> List.rev (a::acc)
      | Soc.Call(o,op,i)::tail -> aux (Soc.Call(o,op,i)::acc) tail 
      | a1::Soc.Call(o,op,i)::tail ->  aux (Soc.Call(o,op,i)::a1::acc) tail 
      | Case(v1,l1)::Case(v2,l2)::tail -> 
        if v1 <> v2 then aux (Soc.Case(v1,l1)::acc) (Case(v2,l2)::tail) else
          let l = merge_gaol l1 l2 [] in
          aux acc (Soc.Case(v1,l)::tail) 
            
    and (merge_gaol : (string * Soc.gao list) list -> (string * Soc.gao list) list -> 
         (string * Soc.gao list) list -> (string * Soc.gao list) list) =
      fun l1 l2 acc -> 
        match l1 with
          | [] -> if l2 = [] then List.rev acc else List.rev_append acc l2
          | (x1,gaol1)::l1 -> 
            (match my_assoc x1 l2 with
              | None -> merge_gaol l1 l2 ((x1,gaol1)::acc)
              | Some(gaol2,l2) -> 
                let gaol = aux [] (gaol1@gaol2) in
                merge_gaol l1 l2 ((x1,gaol)::acc)
            )
    in
    aux [] gaol

(*********************************************************************************)

let (f : action list -> ActionsDeps.t -> Lxm.t -> Soc.gao list) = 
  fun actions deps lxm -> 
    let actions = 
      try topo_sort actions deps
      with DependencyCycle(x,l) ->
        let l = List.map ActionsDeps.string_of_action_simple l in
        let msg = "A combinational cycle been detected "^
          (Lxm.details lxm)^" on \n  "^(ActionsDeps.string_of_action_simple x)^
          "\n  "^(String.concat "\n  " l) ^ "\n\nHint: try to use --expand-nodes.\n"
        in
        raise (Lv6errors.Global_error msg)
    in
    let gaol = List.map gao_of_action actions in
     optimize_test_openning gaol deps 
(*     gaol *)