developing verilog writer for generic module graph
This commit is contained in:
parent
e5956467fd
commit
f2b3341d87
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
|
|
|
@ -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_;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue