[FPA-Bistream] Updating fabric bitstream writer to organize bitstream for flatten BL/WLs

This commit is contained in:
tangxifan 2021-09-24 18:07:07 -07:00
parent a49e3fe57a
commit 8b72447dad
5 changed files with 148 additions and 2 deletions

View File

@ -80,6 +80,19 @@ std::vector<char> ito1hot_charvec(const size_t& in_int,
return ret;
}
std::string combine_two_1hot_str(const std::string& code1,
const std::string& code2) {
VTR_ASSERT(code1.length() == code2.length());
std::string ret = code1;
for (size_t ichar = 0; ichar < code2.length(); ichar++) {
VTR_ASSERT('0' == code2[ichar] || '1' == code2[ichar]);
if ('1' == code2[ichar]) {
ret[ichar] = code2[ichar];
}
}
return ret;
}
/********************************************************************
* Converter an integer to a binary vector
* For example:

View File

@ -25,6 +25,18 @@ std::vector<size_t> ito1hot_vec(const size_t& in_int,
std::vector<char> ito1hot_charvec(const size_t& in_int,
const size_t& bin_len);
/********************************************************************
* @brief Combine to two 1-hot codes which are in string format
* Any unique '1' will be merged
* For example:
* Code 1: 001000110
* Code 2: 010001001
* Output: 011001111
* @note This function requires two codes in the same length
********************************************************************/
std::string combine_two_1hot_str(const std::string& code1,
const std::string& code2);
std::vector<size_t> itobin_vec(const size_t& in_int,
const size_t& bin_len);

View File

