From e82d0d9f340f20feea64c46a393dadf32b3b46e2 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 2 Jul 2020 16:18:32 -0600 Subject: [PATCH] drop id list in bitstream manager to save memory usage --- .../src/bitstream_manager.cpp | 28 +++++--- .../libfpgabitstream/src/bitstream_manager.h | 66 +++++++++++++++++-- 2 files changed, 80 insertions(+), 14 deletions(-) diff --git a/libopenfpga/libfpgabitstream/src/bitstream_manager.cpp b/libopenfpga/libfpgabitstream/src/bitstream_manager.cpp index c08aecb02..bc185a1e0 100644 --- a/libopenfpga/libfpgabitstream/src/bitstream_manager.cpp +++ b/libopenfpga/libfpgabitstream/src/bitstream_manager.cpp @@ -9,17 +9,27 @@ /* begin namespace openfpga */ namespace openfpga { +/************************************************** + * Public Constructors + *************************************************/ +BitstreamManager::BitstreamManager() { + num_blocks_ = 0; + num_bits_ = 0; +} + /************************************************** * Public Accessors : Aggregates *************************************************/ /* Find all the configuration bits */ BitstreamManager::config_bit_range BitstreamManager::bits() const { - return vtr::make_range(bit_ids_.begin(), bit_ids_.end()); + return vtr::make_range(config_bit_iterator(ConfigBitId(0), invalid_bit_ids_), + config_bit_iterator(ConfigBitId(num_bits_), invalid_bit_ids_)); } /* Find all the configuration blocks */ BitstreamManager::config_block_range BitstreamManager::blocks() const { - return vtr::make_range(block_ids_.begin(), block_ids_.end()); + return vtr::make_range(config_block_iterator(ConfigBlockId(0), invalid_block_ids_), + config_block_iterator(ConfigBlockId(num_blocks_), invalid_block_ids_)); } /****************************************************************************** @@ -133,9 +143,9 @@ std::vector BitstreamManager::block_output_net_ids(const ConfigBloc * Public Mutators ******************************************************************************/ ConfigBitId BitstreamManager::add_bit(const bool& bit_value) { - ConfigBitId bit = ConfigBitId(bit_ids_.size()); + ConfigBitId bit = ConfigBitId(num_bits_); /* Add a new bit, and allocate associated data structures */ - bit_ids_.push_back(bit); + num_bits_++; bit_values_.push_back(bit_value); shared_config_bit_values_.emplace_back(); bit_parent_block_ids_.push_back(ConfigBlockId::INVALID()); @@ -144,7 +154,6 @@ ConfigBitId BitstreamManager::add_bit(const bool& bit_value) { } void BitstreamManager::reserve_blocks(const size_t& num_blocks) { - block_ids_.reserve(num_blocks); block_names_.reserve(num_blocks); block_bit_ids_.reserve(num_blocks); block_path_ids_.reserve(num_blocks); @@ -155,16 +164,15 @@ void BitstreamManager::reserve_blocks(const size_t& num_blocks) { } void BitstreamManager::reserve_bits(const size_t& num_bits) { - bit_ids_.reserve(num_bits); bit_values_.reserve(num_bits); shared_config_bit_values_.reserve(num_bits); bit_parent_block_ids_.reserve(num_bits); } ConfigBlockId BitstreamManager::create_block() { - ConfigBlockId block = ConfigBlockId(block_ids_.size()); + ConfigBlockId block = ConfigBlockId(num_blocks_); /* Add a new bit, and allocate associated data structures */ - block_ids_.push_back(block); + num_blocks_++; block_names_.emplace_back(); block_bit_ids_.emplace_back(); block_path_ids_.push_back(-2); @@ -259,11 +267,11 @@ void BitstreamManager::add_shared_config_bit_values(const ConfigBitId& bit, cons * Public Validators ******************************************************************************/ bool BitstreamManager::valid_bit_id(const ConfigBitId& bit_id) const { - return (size_t(bit_id) < bit_ids_.size()) && (bit_id == bit_ids_[bit_id]); + return (size_t(bit_id) < num_bits_); } bool BitstreamManager::valid_block_id(const ConfigBlockId& block_id) const { - return (size_t(block_id) < block_ids_.size()) && (block_id == block_ids_[block_id]); + return (size_t(block_id) < num_blocks_); } bool BitstreamManager::valid_block_path_id(const ConfigBlockId& block_id) const { diff --git a/libopenfpga/libfpgabitstream/src/bitstream_manager.h b/libopenfpga/libfpgabitstream/src/bitstream_manager.h index c3a9372ee..ce741df92 100644 --- a/libopenfpga/libfpgabitstream/src/bitstream_manager.h +++ b/libopenfpga/libfpgabitstream/src/bitstream_manager.h @@ -36,6 +36,8 @@ #include #include +#include +#include #include "vtr_vector.h" #include "bitstream_manager_fwd.h" @@ -44,9 +46,63 @@ namespace openfpga { class BitstreamManager { + 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 lazy_id_iterator : public std::iterator { + 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::value_type value_type; + typedef typename std::iterator::iterator iterator; + + lazy_id_iterator(value_type init, const std::unordered_set& 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 lhs, const lazy_id_iterator rhs) { return lhs.value_ == rhs.value_; } + friend bool operator!=(const lazy_id_iterator lhs, const lazy_id_iterator rhs) { return !(lhs == rhs); } + + private: + value_type value_; + const std::unordered_set& invalid_ids_; + }; + + public: /* Public constructor */ + BitstreamManager(); + public: /* Types and ranges */ - typedef vtr::vector::const_iterator config_bit_iterator; - typedef vtr::vector::const_iterator config_block_iterator; + //Lazy iterator utility forward declaration + template + class lazy_id_iterator; + + typedef lazy_id_iterator config_bit_iterator; + typedef lazy_id_iterator config_block_iterator; typedef vtr::Range config_bit_range; typedef vtr::Range config_block_range; @@ -138,7 +194,8 @@ class BitstreamManager { private: /* Internal data */ /* Unique id of a block of bits in the Bitstream */ - vtr::vector block_ids_; + size_t num_blocks_; + std::unordered_set invalid_block_ids_; vtr::vector> block_bit_ids_; /* Back-annotation for the bits */ @@ -175,7 +232,8 @@ class BitstreamManager { vtr::vector> block_output_net_ids_; /* Unique id of a bit in the Bitstream */ - vtr::vector bit_ids_; + size_t num_bits_; + std::unordered_set invalid_bit_ids_; vtr::vector bit_parent_block_ids_; /* value of a bit in the Bitstream */ vtr::vector bit_values_;