From 244a51086c20dbd937dd21f1eb9c4b74acc5a3c9 Mon Sep 17 00:00:00 2001 From: Alex AUVOLAT Date: Tue, 5 Nov 2013 18:29:27 +0100 Subject: More simplifcation passes... --- sched/graph.ml | 27 ++++++++++++++++-- sched/main.ml | 14 ++++++++-- sched/scheduler.ml | 23 ++++++++++++---- sched/simplify.ml | 80 ++++++++++++++++++++++++++++++++++++------------------ 4 files changed, 109 insertions(+), 35 deletions(-) (limited to 'sched') diff --git a/sched/graph.ml b/sched/graph.ml index 54128ff..ad4fded 100644 --- a/sched/graph.ml +++ b/sched/graph.ml @@ -44,7 +44,7 @@ let has_cycle g = ret in let ret = List.fold_left (fun x n -> x || (if n.n_mark = Visited then false else visit n)) false g.g_nodes - in clear_marks g; ret;; + in clear_marks g; ret let topological g = clear_marks g; @@ -57,5 +57,28 @@ let topological g = end in let ret = List.fold_left (fun x n -> aux x n) [] g.g_nodes - in clear_marks g; List.rev ret;; + in clear_marks g; List.rev ret +let topological_from_roots g roots = + clear_marks g; + let rec aux acc n = + if n.n_mark = Visited + then acc + else begin + n.n_mark <- Visited; + n.n_label :: (List.fold_left (fun x n -> aux x n) acc n.n_linked_by) + end + in + let ret = List.fold_left + (fun x n -> aux x (node_for_label g n)) [] roots + in + let used = List.fold_left + (fun s n -> + if n.n_mark = Visited then + n.n_label::s + else + s) + [] + g.g_nodes in + clear_marks g; + List.rev ret, used diff --git a/sched/main.ml b/sched/main.ml index a2a4d3b..1b4b9d8 100644 --- a/sched/main.ml +++ b/sched/main.ml @@ -8,10 +8,13 @@ let compile filename = let p = Netlist.read_file filename in let out_name = (Filename.chop_suffix filename ".net") ^ "_sch.net" in let dumb_out_name = (Filename.chop_suffix filename ".net") ^ ".dumb" in - let q = ref p in + let out_opt_name = (Filename.chop_suffix filename ".net") ^ "_sch_opt.net" in + let dumb_opt_out_name = (Filename.chop_suffix filename ".net") ^ "_opt.dumb" in + let q, q_opt = ref p, ref p in begin try - q := (Simplify.simplify (Scheduler.schedule p)) + q := Scheduler.schedule p; + q_opt := Simplify.simplify p with | Scheduler.Combinational_cycle -> Format.eprintf "The netlist has a combinatory cycle.@."; @@ -25,6 +28,13 @@ let compile filename = Netlist_printer.print_dumb_program dumb_out !q; close_out dumb_out; + let out_opt = open_out out_opt_name in + Netlist_printer.print_program out_opt !q_opt; + close_out out_opt; + let dumb_opt_out = open_out dumb_opt_out_name in + Netlist_printer.print_dumb_program dumb_opt_out !q_opt; + close_out dumb_opt_out; + if !simulate then ( let simulator = if !number_steps = -1 then diff --git a/sched/scheduler.ml b/sched/scheduler.ml index 130164b..34ce3aa 100644 --- a/sched/scheduler.ml +++ b/sched/scheduler.ml @@ -21,11 +21,15 @@ let read_exp eq = | Eslice(_, _, a) -> add_arg a [] | Eselect(_, a) -> add_arg a [] in - aux eq;; + aux eq -let schedule p = +let prog_eq_map p = + List.fold_left + (fun x (vn, eqn) -> Smap.add vn eqn x) + Smap.empty p.p_eqs + +let prog_graph p eq_map = let graph = Graph.mk_graph() in - let eq_map = List.fold_left (fun x (vn, eqn) -> Smap.add vn eqn x) Smap.empty p.p_eqs in (* Add variables as graph nodes *) List.iter (fun (k, _) -> Graph.add_node graph k) p.p_eqs; (* Add dependencies as graph edges *) @@ -36,17 +40,26 @@ let schedule p = p.p_eqs; (* Verify there are no cycles *) if Graph.has_cycle graph then raise Combinational_cycle; + graph + +let schedule p = + let eq_map = prog_eq_map p in + let graph = prog_graph p eq_map in + (* Topological sort of graph nodes *) let topo_vars = Graph.topological graph in (* Construct new program with sorted expression list *) { p_eqs = List.fold_right - (fun n x -> if Smap.mem n eq_map then (n, Smap.find n eq_map)::x else x) topo_vars []; + (fun n x -> + if Smap.mem n eq_map then + (n, Smap.find n eq_map)::x + else x) + topo_vars []; p_inputs = p.p_inputs; p_outputs = p.p_outputs; p_vars = p.p_vars; } - ;; diff --git a/sched/simplify.ml b/sched/simplify.ml index 01f7c84..ae5ec65 100644 --- a/sched/simplify.ml +++ b/sched/simplify.ml @@ -8,14 +8,15 @@ - transform k = SELECT 0 var into k = var when var is also one bit - look for variables with same equation, put the second to identity - eliminate k' for each equation k' = k - - eliminate dead equations + - topological sort - These simplifications are run on a topologically sorted list of equations (see main.ml) + TODO : eliminate unused variables. problem : they are hard to identify *) open Netlist_ast module Sset = Set.Make(String) +module Smap = Map.Make(String) (* Simplify cascade slicing/selecting *) let cascade_slices p = @@ -23,15 +24,14 @@ let cascade_slices p = let eqs_new = List.map (fun (n, eq) -> (n, match eq with | Eslice(u, v, Avar(x)) -> - let nu, nx = + let dec, nx = if Hashtbl.mem slices x then begin - let ku, kx = Hashtbl.find slices x in - (ku + u, kx) + Hashtbl.find slices x end else - (u, x) + (0, x) in - Hashtbl.add slices n (nu, nx); - Eslice(nu, v, Avar(nx)) + Hashtbl.add slices n (u + dec, nx); + Eslice(u + dec, v + dec, Avar(nx)) | Eselect(u, Avar(x)) -> begin try let ku, kx = Hashtbl.find slices x in @@ -46,7 +46,7 @@ let cascade_slices p = p_inputs = p.p_inputs; p_outputs = p.p_outputs; p_vars = p.p_vars; - } + }, false (* Simplifies some trivial arithmetic possibilites : a and 1 = a @@ -55,6 +55,9 @@ let cascade_slices p = a or 0 = a a xor 0 = a slice i i x = select i x + concat const const = const.const + slice i j const = const.[i..j] + select i const = const.[i] *) let arith_simplify p = { @@ -75,13 +78,30 @@ let arith_simplify p = | Eslice(i, j, k) when i = j -> (n, Eselect(i, k)) + + | Econcat(Aconst(a), Aconst(b)) -> + let aa = match a with + | VBit(a) -> [| a |] + | VBitArray(a) -> a + in + let ba = match b with + | VBit(a) -> [| a |] + | VBitArray(a) -> a + in + (n, Earg(Aconst(VBitArray(Array.append aa ba)))) + + | Eslice(i, j, Aconst(VBitArray(a))) -> + (n, Earg(Aconst(VBitArray(Array.sub a i (j - i + 1))))) + + | Eselect(i, Aconst(VBitArray(a))) -> + (n, Earg(Aconst(VBit(a.(i))))) | _ -> (n, eq)) p.p_eqs; p_inputs = p.p_inputs; p_outputs = p.p_outputs; p_vars = p.p_vars; - } + }, false (* if x is one bit, then : select 0 x = x @@ -98,7 +118,7 @@ let select_to_id p = p_inputs = p.p_inputs; p_outputs = p.p_outputs; p_vars = p.p_vars; - } + }, false (* If a = eqn(v1, v2, ...) and b = eqn(v1, v2, ...) <- the same equation @@ -128,7 +148,7 @@ let same_eq_simplify p = p_inputs = p.p_inputs; p_outputs = p.p_outputs; p_vars = p.p_vars; - } + }, false (* Replace one specific variable by another argument in the arguments of all equations @@ -192,23 +212,31 @@ let rec eliminate_id p = | None -> p, false | Some(n, rep) -> fst (eliminate_id (eliminate_var n rep p)), true - -(* Eliminate dead equations *) -let eliminate_dead p = - p, false (* TODO *) - (* a bit like a topological sort... *) - +(* Topological sort *) +let topo_sort p = + (Scheduler.schedule p, false) (* Apply all the simplification passes, in the order given in the header of this file *) +let dump_varlist p = + print_string "Eq list:\n"; + List.iter (fun (n, _) -> print_string ("- "^n^"\n")) p.p_eqs + let rec simplify p = - let p1 = cascade_slices p in - let p2 = arith_simplify p1 in - let p3 = select_to_id p2 in - let p4 = same_eq_simplify p3 in - let p5, use5 = eliminate_id p4 in - let p6, use6 = eliminate_dead p5 in - let pp = p6 in - if use5 || use6 then simplify pp else pp + let steps = [ + cascade_slices; + arith_simplify; + select_to_id; + same_eq_simplify; + eliminate_id; + topo_sort; + ] in + let pp, use = List.fold_left + (fun (x, u) f -> + let xx, uu = f x in + dump_varlist xx; + (xx, u || uu)) + (p, false) steps in + if use then simplify pp else pp -- cgit v1.2.3