aboutsummaryrefslogtreecommitdiffstats
path: root/passes
diff options
context:
space:
mode:
authorEddie Hung <eddieh@ece.ubc.ca>2019-02-19 12:30:20 -0800
committerEddie Hung <eddieh@ece.ubc.ca>2019-02-19 12:30:20 -0800
commit8158bc3f9930634462166aac72da96d9c9c1a5e0 (patch)
tree6f3dbaad7c53e261cad1b60c93fcfb9757d16f31 /passes
parente79df5e70e8f0a34c29c21e28a80413d01f4e1c9 (diff)
downloadyosys-8158bc3f9930634462166aac72da96d9c9c1a5e0.tar.gz
yosys-8158bc3f9930634462166aac72da96d9c9c1a5e0.tar.bz2
yosys-8158bc3f9930634462166aac72da96d9c9c1a5e0.zip
abc9 to replace $_NOT_ with $lut
Diffstat (limited to 'passes')
-rw-r--r--passes/techmap/abc9.cc43
1 files changed, 39 insertions, 4 deletions
diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc
index 5c10278a9..f63b69acd 100644
--- a/passes/techmap/abc9.cc
+++ b/passes/techmap/abc9.cc
@@ -579,11 +579,46 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
module->connect(conn);
continue;
}
- if (c->type == "\\NOT") {
- RTLIL::Cell *cell = module->addCell(remap_name(c->name), "$_NOT_");
+ if (c->type == "$_NOT_") {
+ RTLIL::Cell *cell;
+ RTLIL::SigBit a_bit = c->getPort("\\A").as_bit();
+ RTLIL::SigBit y_bit = c->getPort("\\Y").as_bit();
+ if (!lut_costs.empty()) {
+ // ABC can return NOT gates that drive POs
+ if (a_bit.wire->port_input) {
+ // If it's a NOT gate that comes from a primary input directly
+ // then implement it 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);
+ }
+ else {
+ // Otherwise, clone the driving LUT to guarantee that we
+ // won't increase the max logic depth
+ // (TODO: Optimise by not cloning unless will increase depth)
+ RTLIL::Cell* driver = mapped_mod->cell(stringf("%s_lut", a_bit.wire->name.c_str()));
+ log_assert(driver);
+ auto driver_a = driver->getPort("\\A").chunks();
+ for (auto &chunk : driver_a)
+ chunk.wire = module->wires_[remap_name(chunk.wire->name)];
+ RTLIL::Const driver_lut = driver->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);
+ }
+ }
+ 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));
+ }
if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx;
- cell->setPort("\\A", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\A").as_wire()->name)]));
- cell->setPort("\\Y", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\Y").as_wire()->name)]));
design->select(module, cell);
continue;
}