Fixed performance bug in proc_dlatch
authorClifford Wolf <clifford@clifford.at>
Sun, 24 Apr 2016 17:29:56 +0000 (19:29 +0200)
committerClifford Wolf <clifford@clifford.at>
Sun, 24 Apr 2016 17:29:56 +0000 (19:29 +0200)
passes/proc/proc_dlatch.cc

index c339ac682112f37285c5db740494085dd51a860c..92bf8906d47de20300575eefb46e53d7cedb0125 100644 (file)
@@ -33,6 +33,7 @@ struct proc_dlatch_db_t
        Module *module;
        SigMap sigmap;
 
+       dict<Cell*, vector<SigBit>> mux_srcbits;
        dict<SigBit, pair<Cell*, int>> mux_drivers;
        dict<SigBit, int> sigusers;
 
@@ -40,10 +41,24 @@ struct proc_dlatch_db_t
        {
                for (auto cell : module->cells())
                {
-                       if (cell->type.in("$mux", "$pmux")) {
+                       if (cell->type.in("$mux", "$pmux"))
+                       {
                                auto sig_y = sigmap(cell->getPort("\\Y"));
                                for (int i = 0; i < GetSize(sig_y); i++)
                                        mux_drivers[sig_y[i]] = pair<Cell*, int>(cell, i);
+
+                               pool<SigBit> mux_srcbits_pool;
+                               for (auto bit : sigmap(cell->getPort("\\A")))
+                                       mux_srcbits_pool.insert(bit);
+                               for (auto bit : sigmap(cell->getPort("\\B")))
+                                       mux_srcbits_pool.insert(bit);
+
+                               vector<SigBit> mux_srcbits_vec;
+                               for (auto bit : mux_srcbits_pool)
+                                       if (bit.wire != nullptr)
+                                               mux_srcbits_vec.push_back(bit);
+
+                               mux_srcbits[cell].swap(mux_srcbits_vec);
                        }
 
                        for (auto &conn : cell->connections())
@@ -58,6 +73,42 @@ struct proc_dlatch_db_t
                                        sigusers[bit]++;
        }
 
+       bool quickcheck(const SigSpec &haystack, const SigSpec &needle)
+       {
+               pool<SigBit> haystack_bits = sigmap(haystack).to_sigbit_pool();
+               pool<SigBit> needle_bits = sigmap(needle).to_sigbit_pool();
+
+               pool<Cell*> cells_queue, cells_visited;
+               pool<SigBit> bits_queue, bits_visited;
+
+               bits_queue = haystack_bits;
+               while (!bits_queue.empty())
+               {
+                       for (auto &bit : bits_queue) {
+                               auto it = mux_drivers.find(bit);
+                               if (it != mux_drivers.end())
+                                       if (!cells_visited.count(it->second.first))
+                                               cells_queue.insert(it->second.first);
+                               bits_visited.insert(bit);
+                       }
+
+                       bits_queue.clear();
+
+                       for (auto c : cells_queue) {
+                               for (auto bit : mux_srcbits[c]) {
+                                       if (needle_bits.count(bit))
+                                               return true;
+                                       if (!bits_visited.count(bit))
+                                               bits_queue.insert(bit);
+                               }
+                       }
+
+                       cells_queue.clear();
+               }
+
+               return false;
+       }
+
        struct rule_node_t
        {
                // a node is true if "signal" equals "match" and [any
@@ -218,9 +269,17 @@ void proc_dlatch(proc_dlatch_db_t &db, RTLIL::Process *proc)
                        continue;
                }
 
-               for (auto ss : sr->actions) {
+               for (auto ss : sr->actions)
+               {
                        db.sigmap.apply(ss.first);
                        db.sigmap.apply(ss.second);
+
+                       if (!db.quickcheck(ss.second, ss.first)) {
+                               nolatches_bits.first.append(ss.first);
+                               nolatches_bits.second.append(ss.second);
+                               continue;
+                       }
+
                        for (int i = 0; i < GetSize(ss.first); i++)
                                latches_out_in[ss.first[i]] = ss.second[i];
                }