mirror of https://github.com/YosysHQ/yosys.git
iopadmap: Look harder for already-present buffers. (#1731)
iopadmap: Look harder for already-present buffers. Fixes #1720.
This commit is contained in:
parent
4f889b2f57
commit
968956badb
|
@ -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,23 +186,50 @@ 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> 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())
|
||||
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())
|
||||
{
|
||||
pool<SigBit> skip_wire_bits;
|
||||
dict<Wire *, dict<int, pair<Cell *, IdString>>> rewrite_bits;
|
||||
|
||||
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);
|
||||
|
||||
if (!toutpad_celltype.empty() || !tinoutpad_celltype.empty())
|
||||
{
|
||||
dict<SigBit, Cell *> tbuf_bits;
|
||||
|
@ -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))
|
||||
|
@ -282,7 +323,6 @@ 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 {
|
||||
|
@ -298,10 +338,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 +355,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))
|
||||
|
|
|
@ -4,12 +4,15 @@ module obuf (input i, (* iopad_external_pin *) output o); endmodule
|
|||
module obuft (input i, input oe, (* iopad_external_pin *) output o); endmodule
|
||||
module iobuf (input i, input oe, output o, (* iopad_external_pin *) inout io); endmodule
|
||||
|
||||
module buf_inside (input i, output o);
|
||||
obuf b (.i(i), .o(o));
|
||||
endmodule
|
||||
|
||||
module a(input i, output o);
|
||||
assign o = i;
|
||||
endmodule
|
||||
|
||||
module b(input i, output o);
|
||||
assign o = i;
|
||||
ibuf b (.i(i), .o(o));
|
||||
endmodule
|
||||
|
||||
|
@ -42,12 +45,22 @@ assign io = i;
|
|||
assign o = io;
|
||||
endmodule
|
||||
|
||||
module i(input i, output o);
|
||||
buf_inside b (.i(i), .o(o));
|
||||
endmodule
|
||||
|
||||
module j(input i, output o);
|
||||
wire tmp;
|
||||
obuf b (.i(i), .o(tmp));
|
||||
assign o = tmp;
|
||||
endmodule
|
||||
|
||||
EOT
|
||||
|
||||
opt_clean
|
||||
tribuf
|
||||
simplemap
|
||||
iopadmap -bits -inpad ibuf o:i -outpad obuf i:o -toutpad obuft oe:i:o -tinoutpad iobuf oe:o:i:io
|
||||
iopadmap -bits -inpad ibuf o:i -outpad obuf i:o -toutpad obuft oe:i:o -tinoutpad iobuf oe:o:i:io a b c d e f g h i j
|
||||
opt_clean
|
||||
|
||||
select -assert-count 1 a/t:ibuf
|
||||
|
@ -121,6 +134,12 @@ select -assert-count 1 h/t:ibuf
|
|||
select -assert-count 1 h/t:iobuf
|
||||
select -assert-count 1 h/t:obuf
|
||||
|
||||
select -assert-count 1 i/t:ibuf
|
||||
select -assert-count 0 i/t:obuf
|
||||
|
||||
select -assert-count 1 j/t:ibuf
|
||||
select -assert-count 1 j/t:obuf
|
||||
|
||||
|
||||
# Check that \init attributes get moved from output buffer
|
||||
# to buffer input
|
||||
|
|
Loading…
Reference in New Issue