Added handling of multiple async paths in proc_arst
authorClifford Wolf <clifford@clifford.at>
Fri, 18 Oct 2013 22:50:13 +0000 (00:50 +0200)
committerClifford Wolf <clifford@clifford.at>
Fri, 18 Oct 2013 22:50:13 +0000 (00:50 +0200)
passes/proc/proc_arst.cc
passes/proc/proc_clean.cc

index d0a0d864c62f9b8d5f6163f0e08c77fe80cb5b29..021d87c81919f691852bd9c29d969c2cef4db8b3 100644 (file)
@@ -23,6 +23,9 @@
 #include <stdlib.h>
 #include <stdio.h>
 
+// defined in proc_clean.cc
+extern void proc_clean_case(RTLIL::CaseRule *cs, bool &did_something, int &count, int max_depth);
+
 static bool check_signal(RTLIL::Module *mod, RTLIL::SigSpec signal, RTLIL::SigSpec ref, bool &polarity)
 {
        if (signal.width != 1)
@@ -132,10 +135,18 @@ static void eliminate_const(RTLIL::Module *mod, RTLIL::CaseRule *cs, RTLIL::SigS
                                eliminate_const(mod, cs2, const_sig, polarity);
                }
        }
+
+       int dummy_count = 0;
+       bool did_something = true;
+       while (did_something) {
+               did_something = false;
+               proc_clean_case(cs, did_something, dummy_count, 1);
+       }
 }
 
 static void proc_arst(RTLIL::Module *mod, RTLIL::Process *proc, SigMap &assign_map)
 {
+restart_proc_arst:
        if (proc->root_case.switches.size() != 1)
                return;
 
@@ -173,6 +184,7 @@ static void proc_arst(RTLIL::Module *mod, RTLIL::Process *proc, SigMap &assign_m
                                        action.second = rval;
                                }
                                eliminate_const(mod, &proc->root_case, root_sig, polarity);
+                               goto restart_proc_arst;
                        }
                }
        }
index e247f2882e3fe6f310ac5d20ca7b0d9d2c007153..83554df908bb28e9e237e54c3218268096746304 100644 (file)
 #include <stdlib.h>
 #include <stdio.h>
 
-static void switch_clean(RTLIL::SwitchRule *sw, RTLIL::CaseRule *parent, bool &did_something, int &count);
-static void case_clean(RTLIL::CaseRule *cs, bool &did_something, int &count);
+extern void proc_clean_switch(RTLIL::SwitchRule *sw, RTLIL::CaseRule *parent, bool &did_something, int &count, int max_depth);
+extern void proc_clean_case(RTLIL::CaseRule *cs, bool &did_something, int &count, int max_depth);
 
-static void switch_clean(RTLIL::SwitchRule *sw, RTLIL::CaseRule *parent, bool &did_something, int &count)
+void proc_clean_switch(RTLIL::SwitchRule *sw, RTLIL::CaseRule *parent, bool &did_something, int &count, int max_depth)
 {
        if (sw->signal.width > 0 && sw->signal.is_fully_const())
        {
@@ -76,7 +76,8 @@ static void switch_clean(RTLIL::SwitchRule *sw, RTLIL::CaseRule *parent, bool &d
                for (auto cs : sw->cases) {
                        if (cs->actions.size() != 0 || cs->switches.size() != 0)
                                all_cases_are_empty = false;
-                       case_clean(cs, did_something, count);
+                       if (max_depth != 0)
+                               proc_clean_case(cs, did_something, count, max_depth-1);
                }
                if (all_cases_are_empty) {
                        did_something = true;
@@ -87,7 +88,7 @@ static void switch_clean(RTLIL::SwitchRule *sw, RTLIL::CaseRule *parent, bool &d
        }
 }
 
-static void case_clean(RTLIL::CaseRule *cs, bool &did_something, int &count)
+void proc_clean_case(RTLIL::CaseRule *cs, bool &did_something, int &count, int max_depth)
 {
        for (size_t i = 0; i < cs->actions.size(); i++) {
                if (cs->actions[i].first.width == 0) {
@@ -102,8 +103,8 @@ static void case_clean(RTLIL::CaseRule *cs, bool &did_something, int &count)
                        did_something = true;
                        delete sw;
                        count++;
-               } else
-                       switch_clean(sw, cs, did_something, count);
+               } else if (max_depth != 0)
+                       proc_clean_switch(sw, cs, did_something, count, max_depth-1);
        }
 }
 
@@ -122,7 +123,7 @@ static void proc_clean(RTLIL::Module *mod, RTLIL::Process *proc, int &total_coun
        }
        while (did_something) {
                did_something = false;
-               case_clean(&proc->root_case, did_something, count);
+               proc_clean_case(&proc->root_case, did_something, count, -1);
        }
        if (count > 0)
                log("Found and cleaned up %d empty switch%s in `%s.%s'.\n", count, count == 1 ? "" : "es", mod->name.c_str(), proc->name.c_str());