[Tool] Bug fixed for multi-region configuration frame

This commit is contained in:
tangxifan 2020-10-30 21:19:20 -06:00
parent 5bcd559851
commit b78f8bec16
7 changed files with 109 additions and 22 deletions

View File

@ -128,4 +128,54 @@ size_t bintoi_charvec(const std::vector<char>& bin) {
return ret;
}
/********************************************************************
* Expand all the don't care bits in a string
* A don't care 'x' can be decoded to either '0' or '1'
* For example:
* input: 0x1x
* output: 0010
* 0100
* 0101
* 0011
*
* Return all the strings
********************************************************************/
std::vector<std::string> expand_dont_care_bin_str(const std::string& input_str) {
std::vector<std::string> ret;
/* If the input is don't care free, we can retrun */
bool has_dont_care = false;
for (const char& bit : input_str) {
if (DONT_CARE_CHAR == bit) {
has_dont_care = true;
break;
}
}
if (false == has_dont_care) {
ret.push_back(input_str);
return ret;
}
/* Recusively expand all the don't bits */
for (size_t i = 0; i < input_str.length(); ++i) {
if (DONT_CARE_CHAR == input_str[i]) {
std::string temp_input_str = input_str;
/* Flip to '0' and go recursively */
temp_input_str[i] = '0';
for (const std::string& expanded_str : expand_dont_care_bin_str(temp_input_str)) {
ret.push_back(expanded_str);
}
/* Flip to '1' and go recursively */
temp_input_str[i] = '1';
for (const std::string& expanded_str : expand_dont_care_bin_str(temp_input_str)) {
ret.push_back(expanded_str);
}
break;
}
}
return ret;
}
} /* end namespace openfpga */

View File

