add more methods to bitstream manager (renamed from bitstream context)

This commit is contained in:
tangxifan 2019-10-24 15:43:29 -06:00
parent f26dbfe080
commit 13c62fdcf8
5 changed files with 269 additions and 108 deletions

View File

@ -1,46 +0,0 @@
/******************************************************************************
* This file includes member functions for data structure BitstreamContext
******************************************************************************/
#include "vtr_assert.h"
#include "bitstream_context.h"
/**************************************************
* Public Accessors : Aggregates
*************************************************/
/* Find all the configuration bits */
BitstreamContext::config_bit_range BitstreamContext::bits() const {
return vtr::make_range(bit_ids_.begin(), bit_ids_.end());
}
/******************************************************************************
* Public Accessors
******************************************************************************/
bool BitstreamContext::bit_value(const ConfigBitId& bit_id) const {
/* Ensure a valid id */
VTR_ASSERT(true == valid_bit_id(bit_id));
return bit_values_[bit_id];
}
/******************************************************************************
* Public Mutators
******************************************************************************/
ConfigBitId BitstreamContext::add_bit(const bool& bit_value) {
ConfigBitId bit = ConfigBitId(bit_ids_.size());
/* Add a new bit, and allocate associated data structures */
bit_ids_.push_back(bit);
bit_values_.push_back(bit_value);
shared_config_bit_values_.emplace_back();
bit_parent_modules_.emplace_back();
bit_parent_instances_.emplace_back();
return bit;
}
/******************************************************************************
* Public Validators
******************************************************************************/
bool BitstreamContext::valid_bit_id(const ConfigBitId& bit_id) const {
return (size_t(bit_id) < bit_ids_.size()) && (bit_id == bit_ids_[bit_id]);
}

View File

@ -1,58 +0,0 @@
/******************************************************************************
* This file introduces a data structure to store bitstream-related information
******************************************************************************/
#ifndef BITSTREAM_CONTEXT_H
#define BITSTREAM_CONTEXT_H
#include <vector>
#include "vtr_vector.h"
#include "module_manager.h"
#include "bitstream_context_fwd.h"
class BitstreamContext {
public: /* Types and ranges */
typedef vtr::vector<ConfigBitId, ConfigBitId>::const_iterator config_bit_iterator;
typedef vtr::Range<config_bit_iterator> config_bit_range;
public: /* Public aggregators */
/* Find all the configuration bits */
config_bit_range bits() const;
public: /* Public Accessors */
bool bit_value(const ConfigBitId& bit_id) const;
public: /* Public Mutators */
ConfigBitId add_bit(const bool& bit_value);
public: /* Public Validators */
bool valid_bit_id(const ConfigBitId& bit_id) const;
private: /* Internal data */
size_t num_shared_bits_; /* Number of reserved Bit/WL Lines, ONLY applicable to RRAM-based FPGA */
/* Unique id of a bit in the Bitstream */
vtr::vector<ConfigBitId, ConfigBitId> bit_ids_;
/* value of a bit in the Bitstream */
vtr::vector<ConfigBitId, bool> bit_values_;
/* value of a shared configuration bits in the Bitstream */
vtr::vector<ConfigBitId, std::vector<bool>> shared_config_bit_values_;
/* Back-annotation for the bits */
/* Parent Module of a bit in the Bitstream
* For each bit, the list of ModuleId and instance ids reflect its position in the module tree
* The first ModuleId/Instance is the direct parent module/instance of the bit
* while the last ModuleId/instance is the top-level module/instance of the bit
* For example: a bit could be back traced by
* <LastModuleId>[<LastInstanceId>]/.../<FirstModuleId>[<FirstInstanceId>]
*/
vtr::vector<ConfigBitId, std::vector<ModuleId>> bit_parent_modules_;
vtr::vector<ConfigBitId, std::vector<size_t>> bit_parent_instances_;
/* Fast lookup for bitstream */
std::map<std::string, ConfigBitId> bit_lookup_;
};
#endif

View File

