Bugfix in fsm_detect for complex muxtrees
authorClifford Wolf <clifford@clifford.at>
Tue, 18 Aug 2015 12:17:50 +0000 (14:17 +0200)
committerClifford Wolf <clifford@clifford.at>
Tue, 18 Aug 2015 12:17:50 +0000 (14:17 +0200)
passes/fsm/fsm_detect.cc

index 7a621b567e9035e41ae8029f20cb316c52fbea4a..feeaa347cfd1998e7809a84631ed880c9d78ed54 100644 (file)
@@ -34,7 +34,7 @@ static SigSet<sig2driver_entry_t> sig2driver, sig2user;
 static std::set<RTLIL::Cell*> muxtree_cells;
 static SigPool sig_at_port;
 
-static bool check_state_mux_tree(RTLIL::SigSpec old_sig, RTLIL::SigSpec sig, SigPool &recursion_monitor)
+static bool check_state_mux_tree(RTLIL::SigSpec old_sig, RTLIL::SigSpec sig, pool<Cell*> &recursion_monitor)
 {
        if (sig_at_port.check_any(assign_map(sig)))
                return false;
@@ -42,31 +42,39 @@ static bool check_state_mux_tree(RTLIL::SigSpec old_sig, RTLIL::SigSpec sig, Sig
        if (sig.is_fully_const() || old_sig == sig)
                return true;
 
-       if (recursion_monitor.check_any(sig)) {
-               log_warning("logic loop in mux tree at signal %s in module %s.\n",
-                               log_signal(sig), RTLIL::id2cstr(module->name));
-               return false;
-       }
-
-       recursion_monitor.add(sig);
-
        std::set<sig2driver_entry_t> cellport_list;
        sig2driver.find(sig, cellport_list);
-       for (auto &cellport : cellport_list) {
+       for (auto &cellport : cellport_list)
+       {
                if ((cellport.first->type != "$mux" && cellport.first->type != "$pmux") || cellport.second != "\\Y")
                        return false;
+
+               if (recursion_monitor.count(cellport.first)) {
+                       log_warning("logic loop in mux tree at signal %s in module %s.\n",
+                                       log_signal(sig), RTLIL::id2cstr(module->name));
+                       return false;
+               }
+
+               recursion_monitor.insert(cellport.first);
+
                RTLIL::SigSpec sig_a = assign_map(cellport.first->getPort("\\A"));
                RTLIL::SigSpec sig_b = assign_map(cellport.first->getPort("\\B"));
-               if (!check_state_mux_tree(old_sig, sig_a, recursion_monitor))
+
+               if (!check_state_mux_tree(old_sig, sig_a, recursion_monitor)) {
+                       recursion_monitor.erase(cellport.first);
                        return false;
+               }
+
                for (int i = 0; i < sig_b.size(); i += sig_a.size())
-                       if (!check_state_mux_tree(old_sig, sig_b.extract(i, sig_a.size()), recursion_monitor))
+                       if (!check_state_mux_tree(old_sig, sig_b.extract(i, sig_a.size()), recursion_monitor)) {
+                               recursion_monitor.erase(cellport.first);
                                return false;
+                       }
+
+               recursion_monitor.erase(cellport.first);
                muxtree_cells.insert(cellport.first);
        }
 
-       recursion_monitor.del(sig);
-
        return true;
 }
 
@@ -111,7 +119,7 @@ static void detect_fsm(RTLIL::Wire *wire)
                if ((cellport.first->type != "$dff" && cellport.first->type != "$adff") || cellport.second != "\\Q")
                        continue;
                muxtree_cells.clear();
-               SigPool recursion_monitor;
+               pool<Cell*> recursion_monitor;
                RTLIL::SigSpec sig_q = assign_map(cellport.first->getPort("\\Q"));
                RTLIL::SigSpec sig_d = assign_map(cellport.first->getPort("\\D"));
                if (sig_q == RTLIL::SigSpec(wire) && check_state_mux_tree(sig_q, sig_d, recursion_monitor) && check_state_users(sig_q)) {