diff --git a/libopenfpga/libarchopenfpga/src/circuit_types.h b/libopenfpga/libarchopenfpga/src/circuit_types.h index f13a8a5ee..3a2604a42 100644 --- a/libopenfpga/libarchopenfpga/src/circuit_types.h +++ b/libopenfpga/libarchopenfpga/src/circuit_types.h @@ -125,10 +125,11 @@ enum e_config_protocol_type { CONFIG_MEM_STANDALONE, CONFIG_MEM_SCAN_CHAIN, CONFIG_MEM_MEMORY_BANK, + CONFIG_MEM_QL_MEMORY_BANK, CONFIG_MEM_FRAME_BASED, NUM_CONFIG_PROTOCOL_TYPES }; -constexpr std::array CONFIG_PROTOCOL_TYPE_STRING = {{"standalone", "scan_chain", "memory_bank", "frame_based"}}; +constexpr std::array CONFIG_PROTOCOL_TYPE_STRING = {{"standalone", "scan_chain", "memory_bank", "ql_memory_bank", "frame_based"}}; #endif diff --git a/openfpga/src/fabric/build_top_module.cpp b/openfpga/src/fabric/build_top_module.cpp index 56b7d4b2b..1066b57bb 100644 --- a/openfpga/src/fabric/build_top_module.cpp +++ b/openfpga/src/fabric/build_top_module.cpp @@ -407,7 +407,7 @@ int build_top_module(ModuleManager& module_manager, * 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 */ - vtr::vector top_module_num_config_bits = find_top_module_regional_num_config_bit(module_manager, top_module, circuit_lib, sram_model, config_protocol.type()); + vtr::vector top_module_num_config_bits = find_top_module_regional_num_config_bit(module_manager, top_module, circuit_lib, sram_model, config_protocol.type()); if (!top_module_num_config_bits.empty()) { add_top_module_sram_ports(module_manager, top_module, diff --git a/openfpga/src/fabric/build_top_module_memory.cpp b/openfpga/src/fabric/build_top_module_memory.cpp index 422a73ff2..44545e608 100644 --- a/openfpga/src/fabric/build_top_module_memory.cpp +++ b/openfpga/src/fabric/build_top_module_memory.cpp @@ -74,8 +74,9 @@ void organize_top_module_tile_cb_modules(ModuleManager& module_manager, if (0 < find_module_num_config_bits(module_manager, cb_module, circuit_lib, sram_model, sram_orgz_type)) { + vtr::Point config_coord(rr_gsb.get_cb_x(cb_type) * 2, rr_gsb.get_cb_y(cb_type) * 2); /* Note that use the original CB coodinate for instance id searching ! */ - module_manager.add_configurable_child(top_module, cb_module, cb_instance_ids[rr_gsb.get_cb_x(cb_type)][rr_gsb.get_cb_y(cb_type)]); + module_manager.add_configurable_child(top_module, cb_module, cb_instance_ids[rr_gsb.get_cb_x(cb_type)][rr_gsb.get_cb_y(cb_type)], config_coord); } } @@ -84,6 +85,37 @@ void organize_top_module_tile_cb_modules(ModuleManager& module_manager, * to the memory modules and memory instances * This function is designed for organizing memory modules in top-level * module + * This function also adds coordindates for each configurable child under the top-level module + * of a FPGA fabric. A configurable child could be a programmable block (grid), + * a Connection Block (CBx/y) or a Switch block (SB). + * This function, we consider a coordinate system as follows + * - Each row may consist of either (1) grid and CBy or (2) CBx and SB + * - Each column may consist of either (1) grid and CBx or (2) CBy and SB + * + * Column 0 Column 1 + * + * +---------------+----------+ + * | | | + * | | | + * | Grid | CBY | Row 3 + * | | | + * | | | + * +---------------+----------+ + * | | | + * | CBX | SB | Row 2 + * | | | + * +---------------+----------+ + * | | | + * | | | + * | Grid | CBY | Row 1 + * | | | + * | | | + * +---------------+----------+ + * | | | + * | CBX | SB | Row 0 + * | | | + * +---------------+----------+ + *******************************************************************/ static void organize_top_module_tile_memory_modules(ModuleManager& module_manager, @@ -130,7 +162,8 @@ void organize_top_module_tile_memory_modules(ModuleManager& module_manager, if (0 < find_module_num_config_bits(module_manager, sb_module, circuit_lib, sram_model, sram_orgz_type)) { - module_manager.add_configurable_child(top_module, sb_module, sb_instance_ids[rr_gsb.get_sb_x()][rr_gsb.get_sb_y()]); + vtr::Point config_coord(rr_gsb.get_sb_x() * 2 + 1, rr_gsb.get_sb_y() * 2 + 1); + module_manager.add_configurable_child(top_module, sb_module, sb_instance_ids[rr_gsb.get_sb_x()][rr_gsb.get_sb_y()], config_coord); } } @@ -172,11 +205,11 @@ void organize_top_module_tile_memory_modules(ModuleManager& module_manager, if (0 < find_module_num_config_bits(module_manager, grid_module, circuit_lib, sram_model, sram_orgz_type)) { - module_manager.add_configurable_child(top_module, grid_module, grid_instance_ids[tile_coord.x()][tile_coord.y()]); + vtr::Point config_coord(tile_coord.x() * 2, tile_coord.y() * 2); + module_manager.add_configurable_child(top_module, grid_module, grid_instance_ids[tile_coord.x()][tile_coord.y()], config_coord); } } - /******************************************************************** * Split memory modules into different configurable regions * This function will create regions based on the definition @@ -496,6 +529,7 @@ void shuffle_top_module_configurable_children(ModuleManager& module_manager, /* Cache the configurable children and their instances */ std::vector orig_configurable_children = module_manager.configurable_children(top_module); std::vector orig_configurable_child_instances = module_manager.configurable_child_instances(top_module); + std::vector> orig_configurable_child_coordinates = module_manager.configurable_child_coordinates(top_module); /* Reorganize the configurable children */ module_manager.clear_configurable_children(top_module); @@ -503,7 +537,8 @@ void shuffle_top_module_configurable_children(ModuleManager& module_manager, for (size_t ikey = 0; ikey < num_keys; ++ikey) { module_manager.add_configurable_child(top_module, orig_configurable_children[shuffled_keys[ikey]], - orig_configurable_child_instances[shuffled_keys[ikey]]); + orig_configurable_child_instances[shuffled_keys[ikey]], + orig_configurable_child_coordinates[shuffled_keys[ikey]]); } /* Reset configurable regions */ @@ -614,13 +649,13 @@ int load_top_module_memory_modules_from_fabric_key(ModuleManager& module_manager * - This function should be called after the configurable children * is loaded to the top-level module! ********************************************************************/ -vtr::vector find_top_module_regional_num_config_bit(const ModuleManager& module_manager, - const ModuleId& top_module, - const CircuitLibrary& circuit_lib, - const CircuitModelId& sram_model, - const e_config_protocol_type& config_protocol_type) { +vtr::vector find_top_module_regional_num_config_bit(const ModuleManager& module_manager, + const ModuleId& top_module, + const CircuitLibrary& circuit_lib, + const CircuitModelId& sram_model, + const e_config_protocol_type& config_protocol_type) { /* Initialize the number of configuration bits for each region */ - vtr::vector num_config_bits(module_manager.regions(top_module).size(), 0); + vtr::vector num_config_bits(module_manager.regions(top_module).size(), TopModuleNumConfigBits(0, 0)); switch (config_protocol_type) { case CONFIG_MEM_STANDALONE: @@ -632,7 +667,36 @@ vtr::vector find_top_module_regional_num_config_bit(cons */ for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { for (const ModuleId& child_module : module_manager.region_configurable_children(top_module, config_region)) { - num_config_bits[config_region] += find_module_num_config_bits(module_manager, child_module, circuit_lib, sram_model, config_protocol_type); + num_config_bits[config_region].first += find_module_num_config_bits(module_manager, child_module, circuit_lib, sram_model, config_protocol_type); + } + } + break; + } + case CONFIG_MEM_QL_MEMORY_BANK: { + /* For QL memory bank: we will use the row and column information for each configuration child + * in order to identify the number of unique BLs and WLs + * In this configuration protocol, + * - all the configurable child in the same row will share the same WLs + * - the number of WLs per row is limited by the configurable child which requires most WLs + * - each row has independent WLs + * - all the configurable child in the same column will share the same BLs + * - the number of BLs per column is limited by the configurable child which requires most BLs + * - each column has independent BLs + */ + for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { + std::map num_bls; + std::map num_wls; + 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 coord = module_manager.region_configurable_child_coordinates(top_module, config_region)[child_id]; + num_bls[coord.x()] = std::max(num_bls[coord.x()], find_module_num_config_bits(module_manager, child_module, circuit_lib, sram_model, config_protocol_type)); + num_wls[coord.y()] = std::max(num_wls[coord.y()], find_module_num_config_bits(module_manager, child_module, circuit_lib, sram_model, config_protocol_type)); + for (const auto& kv : num_bls) { + num_config_bits[config_region].first += kv.first; + } + for (const auto& kv : num_wls) { + num_config_bits[config_region].second += kv.second; + } } } break; @@ -646,14 +710,14 @@ vtr::vector find_top_module_regional_num_config_bit(cons for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { for (const ModuleId& child_module : module_manager.region_configurable_children(top_module, config_region)) { size_t temp_num_config_bits = find_module_num_config_bits(module_manager, child_module, circuit_lib, sram_model, config_protocol_type); - num_config_bits[config_region] = std::max((int)temp_num_config_bits, (int)num_config_bits[config_region]); + num_config_bits[config_region].first = std::max(temp_num_config_bits, num_config_bits[config_region].first); } /* If there are more than 2 configurable children, we need a decoder * Otherwise, we can just short wire the address port to the children */ if (1 < module_manager.region_configurable_children(top_module, config_region).size()) { - num_config_bits[config_region] += find_mux_local_decoder_addr_size(module_manager.region_configurable_children(top_module, config_region).size()); + num_config_bits[config_region].first += find_mux_local_decoder_addr_size(module_manager.region_configurable_children(top_module, config_region).size()); } } @@ -706,34 +770,40 @@ size_t generate_top_module_sram_port_size(const ConfigProtocol& config_protocol, * top-level module * The type and names of added ports strongly depend on the * organization of SRAMs. - * 1. Standalone SRAMs: - * two ports will be added, which are BL and WL - * 2. Scan-chain Flip-flops: - * two ports will be added, which are the head of scan-chain - * and the tail of scan-chain - * IMPORTANT: the port size will be forced to 1 in this case - * because the head and tail are both 1-bit ports!!! - * 3. Memory decoders: - * - An enable signal - * - A BL address port - * - A WL address port - * - A data-in port for the BL decoder - * 4. Frame-based memory: - * - An Enable signal - * - An address port, whose size depends on the number of config bits - * and the maximum size of address ports of configurable children - * - An data_in port (single-bit) + * - Standalone SRAMs: + * two ports will be added, which are BL and WL + * - Scan-chain Flip-flops: + * two ports will be added, which are the head of scan-chain + * and the tail of scan-chain + * IMPORTANT: the port size will be forced to 1 in this case + * because the head and tail are both 1-bit ports!!! + * - Memory decoders: + * - An enable signal + * - A BL address port + * - A WL address port + * - A data-in port for the BL decoder + * - QL memory decoder: + * - An enable signal + * - An BL address port + * - A WL address port + * - A data-in port for the BL decoder + * @note In this memory decoders, the address size will be computed in a different way than the regular one + * - Frame-based memory: + * - An Enable signal + * - An address port, whose size depends on the number of config bits + * and the maximum size of address ports of configurable children + * - An data_in port (single-bit) ********************************************************************/ void add_top_module_sram_ports(ModuleManager& module_manager, const ModuleId& module_id, const CircuitLibrary& circuit_lib, const CircuitModelId& sram_model, const ConfigProtocol& config_protocol, - const vtr::vector& num_config_bits) { + const vtr::vector& num_config_bits) { std::vector sram_port_names = generate_sram_port_names(circuit_lib, sram_model, config_protocol.type()); size_t total_num_config_bits = 0; - for (const size_t& curr_num_config_bits : num_config_bits) { - total_num_config_bits += curr_num_config_bits; + for (const auto& curr_num_config_bits : num_config_bits) { + total_num_config_bits += curr_num_config_bits.first; } size_t sram_port_size = generate_top_module_sram_port_size(config_protocol, total_num_config_bits); @@ -754,7 +824,7 @@ void add_top_module_sram_ports(ModuleManager& module_manager, /* BL address size is the largest among all the regions */ size_t bl_addr_size = 0; for (const ConfigRegionId& config_region : module_manager.regions(module_id)) { - bl_addr_size = std::max(bl_addr_size, find_memory_decoder_addr_size(num_config_bits[config_region])); + bl_addr_size = std::max(bl_addr_size, find_memory_decoder_addr_size(num_config_bits[config_region].first)); } BasicPort bl_addr_port(std::string(DECODER_BL_ADDRESS_PORT_NAME), bl_addr_size); module_manager.add_port(module_id, bl_addr_port, ModuleManager::MODULE_INPUT_PORT); @@ -762,7 +832,33 @@ void add_top_module_sram_ports(ModuleManager& module_manager, /* WL address size is the largest among all the regions */ size_t wl_addr_size = 0; for (const ConfigRegionId& config_region : module_manager.regions(module_id)) { - wl_addr_size = std::max(wl_addr_size, find_memory_decoder_addr_size(num_config_bits[config_region])); + wl_addr_size = std::max(wl_addr_size, find_memory_decoder_addr_size(num_config_bits[config_region].first)); + } + BasicPort wl_addr_port(std::string(DECODER_WL_ADDRESS_PORT_NAME), wl_addr_size); + module_manager.add_port(module_id, wl_addr_port, ModuleManager::MODULE_INPUT_PORT); + + /* Data input should be dependent on the number of configuration regions*/ + BasicPort din_port(std::string(DECODER_DATA_IN_PORT_NAME), config_protocol.num_regions()); + module_manager.add_port(module_id, din_port, ModuleManager::MODULE_INPUT_PORT); + + break; + } + case CONFIG_MEM_QL_MEMORY_BANK: { + BasicPort en_port(std::string(DECODER_ENABLE_PORT_NAME), 1); + module_manager.add_port(module_id, en_port, ModuleManager::MODULE_INPUT_PORT); + + /* BL address size is the largest among all the regions */ + size_t bl_addr_size = 0; + for (const ConfigRegionId& config_region : module_manager.regions(module_id)) { + bl_addr_size = std::max(bl_addr_size, find_memory_decoder_addr_size(num_config_bits[config_region].first)); + } + BasicPort bl_addr_port(std::string(DECODER_BL_ADDRESS_PORT_NAME), bl_addr_size); + module_manager.add_port(module_id, bl_addr_port, ModuleManager::MODULE_INPUT_PORT); + + /* WL address size is the largest among all the regions */ + size_t wl_addr_size = 0; + for (const ConfigRegionId& config_region : module_manager.regions(module_id)) { + wl_addr_size = std::max(wl_addr_size, find_memory_decoder_addr_size(num_config_bits[config_region].second)); } BasicPort wl_addr_port(std::string(DECODER_WL_ADDRESS_PORT_NAME), wl_addr_size); module_manager.add_port(module_id, wl_addr_port, ModuleManager::MODULE_INPUT_PORT); @@ -798,8 +894,8 @@ void add_top_module_sram_ports(ModuleManager& module_manager, module_manager.add_port(module_id, en_port, ModuleManager::MODULE_INPUT_PORT); size_t max_num_config_bits = 0; - for (const size_t& curr_num_config_bits : num_config_bits) { - max_num_config_bits = std::max(max_num_config_bits, curr_num_config_bits); + for (const auto& curr_num_config_bits : num_config_bits) { + max_num_config_bits = std::max(max_num_config_bits, curr_num_config_bits.first); } BasicPort addr_port(std::string(DECODER_ADDRESS_PORT_NAME), max_num_config_bits); @@ -910,7 +1006,7 @@ static void add_top_module_nets_cmos_memory_bank_config_bus(ModuleManager& module_manager, DecoderLibrary& decoder_lib, const ModuleId& top_module, - const vtr::vector& num_config_bits) { + const vtr::vector& num_config_bits) { /* Find Enable port from the top-level module */ ModulePortId en_port = module_manager.find_module_port(top_module, std::string(DECODER_ENABLE_PORT_NAME)); BasicPort en_port_info = module_manager.module_port(top_module, en_port); @@ -935,13 +1031,13 @@ void add_top_module_nets_cmos_memory_bank_config_bus(ModuleManager& module_manag /* Each memory bank has a unified number of BL/WLs */ size_t num_bls = 0; - for (const size_t& curr_config_bits : num_config_bits) { - num_bls = std::max(num_bls, find_memory_decoder_data_size(curr_config_bits)); + for (const auto& curr_config_bits : num_config_bits) { + num_bls = std::max(num_bls, find_memory_decoder_data_size(curr_config_bits.first)); } size_t num_wls = 0; - for (const size_t& curr_config_bits : num_config_bits) { - num_wls = std::max(num_wls, find_memory_decoder_data_size(curr_config_bits)); + for (const auto& curr_config_bits : num_config_bits) { + num_wls = std::max(num_wls, find_memory_decoder_data_size(curr_config_bits.first)); } /* Create separated memory bank circuitry, i.e., BL/WL decoders for each region */ @@ -1582,7 +1678,7 @@ static void add_top_module_nets_cmos_memory_frame_config_bus(ModuleManager& module_manager, DecoderLibrary& decoder_lib, const ModuleId& top_module, - const vtr::vector& num_config_bits) { + const vtr::vector& num_config_bits) { /* Find the number of address bits for the top-level module */ ModulePortId top_addr_port = module_manager.find_module_port(top_module, std::string(DECODER_ADDRESS_PORT_NAME)); BasicPort top_addr_port_info = module_manager.module_port(top_module, top_addr_port); @@ -1598,7 +1694,7 @@ void add_top_module_nets_cmos_memory_frame_config_bus(ModuleManager& module_mana * - The number of address bits of the configurable child is the same as top-level */ if ( (1 == module_manager.region_configurable_children(top_module, config_region).size()) - && (num_config_bits[config_region] == top_addr_size)) { + && (num_config_bits[config_region].first == top_addr_size)) { add_top_module_nets_cmos_memory_frame_short_config_bus(module_manager, top_module, config_region); } else { add_top_module_nets_cmos_memory_frame_decoder_config_bus(module_manager, decoder_lib, top_module, config_region); @@ -1655,7 +1751,7 @@ void add_top_module_nets_cmos_memory_config_bus(ModuleManager& module_manager, DecoderLibrary& decoder_lib, const ModuleId& parent_module, const ConfigProtocol& config_protocol, - const vtr::vector& num_config_bits) { + const vtr::vector& num_config_bits) { switch (config_protocol.type()) { case CONFIG_MEM_STANDALONE: add_module_nets_cmos_flatten_memory_config_bus(module_manager, parent_module, @@ -1717,7 +1813,7 @@ void add_top_module_nets_memory_config_bus(ModuleManager& module_manager, const ModuleId& parent_module, const ConfigProtocol& config_protocol, const e_circuit_model_design_tech& mem_tech, - const vtr::vector& num_config_bits) { + const vtr::vector& num_config_bits) { vtr::ScopedStartFinishTimer timer("Add module nets for configuration buses"); diff --git a/openfpga/src/fabric/build_top_module_memory.h b/openfpga/src/fabric/build_top_module_memory.h index e1d495fd4..d44522ff0 100644 --- a/openfpga/src/fabric/build_top_module_memory.h +++ b/openfpga/src/fabric/build_top_module_memory.h @@ -26,6 +26,8 @@ /* begin namespace openfpga */ namespace openfpga { +typedef std::pair TopModuleNumConfigBits; + void organize_top_module_memory_modules(ModuleManager& module_manager, const ModuleId& top_module, const CircuitLibrary& circuit_lib, @@ -48,25 +50,25 @@ int load_top_module_memory_modules_from_fabric_key(ModuleManager& module_manager const ConfigProtocol& config_protocol, const FabricKey& fabric_key); -vtr::vector find_top_module_regional_num_config_bit(const ModuleManager& module_manager, - const ModuleId& top_module, - const CircuitLibrary& circuit_lib, - const CircuitModelId& sram_model, - const e_config_protocol_type& config_protocol_type); +vtr::vector find_top_module_regional_num_config_bit(const ModuleManager& module_manager, + const ModuleId& top_module, + const CircuitLibrary& circuit_lib, + const CircuitModelId& sram_model, + const e_config_protocol_type& config_protocol_type); void add_top_module_sram_ports(ModuleManager& module_manager, const ModuleId& module_id, const CircuitLibrary& circuit_lib, const CircuitModelId& sram_model, const ConfigProtocol& config_protocol, - const vtr::vector& num_config_bits); + const vtr::vector& num_config_bits); void add_top_module_nets_memory_config_bus(ModuleManager& module_manager, DecoderLibrary& decoder_lib, const ModuleId& parent_module, const ConfigProtocol& config_protocol, const e_circuit_model_design_tech& mem_tech, - const vtr::vector& num_config_bits); + const vtr::vector& num_config_bits); } /* end namespace openfpga */ diff --git a/openfpga/src/fabric/module_manager.cpp b/openfpga/src/fabric/module_manager.cpp index 87fa0ca5c..de5ed0fa6 100644 --- a/openfpga/src/fabric/module_manager.cpp +++ b/openfpga/src/fabric/module_manager.cpp @@ -84,6 +84,13 @@ std::vector ModuleManager::configurable_child_instances(const ModuleId& return configurable_child_instances_[parent_module]; } +std::vector> ModuleManager::configurable_child_coordinates(const ModuleId& parent_module) const { + /* Validate the module_id */ + VTR_ASSERT(valid_module_id(parent_module)); + + return configurable_child_coordinates_[parent_module]; +} + /* Find the source ids of modules */ ModuleManager::module_net_src_range ModuleManager::module_net_sources(const ModuleId& module, const ModuleNetId& net) const { /* Validate the module_id */ @@ -135,6 +142,22 @@ std::vector ModuleManager::region_configurable_child_instances(const Mod return region_config_child_instances; } +std::vector> ModuleManager::region_configurable_child_coordinates(const ModuleId& parent_module, + const ConfigRegionId& region) const { + /* Validate the module_id */ + VTR_ASSERT(valid_module_id(parent_module)); + VTR_ASSERT(valid_region_id(parent_module, region)); + + std::vector> region_config_child_coordinates; + region_config_child_coordinates.reserve(config_region_children_[parent_module][region].size()); + + for (const size_t& child_id : config_region_children_[parent_module][region]) { + region_config_child_coordinates.push_back(configurable_child_coordinates_[parent_module][child_id]); + } + + return region_config_child_coordinates; +} + /****************************************************************************** * Public Accessors ******************************************************************************/ @@ -534,6 +557,7 @@ ModuleId ModuleManager::add_module(const std::string& name) { configurable_children_.emplace_back(); configurable_child_instances_.emplace_back(); configurable_child_regions_.emplace_back(); + configurable_child_coordinates_.emplace_back(); config_region_ids_.emplace_back(); config_region_children_.emplace_back(); @@ -716,7 +740,8 @@ void ModuleManager::set_child_instance_name(const ModuleId& parent_module, */ void ModuleManager::add_configurable_child(const ModuleId& parent_module, const ModuleId& child_module, - const size_t& child_instance) { + const size_t& child_instance, + const vtr::Point coord) { /* Validate the id of both parent and child modules */ VTR_ASSERT ( valid_module_id(parent_module) ); VTR_ASSERT ( valid_module_id(child_module) ); @@ -726,6 +751,7 @@ void ModuleManager::add_configurable_child(const ModuleId& parent_module, configurable_children_[parent_module].push_back(child_module); configurable_child_instances_[parent_module].push_back(child_instance); configurable_child_regions_[parent_module].push_back(ConfigRegionId::INVALID()); + configurable_child_coordinates_[parent_module].push_back(coord); } void ModuleManager::reserve_configurable_child(const ModuleId& parent_module, @@ -738,9 +764,12 @@ void ModuleManager::reserve_configurable_child(const ModuleId& parent_module, if (num_children > configurable_child_instances_[parent_module].size()) { configurable_child_instances_[parent_module].reserve(num_children); } - if (num_children > configurable_child_instances_[parent_module].size()) { + if (num_children > configurable_child_regions_[parent_module].size()) { configurable_child_regions_[parent_module].reserve(num_children); } + if (num_children > configurable_child_coordinates_[parent_module].size()) { + configurable_child_coordinates_[parent_module].reserve(num_children); + } } ConfigRegionId ModuleManager::add_config_region(const ModuleId& module) { @@ -981,6 +1010,7 @@ void ModuleManager::clear_configurable_children(const ModuleId& parent_module) { configurable_children_[parent_module].clear(); configurable_child_instances_[parent_module].clear(); configurable_child_regions_[parent_module].clear(); + configurable_child_coordinates_[parent_module].clear(); } void ModuleManager::clear_config_region(const ModuleId& parent_module) { diff --git a/openfpga/src/fabric/module_manager.h b/openfpga/src/fabric/module_manager.h index d58442c73..3d4405b7a 100644 --- a/openfpga/src/fabric/module_manager.h +++ b/openfpga/src/fabric/module_manager.h @@ -8,6 +8,7 @@ #include #include "vtr_vector.h" +#include "vtr_geometry.h" #include "module_manager_fwd.h" #include "openfpga_port.h" @@ -148,6 +149,8 @@ class ModuleManager { std::vector configurable_children(const ModuleId& parent_module) const; /* Find all the instances of configurable child modules under a parent module */ std::vector configurable_child_instances(const ModuleId& parent_module) const; + /* Find the coordindate of a configurable child module under a parent module */ + std::vector> configurable_child_coordinates(const ModuleId& parent_module) const; /* Find the source ids of modules */ module_net_src_range module_net_sources(const ModuleId& module, const ModuleNetId& net) const; /* Find the sink ids of modules */ @@ -161,6 +164,10 @@ class ModuleManager { /* Find all the instances of configurable child modules under a region of a parent module */ std::vector region_configurable_child_instances(const ModuleId& parent_module, const ConfigRegionId& region) const; + + /* Find all the coordinates of configurable child modules under a region of a parent module */ + std::vector> region_configurable_child_coordinates(const ModuleId& parent_module, + const ConfigRegionId& region) const; public: /* Public accessors */ size_t num_modules() const; @@ -252,8 +259,13 @@ class ModuleManager { void add_child_module(const ModuleId& parent_module, const ModuleId& child_module); /* Set the instance name of a child module */ void set_child_instance_name(const ModuleId& parent_module, const ModuleId& child_module, const size_t& instance_id, const std::string& instance_name); - /* Add a configurable child module to module */ - void add_configurable_child(const ModuleId& module, const ModuleId& child_module, const size_t& child_instance); + /* Add a configurable child module to module + * This function also set the coordinate of a configurable child + * The coordinate is a relative position in each region, which is used to + * idenify BL/WL sharing + * By default, it is an invalid coordinate + */ + void add_configurable_child(const ModuleId& module, const ModuleId& child_module, const size_t& child_instance, const vtr::Point coord = vtr::Point(-1, -1)); /* Reserved a number of configurable children * for memory efficiency */ @@ -350,6 +362,7 @@ class ModuleManager { vtr::vector> configurable_children_; /* Child modules with configurable memory bits that this module contain */ vtr::vector> configurable_child_instances_; /* Instances of child modules with configurable memory bits that this module contain */ vtr::vector> configurable_child_regions_; /* Instances of child modules with configurable memory bits that this module contain */ + vtr::vector>> configurable_child_coordinates_; /* Relative coorindates of child modules with configurable memory bits that this module contain */ /* Configurable regions to group the configurable children * Note: