Create one $shiftx per bit in width
authorEddie Hung <eddieh@ece.ubc.ca>
Mon, 25 Mar 2019 18:16:56 +0000 (11:16 -0700)
committerEddie Hung <eddieh@ece.ubc.ca>
Mon, 25 Mar 2019 18:16:56 +0000 (11:16 -0700)
passes/proc/proc_mux.cc

index 7cac0327b0743338fb51f595062ceb3d5e4170c6..7d3d2340828fe4ba14af3fa5c54999595022f25d 100644 (file)
@@ -340,7 +340,7 @@ RTLIL::SigSpec signal_to_mux_tree(RTLIL::Module *mod, SnippetSwCache &swcache, d
                // evaluate in reverse order to give the first entry the top priority
                RTLIL::SigSpec initial_val = result;
                RTLIL::Cell *last_mux_cell = NULL;
-               bool shiftx = true;
+               bool shiftx = initial_val.is_fully_undef();
                for (size_t i = 0; i < sw->cases.size(); i++) {
                        int case_idx = sw->cases.size() - i - 1;
                        RTLIL::CaseRule *cs2 = sw->cases[case_idx];
@@ -355,20 +355,27 @@ RTLIL::SigSpec signal_to_mux_tree(RTLIL::Module *mod, SnippetSwCache &swcache, d
                                // Keep checking if case condition is the same as the current case index
                                if (cs2->compare.size() == 1 && cs2->compare.front().is_fully_const())
                                        shiftx = (cs2->compare.front().as_int() == case_idx);
+                               else
+                                       shiftx = false;
                        }
                }
 
-               // Transform into a $shiftx if possible
+               // Transform into a $shiftx where possible
                if (shiftx && last_mux_cell->type == "$pmux") {
-                       // Sanity check that A port of $pmux should be 'bx
-                       log_assert(last_mux_cell->getPort("\\A").is_fully_undef());
-                       // Because we went in reverse order above, un-reverse its B port here
-                       auto b_port = last_mux_cell->getPort("\\B").chunks();
-                       std::reverse(b_port.begin(), b_port.end());
-                       // Create a $shiftx that shifts by the address line used in the case statement
-                       mod->addShiftx(NEW_ID, b_port, sw->signal, last_mux_cell->getPort("\\Y"));
+                       // Create bit-blasted $shiftx-es that shifts by the address line used in the case statement
+                       auto pmux_b_port = last_mux_cell->getPort("\\B");
+                       auto pmux_y_port = last_mux_cell->getPort("\\Y");
+                       int width = last_mux_cell->getParam("\\WIDTH").as_int();
+                       for (int i = 0; i < width; ++i) {
+                               RTLIL::SigSpec a_port;
+                               // Because we went in reverse order above, un-reverse $pmux's B port here
+                               for (int j = pmux_b_port.size()/width-1; j >= 0; --j)
+                                       a_port.append(pmux_b_port.extract(j*width+i, 1));
+                               // Create a $shiftx that shifts by the address line used in the case statement
+                               mod->addShiftx(NEW_ID, a_port, sw->signal, pmux_y_port.extract(i, 1));
+                       }
                        // Disconnect $pmux by replacing its output port with a floating wire
-                       last_mux_cell->setPort("\\Y", mod->addWire(NEW_ID, last_mux_cell->getParam("\\WIDTH").as_int()));
+                       last_mux_cell->setPort("\\Y", mod->addWire(NEW_ID, width));
                }
        }