Fix issue #639
authorTK Lam <tklam@easylogic.hk>
Wed, 26 Sep 2018 08:11:45 +0000 (16:11 +0800)
committerTK Lam <tklam@easylogic.hk>
Wed, 26 Sep 2018 08:11:45 +0000 (16:11 +0800)
passes/equiv/equiv_make.cc

index b1f88d55ea85a47346aea5e03f0b0ebd0744ddac..8590c820b76152aa05f7c92e5e5f4a6cbd4e2d48 100644 (file)
@@ -40,6 +40,8 @@ struct EquivMakeWorker
        pool<SigBit> undriven_bits;
        SigMap assign_map;
 
+       dict<SigBit, pool<Cell*>> bit2driven; // map: bit <--> and its driven cells
+
        void read_blacklists()
        {
                for (auto fn : blacklists)
@@ -278,12 +280,20 @@ struct EquivMakeWorker
                        }
                }
 
+               init_bit2driven();
+
+               pool<Cell*> visited_cells;
                for (auto c : cells_list)
                for (auto &conn : c->connections())
                        if (!ct.cell_output(c->type, conn.first)) {
                                SigSpec old_sig = assign_map(conn.second);
                                SigSpec new_sig = rd_signal_map(old_sig);
+                               
+                               visited_cells.clear();
                                if (old_sig != new_sig) {
+                                       if (check_signal_in_fanout(visited_cells, old_sig, new_sig)) 
+                                               continue;
+
                                        log("Changing input %s of cell %s (%s): %s -> %s\n",
                                                        log_id(conn.first), log_id(c), log_id(c->type),
                                                        log_signal(old_sig), log_signal(new_sig));
@@ -378,6 +388,54 @@ struct EquivMakeWorker
                }
        }
 
+       void init_bit2driven()
+       {
+               for (auto cell : equiv_mod->cells()) {
+                       if (!ct.cell_known(cell->type) && !cell->type.in("$dff", "$_DFF_P_", "$_DFF_N_", "$ff", "$_FF_"))
+                               continue;
+                       for (auto &conn : cell->connections())
+                       {
+                               if (yosys_celltypes.cell_input(cell->type, conn.first))
+                                       for (auto bit : assign_map(conn.second))
+                                       {
+                                               bit2driven[bit].insert(cell);
+                                       }
+                       }
+               }
+       }
+
+       bool check_signal_in_fanout(pool<Cell*> visited_cells, SigBit source_bit, SigBit target_bit)
+       {
+               if (source_bit == target_bit)
+                       return true;
+
+               if (bit2driven.count(source_bit) == 0)
+                       return false;
+
+               auto driven_cells = bit2driven.at(source_bit);
+               for (auto driven_cell: driven_cells)
+               {
+                       if (visited_cells.count(driven_cell) > 0)
+                               continue;
+
+                       visited_cells.insert(driven_cell);
+
+                       for (auto &conn: driven_cell->connections())
+                       {
+                               if (yosys_celltypes.cell_input(driven_cell->type, conn.first))
+                                       continue;
+
+                               for (auto bit: conn.second) {
+                                       bool is_in_fanout = check_signal_in_fanout(visited_cells, bit, target_bit);
+                                       if (is_in_fanout == true)
+                                               return true;
+                               }
+                       }
+               }
+
+               return false;
+       }
+
        void run()
        {
                copy_to_equiv();