abc9: Fix breaking of SCCs
authorDavid Shah <dave@ds0.me>
Sun, 1 Dec 2019 20:44:56 +0000 (20:44 +0000)
committerDavid Shah <dave@ds0.me>
Sun, 1 Dec 2019 20:44:56 +0000 (20:44 +0000)
Signed-off-by: David Shah <dave@ds0.me>
passes/techmap/abc9.cc
tests/simple_abc9/abc9.v

index 27106cc5dfd6d8a5de3d9ad20b50d924375f8bd5..8276c3c16f815dbf65b4dd0a182458693b2978d3 100644 (file)
@@ -94,20 +94,30 @@ void handle_loops(RTLIL::Design *design)
                                        if (cell->output(c.first)) {
                                                SigBit b = c.second.as_bit();
                                                Wire *w = b.wire;
-                                               log_assert(!w->port_input);
-                                               w->port_input = true;
-                                               w = module->wire(stringf("%s.abci", w->name.c_str()));
-                                               if (!w) {
-                                                       w = module->addWire(stringf("%s.abci", b.wire->name.c_str()), GetSize(b.wire));
-                                                       w->port_output = true;
+                                               if (w->port_input) {
+                                                       // In this case, hopefully the loop break has been already created
+                                                       // Get the non-prefixed wire
+                                                       Wire *wo = module->wire(stringf("%s.abco", b.wire->name.c_str()));
+                                                       log_assert(wo != nullptr);
+                                                       log_assert(wo->port_output);
+                                                       log_assert(b.offset < GetSize(wo));
+                                                       c.second = RTLIL::SigBit(wo, b.offset);
                                                }
                                                else {
-                                                       log_assert(w->port_input);
-                                                       log_assert(b.offset < GetSize(w));
+                                                       // Create a new output/input loop break
+                                                       w->port_input = true;
+                                                       w = module->wire(stringf("%s.abco", w->name.c_str()));
+                                                       if (!w) {
+                                                               w = module->addWire(stringf("%s.abco", b.wire->name.c_str()), GetSize(b.wire));
+                                                               w->port_output = true;
+                                                       }
+                                                       else {
+                                                               log_assert(w->port_input);
+                                                               log_assert(b.offset < GetSize(w));
+                                                       }
+                                                       w->set_bool_attribute(ID(abc9_scc_break));
+                                                       c.second = RTLIL::SigBit(w, b.offset);
                                                }
-                                               w->set_bool_attribute(ID(abc9_scc_break));
-                                               module->swap_names(b.wire, w);
-                                               c.second = RTLIL::SigBit(w, b.offset);
                                        }
                                }
                        }
@@ -420,24 +430,6 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
 
                design->selection_stack.pop_back();
 
-               // Now 'unexpose' those wires by undoing
-               // the expose operation -- remove them from PO/PI
-               // and re-connecting them back together
-               for (auto wire : module->wires()) {
-                       auto it = wire->attributes.find(ID(abc9_scc_break));
-                       if (it != wire->attributes.end()) {
-                               wire->attributes.erase(it);
-                               log_assert(wire->port_output);
-                               wire->port_output = false;
-                               RTLIL::Wire *i_wire = module->wire(wire->name.str() + ".abci");
-                               log_assert(i_wire);
-                               log_assert(i_wire->port_input);
-                               i_wire->port_input = false;
-                               module->connect(i_wire, wire);
-                       }
-               }
-               module->fixup_ports();
-
                log_header(design, "Executing ABC9.\n");
 
                if (!lut_costs.empty()) {
@@ -781,6 +773,25 @@ clone_lut:
                        }
                }
 
+               // Now 'unexpose' those wires by undoing
+               // the expose operation -- remove them from PO/PI
+               // and re-connecting them back together
+               for (auto wire : module->wires()) {
+                       auto it = wire->attributes.find(ID(abc9_scc_break));
+                       if (it != wire->attributes.end()) {
+                               wire->attributes.erase(it);
+                               log_assert(wire->port_output);
+                               wire->port_output = false;
+                               std::string name = wire->name.str();
+                               RTLIL::Wire *i_wire = module->wire(name.substr(0, GetSize(name) - 5));
+                               log_assert(i_wire);
+                               log_assert(i_wire->port_input);
+                               i_wire->port_input = false;
+                               module->connect(i_wire, wire);
+                       }
+               }
+               module->fixup_ports();
+
                //log("ABC RESULTS:        internal signals: %8d\n", int(signal_list.size()) - in_wires - out_wires);
                log("ABC RESULTS:           input signals: %8d\n", in_wires);
                log("ABC RESULTS:          output signals: %8d\n", out_wires);
index 4d5879e6f3de15110ca3827b0a81322324470245..de60619d1b71ebf54929995e3c79add0942d96df 100644 (file)
@@ -258,3 +258,9 @@ module abc9_test026(output [3:0] o, p);
 assign o = { 1'b1, 1'bx };
 assign p = { 1'b1, 1'bx, 1'b0 };
 endmodule
+
+module abc9_test030(input [3:0] d, input en, output reg [3:0] q);
+always @*
+  if (en)
+    q <= d;
+endmodule