add local direct connection Verilog code generation

This commit is contained in:
tangxifan 2019-10-10 20:54:31 -06:00
parent f2b3341d87
commit 1f650aac73
3 changed files with 139 additions and 6 deletions

View File

@ -267,7 +267,6 @@ void add_pb_type_ports_to_module_manager(ModuleManager& module_manager,
*******************************************************************/
bool module_net_is_local_wire(const ModuleManager& module_manager,
const ModuleId& module_id, const ModuleNetId& module_net) {
/* A flag to identify local wire */
/* Check all the sink modules of the net,
* if we have a source module is the current module, this is not local wire
*/
@ -288,3 +287,42 @@ bool module_net_is_local_wire(const ModuleManager& module_manager,
return true;
}
/********************************************************************
* Identify if a net is a local short connection inside a module:
* The short connection is defined as the direct connection
* between an input port of the module and an output port of the module
*
* module
* +-----------------------------+
* | |
* inputA--->|---------------------------->|--->outputB
* | |
* | |
* | |
* +-----------------------------+
*******************************************************************/
bool module_net_include_local_short_connection(const ModuleManager& module_manager,
const ModuleId& module_id, const ModuleNetId& module_net) {
/* Check all the sink modules of the net,
* if we have a source module is the current module, this is not local wire
*/
bool contain_module_input = false;
for (ModuleId src_module : module_manager.net_source_modules(module_id, module_net)) {
if (module_id == src_module) {
contain_module_input = true;
break;
}
}
/* Check all the sink modules of the net */
bool contain_module_output = false;
for (ModuleId sink_module : module_manager.net_sink_modules(module_id, module_net)) {
if (module_id == sink_module) {
contain_module_output = true;
break;
}
}
return contain_module_input & contain_module_output;
}

View File

@ -46,4 +46,7 @@ void add_pb_type_ports_to_module_manager(ModuleManager& module_manager,
bool module_net_is_local_wire(const ModuleManager& module_manager,
const ModuleId& module_id, const ModuleNetId& module_net);
bool module_net_include_local_short_connection(const ModuleManager& module_manager,
const ModuleId& module_id, const ModuleNetId& module_net);
#endif

View File

@ -13,6 +13,12 @@
#include "verilog_writer_utils.h"
#include "verilog_module_writer.h"
/********************************************************************
* Local constant variables for naming purpose
instance_port.set_name(VERILOG_MODULE_LOCAL_GND_WIRE_NAME);
*******************************************************************/
constexpr char* VERILOG_MODULE_LOCAL_GND_WIRE_NAME = "VERILOG_CONSTANT_GND";
/********************************************************************
* Name a net for a local wire for a verilog module
* 1. If this is a local wire, name it after the <src_module_name>_<instance_id>_<src_port_name>
@ -110,6 +116,79 @@ std::vector<BasicPort> find_verilog_module_local_wires(const ModuleManager& modu
return local_wires;
}
/********************************************************************
* Print a Verilog wire connection
* We search all the sources of the net,
* if we find a module input, we try to find a module output
* among the sinks of the net
* If we find such a pair, we print a wire connection
*******************************************************************/
static
void print_verilog_module_local_short_connection(std::fstream& fp,
const ModuleManager& module_manager,
const ModuleId& module_id,
const ModuleNetId& module_net) {
/* Ensure a valid file stream */
check_file_handler(fp);
for (ModuleNetSrcId net_src : module_manager.module_net_sources(module_id, module_net)) {
ModuleId src_module = module_manager.net_source_modules(module_id, module_net)[net_src];
if (module_id != src_module) {
continue;
}
/* Find the source port and pin information */
ModulePortId src_port_id = module_manager.net_source_ports(module_id, module_net)[net_src];
size_t src_pin = module_manager.net_source_pins(module_id, module_net)[net_src];
BasicPort src_port(module_manager.module_port(module_id, src_port_id).get_name(), src_pin, src_pin);
/* We have found a module input, now check all the sink modules of the net */
for (ModuleNetSinkId net_sink : module_manager.module_net_sinks(module_id, module_net)) {
ModuleId sink_module = module_manager.net_sink_modules(module_id, module_net)[net_sink];
if (module_id != sink_module) {
continue;
}
/* Find the sink port and pin information */
ModulePortId sink_port_id = module_manager.net_sink_ports(module_id, module_net)[net_sink];
size_t sink_pin = module_manager.net_sink_pins(module_id, module_net)[net_sink];
BasicPort sink_port(module_manager.module_port(module_id, sink_port_id).get_name(), sink_pin, sink_pin);
/* We need to print a wire connection here */
print_verilog_wire_connection(fp, sink_port, src_port, false);
}
}
}
/********************************************************************
* Print short connections inside a Verilog module
* The short connection is defined as the direct connection
* between an input port of the module and an output port of the module
* This type of connection is not covered when printing Verilog instances
* Therefore, they are covered in this function
*
* module
* +-----------------------------+
* | |
* inputA--->|---------------------------->|--->outputB
* | |
* | |
* | |
* +-----------------------------+
*******************************************************************/
static
void print_verilog_module_local_short_connections(std::fstream& fp,
const ModuleManager& module_manager,
const ModuleId& module_id) {
/* Local wires come from the child modules */
for (ModuleNetId module_net : module_manager.module_nets(module_id)) {
/* We only care the nets that indicate short connections */
if (false == module_net_include_local_short_connection(module_manager, module_id, module_net)) {
continue;
}
print_verilog_module_local_short_connection(fp, module_manager, module_id, module_net);
}
}
/********************************************************************
* Write a Verilog instance to a file
* This function will name the input and output connections to
@ -173,8 +252,18 @@ void write_verilog_instance_to_file(std::fstream& fp,
/* Find the net linked to the pin */
ModuleNetId net = module_manager.module_instance_port_net(parent_module, child_module, instance_id,
child_port_id, child_pin);
/* Find the name for this child port */
BasicPort instance_port = generate_verilog_port_for_module_net(module_manager, parent_module, net);
BasicPort instance_port;
if (ModuleNetId::INVALID() == net) {
/* For unused net: assign a constant 0 value
* TODO: make it flexible to select between 0 and 1
*/
/* TODO: output a warning? This could be potential issues for Verilog netlists */
instance_port.set_name(VERILOG_MODULE_LOCAL_GND_WIRE_NAME);
instance_port.set_width(1);
} else {
/* Find the name for this child port */
instance_port = generate_verilog_port_for_module_net(module_manager, parent_module, net);
}
/* Create the port information for the net */
instance_ports.push_back(instance_port);
}
@ -194,7 +283,6 @@ void write_verilog_instance_to_file(std::fstream& fp,
/* Print an end to the instance */
fp << ");" << std::endl;
}
/********************************************************************
@ -215,7 +303,10 @@ void write_verilog_module_to_file(std::fstream& fp,
/* Print an empty line as splitter */
fp << std::endl;
/* TODO: Print internal wires */
/* Print constant GND wires */
BasicPort constant_gnd_local_wire(VERILOG_MODULE_LOCAL_GND_WIRE_NAME, 1);
fp << generate_verilog_port(VERILOG_PORT_WIRE, constant_gnd_local_wire) << ";" << std::endl;
/* Print internal wires */
std::vector<BasicPort> local_wires = find_verilog_module_local_wires(module_manager, module_id);
for (BasicPort local_wire : local_wires) {
fp << generate_verilog_port(VERILOG_PORT_WIRE, local_wire) << ";" << std::endl;
@ -224,7 +315,8 @@ void write_verilog_module_to_file(std::fstream& fp,
/* Print an empty line as splitter */
fp << std::endl;
/* TODO: Print local connection (from module inputs to output! */
/* Print local connection (from module inputs to output! */
print_verilog_module_local_short_connections(fp, module_manager, module_id);
/* Print an empty line as splitter */
fp << std::endl;