diff options
| -rw-r--r-- | passes/techmap/iopadmap.cc | 23 | ||||
| -rw-r--r-- | tests/techmap/iopadmap.ys | 37 | 
2 files changed, 57 insertions, 3 deletions
| diff --git a/passes/techmap/iopadmap.cc b/passes/techmap/iopadmap.cc index 531ac2b99..b3ae5eafe 100644 --- a/passes/techmap/iopadmap.cc +++ b/passes/techmap/iopadmap.cc @@ -408,18 +408,35 @@ struct IopadmapPass : public Pass {  				RTLIL::Wire *wire = it.first;  				RTLIL::Wire *new_wire = module->addWire(NEW_ID, wire);  				module->swap_names(new_wire, wire); -				wire->attributes.clear();  				for (int i = 0; i < wire->width; i++)  				{  					SigBit wire_bit(wire, i);  					if (!it.second.count(i)) { -						if (wire->port_output) +						if (wire->port_output) {  							module->connect(SigSpec(new_wire, i), SigSpec(wire, i)); -						else +							wire->attributes.clear(); +						} +						else {  							module->connect(SigSpec(wire, i), SigSpec(new_wire, i)); +							wire->attributes.clear(); + +						}  					} else {  						auto &new_conn = it.second.at(i);  						new_conn.first->setPort(new_conn.second, RTLIL::SigSpec(new_wire, i)); + +						// For cell outputs, move \init attributes from old wire to new wire +						if (new_conn.first->output(new_conn.second)) { +							auto it = wire->attributes.find(ID(init)); +							if (it != wire->attributes.end()) { +								for (auto it2 = wire->attributes.begin(); it2 != wire->attributes.end(); ) +									if (it == it2) +										++it2; +									else +										it2 = wire->attributes.erase(it2); +								new_wire->attributes.erase(ID(init)); +							} +						}  					}  				} diff --git a/tests/techmap/iopadmap.ys b/tests/techmap/iopadmap.ys index c058d1607..b787bb55f 100644 --- a/tests/techmap/iopadmap.ys +++ b/tests/techmap/iopadmap.ys @@ -120,3 +120,40 @@ select -assert-count 1 g/t:iobuf  select -assert-count 1 h/t:ibuf  select -assert-count 1 h/t:iobuf  select -assert-count 1 h/t:obuf + + +# Check that \init attributes get moved from output buffer +#   to buffer input +design -reset +read_verilog << EOT +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 sub(input i, output o); endmodule + +module a(input i, (* init=1'b1 *) output o); +sub s(.i(i), .o(o)); +endmodule + +module b(input i, oe, output o); +(* init=1'b1 *) wire w; +sub s(.i(i), .o(w)); +assign o = oe ? w : 1'bz; +endmodule + +module c(input i, oe, inout io); +(* init=1'b1 *) wire w; +sub s(.i(i), .o(w)); +assign io = oe ? w : 1'bz; +endmodule +EOT +opt_clean +tribuf +simplemap +iopadmap -bits -outpad obuf i:o -toutpad obuft oe:i:o -tinoutpad iobuf oe:o:i:io +select -assert-count 1 a/c:s %co a/a:init=1'1 %i +select -assert-count 1 a/a:init=1'1 +select -assert-count 1 b/c:s %co b/a:init=1'1 %i +select -assert-count 1 b/a:init=1'1 +select -assert-count 1 c/c:s %co c/a:init=1'1 %i +select -assert-count 1 c/a:init=1'1 | 