@ -6,6 +6,7 @@
*******************************************************************/
#include <stddef.h>
#include <vector>
#include <string>
/********************************************************************
* Function declaration
@ -13,6 +14,11 @@
/* namespace openfpga begins */
namespace openfpga {
/****************************************
* Constants
*/
constexpr char DONT_CARE_CHAR = 'x';
std::vector<size_t> ito1hot_vec(const size_t& in_int,
const size_t& bin_len);
@ -24,6 +30,8 @@ std::vector<char> itobin_charvec(const size_t& in_int,
size_t bintoi_charvec(const std::vector<char>& bin);
std::vector<std::string> expand_dont_care_bin_str(const std::string& input_str);
} /* namespace openfpga ends */
#endif

View File

@ -285,6 +285,7 @@ void rec_build_module_fabric_dependent_frame_bitstream(const BitstreamManager& b
const ConfigRegionId& config_region,
const std::vector<ModuleId>& parent_modules,
const std::vector<char>& addr_code,
const char& bitstream_dont_care_char,
FabricBitstream& fabric_bitstream,
FabricBitRegionId& fabric_bitstream_region) {
@ -418,7 +419,8 @@ void rec_build_module_fabric_dependent_frame_bitstream(const BitstreamManager& b
const ModulePortId& child_addr_port_id = module_manager.find_module_port(child_module, std::string(DECODER_ADDRESS_PORT_NAME));
const BasicPort& child_addr_port = module_manager.module_port(child_module, child_addr_port_id);
if (0 < max_child_addr_code_size - child_addr_port.get_width()) {
std::vector<char> dummy_codes(max_child_addr_code_size - child_addr_port.get_width(), '0');
/* Deposit don't care state for the dummy bits */
std::vector<char> dummy_codes(max_child_addr_code_size - child_addr_port.get_width(), bitstream_dont_care_char);
child_addr_code.insert(child_addr_code.begin(), dummy_codes.begin(), dummy_codes.end());
}
}
@ -430,6 +432,7 @@ void rec_build_module_fabric_dependent_frame_bitstream(const BitstreamManager& b
config_region,
child_modules,
child_addr_code,
bitstream_dont_care_char,
fabric_bitstream,
fabric_bitstream_region);
}
@ -583,6 +586,12 @@ void build_module_fabric_dependent_bitstream(const ConfigProtocol& config_protoc
fabric_bitstream.reserve_bits(bitstream_manager.num_bits());
fabric_bitstream.set_address_length(addr_port_info.get_width());
/* Avoid use don't care if there is only a region */
char bitstream_dont_care_char = DONT_CARE_CHAR;
if (1 == module_manager.regions(top_module).size()) {
bitstream_dont_care_char = '0';
}
/* Find the maximum decoder address among all the configurable regions */
size_t max_decoder_addr_size = 0;
for (const ConfigRegionId& config_region : module_manager.regions(top_module)) {
@ -624,7 +633,7 @@ void build_module_fabric_dependent_bitstream(const ConfigProtocol& config_protoc
ModulePortId decoder_addr_port_id = module_manager.find_module_port(decoder_module, DECODER_ADDRESS_PORT_NAME);
BasicPort decoder_addr_port = module_manager.module_port(decoder_module, decoder_addr_port_id);
VTR_ASSERT(max_decoder_addr_size >= decoder_addr_port.get_width());
std::vector<char> idle_addr_bits(max_decoder_addr_size - decoder_addr_port.get_width(), '0');
std::vector<char> idle_addr_bits(max_decoder_addr_size - decoder_addr_port.get_width(), bitstream_dont_care_char);
FabricBitRegionId fabric_bitstream_region = fabric_bitstream.add_region();
rec_build_module_fabric_dependent_frame_bitstream(bitstream_manager,
@ -634,6 +643,7 @@ void build_module_fabric_dependent_bitstream(const ConfigProtocol& config_protoc
config_region,
std::vector<ModuleId>(1, top_module),
idle_addr_bits,
bitstream_dont_care_char,
fabric_bitstream,
fabric_bitstream_region);
}

View File

@ -68,7 +68,7 @@ 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 itobin_charvec(bit_addresses_[bit_id], address_length_);
return bit_addresses_[bit_id];
}
std::vector<char> FabricBitstream::bit_bl_address(const FabricBitId& bit_id) const {
@ -81,7 +81,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 itobin_charvec(bit_wl_addresses_[bit_id], wl_address_length_);
return bit_wl_addresses_[bit_id];
}
char FabricBitstream::bit_din(const FabricBitId& bit_id) const {
@ -122,6 +122,16 @@ FabricBitId FabricBitstream::add_bit(const ConfigBitId& config_bit_id) {
num_bits_++;
config_bit_ids_.push_back(config_bit_id);
if (true == use_address_) {
bit_addresses_.emplace_back();
bit_dins_.emplace_back();
if (true == use_wl_address_) {
bit_wl_addresses_.emplace_back();
}
}
return bit;
}
@ -130,7 +140,7 @@ void FabricBitstream::set_bit_address(const FabricBitId& bit_id,
VTR_ASSERT(true == valid_bit_id(bit_id));
VTR_ASSERT(true == use_address_);
VTR_ASSERT(address_length_ == address.size());
bit_addresses_[bit_id] = bintoi_charvec(address);
bit_addresses_[bit_id] = address;
}
void FabricBitstream::set_bit_bl_address(const FabricBitId& bit_id,
@ -144,7 +154,7 @@ void FabricBitstream::set_bit_wl_address(const FabricBitId& bit_id,
VTR_ASSERT(true == use_address_);
VTR_ASSERT(true == use_wl_address_);
VTR_ASSERT(wl_address_length_ == address.size());
bit_wl_addresses_[bit_id] = bintoi_charvec(address);
bit_wl_addresses_[bit_id] = address;
}
void FabricBitstream::set_bit_din(const FabricBitId& bit_id,

View File

@ -208,8 +208,8 @@ class FabricBitstream {
*
* We use a 2-element array, as we may have a BL address and a WL address
*/
vtr::vector<FabricBitId, size_t> bit_addresses_;
vtr::vector<FabricBitId, size_t> bit_wl_addresses_;
vtr::vector<FabricBitId, std::vector<char>> bit_addresses_;
vtr::vector<FabricBitId, std::vector<char>> bit_wl_addresses_;
/* Data input (Din) bits: this is designed for memory decoders */
vtr::vector<FabricBitId, char> bit_dins_;

View File

@ -295,14 +295,17 @@ void print_verilog_arch_decoder_module(std::fstream& fp,
/* Print the truth table of this decoder */
/* Internal logics */
/* Early exit: Corner case for data size = 1 the logic is very simple:
* data = addr;
* data_inv = ~data_inv
* when enable is '1' and and address is '0'
* data_out is driven by '1'
* else data_out is driven by '0'
*/
if (1 == data_size) {
fp << "always@(" << generate_verilog_port(VERILOG_PORT_CONKT, addr_port);
fp << " or " << generate_verilog_port(VERILOG_PORT_CONKT, enable_port);
fp << ") begin" << std::endl;
fp << "\tif (" << generate_verilog_port(VERILOG_PORT_CONKT, enable_port) << " == 1'b1) begin" << std::endl;
fp << "\tif ((" << generate_verilog_port(VERILOG_PORT_CONKT, enable_port) << " == 1'b1) && (";
fp << generate_verilog_port(VERILOG_PORT_CONKT, addr_port) << " == 1'b0))";
fp << " begin" << std::endl;
fp << "\t\t" << generate_verilog_port_constant_values(data_port, std::vector<size_t>(1, 1)) << ";" << std::endl;
fp << "\t" << "end else begin" << std::endl;
fp << "\t\t" << generate_verilog_port_constant_values(data_port, std::vector<size_t>(1, 0)) << ";" << std::endl;

View File

@ -11,6 +11,9 @@
#include "vtr_assert.h"
#include "vtr_log.h"
/* Headers from openfpgautil library */
#include "openfpga_decode.h"
#include "fabric_bitstream_utils.h"
/* begin namespace openfpga */
@ -85,17 +88,20 @@ std::map<std::string, std::vector<bool>> build_frame_based_fabric_bitstream_by_a
addr_str.push_back(addr_bit);
}
/* Place the config bit */
auto result = fabric_bits_by_addr.find(addr_str);
if (result == fabric_bits_by_addr.end()) {
/* This is a new bit, resize the vector to the number of regions
* and deposit '0' to all the bits
*/
fabric_bits_by_addr[addr_str] = std::vector<bool>(fabric_bitstream.regions().size(), false);
fabric_bits_by_addr[addr_str][size_t(region)] = fabric_bitstream.bit_din(bit_id);
} else {
VTR_ASSERT_SAFE(result != fabric_bits_by_addr.end());
result->second[size_t(region)] = fabric_bitstream.bit_din(bit_id);
/* Expand all the don't care bits */
for (const std::string& curr_addr_str : expand_dont_care_bin_str(addr_str)) {
/* Place the config bit */
auto result = fabric_bits_by_addr.find(curr_addr_str);
if (result == fabric_bits_by_addr.end()) {
/* This is a new bit, resize the vector to the number of regions
* and deposit '0' to all the bits
*/
fabric_bits_by_addr[curr_addr_str] = std::vector<bool>(fabric_bitstream.regions().size(), false);
fabric_bits_by_addr[curr_addr_str][size_t(region)] = fabric_bitstream.bit_din(bit_id);
} else {
VTR_ASSERT_SAFE(result != fabric_bits_by_addr.end());
result->second[size_t(region)] = fabric_bitstream.bit_din(bit_id);
}
}
}
}