Assert on new logic loops in "share" pass
authorClifford Wolf <clifford@clifford.at>
Sun, 21 Sep 2014 10:57:33 +0000 (12:57 +0200)
committerClifford Wolf <clifford@clifford.at>
Sun, 21 Sep 2014 10:57:33 +0000 (12:57 +0200)
kernel/utils.h
passes/opt/share.cc

index 7f10619bc98086180b0c0b3293b8c7899736e3fe..a03caf8042224e05a8ebb714afca8917e61a3e11 100644 (file)
@@ -155,7 +155,7 @@ struct TopoSort
        void sort_worker(const T &n, std::set<T> &marked_cells, std::set<T> &active_cells, std::vector<T> &active_stack)
        {
                if (active_cells.count(n)) {
-                       found_loops = false;
+                       found_loops = true;
                        if (analyze_loops) {
                                std::set<T> loop;
                                for (int i = SIZE(active_stack)-1; i >= 0; i--) {
index c372ed78a853ab46488f83ff9e87e05bd362f8f5..02e845846d10ef9d99c61d84d3c375e550eb40fe 100644 (file)
@@ -21,6 +21,7 @@
 #include "kernel/satgen.h"
 #include "kernel/sigtools.h"
 #include "kernel/modtools.h"
+#include "kernel/utils.h"
 
 PRIVATE_NAMESPACE_BEGIN
 
@@ -640,6 +641,48 @@ struct ShareWorker
        }
 
 
+       // ------------------------------------------------------------------------------------------------
+       // Find SCCs (logic loops). This is only used to make sure that this pass does not introduce loops.
+       // ------------------------------------------------------------------------------------------------
+
+       bool module_has_scc()
+       {
+               SigMap sigmap(module);
+
+               CellTypes ct;
+               ct.setup_internals();
+               ct.setup_stdcells();
+
+               TopoSort<RTLIL::Cell*> toposort;
+               toposort.analyze_loops = false;
+
+               std::map<RTLIL::Cell*, std::set<RTLIL::SigBit>> cell_to_bits;
+               std::map<RTLIL::SigBit, std::set<RTLIL::Cell*>> bit_to_cells;
+
+               for (auto cell : module->cells())
+                       if (ct.cell_known(cell->type))
+                               for (auto &conn : cell->connections()) {
+                                       if (ct.cell_output(cell->type, conn.first))
+                                               for (auto bit : sigmap(conn.second))
+                                                       cell_to_bits[cell].insert(bit);
+                                       else
+                                               for (auto bit : sigmap(conn.second))
+                                                       bit_to_cells[bit].insert(cell);
+                               }
+
+               for (auto &it : cell_to_bits)
+               {
+                       RTLIL::Cell *c1 = it.first;
+
+                       for (auto bit : it.second)
+                       for (auto c2 : bit_to_cells[bit])
+                               toposort.edge(c1, c2);
+               }
+
+               return !toposort.sort();
+       }
+
+
        // -------------
        // Setup and run
        // -------------
@@ -647,6 +690,8 @@ struct ShareWorker
        ShareWorker(ShareWorkerConfig config, RTLIL::Design *design, RTLIL::Module *module) :
                        config(config), design(design), module(module)
        {
+               bool before_scc = module_has_scc();
+
                generic_ops.insert(config.generic_uni_ops.begin(), config.generic_uni_ops.end());
                generic_ops.insert(config.generic_bin_ops.begin(), config.generic_bin_ops.end());
                generic_ops.insert(config.generic_cbin_ops.begin(), config.generic_cbin_ops.end());
@@ -879,6 +924,9 @@ struct ShareWorker
                }
 
                log_assert(recursion_state.empty());
+
+               bool after_scc = before_scc || module_has_scc();
+               log_assert(before_scc == after_scc);
        }
 };