optimize memory efficiency for module net id storage

This commit is contained in:
tangxifan 2020-06-30 11:33:06 -06:00
parent 23bcad0678
commit f49cabeeda
2 changed files with 65 additions and 10 deletions

View File

@ -35,7 +35,8 @@ ModuleManager::module_port_range ModuleManager::module_ports(const ModuleId& mod
ModuleManager::module_net_range ModuleManager::module_nets(const ModuleId& module) const { ModuleManager::module_net_range ModuleManager::module_nets(const ModuleId& module) const {
/* Validate the module_id */ /* Validate the module_id */
VTR_ASSERT(valid_module_id(module)); VTR_ASSERT(valid_module_id(module));
return vtr::make_range(net_ids_[module].begin(), net_ids_[module].end()); return vtr::make_range(module_net_iterator(ModuleNetId(0), invalid_net_ids_[module]),
module_net_iterator(ModuleNetId(num_nets_[module]), invalid_net_ids_[module]));
} }
/* Find all the child modules under a parent module */ /* Find all the child modules under a parent module */
@ -108,7 +109,7 @@ size_t ModuleManager::num_modules() const {
size_t ModuleManager::num_nets(const ModuleId& module) const { size_t ModuleManager::num_nets(const ModuleId& module) const {
/* Validate the module_id */ /* Validate the module_id */
VTR_ASSERT(valid_module_id(module)); VTR_ASSERT(valid_module_id(module));
return net_ids_[module].size(); return num_nets_[module];
} }
/* Find the name of a module */ /* Find the name of a module */
@ -458,7 +459,8 @@ ModuleId ModuleManager::add_module(const std::string& name) {
port_is_register_.emplace_back(); port_is_register_.emplace_back();
port_preproc_flags_.emplace_back(); port_preproc_flags_.emplace_back();
net_ids_.emplace_back(); num_nets_.emplace_back(0);
invalid_net_ids_.emplace_back();
net_names_.emplace_back(); net_names_.emplace_back();
net_src_ids_.emplace_back(); net_src_ids_.emplace_back();
net_src_module_ids_.emplace_back(); net_src_module_ids_.emplace_back();
@ -643,8 +645,6 @@ void ModuleManager::reserve_module_nets(const ModuleId& module,
/* Validate the module id */ /* Validate the module id */
VTR_ASSERT ( valid_module_id(module) ); VTR_ASSERT ( valid_module_id(module) );
net_ids_[module].reserve(num_nets);
net_names_[module].reserve(num_nets); net_names_[module].reserve(num_nets);
net_src_ids_[module].reserve(num_nets); net_src_ids_[module].reserve(num_nets);
net_src_module_ids_[module].reserve(num_nets); net_src_module_ids_[module].reserve(num_nets);
@ -665,8 +665,8 @@ ModuleNetId ModuleManager::create_module_net(const ModuleId& module) {
VTR_ASSERT ( valid_module_id(module) ); VTR_ASSERT ( valid_module_id(module) );
/* Create an new id */ /* Create an new id */
ModuleNetId net = ModuleNetId(net_ids_[module].size()); ModuleNetId net = ModuleNetId(num_nets_[module]);
net_ids_[module].push_back(net); num_nets_[module]++;
/* Allocate net-related data structures */ /* Allocate net-related data structures */
net_names_[module].emplace_back(); net_names_[module].emplace_back();
@ -832,7 +832,7 @@ bool ModuleManager::valid_module_net_id(const ModuleId& module, const ModuleNetI
if (false == valid_module_id(module)) { if (false == valid_module_id(module)) {
return false; return false;
} }
return ( size_t(net) < net_ids_[module].size() ) && ( net == net_ids_[module][net] ); return ( size_t(net) < num_nets_[module] );
} }
void ModuleManager::invalidate_name2id_map() { void ModuleManager::invalidate_name2id_map() {

View File

@ -3,6 +3,9 @@
#include <string> #include <string>
#include <map> #include <map>
#include <unordered_set>
#include <unordered_map>
#include "vtr_vector.h" #include "vtr_vector.h"
#include "module_manager_fwd.h" #include "module_manager_fwd.h"
#include "openfpga_port.h" #include "openfpga_port.h"
@ -40,10 +43,61 @@ class ModuleManager {
public: /* Public Constructors */ public: /* Public Constructors */
public: /* Type implementations */
/*
* This class (forward delcared above) is a template used to represent a lazily calculated
* iterator of the specified ID type. The key assumption made is that the ID space is
* contiguous and can be walked by incrementing the underlying ID value. To account for
* invalid IDs, it keeps a reference to the invalid ID set and returns ID::INVALID() for
* ID values in the set.
*
* It is used to lazily create an iteration range (e.g. as returned by RRGraph::edges() RRGraph::nodes())
* just based on the count of allocated elements (i.e. RRGraph::num_nodes_ or RRGraph::num_edges_),
* and the set of any invalid IDs (i.e. RRGraph::invalid_node_ids_, RRGraph::invalid_edge_ids_).
*/
template<class ID>
class lazy_id_iterator : public std::iterator<std::bidirectional_iterator_tag, ID> {
public:
//Since we pass ID as a template to std::iterator we need to use an explicit 'typename'
//to bring the value_type and iterator names into scope
typedef typename std::iterator<std::bidirectional_iterator_tag, ID>::value_type value_type;
typedef typename std::iterator<std::bidirectional_iterator_tag, ID>::iterator iterator;
lazy_id_iterator(value_type init, const std::unordered_set<ID>& invalid_ids)
: value_(init)
, invalid_ids_(invalid_ids) {}
//Advance to the next ID value
iterator operator++() {
value_ = ID(size_t(value_) + 1);
return *this;
}
//Advance to the previous ID value
iterator operator--() {
value_ = ID(size_t(value_) - 1);
return *this;
}
//Dereference the iterator
value_type operator*() const { return (invalid_ids_.count(value_)) ? ID::INVALID() : value_; }
friend bool operator==(const lazy_id_iterator<ID> lhs, const lazy_id_iterator<ID> rhs) { return lhs.value_ == rhs.value_; }
friend bool operator!=(const lazy_id_iterator<ID> lhs, const lazy_id_iterator<ID> rhs) { return !(lhs == rhs); }
private:
value_type value_;
const std::unordered_set<ID>& invalid_ids_;
};
public: /* Types and ranges */ public: /* Types and ranges */
//Lazy iterator utility forward declaration
template<class ID>
class lazy_id_iterator;
typedef vtr::vector<ModuleId, ModuleId>::const_iterator module_iterator; typedef vtr::vector<ModuleId, ModuleId>::const_iterator module_iterator;
typedef vtr::vector<ModulePortId, ModulePortId>::const_iterator module_port_iterator; typedef vtr::vector<ModulePortId, ModulePortId>::const_iterator module_port_iterator;
typedef vtr::vector<ModuleNetId, ModuleNetId>::const_iterator module_net_iterator; typedef lazy_id_iterator<ModuleNetId> module_net_iterator;
typedef vtr::vector<ModuleNetSrcId, ModuleNetSrcId>::const_iterator module_net_src_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::vector<ModuleNetSinkId, ModuleNetSinkId>::const_iterator module_net_sink_iterator;
@ -239,7 +293,8 @@ class ModuleManager {
* To avoid large memory footprint, we do NOT create pins, * To avoid large memory footprint, we do NOT create pins,
* To enable fast look-up on pins, we create a fast look-up * To enable fast look-up on pins, we create a fast look-up
*/ */
vtr::vector<ModuleId, vtr::vector<ModuleNetId, ModuleNetId>> net_ids_; /* List of nets for each Module */ vtr::vector<ModuleId, size_t> num_nets_; /* List of nets for each Module */
vtr::vector<ModuleId, std::unordered_set<ModuleNetId>> invalid_net_ids_; /* Invalid net ids */
vtr::vector<ModuleId, vtr::vector<ModuleNetId, std::string>> net_names_; /* Name of net */ vtr::vector<ModuleId, vtr::vector<ModuleNetId, std::string>> net_names_; /* Name of 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, ModuleNetSrcId>>> net_src_ids_; /* Unique id of the source that drive the net */