[Tool] Bug fixed for multi-region configuration frame
This commit is contained in:
parent
5bcd559851
commit
b78f8bec16
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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_;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue