diff options
Diffstat (limited to 'passes/techmap/extract.cc')
-rw-r--r-- | passes/techmap/extract.cc | 517 |
1 files changed, 259 insertions, 258 deletions
diff --git a/passes/techmap/extract.cc b/passes/techmap/extract.cc index 221e9e49d..e0b1d360a 100644 --- a/passes/techmap/extract.cc +++ b/passes/techmap/extract.cc @@ -26,256 +26,240 @@ #include <stdio.h> #include <string.h> +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + using RTLIL::id2cstr; -namespace +class SubCircuitSolver : public SubCircuit::Solver { - class SubCircuitSolver : public SubCircuit::Solver - { - public: - bool ignore_parameters; - std::set<std::pair<RTLIL::IdString, RTLIL::IdString>> ignored_parameters; - std::set<RTLIL::IdString> cell_attr, wire_attr; +public: + bool ignore_parameters; + std::set<std::pair<RTLIL::IdString, RTLIL::IdString>> ignored_parameters; + std::set<RTLIL::IdString> cell_attr, wire_attr; - SubCircuitSolver() : ignore_parameters(false) - { - } + SubCircuitSolver() : ignore_parameters(false) + { + } - bool compareAttributes(const std::set<RTLIL::IdString> &attr, const std::map<RTLIL::IdString, RTLIL::Const> &needleAttr, const std::map<RTLIL::IdString, RTLIL::Const> &haystackAttr) - { - for (auto &it : attr) { - size_t nc = needleAttr.count(it), hc = haystackAttr.count(it); - if (nc != hc || (nc > 0 && needleAttr.at(it) != haystackAttr.at(it))) - return false; - } - return true; + bool compareAttributes(const std::set<RTLIL::IdString> &attr, const std::map<RTLIL::IdString, RTLIL::Const> &needleAttr, const std::map<RTLIL::IdString, RTLIL::Const> &haystackAttr) + { + for (auto &it : attr) { + size_t nc = needleAttr.count(it), hc = haystackAttr.count(it); + if (nc != hc || (nc > 0 && needleAttr.at(it) != haystackAttr.at(it))) + return false; } + return true; + } - RTLIL::Const unified_param(RTLIL::IdString cell_type, RTLIL::IdString param, RTLIL::Const value) - { - if (cell_type.substr(0, 1) != "$" || cell_type.substr(0, 2) == "$_") - return value; - - #define param_bool(_n) if (param == _n) return value.as_bool(); - param_bool("\\ARST_POLARITY"); - param_bool("\\A_SIGNED"); - param_bool("\\B_SIGNED"); - param_bool("\\CLK_ENABLE"); - param_bool("\\CLK_POLARITY"); - param_bool("\\CLR_POLARITY"); - param_bool("\\EN_POLARITY"); - param_bool("\\SET_POLARITY"); - param_bool("\\TRANSPARENT"); - #undef param_bool - - #define param_int(_n) if (param == _n) return value.as_int(); - param_int("\\ABITS") - param_int("\\A_WIDTH") - param_int("\\B_WIDTH") - param_int("\\CTRL_IN_WIDTH") - param_int("\\CTRL_OUT_WIDTH") - param_int("\\OFFSET") - param_int("\\PRIORITY") - param_int("\\RD_PORTS") - param_int("\\SIZE") - param_int("\\STATE_BITS") - param_int("\\STATE_NUM") - param_int("\\STATE_NUM_LOG2") - param_int("\\STATE_RST") - param_int("\\S_WIDTH") - param_int("\\TRANS_NUM") - param_int("\\WIDTH") - param_int("\\WR_PORTS") - param_int("\\Y_WIDTH") - #undef param_int - + RTLIL::Const unified_param(RTLIL::IdString cell_type, RTLIL::IdString param, RTLIL::Const value) + { + if (cell_type.substr(0, 1) != "$" || cell_type.substr(0, 2) == "$_") return value; - } - virtual bool userCompareNodes(const std::string &, const std::string &, void *needleUserData, - const std::string &, const std::string &, void *haystackUserData, const std::map<std::string, std::string> &portMapping) - { - RTLIL::Cell *needleCell = (RTLIL::Cell*) needleUserData; - RTLIL::Cell *haystackCell = (RTLIL::Cell*) haystackUserData; + #define param_bool(_n) if (param == _n) return value.as_bool(); + param_bool("\\ARST_POLARITY"); + param_bool("\\A_SIGNED"); + param_bool("\\B_SIGNED"); + param_bool("\\CLK_ENABLE"); + param_bool("\\CLK_POLARITY"); + param_bool("\\CLR_POLARITY"); + param_bool("\\EN_POLARITY"); + param_bool("\\SET_POLARITY"); + param_bool("\\TRANSPARENT"); + #undef param_bool + + #define param_int(_n) if (param == _n) return value.as_int(); + param_int("\\ABITS") + param_int("\\A_WIDTH") + param_int("\\B_WIDTH") + param_int("\\CTRL_IN_WIDTH") + param_int("\\CTRL_OUT_WIDTH") + param_int("\\OFFSET") + param_int("\\PRIORITY") + param_int("\\RD_PORTS") + param_int("\\SIZE") + param_int("\\STATE_BITS") + param_int("\\STATE_NUM") + param_int("\\STATE_NUM_LOG2") + param_int("\\STATE_RST") + param_int("\\S_WIDTH") + param_int("\\TRANS_NUM") + param_int("\\WIDTH") + param_int("\\WR_PORTS") + param_int("\\Y_WIDTH") + #undef param_int + + return value; + } - if (!needleCell || !haystackCell) { - log_assert(!needleCell && !haystackCell); - return true; - } + virtual bool userCompareNodes(const std::string &, const std::string &, void *needleUserData, + const std::string &, const std::string &, void *haystackUserData, const std::map<std::string, std::string> &portMapping) + { + RTLIL::Cell *needleCell = (RTLIL::Cell*) needleUserData; + RTLIL::Cell *haystackCell = (RTLIL::Cell*) haystackUserData; - if (!ignore_parameters) { - std::map<RTLIL::IdString, RTLIL::Const> needle_param, haystack_param; - for (auto &it : needleCell->parameters) - if (!ignored_parameters.count(std::pair<RTLIL::IdString, RTLIL::IdString>(needleCell->type, it.first))) - needle_param[it.first] = unified_param(needleCell->type, it.first, it.second); - for (auto &it : haystackCell->parameters) - if (!ignored_parameters.count(std::pair<RTLIL::IdString, RTLIL::IdString>(haystackCell->type, it.first))) - haystack_param[it.first] = unified_param(haystackCell->type, it.first, it.second); - if (needle_param != haystack_param) - return false; - } + if (!needleCell || !haystackCell) { + log_assert(!needleCell && !haystackCell); + return true; + } - if (cell_attr.size() > 0 && !compareAttributes(cell_attr, needleCell->attributes, haystackCell->attributes)) + if (!ignore_parameters) { + std::map<RTLIL::IdString, RTLIL::Const> needle_param, haystack_param; + for (auto &it : needleCell->parameters) + if (!ignored_parameters.count(std::pair<RTLIL::IdString, RTLIL::IdString>(needleCell->type, it.first))) + needle_param[it.first] = unified_param(needleCell->type, it.first, it.second); + for (auto &it : haystackCell->parameters) + if (!ignored_parameters.count(std::pair<RTLIL::IdString, RTLIL::IdString>(haystackCell->type, it.first))) + haystack_param[it.first] = unified_param(haystackCell->type, it.first, it.second); + if (needle_param != haystack_param) return false; + } - if (wire_attr.size() > 0) - { - RTLIL::Wire *lastNeedleWire = NULL; - RTLIL::Wire *lastHaystackWire = NULL; - std::map<RTLIL::IdString, RTLIL::Const> emptyAttr; + if (cell_attr.size() > 0 && !compareAttributes(cell_attr, needleCell->attributes, haystackCell->attributes)) + return false; - for (auto &conn : needleCell->connections()) - { - RTLIL::SigSpec needleSig = conn.second; - RTLIL::SigSpec haystackSig = haystackCell->getPort(portMapping.at(conn.first.str())); - - for (int i = 0; i < std::min(needleSig.size(), haystackSig.size()); i++) { - RTLIL::Wire *needleWire = needleSig[i].wire, *haystackWire = haystackSig[i].wire; - if (needleWire != lastNeedleWire || haystackWire != lastHaystackWire) - if (!compareAttributes(wire_attr, needleWire ? needleWire->attributes : emptyAttr, haystackWire ? haystackWire->attributes : emptyAttr)) - return false; - lastNeedleWire = needleWire, lastHaystackWire = haystackWire; - } + if (wire_attr.size() > 0) + { + RTLIL::Wire *lastNeedleWire = NULL; + RTLIL::Wire *lastHaystackWire = NULL; + std::map<RTLIL::IdString, RTLIL::Const> emptyAttr; + + for (auto &conn : needleCell->connections()) + { + RTLIL::SigSpec needleSig = conn.second; + RTLIL::SigSpec haystackSig = haystackCell->getPort(portMapping.at(conn.first.str())); + + for (int i = 0; i < std::min(needleSig.size(), haystackSig.size()); i++) { + RTLIL::Wire *needleWire = needleSig[i].wire, *haystackWire = haystackSig[i].wire; + if (needleWire != lastNeedleWire || haystackWire != lastHaystackWire) + if (!compareAttributes(wire_attr, needleWire ? needleWire->attributes : emptyAttr, haystackWire ? haystackWire->attributes : emptyAttr)) + return false; + lastNeedleWire = needleWire, lastHaystackWire = haystackWire; } } - - return true; } - }; - struct bit_ref_t { - std::string cell, port; - int bit; - }; + return true; + } +}; - bool module2graph(SubCircuit::Graph &graph, RTLIL::Module *mod, bool constports, RTLIL::Design *sel = NULL, - int max_fanout = -1, std::set<std::pair<RTLIL::IdString, RTLIL::IdString>> *split = NULL) - { - SigMap sigmap(mod); - std::map<RTLIL::SigBit, bit_ref_t> sig_bit_ref; +struct bit_ref_t { + std::string cell, port; + int bit; +}; - if (sel && !sel->selected(mod)) { - log(" Skipping module %s as it is not selected.\n", id2cstr(mod->name)); - return false; - } +bool module2graph(SubCircuit::Graph &graph, RTLIL::Module *mod, bool constports, RTLIL::Design *sel = NULL, + int max_fanout = -1, std::set<std::pair<RTLIL::IdString, RTLIL::IdString>> *split = NULL) +{ + SigMap sigmap(mod); + std::map<RTLIL::SigBit, bit_ref_t> sig_bit_ref; - if (mod->processes.size() > 0) { - log(" Skipping module %s as it contains unprocessed processes.\n", id2cstr(mod->name)); - return false; - } + if (sel && !sel->selected(mod)) { + log(" Skipping module %s as it is not selected.\n", id2cstr(mod->name)); + return false; + } - if (constports) { - graph.createNode("$const$0", "$const$0", NULL, true); - graph.createNode("$const$1", "$const$1", NULL, true); - graph.createNode("$const$x", "$const$x", NULL, true); - graph.createNode("$const$z", "$const$z", NULL, true); - graph.createPort("$const$0", "\\Y", 1); - graph.createPort("$const$1", "\\Y", 1); - graph.createPort("$const$x", "\\Y", 1); - graph.createPort("$const$z", "\\Y", 1); - graph.markExtern("$const$0", "\\Y", 0); - graph.markExtern("$const$1", "\\Y", 0); - graph.markExtern("$const$x", "\\Y", 0); - graph.markExtern("$const$z", "\\Y", 0); - } + if (mod->processes.size() > 0) { + log(" Skipping module %s as it contains unprocessed processes.\n", id2cstr(mod->name)); + return false; + } - std::map<std::pair<RTLIL::Wire*, int>, int> sig_use_count; - if (max_fanout > 0) - for (auto &cell_it : mod->cells_) - { - RTLIL::Cell *cell = cell_it.second; - if (!sel || sel->selected(mod, cell)) - for (auto &conn : cell->connections()) { - RTLIL::SigSpec conn_sig = conn.second; - sigmap.apply(conn_sig); - for (auto &bit : conn_sig) - if (bit.wire != NULL) - sig_use_count[std::pair<RTLIL::Wire*, int>(bit.wire, bit.offset)]++; - } - } + if (constports) { + graph.createNode("$const$0", "$const$0", NULL, true); + graph.createNode("$const$1", "$const$1", NULL, true); + graph.createNode("$const$x", "$const$x", NULL, true); + graph.createNode("$const$z", "$const$z", NULL, true); + graph.createPort("$const$0", "\\Y", 1); + graph.createPort("$const$1", "\\Y", 1); + graph.createPort("$const$x", "\\Y", 1); + graph.createPort("$const$z", "\\Y", 1); + graph.markExtern("$const$0", "\\Y", 0); + graph.markExtern("$const$1", "\\Y", 0); + graph.markExtern("$const$x", "\\Y", 0); + graph.markExtern("$const$z", "\\Y", 0); + } - // create graph nodes from cells + std::map<std::pair<RTLIL::Wire*, int>, int> sig_use_count; + if (max_fanout > 0) for (auto &cell_it : mod->cells_) { RTLIL::Cell *cell = cell_it.second; - if (sel && !sel->selected(mod, cell)) - continue; + if (!sel || sel->selected(mod, cell)) + for (auto &conn : cell->connections()) { + RTLIL::SigSpec conn_sig = conn.second; + sigmap.apply(conn_sig); + for (auto &bit : conn_sig) + if (bit.wire != NULL) + sig_use_count[std::pair<RTLIL::Wire*, int>(bit.wire, bit.offset)]++; + } + } - std::string type = cell->type.str(); - if (sel == NULL && type.substr(0, 2) == "\\$") - type = type.substr(1); - graph.createNode(cell->name.str(), type, (void*)cell); + // create graph nodes from cells + for (auto &cell_it : mod->cells_) + { + RTLIL::Cell *cell = cell_it.second; + if (sel && !sel->selected(mod, cell)) + continue; - for (auto &conn : cell->connections()) - { - graph.createPort(cell->name.str(), conn.first.str(), conn.second.size()); + std::string type = cell->type.str(); + if (sel == NULL && type.substr(0, 2) == "\\$") + type = type.substr(1); + graph.createNode(cell->name.str(), type, (void*)cell); - if (split && split->count(std::pair<RTLIL::IdString, RTLIL::IdString>(cell->type, conn.first)) > 0) - continue; + for (auto &conn : cell->connections()) + { + graph.createPort(cell->name.str(), conn.first.str(), conn.second.size()); - RTLIL::SigSpec conn_sig = conn.second; - sigmap.apply(conn_sig); + if (split && split->count(std::pair<RTLIL::IdString, RTLIL::IdString>(cell->type, conn.first)) > 0) + continue; - for (int i = 0; i < conn_sig.size(); i++) - { - auto &bit = conn_sig[i]; - - if (bit.wire == NULL) { - if (constports) { - std::string node = "$const$x"; - if (bit == RTLIL::State::S0) node = "$const$0"; - if (bit == RTLIL::State::S1) node = "$const$1"; - if (bit == RTLIL::State::Sz) node = "$const$z"; - graph.createConnection(cell->name.str(), conn.first.str(), i, node, "\\Y", 0); - } else - graph.createConstant(cell->name.str(), conn.first.str(), i, int(bit.data)); - continue; - } + RTLIL::SigSpec conn_sig = conn.second; + sigmap.apply(conn_sig); - if (max_fanout > 0 && sig_use_count[std::pair<RTLIL::Wire*, int>(bit.wire, bit.offset)] > max_fanout) - continue; + for (int i = 0; i < conn_sig.size(); i++) + { + auto &bit = conn_sig[i]; + + if (bit.wire == NULL) { + if (constports) { + std::string node = "$const$x"; + if (bit == RTLIL::State::S0) node = "$const$0"; + if (bit == RTLIL::State::S1) node = "$const$1"; + if (bit == RTLIL::State::Sz) node = "$const$z"; + graph.createConnection(cell->name.str(), conn.first.str(), i, node, "\\Y", 0); + } else + graph.createConstant(cell->name.str(), conn.first.str(), i, int(bit.data)); + continue; + } - if (sel && !sel->selected(mod, bit.wire)) - continue; + if (max_fanout > 0 && sig_use_count[std::pair<RTLIL::Wire*, int>(bit.wire, bit.offset)] > max_fanout) + continue; - if (sig_bit_ref.count(bit) == 0) { - bit_ref_t &bit_ref = sig_bit_ref[bit]; - bit_ref.cell = cell->name.str(); - bit_ref.port = conn.first.str(); - bit_ref.bit = i; - } + if (sel && !sel->selected(mod, bit.wire)) + continue; + if (sig_bit_ref.count(bit) == 0) { bit_ref_t &bit_ref = sig_bit_ref[bit]; - graph.createConnection(bit_ref.cell, bit_ref.port, bit_ref.bit, cell->name.str(), conn.first.str(), i); + bit_ref.cell = cell->name.str(); + bit_ref.port = conn.first.str(); + bit_ref.bit = i; } - } - } - - // mark external signals (used in non-selected cells) - for (auto &cell_it : mod->cells_) - { - RTLIL::Cell *cell = cell_it.second; - if (sel && !sel->selected(mod, cell)) - for (auto &conn : cell->connections()) - { - RTLIL::SigSpec conn_sig = conn.second; - sigmap.apply(conn_sig); - for (auto &bit : conn_sig) - if (sig_bit_ref.count(bit) != 0) { - bit_ref_t &bit_ref = sig_bit_ref[bit]; - graph.markExtern(bit_ref.cell, bit_ref.port, bit_ref.bit); - } - } + bit_ref_t &bit_ref = sig_bit_ref[bit]; + graph.createConnection(bit_ref.cell, bit_ref.port, bit_ref.bit, cell->name.str(), conn.first.str(), i); + } } + } - // mark external signals (used in module ports) - for (auto &wire_it : mod->wires_) - { - RTLIL::Wire *wire = wire_it.second; - if (wire->port_id > 0) + // mark external signals (used in non-selected cells) + for (auto &cell_it : mod->cells_) + { + RTLIL::Cell *cell = cell_it.second; + if (sel && !sel->selected(mod, cell)) + for (auto &conn : cell->connections()) { - RTLIL::SigSpec conn_sig(wire); + RTLIL::SigSpec conn_sig = conn.second; sigmap.apply(conn_sig); for (auto &bit : conn_sig) @@ -284,70 +268,86 @@ namespace graph.markExtern(bit_ref.cell, bit_ref.port, bit_ref.bit); } } - } - - // graph.print(); - return true; } - RTLIL::Cell *replace(RTLIL::Module *needle, RTLIL::Module *haystack, SubCircuit::Solver::Result &match) + // mark external signals (used in module ports) + for (auto &wire_it : mod->wires_) { - SigMap sigmap(needle); - SigSet<std::pair<RTLIL::IdString, int>> sig2port; - - // create new cell - RTLIL::Cell *cell = haystack->addCell(stringf("$extract$%s$%d", needle->name.c_str(), autoidx++), needle->name); - - // create cell ports - for (auto &it : needle->wires_) { - RTLIL::Wire *wire = it.second; - if (wire->port_id > 0) { - for (int i = 0; i < wire->width; i++) - sig2port.insert(sigmap(RTLIL::SigSpec(wire, i)), std::pair<RTLIL::IdString, int>(wire->name, i)); - cell->setPort(wire->name, RTLIL::SigSpec(RTLIL::State::Sz, wire->width)); - } + RTLIL::Wire *wire = wire_it.second; + if (wire->port_id > 0) + { + RTLIL::SigSpec conn_sig(wire); + sigmap.apply(conn_sig); + + for (auto &bit : conn_sig) + if (sig_bit_ref.count(bit) != 0) { + bit_ref_t &bit_ref = sig_bit_ref[bit]; + graph.markExtern(bit_ref.cell, bit_ref.port, bit_ref.bit); + } } + } - // delete replaced cells and connect new ports - for (auto &it : match.mappings) - { - auto &mapping = it.second; - RTLIL::Cell *needle_cell = (RTLIL::Cell*)mapping.needleUserData; - RTLIL::Cell *haystack_cell = (RTLIL::Cell*)mapping.haystackUserData; + // graph.print(); + return true; +} - if (needle_cell == NULL) - continue; +RTLIL::Cell *replace(RTLIL::Module *needle, RTLIL::Module *haystack, SubCircuit::Solver::Result &match) +{ + SigMap sigmap(needle); + SigSet<std::pair<RTLIL::IdString, int>> sig2port; + + // create new cell + RTLIL::Cell *cell = haystack->addCell(stringf("$extract$%s$%d", needle->name.c_str(), autoidx++), needle->name); + + // create cell ports + for (auto &it : needle->wires_) { + RTLIL::Wire *wire = it.second; + if (wire->port_id > 0) { + for (int i = 0; i < wire->width; i++) + sig2port.insert(sigmap(RTLIL::SigSpec(wire, i)), std::pair<RTLIL::IdString, int>(wire->name, i)); + cell->setPort(wire->name, RTLIL::SigSpec(RTLIL::State::Sz, wire->width)); + } + } - for (auto &conn : needle_cell->connections()) { - RTLIL::SigSpec sig = sigmap(conn.second); - if (mapping.portMapping.count(conn.first.str()) > 0 && sig2port.has(sigmap(sig))) { - for (int i = 0; i < sig.size(); i++) - for (auto &port : sig2port.find(sig[i])) { - RTLIL::SigSpec bitsig = haystack_cell->getPort(mapping.portMapping[conn.first.str()]).extract(i, 1); - RTLIL::SigSpec new_sig = cell->getPort(port.first); - new_sig.replace(port.second, bitsig); - cell->setPort(port.first, new_sig); - } + // delete replaced cells and connect new ports + for (auto &it : match.mappings) + { + auto &mapping = it.second; + RTLIL::Cell *needle_cell = (RTLIL::Cell*)mapping.needleUserData; + RTLIL::Cell *haystack_cell = (RTLIL::Cell*)mapping.haystackUserData; + + if (needle_cell == NULL) + continue; + + for (auto &conn : needle_cell->connections()) { + RTLIL::SigSpec sig = sigmap(conn.second); + if (mapping.portMapping.count(conn.first.str()) > 0 && sig2port.has(sigmap(sig))) { + for (int i = 0; i < sig.size(); i++) + for (auto &port : sig2port.find(sig[i])) { + RTLIL::SigSpec bitsig = haystack_cell->getPort(mapping.portMapping[conn.first.str()]).extract(i, 1); + RTLIL::SigSpec new_sig = cell->getPort(port.first); + new_sig.replace(port.second, bitsig); + cell->setPort(port.first, new_sig); } } - - haystack->remove(haystack_cell); } - return cell; + haystack->remove(haystack_cell); } - bool compareSortNeedleList(RTLIL::Module *left, RTLIL::Module *right) - { - int left_idx = 0, right_idx = 0; - if (left->attributes.count("\\extract_order") > 0) - left_idx = left->attributes.at("\\extract_order").as_int(); - if (right->attributes.count("\\extract_order") > 0) - right_idx = right->attributes.at("\\extract_order").as_int(); - if (left_idx != right_idx) - return left_idx < right_idx; - return left->name < right->name; - } + return cell; +} + +bool compareSortNeedleList(RTLIL::Module *left, RTLIL::Module *right) +{ + int left_idx = 0, right_idx = 0; + if (left->attributes.count("\\extract_order") > 0) + left_idx = left->attributes.at("\\extract_order").as_int(); + if (right->attributes.count("\\extract_order") > 0) + right_idx = right->attributes.at("\\extract_order").as_int(); + if (left_idx != right_idx) + return left_idx < right_idx; + return left->name < right->name; } struct ExtractPass : public Pass { @@ -761,3 +761,4 @@ struct ExtractPass : public Pass { } } ExtractPass; +PRIVATE_NAMESPACE_END |