[FPGA-Bitstream] Now encode address bits to save memory in bitstream database

This commit is contained in:
tangxifan 2022-05-25 17:45:08 +08:00
parent bf1a81fbb5
commit ffac5a66e1
2 changed files with 96 additions and 19 deletions

View File

@ -71,7 +71,8 @@ std::vector<char> FabricBitstream::bit_address(const FabricBitId& bit_id) const
VTR_ASSERT(true == valid_bit_id(bit_id));
VTR_ASSERT(true == use_address_);
return bit_addresses_[bit_id];
/* Decode address bits */
return decode_address_bits(bit_address_1bits_[bit_id], bit_address_xbits_[bit_id]);
}
std::vector<char> FabricBitstream::bit_bl_address(const FabricBitId& bit_id) const {
@ -84,7 +85,7 @@ std::vector<char> FabricBitstream::bit_wl_address(const FabricBitId& bit_id) con
VTR_ASSERT(true == use_address_);
VTR_ASSERT(true == use_wl_address_);
return bit_wl_addresses_[bit_id];
return decode_wl_address_bits(bit_wl_address_1bits_[bit_id], bit_wl_address_xbits_[bit_id]);
}
char FabricBitstream::bit_din(const FabricBitId& bit_id) const {
@ -110,11 +111,13 @@ void FabricBitstream::reserve_bits(const size_t& num_bits) {
config_bit_ids_.reserve(num_bits);
if (true == use_address_) {
bit_addresses_.reserve(num_bits);
bit_address_1bits_.reserve(num_bits);
bit_address_xbits_.reserve(num_bits);
bit_dins_.reserve(num_bits);
if (true == use_wl_address_) {
bit_wl_addresses_.reserve(num_bits);
bit_wl_address_1bits_.reserve(num_bits);
bit_wl_address_xbits_.reserve(num_bits);
}
}
}
@ -126,15 +129,16 @@ FabricBitId FabricBitstream::add_bit(const ConfigBitId& config_bit_id) {
config_bit_ids_.push_back(config_bit_id);
if (true == use_address_) {
bit_addresses_.emplace_back();
bit_address_1bits_.emplace_back();
bit_address_xbits_.emplace_back();
bit_dins_.emplace_back();
if (true == use_wl_address_) {
bit_wl_addresses_.emplace_back();
bit_wl_address_1bits_.emplace_back();
bit_wl_address_xbits_.emplace_back();
}
}
return bit;
}
@ -148,7 +152,9 @@ void FabricBitstream::set_bit_address(const FabricBitId& bit_id,
} else {
VTR_ASSERT(address_length_ == address.size());
}
bit_addresses_[bit_id] = address;
/* Encode bit '1' and bit 'x' into two numbers */
bit_address_1bits_[bit_id] = encode_address_1bits(address);
bit_address_xbits_[bit_id] = encode_address_xbits(address);
}
void FabricBitstream::set_bit_bl_address(const FabricBitId& bit_id,
@ -168,7 +174,9 @@ void FabricBitstream::set_bit_wl_address(const FabricBitId& bit_id,
} else {
VTR_ASSERT(wl_address_length_ == address.size());
}
bit_wl_addresses_[bit_id] = address;
/* Encode bit '1' and bit 'x' into two numbers */
bit_wl_address_1bits_[bit_id] = encode_address_1bits(address);
bit_wl_address_xbits_[bit_id] = encode_address_xbits(address);
}
void FabricBitstream::set_bit_din(const FabricBitId& bit_id,
@ -233,11 +241,13 @@ void FabricBitstream::reverse() {
std::reverse(config_bit_ids_.begin(), config_bit_ids_.end());
if (true == use_address_) {
std::reverse(bit_addresses_.begin(), bit_addresses_.end());
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_addresses_.begin(), bit_wl_addresses_.end());
std::reverse(bit_wl_address_1bits_.begin(), bit_wl_address_1bits_.end());
std::reverse(bit_wl_address_xbits_.begin(), bit_wl_address_xbits_.end());
}
}
}
@ -259,4 +269,60 @@ bool FabricBitstream::valid_region_id(const FabricBitRegionId& region_id) const
return (size_t(region_id) < num_regions_);
}
size_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 bintoi_charvec(binary_address);
}
size_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 bintoi_charvec(binary_address);
}
std::vector<char> FabricBitstream::decode_address_bits(const size_t& bit1, const size_t& bitx) const {
/* Decode the bit1 number to a binary vector */
std::vector<char> ret_vec = itobin_charvec(bit1, address_length_);
/* Decode the bitx number to a binary vector */
std::vector<char> bitx_vec = itobin_charvec(bitx, address_length_);
/* 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;
}
std::vector<char> FabricBitstream::decode_wl_address_bits(const size_t& bit1, const size_t& bitx) const {
/* Decode the bit1 number to a binary vector */
std::vector<char> ret_vec = itobin_charvec(bit1, wl_address_length_);
/* Decode the bitx number to a binary vector */
std::vector<char> bitx_vec = itobin_charvec(bitx, wl_address_length_);
/* 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 */

View File

@ -187,6 +187,12 @@ class FabricBitstream {
bool valid_bit_id(const FabricBitId& bit_id) const;
bool valid_region_id(const FabricBitRegionId& bit_id) const;
private: /* Private APIs */
size_t encode_address_1bits(const std::vector<char>& address) const;
size_t encode_address_xbits(const std::vector<char>& address) const;
std::vector<char> decode_address_bits(const size_t& bit1, const size_t& bitx) const;
std::vector<char> decode_wl_address_bits(const size_t& bit1, const size_t& bitx) const;
private: /* Internal data */
/* Unique id of a region in the Bitstream */
size_t num_regions_;
@ -206,17 +212,22 @@ class FabricBitstream {
size_t wl_address_length_;
/* Address bits: this is designed for memory decoders
* Here we store the binary format of the address, which can be loaded
* Here we store the encoded format of the address, and decoded to binary format which can be loaded
* to the configuration protocol directly
*
* We use a 2-element array, as we may have a BL address and a WL address
*
* TODO: use nested vector may cause large memory footprint
* when bitstream size increases
* NEED TO THINK ABOUT A COMPACT MODELING
* Encoding strategy is as follows:
* - An address bit which may contain '0', '1', 'x'. For example
* 101x1
* - The string can be encoded into two integer numbers:
* - bit-one number: which encodes the '0' and '1' bits into a number. For example,
* 101x1 -> 10101 -> 21
* - bit-x number: which encodes the 'x' bits into a number. For example,
* 101x1 -> 00010 -> 2
*/
vtr::vector<FabricBitId, std::vector<char>> bit_addresses_;
vtr::vector<FabricBitId, std::vector<char>> bit_wl_addresses_;
vtr::vector<FabricBitId, size_t> bit_address_1bits_;
vtr::vector<FabricBitId, size_t> bit_address_xbits_;
vtr::vector<FabricBitId, size_t> bit_wl_address_1bits_;
vtr::vector<FabricBitId, size_t> bit_wl_address_xbits_;
/* Data input (Din) bits: this is designed for memory decoders */
vtr::vector<FabricBitId, char> bit_dins_;