From 9693a269eea1ecd4e1a5ab290bbf910360241bd2 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 7 Oct 2021 11:31:16 -0700 Subject: [PATCH] [FPGA-Bitstream] Now dont' care bits are truelly seen in single-chain and flatten QuickLogic memory bank --- .../libopenfpgautil/src/openfpga_decode.cpp | 19 ++++++++++++---- .../libopenfpgautil/src/openfpga_decode.h | 22 ++++++++++++++----- .../build_fabric_bitstream_memory_bank.cpp | 2 +- .../write_text_fabric_bitstream.cpp | 4 ++-- openfpga/src/utils/fabric_bitstream_utils.cpp | 17 +++++++------- 5 files changed, 44 insertions(+), 20 deletions(-) diff --git a/libopenfpga/libopenfpgautil/src/openfpga_decode.cpp b/libopenfpga/libopenfpgautil/src/openfpga_decode.cpp index 2961f423b..bc45e9682 100644 --- a/libopenfpga/libopenfpgautil/src/openfpga_decode.cpp +++ b/libopenfpga/libopenfpgautil/src/openfpga_decode.cpp @@ -65,12 +65,13 @@ std::vector ito1hot_vec(const size_t& in_int, * ********************************************************************/ std::vector ito1hot_charvec(const size_t& in_int, - const size_t& bin_len) { + const size_t& bin_len, + const char& default_bit) { /* Make sure we do not have any overflow! */ VTR_ASSERT ( (in_int <= bin_len) ); /* Initialize */ - std::vector ret(bin_len, '0'); + std::vector ret(bin_len, default_bit); if (bin_len == in_int) { return ret; /* all zero case */ @@ -80,13 +81,23 @@ std::vector ito1hot_charvec(const size_t& in_int, return ret; } +void replace_str_bits(std::string& str_to_convert, + const char& bit_in_place, + const char& bit_to_replace) { + for (char& bit : str_to_convert) { + if (bit_in_place == bit) { + bit = bit_to_replace; + } + } +} + 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]) { + VTR_ASSERT('0' == code2[ichar] || '1' == code2[ichar] || 'x' == code2[ichar]); + if ('1' == code2[ichar] || '0' == code2[ichar]) { ret[ichar] = code2[ichar]; } } diff --git a/libopenfpga/libopenfpgautil/src/openfpga_decode.h b/libopenfpga/libopenfpgautil/src/openfpga_decode.h index 4798af856..92dcf0667 100644 --- a/libopenfpga/libopenfpgautil/src/openfpga_decode.h +++ b/libopenfpga/libopenfpgautil/src/openfpga_decode.h @@ -23,15 +23,27 @@ std::vector ito1hot_vec(const size_t& in_int, const size_t& bin_len); std::vector ito1hot_charvec(const size_t& in_int, - const size_t& bin_len); + const size_t& bin_len, + const char& default_bit = '0'); + +/** @brief Replace the characters in a string with a given replacement + * @param str_to_convert the input and output string + * @param bit_in_place the charater to be replaced + * @param bit_to_replace the charater to replace the bit_in_place + */ +void replace_str_bits(std::string& str_to_convert, + const char& bit_in_place, + const char& bit_to_replace); /******************************************************************** * @brief Combine to two 1-hot codes which are in string format - * Any unique '1' will be merged + * Any unique '1' or '0' will be merged + * @note Where there are both '0' or '1' in the code1 and code2, + * code2 bits will overwrite * For example: - * Code 1: 001000110 - * Code 2: 010001001 - * Output: 011001111 + * Code 1: xx1x0x110 + * Code 2: 01xx01xx1 + * Output: 011x01111 * @note This function requires two codes in the same length ********************************************************************/ std::string combine_two_1hot_str(const std::string& code1, diff --git a/openfpga/src/fpga_bitstream/build_fabric_bitstream_memory_bank.cpp b/openfpga/src/fpga_bitstream/build_fabric_bitstream_memory_bank.cpp index 7742b9bf9..96833b984 100644 --- a/openfpga/src/fpga_bitstream/build_fabric_bitstream_memory_bank.cpp +++ b/openfpga/src/fpga_bitstream/build_fabric_bitstream_memory_bank.cpp @@ -183,7 +183,7 @@ void rec_build_module_fabric_dependent_ql_memory_bank_regional_bitstream(const B bl_addr_bits_vec = itobin_charvec(cur_bl_index, bl_addr_size); } else if (BLWL_PROTOCOL_FLATTEN == config_protocol.bl_protocol_type() || BLWL_PROTOCOL_SHIFT_REGISTER == config_protocol.bl_protocol_type()) { - bl_addr_bits_vec = ito1hot_charvec(cur_bl_index, bl_addr_size); + bl_addr_bits_vec = ito1hot_charvec(cur_bl_index, bl_addr_size, DONT_CARE_CHAR); } /* Find WL address */ diff --git a/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp b/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp index 110cbdb34..51be3783a 100644 --- a/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp @@ -419,8 +419,8 @@ int write_fabric_bitstream_to_text_file(const BitstreamManager& bitstream_manage * - 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 + * Fast configuration is applicable when a row of BLs are all zeros/ones while we have a global reset/set for all the memory cells + * - if BL uses shift-register, same as the flatten. */ if (BLWL_PROTOCOL_DECODER == config_protocol.bl_protocol_type()) { status = write_memory_bank_fabric_bitstream_to_text_file(fp, diff --git a/openfpga/src/utils/fabric_bitstream_utils.cpp b/openfpga/src/utils/fabric_bitstream_utils.cpp index 814666c9b..a4f676b81 100644 --- a/openfpga/src/utils/fabric_bitstream_utils.cpp +++ b/openfpga/src/utils/fabric_bitstream_utils.cpp @@ -236,14 +236,14 @@ MemoryBankFlattenFabricBitstream build_memory_bank_flatten_fabric_bitstream(cons const bool& fast_configuration, const bool& bit_value_to_skip, const char& dont_care_bit) { - /* If fast configuration is not enabled, we need all the wl address even some of them have all-zero BLs */ + /* If fast configuration is not enabled, we need all the wl address even some of them have all-dont-care-bits BLs */ if (!fast_configuration) { vtr::vector> 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(fabric_bitstream.bit_bl_address(bit_id).size(), bit_value_to_skip); + /* Create string for BL address with complete don't care bits */ + std::string bl_addr_str(fabric_bitstream.bit_bl_address(bit_id).size(), dont_care_bit); /* Create string for WL address */ std::string wl_addr_str; @@ -262,16 +262,17 @@ MemoryBankFlattenFabricBitstream build_memory_bank_flatten_fabric_bitstream(cons 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)) { - /* Skip din because they should be pre-configured through programming reset/set */ - if (fabric_bitstream.bit_din(bit_id) == bit_value_to_skip) { - continue; - } /* 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); } + /* If this bit should be programmed to 0, convert the 1s in BL to 0s */ + if (fabric_bitstream.bit_din(bit_id) == bit_value_to_skip) { + replace_str_bits(bl_addr_str, '1', '0'); + } + /* Create string for WL address */ std::string wl_addr_str; for (const char& addr_bit : fabric_bitstream.bit_wl_address(bit_id)) { @@ -284,7 +285,7 @@ MemoryBankFlattenFabricBitstream build_memory_bank_flatten_fabric_bitstream(cons 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); + result->second = combine_two_1hot_str(result->second, bl_addr_str); } } }