developing verilog writer for generic module graph

This commit is contained in:
tangxifan 2019-10-10 20:09:55 -06:00
parent e5956467fd
commit f2b3341d87
11 changed files with 395 additions and 76 deletions

View File

@ -1,6 +1,8 @@
#include <numeric>
#include <algorithm>
#include <limits>
#include <cassert>
#include "vtr_assert.h"
#include "device_port.h"
@ -63,6 +65,24 @@ std::string BasicPort::get_name() const {
return name_;
}
/* Make a range of the pin indices */
std::vector<size_t> BasicPort::pins() const {
std::vector<size_t> pin_indices;
/* Return if the port is invalid */
if (false == is_valid()) {
return pin_indices; /* Return an empty vector */
}
/* For valid ports, create a vector whose length is the port width */
pin_indices.resize(get_width());
/* Fill in an incremental sequence */
std::iota(pin_indices.begin(), pin_indices.end(), get_lsb());
/* Ensure the last one is MSB */
VTR_ASSERT(get_msb() == pin_indices.back());
return pin_indices;
}
/* Mutators */
/* copy */
void BasicPort::set(const BasicPort& basic_port) {
@ -188,7 +208,7 @@ void BasicPort::reset() {
void BasicPort::combine(const BasicPort& port) {
/* LSB follows the current LSB */
/* MSB increases */
assert( 0 < port.get_width() ); /* Make sure port is valid */
VTR_ASSERT(0 < port.get_width() ); /* Make sure port is valid */
/* If current port is invalid, we do not combine */
if (0 == get_width()) {
return;

View File

@ -6,6 +6,7 @@
#define DEVICE_PORT_H
#include <string>
#include <vector>
/* A basic port */
class BasicPort {
@ -22,6 +23,7 @@ class BasicPort {
size_t get_lsb() const; /* get the LSB */
std::string get_name() const; /* get the name */
bool is_valid() const; /* check if port size is valid > 0 */
std::vector<size_t> pins() const; /* Make a range of the pin indices */
public: /* Mutators */
void set(const BasicPort& basic_port); /* copy */
void set_name(const std::string& name); /* set the port LSB and MSB */

View File

@ -56,6 +56,20 @@ std::vector<size_t> ModuleManager::child_module_instances(const ModuleId& parent
return instance_range;
}
/* Find the source ids of modules */
ModuleManager::module_net_src_range ModuleManager::module_net_sources(const ModuleId& module, const ModuleNetId& net) const {
/* Validate the module_id */
VTR_ASSERT(valid_module_net_id(module, net));
return vtr::make_range(net_src_ids_[module][net].begin(), net_src_ids_[module][net].end());
}
/* Find the sink ids of modules */
ModuleManager::module_net_sink_range ModuleManager::module_net_sinks(const ModuleId& module, const ModuleNetId& net) const {
/* Validate the module_id */
VTR_ASSERT(valid_module_net_id(module, net));
return vtr::make_range(net_sink_ids_[module][net].begin(), net_sink_ids_[module][net].end());
}
/******************************************************************************
* Public Accessors
******************************************************************************/
@ -101,6 +115,24 @@ std::vector<BasicPort> ModuleManager::module_ports_by_type(const ModuleId& modul
return ports;
}
/* Find a list of port ids of a module by a given types */
std::vector<ModulePortId> ModuleManager::module_port_ids_by_type(const ModuleId& module_id, const enum e_module_port_type& port_type) const {
/* Validate the module_id */
VTR_ASSERT(valid_module_id(module_id));
std::vector<ModulePortId> port_ids;
for (const auto& port : port_ids_[module_id]) {
/* Skip unmatched ports */
if (port_type != port_types_[module_id][port]) {
continue;
}
port_ids.push_back(port_ids_[module_id][port]);
}
return port_ids;
}
/* Find a port of a module by a given name */
ModulePortId ModuleManager::find_module_port(const ModuleId& module_id, const std::string& port_name) const {
/* Validate the module id */
@ -207,7 +239,7 @@ std::string ModuleManager::net_name(const ModuleId& module, const ModuleNetId& n
}
/* Find the source modules of a net */
std::vector<ModuleId> ModuleManager::net_source_modules(const ModuleId& module, const ModuleNetId& net) const {
vtr::vector<ModuleNetSrcId, ModuleId> ModuleManager::net_source_modules(const ModuleId& module, const ModuleNetId& net) const {
/* Validate module net */
VTR_ASSERT(valid_module_net_id(module, net));
@ -215,7 +247,7 @@ std::vector<ModuleId> ModuleManager::net_source_modules(const ModuleId& module,
}
/* Find the ids of source instances of a net */
std::vector<size_t> ModuleManager::net_source_instances(const ModuleId& module, const ModuleNetId& net) const {
vtr::vector<ModuleNetSrcId, size_t> ModuleManager::net_source_instances(const ModuleId& module, const ModuleNetId& net) const {
/* Validate module net */
VTR_ASSERT(valid_module_net_id(module, net));
@ -223,7 +255,7 @@ std::vector<size_t> ModuleManager::net_source_instances(const ModuleId& module,
}
/* Find the source ports of a net */
std::vector<ModulePortId> ModuleManager::net_source_ports(const ModuleId& module, const ModuleNetId& net) const {
vtr::vector<ModuleNetSrcId, ModulePortId> ModuleManager::net_source_ports(const ModuleId& module, const ModuleNetId& net) const {
/* Validate module net */
VTR_ASSERT(valid_module_net_id(module, net));
@ -231,7 +263,7 @@ std::vector<ModulePortId> ModuleManager::net_source_ports(const ModuleId& module
}
/* Find the source pin indices of a net */
std::vector<size_t> ModuleManager::net_source_pins(const ModuleId& module, const ModuleNetId& net) const {
vtr::vector<ModuleNetSrcId, size_t> ModuleManager::net_source_pins(const ModuleId& module, const ModuleNetId& net) const {
/* Validate module net */
VTR_ASSERT(valid_module_net_id(module, net));
@ -239,7 +271,7 @@ std::vector<size_t> ModuleManager::net_source_pins(const ModuleId& module, const
}
/* Find the sink modules of a net */
std::vector<ModuleId> ModuleManager::net_sink_modules(const ModuleId& module, const ModuleNetId& net) const {
vtr::vector<ModuleNetSinkId, ModuleId> ModuleManager::net_sink_modules(const ModuleId& module, const ModuleNetId& net) const {
/* Validate module net */
VTR_ASSERT(valid_module_net_id(module, net));
@ -247,7 +279,7 @@ std::vector<ModuleId> ModuleManager::net_sink_modules(const ModuleId& module, co
}
/* Find the ids of sink instances of a net */
std::vector<size_t> ModuleManager::net_sink_instances(const ModuleId& module, const ModuleNetId& net) const {
vtr::vector<ModuleNetSinkId, size_t> ModuleManager::net_sink_instances(const ModuleId& module, const ModuleNetId& net) const {
/* Validate module net */
VTR_ASSERT(valid_module_net_id(module, net));
@ -255,7 +287,7 @@ std::vector<size_t> ModuleManager::net_sink_instances(const ModuleId& module, co
}
/* Find the sink ports of a net */
std::vector<ModulePortId> ModuleManager::net_sink_ports(const ModuleId& module, const ModuleNetId& net) const {
vtr::vector<ModuleNetSinkId, ModulePortId> ModuleManager::net_sink_ports(const ModuleId& module, const ModuleNetId& net) const {
/* Validate module net */
VTR_ASSERT(valid_module_net_id(module, net));
@ -263,7 +295,7 @@ std::vector<ModulePortId> ModuleManager::net_sink_ports(const ModuleId& module,
}
/* Find the sink pin indices of a net */
std::vector<size_t> ModuleManager::net_sink_pins(const ModuleId& module, const ModuleNetId& net) const {
vtr::vector<ModuleNetSinkId, size_t> ModuleManager::net_sink_pins(const ModuleId& module, const ModuleNetId& net) const {
/* Validate module net */
VTR_ASSERT(valid_module_net_id(module, net));
@ -300,11 +332,13 @@ ModuleId ModuleManager::add_module(const std::string& name) {
net_ids_.emplace_back();
net_names_.emplace_back();
net_src_ids_.emplace_back();
net_src_module_ids_.emplace_back();
net_src_instance_ids_.emplace_back();
net_src_port_ids_.emplace_back();
net_src_pin_ids_.emplace_back();
net_sink_ids_.emplace_back();
net_sink_module_ids_.emplace_back();
net_sink_instance_ids_.emplace_back();
net_sink_port_ids_.emplace_back();
@ -426,11 +460,13 @@ ModuleNetId ModuleManager::create_module_net(const ModuleId& module) {
/* Allocate net-related data structures */
net_names_[module].emplace_back();
net_src_ids_[module].emplace_back();
net_src_module_ids_[module].emplace_back();
net_src_instance_ids_[module].emplace_back();
net_src_port_ids_[module].emplace_back();
net_src_pin_ids_[module].emplace_back();
net_sink_ids_[module].emplace_back();
net_sink_module_ids_[module].emplace_back();
net_sink_instance_ids_[module].emplace_back();
net_sink_port_ids_[module].emplace_back();
@ -449,12 +485,16 @@ void ModuleManager::set_net_name(const ModuleId& module, const ModuleNetId& net,
}
/* Add a source to a net in the connection graph */
void ModuleManager::add_module_net_source(const ModuleId& module, const ModuleNetId& net,
const ModuleId& src_module, const size_t& instance_id,
const ModulePortId& src_port, const size_t& src_pin) {
ModuleNetSrcId ModuleManager::add_module_net_source(const ModuleId& module, const ModuleNetId& net,
const ModuleId& src_module, const size_t& instance_id,
const ModulePortId& src_port, const size_t& src_pin) {
/* Validate the module and net id */
VTR_ASSERT(valid_module_net_id(module, net));
/* Create a new id for src node */
ModuleNetSrcId net_src = ModuleNetSrcId(net_src_ids_[module][net].size());
net_src_ids_[module][net].push_back(net_src);
/* Validate the source module */
VTR_ASSERT(valid_module_id(src_module));
net_src_module_ids_[module][net].push_back(src_module);
@ -480,15 +520,21 @@ void ModuleManager::add_module_net_source(const ModuleId& module, const ModuleNe
/* Update fast look-up for nets */
net_lookup_[module][src_module][src_instance_id][src_port][src_pin] = net;
return net_src;
}
/* Add a sink to a net in the connection graph */
void ModuleManager::add_module_net_sink(const ModuleId& module, const ModuleNetId& net,
const ModuleId& sink_module, const size_t& instance_id,
const ModulePortId& sink_port, const size_t& sink_pin) {
ModuleNetSinkId ModuleManager::add_module_net_sink(const ModuleId& module, const ModuleNetId& net,
const ModuleId& sink_module, const size_t& instance_id,
const ModulePortId& sink_port, const size_t& sink_pin) {
/* Validate the module and net id */
VTR_ASSERT(valid_module_net_id(module, net));
/* Create a new id for sink node */
ModuleNetSinkId net_sink = ModuleNetSinkId(net_sink_ids_[module][net].size());
net_sink_ids_[module][net].push_back(net_sink);
/* Validate the source module */
VTR_ASSERT(valid_module_id(sink_module));
net_sink_module_ids_[module][net].push_back(sink_module);
@ -514,6 +560,8 @@ void ModuleManager::add_module_net_sink(const ModuleId& module, const ModuleNetI
/* Update fast look-up for nets */
net_lookup_[module][sink_module][sink_instance_id][sink_port][sink_pin] = net;
return net_sink;
}
/******************************************************************************

View File

@ -38,9 +38,13 @@ class ModuleManager {
public: /* Types and ranges */
typedef vtr::vector<ModuleId, ModuleId>::const_iterator module_iterator;
typedef vtr::vector<ModuleNetId, ModuleNetId>::const_iterator module_net_iterator;
typedef vtr::vector<ModuleNetSrcId, ModuleNetSrcId>::const_iterator module_net_src_iterator;
typedef vtr::vector<ModuleNetSinkId, ModuleNetSinkId>::const_iterator module_net_sink_iterator;
typedef vtr::Range<module_iterator> module_range;
typedef vtr::Range<module_net_iterator> module_net_range;
typedef vtr::Range<module_net_src_iterator> module_net_src_range;
typedef vtr::Range<module_net_sink_iterator> module_net_sink_range;
public: /* Public aggregators */
/* Find all the modules */
@ -51,6 +55,10 @@ class ModuleManager {
std::vector<ModuleId> child_modules(const ModuleId& parent_module) const;
/* Find all the instances under a parent module */
std::vector<size_t> child_module_instances(const ModuleId& parent_module, const ModuleId& child_module) const;
/* Find the source ids of modules */
module_net_src_range module_net_sources(const ModuleId& module, const ModuleNetId& net) const;
/* Find the sink ids of modules */
module_net_sink_range module_net_sinks(const ModuleId& module, const ModuleNetId& net) const;
public: /* Public accessors */
size_t num_modules() const;
@ -58,6 +66,7 @@ class ModuleManager {
std::string module_name(const ModuleId& module_id) const;
std::string module_port_type_str(const enum e_module_port_type& port_type) const;
std::vector<BasicPort> module_ports_by_type(const ModuleId& module_id, const enum e_module_port_type& port_type) const;
std::vector<ModulePortId> module_port_ids_by_type(const ModuleId& module_id, const enum e_module_port_type& port_type) const;
/* Find a port of a module by a given name */
ModulePortId find_module_port(const ModuleId& module_id, const std::string& port_name) const;
/* Find the Port information with a given port id */
@ -79,21 +88,22 @@ class ModuleManager {
/* Find the name of net */
std::string net_name(const ModuleId& module, const ModuleNetId& net) const;
/* Find the source modules of a net */
std::vector<ModuleId> net_source_modules(const ModuleId& module, const ModuleNetId& net) const;
vtr::vector<ModuleNetSrcId, ModuleId> net_source_modules(const ModuleId& module, const ModuleNetId& net) const;
/* Find the ids of source instances of a net */
std::vector<size_t> net_source_instances(const ModuleId& module, const ModuleNetId& net) const;
vtr::vector<ModuleNetSrcId, size_t> net_source_instances(const ModuleId& module, const ModuleNetId& net) const;
/* Find the source ports of a net */
std::vector<ModulePortId> net_source_ports(const ModuleId& module, const ModuleNetId& net) const;
vtr::vector<ModuleNetSrcId, ModulePortId> net_source_ports(const ModuleId& module, const ModuleNetId& net) const;
/* Find the source pin indices of a net */
std::vector<size_t> net_source_pins(const ModuleId& module, const ModuleNetId& net) const;
vtr::vector<ModuleNetSrcId, size_t> net_source_pins(const ModuleId& module, const ModuleNetId& net) const;
/* Find the sink modules of a net */
std::vector<ModuleId> net_sink_modules(const ModuleId& module, const ModuleNetId& net) const;
vtr::vector<ModuleNetSinkId, ModuleId> net_sink_modules(const ModuleId& module, const ModuleNetId& net) const;
/* Find the ids of sink instances of a net */
std::vector<size_t> net_sink_instances(const ModuleId& module, const ModuleNetId& net) const;
vtr::vector<ModuleNetSinkId, size_t> net_sink_instances(const ModuleId& module, const ModuleNetId& net) const;
/* Find the sink ports of a net */
std::vector<ModulePortId> net_sink_ports(const ModuleId& module, const ModuleNetId& net) const;
vtr::vector<ModuleNetSinkId, ModulePortId> net_sink_ports(const ModuleId& module, const ModuleNetId& net) const;
/* Find the sink pin indices of a net */
std::vector<size_t> net_sink_pins(const ModuleId& module, const ModuleNetId& net) const;
vtr::vector<ModuleNetSinkId, size_t> net_sink_pins(const ModuleId& module, const ModuleNetId& net) const;
public: /* Public mutators */
/* Add a module */
ModuleId add_module(const std::string& name);
@ -116,13 +126,13 @@ class ModuleManager {
void set_net_name(const ModuleId& module, const ModuleNetId& net,
const std::string& name);
/* Add a source to a net in the connection graph */
void add_module_net_source(const ModuleId& module, const ModuleNetId& net,
const ModuleId& src_module, const size_t& instance_id,
const ModulePortId& src_port, const size_t& src_pin);
ModuleNetSrcId add_module_net_source(const ModuleId& module, const ModuleNetId& net,
const ModuleId& src_module, const size_t& instance_id,
const ModulePortId& src_port, const size_t& src_pin);
/* Add a sink to a net in the connection graph */
void add_module_net_sink(const ModuleId& module, const ModuleNetId& net,
const ModuleId& sink_module, const size_t& instance_id,
const ModulePortId& sink_port, const size_t& sink_pin);
ModuleNetSinkId add_module_net_sink(const ModuleId& module, const ModuleNetId& net,
const ModuleId& sink_module, const size_t& instance_id,
const ModulePortId& sink_port, const size_t& sink_pin);
public: /* Public validators/invalidators */
bool valid_module_id(const ModuleId& module) const;
bool valid_module_port_id(const ModuleId& module, const ModulePortId& port) const;
@ -154,14 +164,19 @@ class ModuleManager {
*/
vtr::vector<ModuleId, vtr::vector<ModuleNetId, ModuleNetId>> net_ids_; /* List of nets for each Module */
vtr::vector<ModuleId, vtr::vector<ModuleNetId, std::string>> net_names_; /* Name of net */
vtr::vector<ModuleId, vtr::vector<ModuleNetId, std::vector<ModuleId>>> net_src_module_ids_; /* Pin ids that drive the net */
vtr::vector<ModuleId, vtr::vector<ModuleNetId, std::vector<size_t>>> net_src_instance_ids_; /* Pin ids that drive the net */
vtr::vector<ModuleId, vtr::vector<ModuleNetId, std::vector<ModulePortId>>> net_src_port_ids_; /* Pin ids that drive the net */
vtr::vector<ModuleId, vtr::vector<ModuleNetId, std::vector<size_t>>> net_src_pin_ids_; /* Pin ids that drive the net */
vtr::vector<ModuleId, vtr::vector<ModuleNetId, std::vector<ModuleId>>> net_sink_module_ids_; /* Pin ids that the net drives */
vtr::vector<ModuleId, vtr::vector<ModuleNetId, std::vector<size_t>>> net_sink_instance_ids_; /* Pin ids that drive the net */
vtr::vector<ModuleId, vtr::vector<ModuleNetId, std::vector<ModulePortId>>> net_sink_port_ids_; /* Pin ids that drive the net */
vtr::vector<ModuleId, vtr::vector<ModuleNetId, std::vector<size_t>>> net_sink_pin_ids_; /* Pin ids that drive the net */
vtr::vector<ModuleId, vtr::vector<ModuleNetId, vtr::vector<ModuleNetSrcId, ModuleNetSrcId>>> net_src_ids_; /* Unique id of the source that drive the net */
vtr::vector<ModuleId, vtr::vector<ModuleNetId, vtr::vector<ModuleNetSrcId, ModuleId>>> net_src_module_ids_; /* Pin ids that drive the net */
vtr::vector<ModuleId, vtr::vector<ModuleNetId, vtr::vector<ModuleNetSrcId, size_t>>> net_src_instance_ids_; /* Pin ids that drive the net */
vtr::vector<ModuleId, vtr::vector<ModuleNetId, vtr::vector<ModuleNetSrcId, ModulePortId>>> net_src_port_ids_; /* Pin ids that drive the net */
vtr::vector<ModuleId, vtr::vector<ModuleNetId, vtr::vector<ModuleNetSrcId, size_t>>> net_src_pin_ids_; /* Pin ids that drive the net */
vtr::vector<ModuleId, vtr::vector<ModuleNetId, vtr::vector<ModuleNetSinkId, ModuleNetSinkId>>> net_sink_ids_; /* Unique ids of the sink that the net drives */
vtr::vector<ModuleId, vtr::vector<ModuleNetId, vtr::vector<ModuleNetSinkId, ModuleId>>> net_sink_module_ids_; /* Pin ids that the net drives */
vtr::vector<ModuleId, vtr::vector<ModuleNetId, vtr::vector<ModuleNetSinkId, size_t>>> net_sink_instance_ids_; /* Pin ids that drive the net */
vtr::vector<ModuleId, vtr::vector<ModuleNetId, vtr::vector<ModuleNetSinkId, ModulePortId>>> net_sink_port_ids_; /* Pin ids that drive the net */
vtr::vector<ModuleId, vtr::vector<ModuleNetId, vtr::vector<ModuleNetSinkId, size_t>>> net_sink_pin_ids_; /* Pin ids that drive the net */
/* fast look-up for module */
std::map<std::string, ModuleId> name_id_map_;

View File

@ -13,11 +13,15 @@ struct module_id_tag;
struct module_port_id_tag;
struct module_pin_id_tag;
struct module_net_id_tag;
struct module_net_src_id_tag;
struct module_net_sink_id_tag;
typedef vtr::StrongId<module_id_tag> ModuleId;
typedef vtr::StrongId<module_port_id_tag> ModulePortId;
typedef vtr::StrongId<module_pin_id_tag> ModulePinId;
typedef vtr::StrongId<module_net_id_tag> ModuleNetId;
typedef vtr::StrongId<module_net_src_id_tag> ModuleNetSrcId;
typedef vtr::StrongId<module_net_sink_id_tag> ModuleNetSinkId;
class ModuleManager;

View File

@ -260,3 +260,31 @@ void add_pb_type_ports_to_module_manager(ModuleManager& module_manager,
}
}
/********************************************************************
* Identify if a net is a local wire inside a module:
* A net is a local wire if it connects between two instances,
* It means that any of its source and sink modules should not include current module_id
*******************************************************************/
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
*/
for (ModuleId src_module : module_manager.net_source_modules(module_id, module_net)) {
if (module_id == src_module) {
/* Here, this is not a local wire */
return false;
}
}
/* Check all the sink modules of the net */
for (ModuleId sink_module : module_manager.net_sink_modules(module_id, module_net)) {
if (module_id == sink_module) {
/* Here, this is not a local wire */
return false;
}
}
return true;
}

View File

@ -43,5 +43,7 @@ void add_pb_type_ports_to_module_manager(ModuleManager& module_manager,
const ModuleId& module_id,
t_pb_type* cur_pb_type);
#endif
bool module_net_is_local_wire(const ModuleManager& module_manager,
const ModuleId& module_id, const ModuleNetId& module_net);
#endif

View File

@ -9,49 +9,192 @@
*******************************************************************/
#include "vtr_assert.h"
#include "fpga_x2p_utils.h"
#include "module_manager_utils.h"
#include "verilog_writer_utils.h"
#include "verilog_module_writer.h"
/********************************************************************
* Collect all the nets that are going to be local wires
* 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>
* 2. If this is not a local wire, name it after the port name of parent module
*
* In addition, it will assign the pin index as well
*
* Restriction: this function requires each net has single driver
* which is definitely always true in circuits.
*******************************************************************/
static
BasicPort generate_verilog_port_for_module_net(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
*/
for (ModuleNetSrcId src_id : module_manager.module_net_sources(module_id, module_net)) {
if (module_id == module_manager.net_source_modules(module_id, module_net)[src_id]) {
/* 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);
}
}
/* Check all the sink modules of the net */
for (ModuleNetSinkId sink_id : module_manager.module_net_sinks(module_id, module_net)) {
if (module_id == module_manager.net_sink_modules(module_id, module_net)[sink_id]) {
/* 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);
}
}
/* Reach here, this is a local wire */
std::string net_name;
/* Each net must only one 1 source */
VTR_ASSERT(1 == module_manager.net_source_modules(module_id, module_net).size());
/* Get the source module */
ModuleId net_src_module = module_manager.net_source_modules(module_id, module_net)[ModuleNetSrcId(0)];
/* Get the instance id */
size_t net_src_instance = module_manager.net_source_instances(module_id, module_net)[ModuleNetSrcId(0)];
/* Get the port id */
ModulePortId net_src_port = module_manager.net_source_ports(module_id, module_net)[ModuleNetSrcId(0)];
/* Get the pin id */
size_t net_src_pin = module_manager.net_source_pins(module_id, module_net)[ModuleNetSrcId(0)];
net_name = module_manager.module_name(net_src_module);
net_name += std::string("_") + std::to_string(net_src_instance) + std::string("_");
net_name += module_manager.module_port(module_id, net_src_port).get_name();
return BasicPort(net_name, net_src_pin, net_src_pin);
}
/********************************************************************
* Find all the nets that are going to be local wires
* And organize it in a vector of ports
* Verilog wire writter function will use the output of this function
* to write up local wire declaration in Verilog format
*
* Here is the strategy to identify local wires:
* Iterate over the nets inside the module.
* A net is a local wire if it connects between two instances,
* This is valid when all the sinks of the net are pins/ports of instances
*******************************************************************/
static
std::vector<BasicPort> find_verilog_module_local_wires(const ModuleManager& module_manager,
const ModuleId& module_id) {
std::vector<BasicPort> local_wire_ports;
/* Find local wires between instances */
std::vector<BasicPort> local_wires;
/* Local wires come from the child modules */
for (ModuleNetId module_net : module_manager.module_nets(module_id)) {
/* A flag to identify local wire */
bool is_local_wire = false;
/* Each net must only one 1 source */
VTR_ASSERT(1 == module_manager.net_source_modules(module_id, module_net).size());
/* Check if source module is the module itself */
if (module_id != module_manager.net_source_modules(module_id, module_net)[0]) {
is_local_wire = true;
/* We only care local wires */
if (false == module_net_is_local_wire(module_manager, module_id, module_net)) {
continue;
}
/* Check all the sink modules of the net */
for (ModuleId sink_module : module_manager.net_sink_modules(module_id, module_net)) {
if (module_id == sink_module) {
is_local_wire = false;
}
/* Find the name for this local wire */
BasicPort local_wire_candidate = generate_verilog_port_for_module_net(module_manager, module_id, module_net);
/* Try to find a port in the list that can absorb the current local wire */
bool merged = false;
for (BasicPort& local_wire : local_wires) {
/* check if the candidate can be combined to an existing local wire */
if (true == two_verilog_ports_mergeable(local_wire, local_wire_candidate)) {
/* Merge the ports */
local_wire = merge_two_verilog_ports(local_wire, local_wire_candidate);
merged = true;
break;
}
}
/* If not merged, push the port to the list */
if (false == merged) {
local_wires.push_back(local_wire_candidate);
}
/* TODO: Push the Verilog port the list, try to combine the ports if we can */
}
return local_wire_ports;
return local_wires;
}
/********************************************************************
* Write a Verilog instance to a file
* This function will name the input and output connections to
* the inputs/output or local wires available in the parent module
*
* Parent_module
* +-----------------------------+
* | |
* | +--------------+ |
* | | | |
* | | child_module | |
* | | [instance] | |
* | +--------------+ |
* | |
* +-----------------------------+
*
*******************************************************************/
static
void write_verilog_instance_to_file(std::fstream& fp,
const ModuleManager& module_manager,
const ModuleId& parent_module,
const ModuleId& child_module,
const size_t& instance_id,
const bool& use_explicit_port_map) {
/* Ensure a valid file stream */
check_file_handler(fp);
/* Print module name */
fp << "\t" << module_manager.module_name(child_module) << " ";
/* Print instance name, <name>_<num_instance_in_parent_module> */
fp << module_manager.module_name(child_module) << "_" << module_manager.num_instance(parent_module, child_module) << "_" << " (" << std::endl;
/* Print each port with/without explicit port map */
/* port type2type mapping */
std::map<ModuleManager::e_module_port_type, enum e_dump_verilog_port_type> port_type2type_map;
port_type2type_map[ModuleManager::MODULE_GLOBAL_PORT] = VERILOG_PORT_CONKT;
port_type2type_map[ModuleManager::MODULE_INOUT_PORT] = VERILOG_PORT_CONKT;
port_type2type_map[ModuleManager::MODULE_INPUT_PORT] = VERILOG_PORT_CONKT;
port_type2type_map[ModuleManager::MODULE_OUTPUT_PORT] = VERILOG_PORT_CONKT;
port_type2type_map[ModuleManager::MODULE_CLOCK_PORT] = VERILOG_PORT_CONKT;
/* Port sequence: global, inout, input, output and clock ports, */
size_t port_cnt = 0;
for (const auto& kv : port_type2type_map) {
for (const ModulePortId& child_port_id : module_manager.module_port_ids_by_type(child_module, kv.first)) {
BasicPort child_port = module_manager.module_port(child_module, child_port_id);
if (0 != port_cnt) {
/* Do not dump a comma for the first port */
fp << "," << std::endl;
}
/* Print port */
fp << "\t\t";
/* if explicit port map is required, output the port name */
if (true == use_explicit_port_map) {
fp << "." << child_port.get_name() << "(";
}
/* Create the port name and width to be used by the instance */
std::vector<BasicPort> instance_ports;
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,
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);
/* Create the port information for the net */
instance_ports.push_back(instance_port);
}
/* Try to merge the ports */
std::vector<BasicPort> merged_ports = combine_verilog_ports(instance_ports);
/* Print a verilog port by combining the instance ports */
fp << generate_verilog_ports(merged_ports);
/* if explicit port map is required, output the pair of branket */
if (true == use_explicit_port_map) {
fp << ")";
}
port_cnt++;
}
}
/* Print an end to the instance */
fp << ");" << std::endl;
}
/********************************************************************
@ -59,27 +202,46 @@ std::vector<BasicPort> find_verilog_module_local_wires(const ModuleManager& modu
* This is a key function, maybe most frequently called in our Verilog writer
* Note that file stream must be valid
*******************************************************************/
void writer_verilog_module_to_file(std::fstream& fp,
const ModuleManager& module_manager,
const ModuleId& module_id) {
/* Ensure a valid file stream */
check_file_handler(fp);
void write_verilog_module_to_file(std::fstream& fp,
const ModuleManager& module_manager,
const ModuleId& module_id,
const bool& use_explicit_port_map) {
/* Ensure we have a valid module_id */
VTR_ASSERT(module_manager.valid_module_id(module_id));
/* Print module declaration */
print_verilog_module_declaration(fp, module_manager, module_id);
/* Print an empty line as splitter */
fp << std::endl;
/* TODO: 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;
}
/* TODO: Print instances */
/* Print an empty line as splitter */
fp << std::endl;
/* TODO: Print local connection (from module inputs to output! */
/* Print an empty line as splitter */
fp << std::endl;
/* Print instances */
for (ModuleId child_module : module_manager.child_modules(module_id)) {
for (size_t instance : module_manager.child_module_instances(module_id, child_module)) {
/* Print an instance */
write_verilog_instance_to_file(fp, module_manager, module_id, child_module, instance, use_explicit_port_map);
/* Print an empty line as splitter */
fp << std::endl;
}
}
/* Print an end for the module */
print_verilog_module_end(fp, module_manager.module_name(module_id));
/* Print an empty line as splitter */
fp << std::endl;
}

View File

@ -8,8 +8,9 @@
#include <fstream>
#include "module_manager.h"
void writer_verilog_module_to_file(std::fstream& fp,
const ModuleManager& module_manager,
const ModuleId& module_id);
void write_verilog_module_to_file(std::fstream& fp,
const ModuleManager& module_manager,
const ModuleId& module_id,
const bool& use_explicit_port_map);
#endif

View File

@ -406,6 +406,37 @@ std::string generate_verilog_port(const enum e_dump_verilog_port_type& verilog_p
return verilog_line;
}
/********************************************************************
* Evaluate if two Verilog ports can be merged:
* If the port name is same, it can merged
*******************************************************************/
bool two_verilog_ports_mergeable(const BasicPort& portA,
const BasicPort& portB) {
if (0 == portA.get_name().compare(portB.get_name())) {
return true;
}
return false;
}
/********************************************************************
* Merge two Verilog ports, return the merged port
* The ports should have the same name
* The new LSB will be minimum of the LSBs of the two ports
* The new MSB will the maximum of the MSBs of the two ports
*******************************************************************/
BasicPort merge_two_verilog_ports(const BasicPort& portA,
const BasicPort& portB) {
BasicPort merged_port;
VTR_ASSERT(true == two_verilog_ports_mergeable(portA, portB));
merged_port.set_name(portA.get_name());
merged_port.set_lsb((size_t)std::min((int)portA.get_lsb(), (int)portB.get_lsb()));
merged_port.set_msb((size_t)std::max((int)portA.get_msb(), (int)portB.get_msb()));
return merged_port;
}
/************************************************
* This function takes a list of ports and
* combine the port string by comparing the name

View File

@ -53,6 +53,12 @@ void print_verilog_module_end(std::fstream& fp,
std::string generate_verilog_port(const enum e_dump_verilog_port_type& dump_port_type,
const BasicPort& port_info);
bool two_verilog_ports_mergeable(const BasicPort& portA,
const BasicPort& portB);
BasicPort merge_two_verilog_ports(const BasicPort& portA,
const BasicPort& portB);
std::vector<BasicPort> combine_verilog_ports(const std::vector<BasicPort>& ports);
std::string generate_verilog_ports(const std::vector<BasicPort>& merged_ports);