From 26efd6f0a9ee5930efef7e1d00724bbb87489885 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 26 Jun 2019 19:57:54 -0700 Subject: [PATCH] Support more than one port in the abc_scc_break attr --- passes/techmap/abc9.cc | 80 ++++++++++++++++++++++-------------------- 1 file changed, 42 insertions(+), 38 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 52ca47a49..0671fc965 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -80,6 +80,8 @@ void handle_loops(RTLIL::Design *design) { Pass::call(design, "scc -set_attr abc_scc_id {}"); + dict> module_break; + // For every unique SCC found, (arbitrarily) find the first // cell in the component, and select (and mark) all its output // wires @@ -113,44 +115,46 @@ void handle_loops(RTLIL::Design *design) } cell->attributes.erase(it); } - RTLIL::Module* box_module = design->module(cell->type); - if (box_module) { - auto jt = box_module->attributes.find("\\abc_scc_break"); - if (jt != box_module->attributes.end()) { - auto it = cell->connections_.find(RTLIL::escape_id(jt->second.decode_string())); - if (it == cell->connections_.end()) - log_error("abc_scc_break attribute value '%s' does not exist as port on module '%s'\n", jt->second.decode_string().c_str(), log_id(box_module)); - log_assert(it != cell->connections_.end()); - RTLIL::SigSpec sig; - for (auto b : it->second) { - Wire *w = b.wire; - if (!w) continue; - if (w->port_output) { - log_assert(w->get_bool_attribute("\\abc_scc_break")); - w = module->wire(stringf("%s.abci", w->name.c_str())); - log_assert(w); - log_assert(b.offset < GetSize(w)); - log_assert(w->port_input); - } - else { - log_assert(!w->port_output); - w->port_output = true; - w->set_bool_attribute("\\abc_scc_break"); - 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_input = true; - } - else { - log_assert(w->port_input); - log_assert(b.offset < GetSize(w)); - } - } - sig.append(RTLIL::SigBit(w, b.offset)); - } - it->second = sig; - } - } + + auto jt = module_break.find(cell->type); + if (jt == module_break.end()) { + std::vector ports; + if (!yosys_celltypes.cell_known(cell->type)) { + RTLIL::Module* box_module = design->module(cell->type); + log_assert(box_module); + auto ports_csv = box_module->attributes.at("\\abc_scc_break", RTLIL::Const::from_string("")).decode_string(); + for (const auto &port_name : split_tokens(ports_csv, ",")) { + auto port_id = RTLIL::escape_id(port_name); + auto kt = cell->connections_.find(port_id); + if (kt == cell->connections_.end()) + log_error("abc_scc_break attribute value '%s' does not exist as port on module '%s'\n", port_name.c_str(), log_id(box_module)); + ports.push_back(port_id); + } + } + jt = module_break.insert(std::make_pair(cell->type, std::move(ports))).first; + } + + for (auto port_name : jt->second) { + RTLIL::SigSpec sig; + auto &rhs = cell->connections_.at(port_name); + for (auto b : rhs) { + Wire *w = b.wire; + if (!w) continue; + w->port_output = true; + w->set_bool_attribute("\\abc_scc_break"); + 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_input = true; + } + else { + log_assert(b.offset < GetSize(w)); + log_assert(w->port_input); + } + sig.append(RTLIL::SigBit(w, b.offset)); + } + rhs = sig; + } } module->fixup_ports(); -- 2.30.2