diff options
author | Eddie Hung <eddie@fpgeh.com> | 2020-01-07 09:48:57 -0800 |
---|---|---|
committer | Eddie Hung <eddie@fpgeh.com> | 2020-01-07 09:48:57 -0800 |
commit | dc3b21c1c050416aae443231729c8f4e4faf93ab (patch) | |
tree | 2c7827d8870c164eceb7e5a35964dfc56e4b40a1 /passes/techmap/abc9_ops.cc | |
parent | 61a2a60595f60acd4d46344e4c974153bbdfe8e3 (diff) | |
download | yosys-dc3b21c1c050416aae443231729c8f4e4faf93ab.tar.gz yosys-dc3b21c1c050416aae443231729c8f4e4faf93ab.tar.bz2 yosys-dc3b21c1c050416aae443231729c8f4e4faf93ab.zip |
abc9_ops -reintegrate: process box connections
Diffstat (limited to 'passes/techmap/abc9_ops.cc')
-rw-r--r-- | passes/techmap/abc9_ops.cc | 161 |
1 files changed, 134 insertions, 27 deletions
diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index 69239c93d..721a33f09 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -437,6 +437,57 @@ void reintegrate(RTLIL::Module *module) for (auto w : mapped_mod->wires()) module->addWire(remap_name(w->name), GetSize(w)); + dict<IdString,IdString> box_lookup; + dict<IdString,std::vector<IdString>> box_ports; + + for (auto m : design->modules()) { + auto it = m->attributes.find(ID(abc9_box_id)); + if (it == m->attributes.end()) + continue; + if (m->name.begins_with("$paramod")) + continue; + auto id = it->second.as_int(); + auto r = box_lookup.insert(std::make_pair(stringf("$__boxid%d", id), m->name)); + if (!r.second) + log_error("Module '%s' has the same abc9_box_id = %d value as '%s'.\n", + log_id(m), id, log_id(r.first->second)); + log_assert(r.second); + + auto r2 = box_ports.insert(m->name); + if (r2.second) { + // Make carry in the last PI, and carry out the last PO + // since ABC requires it this way + IdString carry_in, carry_out; + for (const auto &port_name : m->ports) { + auto w = m->wire(port_name); + log_assert(w); + if (w->get_bool_attribute("\\abc9_carry")) { + if (w->port_input) { + if (carry_in != IdString()) + log_error("Module '%s' contains more than one 'abc9_carry' input port.\n", log_id(m)); + carry_in = port_name; + } + if (w->port_output) { + if (carry_out != IdString()) + log_error("Module '%s' contains more than one 'abc9_carry' output port.\n", log_id(m)); + carry_out = port_name; + } + } + else + r2.first->second.push_back(port_name); + } + + if (carry_in != IdString() && carry_out == IdString()) + log_error("Module '%s' contains an 'abc9_carry' input port but no output port.\n", log_id(m)); + if (carry_in == IdString() && carry_out != IdString()) + log_error("Module '%s' contains an 'abc9_carry' output port but no input port.\n", log_id(m)); + if (carry_in != IdString()) { + r2.first->second.push_back(carry_in); + r2.first->second.push_back(carry_out); + } + } + } + for (auto it = module->cells_.begin(); it != module->cells_.end(); ) if (it->second->type.in(ID($_AND_), ID($_NOT_), ID($__ABC9_FF_))) it = module->cells_.erase(it); @@ -515,42 +566,98 @@ void reintegrate(RTLIL::Module *module) else { existing_cell = module->cell(mapped_cell->name); log_assert(existing_cell); + + if (mapped_cell->type.begins_with("$__boxid")) { + auto type = box_lookup.at(mapped_cell->type, IdString()); + if (type == IdString()) + log_error("No module with abc9_box_id = %s found.\n", mapped_cell->type.c_str() + strlen("$__boxid")); + mapped_cell->type = type; + } cell = module->addCell(remap_name(mapped_cell->name), mapped_cell->type); } - RTLIL::Module* box_module = design->module(mapped_cell->type); - auto abc9_flop = box_module && box_module->attributes.count("\\abc9_flop"); - for (auto &mapped_conn : mapped_cell->connections()) { - RTLIL::SigSpec newsig; - for (auto c : mapped_conn.second.chunks()) { - if (c.width == 0) - continue; - //log_assert(c.width == 1); - if (c.wire) - c.wire = module->wires_.at(remap_name(c.wire->name)); - newsig.append(c); + if (existing_cell) { + auto it = mapped_cell->connections_.find("\\i"); + log_assert(it != mapped_cell->connections_.end()); + SigSpec inputs = std::move(it->second); + mapped_cell->connections_.erase(it); + it = mapped_cell->connections_.find("\\o"); + log_assert(it != mapped_cell->connections_.end()); + SigSpec outputs = std::move(it->second); + mapped_cell->connections_.erase(it); + + RTLIL::Module* box_module = design->module(mapped_cell->type); + auto abc9_flop = box_module->attributes.count("\\abc9_flop"); + if (!abc9_flop) { + for (const auto &i : inputs) + bit_users[i].insert(mapped_cell->name); + for (const auto &i : outputs) + bit_drivers[i].insert(mapped_cell->name); } - if (existing_cell) { - auto it = existing_cell->connections_.find(mapped_conn.first); + + int input_count = 0, output_count = 0; + for (const auto &port_name : box_ports.at(cell->type)) { + RTLIL::Wire *w = box_module->wire(port_name); + log_assert(w); + + SigSpec sig; + if (w->port_input) { + sig = inputs.extract(input_count, GetSize(w)); + input_count += GetSize(w); + } + if (w->port_output) { + sig = outputs.extract(output_count, GetSize(w)); + output_count += GetSize(w); + } + + SigSpec newsig; + for (auto c : sig.chunks()) { + if (c.width == 0) + continue; + //log_assert(c.width == 1); + if (c.wire) + c.wire = module->wires_.at(remap_name(c.wire->name)); + newsig.append(c); + } + + auto it = existing_cell->connections_.find(port_name); if (it == existing_cell->connections_.end()) continue; - log_assert(GetSize(newsig) >= GetSize(it->second)); - newsig = newsig.extract(0, GetSize(it->second)); - } - cell->setPort(mapped_conn.first, newsig); + if (GetSize(newsig) > GetSize(it->second)) + newsig = newsig.extract(0, GetSize(it->second)); + else + log_assert(GetSize(newsig) == GetSize(it->second)); - if (abc9_flop) - continue; + cell->setPort(port_name, newsig); - if (cell->input(mapped_conn.first)) { - for (auto i : newsig) - bit2sinks[i].push_back(cell); - for (auto i : mapped_conn.second) - bit_users[i].insert(mapped_cell->name); + if (w->port_input && !abc9_flop) + for (const auto &i : newsig) + bit2sinks[i].push_back(cell); + } + } + else { + for (auto &mapped_conn : mapped_cell->connections()) { + RTLIL::SigSpec newsig; + for (auto c : mapped_conn.second.chunks()) { + if (c.width == 0) + continue; + //log_assert(c.width == 1); + if (c.wire) + c.wire = module->wires_.at(remap_name(c.wire->name)); + newsig.append(c); + } + cell->setPort(mapped_conn.first, newsig); + + if (cell->input(mapped_conn.first)) { + for (auto i : newsig) + bit2sinks[i].push_back(cell); + for (auto i : mapped_conn.second) + bit_users[i].insert(mapped_cell->name); + } + if (cell->output(mapped_conn.first)) + for (auto i : mapped_conn.second) + bit_drivers[i].insert(mapped_cell->name); } - if (cell->output(mapped_conn.first)) - for (auto i : mapped_conn.second) - bit_drivers[i].insert(mapped_cell->name); } if (existing_cell) { |