[Tool] Bug fix for printing single-bit ports in Verilog netlists
This commit is contained in:
parent
9f4d05da67
commit
73461971d2
|
@ -22,27 +22,33 @@ BasicPort::BasicPort() {
|
|||
/* By default we set an invalid port, which size is 0 */
|
||||
lsb_ = 1;
|
||||
msb_ = 0;
|
||||
|
||||
origin_port_width_ = -1;
|
||||
}
|
||||
|
||||
/* Quick constructor */
|
||||
BasicPort::BasicPort(const char* name, const size_t& lsb, const size_t& msb) {
|
||||
set_name(std::string(name));
|
||||
set_width(lsb, msb);
|
||||
set_origin_port_width(-1);
|
||||
}
|
||||
|
||||
BasicPort::BasicPort(const std::string& name, const size_t& lsb, const size_t& msb) {
|
||||
set_name(name);
|
||||
set_width(lsb, msb);
|
||||
set_origin_port_width(-1);
|
||||
}
|
||||
|
||||
BasicPort::BasicPort(const char* name, const size_t& width) {
|
||||
set_name(std::string(name));
|
||||
set_width(width);
|
||||
set_origin_port_width(-1);
|
||||
}
|
||||
|
||||
BasicPort::BasicPort(const std::string& name, const size_t& width) {
|
||||
set_name(name);
|
||||
set_width(width);
|
||||
set_origin_port_width(-1);
|
||||
}
|
||||
|
||||
/* Copy constructor */
|
||||
|
@ -107,6 +113,11 @@ bool BasicPort::contained(const BasicPort& portA) const {
|
|||
return ( lsb_ <= portA.get_lsb() && portA.get_msb() <= msb_ );
|
||||
}
|
||||
|
||||
/* Set original port width */
|
||||
size_t BasicPort::get_origin_port_width() const {
|
||||
return origin_port_width_;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* Overloaded operators
|
||||
***********************************************************************/
|
||||
|
@ -142,6 +153,7 @@ void BasicPort::set(const BasicPort& basic_port) {
|
|||
name_ = basic_port.get_name();
|
||||
lsb_ = basic_port.get_lsb();
|
||||
msb_ = basic_port.get_msb();
|
||||
origin_port_width_ = basic_port.get_origin_port_width();
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -185,6 +197,11 @@ void BasicPort::set_msb(const size_t& msb) {
|
|||
return;
|
||||
}
|
||||
|
||||
void BasicPort::set_origin_port_width(const size_t& origin_port_width) {
|
||||
origin_port_width_ = origin_port_width;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Increase the port width */
|
||||
void BasicPort::expand(const size_t& width) {
|
||||
if (0 == width) {
|
||||
|
@ -291,6 +308,8 @@ void BasicPort::merge(const BasicPort& portA) {
|
|||
lsb_ = std::min((int)lsb_, (int)portA.get_lsb());
|
||||
/* MSB follows the minium MSB of the two ports */
|
||||
msb_ = std::max((int)msb_, (int)portA.get_msb());
|
||||
/* Origin port width follows the maximum of the two ports */
|
||||
msb_ = std::max((int)origin_port_width_, (int)portA.get_origin_port_width());
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@ class BasicPort {
|
|||
std::vector<size_t> pins() const; /* Make a range of the pin indices */
|
||||
bool mergeable(const BasicPort& portA) const; /* Check if a port can be merged with this port */
|
||||
bool contained(const BasicPort& portA) const; /* Check if a port is contained by this port */
|
||||
size_t get_origin_port_width() const;
|
||||
public: /* Mutators */
|
||||
void set(const BasicPort& basic_port); /* copy */
|
||||
void set_name(const std::string& name); /* set the port LSB and MSB */
|
||||
|
@ -45,12 +46,14 @@ class BasicPort {
|
|||
void reset(); /* Reset to initial port */
|
||||
void combine(const BasicPort& port); /* Combine two ports */
|
||||
void merge(const BasicPort& portA);
|
||||
void set_origin_port_width(const size_t& origin_port_width);
|
||||
private: /* internal functions */
|
||||
void make_invalid(); /* Make a port invalid */
|
||||
private: /* Internal Data */
|
||||
std::string name_; /* Name of this port */
|
||||
size_t msb_; /* Most Significant Bit of this port */
|
||||
size_t lsb_; /* Least Significant Bit of this port */
|
||||
size_t origin_port_width_; /* Original port width of a port, used by traceback port conversion history */
|
||||
};
|
||||
|
||||
/* Configuration ports:
|
||||
|
|
|
@ -59,6 +59,9 @@ void print_verilog_top_random_testbench_ports(std::fstream& fp,
|
|||
/* Validate the file stream */
|
||||
valid_file_stream(fp);
|
||||
|
||||
print_verilog_default_net_type_declaration(fp,
|
||||
VERILOG_DEFAULT_NET_TYPE_NONE);
|
||||
|
||||
/* Print the declaration for the module */
|
||||
fp << "module " << circuit_name << FORMAL_RANDOM_TOP_TESTBENCH_POSTFIX << ";" << std::endl;
|
||||
|
||||
|
|
|
@ -65,6 +65,7 @@ static
|
|||
BasicPort generate_verilog_port_for_module_net(const ModuleManager& module_manager,
|
||||
const ModuleId& module_id,
|
||||
const ModuleNetId& module_net) {
|
||||
BasicPort port_to_return;
|
||||
/* Check all the sink modules of the net,
|
||||
* if we have a source module is the current module, this is not local wire
|
||||
*/
|
||||
|
@ -73,7 +74,10 @@ BasicPort generate_verilog_port_for_module_net(const ModuleManager& module_manag
|
|||
/* Here, this is not a local wire, return the port name of the src_port */
|
||||
ModulePortId net_src_port = module_manager.net_source_ports(module_id, module_net)[src_id];
|
||||
size_t src_pin_index = module_manager.net_source_pins(module_id, module_net)[src_id];
|
||||
return BasicPort(module_manager.module_port(module_id, net_src_port).get_name(), src_pin_index, src_pin_index);
|
||||
port_to_return.set(module_manager.module_port(module_id, net_src_port));
|
||||
port_to_return.set_width(src_pin_index, src_pin_index);
|
||||
port_to_return.set_origin_port_width(module_manager.module_port(module_id, net_src_port).get_width());
|
||||
return port_to_return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -83,7 +87,10 @@ BasicPort generate_verilog_port_for_module_net(const ModuleManager& module_manag
|
|||
/* Here, this is not a local wire, return the port name of the sink_port */
|
||||
ModulePortId net_sink_port = module_manager.net_sink_ports(module_id, module_net)[sink_id];
|
||||
size_t sink_pin_index = module_manager.net_sink_pins(module_id, module_net)[sink_id];
|
||||
return BasicPort(module_manager.module_port(module_id, net_sink_port).get_name(), sink_pin_index, sink_pin_index);
|
||||
port_to_return.set(module_manager.module_port(module_id, net_sink_port));
|
||||
port_to_return.set_width(sink_pin_index, sink_pin_index);
|
||||
port_to_return.set_origin_port_width(module_manager.module_port(module_id, net_sink_port).get_width());
|
||||
return port_to_return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -111,7 +118,10 @@ BasicPort generate_verilog_port_for_module_net(const ModuleManager& module_manag
|
|||
net_name += module_manager.module_port(net_src_module, net_src_port).get_name();
|
||||
}
|
||||
|
||||
return BasicPort(net_name, net_src_pin, net_src_pin);
|
||||
port_to_return.set_name(net_name);
|
||||
port_to_return.set_width(net_src_pin, net_src_pin);
|
||||
port_to_return.set_origin_port_width(module_manager.module_port(net_src_module, net_src_port).get_width());
|
||||
return port_to_return;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
|
@ -422,6 +432,7 @@ void write_verilog_instance_to_file(std::fstream& fp,
|
|||
|
||||
/* Create the port name and width to be used by the instance */
|
||||
std::vector<BasicPort> instance_ports;
|
||||
std::vector<bool> instance_ports_is_single_bit;
|
||||
for (size_t child_pin : child_port.pins()) {
|
||||
/* Find the net linked to the pin */
|
||||
ModuleNetId net = module_manager.module_instance_port_net(parent_module, child_module, instance_id,
|
||||
|
@ -431,6 +442,7 @@ void write_verilog_instance_to_file(std::fstream& fp,
|
|||
/* We give the same port name as child module, this case happens to global ports */
|
||||
instance_port.set_name(generate_verilog_undriven_local_wire_name(module_manager, parent_module, child_module, instance_id, child_port_id));
|
||||
instance_port.set_width(child_pin, child_pin);
|
||||
instance_port.set_origin_port_width(module_manager.module_port(child_module, child_port_id).get_width());
|
||||
} else {
|
||||
/* Find the name for this child port */
|
||||
instance_port = generate_verilog_port_for_module_net(module_manager, parent_module, net);
|
||||
|
@ -478,13 +490,17 @@ void write_verilog_module_to_file(std::fstream& fp,
|
|||
/* Print an empty line as splitter */
|
||||
fp << std::endl;
|
||||
|
||||
/* Print internal wires only when default net type is NOT wire */
|
||||
if (VERILOG_DEFAULT_NET_TYPE_WIRE != default_net_type) {
|
||||
/* Print internal wires */
|
||||
std::map<std::string, std::vector<BasicPort>> local_wires = find_verilog_module_local_wires(module_manager, module_id);
|
||||
for (std::pair<std::string, std::vector<BasicPort>> port_group : local_wires) {
|
||||
for (const BasicPort& local_wire : port_group.second) {
|
||||
fp << generate_verilog_port(VERILOG_PORT_WIRE, local_wire) << ";" << std::endl;
|
||||
/* When default net type is wire, we can skip single-bit wires whose LSB is 0 */
|
||||
if ( (VERILOG_DEFAULT_NET_TYPE_WIRE == default_net_type)
|
||||
&& (1 == local_wire.get_width())
|
||||
&& (0 == local_wire.get_lsb())) {
|
||||
continue;
|
||||
}
|
||||
fp << generate_verilog_port(VERILOG_PORT_WIRE, local_wire) << ";" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -448,6 +448,9 @@ int print_verilog_preconfig_top_module(const ModuleManager &module_manager,
|
|||
std::string title = std::string("Verilog netlist for pre-configured FPGA fabric by design: ") + circuit_name;
|
||||
print_verilog_file_header(fp, title);
|
||||
|
||||
print_verilog_default_net_type_declaration(fp,
|
||||
VERILOG_DEFAULT_NET_TYPE_NONE);
|
||||
|
||||
/* Print module declaration and ports */
|
||||
print_verilog_preconfig_top_module_ports(fp, circuit_name, atom_ctx, netlist_annotation);
|
||||
|
||||
|
|
|
@ -823,9 +823,10 @@ void rec_print_verilog_testbench_primitive_module_signal_initialization(std::fst
|
|||
/* Only for formal verification: deposite a zero signal values */
|
||||
/* Initialize each input port */
|
||||
BasicPort input_port_info(circuit_lib.port_lib_name(input_port), circuit_lib.port_size(input_port));
|
||||
input_port_info.set_origin_port_width(input_port_info.get_width());
|
||||
fp << "\t\t$deposit(";
|
||||
fp << child_hie_path << ".";
|
||||
fp << generate_verilog_port(VERILOG_PORT_CONKT, input_port_info);
|
||||
fp << generate_verilog_port(VERILOG_PORT_CONKT, input_port_info, false);
|
||||
fp << ", " << circuit_lib.port_size(input_port) << "'b" << std::string(circuit_lib.port_size(input_port), '0');
|
||||
fp << ");" << std::endl;
|
||||
}
|
||||
|
@ -834,9 +835,10 @@ void rec_print_verilog_testbench_primitive_module_signal_initialization(std::fst
|
|||
/* Regular case: deposite initial signal values: a random value */
|
||||
for (const auto& input_port : circuit_input_ports) {
|
||||
BasicPort input_port_info(circuit_lib.port_lib_name(input_port), circuit_lib.port_size(input_port));
|
||||
input_port_info.set_origin_port_width(input_port_info.get_width());
|
||||
fp << "\t\t$deposit(";
|
||||
fp << child_hie_path << ".";
|
||||
fp << generate_verilog_port(VERILOG_PORT_CONKT, input_port_info);
|
||||
fp << generate_verilog_port(VERILOG_PORT_CONKT, input_port_info, false);
|
||||
fp << ", $random % 2 ? 1'b1 : 1'b0);" << std::endl;
|
||||
}
|
||||
|
||||
|
|
|
@ -578,6 +578,9 @@ void print_verilog_top_testbench_ports(std::fstream& fp,
|
|||
/* Validate the file stream */
|
||||
valid_file_stream(fp);
|
||||
|
||||
print_verilog_default_net_type_declaration(fp,
|
||||
VERILOG_DEFAULT_NET_TYPE_NONE);
|
||||
|
||||
/* Print module definition */
|
||||
fp << "module " << circuit_name << std::string(AUTOCHECK_TOP_TESTBENCH_VERILOG_MODULE_POSTFIX);
|
||||
fp << ";" << std::endl;
|
||||
|
|
|
@ -460,7 +460,8 @@ void print_verilog_module_end(std::fstream& fp,
|
|||
* Generate a string of a Verilog port
|
||||
***********************************************/
|
||||
std::string generate_verilog_port(const enum e_dump_verilog_port_type& verilog_port_type,
|
||||
const BasicPort& port_info) {
|
||||
const BasicPort& port_info,
|
||||
const bool& must_print_port_size) {
|
||||
std::string verilog_line;
|
||||
|
||||
/* Ensure the port type is valid */
|
||||
|
@ -472,8 +473,22 @@ std::string generate_verilog_port(const enum e_dump_verilog_port_type& verilog_p
|
|||
* others require a format of <port_type> [<lsb>:<msb>] <port_name>
|
||||
*/
|
||||
if (VERILOG_PORT_CONKT == verilog_port_type) {
|
||||
/* When LSB == MSB, we can use a simplified format <port_type>[<lsb>]*/
|
||||
if ( 1 == port_info.get_width()) {
|
||||
/* Simplication:
|
||||
* - When LSB == MSB == 0, we do not need to specify size when the user option allows
|
||||
* Note that user option is essential, otherwise what could happen is that
|
||||
* a multi-bit verilog port used in instance port mapping is printed as a single-bit net
|
||||
* For example,
|
||||
* input [1:0] in;
|
||||
* inv inv_inst (.A(in), .Y(out));
|
||||
* The original port width is the reference to backtrace the defintion of the port
|
||||
* - When LSB == MSB, we can use a simplified format <port_type>[<lsb>]
|
||||
*/
|
||||
if ((false == must_print_port_size)
|
||||
&& (1 == port_info.get_width())
|
||||
&& (0 == port_info.get_lsb())
|
||||
&& (1 == port_info.get_origin_port_width())) {
|
||||
size_str.clear();
|
||||
} else if ((1 == port_info.get_width()) && (0 != port_info.get_lsb())) {
|
||||
size_str = "[" + std::to_string(port_info.get_lsb()) + "]";
|
||||
}
|
||||
verilog_line = port_info.get_name() + size_str;
|
||||
|
@ -582,7 +597,7 @@ std::string generate_verilog_ports(const std::vector<BasicPort>& merged_ports) {
|
|||
VTR_ASSERT(0 < merged_ports.size());
|
||||
if ( 1 == merged_ports.size()) {
|
||||
/* Use connection type of verilog port */
|
||||
return generate_verilog_port(VERILOG_PORT_CONKT, merged_ports[0]);
|
||||
return generate_verilog_port(VERILOG_PORT_CONKT, merged_ports[0], false);
|
||||
}
|
||||
|
||||
std::string verilog_line = "{";
|
||||
|
@ -591,7 +606,7 @@ std::string generate_verilog_ports(const std::vector<BasicPort>& merged_ports) {
|
|||
if (&port != &merged_ports[0]) {
|
||||
verilog_line += ", ";
|
||||
}
|
||||
verilog_line += generate_verilog_port(VERILOG_PORT_CONKT, port);
|
||||
verilog_line += generate_verilog_port(VERILOG_PORT_CONKT, port, false);
|
||||
}
|
||||
verilog_line += "}";
|
||||
|
||||
|
|
|
@ -85,7 +85,8 @@ void print_verilog_module_end(std::fstream& fp,
|
|||
const std::string& module_name);
|
||||
|
||||
std::string generate_verilog_port(const enum e_dump_verilog_port_type& dump_port_type,
|
||||
const BasicPort& port_info);
|
||||
const BasicPort& port_info,
|
||||
const bool& must_print_port_size = true);
|
||||
|
||||
bool two_verilog_ports_mergeable(const BasicPort& portA,
|
||||
const BasicPort& portB);
|
||||
|
|
Loading…
Reference in New Issue