From 58dbb28fd3e1176d9f8a1355897cf4b56b7b46b2 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 12 Jul 2019 15:29:04 -0700 Subject: [PATCH 01/11] Cleanup --- passes/techmap/abc9.cc | 122 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 109 insertions(+), 13 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 5f448e37a..224a2d504 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -24,12 +24,14 @@ #if 0 // Based on &flow3 - better QoR but more experimental -#define ABC_COMMAND_LUT "&st; &ps -l; "/*"&sweep -v;"*/" &scorr; " \ - "&st; &if {W}; &save; &st; &syn2; &if {W}; &save; &load; "\ - "&st; &if -g -K 6; &dch -f; &if {W}; &save; &load; "\ - "&st; &if -g -K 6; &synch2; &if {W}; &save; &load" +#define ABC_COMMAND_LUT "&st; &ps -l; &sweep -v; &scorr; " \ + "&st; &if {W}; &save; &st; &syn2; &if {W} -v; &save; &load; "\ + "&st; &if -g -K 6; &dch -f; &if {W} -v; &save; &load; "\ + "&st; &if -g -K 6; &synch2; &if {W} -v; &save; &load; "\ + "&mfs; &ps -l" #else -#define ABC_COMMAND_LUT "&st; &scorr; &sweep; &dc2; &st; &dch -f; &ps -l; &if {W} {D} -v; &mfs; &ps -l" +#define ABC_COMMAND_LUT "&st; &scorr; &sweep; &dc2; &st; &dch -f; &ps; &if {W} {D} -v; &mfs -b; &ps -l" +//#define ABC_COMMAND_LUT "&st; &scorr; &sweep; &dc2; &st; &put -v; dch -f; if {W} {D} -vo; mfs2; &get -vm; &ps -l" #endif @@ -570,13 +572,15 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri boxes.emplace_back(cell); } + std::vector> not_gates; + dict> bit2sinks; std::map cell_stats; for (auto c : mapped_mod->cells()) { RTLIL::Cell *cell = nullptr; if (c->type == "$_NOT_") { - RTLIL::SigBit a_bit = c->getPort("\\A").as_bit(); - RTLIL::SigBit y_bit = c->getPort("\\Y").as_bit(); + RTLIL::SigBit a_bit = c->getPort("\\A"); + RTLIL::SigBit y_bit = c->getPort("\\Y"); if (!a_bit.wire) { c->setPort("\\Y", module->addWire(NEW_ID)); RTLIL::Wire *wire = module->wire(remap_name(y_bit.wire->name)); @@ -600,14 +604,16 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri } if (!driving_lut) { - // If a driver couldn't be found (could be from PI, - // or from a box) then implement using a LUT + // If a driver couldn't be found (could be from PI or box CI) + // then implement using a LUT cell = module->addLut(remap_name(stringf("%s$lut", c->name.c_str())), RTLIL::SigBit(module->wires_[remap_name(a_bit.wire->name)], a_bit.offset), RTLIL::SigBit(module->wires_[remap_name(y_bit.wire->name)], y_bit.offset), - 1); + RTLIL::Const::from_string("01")); + bit2sinks[cell->getPort("\\A")].push_back(cell); } else { +#if 0 auto driver_a = driving_lut->getPort("\\A").chunks(); for (auto &chunk : driver_a) chunk.wire = module->wires_[remap_name(chunk.wire->name)]; @@ -620,6 +626,19 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri driver_a, RTLIL::SigBit(module->wires_[remap_name(y_bit.wire->name)], y_bit.offset), driver_lut); +#elif 0 + cell = module->addLut(remap_name(stringf("%s$lut", c->name.c_str())), + RTLIL::SigBit(module->wires_[remap_name(a_bit.wire->name)], a_bit.offset), + RTLIL::SigBit(module->wires_[remap_name(y_bit.wire->name)], y_bit.offset), + RTLIL::Const::from_string("01")); + +#else + cell = module->addCell(remap_name(c->name), "$_NOT_"); + cell->setPort("\\A", RTLIL::SigBit(module->wires_[remap_name(a_bit.wire->name)], a_bit.offset)); + cell->setPort("\\Y", RTLIL::SigBit(module->wires_[remap_name(y_bit.wire->name)], y_bit.offset)); + not_gates.emplace_back(cell, driving_lut); +#endif + cell_stats[RTLIL::unescape_id(c->type)]++; } } else { @@ -627,19 +646,21 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri cell->setPort("\\A", RTLIL::SigBit(module->wires_[remap_name(a_bit.wire->name)], a_bit.offset)); cell->setPort("\\Y", RTLIL::SigBit(module->wires_[remap_name(y_bit.wire->name)], y_bit.offset)); cell_stats[RTLIL::unescape_id(c->type)]++; + log_abort(); } if (cell && markgroups) cell->attributes["\\abcgroup"] = map_autoidx; continue; } cell_stats[RTLIL::unescape_id(c->type)]++; - RTLIL::Cell *existing_cell = nullptr; + RTLIL::Cell *existing_cell = nullptr; if (c->type == "$lut") { - if (GetSize(c->getPort("\\A")) == 1 && c->getParam("\\LUT").as_int() == 2) { + if (GetSize(c->getPort("\\A")) == 1 && c->getParam("\\LUT") == RTLIL::Const::from_string("01")) { SigSpec my_a = module->wires_[remap_name(c->getPort("\\A").as_wire()->name)]; SigSpec my_y = module->wires_[remap_name(c->getPort("\\Y").as_wire()->name)]; module->connect(my_y, my_a); - if (markgroups) c->attributes["\\abcgroup"] = map_autoidx; + if (markgroups) c->attributes["\\abcgroup"] = map_autoidx; + log_abort(); continue; } cell = module->addCell(remap_name(c->name), c->type); @@ -670,6 +691,10 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri newsig.append(c); } cell->setPort(conn.first, newsig); + + if (cell->input(conn.first)) + for (auto i : newsig) + bit2sinks[i].push_back(cell); } } @@ -725,6 +750,77 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri } } + for (auto i : not_gates) { + RTLIL::Cell *not_cell = i.first; + auto driving_lut = i.second; + log_assert(driving_lut); + RTLIL::SigBit a_bit = not_cell->getPort("\\A"); + RTLIL::SigBit y_bit = not_cell->getPort("\\Y"); + driving_lut = module->cell(remap_name(driving_lut->name)); + log_assert(driving_lut); + RTLIL::Const driver_lut = driving_lut->getParam("\\LUT"); + for (auto &b : driver_lut.bits) { + if (b == RTLIL::State::S0) b = RTLIL::State::S1; + else if (b == RTLIL::State::S1) b = RTLIL::State::S0; + } + + auto it = bit2sinks.find(a_bit); + if (it == bit2sinks.end()) + goto duplicate_lut; + + for (auto sink_cell : it->second) + if (sink_cell->type != "$lut") + goto duplicate_lut; + + //static int count = 0; + //log_warning("%d\n", count); + //if (count++ >= 41) + // goto duplicate_lut; + + for (auto sink_cell : it->second) { + SigSpec A = sink_cell->getPort("\\A"); + RTLIL::Const mask = sink_cell->getParam("\\LUT"); + int index = 0; + for (; index < GetSize(A); index++) + if (A[index] == a_bit) + break; + log_assert(index < GetSize(A)); + int i = 0; + while (i < GetSize(mask)) { + for (int j = 0; j < (1 << index); j++) + std::swap(mask[i+j], mask[i+j+(1 << index)]); + i += 1 << (index+1); + } + A[index] = y_bit; + sink_cell->setPort("\\A", A); + sink_cell->setParam("\\LUT", mask); + } + + // FIXME: Since we have rewritten all sink_LUTs, + // we should be able to continue here + // and expect the $_NOT_ gate to be optimised + // away as it will have no sinks... + //continue; + +duplicate_lut: + auto not_cell_name = not_cell->name; + module->remove(not_cell); +#if 0 + auto driver_a = driving_lut->getPort("\\A").chunks(); + for (auto &chunk : driver_a) + chunk.wire = module->wires_[remap_name(chunk.wire->name)]; + module->addLut(not_cell_name, + driver_a, + y_bit, + driver_lut); +#else + module->addLut(not_cell_name, + a_bit, + y_bit, + RTLIL::Const::from_string("01")); +#endif + } + //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); From 399e1ec87033d44d8d9e55b6a15a06e4412eb81a Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 12 Jul 2019 15:31:02 -0700 Subject: [PATCH 02/11] Cleanup --- passes/techmap/abc9.cc | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 224a2d504..f6592098b 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -756,7 +756,6 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri log_assert(driving_lut); RTLIL::SigBit a_bit = not_cell->getPort("\\A"); RTLIL::SigBit y_bit = not_cell->getPort("\\Y"); - driving_lut = module->cell(remap_name(driving_lut->name)); log_assert(driving_lut); RTLIL::Const driver_lut = driving_lut->getParam("\\LUT"); for (auto &b : driver_lut.bits) { @@ -772,11 +771,6 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri if (sink_cell->type != "$lut") goto duplicate_lut; - //static int count = 0; - //log_warning("%d\n", count); - //if (count++ >= 41) - // goto duplicate_lut; - for (auto sink_cell : it->second) { SigSpec A = sink_cell->getPort("\\A"); RTLIL::Const mask = sink_cell->getParam("\\LUT"); @@ -805,7 +799,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri duplicate_lut: auto not_cell_name = not_cell->name; module->remove(not_cell); -#if 0 +#if 1 auto driver_a = driving_lut->getPort("\\A").chunks(); for (auto &chunk : driver_a) chunk.wire = module->wires_[remap_name(chunk.wire->name)]; From 91c07be196c71cc172834dcbddd30f5944972b41 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 12 Jul 2019 15:41:06 -0700 Subject: [PATCH 03/11] Cleanup --- passes/techmap/abc9.cc | 62 +++++++++++------------------------------- 1 file changed, 16 insertions(+), 46 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index f6592098b..cdad38c9e 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -572,7 +572,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri boxes.emplace_back(cell); } - std::vector> not_gates; + std::vector> push_inverters; dict> bit2sinks; std::map cell_stats; for (auto c : mapped_mod->cells()) @@ -613,32 +613,8 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri bit2sinks[cell->getPort("\\A")].push_back(cell); } else { -#if 0 - auto driver_a = driving_lut->getPort("\\A").chunks(); - for (auto &chunk : driver_a) - chunk.wire = module->wires_[remap_name(chunk.wire->name)]; - RTLIL::Const driver_lut = driving_lut->getParam("\\LUT"); - for (auto &b : driver_lut.bits) { - if (b == RTLIL::State::S0) b = RTLIL::State::S1; - else if (b == RTLIL::State::S1) b = RTLIL::State::S0; - } - cell = module->addLut(remap_name(stringf("%s$lut", c->name.c_str())), - driver_a, - RTLIL::SigBit(module->wires_[remap_name(y_bit.wire->name)], y_bit.offset), - driver_lut); -#elif 0 - cell = module->addLut(remap_name(stringf("%s$lut", c->name.c_str())), - RTLIL::SigBit(module->wires_[remap_name(a_bit.wire->name)], a_bit.offset), - RTLIL::SigBit(module->wires_[remap_name(y_bit.wire->name)], y_bit.offset), - RTLIL::Const::from_string("01")); - -#else - cell = module->addCell(remap_name(c->name), "$_NOT_"); - cell->setPort("\\A", RTLIL::SigBit(module->wires_[remap_name(a_bit.wire->name)], a_bit.offset)); - cell->setPort("\\Y", RTLIL::SigBit(module->wires_[remap_name(y_bit.wire->name)], y_bit.offset)); - not_gates.emplace_back(cell, driving_lut); -#endif - cell_stats[RTLIL::unescape_id(c->type)]++; + push_inverters.emplace_back(c, driving_lut); + continue; } } else { @@ -649,6 +625,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri log_abort(); } if (cell && markgroups) cell->attributes["\\abcgroup"] = map_autoidx; + cell_stats[RTLIL::unescape_id(c->type)]++; continue; } cell_stats[RTLIL::unescape_id(c->type)]++; @@ -750,18 +727,14 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri } } - for (auto i : not_gates) { + for (auto i : push_inverters) { RTLIL::Cell *not_cell = i.first; - auto driving_lut = i.second; - log_assert(driving_lut); + RTLIL::Cell *driving_lut = i.second; RTLIL::SigBit a_bit = not_cell->getPort("\\A"); RTLIL::SigBit y_bit = not_cell->getPort("\\Y"); - log_assert(driving_lut); - RTLIL::Const driver_lut = driving_lut->getParam("\\LUT"); - for (auto &b : driver_lut.bits) { - if (b == RTLIL::State::S0) b = RTLIL::State::S1; - else if (b == RTLIL::State::S1) b = RTLIL::State::S0; - } + + a_bit.wire = module->wires_.at(remap_name(a_bit.wire->name)); + y_bit.wire = module->wires_.at(remap_name(y_bit.wire->name)); auto it = bit2sinks.find(a_bit); if (it == bit2sinks.end()) @@ -797,22 +770,19 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri //continue; duplicate_lut: - auto not_cell_name = not_cell->name; - module->remove(not_cell); -#if 1 + RTLIL::Const driver_lut = driving_lut->getParam("\\LUT"); + for (auto &b : driver_lut.bits) { + if (b == RTLIL::State::S0) b = RTLIL::State::S1; + else if (b == RTLIL::State::S1) b = RTLIL::State::S0; + } auto driver_a = driving_lut->getPort("\\A").chunks(); for (auto &chunk : driver_a) chunk.wire = module->wires_[remap_name(chunk.wire->name)]; - module->addLut(not_cell_name, + module->addLut(remap_name(not_cell->name), driver_a, y_bit, driver_lut); -#else - module->addLut(not_cell_name, - a_bit, - y_bit, - RTLIL::Const::from_string("01")); -#endif + //mapped_mod->remove(not_cell); } //log("ABC RESULTS: internal signals: %8d\n", int(signal_list.size()) - in_wires - out_wires); From 39a7c7c54c1845ee4d13c33745085318a9a44b96 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 12 Jul 2019 15:43:39 -0700 Subject: [PATCH 04/11] More cleanup --- passes/techmap/abc9.cc | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index cdad38c9e..2b4a5cdba 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -607,8 +607,8 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri // If a driver couldn't be found (could be from PI or box CI) // then implement using a LUT cell = module->addLut(remap_name(stringf("%s$lut", c->name.c_str())), - RTLIL::SigBit(module->wires_[remap_name(a_bit.wire->name)], a_bit.offset), - RTLIL::SigBit(module->wires_[remap_name(y_bit.wire->name)], y_bit.offset), + RTLIL::SigBit(module->wires_.at(remap_name(a_bit.wire->name)), a_bit.offset), + RTLIL::SigBit(module->wires_.at(remap_name(y_bit.wire->name)), y_bit.offset), RTLIL::Const::from_string("01")); bit2sinks[cell->getPort("\\A")].push_back(cell); } @@ -619,8 +619,8 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri } else { cell = module->addCell(remap_name(c->name), "$_NOT_"); - cell->setPort("\\A", RTLIL::SigBit(module->wires_[remap_name(a_bit.wire->name)], a_bit.offset)); - cell->setPort("\\Y", RTLIL::SigBit(module->wires_[remap_name(y_bit.wire->name)], y_bit.offset)); + cell->setPort("\\A", RTLIL::SigBit(module->wires_.at(remap_name(a_bit.wire->name)), a_bit.offset)); + cell->setPort("\\Y", RTLIL::SigBit(module->wires_.at(remap_name(y_bit.wire->name)), y_bit.offset)); cell_stats[RTLIL::unescape_id(c->type)]++; log_abort(); } @@ -633,8 +633,8 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri RTLIL::Cell *existing_cell = nullptr; if (c->type == "$lut") { if (GetSize(c->getPort("\\A")) == 1 && c->getParam("\\LUT") == RTLIL::Const::from_string("01")) { - SigSpec my_a = module->wires_[remap_name(c->getPort("\\A").as_wire()->name)]; - SigSpec my_y = module->wires_[remap_name(c->getPort("\\Y").as_wire()->name)]; + SigSpec my_a = module->wires_.at(remap_name(c->getPort("\\A").as_wire()->name)); + SigSpec my_y = module->wires_.at(remap_name(c->getPort("\\Y").as_wire()->name)); module->connect(my_y, my_a); if (markgroups) c->attributes["\\abcgroup"] = map_autoidx; log_abort(); @@ -664,7 +664,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri continue; //log_assert(c.width == 1); if (c.wire) - c.wire = module->wires_[remap_name(c.wire->name)]; + c.wire = module->wires_.at(remap_name(c.wire->name)); newsig.append(c); } cell->setPort(conn.first, newsig); @@ -683,14 +683,14 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri if (!conn.first.is_fully_const()) { auto chunks = conn.first.chunks(); for (auto &c : chunks) - c.wire = module->wires_[remap_name(c.wire->name)]; + c.wire = module->wires_.at(remap_name(c.wire->name)); conn.first = std::move(chunks); } if (!conn.second.is_fully_const()) { auto chunks = conn.second.chunks(); for (auto &c : chunks) if (c.wire) - c.wire = module->wires_[remap_name(c.wire->name)]; + c.wire = module->wires_.at(remap_name(c.wire->name)); conn.second = std::move(chunks); } module->connect(conn); @@ -777,12 +777,11 @@ duplicate_lut: } auto driver_a = driving_lut->getPort("\\A").chunks(); for (auto &chunk : driver_a) - chunk.wire = module->wires_[remap_name(chunk.wire->name)]; + chunk.wire = module->wires_.at(remap_name(chunk.wire->name)); module->addLut(remap_name(not_cell->name), driver_a, y_bit, driver_lut); - //mapped_mod->remove(not_cell); } //log("ABC RESULTS: internal signals: %8d\n", int(signal_list.size()) - in_wires - out_wires); From 1adbfb55338fdb29eae638f988ae361b9e401d8b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 12 Jul 2019 16:01:11 -0700 Subject: [PATCH 05/11] Cleanup --- passes/techmap/abc9.cc | 39 ++++++++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 2b4a5cdba..5da5efcdc 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -588,11 +588,11 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri module->connect(RTLIL::SigBit(wire, y_bit.offset), RTLIL::S1); } else if (!lut_costs.empty() || !lut_file.empty()) { - RTLIL::Cell* driving_lut = nullptr; + RTLIL::Cell* driver_lut = nullptr; // ABC can return NOT gates that drive POs if (!a_bit.wire->port_input) { // If it's not a NOT gate that that comes from a PI directly, - // find the driving LUT and clone that to guarantee that we won't + // find the driver LUT and clone that to guarantee that we won't // increase the max logic depth // (TODO: Optimise by not cloning unless will increase depth) RTLIL::IdString driver_name; @@ -600,10 +600,10 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri driver_name = stringf("%s$lut", a_bit.wire->name.c_str()); else driver_name = stringf("%s[%d]$lut", a_bit.wire->name.c_str(), a_bit.offset); - driving_lut = mapped_mod->cell(driver_name); + driver_lut = mapped_mod->cell(driver_name); } - if (!driving_lut) { + if (!driver_lut) { // If a driver couldn't be found (could be from PI or box CI) // then implement using a LUT cell = module->addLut(remap_name(stringf("%s$lut", c->name.c_str())), @@ -613,7 +613,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri bit2sinks[cell->getPort("\\A")].push_back(cell); } else { - push_inverters.emplace_back(c, driving_lut); + push_inverters.emplace_back(c, driver_lut); continue; } } @@ -729,13 +729,19 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri for (auto i : push_inverters) { RTLIL::Cell *not_cell = i.first; - RTLIL::Cell *driving_lut = i.second; + RTLIL::Cell *driver_lut = i.second; RTLIL::SigBit a_bit = not_cell->getPort("\\A"); RTLIL::SigBit y_bit = not_cell->getPort("\\Y"); + RTLIL::Const driver_mask = driver_lut->getParam("\\LUT"); a_bit.wire = module->wires_.at(remap_name(a_bit.wire->name)); y_bit.wire = module->wires_.at(remap_name(y_bit.wire->name)); + for (auto &b : driver_mask.bits) { + if (b == RTLIL::State::S0) b = RTLIL::State::S1; + else if (b == RTLIL::State::S1) b = RTLIL::State::S0; + } + auto it = bit2sinks.find(a_bit); if (it == bit2sinks.end()) goto duplicate_lut; @@ -744,6 +750,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri if (sink_cell->type != "$lut") goto duplicate_lut; + // Push downstream LUTs past inverter for (auto sink_cell : it->second) { SigSpec A = sink_cell->getPort("\\A"); RTLIL::Const mask = sink_cell->getParam("\\LUT"); @@ -763,25 +770,27 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri sink_cell->setParam("\\LUT", mask); } - // FIXME: Since we have rewritten all sink_LUTs, - // we should be able to continue here - // and expect the $_NOT_ gate to be optimised - // away as it will have no sinks... + // FIXME: Since we have rewritten all sinks + // (which we know to be only LUTs) + // to be after the inverter, we can now + // merge the inverter into the driving LUT + // and let the (now dangling) $_NOT_ cell + // from mapped_mod get cleaned away + //driver_lut->setParam("\\INIT", driver_mask); + //driver_lut->setPort("\\Y", y_bit); //continue; - duplicate_lut: - RTLIL::Const driver_lut = driving_lut->getParam("\\LUT"); - for (auto &b : driver_lut.bits) { + for (auto &b : driver_mask.bits) { if (b == RTLIL::State::S0) b = RTLIL::State::S1; else if (b == RTLIL::State::S1) b = RTLIL::State::S0; } - auto driver_a = driving_lut->getPort("\\A").chunks(); + auto driver_a = driver_lut->getPort("\\A").chunks(); for (auto &chunk : driver_a) chunk.wire = module->wires_.at(remap_name(chunk.wire->name)); module->addLut(remap_name(not_cell->name), driver_a, y_bit, - driver_lut); + driver_mask); } //log("ABC RESULTS: internal signals: %8d\n", int(signal_list.size()) - in_wires - out_wires); From 83f23a24a880fb3cd40ea16b478540bdbdfe597c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 12 Jul 2019 16:06:14 -0700 Subject: [PATCH 06/11] Cleanup --- passes/techmap/abc9.cc | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 5da5efcdc..867b06cbe 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -611,21 +611,15 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri RTLIL::SigBit(module->wires_.at(remap_name(y_bit.wire->name)), y_bit.offset), RTLIL::Const::from_string("01")); bit2sinks[cell->getPort("\\A")].push_back(cell); + cell_stats["$lut"]++; } - else { + else push_inverters.emplace_back(c, driver_lut); - continue; - } + continue; } - else { - cell = module->addCell(remap_name(c->name), "$_NOT_"); - cell->setPort("\\A", RTLIL::SigBit(module->wires_.at(remap_name(a_bit.wire->name)), a_bit.offset)); - cell->setPort("\\Y", RTLIL::SigBit(module->wires_.at(remap_name(y_bit.wire->name)), y_bit.offset)); - cell_stats[RTLIL::unescape_id(c->type)]++; + else log_abort(); - } if (cell && markgroups) cell->attributes["\\abcgroup"] = map_autoidx; - cell_stats[RTLIL::unescape_id(c->type)]++; continue; } cell_stats[RTLIL::unescape_id(c->type)]++; From 7d583f9e57dc3feb7e525c5ad120b1ba3959fdcd Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 12 Jul 2019 19:17:32 -0700 Subject: [PATCH 07/11] Cleanup --- passes/techmap/abc9.cc | 82 ++++++++++++++++++++++++++---------------- 1 file changed, 52 insertions(+), 30 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 867b06cbe..7b1c9f815 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -55,6 +55,7 @@ #endif #include "frontends/aiger/aigerparse.h" +#include "kernel/utils.h" #ifdef YOSYS_LINK_ABC extern "C" int Abc_RealMain(int argc, char *argv[]); @@ -572,15 +573,23 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri boxes.emplace_back(cell); } - std::vector> push_inverters; + dict> bit_drivers, bit_users; + TopoSort toposort; + dict not2drivers; dict> bit2sinks; + std::map cell_stats; for (auto c : mapped_mod->cells()) { + toposort.node(c->name); + RTLIL::Cell *cell = nullptr; if (c->type == "$_NOT_") { RTLIL::SigBit a_bit = c->getPort("\\A"); RTLIL::SigBit y_bit = c->getPort("\\Y"); + bit_users[a_bit].insert(c->name); + bit_drivers[y_bit].insert(c->name); + if (!a_bit.wire) { c->setPort("\\Y", module->addWire(NEW_ID)); RTLIL::Wire *wire = module->wire(remap_name(y_bit.wire->name)); @@ -614,7 +623,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri cell_stats["$lut"]++; } else - push_inverters.emplace_back(c, driver_lut); + not2drivers[c] = driver_lut; continue; } else @@ -663,9 +672,15 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri } cell->setPort(conn.first, newsig); - if (cell->input(conn.first)) + if (cell->input(conn.first)) { for (auto i : newsig) bit2sinks[i].push_back(cell); + for (auto i : conn.second) + bit_users[i].insert(c->name); + } + if (cell->output(conn.first)) + for (auto i : conn.second) + bit_drivers[i].insert(c->name); } } @@ -721,31 +736,45 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri } } - for (auto i : push_inverters) { - RTLIL::Cell *not_cell = i.first; - RTLIL::Cell *driver_lut = i.second; + for (auto &it : bit_users) + if (bit_drivers.count(it.first)) + for (auto driver_cell : bit_drivers.at(it.first)) + for (auto user_cell : it.second) + toposort.edge(driver_cell, user_cell); + bool no_loops = toposort.sort(); + log_assert(no_loops); + + for (auto ii = toposort.sorted.rbegin(); ii != toposort.sorted.rend(); ii++) { + RTLIL::Cell *not_cell = mapped_mod->cell(*ii); + log_assert(not_cell); + if (not_cell->type != "$_NOT_") + continue; + auto it = not2drivers.find(not_cell); + if (it == not2drivers.end()) + continue; + RTLIL::Cell *driver_lut = it->second; RTLIL::SigBit a_bit = not_cell->getPort("\\A"); RTLIL::SigBit y_bit = not_cell->getPort("\\Y"); - RTLIL::Const driver_mask = driver_lut->getParam("\\LUT"); + RTLIL::Const driver_mask; + RTLIL::Wire *orig_a_bit_wire = a_bit.wire; + decltype(bit2sinks)::const_iterator jt; a_bit.wire = module->wires_.at(remap_name(a_bit.wire->name)); y_bit.wire = module->wires_.at(remap_name(y_bit.wire->name)); - for (auto &b : driver_mask.bits) { - if (b == RTLIL::State::S0) b = RTLIL::State::S1; - else if (b == RTLIL::State::S1) b = RTLIL::State::S0; - } - - auto it = bit2sinks.find(a_bit); - if (it == bit2sinks.end()) + if (orig_a_bit_wire->port_output) goto duplicate_lut; - for (auto sink_cell : it->second) + jt = bit2sinks.find(a_bit); + if (jt == bit2sinks.end()) + goto duplicate_lut; + + for (auto sink_cell : jt->second) if (sink_cell->type != "$lut") goto duplicate_lut; // Push downstream LUTs past inverter - for (auto sink_cell : it->second) { + for (auto sink_cell : jt->second) { SigSpec A = sink_cell->getPort("\\A"); RTLIL::Const mask = sink_cell->getParam("\\LUT"); int index = 0; @@ -764,27 +793,20 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri sink_cell->setParam("\\LUT", mask); } - // FIXME: Since we have rewritten all sinks - // (which we know to be only LUTs) - // to be after the inverter, we can now - // merge the inverter into the driving LUT - // and let the (now dangling) $_NOT_ cell - // from mapped_mod get cleaned away - //driver_lut->setParam("\\INIT", driver_mask); - //driver_lut->setPort("\\Y", y_bit); - //continue; duplicate_lut: + driver_mask = driver_lut->getParam("\\LUT"); for (auto &b : driver_mask.bits) { if (b == RTLIL::State::S0) b = RTLIL::State::S1; else if (b == RTLIL::State::S1) b = RTLIL::State::S0; } - auto driver_a = driver_lut->getPort("\\A").chunks(); - for (auto &chunk : driver_a) - chunk.wire = module->wires_.at(remap_name(chunk.wire->name)); - module->addLut(remap_name(not_cell->name), - driver_a, + auto cell = module->addLut(NEW_ID, + driver_lut->getPort("\\A"), y_bit, driver_mask); + for (auto &bit : cell->connections_.at("\\A")) { + bit.wire = module->wires_.at(remap_name(bit.wire->name)); + bit2sinks[bit].push_back(cell); + } } //log("ABC RESULTS: internal signals: %8d\n", int(signal_list.size()) - in_wires - out_wires); From be0cb7f4b81af91ce47a8baf57d0aff716eecddc Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 12 Jul 2019 19:21:03 -0700 Subject: [PATCH 08/11] More cleanup --- passes/techmap/abc9.cc | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 7b1c9f815..36f2fafc3 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -30,8 +30,7 @@ "&st; &if -g -K 6; &synch2; &if {W} -v; &save; &load; "\ "&mfs; &ps -l" #else -#define ABC_COMMAND_LUT "&st; &scorr; &sweep; &dc2; &st; &dch -f; &ps; &if {W} {D} -v; &mfs -b; &ps -l" -//#define ABC_COMMAND_LUT "&st; &scorr; &sweep; &dc2; &st; &put -v; dch -f; if {W} {D} -vo; mfs2; &get -vm; &ps -l" +#define ABC_COMMAND_LUT "&st; &scorr; &sweep; &dc2; &st; &dch -f; &ps; &if {W} {D} -v; &mfs; &ps -l" #endif @@ -756,16 +755,11 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri RTLIL::SigBit a_bit = not_cell->getPort("\\A"); RTLIL::SigBit y_bit = not_cell->getPort("\\Y"); RTLIL::Const driver_mask; - RTLIL::Wire *orig_a_bit_wire = a_bit.wire; - decltype(bit2sinks)::const_iterator jt; a_bit.wire = module->wires_.at(remap_name(a_bit.wire->name)); y_bit.wire = module->wires_.at(remap_name(y_bit.wire->name)); - if (orig_a_bit_wire->port_output) - goto duplicate_lut; - - jt = bit2sinks.find(a_bit); + auto jt = bit2sinks.find(a_bit); if (jt == bit2sinks.end()) goto duplicate_lut; From e9bdc86c0e0ea41d1ee8a610b7f1304c3eaf43e9 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 12 Jul 2019 19:33:02 -0700 Subject: [PATCH 09/11] duplicate -> clone --- passes/techmap/abc9.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 36f2fafc3..4a6ec3a47 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -761,11 +761,11 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri auto jt = bit2sinks.find(a_bit); if (jt == bit2sinks.end()) - goto duplicate_lut; + goto clone_lut; for (auto sink_cell : jt->second) if (sink_cell->type != "$lut") - goto duplicate_lut; + goto clone_lut; // Push downstream LUTs past inverter for (auto sink_cell : jt->second) { @@ -787,7 +787,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri sink_cell->setParam("\\LUT", mask); } -duplicate_lut: +clone_lut: driver_mask = driver_lut->getParam("\\LUT"); for (auto &b : driver_mask.bits) { if (b == RTLIL::State::S0) b = RTLIL::State::S1; From 41243a53b384a9ecfadd7b424c9e22c7c84fb721 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 12 Jul 2019 21:00:13 -0700 Subject: [PATCH 10/11] Update test with more accurate LUT mask --- tests/various/abc9.ys | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/various/abc9.ys b/tests/various/abc9.ys index a84b637d9..5c9a4075d 100644 --- a/tests/various/abc9.ys +++ b/tests/various/abc9.ys @@ -19,6 +19,6 @@ hierarchy -top abc9_test028 proc abc9 -lut 4 -select -assert-count 1 t:$lut r:LUT=1 r:WIDTH=1 %i %i +select -assert-count 1 t:$lut r:LUT=2'b01 r:WIDTH=1 %i %i select -assert-count 1 t:unknown select -assert-none t:$lut t:unknown %% t: %D From fb062c3426e8acb5b3f54dfed7209631208fec81 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 13 Jul 2019 00:52:21 -0700 Subject: [PATCH 11/11] Add comment --- passes/techmap/abc9.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 4a6ec3a47..658bb1225 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -787,6 +787,11 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri sink_cell->setParam("\\LUT", mask); } + // Since we have rewritten all sinks (which we know + // to be only LUTs) to be after the inverter, we can + // go ahead and clone the LUT with the expectation + // that the original driving LUT will become dangling + // and get cleaned away clone_lut: driver_mask = driver_lut->getParam("\\LUT"); for (auto &b : driver_mask.bits) {