[FPGA-Bitstream] Upgrade bitstream generator to support multiple shift register banks in a configuration region for QuickLogic memory bank

This commit is contained in:
tangxifan 2021-10-09 20:39:45 -07:00
parent aac74d9163
commit 34575f7222
15 changed files with 158 additions and 16 deletions

View File

@ -122,6 +122,7 @@ int write_fabric_bitstream(const OpenfpgaContext& openfpga_ctx,
/* By default, output in plain text format */
status = write_fabric_bitstream_to_text_file(openfpga_ctx.bitstream_manager(),
openfpga_ctx.fabric_bitstream(),
openfpga_ctx.blwl_shift_register_banks(),
openfpga_ctx.arch().config_protocol,
openfpga_ctx.fabric_global_port_info(),
cmd_context.option_value(cmd, opt_file),

View File

@ -66,7 +66,7 @@ class OpenfpgaContext : public Context {
const openfpga::DeviceRRGSB& device_rr_gsb() const { return device_rr_gsb_; }
const openfpga::MuxLibrary& mux_lib() const { return mux_lib_; }
const openfpga::DecoderLibrary& decoder_lib() const { return decoder_lib_; }
const openfpga::MemoryBankShiftRegisterBanks& blwl_shift_register_banks() { return blwl_sr_banks_; }
const openfpga::MemoryBankShiftRegisterBanks& blwl_shift_register_banks() const { return blwl_sr_banks_; }
const openfpga::TileDirect& tile_direct() const { return tile_direct_; }
const openfpga::ModuleManager& module_graph() const { return module_graph_; }
const openfpga::FlowManager& flow_manager() const { return flow_manager_; }

View File

@ -107,6 +107,7 @@ int write_full_testbench(const OpenfpgaContext& openfpga_ctx,
return fpga_verilog_full_testbench(openfpga_ctx.module_graph(),
openfpga_ctx.bitstream_manager(),
openfpga_ctx.fabric_bitstream(),
openfpga_ctx.blwl_shift_register_banks(),
g_vpr_ctx.atom(),
g_vpr_ctx.placement(),
pin_constraints,

View File

@ -6,6 +6,10 @@
/* begin namespace openfpga */
namespace openfpga {
ModuleManager::region_range MemoryBankShiftRegisterBanks::regions() const {
return vtr::make_range(config_region_ids_.begin(), config_region_ids_.end());
}
std::vector<size_t> MemoryBankShiftRegisterBanks::bl_bank_unique_sizes() const {
std::vector<size_t> unique_sizes;
for (const auto& region : bl_bank_data_ports_) {
@ -203,6 +207,10 @@ BasicPort MemoryBankShiftRegisterBanks::find_wl_shift_register_bank_data_port(co
}
void MemoryBankShiftRegisterBanks::resize_regions(const size_t& num_regions) {
config_region_ids_.resize(num_regions);
for (size_t iregion = 0; iregion < num_regions; ++iregion) {
config_region_ids_[ConfigRegionId(iregion)] = ConfigRegionId(iregion);
}
bl_bank_ids_.resize(num_regions);
bl_bank_data_ports_.resize(num_regions);
bl_bank_modules_.resize(num_regions);

View File

@ -23,6 +23,7 @@ namespace openfpga {
******************************************************************************/
class MemoryBankShiftRegisterBanks {
public: /* Accessors: aggregates */
ModuleManager::region_range regions() const;
FabricKey::fabric_bit_line_bank_range bl_banks(const ConfigRegionId& region_id) const;
FabricKey::fabric_word_line_bank_range wl_banks(const ConfigRegionId& region_id) const;
public: /* Accessors */
@ -200,6 +201,8 @@ class MemoryBankShiftRegisterBanks {
void build_wl_port_fast_lookup() const;
private: /* Internal data */
vtr::vector<ConfigRegionId, ConfigRegionId> config_region_ids_;
/* General information about the BL shift register bank */
vtr::vector<ConfigRegionId, vtr::vector<FabricBitLineBankId, FabricBitLineBankId>> bl_bank_ids_;
vtr::vector<ConfigRegionId, vtr::vector<FabricBitLineBankId, std::vector<BasicPort>>> bl_bank_data_ports_;

View File

@ -244,6 +244,7 @@ int write_memory_bank_shift_register_fabric_bitstream_to_text_file(std::fstream&
const bool& fast_configuration,
const bool& bit_value_to_skip,
const FabricBitstream& fabric_bitstream,
const MemoryBankShiftRegisterBanks& blwl_sr_banks,
const bool& keep_dont_care_bits) {
int status = 0;
@ -251,7 +252,7 @@ int write_memory_bank_shift_register_fabric_bitstream_to_text_file(std::fstream&
if (keep_dont_care_bits) {
dont_care_bit = DONT_CARE_CHAR;
}
MemoryBankShiftRegisterFabricBitstream fabric_bits = build_memory_bank_shift_register_fabric_bitstream(fabric_bitstream, fast_configuration, bit_value_to_skip, dont_care_bit);
MemoryBankShiftRegisterFabricBitstream fabric_bits = build_memory_bank_shift_register_fabric_bitstream(fabric_bitstream, blwl_sr_banks, fast_configuration, bit_value_to_skip, dont_care_bit);
/* Output information about how to intepret the bitstream */
fp << "// Bitstream word count: " << fabric_bits.num_words() << std::endl;
@ -363,6 +364,7 @@ int write_frame_based_fabric_bitstream_to_text_file(std::fstream& fp,
*******************************************************************/
int write_fabric_bitstream_to_text_file(const BitstreamManager& bitstream_manager,
const FabricBitstream& fabric_bitstream,
const MemoryBankShiftRegisterBanks& blwl_sr_banks,
const ConfigProtocol& config_protocol,
const FabricGlobalPortInfo& global_ports,
const std::string& fname,
@ -439,6 +441,7 @@ int write_fabric_bitstream_to_text_file(const BitstreamManager& bitstream_manage
apply_fast_configuration,
bit_value_to_skip,
fabric_bitstream,
blwl_sr_banks,
keep_dont_care_bits);
}
break;

View File

@ -9,6 +9,7 @@
#include "bitstream_manager.h"
#include "fabric_bitstream.h"
#include "config_protocol.h"
#include "memory_bank_shift_register_banks.h"
#include "fabric_global_port_info.h"
/********************************************************************
@ -20,6 +21,7 @@ namespace openfpga {
int write_fabric_bitstream_to_text_file(const BitstreamManager& bitstream_manager,
const FabricBitstream& fabric_bitstream,
const MemoryBankShiftRegisterBanks& blwl_sr_banks,
const ConfigProtocol& config_protocol,
const FabricGlobalPortInfo& global_ports,
const std::string& fname,

View File

@ -149,6 +149,7 @@ void fpga_fabric_verilog(ModuleManager &module_manager,
int fpga_verilog_full_testbench(const ModuleManager &module_manager,
const BitstreamManager &bitstream_manager,
const FabricBitstream &fabric_bitstream,
const MemoryBankShiftRegisterBanks& blwl_sr_banks,
const AtomContext &atom_ctx,
const PlacementContext &place_ctx,
const PinConstraints& pin_constraints,
@ -175,7 +176,7 @@ int fpga_verilog_full_testbench(const ModuleManager &module_manager,
/* Generate full testbench for verification, including configuration phase and operating phase */
std::string top_testbench_file_path = src_dir_path + netlist_name + std::string(AUTOCHECK_TOP_TESTBENCH_VERILOG_FILE_POSTFIX);
print_verilog_full_testbench(module_manager,
bitstream_manager, fabric_bitstream,
bitstream_manager, fabric_bitstream, blwl_sr_banks,
circuit_lib,
config_protocol,
fabric_global_port_info,

View File

@ -48,6 +48,7 @@ void fpga_fabric_verilog(ModuleManager& module_manager,
int fpga_verilog_full_testbench(const ModuleManager& module_manager,
const BitstreamManager& bitstream_manager,
const FabricBitstream& fabric_bitstream,
const MemoryBankShiftRegisterBanks& blwl_sr_banks,
const AtomContext& atom_ctx,
const PlacementContext& place_ctx,
const PinConstraints& pin_constraints,

View File

@ -1132,6 +1132,7 @@ int print_verilog_top_testbench_configuration_protocol_stimulus(std::fstream& fp
const bool& fast_configuration,
const bool& bit_value_to_skip,
const FabricBitstream& fabric_bitstream,
const MemoryBankShiftRegisterBanks& blwl_sr_banks,
const float& prog_clock_period,
const float& timescale) {
/* Validate the file stream */
@ -1147,7 +1148,8 @@ int print_verilog_top_testbench_configuration_protocol_stimulus(std::fstream& fp
return print_verilog_top_testbench_configuration_protocol_ql_memory_bank_stimulus(fp,
config_protocol, sim_settings,
module_manager, top_module,
fast_configuration, bit_value_to_skip, fabric_bitstream,
fast_configuration, bit_value_to_skip,
fabric_bitstream, blwl_sr_banks,
prog_clock_period, timescale);
break;
case CONFIG_MEM_MEMORY_BANK:
@ -1738,7 +1740,8 @@ void print_verilog_full_testbench_bitstream(std::fstream& fp,
const ModuleManager& module_manager,
const ModuleId& top_module,
const BitstreamManager& bitstream_manager,
const FabricBitstream& fabric_bitstream) {
const FabricBitstream& fabric_bitstream,
const MemoryBankShiftRegisterBanks& blwl_sr_banks) {
/* Branch on the type of configuration protocol */
switch (config_protocol.type()) {
@ -1771,7 +1774,7 @@ void print_verilog_full_testbench_bitstream(std::fstream& fp,
fast_configuration,
bit_value_to_skip,
module_manager, top_module,
fabric_bitstream);
fabric_bitstream, blwl_sr_banks);
break;
case CONFIG_MEM_FRAME_BASED:
print_verilog_full_testbench_frame_decoder_bitstream(fp, bitstream_file,
@ -1893,6 +1896,7 @@ void print_verilog_top_testbench_check(std::fstream& fp,
int print_verilog_full_testbench(const ModuleManager& module_manager,
const BitstreamManager& bitstream_manager,
const FabricBitstream& fabric_bitstream,
const MemoryBankShiftRegisterBanks& blwl_sr_banks,
const CircuitLibrary& circuit_lib,
const ConfigProtocol& config_protocol,
const FabricGlobalPortInfo& global_ports,
@ -1984,7 +1988,8 @@ int print_verilog_full_testbench(const ModuleManager& module_manager,
status = print_verilog_top_testbench_configuration_protocol_stimulus(fp,
config_protocol, simulation_parameters,
module_manager, top_module,
fast_configuration, bit_value_to_skip, fabric_bitstream,
fast_configuration, bit_value_to_skip,
fabric_bitstream, blwl_sr_banks,
prog_clock_period,
VERILOG_SIM_TIMESCALE);
@ -2057,7 +2062,7 @@ int print_verilog_full_testbench(const ModuleManager& module_manager,
apply_fast_configuration,
bit_value_to_skip,
module_manager, top_module,
bitstream_manager, fabric_bitstream);
bitstream_manager, fabric_bitstream, blwl_sr_banks);
/* Add signal initialization:
* Bypass writing codes to files due to the autogenerated codes are very large.

View File

@ -17,6 +17,7 @@
#include "fabric_global_port_info.h"
#include "vpr_netlist_annotation.h"
#include "simulation_setting.h"
#include "memory_bank_shift_register_banks.h"
#include "verilog_testbench_options.h"
/********************************************************************
@ -29,6 +30,7 @@ namespace openfpga {
int print_verilog_full_testbench(const ModuleManager& module_manager,
const BitstreamManager& bitstream_manager,
const FabricBitstream& fabric_bitstream,
const MemoryBankShiftRegisterBanks& blwl_sr_banks,
const CircuitLibrary& circuit_lib,
const ConfigProtocol& config_protocol,
const FabricGlobalPortInfo& global_ports,

View File

@ -326,6 +326,7 @@ int print_verilog_top_testbench_configuration_protocol_ql_memory_bank_stimulus(s
const bool& fast_configuration,
const bool& bit_value_to_skip,
const FabricBitstream& fabric_bitstream,
const MemoryBankShiftRegisterBanks& blwl_sr_banks,
const float& prog_clock_period,
const float& timescale) {
ModulePortId en_port_id = module_manager.find_module_port(top_module,
@ -350,6 +351,7 @@ int print_verilog_top_testbench_configuration_protocol_ql_memory_bank_stimulus(s
/* Reorganize the fabric bitstream by the same address across regions */
if (CONFIG_MEM_QL_MEMORY_BANK == config_protocol.type()) {
MemoryBankShiftRegisterFabricBitstream fabric_bits_by_addr = build_memory_bank_shift_register_fabric_bitstream(fabric_bitstream,
blwl_sr_banks,
fast_configuration,
bit_value_to_skip);
@ -541,12 +543,14 @@ void print_verilog_full_testbench_ql_memory_bank_shift_register_bitstream(std::f
const bool& bit_value_to_skip,
const ModuleManager& module_manager,
const ModuleId& top_module,
const FabricBitstream& fabric_bitstream) {
const FabricBitstream& fabric_bitstream,
const MemoryBankShiftRegisterBanks& blwl_sr_banks) {
/* Validate the file stream */
valid_file_stream(fp);
/* Reorganize the fabric bitstream by the same address across regions */
MemoryBankShiftRegisterFabricBitstream fabric_bits_by_addr = build_memory_bank_shift_register_fabric_bitstream(fabric_bitstream,
blwl_sr_banks,
fast_configuration,
bit_value_to_skip);
@ -940,7 +944,8 @@ void print_verilog_full_testbench_ql_memory_bank_bitstream(std::fstream& fp,
const bool& bit_value_to_skip,
const ModuleManager& module_manager,
const ModuleId& top_module,
const FabricBitstream& fabric_bitstream) {
const FabricBitstream& fabric_bitstream,
const MemoryBankShiftRegisterBanks& blwl_sr_banks) {
if ( (BLWL_PROTOCOL_DECODER == config_protocol.bl_protocol_type())
&& (BLWL_PROTOCOL_DECODER == config_protocol.wl_protocol_type()) ) {
print_verilog_full_testbench_ql_memory_bank_decoder_bitstream(fp, bitstream_file,
@ -961,7 +966,7 @@ void print_verilog_full_testbench_ql_memory_bank_bitstream(std::fstream& fp,
fast_configuration,
bit_value_to_skip,
module_manager, top_module,
fabric_bitstream);
fabric_bitstream, blwl_sr_banks);
}
}

View File

@ -17,6 +17,7 @@
#include "fabric_global_port_info.h"
#include "vpr_netlist_annotation.h"
#include "simulation_setting.h"
#include "memory_bank_shift_register_banks.h"
#include "verilog_testbench_options.h"
/********************************************************************
@ -53,6 +54,7 @@ int print_verilog_top_testbench_configuration_protocol_ql_memory_bank_stimulus(s
const bool& fast_configuration,
const bool& bit_value_to_skip,
const FabricBitstream& fabric_bitstream,
const MemoryBankShiftRegisterBanks& blwl_sr_banks,
const float& prog_clock_period,
const float& timescale);
@ -67,7 +69,8 @@ void print_verilog_full_testbench_ql_memory_bank_bitstream(std::fstream& fp,
const bool& bit_value_to_skip,
const ModuleManager& module_manager,
const ModuleId& top_module,
const FabricBitstream& fabric_bitstream);
const FabricBitstream& fabric_bitstream,
const MemoryBankShiftRegisterBanks& blwl_sr_banks);
} /* end namespace openfpga */

View File

@ -12,6 +12,7 @@
#include "vtr_log.h"
/* Headers from openfpgautil library */
#include "openfpga_reserved_words.h"
#include "openfpga_decode.h"
#include "fabric_bitstream_utils.h"
@ -397,9 +398,109 @@ std::vector<std::string> reshape_bitstream_vectors_to_first_element(const std::v
return rotated_vectors;
}
/** @brief Split each BL vector in a configuration region into multiple shift register banks
* For example
* Original vector: 1xxx010xxx1
* Resulting vector (2 register register banks):
* 1xxx0
* 10xxx1
*/
static
std::vector<std::string> redistribute_bl_vectors_to_shift_register_banks(const std::vector<std::string> bl_vectors,
const MemoryBankShiftRegisterBanks& blwl_sr_banks) {
std::vector<std::string> multi_bank_bl_vec;
/* Resize the vector by counting the dimension */
/* Compute the start index of each region */
vtr::vector<ConfigRegionId, size_t> region_start_index;
region_start_index.resize(blwl_sr_banks.regions().size(), 0);
size_t total_num_banks = 0;
for (const auto& region : blwl_sr_banks.regions()) {
region_start_index[region] = total_num_banks;
total_num_banks += blwl_sr_banks.bl_banks(region).size();
}
multi_bank_bl_vec.resize(total_num_banks);
/* Resize each bank to be memory efficient */
size_t vec_start_index = 0;
for (const auto& region : blwl_sr_banks.regions()) {
for (const auto& bank : blwl_sr_banks.bl_banks(region)) {
size_t bank_size = blwl_sr_banks.bl_bank_size(region, bank);
multi_bank_bl_vec[vec_start_index].resize(bank_size);
vec_start_index++;
}
}
for (const std::string& region_bl_vec : bl_vectors) {
ConfigRegionId region = ConfigRegionId(&region_bl_vec - &bl_vectors[0]);
for (size_t ibit = 0; ibit < region_bl_vec.size(); ++ibit) {
/* Find the shift register bank id and the offset in data lines */
BasicPort bl_port(std::string(MEMORY_BL_PORT_NAME), ibit, ibit);
FabricBitLineBankId bank_id = blwl_sr_banks.find_bl_shift_register_bank_id(region, bl_port);
BasicPort sr_port = blwl_sr_banks.find_bl_shift_register_bank_data_port(region, bl_port);
VTR_ASSERT(1 == sr_port.get_width());
size_t vec_index = region_start_index[region] + size_t(bank_id);
multi_bank_bl_vec[vec_index][sr_port.get_lsb()] = region_bl_vec[ibit];
}
}
return multi_bank_bl_vec;
}
/** @brief Split each WL vector in a configuration region into multiple shift register banks
* For example
* Original vector: 1xxx010xxx1
* Resulting vector (2 register register banks):
* 1xxx0
* 10xxx1
*/
static
std::vector<std::string> redistribute_wl_vectors_to_shift_register_banks(const std::vector<std::string> wl_vectors,
const MemoryBankShiftRegisterBanks& blwl_sr_banks) {
std::vector<std::string> multi_bank_wl_vec;
/* Resize the vector by counting the dimension */
/* Compute the start index of each region */
vtr::vector<ConfigRegionId, size_t> region_start_index;
region_start_index.resize(blwl_sr_banks.regions().size(), 0);
size_t total_num_banks = 0;
for (const auto& region : blwl_sr_banks.regions()) {
region_start_index[region] = total_num_banks;
total_num_banks += blwl_sr_banks.wl_banks(region).size();
}
multi_bank_wl_vec.resize(total_num_banks);
/* Resize each bank to be memory efficient */
size_t vec_start_index = 0;
for (const auto& region : blwl_sr_banks.regions()) {
for (const auto& bank : blwl_sr_banks.wl_banks(region)) {
size_t bank_size = blwl_sr_banks.wl_bank_size(region, bank);
multi_bank_wl_vec[vec_start_index].resize(bank_size);
vec_start_index++;
}
}
for (const std::string& region_wl_vec : wl_vectors) {
ConfigRegionId region = ConfigRegionId(&region_wl_vec - &wl_vectors[0]);
for (size_t ibit = 0; ibit < region_wl_vec.size(); ++ibit) {
/* Find the shift register bank id and the offset in data lines */
BasicPort wl_port(std::string(MEMORY_WL_PORT_NAME), ibit, ibit);
FabricWordLineBankId bank_id = blwl_sr_banks.find_wl_shift_register_bank_id(region, wl_port);
BasicPort sr_port = blwl_sr_banks.find_wl_shift_register_bank_data_port(region, wl_port);
VTR_ASSERT(1 == sr_port.get_width());
size_t vec_index = region_start_index[region] + size_t(bank_id);
multi_bank_wl_vec[vec_index][sr_port.get_lsb()] = region_wl_vec[ibit];
}
}
return multi_bank_wl_vec;
}
MemoryBankShiftRegisterFabricBitstream build_memory_bank_shift_register_fabric_bitstream(const FabricBitstream& fabric_bitstream,
const MemoryBankShiftRegisterBanks& blwl_sr_banks,
const bool& fast_configuration,
//const MemoryBankShiftRegisterBanks& blwl_sr_banks,
const bool& bit_value_to_skip,
const char& dont_care_bit) {
MemoryBankFlattenFabricBitstream raw_fabric_bits = build_memory_bank_flatten_fabric_bitstream(fabric_bitstream, fast_configuration, bit_value_to_skip, dont_care_bit);
@ -411,7 +512,10 @@ MemoryBankShiftRegisterFabricBitstream build_memory_bank_shift_register_fabric_b
MemoryBankShiftRegisterFabricBitstreamWordId word_id = fabric_bits.create_word();
std::vector<std::string> reshaped_bl_vectors = reshape_bitstream_vectors_to_first_element(bl_vec, dont_care_bit);
/* Redistribute the BL vector to multiple banks */
std::vector<std::string> multi_bank_bl_vec = redistribute_bl_vectors_to_shift_register_banks(bl_vec, blwl_sr_banks);
std::vector<std::string> reshaped_bl_vectors = reshape_bitstream_vectors_to_first_element(multi_bank_bl_vec, dont_care_bit);
/* Reverse the vectors due to the shift register chain nature: first-in first-out */
std::reverse(reshaped_bl_vectors.begin(), reshaped_bl_vectors.end());
/* Add the BL word to final bitstream */
@ -419,7 +523,10 @@ MemoryBankShiftRegisterFabricBitstream build_memory_bank_shift_register_fabric_b
fabric_bits.add_bl_vectors(word_id, reshaped_bl_vec);
}
std::vector<std::string> reshaped_wl_vectors = reshape_bitstream_vectors_to_first_element(wl_vec, dont_care_bit);
/* Redistribute the WL vector to multiple banks */
std::vector<std::string> multi_bank_wl_vec = redistribute_wl_vectors_to_shift_register_banks(wl_vec, blwl_sr_banks);
std::vector<std::string> reshaped_wl_vectors = reshape_bitstream_vectors_to_first_element(multi_bank_wl_vec, dont_care_bit);
/* Reverse the vectors due to the shift register chain nature: first-in first-out */
std::reverse(reshaped_wl_vectors.begin(), reshaped_wl_vectors.end());
/* Add the BL word to final bitstream */

View File

@ -95,8 +95,8 @@ MemoryBankFlattenFabricBitstream build_memory_bank_flatten_fabric_bitstream(cons
* @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 MemoryBankShiftRegisterBanks& blwl_sr_banks,
const bool& fast_configuration,
//const MemoryBankShiftRegisterBanks& blwl_sr_banks,
const bool& bit_value_to_skip,
const char& dont_care_bit = 'x');