@ -180,6 +180,45 @@ int write_memory_bank_fabric_bitstream_to_text_file(std::fstream& fp,
return status;
}
/********************************************************************
* Write the fabric bitstream fitting a memory bank protocol
* to a plain text file
*
* Return:
* - 0 if succeed
* - 1 if critical errors occured
*******************************************************************/
static
int write_memory_bank_flatten_fabric_bitstream_to_text_file(std::fstream& fp,
const FabricBitstream& fabric_bitstream) {
int status = 0;
MemoryBankFabricBitstream fabric_bits_by_addr = build_memory_bank_fabric_bitstream_by_address(fabric_bitstream);
/* The address sizes and data input sizes are the same across any element,
* just get it from the 1st element to save runtime
*/
size_t bl_addr_size = fabric_bits_by_addr.begin()->first.first.size();
size_t wl_addr_size = fabric_bits_by_addr.begin()->first.second.size();
/* Output information about how to intepret the bitstream */
fp << "// Bitstream length: " << fabric_bits_by_addr.size() << std::endl;
fp << "// Bitstream width (LSB -> MSB): ";
fp << "<bl_address " << bl_addr_size << " bits>";
fp << "<wl_address " << wl_addr_size << " bits>";
fp << std::endl;
for (const auto& addr_din_pair : fabric_bits_by_addr) {
/* Write BL address code */
fp << addr_din_pair.first.first;
/* Write WL address code */
fp << addr_din_pair.first.second;
fp << std::endl;
}
return status;
}
/********************************************************************
* Write the fabric bitstream fitting a frame-based protocol
* to a plain text file
@ -306,7 +345,27 @@ int write_fabric_bitstream_to_text_file(const BitstreamManager& bitstream_manage
bitstream_manager,
fabric_bitstream);
break;
case CONFIG_MEM_QL_MEMORY_BANK:
case CONFIG_MEM_QL_MEMORY_BANK: {
/* Bitstream organization depends on the BL/WL protocols
* - If BL uses decoders, we have to config each memory cell one by one.
* - If BL uses flatten, we can configure all the memory cells on the same row by enabling dedicated WL
* In such case, we will merge the BL data under the same WL address
* Fast configuration is NOT applicable in this case
* - if BL uses shift-register, TODO
*/
if (BLWL_PROTOCOL_DECODER == config_protocol.bl_protocol_type()) {
status = write_memory_bank_fabric_bitstream_to_text_file(fp,
apply_fast_configuration,
bit_value_to_skip,
fabric_bitstream);
} else {
VTR_ASSERT(BLWL_PROTOCOL_DECODER == config_protocol.bl_protocol_type()
|| BLWL_PROTOCOL_SHIFT_REGISTER == config_protocol.bl_protocol_type());
status = write_memory_bank_flatten_fabric_bitstream_to_text_file(fp,
fabric_bitstream);
}
break;
}
case CONFIG_MEM_MEMORY_BANK:
status = write_memory_bank_fabric_bitstream_to_text_file(fp,
apply_fast_configuration,

View File

@ -188,7 +188,7 @@ size_t find_frame_based_fast_configuration_fabric_bitstream_size(const FabricBit
}
/********************************************************************
* Reorganize the fabric bitstream for memory banks
* Reorganize the fabric bitstream for memory banks which use BL and WL decoders
* by the same address across regions:
* This is due to that the length of fabric bitstream could be different in each region.
* Template:
@ -232,6 +232,45 @@ MemoryBankFabricBitstream build_memory_bank_fabric_bitstream_by_address(const Fa
return fabric_bits_by_addr;
}
MemoryBankFlattenFabricBitstream build_memory_bank_flatten_fabric_bitstream(const FabricBitstream& fabric_bitstream) {
/* Build the bitstream by each region, here we use (WL, BL) pairs when storing bitstreams */
vtr::vector<FabricBitRegionId, std::map<std::string, std::string>> fabric_bits_per_region;
fabric_bits_per_region.resize(fabric_bitstream.num_regions());
for (const FabricBitRegionId& region : fabric_bitstream.regions()) {
for (const FabricBitId& bit_id : fabric_bitstream.region_bits(region)) {
/* Create string for BL address */
std::string bl_addr_str;
for (const char& addr_bit : fabric_bitstream.bit_bl_address(bit_id)) {
bl_addr_str.push_back(addr_bit);
}
/* Create string for WL address */
std::string wl_addr_str;
for (const char& addr_bit : fabric_bitstream.bit_wl_address(bit_id)) {
wl_addr_str.push_back(addr_bit);
}
/* Place the config bit */
auto result = fabric_bits_per_region[region].find(wl_addr_str);
if (result == fabric_bits_per_region[region].end()) {
/* This is a new bit, resize the vector to the number of regions
* and deposit '0' to all the bits
*/
fabric_bits_per_region[region][wl_addr_str] = bl_addr_str;
} else {
VTR_ASSERT_SAFE(result != fabric_bits_per_region[region].end());
result->second = combine_two_1hot_str(bl_addr_str, result->second);
}
}
}
/* TODO: Combine the bitstream from different region into a unique one. Now we follow the convention: use (BL, WL) pairs */
MemoryBankFlattenFabricBitstream fabric_bits;
return fabric_bits;
}
/********************************************************************
* For fast configuration, the number of bits to be skipped
* the rule to skip any configuration bit should consider the whole data input values.

View File

@ -37,6 +37,29 @@ FrameFabricBitstream build_frame_based_fabric_bitstream_by_address(const FabricB
size_t find_frame_based_fast_configuration_fabric_bitstream_size(const FabricBitstream& fabric_bitstream,
const bool& bit_value_to_skip);
/********************************************************************
* @ brief Reorganize the fabric bitstream for memory banks which use flatten or shift register to manipulate BL and WLs
* For each configuration region, we will merge BL address (which are 1-hot codes) under the same WL address
*
* Quick Example
* <bl of region A>_<bl of region B> <wl of region A>_<wl of region B>
* An example:
* 010_111 000_101
*
* Note that all the BL/WLs across configuration regions are independent. We will combine them together
* Quick Example
* <bl of region A>_<bl of region B> <wl of region A>_<wl of region B>
* 001_010 000_000
* 100_100 000_000
*
* the bitstream will be merged as
* 101_110 000_000
*
* @note the std::map may cause large memory footprint for large bitstream databases!
*******************************************************************/
typedef std::map<std::vector<std::string>, std::vector<std::string>> MemoryBankFlattenFabricBitstream;
MemoryBankFlattenFabricBitstream build_memory_bank_flatten_fabric_bitstream(const FabricBitstream& fabric_bitstream);
/* Alias to a specific organization of bitstreams for memory bank configuration protocol */
typedef std::map<std::pair<std::string, std::string>, std::vector<bool>> MemoryBankFabricBitstream;
MemoryBankFabricBitstream build_memory_bank_fabric_bitstream_by_address(const FabricBitstream& fabric_bitstream);