[FPGA-Bitstream] Upgraded bitstream writer to support QuickLogic memory bank using shift registers
This commit is contained in:
parent
4526133089
commit
33972fc0ec
|
@ -1323,13 +1323,19 @@ void add_top_module_nets_cmos_ql_memory_bank_bl_shift_register_config_bus(Module
|
|||
|
||||
for (size_t child_id = 0; child_id < module_manager.region_configurable_children(top_module, config_region).size(); ++child_id) {
|
||||
ModuleId child_module = module_manager.region_configurable_children(top_module, config_region)[child_id];
|
||||
vtr::Point<int> coord = module_manager.region_configurable_child_coordinates(top_module, config_region)[child_id];
|
||||
|
||||
/* Find the BL port */
|
||||
ModulePortId child_bl_port = module_manager.find_module_port(child_module, std::string(MEMORY_BL_PORT_NAME));
|
||||
BasicPort child_bl_port_info = module_manager.module_port(child_module, child_bl_port);
|
||||
|
||||
size_t cur_bl_index = 0;
|
||||
|
||||
for (const size_t& sink_bl_pin : child_bl_port_info.pins()) {
|
||||
size_t bl_pin_id = bl_start_index_per_tile[coord.x()] + cur_bl_index;
|
||||
|
||||
sr_banks.add_shift_register_sink_nodes(config_region, sr_bank_module, cur_inst, child_id, sink_bl_pin);
|
||||
sr_banks.add_shift_register_sink_blwls(config_region, sr_bank_module, cur_inst, bl_pin_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1409,13 +1415,18 @@ void add_top_module_nets_cmos_ql_memory_bank_wl_shift_register_config_bus(Module
|
|||
|
||||
for (size_t child_id = 0; child_id < module_manager.region_configurable_children(top_module, config_region).size(); ++child_id) {
|
||||
ModuleId child_module = module_manager.region_configurable_children(top_module, config_region)[child_id];
|
||||
vtr::Point<int> coord = module_manager.region_configurable_child_coordinates(top_module, config_region)[child_id];
|
||||
|
||||
/* Find the BL port */
|
||||
size_t cur_wl_index = 0;
|
||||
|
||||
/* Find the WL port */
|
||||
ModulePortId child_wl_port = module_manager.find_module_port(child_module, std::string(MEMORY_WL_PORT_NAME));
|
||||
BasicPort child_wl_port_info = module_manager.module_port(child_module, child_wl_port);
|
||||
|
||||
for (const size_t& sink_wl_pin : child_wl_port_info.pins()) {
|
||||
size_t wl_pin_id = wl_start_index_per_tile[coord.y()] + cur_wl_index;
|
||||
sr_banks.add_shift_register_sink_nodes(config_region, sr_bank_module, cur_inst, child_id, sink_wl_pin);
|
||||
sr_banks.add_shift_register_sink_blwls(config_region, sr_bank_module, cur_inst, wl_pin_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ namespace openfpga {
|
|||
|
||||
std::vector<ModuleId> MemoryBankShiftRegisterBanks::shift_register_bank_unique_modules() const {
|
||||
std::vector<ModuleId> sr_bank_modules;
|
||||
for (const auto& region : sr_instance_info_) {
|
||||
for (const auto& region : sr_instance_sink_child_ids_) {
|
||||
for (const auto& pair : region) {
|
||||
if (sr_bank_modules.end() == std::find(sr_bank_modules.begin(), sr_bank_modules.end(), pair.first.first)) {
|
||||
sr_bank_modules.push_back(pair.first.first);
|
||||
|
@ -20,7 +20,7 @@ std::vector<ModuleId> MemoryBankShiftRegisterBanks::shift_register_bank_unique_m
|
|||
std::vector<ModuleId> MemoryBankShiftRegisterBanks::shift_register_bank_modules(const ConfigRegionId& region) const {
|
||||
std::vector<ModuleId> sr_bank_modules;
|
||||
VTR_ASSERT(valid_region_id(region));
|
||||
for (const auto& pair : sr_instance_info_[region]) {
|
||||
for (const auto& pair : sr_instance_sink_child_ids_[region]) {
|
||||
sr_bank_modules.push_back(pair.first.first);
|
||||
}
|
||||
return sr_bank_modules;
|
||||
|
@ -29,7 +29,7 @@ std::vector<ModuleId> MemoryBankShiftRegisterBanks::shift_register_bank_modules(
|
|||
std::vector<size_t> MemoryBankShiftRegisterBanks::shift_register_bank_instances(const ConfigRegionId& region) const {
|
||||
std::vector<size_t> sr_bank_instances;
|
||||
VTR_ASSERT(valid_region_id(region));
|
||||
for (const auto& pair : sr_instance_info_[region]) {
|
||||
for (const auto& pair : sr_instance_sink_child_ids_[region]) {
|
||||
sr_bank_instances.push_back(pair.first.second);
|
||||
}
|
||||
return sr_bank_instances;
|
||||
|
@ -39,43 +39,41 @@ std::vector<size_t> MemoryBankShiftRegisterBanks::shift_register_bank_sink_child
|
|||
const ModuleId& sr_module,
|
||||
const size_t& sr_instance) const {
|
||||
VTR_ASSERT(valid_region_id(region));
|
||||
std::vector<size_t> sink_child_ids;
|
||||
|
||||
auto result = sr_instance_info_[region].find(std::make_pair(sr_module, sr_instance));
|
||||
auto result = sr_instance_sink_child_ids_[region].find(std::make_pair(sr_module, sr_instance));
|
||||
/* Return an empty vector if not found */
|
||||
if (result != sr_instance_info_[region].end()) {
|
||||
for (const auto& sink_child : result->second) {
|
||||
sink_child_ids.push_back(sink_child.first);
|
||||
}
|
||||
if (result != sr_instance_sink_child_ids_[region].end()) {
|
||||
return result->second;
|
||||
}
|
||||
return sink_child_ids;
|
||||
return std::vector<size_t>();
|
||||
}
|
||||
|
||||
std::vector<size_t> MemoryBankShiftRegisterBanks::shift_register_bank_sink_pin_ids(const ConfigRegionId& region,
|
||||
const ModuleId& sr_module,
|
||||
const size_t& sr_instance) const {
|
||||
VTR_ASSERT(valid_region_id(region));
|
||||
std::vector<size_t> sink_child_pin_ids;
|
||||
|
||||
auto result = sr_instance_info_[region].find(std::make_pair(sr_module, sr_instance));
|
||||
auto result = sr_instance_sink_child_pin_ids_[region].find(std::make_pair(sr_module, sr_instance));
|
||||
/* Return an empty vector if not found */
|
||||
if (result != sr_instance_info_[region].end()) {
|
||||
for (const auto& sink_child : result->second) {
|
||||
sink_child_pin_ids.push_back(sink_child.second);
|
||||
}
|
||||
if (result != sr_instance_sink_child_pin_ids_[region].end()) {
|
||||
return result->second;
|
||||
}
|
||||
return sink_child_pin_ids;
|
||||
return std::vector<size_t>();
|
||||
}
|
||||
|
||||
void MemoryBankShiftRegisterBanks::resize_regions(const size_t& num_regions) {
|
||||
sr_instance_info_.resize(num_regions);
|
||||
sr_instance_sink_child_ids_.resize(num_regions);
|
||||
sr_instance_sink_child_pin_ids_.resize(num_regions);
|
||||
sr_instance_sink_blwl_ids_.resize(num_regions);
|
||||
}
|
||||
|
||||
void MemoryBankShiftRegisterBanks::add_shift_register_instance(const ConfigRegionId& region,
|
||||
const ModuleId& sr_module,
|
||||
const size_t& sr_instance) {
|
||||
VTR_ASSERT(valid_region_id(region));
|
||||
sr_instance_info_[region][std::make_pair(sr_module, sr_instance)];
|
||||
sr_instance_sink_child_ids_[region][std::make_pair(sr_module, sr_instance)];
|
||||
sr_instance_sink_child_pin_ids_[region][std::make_pair(sr_module, sr_instance)];
|
||||
sr_instance_sink_blwl_ids_[region][std::make_pair(sr_module, sr_instance)];
|
||||
}
|
||||
|
||||
void MemoryBankShiftRegisterBanks::add_shift_register_sink_nodes(const ConfigRegionId& region,
|
||||
|
@ -84,11 +82,20 @@ void MemoryBankShiftRegisterBanks::add_shift_register_sink_nodes(const ConfigReg
|
|||
const size_t& sink_child_id,
|
||||
const size_t& sink_child_pin_id) {
|
||||
VTR_ASSERT(valid_region_id(region));
|
||||
sr_instance_info_[region][std::make_pair(sr_module, sr_instance)].push_back(std::make_pair(sink_child_id, sink_child_pin_id));
|
||||
sr_instance_sink_child_ids_[region][std::make_pair(sr_module, sr_instance)].push_back(sink_child_id);
|
||||
sr_instance_sink_child_pin_ids_[region][std::make_pair(sr_module, sr_instance)].push_back(sink_child_pin_id);
|
||||
}
|
||||
|
||||
void MemoryBankShiftRegisterBanks::add_shift_register_sink_blwls(const ConfigRegionId& region,
|
||||
const ModuleId& sr_module,
|
||||
const size_t& sr_instance,
|
||||
const size_t& sink_blwl_id) {
|
||||
VTR_ASSERT(valid_region_id(region));
|
||||
sr_instance_sink_blwl_ids_[region][std::make_pair(sr_module, sr_instance)].push_back(sink_blwl_id);
|
||||
}
|
||||
|
||||
bool MemoryBankShiftRegisterBanks::valid_region_id(const ConfigRegionId& region) const {
|
||||
return size_t(region) < sr_instance_info_.size();
|
||||
return size_t(region) < sr_instance_sink_child_ids_.size();
|
||||
}
|
||||
|
||||
} /* end namespace openfpga */
|
||||
|
|
|
@ -52,18 +52,26 @@ class MemoryBankShiftRegisterBanks {
|
|||
const ModuleId& sr_module,
|
||||
const size_t& sr_instance);
|
||||
|
||||
/* @brief Add the module id and instance id of a shift register under a specific configuration region of top-level module */
|
||||
/* @brief Add the child id and pin id of BL/WL to which a shift register is connected to under a specific configuration region of top-level module */
|
||||
void add_shift_register_sink_nodes(const ConfigRegionId& region,
|
||||
const ModuleId& sr_module,
|
||||
const size_t& sr_instance,
|
||||
const size_t& sink_child_id,
|
||||
const size_t& sink_child_pin_id);
|
||||
|
||||
/* @brief Add the BL/WL id under a specific configuration region of top-level module to which a shift register is connected to */
|
||||
void add_shift_register_sink_blwls(const ConfigRegionId& region,
|
||||
const ModuleId& sr_module,
|
||||
const size_t& sr_instance,
|
||||
const size_t& sink_blwl_id);
|
||||
public: /* Validators */
|
||||
bool valid_region_id(const ConfigRegionId& region) const;
|
||||
|
||||
private: /* Internal data */
|
||||
/* [config_region][(shift_register_module, shift_register_instance)][i] = (reconfigurable_child_id, blwl_port_pin_index)*/
|
||||
vtr::vector<ConfigRegionId, std::map<std::pair<ModuleId, size_t>, std::vector<std::pair<size_t, size_t>>>> sr_instance_info_;
|
||||
vtr::vector<ConfigRegionId, std::map<std::pair<ModuleId, size_t>, std::vector<size_t>>> sr_instance_sink_child_ids_;
|
||||
vtr::vector<ConfigRegionId, std::map<std::pair<ModuleId, size_t>, std::vector<size_t>>> sr_instance_sink_child_pin_ids_;
|
||||
vtr::vector<ConfigRegionId, std::map<std::pair<ModuleId, size_t>, std::vector<size_t>>> sr_instance_sink_blwl_ids_;
|
||||
};
|
||||
|
||||
} /* end namespace openfpga */
|
||||
|
|
|
@ -43,6 +43,16 @@ std::vector<std::string> MemoryBankShiftRegisterFabricBitstream::wl_vectors(cons
|
|||
return bitstream_word_wls_[word_id];
|
||||
}
|
||||
|
||||
std::vector<std::string> MemoryBankShiftRegisterFabricBitstream::blwl_vectors(const MemoryBankShiftRegisterFabricBitstreamWordId& word_id) const {
|
||||
VTR_ASSERT(valid_word_id(word_id));
|
||||
std::vector<std::string> blwl_vec = bitstream_word_bls_[word_id];
|
||||
VTR_ASSERT(blwl_vec.size() == bitstream_word_wls_[word_id].size());
|
||||
for (size_t iwl = 0; iwl < bitstream_word_wls_[word_id].size(); ++iwl) {
|
||||
blwl_vec[iwl] += bitstream_word_wls_[word_id][iwl];
|
||||
}
|
||||
return blwl_vec;
|
||||
}
|
||||
|
||||
MemoryBankShiftRegisterFabricBitstreamWordId MemoryBankShiftRegisterFabricBitstream::create_word() {
|
||||
/* Create a new id*/
|
||||
MemoryBankShiftRegisterFabricBitstreamWordId word_id = MemoryBankShiftRegisterFabricBitstreamWordId(bitstream_word_ids_.size());
|
||||
|
@ -59,14 +69,12 @@ MemoryBankShiftRegisterFabricBitstreamWordId MemoryBankShiftRegisterFabricBitstr
|
|||
void MemoryBankShiftRegisterFabricBitstream::add_bl_vectors(const MemoryBankShiftRegisterFabricBitstreamWordId& word_id,
|
||||
const std::string& bl_vec) {
|
||||
VTR_ASSERT(valid_word_id(word_id));
|
||||
VTR_ASSERT(bl_vec.size() == bl_width());
|
||||
return bitstream_word_bls_[word_id].push_back(bl_vec);
|
||||
}
|
||||
|
||||
void MemoryBankShiftRegisterFabricBitstream::add_wl_vectors(const MemoryBankShiftRegisterFabricBitstreamWordId& word_id,
|
||||
const std::string& wl_vec) {
|
||||
VTR_ASSERT(valid_word_id(word_id));
|
||||
VTR_ASSERT(wl_vec.size() == wl_width());
|
||||
return bitstream_word_wls_[word_id].push_back(wl_vec);
|
||||
}
|
||||
|
||||
|
|
|
@ -43,6 +43,9 @@ class MemoryBankShiftRegisterFabricBitstream {
|
|||
/* @brief Return the WL vectors in a given word id */
|
||||
std::vector<std::string> wl_vectors(const MemoryBankShiftRegisterFabricBitstreamWordId& word_id) const;
|
||||
|
||||
/* @brief Return the pair of BL and WL vectors in a given word id */
|
||||
std::vector<std::string> blwl_vectors(const MemoryBankShiftRegisterFabricBitstreamWordId& word_id) const;
|
||||
|
||||
public: /* Mutators */
|
||||
/* @brief Create a new word */
|
||||
MemoryBankShiftRegisterFabricBitstreamWordId create_word();
|
||||
|
|
|
@ -238,26 +238,23 @@ int write_memory_bank_shift_register_fabric_bitstream_to_text_file(std::fstream&
|
|||
const FabricBitstream& fabric_bitstream) {
|
||||
int status = 0;
|
||||
|
||||
MemoryBankFlattenFabricBitstream fabric_bits = build_memory_bank_flatten_fabric_bitstream(fabric_bitstream, bit_value_to_skip);
|
||||
|
||||
size_t bl_addr_size = fabric_bits.bl_vector_size();
|
||||
size_t wl_addr_size = fabric_bits.wl_vector_size();
|
||||
MemoryBankShiftRegisterFabricBitstream fabric_bits = build_memory_bank_shift_register_fabric_bitstream(fabric_bitstream, bit_value_to_skip);
|
||||
|
||||
/* Output information about how to intepret the bitstream */
|
||||
fp << "// Bitstream length: " << fabric_bits.size() << std::endl;
|
||||
fp << "// Bitstream word count: " << fabric_bits.num_words() << std::endl;
|
||||
fp << "// Bitstream word size: " << fabric_bits.word_size() << std::endl;
|
||||
fp << "// Bitstream width (LSB -> MSB): ";
|
||||
fp << "<bl shift register heads" << bl_addr_size << " bits>";
|
||||
fp << "<wl shift register heads " << wl_addr_size << " bits>";
|
||||
fp << "<bl shift register heads" << fabric_bits.bl_width() << " bits>";
|
||||
fp << "<wl shift register heads " << fabric_bits.wl_width() << " bits>";
|
||||
fp << std::endl;
|
||||
|
||||
for (const auto& wl_vec : fabric_bits.wl_vectors()) {
|
||||
/* Write BL address code */
|
||||
for (const auto& bl_unit : fabric_bits.bl_vector(wl_vec)) {
|
||||
fp << bl_unit;
|
||||
}
|
||||
/* Write WL address code */
|
||||
for (const auto& wl_unit : wl_vec) {
|
||||
fp << wl_unit;
|
||||
size_t word_cnt = 0;
|
||||
|
||||
for (const auto& word : fabric_bits.words()) {
|
||||
fp << "// Word " << word_cnt << std::endl;
|
||||
/* Write BL/WL address code */
|
||||
for (const auto& blwl_vec : fabric_bits.blwl_vectors(word)) {
|
||||
fp << blwl_vec;
|
||||
}
|
||||
fp << std::endl;
|
||||
}
|
||||
|
|
|
@ -319,6 +319,61 @@ MemoryBankFlattenFabricBitstream build_memory_bank_flatten_fabric_bitstream(cons
|
|||
return fabric_bits;
|
||||
}
|
||||
|
||||
MemoryBankShiftRegisterFabricBitstream build_memory_bank_shift_register_fabric_bitstream(const FabricBitstream& fabric_bitstream,
|
||||
//const std::array<MemoryBankShiftRegisterBanks, 2>& blwl_sr_banks,
|
||||
const bool& bit_value_to_skip) {
|
||||
MemoryBankFlattenFabricBitstream raw_fabric_bits = build_memory_bank_flatten_fabric_bitstream(fabric_bitstream, bit_value_to_skip);
|
||||
MemoryBankShiftRegisterFabricBitstream fabric_bits;
|
||||
|
||||
/* Iterate over each word */
|
||||
for (const auto& wl_vec : raw_fabric_bits.wl_vectors()) {
|
||||
std::vector<std::string> bl_vec = raw_fabric_bits.bl_vector(wl_vec);
|
||||
/* Find the max sizes of BL/WL bits, this determines the size of shift register chain */
|
||||
size_t max_blwl_sizes = 0;
|
||||
for (const auto& bl_bits : bl_vec) {
|
||||
max_blwl_sizes = std::max(max_blwl_sizes, bl_bits.size());
|
||||
}
|
||||
for (const auto& wl_bits : wl_vec) {
|
||||
max_blwl_sizes = std::max(max_blwl_sizes, wl_bits.size());
|
||||
}
|
||||
/* Reshape the BL and WL vectors */
|
||||
std::vector<std::string> reshaped_blwls(bl_vec.size() + wl_vec.size(), std::string(max_blwl_sizes, '0'));
|
||||
size_t blwl_col_cnt = 0;
|
||||
for (const auto& bl_bits : bl_vec) {
|
||||
size_t offset = max_blwl_sizes - bl_vec.size();
|
||||
for (const char& bl_bit : bl_bits) {
|
||||
reshaped_blwls[blwl_col_cnt][offset] = bl_bit;
|
||||
offset++;
|
||||
}
|
||||
blwl_col_cnt++;
|
||||
}
|
||||
for (const auto& wl_bits : wl_vec) {
|
||||
size_t offset = max_blwl_sizes - wl_vec.size();
|
||||
for (const char& wl_bit : wl_bits) {
|
||||
reshaped_blwls[blwl_col_cnt][offset] = wl_bit;
|
||||
offset++;
|
||||
}
|
||||
blwl_col_cnt++;
|
||||
}
|
||||
/* Add the word to final bitstream */
|
||||
MemoryBankShiftRegisterFabricBitstreamWordId word_id = fabric_bits.create_word();
|
||||
for (size_t irow = 0; irow < max_blwl_sizes; ++irow) {
|
||||
std::string cur_bl_vec;
|
||||
for (size_t icol = 0; icol < bl_vec.size(); ++icol) {
|
||||
cur_bl_vec.push_back(reshaped_blwls[icol][irow]);
|
||||
}
|
||||
fabric_bits.add_bl_vectors(word_id, cur_bl_vec);
|
||||
|
||||
std::string cur_wl_vec;
|
||||
for (size_t icol = bl_vec.size(); icol < bl_vec.size() + wl_vec.size(); ++icol) {
|
||||
cur_wl_vec.push_back(reshaped_blwls[icol][irow]);
|
||||
}
|
||||
fabric_bits.add_wl_vectors(word_id, cur_wl_vec);
|
||||
}
|
||||
}
|
||||
|
||||
return fabric_bits;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* For fast configuration, the number of bits to be skipped
|
||||
|
|
|
@ -9,8 +9,11 @@
|
|||
*******************************************************************/
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <array>
|
||||
#include "bitstream_manager.h"
|
||||
#include "memory_bank_flatten_fabric_bitstream.h"
|
||||
#include "memory_bank_shift_register_banks.h"
|
||||
#include "memory_bank_shift_register_fabric_bitstream.h"
|
||||
#include "fabric_bitstream.h"
|
||||
|
||||
/********************************************************************
|
||||
|
@ -39,7 +42,7 @@ size_t find_frame_based_fast_configuration_fabric_bitstream_size(const FabricBit
|
|||
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
|
||||
* @ brief Reorganize the fabric bitstream for memory banks which use flatten BL and WLs
|
||||
* For each configuration region, we will merge BL address (which are 1-hot codes) under the same WL address
|
||||
*
|
||||
* Quick Example
|
||||
|
@ -61,6 +64,38 @@ size_t find_frame_based_fast_configuration_fabric_bitstream_size(const FabricBit
|
|||
MemoryBankFlattenFabricBitstream build_memory_bank_flatten_fabric_bitstream(const FabricBitstream& fabric_bitstream,
|
||||
const bool& bit_value_to_skip);
|
||||
|
||||
/********************************************************************
|
||||
* @ brief Reorganize the fabric bitstream for memory banks which use 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
|
||||
*
|
||||
* Because that the BL/WL are loaded through shift registers (perhaps using multiple heads), the bitstream will be reorganized as
|
||||
* Considering single head:
|
||||
*
|
||||
* <bl of region A>_<bl of region B> <wl of region A>_<wl of region B>
|
||||
* 1_1 0_0
|
||||
* 0_1 0_0
|
||||
* 1_0 0_0
|
||||
*
|
||||
* @note the std::map may cause large memory footprint for large bitstream databases!
|
||||
*******************************************************************/
|
||||
MemoryBankShiftRegisterFabricBitstream build_memory_bank_shift_register_fabric_bitstream(const FabricBitstream& fabric_bitstream,
|
||||
//const std::array<MemoryBankShiftRegisterBanks, 2>& blwl_sr_banks,
|
||||
const bool& bit_value_to_skip);
|
||||
|
||||
/* 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);
|
||||
|
|
Loading…
Reference in New Issue