diff options
Diffstat (limited to 'passes/techmap/techmap.cc')
-rw-r--r-- | passes/techmap/techmap.cc | 104 |
1 files changed, 86 insertions, 18 deletions
diff --git a/passes/techmap/techmap.cc b/passes/techmap/techmap.cc index 51a65aea6..0c57733d4 100644 --- a/passes/techmap/techmap.cc +++ b/passes/techmap/techmap.cc @@ -206,10 +206,27 @@ struct TechmapWorker std::map<RTLIL::IdString, RTLIL::IdString> positional_ports; dict<Wire*, IdString> temp_renamed_wires; + pool<SigBit> autopurge_tpl_bits; - for (auto &it : tpl->wires_) { + for (auto &it : tpl->wires_) + { if (it.second->port_id > 0) - positional_ports[stringf("$%d", it.second->port_id)] = it.first; + { + IdString posportname = stringf("$%d", it.second->port_id); + positional_ports[posportname] = it.first; + + if (!flatten_mode && it.second->get_bool_attribute(ID(techmap_autopurge)) && + (!cell->hasPort(it.second->name) || !GetSize(cell->getPort(it.second->name))) && + (!cell->hasPort(posportname) || !GetSize(cell->getPort(posportname)))) + { + if (sigmaps.count(tpl) == 0) + sigmaps[tpl].set(tpl); + + for (auto bit : sigmaps.at(tpl)(it.second)) + if (bit.wire != nullptr) + autopurge_tpl_bits.insert(bit); + } + } IdString w_name = it.second->name; apply_prefix(cell->name, w_name); RTLIL::Wire *w = module->wire(w_name); @@ -232,12 +249,20 @@ struct TechmapWorker w->port_input = false; w->port_output = false; w->port_id = 0; + if (!flatten_mode) + w->attributes.erase(ID(techmap_autopurge)); if (it.second->get_bool_attribute(ID(_techmap_special_))) w->attributes.clear(); if (w->attributes.count(ID(src))) w->add_strpool_attribute(ID(src), extra_src_attrs); } design->select(module, w); + + if (it.second->name.begins_with("\\_TECHMAP_REPLACE_.")) { + IdString replace_name = stringf("%s%s", orig_cell_name.c_str(), it.second->name.c_str() + strlen("\\_TECHMAP_REPLACE_")); + Wire *replace_w = module->addWire(replace_name, it.second); + module->connect(replace_w, w); + } } SigMap tpl_sigmap(tpl); @@ -340,6 +365,12 @@ struct TechmapWorker for (auto &attr : w->attributes) { if (attr.first == ID(src)) continue; + auto lhs = GetSize(extra_connect.first); + auto rhs = GetSize(extra_connect.second); + if (lhs > rhs) + extra_connect.first.remove(rhs, lhs-rhs); + else if (rhs > lhs) + extra_connect.second.remove(lhs, rhs-lhs); module->connect(extra_connect); break; } @@ -353,6 +384,8 @@ struct TechmapWorker if (techmap_replace_cell) c_name = orig_cell_name; + else if (it.second->name.begins_with("\\_TECHMAP_REPLACE_.")) + c_name = stringf("%s%s", orig_cell_name.c_str(), c_name.c_str() + strlen("\\_TECHMAP_REPLACE_")); else apply_prefix(cell->name, c_name); @@ -362,11 +395,31 @@ struct TechmapWorker if (!flatten_mode && c->type.begins_with("\\$")) c->type = c->type.substr(1); - for (auto &it2 : c->connections_) { - apply_prefix(cell->name, it2.second, module); - port_signal_map.apply(it2.second); + vector<IdString> autopurge_ports; + + for (auto &it2 : c->connections_) + { + bool autopurge = false; + if (!autopurge_tpl_bits.empty()) { + autopurge = GetSize(it2.second) != 0; + for (auto &bit : sigmaps.at(tpl)(it2.second)) + if (!autopurge_tpl_bits.count(bit)) { + autopurge = false; + break; + } + } + + if (autopurge) { + autopurge_ports.push_back(it2.first); + } else { + apply_prefix(cell->name, it2.second, module); + port_signal_map.apply(it2.second); + } } + for (auto &it2 : autopurge_ports) + c->unsetPort(it2); + if (c->type.in(ID($memrd), ID($memwr), ID($meminit))) { IdString memid = c->getParam(ID(MEMID)).decode_string(); log_assert(memory_renames.count(memid) != 0); @@ -890,19 +943,6 @@ struct TechmapWorker for (auto &it2 : it.second) if (!it2.value.is_fully_const()) log_error("Techmap yielded config wire %s with non-const value %s.\n", RTLIL::id2cstr(it2.wire->name), log_signal(it2.value)); - if (it.first.substr(0, 20) == "_TECHMAP_REMOVEINIT_" && techmap_do_cache[tpl]) { - for (auto &it2 : it.second) { - auto val = it2.value.as_const(); - auto wirename = RTLIL::escape_id(it.first.substr(20, it.first.size() - 20 - 1)); - auto it = cell->connections().find(wirename); - if (it != cell->connections().end()) { - auto sig = sigmap(it->second); - for (int i = 0; i < sig.size(); i++) - if (val[i] == State::S1) - remove_init_bits.insert(sig[i]); - } - } - } techmap_wire_names.erase(it.first); } @@ -928,6 +968,23 @@ struct TechmapWorker mkdebug.off(); } + TechmapWires twd = techmap_find_special_wires(tpl); + for (auto &it : twd) { + if (it.first.substr(0, 20) == "_TECHMAP_REMOVEINIT_") { + for (auto &it2 : it.second) { + auto val = it2.value.as_const(); + auto wirename = RTLIL::escape_id(it.first.substr(20, it.first.size() - 20 - 1)); + auto it = cell->connections().find(wirename); + if (it != cell->connections().end()) { + auto sig = sigmap(it->second); + for (int i = 0; i < sig.size(); i++) + if (val[i] == State::S1) + remove_init_bits.insert(sig[i]); + } + } + } + } + if (extern_mode && !in_recursion) { std::string m_name = stringf("$extern:%s", log_id(tpl)); @@ -1064,6 +1121,11 @@ struct TechmapPass : public Pass { log("will create a wrapper for the cell and then run the command string that the\n"); log("attribute is set to on the wrapper module.\n"); log("\n"); + log("When a port on a module in the map file has the 'techmap_autopurge' attribute\n"); + log("set, and that port is not connected in the instantiation that is mapped, then\n"); + log("then a cell port connected only to such wires will be omitted in the mapped\n"); + log("version of the circuit.\n"); + log("\n"); log("All wires in the modules from the map file matching the pattern _TECHMAP_*\n"); log("or *._TECHMAP_* are special wires that are used to pass instructions from\n"); log("the mapping module to the techmap command. At the moment the following special\n"); @@ -1144,6 +1206,12 @@ struct TechmapPass : public Pass { log("\n"); log("A cell with the name _TECHMAP_REPLACE_ in the map file will inherit the name\n"); log("and attributes of the cell that is being replaced.\n"); + log("A cell with a name of the form `_TECHMAP_REPLACE_.<suffix>` in the map file will\n"); + log("be named thus but with the `_TECHMAP_REPLACE_' prefix substituted with the name\n"); + log("of the cell being replaced.\n"); + log("Similarly, a wire named in the form `_TECHMAP_REPLACE_.<suffix>` will cause a\n"); + log("new wire alias to be created and named as above but with the `_TECHMAP_REPLACE_'\n"); + log("prefix also substituted.\n"); log("\n"); log("See 'help extract' for a pass that does the opposite thing.\n"); log("\n"); |