From e9ce4e658b2dddfc808e1d0383a5b93a906e2bbb Mon Sep 17 00:00:00 2001 From: David Shah Date: Sun, 1 Dec 2019 20:44:56 +0000 Subject: [PATCH] abc9: Fix breaking of SCCs Signed-off-by: David Shah --- passes/techmap/abc9.cc | 69 +++++++++++++++++++++++----------------- tests/simple_abc9/abc9.v | 6 ++++ 2 files changed, 46 insertions(+), 29 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 27106cc5d..8276c3c16 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -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); diff --git a/tests/simple_abc9/abc9.v b/tests/simple_abc9/abc9.v index 4d5879e6f..de60619d1 100644 --- a/tests/simple_abc9/abc9.v +++ b/tests/simple_abc9/abc9.v @@ -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 -- 2.30.2