Correct handling of unconnected ports in output Verilog netlist...
...so that outputs are not connected to constants. Signed-off-by: Maciej Kurc <mkurc@antmicro.com>
This commit is contained in:
parent
782cdfd8e1
commit
721ac99696
|
@ -125,6 +125,9 @@ std::string join_identifier(std::string lhs, std::string rhs);
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
|
|
||||||
|
// Unconnected net prefix
|
||||||
|
const std::string unconn_prefix = "__vpr__unconn";
|
||||||
|
|
||||||
//A combinational timing arc
|
//A combinational timing arc
|
||||||
class Arc {
|
class Arc {
|
||||||
public:
|
public:
|
||||||
|
@ -945,6 +948,16 @@ class NetlistWriterVisitor : public NetlistVisitor {
|
||||||
inst->print_verilog(verilog_os_, unconn_count, depth + 1);
|
inst->print_verilog(verilog_os_, unconn_count, depth + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Unconnected wires
|
||||||
|
if (unconn_count) {
|
||||||
|
verilog_os_ << "\n";
|
||||||
|
verilog_os_ << indent(depth + 1) << "//Unconnected wires\n";
|
||||||
|
for (size_t i = 0; i < unconn_count; ++i) {
|
||||||
|
auto name = unconn_prefix + std::to_string(i);
|
||||||
|
verilog_os_ << indent(depth + 1) << "wire " << escape_verilog_identifier(name) << ";\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
verilog_os_ << "\n";
|
verilog_os_ << "\n";
|
||||||
verilog_os_ << indent(depth) << "endmodule\n";
|
verilog_os_ << indent(depth) << "endmodule\n";
|
||||||
}
|
}
|
||||||
|
@ -2126,7 +2139,7 @@ double get_delay_ps(double delay_sec) {
|
||||||
std::string create_unconn_net(size_t& unconn_count) {
|
std::string create_unconn_net(size_t& unconn_count) {
|
||||||
//We increment unconn_count by reference so each
|
//We increment unconn_count by reference so each
|
||||||
//call generates a unique name
|
//call generates a unique name
|
||||||
return "__vpr__unconn" + std::to_string(unconn_count++);
|
return unconn_prefix + std::to_string(unconn_count++);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2169,6 +2182,30 @@ void print_blif_port(std::ostream& os, size_t& unconn_count, const std::string&
|
||||||
* Handles special cases like multi-bit and disconnected ports
|
* Handles special cases like multi-bit and disconnected ports
|
||||||
*/
|
*/
|
||||||
void print_verilog_port(std::ostream& os, size_t& unconn_count, const std::string& port_name, const std::vector<std::string>& nets, PortType type, int depth, struct t_analysis_opts& opts) {
|
void print_verilog_port(std::ostream& os, size_t& unconn_count, const std::string& port_name, const std::vector<std::string>& nets, PortType type, int depth, struct t_analysis_opts& opts) {
|
||||||
|
auto unconn_inp_name = [&]() {
|
||||||
|
switch (opts.post_synth_netlist_unconn_input_handling) {
|
||||||
|
case e_post_synth_netlist_unconn_handling::GND:
|
||||||
|
return std::string("1'b0");
|
||||||
|
case e_post_synth_netlist_unconn_handling::VCC:
|
||||||
|
return std::string("1'b1");
|
||||||
|
case e_post_synth_netlist_unconn_handling::NETS:
|
||||||
|
return create_unconn_net(unconn_count);
|
||||||
|
case e_post_synth_netlist_unconn_handling::UNCONNECTED:
|
||||||
|
default:
|
||||||
|
return std::string("1'bX");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
auto unconn_out_name = [&]() {
|
||||||
|
switch (opts.post_synth_netlist_unconn_output_handling) {
|
||||||
|
case e_post_synth_netlist_unconn_handling::NETS:
|
||||||
|
return create_unconn_net(unconn_count);
|
||||||
|
case e_post_synth_netlist_unconn_handling::UNCONNECTED:
|
||||||
|
default:
|
||||||
|
return std::string();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
//Port name
|
//Port name
|
||||||
os << indent(depth) << "." << port_name << "(";
|
os << indent(depth) << "." << port_name << "(";
|
||||||
|
|
||||||
|
@ -2178,60 +2215,58 @@ void print_verilog_port(std::ostream& os, size_t& unconn_count, const std::strin
|
||||||
if (nets[0].empty()) {
|
if (nets[0].empty()) {
|
||||||
//Disconnected
|
//Disconnected
|
||||||
if (type == PortType::INPUT || type == PortType::CLOCK) {
|
if (type == PortType::INPUT || type == PortType::CLOCK) {
|
||||||
switch (opts.post_synth_netlist_unconn_input_handling) {
|
os << unconn_inp_name();
|
||||||
case e_post_synth_netlist_unconn_handling::GND:
|
|
||||||
os << "1'b0";
|
|
||||||
break;
|
|
||||||
case e_post_synth_netlist_unconn_handling::VCC:
|
|
||||||
os << "1'b1";
|
|
||||||
break;
|
|
||||||
case e_post_synth_netlist_unconn_handling::NETS:
|
|
||||||
os << create_unconn_net(unconn_count);
|
|
||||||
break;
|
|
||||||
case e_post_synth_netlist_unconn_handling::UNCONNECTED:
|
|
||||||
default:
|
|
||||||
os << "1'bX";
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
VTR_ASSERT(type == PortType::OUTPUT);
|
VTR_ASSERT(type == PortType::OUTPUT);
|
||||||
switch (opts.post_synth_netlist_unconn_output_handling) {
|
os << unconn_out_name();
|
||||||
case e_post_synth_netlist_unconn_handling::NETS:
|
|
||||||
os << create_unconn_net(unconn_count);
|
|
||||||
break;
|
|
||||||
case e_post_synth_netlist_unconn_handling::UNCONNECTED:
|
|
||||||
default:
|
|
||||||
os << "1'bX";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
//Connected
|
//Connected
|
||||||
os << escape_verilog_identifier(nets[0]);
|
os << escape_verilog_identifier(nets[0]);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
//A multi-bit port, we explicitly concat the single-bit nets to build the port,
|
// Check if all pins are unconnected
|
||||||
//taking care to print MSB on left and LSB on right
|
bool all_unconnected = true;
|
||||||
os << "{"
|
for (size_t i = 0; i < nets.size(); ++i) {
|
||||||
<< "\n";
|
if (!nets[i].empty()) {
|
||||||
for (int ipin = (int)nets.size() - 1; ipin >= 0; --ipin) { //Reverse order to match endianess
|
all_unconnected = false;
|
||||||
os << indent(depth + 1);
|
break;
|
||||||
if (nets[ipin].empty()) {
|
|
||||||
//Disconnected
|
|
||||||
if (type == PortType::INPUT || type == PortType::CLOCK) {
|
|
||||||
os << "1'b0";
|
|
||||||
} else {
|
|
||||||
VTR_ASSERT(type == PortType::OUTPUT);
|
|
||||||
os << "";
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
//Connected
|
|
||||||
os << escape_verilog_identifier(nets[ipin]);
|
|
||||||
}
|
|
||||||
if (ipin != 0) {
|
|
||||||
os << ",";
|
|
||||||
os << "\n";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
os << "}";
|
|
||||||
|
|
||||||
|
//A multi-bit port, we explicitly concat the single-bit nets to build the port,
|
||||||
|
//taking care to print MSB on left and LSB on right
|
||||||
|
if (all_unconnected && type == PortType::OUTPUT && opts.post_synth_netlist_unconn_output_handling == e_post_synth_netlist_unconn_handling::UNCONNECTED) {
|
||||||
|
// Empty connection
|
||||||
|
} else {
|
||||||
|
// Individual bits
|
||||||
|
os << "{"
|
||||||
|
<< "\n";
|
||||||
|
for (int ipin = (int)nets.size() - 1; ipin >= 0; --ipin) { //Reverse order to match endianess
|
||||||
|
os << indent(depth + 1);
|
||||||
|
if (nets[ipin].empty()) {
|
||||||
|
//Disconnected
|
||||||
|
if (type == PortType::INPUT || type == PortType::CLOCK) {
|
||||||
|
os << unconn_inp_name();
|
||||||
|
} else {
|
||||||
|
VTR_ASSERT(type == PortType::OUTPUT);
|
||||||
|
// When concatenating output connection there cannot
|
||||||
|
// be an empty placeholder so we have to create a
|
||||||
|
// dummy net.
|
||||||
|
os << create_unconn_net(unconn_count);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//Connected
|
||||||
|
os << escape_verilog_identifier(nets[ipin]);
|
||||||
|
}
|
||||||
|
if (ipin != 0) {
|
||||||
|
os << ",";
|
||||||
|
}
|
||||||
|
os << "\n";
|
||||||
|
}
|
||||||
|
os << indent(depth) + " }";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
os << ")";
|
os << ")";
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue