From 39a69e0d888d287aa69b13d6f166c1fb6813a070 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 8 Oct 2021 17:58:06 -0700 Subject: [PATCH] [Engine] Upgrading fabric generator to support customizable shift register banks from fabric key and configuration protocols --- openfpga/src/fabric/build_top_module.cpp | 13 ++ .../fabric/build_top_module_memory_bank.cpp | 115 ++++++++++++++++++ .../src/fabric/build_top_module_memory_bank.h | 8 ++ .../memory_bank_shift_register_banks.cpp | 47 ++++++- .../fabric/memory_bank_shift_register_banks.h | 11 ++ 5 files changed, 189 insertions(+), 5 deletions(-) diff --git a/openfpga/src/fabric/build_top_module.cpp b/openfpga/src/fabric/build_top_module.cpp index 1bd5dc703..b0ab747a8 100644 --- a/openfpga/src/fabric/build_top_module.cpp +++ b/openfpga/src/fabric/build_top_module.cpp @@ -23,6 +23,7 @@ #include "build_top_module_utils.h" #include "build_top_module_connection.h" #include "build_top_module_memory.h" +#include "build_top_module_memory_bank.h" #include "build_top_module_directs.h" #include "build_module_graph_utils.h" @@ -382,6 +383,11 @@ int build_top_module(ModuleManager& module_manager, if (CMD_EXEC_FATAL_ERROR == status) { return status; } + + status = load_top_module_shift_register_banks_from_fabric_key(fabric_key, blwl_sr_banks); + if (CMD_EXEC_FATAL_ERROR == status) { + return status; + } } /* Shuffle the configurable children in a random sequence */ @@ -389,6 +395,13 @@ int build_top_module(ModuleManager& module_manager, shuffle_top_module_configurable_children(module_manager, top_module, config_protocol); } + /* Build shift register bank detailed connections */ + sync_memory_bank_shift_register_banks_with_config_protocol_settings(module_manager, + blwl_sr_banks, + config_protocol, + top_module, + circuit_lib); + /* Add shared SRAM ports from the sub-modules under this Verilog module * This is a much easier job after adding sub modules (instances), * we just need to find all the I/O ports from the child modules and build a list of it diff --git a/openfpga/src/fabric/build_top_module_memory_bank.cpp b/openfpga/src/fabric/build_top_module_memory_bank.cpp index e58ab9b4c..077bf4d78 100644 --- a/openfpga/src/fabric/build_top_module_memory_bank.cpp +++ b/openfpga/src/fabric/build_top_module_memory_bank.cpp @@ -1728,4 +1728,119 @@ void add_top_module_ql_memory_bank_sram_ports(ModuleManager& module_manager, } } +/******************************************************************** + * Load the shift register bank -related data from fabric key to + * the dedicated and unified data structure + ********************************************************************/ +int load_top_module_shift_register_banks_from_fabric_key(const FabricKey& fabric_key, + MemoryBankShiftRegisterBanks& blwl_sr_banks) { + blwl_sr_banks.resize_regions(fabric_key.regions().size()); + + /* Load Bit-Line shift register banks */ + for (const auto& region : fabric_key.regions()) { + blwl_sr_banks.reserve_bl_shift_register_banks(region, fabric_key.bl_banks(region).size()); + for (const auto& bank : fabric_key.bl_banks(region)) { + FabricBitLineBankId sr_bank = blwl_sr_banks.create_bl_shift_register_bank(region); + for (const auto& data_port : fabric_key.bl_bank_data_ports(region, bank)) { + blwl_sr_banks.add_data_port_to_bl_shift_register_bank(region, sr_bank, data_port); + } + } + } + + /* Load Bit-Line shift register banks */ + for (const auto& region : fabric_key.regions()) { + blwl_sr_banks.reserve_wl_shift_register_banks(region, fabric_key.wl_banks(region).size()); + for (const auto& bank : fabric_key.wl_banks(region)) { + FabricWordLineBankId sr_bank = blwl_sr_banks.create_wl_shift_register_bank(region); + for (const auto& data_port : fabric_key.wl_bank_data_ports(region, bank)) { + blwl_sr_banks.add_data_port_to_wl_shift_register_bank(region, sr_bank, data_port); + } + } + } +} + +/******************************************************************** + * @brief This functions synchronize the settings in configuration protocol (from architecture description) + * and the existing information (loaded from fabric key files) + * @note This function should be called AFTER load_top_module_shift_register_banks_from_fabric_key() + ********************************************************************/ +void sync_memory_bank_shift_register_banks_with_config_protocol_settings(ModuleManager& module_manager, + MemoryBankShiftRegisterBanks& blwl_sr_banks, + const ConfigProtocol& config_protocol, + const ModuleId& top_module, + const CircuitLibrary& circuit_lib) { + /* ONLY synchronize when the configuration protocol is memory bank using shift registers */ + if ( CONFIG_MEM_QL_MEMORY_BANK != config_protocol.type() + || BLWL_PROTOCOL_SHIFT_REGISTER != config_protocol.bl_protocol_type() + || BLWL_PROTOCOL_SHIFT_REGISTER != config_protocol.wl_protocol_type() ) { + return; + } + + /* Fabric key has a higher priority in defining the shift register bank organization */ + if (!blwl_sr_banks.empty()) { + return; + } + + CircuitModelId sram_model = config_protocol.memory_model(); + + /* Reach here, if means we do not have any definition from fabric key files, use the settings from the configuration protocol */ + blwl_sr_banks.resize_regions(module_manager.regions(top_module).size()); + + /* Based on the number of shift register banks, evenly distribute the BLs in each region for each shift register bank */ + for (const auto& config_region : module_manager.regions(top_module)) { + size_t num_bls = compute_memory_bank_regional_num_bls(module_manager, top_module, + config_region, + circuit_lib, sram_model); + size_t num_bl_banks = config_protocol.bl_num_banks(); + blwl_sr_banks.reserve_bl_shift_register_banks(config_region, num_bl_banks); + + size_t regular_sr_bank_size = num_bls / num_bl_banks; + size_t cur_bl_index = 0; + for (size_t ibank = 0; ibank < num_bl_banks; ++ibank) { + /* For last bank, use all the residual sizes */ + size_t cur_sr_bank_size = regular_sr_bank_size; + if (ibank == num_bl_banks - 1) { + cur_sr_bank_size = num_bls - ibank * regular_sr_bank_size; + } + /* Create a bank and assign data ports */ + FabricBitLineBankId bank = blwl_sr_banks.create_bl_shift_register_bank(config_region); + BasicPort data_ports(std::string(MEMORY_BL_PORT_NAME), cur_bl_index, cur_bl_index + cur_sr_bank_size - 1); + blwl_sr_banks.add_data_port_to_bl_shift_register_bank(config_region, bank, data_ports); + + /* Increment the bl index */ + cur_bl_index += cur_sr_bank_size; + } + + VTR_ASSERT(cur_bl_index == num_bls); + } + + /* Based on the number of shift register banks, evenly distribute the WLs in each region for each shift register bank */ + for (const auto& config_region : module_manager.regions(top_module)) { + size_t num_wls = compute_memory_bank_regional_num_wls(module_manager, top_module, + config_region, + circuit_lib, sram_model); + size_t num_wl_banks = config_protocol.wl_num_banks(); + blwl_sr_banks.reserve_wl_shift_register_banks(config_region, num_wl_banks); + + size_t regular_sr_bank_size = num_wls / num_wl_banks; + size_t cur_wl_index = 0; + for (size_t ibank = 0; ibank < num_wl_banks; ++ibank) { + /* For last bank, use all the residual sizes */ + size_t cur_sr_bank_size = regular_sr_bank_size; + if (ibank == num_wl_banks - 1) { + cur_sr_bank_size = num_wls - ibank * regular_sr_bank_size; + } + /* Create a bank and assign data ports */ + FabricWordLineBankId bank = blwl_sr_banks.create_wl_shift_register_bank(config_region); + BasicPort data_ports(std::string(MEMORY_WL_PORT_NAME), cur_wl_index, cur_wl_index + cur_sr_bank_size - 1); + blwl_sr_banks.add_data_port_to_wl_shift_register_bank(config_region, bank, data_ports); + + /* Increment the bl index */ + cur_wl_index += cur_sr_bank_size; + } + + VTR_ASSERT(cur_wl_index == num_wls); + } +} + } /* end namespace openfpga */ diff --git a/openfpga/src/fabric/build_top_module_memory_bank.h b/openfpga/src/fabric/build_top_module_memory_bank.h index 5617271df..74bcdcc7a 100644 --- a/openfpga/src/fabric/build_top_module_memory_bank.h +++ b/openfpga/src/fabric/build_top_module_memory_bank.h @@ -38,6 +38,14 @@ void add_top_module_ql_memory_bank_sram_ports(ModuleManager& module_manager, const ConfigProtocol& config_protocol, const TopModuleNumConfigBits& num_config_bits); +int load_top_module_shift_register_banks_from_fabric_key(const FabricKey& fabric_key, + MemoryBankShiftRegisterBanks& blwl_sr_banks); + +void sync_memory_bank_shift_register_banks_with_config_protocol_settings(ModuleManager& module_manager, + MemoryBankShiftRegisterBanks& blwl_sr_banks, + const ConfigProtocol& config_protocol, + const ModuleId& top_module, + const CircuitLibrary& circuit_lib); } /* end namespace openfpga */ diff --git a/openfpga/src/fabric/memory_bank_shift_register_banks.cpp b/openfpga/src/fabric/memory_bank_shift_register_banks.cpp index 43278f2f5..bdd403ebc 100644 --- a/openfpga/src/fabric/memory_bank_shift_register_banks.cpp +++ b/openfpga/src/fabric/memory_bank_shift_register_banks.cpp @@ -275,12 +275,22 @@ void MemoryBankShiftRegisterBanks::reserve_bl_shift_register_banks(const ConfigR bl_bank_data_ports_[region_id].reserve(num_banks); } +void MemoryBankShiftRegisterBanks::reserve_bl_shift_register_banks(const FabricRegionId& region_id, const size_t& num_banks) { + ConfigRegionId config_region_id = ConfigRegionId(size_t(region_id)); + reserve_bl_shift_register_banks(config_region_id, num_banks); +} + void MemoryBankShiftRegisterBanks::reserve_wl_shift_register_banks(const ConfigRegionId& region_id, const size_t& num_banks) { VTR_ASSERT(valid_region_id(region_id)); wl_bank_ids_[region_id].reserve(num_banks); wl_bank_data_ports_[region_id].reserve(num_banks); } +void MemoryBankShiftRegisterBanks::reserve_wl_shift_register_banks(const FabricRegionId& region_id, const size_t& num_banks) { + ConfigRegionId config_region_id = ConfigRegionId(size_t(region_id)); + reserve_wl_shift_register_banks(config_region_id, num_banks); +} + FabricBitLineBankId MemoryBankShiftRegisterBanks::create_bl_shift_register_bank(const ConfigRegionId& region_id) { VTR_ASSERT(valid_region_id(region_id)); @@ -292,13 +302,30 @@ FabricBitLineBankId MemoryBankShiftRegisterBanks::create_bl_shift_register_bank( return bank; } +FabricBitLineBankId MemoryBankShiftRegisterBanks::create_bl_shift_register_bank(const FabricRegionId& region_id) { + ConfigRegionId config_region_id = ConfigRegionId(size_t(region_id)); + return create_bl_shift_register_bank(config_region_id); +} + +void MemoryBankShiftRegisterBanks::add_data_port_to_bl_shift_register_bank(const FabricRegionId& region_id, + const FabricBitLineBankId& bank_id, + const openfpga::BasicPort& data_port) { + ConfigRegionId config_region_id = ConfigRegionId(size_t(region_id)); + add_data_port_to_bl_shift_register_bank(config_region_id, bank_id, data_port); +} + void MemoryBankShiftRegisterBanks::add_data_port_to_bl_shift_register_bank(const ConfigRegionId& region_id, - const FabricBitLineBankId& bank_id, - const openfpga::BasicPort& data_port) { + const FabricBitLineBankId& bank_id, + const openfpga::BasicPort& data_port) { VTR_ASSERT(valid_bl_bank_id(region_id, bank_id)); bl_bank_data_ports_[region_id][bank_id].push_back(data_port); } +FabricWordLineBankId MemoryBankShiftRegisterBanks::create_wl_shift_register_bank(const FabricRegionId& region_id) { + ConfigRegionId config_region_id = ConfigRegionId(size_t(region_id)); + return create_wl_shift_register_bank(config_region_id); +} + FabricWordLineBankId MemoryBankShiftRegisterBanks::create_wl_shift_register_bank(const ConfigRegionId& region_id) { VTR_ASSERT(valid_region_id(region_id)); @@ -310,14 +337,20 @@ FabricWordLineBankId MemoryBankShiftRegisterBanks::create_wl_shift_register_bank return bank; } +void MemoryBankShiftRegisterBanks::add_data_port_to_wl_shift_register_bank(const FabricRegionId& region_id, + const FabricWordLineBankId& bank_id, + const openfpga::BasicPort& data_port) { + ConfigRegionId config_region_id = ConfigRegionId(size_t(region_id)); + add_data_port_to_wl_shift_register_bank(config_region_id, bank_id, data_port); +} + void MemoryBankShiftRegisterBanks::add_data_port_to_wl_shift_register_bank(const ConfigRegionId& region_id, - const FabricWordLineBankId& bank_id, - const openfpga::BasicPort& data_port) { + const FabricWordLineBankId& bank_id, + const openfpga::BasicPort& data_port) { VTR_ASSERT(valid_wl_bank_id(region_id, bank_id)); wl_bank_data_ports_[region_id][bank_id].push_back(data_port); } - bool MemoryBankShiftRegisterBanks::valid_region_id(const ConfigRegionId& region) const { return size_t(region) < bl_sr_instance_sink_child_ids_.size(); } @@ -336,4 +369,8 @@ bool MemoryBankShiftRegisterBanks::valid_wl_bank_id(const ConfigRegionId& region return ( size_t(bank_id) < wl_bank_ids_[region_id].size() ) && ( bank_id == wl_bank_ids_[region_id][bank_id] ); } +bool MemoryBankShiftRegisterBanks::empty() const { + return bl_bank_ids_.empty() && wl_bank_ids_.empty(); +} + } /* end namespace openfpga */ diff --git a/openfpga/src/fabric/memory_bank_shift_register_banks.h b/openfpga/src/fabric/memory_bank_shift_register_banks.h index 740d2676d..0041df1ac 100644 --- a/openfpga/src/fabric/memory_bank_shift_register_banks.h +++ b/openfpga/src/fabric/memory_bank_shift_register_banks.h @@ -108,21 +108,31 @@ class MemoryBankShiftRegisterBanks { void resize_regions(const size_t& num_regions); /* Reserve a number of banks to be memory efficent */ + void reserve_bl_shift_register_banks(const FabricRegionId& region_id, const size_t& num_banks); void reserve_bl_shift_register_banks(const ConfigRegionId& region_id, const size_t& num_banks); + void reserve_wl_shift_register_banks(const FabricRegionId& region_id, const size_t& num_banks); void reserve_wl_shift_register_banks(const ConfigRegionId& region_id, const size_t& num_banks); /* Create a new shift register bank for BLs and return an id */ + FabricBitLineBankId create_bl_shift_register_bank(const FabricRegionId& region_id); FabricBitLineBankId create_bl_shift_register_bank(const ConfigRegionId& region_id); /* Add a data port to a given BL shift register bank */ + void add_data_port_to_bl_shift_register_bank(const FabricRegionId& region_id, + const FabricBitLineBankId& bank_id, + const openfpga::BasicPort& data_port); void add_data_port_to_bl_shift_register_bank(const ConfigRegionId& region_id, const FabricBitLineBankId& bank_id, const openfpga::BasicPort& data_port); /* Create a new shift register bank for WLs and return an id */ + FabricWordLineBankId create_wl_shift_register_bank(const FabricRegionId& region_id); FabricWordLineBankId create_wl_shift_register_bank(const ConfigRegionId& region_id); /* Add a data port to a given WL shift register bank */ + void add_data_port_to_wl_shift_register_bank(const FabricRegionId& region_id, + const FabricWordLineBankId& bank_id, + const openfpga::BasicPort& data_port); void add_data_port_to_wl_shift_register_bank(const ConfigRegionId& region_id, const FabricWordLineBankId& bank_id, const openfpga::BasicPort& data_port); @@ -167,6 +177,7 @@ class MemoryBankShiftRegisterBanks { bool valid_region_id(const ConfigRegionId& region) const; bool valid_bl_bank_id(const ConfigRegionId& region_id, const FabricBitLineBankId& bank_id) const; bool valid_wl_bank_id(const ConfigRegionId& region_id, const FabricWordLineBankId& bank_id) const; + bool empty() const; private: /* Internal data */ /* General information about the BL shift register bank */