diff options
Diffstat (limited to 'passes/techmap/iopadmap.cc')
-rw-r--r-- | passes/techmap/iopadmap.cc | 101 |
1 files changed, 81 insertions, 20 deletions
diff --git a/passes/techmap/iopadmap.cc b/passes/techmap/iopadmap.cc index 531ac2b99..8b1862237 100644 --- a/passes/techmap/iopadmap.cc +++ b/passes/techmap/iopadmap.cc @@ -83,6 +83,20 @@ struct IopadmapPass : public Pass { log("Tristate PADS (-toutpad, -tinoutpad) always operate in -bits mode.\n"); log("\n"); } + + void module_queue(Design *design, Module *module, std::vector<Module *> &modules_sorted, pool<Module *> &modules_processed) { + if (modules_processed.count(module)) + return; + for (auto cell : module->cells()) { + Module *submodule = design->module(cell->type); + if (!submodule) + continue; + module_queue(design, submodule, modules_sorted, modules_processed); + } + modules_sorted.push_back(module); + modules_processed.insert(module); + } + void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing IOPADMAP pass (mapping inputs/outputs to IO-PAD cells).\n"); @@ -172,22 +186,49 @@ struct IopadmapPass : public Pass { if (!tinoutpad_portname_pad.empty()) ignore.insert(make_pair(RTLIL::escape_id(tinoutpad_celltype), RTLIL::escape_id(tinoutpad_portname_pad))); - for (auto module : design->modules()) - if (module->get_blackbox_attribute()) - for (auto wire : module->wires()) - if (wire->get_bool_attribute("\\iopad_external_pin")) - ignore.insert(make_pair(module->name, wire->name)); + // Recursively collect list of (module, port, bit) triples that already have buffers. + + pool<pair<IdString, pair<IdString, int>>> buf_ports; + // Process submodules before module using them. + std::vector<Module *> modules_sorted; + pool<Module *> modules_processed; for (auto module : design->selected_modules()) + module_queue(design, module, modules_sorted, modules_processed); + + for (auto module : modules_sorted) { - pool<SigBit> skip_wire_bits; - dict<Wire *, dict<int, pair<Cell *, IdString>>> rewrite_bits; + pool<SigBit> buf_bits; + SigMap sigmap(module); + // Collect explicitly-marked already-buffered SigBits. + for (auto wire : module->wires()) + if (wire->get_bool_attribute("\\iopad_external_pin") || ignore.count(make_pair(module->name, wire->name))) + for (int i = 0; i < GetSize(wire); i++) + buf_bits.insert(sigmap(SigBit(wire, i))); + + // Collect SigBits connected to already-buffered ports. for (auto cell : module->cells()) for (auto port : cell->connections()) - if (ignore.count(make_pair(cell->type, port.first))) - for (auto bit : port.second) - skip_wire_bits.insert(bit); + for (int i = 0; i < port.second.size(); i++) + if (buf_ports.count(make_pair(cell->type, make_pair(port.first, i)))) + buf_bits.insert(sigmap(port.second[i])); + + // Now fill buf_ports. + for (auto wire : module->wires()) + if (wire->port_input || wire->port_output) + for (int i = 0; i < GetSize(wire); i++) + if (buf_bits.count(sigmap(SigBit(wire, i)))) { + buf_ports.insert(make_pair(module->name, make_pair(wire->name, i))); + log("Marking already mapped port: %s.%s[%d].\n", log_id(module), log_id(wire), i); + } + } + + // Now do the actual buffer insertion. + + for (auto module : design->selected_modules()) + { + dict<Wire *, dict<int, pair<Cell *, IdString>>> rewrite_bits; if (!toutpad_celltype.empty() || !tinoutpad_celltype.empty()) { @@ -234,7 +275,7 @@ struct IopadmapPass : public Pass { SigBit wire_bit(wire, i); Cell *tbuf_cell = nullptr; - if (skip_wire_bits.count(wire_bit)) + if (buf_ports.count(make_pair(module->name, make_pair(wire->name, i)))) continue; if (tbuf_bits.count(wire_bit)) @@ -267,7 +308,9 @@ struct IopadmapPass : public Pass { { log("Mapping port %s.%s[%d] using %s.\n", log_id(module), log_id(wire), i, tinoutpad_celltype.c_str()); - Cell *cell = module->addCell(NEW_ID, RTLIL::escape_id(tinoutpad_celltype)); + Cell *cell = module->addCell( + module->uniquify(stringf("$iopadmap$%s.%s[%d]", log_id(module), log_id(wire), i)), + RTLIL::escape_id(tinoutpad_celltype)); cell->setPort(RTLIL::escape_id(tinoutpad_portname_oe), en_sig); cell->attributes[ID::keep] = RTLIL::Const(1); @@ -282,13 +325,14 @@ struct IopadmapPass : public Pass { cell->setPort(RTLIL::escape_id(tinoutpad_portname_o), wire_bit); cell->setPort(RTLIL::escape_id(tinoutpad_portname_i), data_sig); } - skip_wire_bits.insert(wire_bit); if (!tinoutpad_portname_pad.empty()) rewrite_bits[wire][i] = make_pair(cell, RTLIL::escape_id(tinoutpad_portname_pad)); } else { log("Mapping port %s.%s[%d] using %s.\n", log_id(module), log_id(wire), i, toutpad_celltype.c_str()); - Cell *cell = module->addCell(NEW_ID, RTLIL::escape_id(toutpad_celltype)); + Cell *cell = module->addCell( + module->uniquify(stringf("$iopadmap$%s.%s[%d]", log_id(module), log_id(wire), i)), + RTLIL::escape_id(toutpad_celltype)); cell->setPort(RTLIL::escape_id(toutpad_portname_oe), en_sig); cell->setPort(RTLIL::escape_id(toutpad_portname_i), data_sig); @@ -298,10 +342,10 @@ struct IopadmapPass : public Pass { module->remove(tbuf_cell); module->connect(wire_bit, data_sig); } - skip_wire_bits.insert(wire_bit); if (!toutpad_portname_pad.empty()) rewrite_bits[wire][i] = make_pair(cell, RTLIL::escape_id(toutpad_portname_pad)); } + buf_ports.insert(make_pair(module->name, make_pair(wire->name, i))); } } } @@ -315,7 +359,7 @@ struct IopadmapPass : public Pass { pool<int> skip_bit_indices; for (int i = 0; i < GetSize(wire); i++) - if (skip_wire_bits.count(SigBit(wire, i))) + if (buf_ports.count(make_pair(module->name, make_pair(wire->name, i)))) skip_bit_indices.insert(i); if (GetSize(wire) == GetSize(skip_bit_indices)) @@ -366,7 +410,9 @@ struct IopadmapPass : public Pass { SigBit wire_bit(wire, i); - RTLIL::Cell *cell = module->addCell(NEW_ID, RTLIL::escape_id(celltype)); + RTLIL::Cell *cell = module->addCell( + module->uniquify(stringf("$iopadmap$%s.%s", log_id(module->name), log_id(wire->name))), + RTLIL::escape_id(celltype)); cell->setPort(RTLIL::escape_id(portname_int), wire_bit); if (!portname_pad.empty()) @@ -380,12 +426,16 @@ struct IopadmapPass : public Pass { } else { - RTLIL::Cell *cell = module->addCell(NEW_ID, RTLIL::escape_id(celltype)); + RTLIL::Cell *cell = module->addCell( + module->uniquify(stringf("$iopadmap$%s.%s", log_id(module->name), log_id(wire->name))), + RTLIL::escape_id(celltype)); cell->setPort(RTLIL::escape_id(portname_int), RTLIL::SigSpec(wire)); if (!portname_pad.empty()) { RTLIL::Wire *new_wire = NULL; - new_wire = module->addWire(NEW_ID, wire); + new_wire = module->addWire( + module->uniquify(stringf("$iopadmap$%s", log_id(wire))), + wire); module->swap_names(new_wire, wire); wire->attributes.clear(); cell->setPort(RTLIL::escape_id(portname_pad), RTLIL::SigSpec(new_wire)); @@ -406,7 +456,9 @@ struct IopadmapPass : public Pass { for (auto &it : rewrite_bits) { RTLIL::Wire *wire = it.first; - RTLIL::Wire *new_wire = module->addWire(NEW_ID, wire); + RTLIL::Wire *new_wire = module->addWire( + module->uniquify(stringf("$iopadmap$%s", log_id(wire))), + wire); module->swap_names(new_wire, wire); wire->attributes.clear(); for (int i = 0; i < wire->width; i++) @@ -423,6 +475,15 @@ struct IopadmapPass : public Pass { } } + if (wire->port_output) { + auto jt = new_wire->attributes.find(ID(init)); + // For output ports, move \init attributes from old wire to new wire + if (jt != new_wire->attributes.end()) { + wire->attributes[ID(init)] = std::move(jt->second); + new_wire->attributes.erase(jt); + } + } + wire->port_id = 0; wire->port_input = false; wire->port_output = false; |