@ -0,0 +1,141 @@
/******************************************************************************
* This file includes member functions for data structure BitstreamManager
******************************************************************************/
#include <algorithm>
#include "vtr_assert.h"
#include "bitstream_manager.h"
/**************************************************
* 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());
}
/* Find all the configuration blocks */
BitstreamManager::config_block_range BitstreamManager::blocks() const {
return vtr::make_range(block_ids_.begin(), block_ids_.end());
}
/******************************************************************************
* Public Accessors
******************************************************************************/
bool BitstreamManager::bit_value(const ConfigBitId& bit_id) const {
/* Ensure a valid id */
VTR_ASSERT(true == valid_bit_id(bit_id));
return bit_values_[bit_id];
}
std::string BitstreamManager::block_name(const ConfigBlockId& block_id) const {
/* Ensure the input ids are valid */
VTR_ASSERT(true == valid_block_id(block_id));
return block_names_[block_id];
}
ConfigBlockId BitstreamManager::block_parent(const ConfigBlockId& block_id) const {
/* Ensure the input ids are valid */
VTR_ASSERT(true == valid_block_id(block_id));
return parent_block_ids_[block_id];
}
std::vector<ConfigBlockId> BitstreamManager::block_children(const ConfigBlockId& block_id) const {
/* Ensure the input ids are valid */
VTR_ASSERT(true == valid_block_id(block_id));
return child_block_ids_[block_id];
}
std::vector<ConfigBitId> BitstreamManager::block_bits(const ConfigBlockId& block_id) const {
/* Ensure the input ids are valid */
VTR_ASSERT(true == valid_block_id(block_id));
return block_bit_ids_[block_id];
}
ConfigBlockId BitstreamManager::bit_parent_block(const ConfigBitId& bit_id) const {
/* Ensure the input ids are valid */
VTR_ASSERT(true == valid_bit_id(bit_id));
return bit_parent_block_ids_[bit_id];
}
/******************************************************************************
* Public Mutators
******************************************************************************/
ConfigBitId BitstreamManager::add_bit(const bool& bit_value) {
ConfigBitId bit = ConfigBitId(bit_ids_.size());
/* Add a new bit, and allocate associated data structures */
bit_ids_.push_back(bit);
bit_values_.push_back(bit_value);
shared_config_bit_values_.emplace_back();
bit_parent_block_ids_.push_back(ConfigBlockId::INVALID());
return bit;
}
ConfigBlockId BitstreamManager::add_block(const std::string& block_name) {
ConfigBlockId block = ConfigBlockId(block_ids_.size());
/* Add a new bit, and allocate associated data structures */
block_ids_.push_back(block);
block_names_.push_back(block_name);
block_bit_ids_.emplace_back();
parent_block_ids_.push_back(ConfigBlockId::INVALID());
child_block_ids_.emplace_back();
return block;
}
void BitstreamManager::add_child_block(const ConfigBlockId& parent_block, const ConfigBlockId& child_block) {
/* Ensure the input ids are valid */
VTR_ASSERT(true == valid_block_id(parent_block));
VTR_ASSERT(true == valid_block_id(child_block));
/* We should have only a parent block for each block! */
VTR_ASSERT(ConfigBlockId::INVALID() == parent_block_ids_[child_block]);
/* Ensure the child block is not in the list of children of the parent block */
std::vector<ConfigBlockId>::iterator it = std::find(child_block_ids_[parent_block].begin(), child_block_ids_[parent_block].end(), child_block);
VTR_ASSERT(it == child_block_ids_[parent_block].end());
/* Add the child_block to the parent_block */
child_block_ids_[parent_block].push_back(child_block);
/* Register the block in the parent of the block */
parent_block_ids_[child_block] = parent_block;
}
void BitstreamManager::add_bit_to_block(const ConfigBlockId& block, const ConfigBitId& bit) {
/* Ensure the input ids are valid */
VTR_ASSERT(true == valid_block_id(block));
VTR_ASSERT(true == valid_bit_id(bit));
/* We should have only a parent block for each bit! */
VTR_ASSERT(ConfigBlockId::INVALID() == bit_parent_block_ids_[bit]);
/* Add the bit to the block */
block_bit_ids_[block].push_back(bit);
/* Register the block in the parent of the bit */
bit_parent_block_ids_[bit] = block;
}
void BitstreamManager::add_shared_config_bit_values(const ConfigBitId& bit, const std::vector<bool>& shared_config_bits) {
/* Ensure the input ids are valid */
VTR_ASSERT(true == valid_bit_id(bit));
shared_config_bit_values_[bit] = shared_config_bits;
}
/******************************************************************************
* 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]);
}
bool BitstreamManager::valid_block_id(const ConfigBlockId& block_id) const {
return (size_t(block_id) < block_ids_.size()) && (block_id == block_ids_[block_id]);
}

View File

@ -0,0 +1,122 @@
/******************************************************************************
* This file introduces a data structure to store bitstream-related information
*
* General concept
* ---------------
* The idea is to create a unified data structure that stores all the configuration bits
* with proper annotation to which modules in FPGA fabric it belongs to.
* 1. It can be easily organized in fabric-dependent representation
* (generate a sequence of bitstream which exactly fit the configuration protocol of FPGA fabric)
* 2. Or it can be easily organized in fabric-independent representation (think about XML file)
*
* Cross-reference
* ---------------
* May be used only when you want to bind the bitstream to a specific FPGA fabric!
* If you do so, please make sure the block name is exactly same as the instance name
* of a child module in ModuleManager!!!
* The configurable modules/instances in module manager are arranged
* in the sequence to fit different configuration protocol.
* By using the link between ModuleManager and BitstreamManager,
* we can build a sequence of configuration bits to fit different configuration protocols.
*
* +------------------+ +-----------------+
* | | block_name == instance_name | |
* | BitstreamManager |-------------------------------->| ModuleManager |
* | | | |
* +------------------+ +-----------------+
*
* Restrictions:
* 1. Each block inside BitstreamManager should have only 1 parent block
* and multiple child block
* 2. Each bit inside BitstreamManager should have only 1 parent block
*
******************************************************************************/
#ifndef BITSTREAM_MANAGER_H
#define BITSTREAM_MANAGER_H
#include <vector>
#include "vtr_vector.h"
#include "bitstream_manager_fwd.h"
class BitstreamManager {
public: /* Types and ranges */
typedef vtr::vector<ConfigBitId, ConfigBitId>::const_iterator config_bit_iterator;
typedef vtr::vector<ConfigBlockId, ConfigBlockId>::const_iterator config_block_iterator;
typedef vtr::Range<config_bit_iterator> config_bit_range;
typedef vtr::Range<config_block_iterator> config_block_range;
public: /* Public aggregators */
/* Find all the configuration bits */
config_bit_range bits() const;
config_block_range blocks() const;
public: /* Public Accessors */
/* Find the value of bitstream */
bool bit_value(const ConfigBitId& bit_id) const;
/* Find a name of a block */
std::string block_name(const ConfigBlockId& block_id) const;
/* Find the parent of a block */
ConfigBlockId block_parent(const ConfigBlockId& block_id) const;
/* Find the children of a block */
std::vector<ConfigBlockId> block_children(const ConfigBlockId& block_id) const;
/* Find all the bits that belong to a block */
std::vector<ConfigBitId> block_bits(const ConfigBlockId& block_id) const;
/* Find the parent block of a bit */
ConfigBlockId bit_parent_block(const ConfigBitId& bit_id) const;
public: /* Public Mutators */
/* Add a new configuration bit to the bitstream manager */
ConfigBitId add_bit(const bool& bit_value);
/* Add a new block of configuration bits to the bitstream manager */
ConfigBlockId add_block(const std::string& block_name);
/* Set a block as a child block of another */
void add_child_block(const ConfigBlockId& parent_block, const ConfigBlockId& child_block);
/* Add a configuration bit to a block */
void add_bit_to_block(const ConfigBlockId& block, const ConfigBitId& bit);
/* Add share configuration bits to a configuration bit */
void add_shared_config_bit_values(const ConfigBitId& bit, const std::vector<bool>& shared_config_bits);
public: /* Public Validators */
bool valid_bit_id(const ConfigBitId& bit_id) const;
bool valid_block_id(const ConfigBlockId& block_id) const;
private: /* Internal data */
/* Unique id of a block of bits in the Bitstream */
vtr::vector<ConfigBlockId, ConfigBlockId> block_ids_;
vtr::vector<ConfigBlockId, std::vector<ConfigBitId>> block_bit_ids_;
/* Back-annotation for the bits */
/* Parent block of a bit in the Bitstream
* For each bit, the block name can be designed to be same as the instance name in a module
* to reflect its position in the module tree (ModuleManager)
* Note that the blocks here all unique, unlike ModuleManager where modules can be instanciated
* Therefore, this block graph can be considered as a flattened graph of ModuleGraph
*/
vtr::vector<ConfigBlockId, std::string> block_names_;
vtr::vector<ConfigBlockId, ConfigBlockId> parent_block_ids_;
vtr::vector<ConfigBlockId, std::vector<ConfigBlockId>> child_block_ids_;
/* Unique id of a bit in the Bitstream */
vtr::vector<ConfigBitId, ConfigBitId> bit_ids_;
vtr::vector<ConfigBitId, ConfigBlockId> bit_parent_block_ids_;
/* value of a bit in the Bitstream */
vtr::vector<ConfigBitId, bool> bit_values_;
/* value of a shared configuration bits in the Bitstream */
vtr::vector<ConfigBitId, std::vector<bool>> shared_config_bit_values_;
};
#endif

View File

@ -1,18 +1,20 @@
/**************************************************
* This file includes only declarations for
* the data structures for bitstream database
* Please refer to bitstream_context.h for more details
* Please refer to bitstream_manager.h for more details
*************************************************/
#ifndef BITSTREAM_CONTEXT_FWD_H
#define BITSTREAM_CONTEXT_MANAGER_FWD_H
#ifndef BITSTREAM_MANAGER_FWD_H
#define BITSTREAM_MANAGER_FWD_H
#include "vtr_strong_id.h"
/* Strong Ids for BitstreamContext */
struct config_block_id_tag;
struct config_bit_id_tag;
typedef vtr::StrongId<config_block_id_tag> ConfigBlockId;
typedef vtr::StrongId<config_bit_id_tag> ConfigBitId;
class BitstreamContext;
class BitstreamManager;
#endif