diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 790ba52a3..f732b56b0 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -1565,13 +1565,21 @@ void RTLIL::Module::remove(const pool &wires) void RTLIL::Module::remove(RTLIL::Cell *cell) { + auto it = cells_.find(cell->name); + log_assert(it != cells_.end()); + remove(it); +} + +dict::iterator RTLIL::Module::remove(dict::iterator it) +{ + RTLIL::Cell *cell = it->second; while (!cell->connections_.empty()) cell->unsetPort(cell->connections_.begin()->first); - log_assert(cells_.count(cell->name) != 0); log_assert(refcount_cells_ == 0); - cells_.erase(cell->name); + it = cells_.erase(it); delete cell; + return it; } void RTLIL::Module::rename(RTLIL::Wire *wire, RTLIL::IdString new_name) diff --git a/kernel/rtlil.h b/kernel/rtlil.h index f4fcf5dcf..4a0f8b4f8 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -1040,6 +1040,7 @@ public: // Removing wires is expensive. If you have to remove wires, remove them all at once. void remove(const pool &wires); void remove(RTLIL::Cell *cell); + dict::iterator remove(dict::iterator it); void rename(RTLIL::Wire *wire, RTLIL::IdString new_name); void rename(RTLIL::Cell *cell, RTLIL::IdString new_name); diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 54aba3b18..9c4e6bb39 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -500,24 +500,6 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri } } - // Remove all AND, NOT, and ABC box instances - // in preparation for stitching mapped_mod in - dict erased_boxes; - for (auto it = module->cells_.begin(); it != module->cells_.end(); ) { - RTLIL::Cell* cell = it->second; - if (cell->type.in("$_AND_", "$_NOT_")) { - it = module->cells_.erase(it); - continue; - } - RTLIL::Module* box_module = design->module(cell->type); - if (box_module && box_module->attributes.count("\\abc_box_id")) { - erased_boxes.insert(std::make_pair(it->first, std::move(cell->parameters))); - it = module->cells_.erase(it); - continue; - } - ++it; - } - // Do the same for module connections for (auto &it : module->connections_) { auto &signal = it.first; auto bits = signal.bits(); @@ -527,6 +509,19 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri signal = std::move(bits); } + vector boxes; + for (auto it = module->cells_.begin(); it != module->cells_.end(); ) { + RTLIL::Cell* cell = it->second; + if (cell->type.in("$_AND_", "$_NOT_", "$__ABC_FF_")) { + it = module->remove(it); + continue; + } + RTLIL::Module* box_module = design->module(cell->type); + if (box_module && box_module->attributes.count("\\abc_box_id")) + boxes.emplace_back(it->second); + ++it; + } + std::map cell_stats; for (auto c : mapped_mod->cells()) { @@ -595,18 +590,21 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri 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; continue; } } - else { - auto it = erased_boxes.find(c->name); - log_assert(it != erased_boxes.end()); - c->parameters = std::move(it->second); - } - RTLIL::Cell* cell = module->addCell(remap_name(c->name), c->type); + RTLIL::Cell *cell = module->addCell(remap_name(c->name), c->type); if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx; - cell->parameters = c->parameters; + RTLIL::Cell *existing_cell = module->cell(c->name); + if (existing_cell) { + cell->parameters = std::move(existing_cell->parameters); + cell->attributes = std::move(existing_cell->attributes); + } + else { + cell->parameters = std::move(c->parameters); + } for (auto &conn : c->connections()) { RTLIL::SigSpec newsig; for (auto c : conn.second.chunks()) { @@ -621,6 +619,9 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri } } + for (auto cell : boxes) + module->remove(cell); + // Copy connections (and rename) from mapped_mod to module for (auto conn : mapped_mod->connections()) { if (!conn.first.is_fully_const()) {