OpenFPGA/openfpga/src/fpga_bitstream/fabric_bitstream.cpp

359 lines
12 KiB
C++

/******************************************************************************
* This file includes member functions for data structure FabricBitstream
******************************************************************************/
#include "fabric_bitstream.h"
#include <algorithm>
#include "openfpga_decode.h"
#include "vtr_assert.h"
/* begin namespace openfpga */
namespace openfpga {
/**************************************************
* Public Constructor
*************************************************/
FabricBitstream::FabricBitstream() {
num_bits_ = 0;
invalid_bit_ids_.clear();
address_length_ = 0;
wl_address_length_ = 0;
num_regions_ = 0;
invalid_region_ids_.clear();
use_address_ = false;
use_wl_address_ = false;
}
/**************************************************
* Public Accessors : Aggregates
*************************************************/
size_t FabricBitstream::num_bits() const { return num_bits_; }
/* Find all the configuration bits */
FabricBitstream::fabric_bit_range FabricBitstream::bits() const {
return vtr::make_range(
fabric_bit_iterator(FabricBitId(0), invalid_bit_ids_),
fabric_bit_iterator(FabricBitId(num_bits_), invalid_bit_ids_));
}
size_t FabricBitstream::num_regions() const { return num_regions_; }
/* Find all the configuration bits */
FabricBitstream::fabric_bit_region_range FabricBitstream::regions() const {
return vtr::make_range(
fabric_bit_region_iterator(FabricBitRegionId(0), invalid_region_ids_),
fabric_bit_region_iterator(FabricBitRegionId(num_regions_),
invalid_region_ids_));
}
std::vector<FabricBitId> FabricBitstream::region_bits(
const FabricBitRegionId& region_id) const {
/* Ensure a valid id */
VTR_ASSERT(true == valid_region_id(region_id));
return region_bit_ids_[region_id];
}
/******************************************************************************
* Public Accessors
******************************************************************************/
ConfigBitId FabricBitstream::config_bit(const FabricBitId& bit_id) const {
/* Ensure a valid id */
VTR_ASSERT(true == valid_bit_id(bit_id));
return config_bit_ids_[bit_id];
}
std::vector<char> FabricBitstream::bit_address(
const FabricBitId& bit_id) const {
/* Ensure a valid id */
VTR_ASSERT(true == valid_bit_id(bit_id));
VTR_ASSERT(true == use_address_);
/* Decode address bits */
std::vector<char> addr_bits;
addr_bits.reserve(address_length_);
for (size_t curr_idx = 0; curr_idx < bit_address_1bits_[bit_id].size();
curr_idx++) {
size_t curr_addr_len =
std::min(size_t(64), address_length_ - curr_idx * 64);
std::vector<char> curr_addr_vec =
decode_address_bits(bit_address_1bits_[bit_id][curr_idx],
bit_address_xbits_[bit_id][curr_idx], curr_addr_len);
addr_bits.insert(addr_bits.end(), curr_addr_vec.begin(),
curr_addr_vec.end());
}
return addr_bits;
}
std::vector<char> FabricBitstream::bit_bl_address(
const FabricBitId& bit_id) const {
return bit_address(bit_id);
}
std::vector<char> FabricBitstream::bit_wl_address(
const FabricBitId& bit_id) const {
/* Ensure a valid id */
VTR_ASSERT(true == valid_bit_id(bit_id));
VTR_ASSERT(true == use_address_);
VTR_ASSERT(true == use_wl_address_);
/* Decode address bits */
std::vector<char> addr_bits;
addr_bits.reserve(wl_address_length_);
for (size_t curr_idx = 0; curr_idx < bit_wl_address_1bits_[bit_id].size();
curr_idx++) {
size_t curr_addr_len =
std::min(size_t(64), wl_address_length_ - curr_idx * 64);
std::vector<char> curr_addr_vec = decode_address_bits(
bit_wl_address_1bits_[bit_id][curr_idx],
bit_wl_address_xbits_[bit_id][curr_idx], curr_addr_len);
addr_bits.insert(addr_bits.end(), curr_addr_vec.begin(),
curr_addr_vec.end());
}
return addr_bits;
}
char FabricBitstream::bit_din(const FabricBitId& bit_id) const {
/* Ensure a valid id */
VTR_ASSERT(true == valid_bit_id(bit_id));
VTR_ASSERT(true == use_address_);
return bit_dins_[bit_id];
}
bool FabricBitstream::use_address() const { return use_address_; }
bool FabricBitstream::use_wl_address() const { return use_wl_address_; }
/******************************************************************************
* Public Mutators
******************************************************************************/
void FabricBitstream::reserve_bits(const size_t& num_bits) {
config_bit_ids_.reserve(num_bits);
if (true == use_address_) {
bit_address_1bits_.reserve(num_bits);
bit_address_xbits_.reserve(num_bits);
bit_dins_.reserve(num_bits);
if (true == use_wl_address_) {
bit_wl_address_1bits_.reserve(num_bits);
bit_wl_address_xbits_.reserve(num_bits);
}
}
}
FabricBitId FabricBitstream::add_bit(const ConfigBitId& config_bit_id) {
FabricBitId bit = FabricBitId(num_bits_);
/* Add a new bit, and allocate associated data structures */
num_bits_++;
config_bit_ids_.push_back(config_bit_id);
if (true == use_address_) {
bit_address_1bits_.emplace_back();
bit_address_xbits_.emplace_back();
bit_dins_.emplace_back();
if (true == use_wl_address_) {
bit_wl_address_1bits_.emplace_back();
bit_wl_address_xbits_.emplace_back();
}
}
return bit;
}
void FabricBitstream::set_bit_address(const FabricBitId& bit_id,
const std::vector<char>& address,
const bool& tolerant_short_address) {
VTR_ASSERT(true == valid_bit_id(bit_id));
VTR_ASSERT(true == use_address_);
if (tolerant_short_address) {
VTR_ASSERT(address_length_ >= address.size());
} else {
VTR_ASSERT(address_length_ == address.size());
}
/* Split the address into several 64 vectors */
for (size_t start_idx = 0; start_idx < address.size();
start_idx = start_idx + 64) {
size_t curr_end_idx = std::min(address.size(), start_idx + 64);
std::vector<char> curr_addr_vec64(address.begin() + start_idx,
address.begin() + curr_end_idx);
/* Encode bit '1' and bit 'x' into two numbers */
bit_address_1bits_[bit_id].push_back(encode_address_1bits(curr_addr_vec64));
bit_address_xbits_[bit_id].push_back(encode_address_xbits(curr_addr_vec64));
}
}
void FabricBitstream::set_bit_bl_address(const FabricBitId& bit_id,
const std::vector<char>& address,
const bool& tolerant_short_address) {
set_bit_address(bit_id, address, tolerant_short_address);
}
void FabricBitstream::set_bit_wl_address(const FabricBitId& bit_id,
const std::vector<char>& address,
const bool& tolerant_short_address) {
VTR_ASSERT(true == valid_bit_id(bit_id));
VTR_ASSERT(true == use_address_);
VTR_ASSERT(true == use_wl_address_);
if (tolerant_short_address) {
VTR_ASSERT(wl_address_length_ >= address.size());
} else {
VTR_ASSERT(wl_address_length_ == address.size());
}
/* Split the address into several 64 vectors */
for (size_t start_idx = 0; start_idx < address.size();
start_idx = start_idx + 64) {
size_t curr_end_idx = std::min(address.size(), start_idx + 64);
std::vector<char> curr_addr_vec64(address.begin() + start_idx,
address.begin() + curr_end_idx);
/* Encode bit '1' and bit 'x' into two numbers */
bit_wl_address_1bits_[bit_id].push_back(
encode_address_1bits(curr_addr_vec64));
bit_wl_address_xbits_[bit_id].push_back(
encode_address_xbits(curr_addr_vec64));
}
}
void FabricBitstream::set_bit_din(const FabricBitId& bit_id, const char& din) {
VTR_ASSERT(true == valid_bit_id(bit_id));
VTR_ASSERT(true == use_address_);
bit_dins_[bit_id] = din;
}
void FabricBitstream::set_use_address(const bool& enable) {
/* Add a lock, only can be modified when num bits are zero*/
if (0 == num_bits_) {
use_address_ = enable;
}
}
void FabricBitstream::set_address_length(const size_t& length) {
if (true == use_address_) {
address_length_ = length;
}
}
void FabricBitstream::set_bl_address_length(const size_t& length) {
set_address_length(length);
}
void FabricBitstream::set_use_wl_address(const bool& enable) {
/* Add a lock, only can be modified when num bits are zero*/
if (0 == num_bits_) {
use_wl_address_ = enable;
}
}
void FabricBitstream::set_wl_address_length(const size_t& length) {
if (true == use_address_) {
wl_address_length_ = length;
}
}
void FabricBitstream::reserve_regions(const size_t& num_regions) {
region_bit_ids_.reserve(num_regions);
}
FabricBitRegionId FabricBitstream::add_region() {
FabricBitRegionId region = FabricBitRegionId(num_regions_);
/* Add a new bit, and allocate associated data structures */
num_regions_++;
region_bit_ids_.emplace_back();
return region;
}
void FabricBitstream::add_bit_to_region(const FabricBitRegionId& region_id,
const FabricBitId& bit_id) {
VTR_ASSERT(true == valid_region_id(region_id));
VTR_ASSERT(true == valid_bit_id(bit_id));
region_bit_ids_[region_id].push_back(bit_id);
}
void FabricBitstream::reverse() {
std::reverse(config_bit_ids_.begin(), config_bit_ids_.end());
if (true == use_address_) {
std::reverse(bit_address_1bits_.begin(), bit_address_1bits_.end());
std::reverse(bit_address_xbits_.begin(), bit_address_xbits_.end());
std::reverse(bit_dins_.begin(), bit_dins_.end());
if (true == use_wl_address_) {
std::reverse(bit_wl_address_1bits_.begin(), bit_wl_address_1bits_.end());
std::reverse(bit_wl_address_xbits_.begin(), bit_wl_address_xbits_.end());
}
}
}
void FabricBitstream::reverse_region_bits(const FabricBitRegionId& region_id) {
VTR_ASSERT(true == valid_region_id(region_id));
std::reverse(region_bit_ids_[region_id].begin(),
region_bit_ids_[region_id].end());
}
/******************************************************************************
* Public Validators
******************************************************************************/
bool FabricBitstream::valid_bit_id(const FabricBitId& bit_id) const {
return (size_t(bit_id) < num_bits_);
}
bool FabricBitstream::valid_region_id(
const FabricBitRegionId& region_id) const {
return (size_t(region_id) < num_regions_);
}
uint64_t FabricBitstream::encode_address_1bits(
const std::vector<char>& address) const {
/* Convert all the 'x' bit into 0 */
std::vector<char> binary_address = address;
for (char& bit : binary_address) {
if (bit == 'x') {
bit = '0';
}
}
/* Convert the binary address to a number */
return (uint64_t)bintoi_charvec(binary_address);
}
uint64_t FabricBitstream::encode_address_xbits(
const std::vector<char>& address) const {
/* Convert all the '1' bit into 0 and Convert all the 'x' bit into 1 */
std::vector<char> binary_address = address;
for (char& bit : binary_address) {
if (bit == '1') {
bit = '0';
}
if (bit == 'x') {
bit = '1';
}
}
/* Convert the binary address to a number */
return (uint64_t)bintoi_charvec(binary_address);
}
std::vector<char> FabricBitstream::decode_address_bits(
const size_t& bit1, const size_t& bitx, const size_t& addr_len) const {
/* Decode the bit1 number to a binary vector */
std::vector<char> ret_vec = itobin_charvec(bit1, addr_len);
/* Decode the bitx number to a binary vector */
std::vector<char> bitx_vec = itobin_charvec(bitx, addr_len);
/* Combine the two vectors: 'x' overwrite any bit '0' and '1' */
for (size_t ibit = 0; ibit < ret_vec.size(); ++ibit) {
if (bitx_vec[ibit] == '1') {
ret_vec[ibit] = 'x';
}
}
return ret_vec;
}
} /* end namespace openfpga */