diff --git a/docs/source/manual/file_formats/tile_config_file.rst b/docs/source/manual/file_formats/tile_config_file.rst new file mode 100644 index 000000000..c3dfcbbce --- /dev/null +++ b/docs/source/manual/file_formats/tile_config_file.rst @@ -0,0 +1,39 @@ +.. _file_formats_tile_config_file: + +Tile Organization (.xml) +------------------------ + +The XML-based description language is used to describe how each tile is composed. +For example, what programmable blocks, connection blocks and switch blocks should be included. + +Using the description language, users can customize the tiles of an FPGA fabric, as detailed as each component in each tile. + +Under the root node ````, the detailes of tile organization can be described. + +.. code-block:: xml + + + + +Syntax +`````` + +Detailed syntax are presented as follows. + +.. option:: style="" + + Specify the style of tile organization. Can be [``top_left`` | ``top_right`` | ``bottom_left`` | ``bottom_right`` | ``custom``] + + .. warning:: Currently, only ``top_left`` is supported! + + The ``top_left`` is a shortcut to define the organization for all the tiles. :numref:`fig_tile_style_top_left` shows an example of tiles in the top-left sytle, where the programmable block locates in the top-left corner of all the tiles, surrounded by two connection blocks and one switch blocks. + +.. _fig_tile_style_top_left: + +.. figure:: ./figures/tile_style_top_left.png + :width: 100% + :alt: An example of top-left style of tile + + An example of top-left style of a tile in FPGA fabric + + diff --git a/docs/source/manual/openfpga_shell/openfpga_commands/figures/group_config_block_hierarchy.png b/docs/source/manual/openfpga_shell/openfpga_commands/figures/group_config_block_hierarchy.png new file mode 100644 index 000000000..e4e3cdcfe Binary files /dev/null and b/docs/source/manual/openfpga_shell/openfpga_commands/figures/group_config_block_hierarchy.png differ diff --git a/docs/source/manual/openfpga_shell/openfpga_commands/figures/group_config_block_overview.png b/docs/source/manual/openfpga_shell/openfpga_commands/figures/group_config_block_overview.png new file mode 100644 index 000000000..44c17a3dc Binary files /dev/null and b/docs/source/manual/openfpga_shell/openfpga_commands/figures/group_config_block_overview.png differ diff --git a/docs/source/manual/openfpga_shell/openfpga_commands/setup_commands.rst b/docs/source/manual/openfpga_shell/openfpga_commands/setup_commands.rst index 7aaa2f7e6..62ec61e21 100644 --- a/docs/source/manual/openfpga_shell/openfpga_commands/setup_commands.rst +++ b/docs/source/manual/openfpga_shell/openfpga_commands/setup_commands.rst @@ -260,7 +260,26 @@ build_fabric .. warning:: This option does not support ``--duplicate_grid_pin``! .. warning:: This option requires ``--compress_routing`` to be enabled! + + .. option:: --group_config_block + + Group configuration memory blocks under each CLB/SB/CB etc. into a centralized configuration memory blocks, as depicted in :numref:`fig_group_config_block_overview`. When disabled, the configuration memory blocks are placed in a distributed way under CLB/SB/CB etc. For example, each programming resource, e.g., LUT, has a dedicated configuration memory block, being placed in the same module. When enabled, as illustrated in :numref:`fig_group_config_block_hierarchy`, the physical memory block locates under a CLB, driving a number of logical memory blocks which are close to the programmable resources. The logical memory blocks contain only pass-through wires which can be optimized out during physical design phase. + + .. _fig_group_config_block_overview: + .. figure:: ./figures/group_config_block_overview.png + :width: 100% + + Impact on grouping configuable blocks: before and after + + .. _fig_group_config_block_hierarchy: + + .. figure:: ./figures/group_config_block_hierarchy.png + :width: 100% + + Netlist hierarchy on grouped configuable blocks + + .. option:: --duplicate_grid_pin Enable pin duplication on grid modules. This is optional unless ultra-dense layout generation is needed diff --git a/libs/libarchopenfpga/src/circuit_types.h b/libs/libarchopenfpga/src/circuit_types.h index 35000d80e..86143bb65 100644 --- a/libs/libarchopenfpga/src/circuit_types.h +++ b/libs/libarchopenfpga/src/circuit_types.h @@ -129,10 +129,13 @@ constexpr std::array /******************************************************************** * Types of configuration protocol - * 1. configurable memories are organized and accessed as standalone elements - * 2. configurable memories are organized and accessed by a scan-chain - * 3. configurable memories are organized and accessed by memory bank - * 4. configurable memories are organized and accessed by frames + * - configurable memories are organized and accessed as standalone elements + * - configurable memories are organized and accessed by a scan-chain + * - configurable memories are organized and accessed by quicklogic memory bank + * - configurable memories are organized and accessed by memory bank + * - configurable memories are organized and accessed by frames + * - configurable memories are organized and accessed by feedthrough. Currently, + * this is only for internal use only */ enum e_config_protocol_type { CONFIG_MEM_STANDALONE, @@ -140,11 +143,13 @@ enum e_config_protocol_type { CONFIG_MEM_MEMORY_BANK, CONFIG_MEM_QL_MEMORY_BANK, CONFIG_MEM_FRAME_BASED, + CONFIG_MEM_FEEDTHROUGH, NUM_CONFIG_PROTOCOL_TYPES }; constexpr std::array CONFIG_PROTOCOL_TYPE_STRING = {{"standalone", "scan_chain", "memory_bank", - "ql_memory_bank", "frame_based"}}; + "ql_memory_bank", "frame_based", + "feedthrough"}}; #endif diff --git a/libs/libopenfpgautil/src/openfpga_reserved_words.h b/libs/libopenfpgautil/src/openfpga_reserved_words.h index f06ed9c66..3317b12ff 100644 --- a/libs/libopenfpgautil/src/openfpga_reserved_words.h +++ b/libs/libopenfpgautil/src/openfpga_reserved_words.h @@ -41,6 +41,11 @@ constexpr const char* GRID_MEM_INSTANCE_PREFIX = "mem_"; constexpr const char* SWITCH_BLOCK_MEM_INSTANCE_PREFIX = "mem_"; constexpr const char* CONNECTION_BLOCK_MEM_INSTANCE_PREFIX = "mem_"; constexpr const char* MEMORY_MODULE_POSTFIX = "_mem"; +constexpr const char* MEMORY_FEEDTHROUGH_MODULE_POSTFIX = "_feedthrough_mem"; +constexpr const char* MEMORY_FEEDTHROUGH_DATA_IN_PORT_NAME = + "feedthrough_mem_in"; +constexpr const char* MEMORY_FEEDTHROUGH_DATA_IN_INV_PORT_NAME = + "feedthrough_mem_inb"; constexpr const char* MEMORY_BL_PORT_NAME = "bl"; constexpr const char* MEMORY_WL_PORT_NAME = "wl"; constexpr const char* MEMORY_WLR_PORT_NAME = "wlr"; diff --git a/openfpga/src/base/openfpga_build_fabric_template.h b/openfpga/src/base/openfpga_build_fabric_template.h index 31e9c565a..453c4c3b2 100644 --- a/openfpga/src/base/openfpga_build_fabric_template.h +++ b/openfpga/src/base/openfpga_build_fabric_template.h @@ -100,6 +100,7 @@ int build_fabric_template(T& openfpga_ctx, const Command& cmd, CommandOptionId opt_write_fabric_key = cmd.option("write_fabric_key"); CommandOptionId opt_load_fabric_key = cmd.option("load_fabric_key"); CommandOptionId opt_group_tile = cmd.option("group_tile"); + CommandOptionId opt_group_config_block = cmd.option("group_config_block"); CommandOptionId opt_verbose = cmd.option("verbose"); /* Report conflicts with options: @@ -175,6 +176,7 @@ int build_fabric_template(T& openfpga_ctx, const Command& cmd, cmd_context.option_enable(cmd, opt_compress_routing), cmd_context.option_enable(cmd, opt_duplicate_grid_pin), predefined_fabric_key, tile_config, + cmd_context.option_enable(cmd, opt_group_config_block), cmd_context.option_enable(cmd, opt_gen_random_fabric_key), cmd_context.option_enable(cmd, opt_verbose)); diff --git a/openfpga/src/base/openfpga_naming.cpp b/openfpga/src/base/openfpga_naming.cpp index 784f51685..1623df96f 100644 --- a/openfpga/src/base/openfpga_naming.cpp +++ b/openfpga/src/base/openfpga_naming.cpp @@ -225,12 +225,18 @@ std::string generate_segment_wire_mid_output_name( /********************************************************************* * Generate the module name for a memory sub-circuit + * If this is a module just to feed through memory lines, use a special name ********************************************************************/ std::string generate_memory_module_name(const CircuitLibrary& circuit_lib, const CircuitModelId& circuit_model, const CircuitModelId& sram_model, - const std::string& postfix) { - return std::string(circuit_lib.model_name(circuit_model) + "_" + + const std::string& postfix, + const bool& feedthrough_memory) { + std::string mid_name; + if (feedthrough_memory) { + mid_name = "feedthrough_"; + } + return std::string(circuit_lib.model_name(circuit_model) + "_" + mid_name + circuit_lib.model_name(sram_model) + postfix); } @@ -522,6 +528,15 @@ std::string generate_tile_module_netlist_name(const std::string& block_name, return block_name + postfix; } +/********************************************************************* + * Generate the module name of a physical memory module + **********************************************************************/ +std::string generate_physical_memory_module_name(const std::string& prefix, + const size_t& mem_size) { + return prefix + std::string("_config_group_mem_size") + + std::to_string(mem_size); +} + /********************************************************************* * Generate the module name for a connection block with a given coordinate *********************************************************************/ @@ -734,6 +749,26 @@ std::string generate_sram_port_name( std::string port_name; switch (sram_orgz_type) { + case CONFIG_MEM_FEEDTHROUGH: + /* Two types of ports are available: + * (1) BL indicates the mem port + * (2) BLB indicates the inverted mem port + * + * mem mem_inv + * [0] [0] + * | | + * v v + * +----------------+ + * | Virtual Mem | + * +----------------+ + */ + if (CIRCUIT_MODEL_PORT_BL == port_type) { + port_name = std::string(MEMORY_FEEDTHROUGH_DATA_IN_PORT_NAME); + } else { + VTR_ASSERT(CIRCUIT_MODEL_PORT_BLB == port_type); + port_name = std::string(MEMORY_FEEDTHROUGH_DATA_IN_INV_PORT_NAME); + } + break; case CONFIG_MEM_SCAN_CHAIN: /* Two types of ports are available: * (1) Head of a chain of Configuration-chain Flip-Flops (CCFFs), enabled @@ -1065,8 +1100,12 @@ std::string generate_sb_mux_instance_name(const std::string& prefix, std::string generate_sb_memory_instance_name(const std::string& prefix, const e_side& sb_side, const size_t& track_id, - const std::string& postfix) { + const std::string& postfix, + const bool& feedthrough_memory) { std::string instance_name(prefix); + if (feedthrough_memory) { + instance_name = std::string("feedthrough_") + instance_name; + } instance_name += SideManager(sb_side).to_string(); instance_name += std::string("_track_") + std::to_string(track_id); instance_name += postfix; @@ -1103,8 +1142,12 @@ std::string generate_cb_mux_instance_name(const std::string& prefix, std::string generate_cb_memory_instance_name(const std::string& prefix, const e_side& cb_side, const size_t& pin_id, - const std::string& postfix) { + const std::string& postfix, + const bool& feedthrough_memory) { std::string instance_name(prefix); + if (feedthrough_memory) { + instance_name = std::string("feedthrough_") + instance_name; + } instance_name += SideManager(cb_side).to_string(); instance_name += std::string("_ipin_") + std::to_string(pin_id); @@ -1159,8 +1202,10 @@ std::string generate_pb_mux_instance_name(const std::string& prefix, ********************************************************************/ std::string generate_pb_memory_instance_name(const std::string& prefix, t_pb_graph_pin* pb_graph_pin, - const std::string& postfix) { - std::string instance_name(prefix); + const std::string& postfix, + const bool& feedthrough_memory) { + std::string mid_name = feedthrough_memory ? "virtual_" : ""; + std::string instance_name(mid_name + prefix); instance_name += std::string(pb_graph_pin->parent_node->pb_type->name); if (IN_PORT == pb_graph_pin->port->type) { diff --git a/openfpga/src/base/openfpga_naming.h b/openfpga/src/base/openfpga_naming.h index 389e4c951..4a1d35e8e 100644 --- a/openfpga/src/base/openfpga_naming.h +++ b/openfpga/src/base/openfpga_naming.h @@ -68,7 +68,8 @@ std::string generate_segment_wire_mid_output_name( std::string generate_memory_module_name(const CircuitLibrary& circuit_lib, const CircuitModelId& circuit_model, const CircuitModelId& sram_model, - const std::string& postfix); + const std::string& postfix, + const bool& feedthrough_memory = false); std::string generate_routing_block_netlist_name(const std::string& prefix, const size_t& block_id, @@ -118,33 +119,34 @@ std::string generate_tile_module_port_name(const std::string& prefix, std::string generate_tile_module_netlist_name(const std::string& block_name, const std::string& postfix); +std::string generate_physical_memory_module_name(const std::string& prefix, + const size_t& mem_size); + std::string generate_sb_mux_instance_name(const std::string& prefix, const e_side& sb_side, const size_t& track_id, const std::string& postfix); -std::string generate_sb_memory_instance_name(const std::string& prefix, - const e_side& sb_side, - const size_t& track_id, - const std::string& postfix); +std::string generate_sb_memory_instance_name( + const std::string& prefix, const e_side& sb_side, const size_t& track_id, + const std::string& postfix, const bool& feedthrough_memory = false); std::string generate_cb_mux_instance_name(const std::string& prefix, const e_side& cb_side, const size_t& pin_id, const std::string& postfix); -std::string generate_cb_memory_instance_name(const std::string& prefix, - const e_side& cb_side, - const size_t& pin_id, - const std::string& postfix); +std::string generate_cb_memory_instance_name( + const std::string& prefix, const e_side& cb_side, const size_t& pin_id, + const std::string& postfix, const bool& feedthrough_memory = false); std::string generate_pb_mux_instance_name(const std::string& prefix, t_pb_graph_pin* pb_graph_pin, const std::string& postfix); -std::string generate_pb_memory_instance_name(const std::string& prefix, - t_pb_graph_pin* pb_graph_pin, - const std::string& postfix); +std::string generate_pb_memory_instance_name( + const std::string& prefix, t_pb_graph_pin* pb_graph_pin, + const std::string& postfix, const bool& feedthrough_memory = false); std::string generate_grid_port_name(const size_t& width, const size_t& height, const int& subtile_index, diff --git a/openfpga/src/base/openfpga_setup_command_template.h b/openfpga/src/base/openfpga_setup_command_template.h index 12d34c00d..55b0ae52f 100644 --- a/openfpga/src/base/openfpga_setup_command_template.h +++ b/openfpga/src/base/openfpga_setup_command_template.h @@ -412,6 +412,13 @@ ShellCommandId add_build_fabric_command_template( "reduce the number of blocks at top-level"); shell_cmd.set_option_require_value(opt_group_tile, openfpga::OPT_STRING); + /* Add an option '--group_config_block' */ + shell_cmd.add_option("group_config_block", false, + "group configuration memory blocks under CLB/SB/CB " + "blocks etc. This helps to " + "reduce optimize the density of configuration memory " + "through physical design"); + /* Add an option '--generate_random_fabric_key' */ shell_cmd.add_option("generate_random_fabric_key", false, "Create a random fabric key which will shuffle the " diff --git a/openfpga/src/fabric/build_device_module.cpp b/openfpga/src/fabric/build_device_module.cpp index b4d9cb222..e20413f3e 100644 --- a/openfpga/src/fabric/build_device_module.cpp +++ b/openfpga/src/fabric/build_device_module.cpp @@ -37,8 +37,8 @@ int build_device_module_graph( const OpenfpgaContext& openfpga_ctx, const DeviceContext& vpr_device_ctx, const bool& frame_view, const bool& compress_routing, const bool& duplicate_grid_pin, const FabricKey& fabric_key, - const TileConfig& tile_config, const bool& generate_random_fabric_key, - const bool& verbose) { + const TileConfig& tile_config, const bool& group_config_block, + const bool& generate_random_fabric_key, const bool& verbose) { vtr::ScopedStartFinishTimer timer("Build fabric module graph"); int status = CMD_EXEC_SUCCESS; @@ -78,28 +78,34 @@ int build_device_module_graph( /* Build memory modules */ build_memory_modules(module_manager, decoder_lib, openfpga_ctx.mux_lib(), openfpga_ctx.arch().circuit_lib, - openfpga_ctx.arch().config_protocol.type()); + openfpga_ctx.arch().config_protocol.type(), + group_config_block, verbose); /* Build grid and programmable block modules */ - build_grid_modules(module_manager, decoder_lib, vpr_device_ctx, - openfpga_ctx.vpr_device_annotation(), - openfpga_ctx.arch().circuit_lib, openfpga_ctx.mux_lib(), - openfpga_ctx.arch().config_protocol.type(), sram_model, - duplicate_grid_pin, verbose); + status = build_grid_modules( + module_manager, decoder_lib, vpr_device_ctx, + openfpga_ctx.vpr_device_annotation(), openfpga_ctx.arch().circuit_lib, + openfpga_ctx.mux_lib(), openfpga_ctx.arch().config_protocol.type(), + sram_model, duplicate_grid_pin, group_config_block, verbose); + if (CMD_EXEC_FATAL_ERROR == status) { + return status; + } if (true == compress_routing) { - build_unique_routing_modules( - module_manager, decoder_lib, vpr_device_ctx, - openfpga_ctx.vpr_device_annotation(), openfpga_ctx.device_rr_gsb(), - openfpga_ctx.arch().circuit_lib, - openfpga_ctx.arch().config_protocol.type(), sram_model, verbose); + build_unique_routing_modules(module_manager, decoder_lib, vpr_device_ctx, + openfpga_ctx.vpr_device_annotation(), + openfpga_ctx.device_rr_gsb(), + openfpga_ctx.arch().circuit_lib, + openfpga_ctx.arch().config_protocol.type(), + sram_model, group_config_block, verbose); } else { VTR_ASSERT_SAFE(false == compress_routing); - build_flatten_routing_modules( - module_manager, decoder_lib, vpr_device_ctx, - openfpga_ctx.vpr_device_annotation(), openfpga_ctx.device_rr_gsb(), - openfpga_ctx.arch().circuit_lib, - openfpga_ctx.arch().config_protocol.type(), sram_model, verbose); + build_flatten_routing_modules(module_manager, decoder_lib, vpr_device_ctx, + openfpga_ctx.vpr_device_annotation(), + openfpga_ctx.device_rr_gsb(), + openfpga_ctx.arch().circuit_lib, + openfpga_ctx.arch().config_protocol.type(), + sram_model, group_config_block, verbose); } /* Build tile modules if defined */ @@ -128,7 +134,7 @@ int build_device_module_graph( openfpga_ctx.device_rr_gsb(), openfpga_ctx.tile_direct(), openfpga_ctx.arch().arch_direct, openfpga_ctx.arch().config_protocol, sram_model, fabric_tile, frame_view, compress_routing, duplicate_grid_pin, - fabric_key, generate_random_fabric_key, verbose); + fabric_key, generate_random_fabric_key, group_config_block, verbose); if (CMD_EXEC_FATAL_ERROR == status) { return status; diff --git a/openfpga/src/fabric/build_device_module.h b/openfpga/src/fabric/build_device_module.h index 6244fc7dd..fb4178cc8 100644 --- a/openfpga/src/fabric/build_device_module.h +++ b/openfpga/src/fabric/build_device_module.h @@ -24,8 +24,8 @@ int build_device_module_graph( const OpenfpgaContext& openfpga_ctx, const DeviceContext& vpr_device_ctx, const bool& frame_view, const bool& compress_routing, const bool& duplicate_grid_pin, const FabricKey& fabric_key, - const TileConfig& tile_config, const bool& generate_random_fabric_key, - const bool& verbose); + const TileConfig& tile_config, const bool& group_config_block, + const bool& generate_random_fabric_key, const bool& verbose); } /* end namespace openfpga */ diff --git a/openfpga/src/fabric/build_fpga_core_wrapper_module.cpp b/openfpga/src/fabric/build_fpga_core_wrapper_module.cpp index 4c3ea3257..d8af89dc5 100644 --- a/openfpga/src/fabric/build_fpga_core_wrapper_module.cpp +++ b/openfpga/src/fabric/build_fpga_core_wrapper_module.cpp @@ -381,7 +381,8 @@ int add_fpga_core_to_device_module_graph(ModuleManager& module_manager, /* Now fpga_core should be the only configurable child under the top-level * module */ - module_manager.add_configurable_child(new_top_module, top_module, 0); + module_manager.add_configurable_child( + new_top_module, top_module, 0, ModuleManager::e_config_child_type::UNIFIED); return status; } diff --git a/openfpga/src/fabric/build_grid_modules.cpp b/openfpga/src/fabric/build_grid_modules.cpp index f724abd66..bf8ca86ac 100644 --- a/openfpga/src/fabric/build_grid_modules.cpp +++ b/openfpga/src/fabric/build_grid_modules.cpp @@ -6,6 +6,7 @@ #include /* Headers from vtrutil library */ +#include "command_exit_codes.h" #include "vtr_assert.h" #include "vtr_geometry.h" #include "vtr_log.h" @@ -15,6 +16,7 @@ #include "build_grid_module_duplicated_pins.h" #include "build_grid_module_utils.h" #include "build_grid_modules.h" +#include "build_memory_modules.h" #include "circuit_library_utils.h" #include "module_manager_utils.h" #include "openfpga_interconnect_types.h" @@ -265,7 +267,7 @@ static void build_primitive_block_module( const CircuitLibrary& circuit_lib, const e_config_protocol_type& sram_orgz_type, const CircuitModelId& sram_model, t_pb_graph_node* primitive_pb_graph_node, - const bool& verbose) { + const bool& group_config_block, const bool& verbose) { /* Ensure a valid pb_graph_node */ VTR_ASSERT(nullptr != primitive_pb_graph_node); @@ -277,7 +279,8 @@ static void build_primitive_block_module( std::string primitive_module_name = generate_physical_block_module_name(primitive_pb_graph_node->pb_type); - VTR_LOGV(verbose, "Building module '%s'...", primitive_module_name.c_str()); + VTR_LOGV(verbose, "Building primitive module '%s'...\n", + primitive_module_name.c_str()); /* Create a module of the primitive LUT and register it to module manager */ ModuleId primitive_module = module_manager.add_module(primitive_module_name); @@ -310,11 +313,13 @@ static void build_primitive_block_module( } /* Regular (independent) SRAM ports */ + e_config_protocol_type mem_module_type = + group_config_block ? CONFIG_MEM_FEEDTHROUGH : sram_orgz_type; size_t num_config_bits = - find_circuit_num_config_bits(sram_orgz_type, circuit_lib, primitive_model); + find_circuit_num_config_bits(mem_module_type, circuit_lib, primitive_model); if (0 < num_config_bits) { add_sram_ports_to_module_manager(module_manager, primitive_module, - circuit_lib, sram_model, sram_orgz_type, + circuit_lib, sram_model, mem_module_type, num_config_bits); } @@ -333,9 +338,9 @@ static void build_primitive_block_module( circuit_lib, primitive_pb_graph_node->pb_type, device_annotation); /* Add the associated memory module as a child of primitive module */ - std::string memory_module_name = - generate_memory_module_name(circuit_lib, primitive_model, sram_model, - std::string(MEMORY_MODULE_POSTFIX)); + std::string memory_module_name = generate_memory_module_name( + circuit_lib, primitive_model, sram_model, + std::string(MEMORY_MODULE_POSTFIX), group_config_block); ModuleId memory_module = module_manager.find_module(memory_module_name); /* If there is no memory module required, we can skip the assocated net @@ -355,18 +360,41 @@ static void build_primitive_block_module( module_manager, primitive_module, logic_module, logic_instance_id, memory_module, memory_instance_id, circuit_lib, primitive_model); /* Record memory-related information */ - module_manager.add_configurable_child(primitive_module, memory_module, - memory_instance_id); + size_t config_child_id = module_manager.num_configurable_children( + primitive_module, ModuleManager::e_config_child_type::LOGICAL); + module_manager.add_configurable_child( + primitive_module, memory_module, memory_instance_id, + group_config_block ? ModuleManager::e_config_child_type::LOGICAL + : ModuleManager::e_config_child_type::UNIFIED); + /* For logical memory, define the physical memory here */ + if (group_config_block) { + std::string physical_memory_module_name = + generate_memory_module_name(circuit_lib, primitive_model, sram_model, + std::string(MEMORY_MODULE_POSTFIX), false); + ModuleId physical_memory_module = + module_manager.find_module(physical_memory_module_name); + VTR_LOGV(verbose, + "Mapping feedthrough memory module '%s' to physical memory " + "module '%s'...\n", + memory_module_name.c_str(), physical_memory_module_name.c_str()); + VTR_ASSERT(module_manager.valid_module_id(physical_memory_module)); + module_manager.set_logical2physical_configurable_child( + primitive_module, config_child_id, physical_memory_module); + module_manager.set_logical2physical_configurable_child_instance_name( + primitive_module, config_child_id, physical_memory_module_name); + } } /* Add all the nets to connect configuration ports from memory module to * primitive modules This is a one-shot addition that covers all the memory * modules in this primitive module! */ - if (0 < module_manager.configurable_children(primitive_module).size()) { - add_module_nets_memory_config_bus(module_manager, decoder_lib, - primitive_module, sram_orgz_type, - circuit_lib.design_tech_type(sram_model)); + if (0 < module_manager.num_configurable_children( + primitive_module, ModuleManager::e_config_child_type::LOGICAL)) { + add_module_nets_memory_config_bus( + module_manager, decoder_lib, primitive_module, mem_module_type, + circuit_lib.design_tech_type(sram_model), + ModuleManager::e_config_child_type::LOGICAL); } /* Add global ports to the pb_module: @@ -504,7 +532,7 @@ static void add_module_pb_graph_pin_interc( std::vector& memory_modules, std::vector& memory_instances, const VprDeviceAnnotation& device_annotation, const CircuitLibrary& circuit_lib, t_pb_graph_pin* des_pb_graph_pin, - t_mode* physical_mode) { + t_mode* physical_mode, const bool& group_config_block, const bool& verbose) { /* Find the number of fan-in and detailed interconnection information * related to the destination pb_graph_pin */ @@ -628,6 +656,11 @@ static void add_module_pb_graph_pin_interc( std::string mux_mem_module_name = generate_mux_subckt_name(circuit_lib, interc_circuit_model, fan_in, std::string(MEMORY_MODULE_POSTFIX)); + if (group_config_block) { + mux_mem_module_name = generate_mux_subckt_name( + circuit_lib, interc_circuit_model, fan_in, + std::string(MEMORY_FEEDTHROUGH_MODULE_POSTFIX)); + } ModuleId mux_mem_module = module_manager.find_module(mux_mem_module_name); VTR_ASSERT(true == module_manager.valid_module_id(mux_mem_module)); size_t mux_mem_instance = @@ -638,12 +671,38 @@ static void add_module_pb_graph_pin_interc( * generation to modules */ std::string mux_mem_instance_name = generate_pb_memory_instance_name( - GRID_MEM_INSTANCE_PREFIX, des_pb_graph_pin, std::string("")); + GRID_MEM_INSTANCE_PREFIX, des_pb_graph_pin, std::string(""), + group_config_block); module_manager.set_child_instance_name( pb_module, mux_mem_module, mux_mem_instance, mux_mem_instance_name); /* Add this MUX as a configurable child to the pb_module */ - module_manager.add_configurable_child(pb_module, mux_mem_module, - mux_mem_instance); + size_t config_child_id = module_manager.num_configurable_children( + pb_module, ModuleManager::e_config_child_type::LOGICAL); + module_manager.add_configurable_child( + pb_module, mux_mem_module, mux_mem_instance, + group_config_block ? ModuleManager::e_config_child_type::LOGICAL + : ModuleManager::e_config_child_type::UNIFIED); + if (group_config_block) { + std::string phy_mem_module_name = + generate_mux_subckt_name(circuit_lib, interc_circuit_model, fan_in, + std::string(MEMORY_MODULE_POSTFIX)); + ModuleId phy_mem_module = + module_manager.find_module(phy_mem_module_name); + VTR_ASSERT(module_manager.valid_module_id(phy_mem_module)); + VTR_LOGV(verbose, + "Mapping feedthrough memory module '%s' to physical memory " + "module '%s'...\n", + mux_mem_module_name.c_str(), phy_mem_module_name.c_str()); + module_manager.set_logical2physical_configurable_child( + pb_module, config_child_id, phy_mem_module); + std::string phy_mux_mem_instance_name = + generate_pb_memory_instance_name( + GRID_MEM_INSTANCE_PREFIX, des_pb_graph_pin, std::string(""), false); + module_manager.set_logical2physical_configurable_child_instance_name( + pb_module, config_child_id, phy_mux_mem_instance_name); + VTR_LOGV(verbose, "Now use a feedthrough memory for '%s'\n", + phy_mem_module_name.c_str()); + } /* Add nets to connect SRAM ports of the MUX to the SRAM port of memory * module */ @@ -732,7 +791,8 @@ static void add_module_pb_graph_port_interc( std::vector& memory_modules, std::vector& memory_instances, const VprDeviceAnnotation& device_annotation, const CircuitLibrary& circuit_lib, t_pb_graph_node* des_pb_graph_node, - const e_circuit_pb_port_type& pb_port_type, t_mode* physical_mode) { + const e_circuit_pb_port_type& pb_port_type, t_mode* physical_mode, + const bool& group_config_block, const bool& verbose) { switch (pb_port_type) { case CIRCUIT_PB_PORT_INPUT: { for (int iport = 0; iport < des_pb_graph_node->num_input_ports; ++iport) { @@ -742,7 +802,8 @@ static void add_module_pb_graph_port_interc( add_module_pb_graph_pin_interc( module_manager, pb_module, memory_modules, memory_instances, device_annotation, circuit_lib, - &(des_pb_graph_node->input_pins[iport][ipin]), physical_mode); + &(des_pb_graph_node->input_pins[iport][ipin]), physical_mode, + group_config_block, verbose); } } break; @@ -755,7 +816,8 @@ static void add_module_pb_graph_port_interc( add_module_pb_graph_pin_interc( module_manager, pb_module, memory_modules, memory_instances, device_annotation, circuit_lib, - &(des_pb_graph_node->output_pins[iport][ipin]), physical_mode); + &(des_pb_graph_node->output_pins[iport][ipin]), physical_mode, + group_config_block, verbose); } } break; @@ -767,7 +829,8 @@ static void add_module_pb_graph_port_interc( add_module_pb_graph_pin_interc( module_manager, pb_module, memory_modules, memory_instances, device_annotation, circuit_lib, - &(des_pb_graph_node->clock_pins[iport][ipin]), physical_mode); + &(des_pb_graph_node->clock_pins[iport][ipin]), physical_mode, + group_config_block, verbose); } } break; @@ -814,7 +877,8 @@ static void add_module_pb_graph_interc( std::vector& memory_modules, std::vector& memory_instances, const VprDeviceAnnotation& device_annotation, const CircuitLibrary& circuit_lib, t_pb_graph_node* physical_pb_graph_node, - const int& physical_mode_index) { + const int& physical_mode_index, const bool& group_config_block, + const bool& verbose) { /* Check cur_pb_graph_node*/ VTR_ASSERT(nullptr != physical_pb_graph_node); @@ -830,10 +894,10 @@ static void add_module_pb_graph_interc( * | * input_pins, edges, output_pins */ - add_module_pb_graph_port_interc(module_manager, pb_module, memory_modules, - memory_instances, device_annotation, - circuit_lib, physical_pb_graph_node, - CIRCUIT_PB_PORT_OUTPUT, physical_mode); + add_module_pb_graph_port_interc( + module_manager, pb_module, memory_modules, memory_instances, + device_annotation, circuit_lib, physical_pb_graph_node, + CIRCUIT_PB_PORT_OUTPUT, physical_mode, group_config_block, verbose); /* We check input_pins of child_pb_graph_node and its the input_edges * Built the interconnections between inputs of cur_pb_graph_node and inputs @@ -856,16 +920,16 @@ static void add_module_pb_graph_interc( &(physical_pb_graph_node ->child_pb_graph_nodes[physical_mode_index][child][inst]); /* For each child_pb_graph_node input pins*/ - add_module_pb_graph_port_interc(module_manager, pb_module, memory_modules, - memory_instances, device_annotation, - circuit_lib, child_pb_graph_node, - CIRCUIT_PB_PORT_INPUT, physical_mode); + add_module_pb_graph_port_interc( + module_manager, pb_module, memory_modules, memory_instances, + device_annotation, circuit_lib, child_pb_graph_node, + CIRCUIT_PB_PORT_INPUT, physical_mode, group_config_block, verbose); /* For each child_pb_graph_node clock pins*/ - add_module_pb_graph_port_interc(module_manager, pb_module, memory_modules, - memory_instances, device_annotation, - circuit_lib, child_pb_graph_node, - CIRCUIT_PB_PORT_CLOCK, physical_mode); + add_module_pb_graph_port_interc( + module_manager, pb_module, memory_modules, memory_instances, + device_annotation, circuit_lib, child_pb_graph_node, + CIRCUIT_PB_PORT_CLOCK, physical_mode, group_config_block, verbose); } } } @@ -892,7 +956,7 @@ static void rec_build_logical_tile_modules( const CircuitLibrary& circuit_lib, const MuxLibrary& mux_lib, const e_config_protocol_type& sram_orgz_type, const CircuitModelId& sram_model, t_pb_graph_node* physical_pb_graph_node, - const bool& verbose) { + const bool& group_config_block, const bool& verbose) { /* Check cur_pb_graph_node*/ VTR_ASSERT(nullptr != physical_pb_graph_node); @@ -913,7 +977,7 @@ static void rec_build_logical_tile_modules( sram_orgz_type, sram_model, &(physical_pb_graph_node ->child_pb_graph_nodes[physical_mode->index][ipb][0]), - verbose); + group_config_block, verbose); } } @@ -921,7 +985,8 @@ static void rec_build_logical_tile_modules( if (true == is_primitive_pb_type(physical_pb_type)) { build_primitive_block_module(module_manager, decoder_lib, device_annotation, circuit_lib, sram_orgz_type, sram_model, - physical_pb_graph_node, verbose); + physical_pb_graph_node, group_config_block, + verbose); /* Finish for primitive node, return */ return; } @@ -930,7 +995,7 @@ static void rec_build_logical_tile_modules( std::string pb_module_name = generate_physical_block_module_name(physical_pb_type); - VTR_LOGV(verbose, "Building module '%s'...", pb_module_name.c_str()); + VTR_LOGV(verbose, "Building module '%s'...\n", pb_module_name.c_str()); /* Register the Verilog module in module manager */ ModuleId pb_module = module_manager.add_module(pb_module_name); @@ -949,6 +1014,9 @@ static void rec_build_logical_tile_modules( std::vector memory_modules; std::vector memory_instances; + e_config_protocol_type mem_module_type = + group_config_block ? CONFIG_MEM_FEEDTHROUGH : sram_orgz_type; + /* Add all the child Verilog modules as instances */ for (int ichild = 0; ichild < physical_mode->num_pb_type_children; ++ichild) { /* Get the name and module id for this child pb_type */ @@ -986,14 +1054,19 @@ static void rec_build_logical_tile_modules( module_manager.set_child_instance_name( pb_module, child_pb_module, child_instance_id, child_pb_instance_name); + VTR_LOGV(verbose, "Building instance '%s'\n", + child_pb_instance_name.c_str()); + /* Identify if this sub module includes configuration bits, * we will update the memory module and instance list */ if (0 < find_module_num_config_bits(module_manager, child_pb_module, circuit_lib, sram_model, - sram_orgz_type)) { - module_manager.add_configurable_child(pb_module, child_pb_module, - child_instance_id); + mem_module_type)) { + module_manager.add_configurable_child( + pb_module, child_pb_module, child_instance_id, + group_config_block ? ModuleManager::e_config_child_type::LOGICAL + : ModuleManager::e_config_child_type::UNIFIED); } } } @@ -1001,9 +1074,11 @@ static void rec_build_logical_tile_modules( /* Add modules and nets for programmable/non-programmable interconnections * inside the Verilog module */ + VTR_LOGV(verbose, "Building local interconnecting modules\n"); add_module_pb_graph_interc(module_manager, pb_module, memory_modules, memory_instances, device_annotation, circuit_lib, - physical_pb_graph_node, physical_mode->index); + physical_pb_graph_node, physical_mode->index, + group_config_block, verbose); /* Add global ports to the pb_module: * This is a much easier job after adding sub modules (instances), @@ -1039,10 +1114,11 @@ static void rec_build_logical_tile_modules( */ size_t module_num_config_bits = find_module_num_config_bits_from_child_modules( - module_manager, pb_module, circuit_lib, sram_model, sram_orgz_type); + module_manager, pb_module, circuit_lib, sram_model, mem_module_type, + ModuleManager::e_config_child_type::LOGICAL); if (0 < module_num_config_bits) { add_sram_ports_to_module_manager(module_manager, pb_module, circuit_lib, - sram_model, sram_orgz_type, + sram_model, mem_module_type, module_num_config_bits); } @@ -1050,10 +1126,12 @@ static void rec_build_logical_tile_modules( * This is a one-shot addition that covers all the memory modules in this pb * module! */ - if (0 < module_manager.configurable_children(pb_module).size()) { - add_module_nets_memory_config_bus(module_manager, decoder_lib, pb_module, - sram_orgz_type, - circuit_lib.design_tech_type(sram_model)); + if (0 < module_manager.num_configurable_children( + pb_module, ModuleManager::e_config_child_type::LOGICAL)) { + add_module_nets_memory_config_bus( + module_manager, decoder_lib, pb_module, mem_module_type, + circuit_lib.design_tech_type(sram_model), + ModuleManager::e_config_child_type::LOGICAL); } VTR_LOGV(verbose, "Done\n"); @@ -1067,14 +1145,15 @@ static void rec_build_logical_tile_modules( * The param 'border_side' is required, which is specify which side of fabric * the I/O block locates at. *****************************************************************************/ -static void build_physical_tile_module( +static int build_physical_tile_module( ModuleManager& module_manager, DecoderLibrary& decoder_lib, const VprDeviceAnnotation& vpr_device_annotation, const CircuitLibrary& circuit_lib, const e_config_protocol_type& sram_orgz_type, const CircuitModelId& sram_model, t_physical_tile_type_ptr phy_block_type, const e_side& border_side, const bool& duplicate_grid_pin, - const bool& verbose) { + const bool& group_config_block, const bool& verbose) { + int status = CMD_EXEC_SUCCESS; /* Create a Module for the top-level physical block, and add to module manager */ std::string grid_module_name = generate_grid_block_module_name( @@ -1124,15 +1203,29 @@ static void build_physical_tile_module( /* Identify if this sub module includes configuration bits, * we will update the memory module and instance list */ - if (0 < find_module_num_config_bits(module_manager, pb_module, - circuit_lib, sram_model, - sram_orgz_type)) { - module_manager.add_configurable_child(grid_module, pb_module, - pb_instance_id); + if (0 < find_module_num_config_bits( + module_manager, pb_module, circuit_lib, sram_model, + group_config_block ? CONFIG_MEM_FEEDTHROUGH : sram_orgz_type)) { + /* Only add logical configurable children here. Since we will add a + * physical memory block at this level */ + module_manager.add_configurable_child( + grid_module, pb_module, pb_instance_id, + group_config_block ? ModuleManager::e_config_child_type::LOGICAL + : ModuleManager::e_config_child_type::UNIFIED); } } } + /* TODO: Add a physical memory block */ + if (group_config_block) { + status = add_physical_memory_module(module_manager, decoder_lib, + grid_module, circuit_lib, + sram_orgz_type, sram_model, verbose); + if (status != CMD_EXEC_SUCCESS) { + return CMD_EXEC_FATAL_ERROR; + } + } + /* Add grid ports(pins) to the module */ if (false == duplicate_grid_pin) { /* Default way to add these ports by following the definition in pb_types */ @@ -1218,9 +1311,13 @@ static void build_physical_tile_module( * we just need to find all the I/O ports from the child modules and build a * list of it */ + ModuleManager::e_config_child_type config_child_type = + group_config_block ? ModuleManager::e_config_child_type::PHYSICAL + : ModuleManager::e_config_child_type::LOGICAL; size_t module_num_config_bits = find_module_num_config_bits_from_child_modules( - module_manager, grid_module, circuit_lib, sram_model, sram_orgz_type); + module_manager, grid_module, circuit_lib, sram_model, sram_orgz_type, + config_child_type); if (0 < module_num_config_bits) { add_pb_sram_ports_to_module_manager(module_manager, grid_module, circuit_lib, sram_model, sram_orgz_type, @@ -1231,13 +1328,16 @@ static void build_physical_tile_module( * This is a one-shot addition that covers all the memory modules in this pb * module! */ - if (0 < module_manager.configurable_children(grid_module).size()) { + if (0 < module_manager.num_configurable_children(grid_module, + config_child_type)) { add_pb_module_nets_memory_config_bus( module_manager, decoder_lib, grid_module, sram_orgz_type, - circuit_lib.design_tech_type(sram_model)); + circuit_lib.design_tech_type(sram_model), config_child_type); } VTR_LOGV(verbose, "Done\n"); + + return status; } /***************************************************************************** @@ -1253,18 +1353,18 @@ static void build_physical_tile_module( * - Only one module for each CLB (FILL_TYPE) * - Only one module for each heterogeneous block ****************************************************************************/ -void build_grid_modules(ModuleManager& module_manager, - DecoderLibrary& decoder_lib, - const DeviceContext& device_ctx, - const VprDeviceAnnotation& device_annotation, - const CircuitLibrary& circuit_lib, - const MuxLibrary& mux_lib, - const e_config_protocol_type& sram_orgz_type, - const CircuitModelId& sram_model, - const bool& duplicate_grid_pin, const bool& verbose) { +int build_grid_modules( + ModuleManager& module_manager, DecoderLibrary& decoder_lib, + const DeviceContext& device_ctx, const VprDeviceAnnotation& device_annotation, + const CircuitLibrary& circuit_lib, const MuxLibrary& mux_lib, + const e_config_protocol_type& sram_orgz_type, + const CircuitModelId& sram_model, const bool& duplicate_grid_pin, + const bool& group_config_block, const bool& verbose) { /* Start time count */ vtr::ScopedStartFinishTimer timer("Build grid modules"); + int status = CMD_EXEC_SUCCESS; + /* Enumerate the types of logical tiles, and build a module for each * Build modules for all the pb_types/pb_graph_nodes * use a Depth-First Search Algorithm to print the sub-modules @@ -1284,7 +1384,8 @@ void build_grid_modules(ModuleManager& module_manager, } rec_build_logical_tile_modules( module_manager, decoder_lib, device_annotation, circuit_lib, mux_lib, - sram_orgz_type, sram_model, logical_tile.pb_graph_head, verbose); + sram_orgz_type, sram_model, logical_tile.pb_graph_head, + group_config_block, verbose); } VTR_LOG("Done\n"); @@ -1311,20 +1412,28 @@ void build_grid_modules(ModuleManager& module_manager, std::set io_type_sides = find_physical_io_tile_located_sides(device_ctx.grid, &physical_tile); for (const e_side& io_type_side : io_type_sides) { - build_physical_tile_module(module_manager, decoder_lib, - device_annotation, circuit_lib, - sram_orgz_type, sram_model, &physical_tile, - io_type_side, duplicate_grid_pin, verbose); + status = build_physical_tile_module( + module_manager, decoder_lib, device_annotation, circuit_lib, + sram_orgz_type, sram_model, &physical_tile, io_type_side, + duplicate_grid_pin, group_config_block, verbose); + if (status != CMD_EXEC_SUCCESS) { + return CMD_EXEC_FATAL_ERROR; + } } } else { /* For CLB and heterogenenous blocks */ - build_physical_tile_module(module_manager, decoder_lib, device_annotation, - circuit_lib, sram_orgz_type, sram_model, - &physical_tile, NUM_SIDES, duplicate_grid_pin, - verbose); + status = build_physical_tile_module( + module_manager, decoder_lib, device_annotation, circuit_lib, + sram_orgz_type, sram_model, &physical_tile, NUM_SIDES, + duplicate_grid_pin, group_config_block, verbose); + if (status != CMD_EXEC_SUCCESS) { + return CMD_EXEC_FATAL_ERROR; + } } } VTR_LOG("Done\n"); + + return status; } } /* end namespace openfpga */ diff --git a/openfpga/src/fabric/build_grid_modules.h b/openfpga/src/fabric/build_grid_modules.h index 61c0963c3..d83cc3ac3 100644 --- a/openfpga/src/fabric/build_grid_modules.h +++ b/openfpga/src/fabric/build_grid_modules.h @@ -17,15 +17,13 @@ /* begin namespace openfpga */ namespace openfpga { -void build_grid_modules(ModuleManager& module_manager, - DecoderLibrary& decoder_lib, - const DeviceContext& device_ctx, - const VprDeviceAnnotation& device_annotation, - const CircuitLibrary& circuit_lib, - const MuxLibrary& mux_lib, - const e_config_protocol_type& sram_orgz_type, - const CircuitModelId& sram_model, - const bool& duplicate_grid_pin, const bool& verbose); +int build_grid_modules( + ModuleManager& module_manager, DecoderLibrary& decoder_lib, + const DeviceContext& device_ctx, const VprDeviceAnnotation& device_annotation, + const CircuitLibrary& circuit_lib, const MuxLibrary& mux_lib, + const e_config_protocol_type& sram_orgz_type, + const CircuitModelId& sram_model, const bool& duplicate_grid_pin, + const bool& group_config_block, const bool& verbose); } /* end namespace openfpga */ diff --git a/openfpga/src/fabric/build_memory_modules.cpp b/openfpga/src/fabric/build_memory_modules.cpp index 9ce406ca6..80899a04c 100644 --- a/openfpga/src/fabric/build_memory_modules.cpp +++ b/openfpga/src/fabric/build_memory_modules.cpp @@ -3,15 +3,18 @@ * the memories that are affiliated to multiplexers and other programmable * circuit models, such as IOPADs, LUTs, etc. ********************************************************************/ +#include "build_memory_modules.h" + #include #include +#include #include -/* Headers from vtrutil library */ #include "build_decoder_modules.h" -#include "build_memory_modules.h" #include "circuit_library_utils.h" +#include "command_exit_codes.h" #include "decoder_library_utils.h" +#include "memory_utils.h" #include "module_manager.h" #include "module_manager_utils.h" #include "mux_graph.h" @@ -173,7 +176,11 @@ static void add_module_nets_to_cmos_memory_config_chain_module( const CircuitLibrary& circuit_lib, const CircuitPortId& model_input_port, const CircuitPortId& model_output_port) { for (size_t mem_index = 0; - mem_index < module_manager.configurable_children(parent_module).size(); + mem_index < + module_manager + .configurable_children(parent_module, + ModuleManager::e_config_child_type::LOGICAL) + .size(); ++mem_index) { ModuleId net_src_module_id; size_t net_src_instance_id; @@ -193,28 +200,30 @@ static void add_module_nets_to_cmos_memory_config_chain_module( /* Find the port name of next memory module */ std::string sink_port_name = circuit_lib.port_prefix(model_input_port); - net_sink_module_id = - module_manager.configurable_children(parent_module)[mem_index]; - net_sink_instance_id = - module_manager.configurable_child_instances(parent_module)[mem_index]; + net_sink_module_id = module_manager.configurable_children( + parent_module, ModuleManager::e_config_child_type::LOGICAL)[mem_index]; + net_sink_instance_id = module_manager.configurable_child_instances( + parent_module, ModuleManager::e_config_child_type::LOGICAL)[mem_index]; net_sink_port_id = module_manager.find_module_port(net_sink_module_id, sink_port_name); } else { /* Find the port name of previous memory module */ std::string src_port_name = circuit_lib.port_prefix(model_output_port); - net_src_module_id = - module_manager.configurable_children(parent_module)[mem_index - 1]; + net_src_module_id = module_manager.configurable_children( + parent_module, + ModuleManager::e_config_child_type::LOGICAL)[mem_index - 1]; net_src_instance_id = module_manager.configurable_child_instances( - parent_module)[mem_index - 1]; + parent_module, + ModuleManager::e_config_child_type::LOGICAL)[mem_index - 1]; net_src_port_id = module_manager.find_module_port(net_src_module_id, src_port_name); /* Find the port name of next memory module */ std::string sink_port_name = circuit_lib.port_prefix(model_input_port); - net_sink_module_id = - module_manager.configurable_children(parent_module)[mem_index]; - net_sink_instance_id = - module_manager.configurable_child_instances(parent_module)[mem_index]; + net_sink_module_id = module_manager.configurable_children( + parent_module, ModuleManager::e_config_child_type::LOGICAL)[mem_index]; + net_sink_instance_id = module_manager.configurable_child_instances( + parent_module, ModuleManager::e_config_child_type::LOGICAL)[mem_index]; net_sink_port_id = module_manager.find_module_port(net_sink_module_id, sink_port_name); } @@ -248,9 +257,15 @@ static void add_module_nets_to_cmos_memory_config_chain_module( /* Find the port name of previous memory module */ std::string src_port_name = circuit_lib.port_prefix(model_output_port); ModuleId net_src_module_id = - module_manager.configurable_children(parent_module).back(); + module_manager + .configurable_children(parent_module, + ModuleManager::e_config_child_type::LOGICAL) + .back(); size_t net_src_instance_id = - module_manager.configurable_child_instances(parent_module).back(); + module_manager + .configurable_child_instances(parent_module, + ModuleManager::e_config_child_type::LOGICAL) + .back(); ModulePortId net_src_port_id = module_manager.find_module_port(net_src_module_id, src_port_name); @@ -310,7 +325,11 @@ static void add_module_nets_to_cmos_memory_scan_chain_module( const CircuitLibrary& circuit_lib, const CircuitPortId& model_input_port, const CircuitPortId& model_output_port) { for (size_t mem_index = 0; - mem_index < module_manager.configurable_children(parent_module).size(); + mem_index < + module_manager + .configurable_children(parent_module, + ModuleManager::e_config_child_type::LOGICAL) + .size(); ++mem_index) { ModuleId net_src_module_id; size_t net_src_instance_id; @@ -330,28 +349,30 @@ static void add_module_nets_to_cmos_memory_scan_chain_module( /* Find the port name of next memory module */ std::string sink_port_name = circuit_lib.port_prefix(model_input_port); - net_sink_module_id = - module_manager.configurable_children(parent_module)[mem_index]; - net_sink_instance_id = - module_manager.configurable_child_instances(parent_module)[mem_index]; + net_sink_module_id = module_manager.configurable_children( + parent_module, ModuleManager::e_config_child_type::LOGICAL)[mem_index]; + net_sink_instance_id = module_manager.configurable_child_instances( + parent_module, ModuleManager::e_config_child_type::LOGICAL)[mem_index]; net_sink_port_id = module_manager.find_module_port(net_sink_module_id, sink_port_name); } else { /* Find the port name of previous memory module */ std::string src_port_name = circuit_lib.port_prefix(model_output_port); - net_src_module_id = - module_manager.configurable_children(parent_module)[mem_index - 1]; + net_src_module_id = module_manager.configurable_children( + parent_module, + ModuleManager::e_config_child_type::LOGICAL)[mem_index - 1]; net_src_instance_id = module_manager.configurable_child_instances( - parent_module)[mem_index - 1]; + parent_module, + ModuleManager::e_config_child_type::LOGICAL)[mem_index - 1]; net_src_port_id = module_manager.find_module_port(net_src_module_id, src_port_name); /* Find the port name of next memory module */ std::string sink_port_name = circuit_lib.port_prefix(model_input_port); - net_sink_module_id = - module_manager.configurable_children(parent_module)[mem_index]; - net_sink_instance_id = - module_manager.configurable_child_instances(parent_module)[mem_index]; + net_sink_module_id = module_manager.configurable_children( + parent_module, ModuleManager::e_config_child_type::LOGICAL)[mem_index]; + net_sink_instance_id = module_manager.configurable_child_instances( + parent_module, ModuleManager::e_config_child_type::LOGICAL)[mem_index]; net_sink_port_id = module_manager.find_module_port(net_sink_module_id, sink_port_name); } @@ -404,7 +425,8 @@ static void build_memory_flatten_module(ModuleManager& module_manager, const CircuitLibrary& circuit_lib, const std::string& module_name, const CircuitModelId& sram_model, - const size_t& num_mems) { + const size_t& num_mems, + const bool& verbose) { /* Get the global ports required by the SRAM */ std::vector global_port_types; global_port_types.push_back(CIRCUIT_MODEL_PORT_CLOCK); @@ -433,6 +455,7 @@ static void build_memory_flatten_module(ModuleManager& module_manager, VTR_ASSERT(2 == sram_output_ports.size()); /* Create a module and add to the module manager */ + VTR_LOGV(verbose, "Building memory module '%s'\n", module_name.c_str()); ModuleId mem_module = module_manager.add_module(module_name); VTR_ASSERT(true == module_manager.valid_module_id(mem_module)); @@ -479,8 +502,9 @@ static void build_memory_flatten_module(ModuleManager& module_manager, size_t sram_mem_instance = module_manager.num_instance(mem_module, sram_mem_module); module_manager.add_child_module(mem_module, sram_mem_module); - module_manager.add_configurable_child(mem_module, sram_mem_module, - sram_mem_instance); + module_manager.add_configurable_child( + mem_module, sram_mem_module, sram_mem_instance, + ModuleManager::e_config_child_type::UNIFIED); /* Build module nets */ /* Wire inputs of parent module to inputs of child modules */ @@ -530,7 +554,8 @@ static void build_memory_chain_module(ModuleManager& module_manager, const CircuitLibrary& circuit_lib, const std::string& module_name, const CircuitModelId& sram_model, - const size_t& num_mems) { + const size_t& num_mems, + const bool& verbose) { /* Get the input ports from the SRAM */ std::vector sram_input_ports = circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_INPUT, true); @@ -546,6 +571,7 @@ static void build_memory_chain_module(ModuleManager& module_manager, (3 == sram_output_ports.size())); /* Create a module and add to the module manager */ + VTR_LOGV(verbose, "Building memory module '%s'\n", module_name.c_str()); ModuleId mem_module = module_manager.add_module(module_name); VTR_ASSERT(true == module_manager.valid_module_id(mem_module)); @@ -612,8 +638,9 @@ static void build_memory_chain_module(ModuleManager& module_manager, size_t sram_mem_instance = module_manager.num_instance(mem_module, sram_mem_module); module_manager.add_child_module(mem_module, sram_mem_module); - module_manager.add_configurable_child(mem_module, sram_mem_module, - sram_mem_instance); + module_manager.add_configurable_child( + mem_module, sram_mem_module, sram_mem_instance, + ModuleManager::e_config_child_type::UNIFIED); /* Build module nets to wire outputs of sram modules to outputs of memory * module */ @@ -689,7 +716,8 @@ static void build_frame_memory_module(ModuleManager& module_manager, const CircuitLibrary& circuit_lib, const std::string& module_name, const CircuitModelId& sram_model, - const size_t& num_mems) { + const size_t& num_mems, + const bool& verbose) { /* Get the global ports required by the SRAM */ std::vector global_port_types; global_port_types.push_back(CIRCUIT_MODEL_PORT_CLOCK); @@ -732,6 +760,7 @@ static void build_frame_memory_module(ModuleManager& module_manager, VTR_ASSERT(0 == sram_blb_ports.size()); /* Create a module and add to the module manager */ + VTR_LOGV(verbose, "Building memory module '%s'\n", module_name.c_str()); ModuleId mem_module = module_manager.add_module(module_name); VTR_ASSERT(true == module_manager.valid_module_id(mem_module)); @@ -829,8 +858,9 @@ static void build_frame_memory_module(ModuleManager& module_manager, size_t sram_instance = module_manager.num_instance(mem_module, sram_mem_module); module_manager.add_child_module(mem_module, sram_mem_module); - module_manager.add_configurable_child(mem_module, sram_mem_module, - sram_instance); + module_manager.add_configurable_child( + mem_module, sram_mem_module, sram_instance, + ModuleManager::e_config_child_type::UNIFIED); /* Wire data_in port to SRAM BL port */ ModulePortId sram_bl_port = module_manager.find_module_port( @@ -890,7 +920,8 @@ static void build_frame_memory_module(ModuleManager& module_manager, add_module_global_ports_from_child_modules(module_manager, mem_module); /* Add the decoder as the last configurable children */ - module_manager.add_configurable_child(mem_module, decoder_module, 0); + module_manager.add_configurable_child( + mem_module, decoder_module, 0, ModuleManager::e_config_child_type::UNIFIED); } /********************************************************************* @@ -909,21 +940,21 @@ static void build_memory_module(ModuleManager& module_manager, const e_config_protocol_type& sram_orgz_type, const std::string& module_name, const CircuitModelId& sram_model, - const size_t& num_mems) { + const size_t& num_mems, const bool& verbose) { switch (sram_orgz_type) { case CONFIG_MEM_STANDALONE: case CONFIG_MEM_QL_MEMORY_BANK: case CONFIG_MEM_MEMORY_BANK: build_memory_flatten_module(module_manager, circuit_lib, module_name, - sram_model, num_mems); + sram_model, num_mems, verbose); break; case CONFIG_MEM_SCAN_CHAIN: build_memory_chain_module(module_manager, circuit_lib, module_name, - sram_model, num_mems); + sram_model, num_mems, verbose); break; case CONFIG_MEM_FRAME_BASED: build_frame_memory_module(module_manager, arch_decoder_lib, circuit_lib, - module_name, sram_model, num_mems); + module_name, sram_model, num_mems, verbose); break; default: VTR_LOGF_ERROR(__FILE__, __LINE__, @@ -932,6 +963,84 @@ static void build_memory_module(ModuleManager& module_manager, } } +/********************************************************************* + * Generate Verilog modules for the feedthrough memories that are used + * by a circuit model + * mem_out mem_outb + * | | + * v v + * +------------------------------------+ + * | | + * | | + * | | + * +------------------------------------+ + * | | + * | mem_in | mem_inb + * v v + * +------------------------------------+ + * | Multiplexer Configuration port | + * + ********************************************************************/ +static int build_feedthrough_memory_module(ModuleManager& module_manager, + const std::string& module_name, + const size_t& num_mems, + const bool& verbose) { + /* Create a module and add to the module manager */ + VTR_LOGV(verbose, "Building feedthrough memory module '%s'\n", + module_name.c_str()); + ModuleId mem_module = module_manager.add_module(module_name); + if (!module_manager.valid_module_id(mem_module)) { + return CMD_EXEC_FATAL_ERROR; + } + + /* Label module usage */ + module_manager.set_module_usage(mem_module, ModuleManager::MODULE_CONFIG); + + /* Add module ports */ + /* Input: memory inputs */ + BasicPort in_port(std::string(MEMORY_FEEDTHROUGH_DATA_IN_PORT_NAME), + num_mems); + ModulePortId mem_in_port = module_manager.add_port( + mem_module, in_port, ModuleManager::MODULE_INPUT_PORT); + BasicPort inb_port(std::string(MEMORY_FEEDTHROUGH_DATA_IN_INV_PORT_NAME), + num_mems); + ModulePortId mem_inb_port = module_manager.add_port( + mem_module, inb_port, ModuleManager::MODULE_INPUT_PORT); + + /* Add each output port */ + BasicPort out_port(std::string(CONFIGURABLE_MEMORY_DATA_OUT_NAME), num_mems); + ModulePortId mem_out_port = module_manager.add_port( + mem_module, out_port, ModuleManager::MODULE_OUTPUT_PORT); + BasicPort outb_port(std::string(CONFIGURABLE_MEMORY_INVERTED_DATA_OUT_NAME), + num_mems); + ModulePortId mem_outb_port = module_manager.add_port( + mem_module, outb_port, ModuleManager::MODULE_OUTPUT_PORT); + + /* Build feedthrough nets */ + for (size_t pin_id = 0; pin_id < in_port.pins().size(); ++pin_id) { + ModuleNetId net = module_manager.create_module_net(mem_module); + if (!module_manager.valid_module_net_id(mem_module, net)) { + return CMD_EXEC_FATAL_ERROR; + } + module_manager.add_module_net_source(mem_module, net, mem_module, 0, + mem_in_port, in_port.pins()[pin_id]); + module_manager.add_module_net_sink(mem_module, net, mem_module, 0, + mem_out_port, out_port.pins()[pin_id]); + } + for (size_t pin_id = 0; pin_id < inb_port.pins().size(); ++pin_id) { + ModuleNetId net = module_manager.create_module_net(mem_module); + if (!module_manager.valid_module_net_id(mem_module, net)) { + return CMD_EXEC_FATAL_ERROR; + } + module_manager.add_module_net_source(mem_module, net, mem_module, 0, + mem_inb_port, inb_port.pins()[pin_id]); + module_manager.add_module_net_sink(mem_module, net, mem_module, 0, + mem_outb_port, outb_port.pins()[pin_id]); + } + + return CMD_EXEC_SUCCESS; +} + /********************************************************************* * Generate Verilog modules for the memories that are used * by multiplexers @@ -949,7 +1058,7 @@ static void build_mux_memory_module( ModuleManager& module_manager, DecoderLibrary& arch_decoder_lib, const CircuitLibrary& circuit_lib, const e_config_protocol_type& sram_orgz_type, const CircuitModelId& mux_model, - const MuxGraph& mux_graph) { + const MuxGraph& mux_graph, const bool& verbose) { /* Find the actual number of configuration bits, based on the mux graph * Due to the use of local decoders inside mux, this may be */ @@ -973,7 +1082,7 @@ static void build_mux_memory_module( build_memory_module(module_manager, arch_decoder_lib, circuit_lib, sram_orgz_type, module_name, sram_models[0], - num_config_bits); + num_config_bits, verbose); break; } case CIRCUIT_MODEL_DESIGN_RRAM: @@ -990,6 +1099,61 @@ static void build_mux_memory_module( } } +/********************************************************************* + * Generate Verilog modules for the feedthrough memories that are used + * by multiplexers + * SRAM ports as feedthrough (driven by physical memory blocks) + * | | | | + * v v ... v v + * +----------------+ + * | Memory Module | + * +----------------+ + * | | ... | | + * v v v v SRAM ports of multiplexer + * +---------------------+ + * in--->| Multiplexer Module |---> out + * +---------------------+ + ********************************************************************/ +static int build_mux_feedthrough_memory_module( + ModuleManager& module_manager, const CircuitLibrary& circuit_lib, + const e_config_protocol_type& sram_orgz_type, const CircuitModelId& mux_model, + const MuxGraph& mux_graph, const bool& verbose) { + int status = CMD_EXEC_SUCCESS; + /* Find the actual number of configuration bits, based on the mux graph + * Due to the use of local decoders inside mux, this may be + */ + size_t num_config_bits = + find_mux_num_config_bits(circuit_lib, mux_model, mux_graph, sram_orgz_type); + /* Multiplexers built with different technology is in different organization + */ + switch (circuit_lib.design_tech_type(mux_model)) { + case CIRCUIT_MODEL_DESIGN_CMOS: { + /* Generate module name */ + std::string module_name = generate_mux_subckt_name( + circuit_lib, mux_model, + find_mux_num_datapath_inputs(circuit_lib, mux_model, + mux_graph.num_inputs()), + std::string(MEMORY_FEEDTHROUGH_MODULE_POSTFIX)); + + status = build_feedthrough_memory_module(module_manager, module_name, + num_config_bits, verbose); + break; + } + case CIRCUIT_MODEL_DESIGN_RRAM: + /* We do not need a memory submodule for RRAM MUX, + * RRAM are embedded in the datapath + * TODO: generate local encoders for RRAM-based multiplexers here!!! + */ + break; + default: + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Invalid design technology of multiplexer '%s'\n", + circuit_lib.model_name(mux_model).c_str()); + exit(1); + } + return status; +} + /********************************************************************* * Build modules for * the memories that are affiliated to multiplexers and other programmable @@ -1005,12 +1169,17 @@ static void build_mux_memory_module( * memory modules. * Take another example, the memory circuit can implement the scan-chain or * memory-bank organization for the memories. + * If we need feedthrough memory blocks, build the memory modules which contain + *only feedthrough wires ********************************************************************/ -void build_memory_modules(ModuleManager& module_manager, - DecoderLibrary& arch_decoder_lib, - const MuxLibrary& mux_lib, - const CircuitLibrary& circuit_lib, - const e_config_protocol_type& sram_orgz_type) { +int build_memory_modules(ModuleManager& module_manager, + DecoderLibrary& arch_decoder_lib, + const MuxLibrary& mux_lib, + const CircuitLibrary& circuit_lib, + const e_config_protocol_type& sram_orgz_type, + const bool& require_feedthrough_memory, + const bool& verbose) { + int status = CMD_EXEC_SUCCESS; vtr::ScopedStartFinishTimer timer("Build memory modules"); /* Create the memory circuits for the multiplexer */ @@ -1026,7 +1195,16 @@ void build_memory_modules(ModuleManager& module_manager, } /* Create a Verilog module for the memories used by the multiplexer */ build_mux_memory_module(module_manager, arch_decoder_lib, circuit_lib, - sram_orgz_type, mux_model, mux_graph); + sram_orgz_type, mux_model, mux_graph, verbose); + /* Create feedthrough memory module */ + if (require_feedthrough_memory) { + status = build_mux_feedthrough_memory_module(module_manager, circuit_lib, + sram_orgz_type, mux_model, + mux_graph, verbose); + if (status != CMD_EXEC_SUCCESS) { + return CMD_EXEC_FATAL_ERROR; + } + } } /* Create the memory circuits for non-MUX circuit models. @@ -1062,8 +1240,381 @@ void build_memory_modules(ModuleManager& module_manager, /* Create a Verilog module for the memories used by the circuit model */ build_memory_module(module_manager, arch_decoder_lib, circuit_lib, - sram_orgz_type, module_name, sram_models[0], num_mems); + sram_orgz_type, module_name, sram_models[0], num_mems, + verbose); + /* Create feedthrough memory module */ + if (require_feedthrough_memory) { + module_name = + generate_memory_module_name(circuit_lib, model, sram_models[0], + std::string(MEMORY_MODULE_POSTFIX), true); + status = build_feedthrough_memory_module(module_manager, module_name, + num_mems, verbose); + if (status != CMD_EXEC_SUCCESS) { + return CMD_EXEC_FATAL_ERROR; + } + } + } + return status; +} + +/********************************************************************* + * Add module nets to connect an output port of a configuration-chain + * memory module to an output port of its child module + * Restriction: this function is really designed for memory modules + * 1. It assumes that output port name of child module is the same as memory + *module + * 2. It assumes exact pin-to-pin mapping: + * j-th pin of output port of the i-th child module is wired to the j + i*W + *-th pin of output port of the memory module, where W is the size of port + * 3. It assumes fixed port name for output ports + ********************************************************************/ +static void add_module_output_nets_to_memory_group_module( + ModuleManager& module_manager, const ModuleId& mem_module, + const std::string& mem_module_output_name, const ModuleId& child_module, + const size_t& output_pin_start_index, const size_t& child_instance) { + /* Wire inputs of parent module to inputs of child modules */ + ModulePortId src_port_id = + module_manager.find_module_port(child_module, mem_module_output_name); + ModulePortId sink_port_id = + module_manager.find_module_port(mem_module, mem_module_output_name); + for (size_t pin_id = 0; + pin_id < + module_manager.module_port(child_module, src_port_id).pins().size(); + ++pin_id) { + ModuleNetId net = module_manager.create_module_net(mem_module); + /* Source pin is shifted by the number of memories */ + size_t src_pin_id = + module_manager.module_port(child_module, src_port_id).pins()[pin_id]; + /* Source node of the input net is the input of memory module */ + module_manager.add_module_net_source( + mem_module, net, child_module, child_instance, src_port_id, src_pin_id); + /* Sink node of the input net is the input of sram module */ + size_t sink_pin_id = + output_pin_start_index + + module_manager.module_port(mem_module, sink_port_id).pins()[pin_id]; + module_manager.add_module_net_sink(mem_module, net, mem_module, 0, + sink_port_id, sink_pin_id); } } +/********************************************************************* + * Build a grouped memory module based on existing memory modules + * - Create the module + * - Add dedicated instance + * - Add ports + * - Add nets + ********************************************************************/ +int build_memory_group_module( + ModuleManager& module_manager, DecoderLibrary& decoder_lib, + const CircuitLibrary& circuit_lib, + const e_config_protocol_type& sram_orgz_type, const std::string& module_name, + const CircuitModelId& sram_model, const std::vector& child_modules, + const std::vector& child_instance_names, const size_t& num_mems, + const bool& verbose) { + VTR_LOGV(verbose, "Building memory group module '%s'...\n", + module_name.c_str()); + ModuleId mem_module = module_manager.add_module(module_name); + if (!module_manager.valid_module_id(mem_module)) { + return CMD_EXEC_FATAL_ERROR; + } + + /* Label module usage */ + module_manager.set_module_usage(mem_module, + ModuleManager::MODULE_CONFIG_GROUP); + + /* Add output ports */ + std::string out_port_name = generate_configurable_memory_data_out_name(); + BasicPort out_port(out_port_name, num_mems); + module_manager.add_port(mem_module, out_port, + ModuleManager::MODULE_OUTPUT_PORT); + + std::string outb_port_name = + generate_configurable_memory_inverted_data_out_name(); + BasicPort outb_port(outb_port_name, num_mems); + module_manager.add_port(mem_module, outb_port, + ModuleManager::MODULE_OUTPUT_PORT); + + /* Identify the duplicated instance name: This mainly comes from the grid + * modules, which contains multi-instanced blocks. Therefore, we just count + * the duplicated instance names and name each of them with a unique index, + * e.g., mem_lut -> mem_lut_0, mem_lut_1 etc. The only exception is for the + * uinque instance name, we keep the original instance name */ + std::vector unique_child_instance_names; + unique_child_instance_names.reserve(child_instance_names.size()); + std::map unique_child_instance_name_count; + for (std::string curr_inst_name : child_instance_names) { + auto result = unique_child_instance_name_count.find(curr_inst_name); + if (result == unique_child_instance_name_count.end()) { + unique_child_instance_name_count[curr_inst_name] = 1; + } else { + unique_child_instance_name_count[curr_inst_name]++; + } + } + std::map unique_child_instance_name_scoreboard; + for (std::string curr_inst_name : child_instance_names) { + if (1 == unique_child_instance_name_count[curr_inst_name]) { + unique_child_instance_names.push_back(curr_inst_name); + unique_child_instance_name_scoreboard[curr_inst_name] = 1; + continue; + } + auto result = unique_child_instance_name_scoreboard.find(curr_inst_name); + if (result == unique_child_instance_name_scoreboard.end()) { + unique_child_instance_name_scoreboard[curr_inst_name] = 0; + unique_child_instance_names.push_back(curr_inst_name); + } else { + unique_child_instance_name_scoreboard[curr_inst_name]++; + unique_child_instance_names.push_back(generate_instance_name( + curr_inst_name, unique_child_instance_name_scoreboard[curr_inst_name])); + } + } + VTR_ASSERT(unique_child_instance_names.size() == child_instance_names.size()); + + /* Add nets between child module outputs and memory modules */ + size_t mem_out_pin_start_index = 0; + size_t mem_outb_pin_start_index = 0; + for (size_t ichild = 0; ichild < child_modules.size(); ++ichild) { + ModuleId child_module = child_modules[ichild]; + size_t child_instance = + module_manager.num_instance(mem_module, child_module); + module_manager.add_child_module(mem_module, child_module, false); + module_manager.set_child_instance_name(mem_module, child_module, + child_instance, + unique_child_instance_names[ichild]); + module_manager.add_configurable_child( + mem_module, child_module, child_instance, + ModuleManager::e_config_child_type::UNIFIED); + /* Wire outputs of child module to outputs of parent module */ + ModulePortId child_out_port_id = + module_manager.find_module_port(child_module, out_port_name); + if (module_manager.valid_module_port_id(child_module, child_out_port_id)) { + add_module_output_nets_to_memory_group_module( + module_manager, mem_module, out_port_name, child_module, + mem_out_pin_start_index, child_instance); + /* Update pin counter */ + mem_out_pin_start_index += + module_manager.module_port(child_module, child_out_port_id).get_width(); + } + ModulePortId child_outb_port_id = + module_manager.find_module_port(child_module, outb_port_name); + if (module_manager.valid_module_port_id(child_module, child_outb_port_id)) { + add_module_output_nets_to_memory_group_module( + module_manager, mem_module, outb_port_name, child_module, + mem_outb_pin_start_index, child_instance); + /* Update pin counter */ + mem_outb_pin_start_index += + module_manager.module_port(child_module, child_outb_port_id) + .get_width(); + } + } + + /* Add global ports to the pb_module: + * This is a much easier job after adding sub modules (instances), + * we just need to find all the global ports from the child modules and build + * a list of it + */ + add_module_global_ports_from_child_modules(module_manager, mem_module); + + /* Count GPIO 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 + */ + add_module_gpio_ports_from_child_modules(module_manager, mem_module); + + /* Count 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 + */ + size_t module_num_shared_config_bits = + find_module_num_shared_config_bits_from_child_modules(module_manager, + mem_module); + if (0 < module_num_shared_config_bits) { + add_reserved_sram_ports_to_module_manager(module_manager, mem_module, + module_num_shared_config_bits); + } + + /* Count 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 + */ + ModuleManager::e_config_child_type config_child_type = + ModuleManager::e_config_child_type::PHYSICAL; + size_t module_num_config_bits = + find_module_num_config_bits_from_child_modules( + module_manager, mem_module, circuit_lib, sram_model, sram_orgz_type, + config_child_type); + if (0 < module_num_config_bits) { + add_sram_ports_to_module_manager(module_manager, mem_module, circuit_lib, + sram_model, sram_orgz_type, + module_num_config_bits); + } + + /* Add module nets to connect memory cells inside + * This is a one-shot addition that covers all the memory modules in this pb + * module! + */ + if (0 < + module_manager.num_configurable_children(mem_module, config_child_type)) { + add_module_nets_memory_config_bus( + module_manager, decoder_lib, mem_module, sram_orgz_type, + circuit_lib.design_tech_type(sram_model), config_child_type); + } + + return CMD_EXEC_SUCCESS; +} + +/***************************************************************************** + * This function creates a physical memory module and add it the current module + * The following tasks will be accomplished: + * - Traverse all the logical configurable children in the module tree, starting + *from the current module + * - Build a list of the leaf logical configurable children and count the total + *memory sizes, the memory size for each physical memory submodule. Note that + *the physical memory submodule should be cached already in each leaf logical + *configurable children + * - Get the physical memory module required by each leaf logical configurable + *child + * - Create a dedicated module name for the physical memory (check if already + *exists, if yes, skip creating a new module) + * - Instanciate the module + * - Built nets. Note that only the output ports of the physical memory block is + *required, since they should drive the dedicated memory ports of logical + *configurable children + *****************************************************************************/ +int add_physical_memory_module(ModuleManager& module_manager, + DecoderLibrary& decoder_lib, + const ModuleId& curr_module, + const CircuitLibrary& circuit_lib, + const e_config_protocol_type& sram_orgz_type, + const CircuitModelId& sram_model, + const bool& verbose) { + int status = CMD_EXEC_SUCCESS; + + std::vector required_phy_mem_modules; + std::vector required_phy_mem_instance_names; + status = rec_find_physical_memory_children( + static_cast(module_manager), curr_module, + required_phy_mem_modules, required_phy_mem_instance_names, verbose); + if (status != CMD_EXEC_SUCCESS) { + return CMD_EXEC_FATAL_ERROR; + } + + size_t module_num_config_bits = + find_module_num_config_bits_from_child_modules( + module_manager, curr_module, circuit_lib, sram_model, + CONFIG_MEM_FEEDTHROUGH, ModuleManager::e_config_child_type::LOGICAL); + /* No need to build a memory when there are no configuration bits required */ + if (module_num_config_bits == 0) { + return CMD_EXEC_SUCCESS; + } + std::string phy_mem_module_name = generate_physical_memory_module_name( + module_manager.module_name(curr_module), module_num_config_bits); + VTR_LOGV(verbose, "Adding memory group module '%s' as a child to '%s'...\n", + phy_mem_module_name.c_str(), + module_manager.module_name(curr_module).c_str()); + ModuleId phy_mem_module = module_manager.find_module(phy_mem_module_name); + if (!module_manager.valid_module_id(phy_mem_module)) { + status = build_memory_group_module( + module_manager, decoder_lib, circuit_lib, sram_orgz_type, + phy_mem_module_name, sram_model, required_phy_mem_modules, + required_phy_mem_instance_names, module_num_config_bits, verbose); + } + if (status != CMD_EXEC_SUCCESS) { + VTR_LOG_ERROR("Failed to create the physical memory module '%s'!\n", + phy_mem_module_name.c_str()); + return CMD_EXEC_FATAL_ERROR; + } + phy_mem_module = module_manager.find_module(phy_mem_module_name); + if (!module_manager.valid_module_id(phy_mem_module)) { + VTR_LOG_ERROR("Failed to create the physical memory module '%s'!\n", + phy_mem_module_name.c_str()); + return CMD_EXEC_FATAL_ERROR; + } + /* Add the physical memory module to the current module */ + size_t phy_mem_instance = + module_manager.num_instance(curr_module, phy_mem_module); + module_manager.add_child_module(curr_module, phy_mem_module, false); + /* TODO: Give a more meaningful instance name? */ + module_manager.set_child_instance_name(curr_module, phy_mem_module, + phy_mem_instance, phy_mem_module_name); + + /* Register in the physical configurable children list */ + module_manager.add_configurable_child( + curr_module, phy_mem_module, phy_mem_instance, + ModuleManager::e_config_child_type::PHYSICAL); + + /* Build nets between the data output of the physical memory module and the + * outputs of the logical configurable children */ + std::map curr_mem_pin_index; + curr_mem_pin_index[CIRCUIT_MODEL_PORT_BL] = 0; + curr_mem_pin_index[CIRCUIT_MODEL_PORT_BLB] = 0; + std::map mem2mem_port_map; + mem2mem_port_map[CIRCUIT_MODEL_PORT_BL] = + std::string(CONFIGURABLE_MEMORY_DATA_OUT_NAME); + mem2mem_port_map[CIRCUIT_MODEL_PORT_BLB] = + std::string(CONFIGURABLE_MEMORY_INVERTED_DATA_OUT_NAME); + for (size_t ichild = 0; + ichild < module_manager + .configurable_children( + curr_module, ModuleManager::e_config_child_type::LOGICAL) + .size(); + ++ichild) { + ModuleId des_module = module_manager.configurable_children( + curr_module, ModuleManager::e_config_child_type::LOGICAL)[ichild]; + size_t des_instance = module_manager.configurable_child_instances( + curr_module, ModuleManager::e_config_child_type::LOGICAL)[ichild]; + + for (e_circuit_model_port_type port_type : + {CIRCUIT_MODEL_PORT_BL, CIRCUIT_MODEL_PORT_BLB}) { + std::string src_port_name = mem2mem_port_map[port_type]; + std::string des_port_name = + generate_sram_port_name(CONFIG_MEM_FEEDTHROUGH, port_type); + /* Try to find these ports in the module manager */ + ModulePortId src_port_id = + module_manager.find_module_port(phy_mem_module, src_port_name); + if (!module_manager.valid_module_port_id(phy_mem_module, src_port_id)) { + return CMD_EXEC_FATAL_ERROR; + } + BasicPort src_port = + module_manager.module_port(phy_mem_module, src_port_id); + + ModulePortId des_port_id = + module_manager.find_module_port(des_module, des_port_name); + if (!module_manager.valid_module_port_id(des_module, des_port_id)) { + return CMD_EXEC_FATAL_ERROR; + } + BasicPort des_port = module_manager.module_port(des_module, des_port_id); + /* Build nets */ + for (size_t ipin = 0; ipin < des_port.pins().size(); ++ipin) { + VTR_LOGV( + verbose, "Building net '%s[%lu].%s[%lu]' -> '%s[%lu].%s[%lu]\n", + module_manager.module_name(phy_mem_module).c_str(), phy_mem_instance, + src_port.get_name().c_str(), curr_mem_pin_index[port_type], + module_manager.module_name(des_module).c_str(), des_instance, + des_port.get_name().c_str(), des_port.pins()[ipin]); + /* Create a net and add source and sink to it */ + ModuleNetId net = create_module_source_pin_net( + module_manager, curr_module, phy_mem_module, phy_mem_instance, + src_port_id, src_port.pins()[curr_mem_pin_index[port_type]]); + if (!module_manager.valid_module_net_id(curr_module, net)) { + return CMD_EXEC_FATAL_ERROR; + } + /* Add net sink */ + module_manager.add_module_net_sink(curr_module, net, des_module, + des_instance, des_port_id, + des_port.pins()[ipin]); + curr_mem_pin_index[port_type]++; + } + } + } + VTR_ASSERT(curr_mem_pin_index[CIRCUIT_MODEL_PORT_BL] == + module_num_config_bits); + VTR_ASSERT(curr_mem_pin_index[CIRCUIT_MODEL_PORT_BLB] == + module_num_config_bits); + + return status; +} + } /* end namespace openfpga */ diff --git a/openfpga/src/fabric/build_memory_modules.h b/openfpga/src/fabric/build_memory_modules.h index 5eeaf25e8..b79fd4b90 100644 --- a/openfpga/src/fabric/build_memory_modules.h +++ b/openfpga/src/fabric/build_memory_modules.h @@ -22,11 +22,29 @@ std::vector add_module_output_nets_to_chain_mem_modules( const CircuitPortId& circuit_port, const ModuleId& child_module, const size_t& child_index, const size_t& child_instance); -void build_memory_modules(ModuleManager& module_manager, - DecoderLibrary& arch_decoder_lib, - const MuxLibrary& mux_lib, - const CircuitLibrary& circuit_lib, - const e_config_protocol_type& sram_orgz_type); +int build_memory_modules(ModuleManager& module_manager, + DecoderLibrary& arch_decoder_lib, + const MuxLibrary& mux_lib, + const CircuitLibrary& circuit_lib, + const e_config_protocol_type& sram_orgz_type, + const bool& require_feedthrough_memory, + const bool& verbose); + +int build_memory_group_module( + ModuleManager& module_manager, DecoderLibrary& decoder_lib, + const CircuitLibrary& circuit_lib, + const e_config_protocol_type& sram_orgz_type, const std::string& module_name, + const CircuitModelId& sram_model, const std::vector& child_modules, + const std::vector& child_instance_names, const size_t& num_mems, + const bool& verbose); + +int add_physical_memory_module(ModuleManager& module_manager, + DecoderLibrary& decoder_lib, + const ModuleId& curr_module, + const CircuitLibrary& circuit_lib, + const e_config_protocol_type& sram_orgz_type, + const CircuitModelId& sram_model, + const bool& verbose); } /* end namespace openfpga */ diff --git a/openfpga/src/fabric/build_routing_modules.cpp b/openfpga/src/fabric/build_routing_modules.cpp index f57ccce29..4693db986 100644 --- a/openfpga/src/fabric/build_routing_modules.cpp +++ b/openfpga/src/fabric/build_routing_modules.cpp @@ -14,6 +14,7 @@ #include "vtr_time.h" /* Headers from openfpgautil library */ +#include "build_memory_modules.h" #include "build_module_graph_utils.h" #include "build_routing_module_utils.h" #include "build_routing_modules.h" @@ -108,7 +109,8 @@ static void build_switch_block_mux_module( const CircuitLibrary& circuit_lib, const e_side& chan_side, const size_t& chan_node_id, const RRNodeId& cur_rr_node, const std::vector& driver_rr_nodes, const RRSwitchId& switch_index, - const std::map& input_port_to_module_nets) { + const std::map& input_port_to_module_nets, + const bool& group_config_block) { /* Check current rr_node is CHANX or CHANY*/ VTR_ASSERT((CHANX == rr_graph.node_type(cur_rr_node)) || (CHANY == rr_graph.node_type(cur_rr_node))); @@ -214,6 +216,11 @@ static void build_switch_block_mux_module( std::string mem_module_name = generate_mux_subckt_name(circuit_lib, mux_model, datapath_mux_size, std::string(MEMORY_MODULE_POSTFIX)); + if (group_config_block) { + mem_module_name = + generate_mux_subckt_name(circuit_lib, mux_model, datapath_mux_size, + std::string(MEMORY_FEEDTHROUGH_MODULE_POSTFIX)); + } ModuleId mem_module = module_manager.find_module(mem_module_name); VTR_ASSERT(true == module_manager.valid_module_id(mem_module)); @@ -224,7 +231,8 @@ static void build_switch_block_mux_module( * modules */ std::string mem_instance_name = generate_sb_memory_instance_name( - SWITCH_BLOCK_MEM_INSTANCE_PREFIX, chan_side, chan_node_id, std::string("")); + SWITCH_BLOCK_MEM_INSTANCE_PREFIX, chan_side, chan_node_id, std::string(""), + group_config_block); module_manager.set_child_instance_name(sb_module, mem_module, mem_instance_id, mem_instance_name); @@ -234,7 +242,28 @@ static void build_switch_block_mux_module( module_manager, sb_module, mux_module, mux_instance_id, mem_module, mem_instance_id, circuit_lib, mux_model); /* Update memory and instance list */ - module_manager.add_configurable_child(sb_module, mem_module, mem_instance_id); + size_t config_child_id = module_manager.num_configurable_children( + sb_module, ModuleManager::e_config_child_type::LOGICAL); + module_manager.add_configurable_child( + sb_module, mem_module, mem_instance_id, + group_config_block ? ModuleManager::e_config_child_type::LOGICAL + : ModuleManager::e_config_child_type::UNIFIED); + /* For logical memory, define the physical memory here */ + if (group_config_block) { + std::string physical_mem_module_name = + generate_mux_subckt_name(circuit_lib, mux_model, datapath_mux_size, + std::string(MEMORY_MODULE_POSTFIX)); + ModuleId physical_mem_module = + module_manager.find_module(physical_mem_module_name); + VTR_ASSERT(true == module_manager.valid_module_id(physical_mem_module)); + module_manager.set_logical2physical_configurable_child( + sb_module, config_child_id, physical_mem_module); + std::string physical_mem_instance_name = generate_sb_memory_instance_name( + SWITCH_BLOCK_MEM_INSTANCE_PREFIX, chan_side, chan_node_id, + std::string(""), false); + module_manager.set_logical2physical_configurable_child_instance_name( + sb_module, config_child_id, physical_mem_instance_name); + } } /********************************************************************* @@ -248,7 +277,8 @@ static void build_switch_block_interc_modules( const RRGraphView& rr_graph, const RRGSB& rr_gsb, const CircuitLibrary& circuit_lib, const e_side& chan_side, const size_t& chan_node_id, - const std::map& input_port_to_module_nets) { + const std::map& input_port_to_module_nets, + const bool& group_config_block) { std::vector driver_rr_nodes; /* Get the node */ @@ -284,7 +314,7 @@ static void build_switch_block_interc_modules( build_switch_block_mux_module( module_manager, sb_module, device_annotation, grids, rr_graph, rr_gsb, circuit_lib, chan_side, chan_node_id, cur_rr_node, driver_rr_nodes, - driver_switches[0], input_port_to_module_nets); + driver_switches[0], input_port_to_module_nets, group_config_block); } /*Nothing should be done else*/ } @@ -354,7 +384,8 @@ static void build_switch_block_module( const VprDeviceAnnotation& device_annotation, const DeviceGrid& grids, const RRGraphView& rr_graph, const CircuitLibrary& circuit_lib, const e_config_protocol_type& sram_orgz_type, - const CircuitModelId& sram_model, const RRGSB& rr_gsb, const bool& verbose) { + const CircuitModelId& sram_model, const RRGSB& rr_gsb, + const bool& group_config_block, const bool& verbose) { /* Create a Module of Switch Block and add to module manager */ vtr::Point gsb_coordinate(rr_gsb.get_sb_x(), rr_gsb.get_sb_y()); ModuleId sb_module = module_manager.add_module( @@ -456,11 +487,18 @@ static void build_switch_block_module( build_switch_block_interc_modules( module_manager, sb_module, device_annotation, grids, rr_graph, rr_gsb, circuit_lib, side_manager.get_side(), itrack, - input_port_to_module_nets); + input_port_to_module_nets, group_config_block); } } } + /* Build a physical memory block */ + if (group_config_block) { + add_physical_memory_module(module_manager, decoder_lib, sb_module, + circuit_lib, sram_orgz_type, sram_model, + verbose); + } + /* Add global ports to the pb_module: * This is a much easier job after adding sub modules (instances), * we just need to find all the global ports from the child modules and build @@ -486,9 +524,13 @@ static void build_switch_block_module( * we just need to find all the I/O ports from the child modules and build a * list of it */ + ModuleManager::e_config_child_type config_child_type = + group_config_block ? ModuleManager::e_config_child_type::PHYSICAL + : ModuleManager::e_config_child_type::LOGICAL; size_t module_num_config_bits = find_module_num_config_bits_from_child_modules( - module_manager, sb_module, circuit_lib, sram_model, sram_orgz_type); + module_manager, sb_module, circuit_lib, sram_model, sram_orgz_type, + config_child_type); if (0 < module_num_config_bits) { add_pb_sram_ports_to_module_manager(module_manager, sb_module, circuit_lib, sram_model, sram_orgz_type, @@ -499,10 +541,11 @@ static void build_switch_block_module( * primitive modules This is a one-shot addition that covers all the memory * modules in this primitive module! */ - if (0 < module_manager.configurable_children(sb_module).size()) { + if (0 < + module_manager.num_configurable_children(sb_module, config_child_type)) { add_pb_module_nets_memory_config_bus( module_manager, decoder_lib, sb_module, sram_orgz_type, - circuit_lib.design_tech_type(sram_model)); + circuit_lib.design_tech_type(sram_model), config_child_type); } VTR_LOGV(verbose, "Done\n"); @@ -586,7 +629,8 @@ static void build_connection_block_mux_module( const RRGraphView& rr_graph, const RRGSB& rr_gsb, const t_rr_type& cb_type, const CircuitLibrary& circuit_lib, const e_side& cb_ipin_side, const size_t& ipin_index, - const std::map& input_port_to_module_nets) { + const std::map& input_port_to_module_nets, + const bool& group_config_block) { const RRNodeId& cur_rr_node = rr_gsb.get_ipin_node(cb_ipin_side, ipin_index); /* Check current rr_node is an input pin of a CLB */ VTR_ASSERT(IPIN == rr_graph.node_type(cur_rr_node)); @@ -697,6 +741,11 @@ static void build_connection_block_mux_module( std::string mem_module_name = generate_mux_subckt_name(circuit_lib, mux_model, datapath_mux_size, std::string(MEMORY_MODULE_POSTFIX)); + if (group_config_block) { + mem_module_name = + generate_mux_subckt_name(circuit_lib, mux_model, datapath_mux_size, + std::string(MEMORY_FEEDTHROUGH_MODULE_POSTFIX)); + } ModuleId mem_module = module_manager.find_module(mem_module_name); VTR_ASSERT(true == module_manager.valid_module_id(mem_module)); @@ -711,7 +760,7 @@ static void build_connection_block_mux_module( CONNECTION_BLOCK_MEM_INSTANCE_PREFIX, get_rr_graph_single_node_side( rr_graph, rr_gsb.get_ipin_node(cb_ipin_side, ipin_index)), - ipin_index, std::string("")); + ipin_index, std::string(""), group_config_block); module_manager.set_child_instance_name(cb_module, mem_module, mem_instance_id, mem_instance_name); @@ -721,7 +770,30 @@ static void build_connection_block_mux_module( module_manager, cb_module, mux_module, mux_instance_id, mem_module, mem_instance_id, circuit_lib, mux_model); /* Update memory and instance list */ - module_manager.add_configurable_child(cb_module, mem_module, mem_instance_id); + size_t config_child_id = module_manager.num_configurable_children( + cb_module, ModuleManager::e_config_child_type::LOGICAL); + module_manager.add_configurable_child( + cb_module, mem_module, mem_instance_id, + group_config_block ? ModuleManager::e_config_child_type::LOGICAL + : ModuleManager::e_config_child_type::UNIFIED); + /* For logical memory, define the physical memory here */ + if (group_config_block) { + std::string physical_mem_module_name = + generate_mux_subckt_name(circuit_lib, mux_model, datapath_mux_size, + std::string(MEMORY_MODULE_POSTFIX)); + ModuleId physical_mem_module = + module_manager.find_module(physical_mem_module_name); + VTR_ASSERT(true == module_manager.valid_module_id(physical_mem_module)); + module_manager.set_logical2physical_configurable_child( + cb_module, config_child_id, physical_mem_module); + std::string physical_mem_instance_name = generate_cb_memory_instance_name( + CONNECTION_BLOCK_MEM_INSTANCE_PREFIX, + get_rr_graph_single_node_side( + rr_graph, rr_gsb.get_ipin_node(cb_ipin_side, ipin_index)), + ipin_index, std::string(""), false); + module_manager.set_logical2physical_configurable_child_instance_name( + cb_module, config_child_id, physical_mem_instance_name); + } } /******************************************************************** @@ -737,7 +809,8 @@ static void build_connection_block_interc_modules( const RRGraphView& rr_graph, const RRGSB& rr_gsb, const t_rr_type& cb_type, const CircuitLibrary& circuit_lib, const e_side& cb_ipin_side, const size_t& ipin_index, - const std::map& input_port_to_module_nets) { + const std::map& input_port_to_module_nets, + const bool& group_config_block) { std::vector driver_rr_edges = rr_gsb.get_ipin_node_in_edges(rr_graph, cb_ipin_side, ipin_index); @@ -753,8 +826,8 @@ static void build_connection_block_interc_modules( /* Print the multiplexer, fan_in >= 2 */ build_connection_block_mux_module( module_manager, cb_module, device_annotation, grids, rr_graph, rr_gsb, - cb_type, circuit_lib, cb_ipin_side, ipin_index, - input_port_to_module_nets); + cb_type, circuit_lib, cb_ipin_side, ipin_index, input_port_to_module_nets, + group_config_block); } /*Nothing should be done else*/ } @@ -819,7 +892,8 @@ static void build_connection_block_module( const RRGraphView& rr_graph, const CircuitLibrary& circuit_lib, const e_config_protocol_type& sram_orgz_type, const CircuitModelId& sram_model, const RRGSB& rr_gsb, - const t_rr_type& cb_type, const bool& verbose) { + const t_rr_type& cb_type, const bool& group_config_block, + const bool& verbose) { /* Create the netlist */ vtr::Point gsb_coordinate(rr_gsb.get_cb_x(cb_type), rr_gsb.get_cb_y(cb_type)); @@ -941,10 +1015,18 @@ static void build_connection_block_module( ++inode) { build_connection_block_interc_modules( module_manager, cb_module, device_annotation, grids, rr_graph, rr_gsb, - cb_type, circuit_lib, cb_ipin_side, inode, input_port_to_module_nets); + cb_type, circuit_lib, cb_ipin_side, inode, input_port_to_module_nets, + group_config_block); } } + /* Build a physical memory block */ + if (group_config_block) { + add_physical_memory_module(module_manager, decoder_lib, cb_module, + circuit_lib, sram_orgz_type, sram_model, + verbose); + } + /* Add global ports to the pb_module: * This is a much easier job after adding sub modules (instances), * we just need to find all the global ports from the child modules and build @@ -970,9 +1052,13 @@ static void build_connection_block_module( * we just need to find all the I/O ports from the child modules and build a * list of it */ + ModuleManager::e_config_child_type config_child_type = + group_config_block ? ModuleManager::e_config_child_type::PHYSICAL + : ModuleManager::e_config_child_type::LOGICAL; size_t module_num_config_bits = find_module_num_config_bits_from_child_modules( - module_manager, cb_module, circuit_lib, sram_model, sram_orgz_type); + module_manager, cb_module, circuit_lib, sram_model, sram_orgz_type, + config_child_type); if (0 < module_num_config_bits) { add_pb_sram_ports_to_module_manager(module_manager, cb_module, circuit_lib, sram_model, sram_orgz_type, @@ -983,10 +1069,11 @@ static void build_connection_block_module( * primitive modules This is a one-shot addition that covers all the memory * modules in this primitive module! */ - if (0 < module_manager.configurable_children(cb_module).size()) { + if (0 < + module_manager.num_configurable_children(cb_module, config_child_type)) { add_pb_module_nets_memory_config_bus( module_manager, decoder_lib, cb_module, sram_orgz_type, - circuit_lib.design_tech_type(sram_model)); + circuit_lib.design_tech_type(sram_model), config_child_type); } VTR_LOGV(verbose, "Done\n"); @@ -1002,7 +1089,7 @@ static void build_flatten_connection_block_modules( const DeviceRRGSB& device_rr_gsb, const CircuitLibrary& circuit_lib, const e_config_protocol_type& sram_orgz_type, const CircuitModelId& sram_model, const t_rr_type& cb_type, - const bool& verbose) { + const bool& group_config_block, const bool& verbose) { /* Build unique X-direction connection block modules */ vtr::Point cb_range = device_rr_gsb.get_gsb_range(); @@ -1019,7 +1106,7 @@ static void build_flatten_connection_block_modules( build_connection_block_module( module_manager, decoder_lib, device_annotation, device_ctx.grid, device_ctx.rr_graph, circuit_lib, sram_orgz_type, sram_model, rr_gsb, - cb_type, verbose); + cb_type, group_config_block, verbose); } } } @@ -1038,7 +1125,8 @@ void build_flatten_routing_modules( const DeviceContext& device_ctx, const VprDeviceAnnotation& device_annotation, const DeviceRRGSB& device_rr_gsb, const CircuitLibrary& circuit_lib, const e_config_protocol_type& sram_orgz_type, - const CircuitModelId& sram_model, const bool& verbose) { + const CircuitModelId& sram_model, const bool& group_config_block, + const bool& verbose) { vtr::ScopedStartFinishTimer timer("Build routing modules..."); vtr::Point sb_range = device_rr_gsb.get_gsb_range(); @@ -1053,17 +1141,19 @@ void build_flatten_routing_modules( build_switch_block_module(module_manager, decoder_lib, device_annotation, device_ctx.grid, device_ctx.rr_graph, circuit_lib, sram_orgz_type, sram_model, rr_gsb, - verbose); + group_config_block, verbose); } } build_flatten_connection_block_modules( module_manager, decoder_lib, device_ctx, device_annotation, device_rr_gsb, - circuit_lib, sram_orgz_type, sram_model, CHANX, verbose); + circuit_lib, sram_orgz_type, sram_model, CHANX, group_config_block, + verbose); build_flatten_connection_block_modules( module_manager, decoder_lib, device_ctx, device_annotation, device_rr_gsb, - circuit_lib, sram_orgz_type, sram_model, CHANY, verbose); + circuit_lib, sram_orgz_type, sram_model, CHANY, group_config_block, + verbose); } /******************************************************************** @@ -1082,7 +1172,8 @@ void build_unique_routing_modules( const DeviceContext& device_ctx, const VprDeviceAnnotation& device_annotation, const DeviceRRGSB& device_rr_gsb, const CircuitLibrary& circuit_lib, const e_config_protocol_type& sram_orgz_type, - const CircuitModelId& sram_model, const bool& verbose) { + const CircuitModelId& sram_model, const bool& group_config_block, + const bool& verbose) { vtr::ScopedStartFinishTimer timer("Build unique routing modules..."); /* Build unique switch block modules */ @@ -1091,7 +1182,7 @@ void build_unique_routing_modules( build_switch_block_module(module_manager, decoder_lib, device_annotation, device_ctx.grid, device_ctx.rr_graph, circuit_lib, sram_orgz_type, sram_model, unique_mirror, - verbose); + group_config_block, verbose); } /* Build unique X-direction connection block modules */ @@ -1102,7 +1193,7 @@ void build_unique_routing_modules( build_connection_block_module( module_manager, decoder_lib, device_annotation, device_ctx.grid, device_ctx.rr_graph, circuit_lib, sram_orgz_type, sram_model, - unique_mirror, CHANX, verbose); + unique_mirror, CHANX, group_config_block, verbose); } /* Build unique X-direction connection block modules */ @@ -1113,7 +1204,7 @@ void build_unique_routing_modules( build_connection_block_module( module_manager, decoder_lib, device_annotation, device_ctx.grid, device_ctx.rr_graph, circuit_lib, sram_orgz_type, sram_model, - unique_mirror, CHANY, verbose); + unique_mirror, CHANY, group_config_block, verbose); } } diff --git a/openfpga/src/fabric/build_routing_modules.h b/openfpga/src/fabric/build_routing_modules.h index 59274bc11..038da3b3e 100644 --- a/openfpga/src/fabric/build_routing_modules.h +++ b/openfpga/src/fabric/build_routing_modules.h @@ -24,14 +24,16 @@ void build_flatten_routing_modules( const DeviceContext& device_ctx, const VprDeviceAnnotation& device_annotation, const DeviceRRGSB& device_rr_gsb, const CircuitLibrary& circuit_lib, const e_config_protocol_type& sram_orgz_type, - const CircuitModelId& sram_model, const bool& verbose); + const CircuitModelId& sram_model, const bool& group_config_block, + const bool& verbose); void build_unique_routing_modules( ModuleManager& module_manager, DecoderLibrary& decoder_lib, const DeviceContext& device_ctx, const VprDeviceAnnotation& device_annotation, const DeviceRRGSB& device_rr_gsb, const CircuitLibrary& circuit_lib, const e_config_protocol_type& sram_orgz_type, - const CircuitModelId& sram_model, const bool& verbose); + const CircuitModelId& sram_model, const bool& group_config_block, + const bool& verbose); } /* end namespace openfpga */ diff --git a/openfpga/src/fabric/build_tile_modules.cpp b/openfpga/src/fabric/build_tile_modules.cpp index 7f29a6279..88858cb0c 100644 --- a/openfpga/src/fabric/build_tile_modules.cpp +++ b/openfpga/src/fabric/build_tile_modules.cpp @@ -1331,8 +1331,9 @@ static int build_tile_module( if (0 < find_module_num_config_bits(module_manager, pb_module, circuit_lib, sram_model, sram_orgz_type)) { - module_manager.add_configurable_child(tile_module, pb_module, - pb_instance); + module_manager.add_configurable_child( + tile_module, pb_module, pb_instance, + ModuleManager::e_config_child_type::UNIFIED); } VTR_LOGV( verbose, @@ -1378,8 +1379,9 @@ static int build_tile_module( if (0 < find_module_num_config_bits(module_manager, cb_module, circuit_lib, sram_model, sram_orgz_type)) { - module_manager.add_configurable_child(tile_module, cb_module, - cb_instance); + module_manager.add_configurable_child( + tile_module, cb_module, cb_instance, + ModuleManager::e_config_child_type::UNIFIED); } VTR_LOGV(verbose, "Added connection block module '%s' (instance: '%s') to " @@ -1417,8 +1419,9 @@ static int build_tile_module( sb_instance_name); if (0 < find_module_num_config_bits(module_manager, sb_module, circuit_lib, sram_model, sram_orgz_type)) { - module_manager.add_configurable_child(tile_module, sb_module, - sb_instance); + module_manager.add_configurable_child( + tile_module, sb_module, sb_instance, + ModuleManager::e_config_child_type::UNIFIED); } VTR_LOGV( verbose, @@ -1468,7 +1471,8 @@ static int build_tile_module( */ size_t module_num_config_bits = find_module_num_config_bits_from_child_modules( - module_manager, tile_module, circuit_lib, sram_model, sram_orgz_type); + module_manager, tile_module, circuit_lib, sram_model, sram_orgz_type, + ModuleManager::e_config_child_type::LOGICAL); if (0 < module_num_config_bits) { add_pb_sram_ports_to_module_manager(module_manager, tile_module, circuit_lib, sram_model, sram_orgz_type, @@ -1479,10 +1483,12 @@ static int build_tile_module( * This is a one-shot addition that covers all the memory modules in this pb * module! */ - if (0 < module_manager.configurable_children(tile_module).size()) { + if (0 < module_manager.num_configurable_children( + tile_module, ModuleManager::e_config_child_type::LOGICAL)) { add_pb_module_nets_memory_config_bus( module_manager, decoder_lib, tile_module, sram_orgz_type, - circuit_lib.design_tech_type(sram_model)); + circuit_lib.design_tech_type(sram_model), + ModuleManager::e_config_child_type::LOGICAL); } VTR_LOGV(verbose, "Done\n"); diff --git a/openfpga/src/fabric/build_top_module.cpp b/openfpga/src/fabric/build_top_module.cpp index cb98ed8dd..e8e5066a1 100644 --- a/openfpga/src/fabric/build_top_module.cpp +++ b/openfpga/src/fabric/build_top_module.cpp @@ -57,7 +57,8 @@ int build_top_module( const CircuitModelId& sram_model, const FabricTile& fabric_tile, const bool& frame_view, const bool& compact_routing_hierarchy, const bool& duplicate_grid_pin, const FabricKey& fabric_key, - const bool& generate_random_fabric_key, const bool& verbose) { + const bool& generate_random_fabric_key, const bool& group_config_block, + const bool& verbose) { vtr::ScopedStartFinishTimer timer("Build FPGA fabric module"); int status = CMD_EXEC_SUCCESS; @@ -75,14 +76,15 @@ int build_top_module( module_manager, top_module, blwl_sr_banks, circuit_lib, clk_ntwk, rr_clock_lookup, vpr_device_annotation, grids, tile_annotation, rr_graph, device_rr_gsb, tile_direct, arch_direct, config_protocol, sram_model, - frame_view, compact_routing_hierarchy, duplicate_grid_pin, fabric_key); + frame_view, compact_routing_hierarchy, duplicate_grid_pin, fabric_key, + group_config_block); } else { /* TODO: Build the tile instances under the top module */ status = build_top_module_tile_child_instances( module_manager, top_module, blwl_sr_banks, circuit_lib, clk_ntwk, rr_clock_lookup, vpr_device_annotation, grids, tile_annotation, rr_graph, device_rr_gsb, tile_direct, arch_direct, fabric_tile, config_protocol, - sram_model, fabric_key, frame_view, verbose); + sram_model, fabric_key, group_config_block, frame_view, verbose); } if (status != CMD_EXEC_SUCCESS) { @@ -134,7 +136,10 @@ int build_top_module( * module! */ if (false == frame_view) { - if (0 < module_manager.configurable_children(top_module).size()) { + if (0 < module_manager + .configurable_children( + top_module, ModuleManager::e_config_child_type::PHYSICAL) + .size()) { add_top_module_nets_memory_config_bus( module_manager, decoder_lib, blwl_sr_banks, top_module, circuit_lib, config_protocol, circuit_lib.design_tech_type(sram_model), diff --git a/openfpga/src/fabric/build_top_module.h b/openfpga/src/fabric/build_top_module.h index 46fe36219..d62ac4993 100644 --- a/openfpga/src/fabric/build_top_module.h +++ b/openfpga/src/fabric/build_top_module.h @@ -44,7 +44,8 @@ int build_top_module( const CircuitModelId& sram_model, const FabricTile& fabric_tile, const bool& frame_view, const bool& compact_routing_hierarchy, const bool& duplicate_grid_pin, const FabricKey& fabric_key, - const bool& generate_random_fabric_key, const bool& verbose); + const bool& generate_random_fabric_key, const bool& group_config_block, + const bool& verbose); } /* end namespace openfpga */ diff --git a/openfpga/src/fabric/build_top_module_child_fine_grained_instance.cpp b/openfpga/src/fabric/build_top_module_child_fine_grained_instance.cpp index 109f29c08..78e2565d0 100644 --- a/openfpga/src/fabric/build_top_module_child_fine_grained_instance.cpp +++ b/openfpga/src/fabric/build_top_module_child_fine_grained_instance.cpp @@ -436,7 +436,7 @@ int build_top_module_fine_grained_child_instances( const ArchDirect& arch_direct, const ConfigProtocol& config_protocol, const CircuitModelId& sram_model, const bool& frame_view, const bool& compact_routing_hierarchy, const bool& duplicate_grid_pin, - const FabricKey& fabric_key) { + const FabricKey& fabric_key, const bool& group_config_block) { int status = CMD_EXEC_SUCCESS; std::map> cb_instance_ids; @@ -529,7 +529,8 @@ int build_top_module_fine_grained_child_instances( /* Update the memory organization in sub module (non-top) */ status = load_submodules_memory_modules_from_fabric_key( - module_manager, circuit_lib, config_protocol, fabric_key); + module_manager, circuit_lib, config_protocol, fabric_key, + group_config_block); if (CMD_EXEC_FATAL_ERROR == status) { return status; } diff --git a/openfpga/src/fabric/build_top_module_child_fine_grained_instance.h b/openfpga/src/fabric/build_top_module_child_fine_grained_instance.h index 7db61cb93..41628ac79 100644 --- a/openfpga/src/fabric/build_top_module_child_fine_grained_instance.h +++ b/openfpga/src/fabric/build_top_module_child_fine_grained_instance.h @@ -43,7 +43,7 @@ int build_top_module_fine_grained_child_instances( const ArchDirect& arch_direct, const ConfigProtocol& config_protocol, const CircuitModelId& sram_model, const bool& frame_view, const bool& compact_routing_hierarchy, const bool& duplicate_grid_pin, - const FabricKey& fabric_key); + const FabricKey& fabric_key, const bool& group_config_block); } /* end namespace openfpga */ diff --git a/openfpga/src/fabric/build_top_module_child_tile_instance.cpp b/openfpga/src/fabric/build_top_module_child_tile_instance.cpp index acd844766..664be1ceb 100644 --- a/openfpga/src/fabric/build_top_module_child_tile_instance.cpp +++ b/openfpga/src/fabric/build_top_module_child_tile_instance.cpp @@ -1076,7 +1076,11 @@ static void organize_top_module_tile_based_memory_modules( const CircuitModelId& sram_model, const DeviceGrid& grids, const vtr::Matrix& tile_instance_ids, const FabricTile& fabric_tile) { /* Ensure clean vectors to return */ - VTR_ASSERT(true == module_manager.configurable_children(top_module).empty()); + VTR_ASSERT(true == + module_manager + .configurable_children( + top_module, ModuleManager::e_config_child_type::PHYSICAL) + .empty()); std::vector> tile_coords; bool positive_direction = true; @@ -1116,6 +1120,7 @@ static void organize_top_module_tile_based_memory_modules( module_manager.add_configurable_child( top_module, tile_module, tile_instance_ids[curr_tile_coord.x()][curr_tile_coord.y()], + ModuleManager::e_config_child_type::UNIFIED, vtr::Point(curr_tile_coord.x(), curr_tile_coord.y())); } } @@ -1859,7 +1864,8 @@ int build_top_module_tile_child_instances( const DeviceRRGSB& device_rr_gsb, const TileDirect& tile_direct, const ArchDirect& arch_direct, const FabricTile& fabric_tile, const ConfigProtocol& config_protocol, const CircuitModelId& sram_model, - const FabricKey& fabric_key, const bool& frame_view, const bool& verbose) { + const FabricKey& fabric_key, const bool& group_config_block, + const bool& frame_view, const bool& verbose) { int status = CMD_EXEC_SUCCESS; vtr::Matrix tile_instance_ids; status = add_top_module_tile_instances(module_manager, top_module, @@ -1941,7 +1947,8 @@ int build_top_module_tile_child_instances( /* Update the memory organization in sub module (non-top) */ status = load_submodules_memory_modules_from_fabric_key( - module_manager, circuit_lib, config_protocol, fabric_key); + module_manager, circuit_lib, config_protocol, fabric_key, + group_config_block); if (CMD_EXEC_FATAL_ERROR == status) { return status; } diff --git a/openfpga/src/fabric/build_top_module_child_tile_instance.h b/openfpga/src/fabric/build_top_module_child_tile_instance.h index 02df43e76..5adc39c75 100644 --- a/openfpga/src/fabric/build_top_module_child_tile_instance.h +++ b/openfpga/src/fabric/build_top_module_child_tile_instance.h @@ -42,7 +42,8 @@ int build_top_module_tile_child_instances( const DeviceRRGSB& device_rr_gsb, const TileDirect& tile_direct, const ArchDirect& arch_direct, const FabricTile& fabric_tile, const ConfigProtocol& config_protocol, const CircuitModelId& sram_model, - const FabricKey& fabric_key, const bool& frame_view, const bool& verbose); + const FabricKey& fabric_key, const bool& group_config_block, + const bool& frame_view, const bool& verbose); } /* end namespace openfpga */ diff --git a/openfpga/src/fabric/build_top_module_memory.cpp b/openfpga/src/fabric/build_top_module_memory.cpp index 92eef9967..4e0b45c98 100644 --- a/openfpga/src/fabric/build_top_module_memory.cpp +++ b/openfpga/src/fabric/build_top_module_memory.cpp @@ -86,7 +86,7 @@ static void organize_top_module_tile_cb_modules( 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); + ModuleManager::e_config_child_type::UNIFIED, config_coord); } } @@ -173,7 +173,8 @@ static void organize_top_module_tile_memory_modules( 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); + sb_instance_ids[rr_gsb.get_sb_x()][rr_gsb.get_sb_y()], + ModuleManager::e_config_child_type::UNIFIED, config_coord); } } @@ -219,7 +220,8 @@ static void organize_top_module_tile_memory_modules( 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); + grid_instance_ids[tile_coord.x()][tile_coord.y()], + ModuleManager::e_config_child_type::UNIFIED, config_coord); } } @@ -269,14 +271,21 @@ void build_top_module_configurable_regions( "Build configurable regions for the top module"); /* Ensure we have valid configurable children */ - VTR_ASSERT(false == module_manager.configurable_children(top_module).empty()); + VTR_ASSERT(false == + module_manager + .configurable_children( + top_module, ModuleManager::e_config_child_type::PHYSICAL) + .empty()); /* Ensure that our region definition is valid */ VTR_ASSERT(1 <= config_protocol.num_regions()); /* Exclude decoders from the list */ size_t num_configurable_children = - module_manager.configurable_children(top_module).size(); + module_manager + .configurable_children(top_module, + ModuleManager::e_config_child_type::PHYSICAL) + .size(); if (CONFIG_MEM_MEMORY_BANK == config_protocol.type() || CONFIG_MEM_QL_MEMORY_BANK == config_protocol.type()) { num_configurable_children -= 2; @@ -291,7 +300,10 @@ void build_top_module_configurable_regions( bool create_region = true; ConfigRegionId curr_region = ConfigRegionId::INVALID(); for (size_t ichild = 0; - ichild < module_manager.configurable_children(top_module).size(); + ichild < module_manager + .configurable_children( + top_module, ModuleManager::e_config_child_type::PHYSICAL) + .size(); ++ichild) { if (true == create_region) { curr_region = module_manager.add_config_region(top_module); @@ -300,8 +312,11 @@ void build_top_module_configurable_regions( /* Add the child to a region */ module_manager.add_configurable_child_to_region( top_module, curr_region, - module_manager.configurable_children(top_module)[ichild], - module_manager.configurable_child_instances(top_module)[ichild], ichild); + module_manager.configurable_children( + top_module, ModuleManager::e_config_child_type::PHYSICAL)[ichild], + module_manager.configurable_child_instances( + top_module, ModuleManager::e_config_child_type::PHYSICAL)[ichild], + ichild); /* See if the current region is full or not: * For the last region, we will keep adding until we finish all the children @@ -427,7 +442,11 @@ void organize_top_module_memory_modules( const std::map>& cb_instance_ids, const bool& compact_routing_hierarchy) { /* Ensure clean vectors to return */ - VTR_ASSERT(true == module_manager.configurable_children(top_module).empty()); + VTR_ASSERT(true == + module_manager + .configurable_children( + top_module, ModuleManager::e_config_child_type::PHYSICAL) + .empty()); /* First, organize the I/O tiles on the border */ /* Special for the I/O tileas on RIGHT and BOTTOM, @@ -530,7 +549,11 @@ void organize_top_module_memory_modules( void shuffle_top_module_configurable_children( ModuleManager& module_manager, const ModuleId& top_module, const ConfigProtocol& config_protocol) { - size_t num_keys = module_manager.configurable_children(top_module).size(); + size_t num_keys = + module_manager + .configurable_children(top_module, + ModuleManager::e_config_child_type::PHYSICAL) + .size(); std::vector shuffled_keys; shuffled_keys.reserve(num_keys); for (size_t ikey = 0; ikey < num_keys; ++ikey) { @@ -541,11 +564,14 @@ void shuffle_top_module_configurable_children( /* Cache the configurable children and their instances */ std::vector orig_configurable_children = - module_manager.configurable_children(top_module); + module_manager.configurable_children( + top_module, ModuleManager::e_config_child_type::PHYSICAL); std::vector orig_configurable_child_instances = - module_manager.configurable_child_instances(top_module); + module_manager.configurable_child_instances( + top_module, ModuleManager::e_config_child_type::PHYSICAL); std::vector> orig_configurable_child_coordinates = - module_manager.configurable_child_coordinates(top_module); + module_manager.configurable_child_coordinates( + top_module, ModuleManager::e_config_child_type::PHYSICAL); /* Reorganize the configurable children */ module_manager.clear_configurable_children(top_module); @@ -554,6 +580,7 @@ void shuffle_top_module_configurable_children( module_manager.add_configurable_child( top_module, orig_configurable_children[shuffled_keys[ikey]], orig_configurable_child_instances[shuffled_keys[ikey]], + ModuleManager::e_config_child_type::UNIFIED, orig_configurable_child_coordinates[shuffled_keys[ikey]]); } @@ -650,9 +677,10 @@ int load_top_module_memory_modules_from_fabric_key( } /* Now we can add the child to configurable children of the top module */ - module_manager.add_configurable_child(top_module, instance_info.first, - instance_info.second, - fabric_key.key_coordinate(key)); + module_manager.add_configurable_child( + top_module, instance_info.first, instance_info.second, + ModuleManager::e_config_child_type::UNIFIED, + fabric_key.key_coordinate(key)); module_manager.add_configurable_child_to_region( top_module, top_module_config_region, instance_info.first, instance_info.second, curr_configurable_child_id); @@ -1329,17 +1357,27 @@ static void add_top_module_nets_cmos_memory_bank_config_bus( * Note: this MUST be done after adding all the module nets to other regular * configurable children */ - module_manager.add_configurable_child(top_module, bl_decoder_module, - curr_bl_decoder_instance_id); + module_manager.add_configurable_child( + top_module, bl_decoder_module, curr_bl_decoder_instance_id, + ModuleManager::e_config_child_type::PHYSICAL); module_manager.add_configurable_child_to_region( top_module, config_region, bl_decoder_module, curr_bl_decoder_instance_id, - module_manager.configurable_children(top_module).size() - 1); + module_manager + .configurable_children(top_module, + ModuleManager::e_config_child_type::PHYSICAL) + .size() - + 1); - module_manager.add_configurable_child(top_module, wl_decoder_module, - curr_wl_decoder_instance_id); + module_manager.add_configurable_child( + top_module, wl_decoder_module, curr_wl_decoder_instance_id, + ModuleManager::e_config_child_type::PHYSICAL); module_manager.add_configurable_child_to_region( top_module, config_region, wl_decoder_module, curr_wl_decoder_instance_id, - module_manager.configurable_children(top_module).size() - 1); + module_manager + .configurable_children(top_module, + ModuleManager::e_config_child_type::PHYSICAL) + .size() - + 1); } } @@ -1759,8 +1797,8 @@ static void add_top_module_nets_cmos_memory_frame_decoder_config_bus( for (size_t mem_index = 0; mem_index < configurable_children.size(); ++mem_index) { ModuleId child_module = configurable_children[mem_index]; - size_t child_instance = - module_manager.configurable_child_instances(parent_module)[mem_index]; + size_t child_instance = module_manager.configurable_child_instances( + parent_module, ModuleManager::e_config_child_type::PHYSICAL)[mem_index]; ModulePortId child_din_port = module_manager.find_module_port( child_module, std::string(DECODER_DATA_IN_PORT_NAME)); BasicPort child_din_port_info = @@ -1794,8 +1832,8 @@ static void add_top_module_nets_cmos_memory_frame_decoder_config_bus( for (size_t mem_index = 0; mem_index < configurable_children.size(); ++mem_index) { ModuleId child_module = configurable_children[mem_index]; - size_t child_instance = - module_manager.configurable_child_instances(parent_module)[mem_index]; + size_t child_instance = module_manager.configurable_child_instances( + parent_module, ModuleManager::e_config_child_type::PHYSICAL)[mem_index]; ModulePortId child_en_port = module_manager.find_module_port( child_module, std::string(DECODER_ENABLE_PORT_NAME)); BasicPort child_en_port_info = @@ -1814,12 +1852,17 @@ static void add_top_module_nets_cmos_memory_frame_decoder_config_bus( } /* Add the decoder as the last configurable children */ - module_manager.add_configurable_child(parent_module, decoder_module, - decoder_instance); + module_manager.add_configurable_child( + parent_module, decoder_module, decoder_instance, + ModuleManager::e_config_child_type::PHYSICAL); /* Register the configurable child to configuration region */ module_manager.add_configurable_child_to_region( parent_module, config_region, decoder_module, decoder_instance, - module_manager.configurable_children(parent_module).size() - 1); + module_manager + .configurable_children(parent_module, + ModuleManager::e_config_child_type::PHYSICAL) + .size() - + 1); } /********************************************************************* @@ -1927,10 +1970,10 @@ static void add_top_module_nets_cmos_memory_config_bus( case CONFIG_MEM_STANDALONE: add_module_nets_cmos_flatten_memory_config_bus( module_manager, parent_module, config_protocol.type(), - CIRCUIT_MODEL_PORT_BL); + CIRCUIT_MODEL_PORT_BL, ModuleManager::e_config_child_type::PHYSICAL); add_module_nets_cmos_flatten_memory_config_bus( module_manager, parent_module, config_protocol.type(), - CIRCUIT_MODEL_PORT_WL); + CIRCUIT_MODEL_PORT_WL, ModuleManager::e_config_child_type::PHYSICAL); break; case CONFIG_MEM_SCAN_CHAIN: { add_top_module_nets_cmos_memory_chain_config_bus( diff --git a/openfpga/src/fabric/build_top_module_memory_bank.cpp b/openfpga/src/fabric/build_top_module_memory_bank.cpp index 0e5823ae2..62b12f254 100644 --- a/openfpga/src/fabric/build_top_module_memory_bank.cpp +++ b/openfpga/src/fabric/build_top_module_memory_bank.cpp @@ -58,7 +58,11 @@ static void add_module_nets_to_ql_memory_bank_shift_register_module( const std::string& chain_head_port_name, const std::string& chain_tail_port_name) { for (size_t mem_index = 0; - mem_index < module_manager.configurable_children(parent_module).size(); + mem_index < + module_manager + .configurable_children(parent_module, + ModuleManager::e_config_child_type::PHYSICAL) + .size(); ++mem_index) { ModuleId net_src_module_id; size_t net_src_instance_id; @@ -78,28 +82,30 @@ static void add_module_nets_to_ql_memory_bank_shift_register_module( /* Find the port name of next memory module */ std::string sink_port_name = circuit_lib.port_prefix(model_input_port); - net_sink_module_id = - module_manager.configurable_children(parent_module)[mem_index]; - net_sink_instance_id = - module_manager.configurable_child_instances(parent_module)[mem_index]; + net_sink_module_id = module_manager.configurable_children( + parent_module, ModuleManager::e_config_child_type::PHYSICAL)[mem_index]; + net_sink_instance_id = module_manager.configurable_child_instances( + parent_module, ModuleManager::e_config_child_type::PHYSICAL)[mem_index]; net_sink_port_id = module_manager.find_module_port(net_sink_module_id, sink_port_name); } else { /* Find the port name of previous memory module */ std::string src_port_name = circuit_lib.port_prefix(model_output_port); - net_src_module_id = - module_manager.configurable_children(parent_module)[mem_index - 1]; + net_src_module_id = module_manager.configurable_children( + parent_module, + ModuleManager::e_config_child_type::PHYSICAL)[mem_index - 1]; net_src_instance_id = module_manager.configurable_child_instances( - parent_module)[mem_index - 1]; + parent_module, + ModuleManager::e_config_child_type::PHYSICAL)[mem_index - 1]; net_src_port_id = module_manager.find_module_port(net_src_module_id, src_port_name); /* Find the port name of next memory module */ std::string sink_port_name = circuit_lib.port_prefix(model_input_port); - net_sink_module_id = - module_manager.configurable_children(parent_module)[mem_index]; - net_sink_instance_id = - module_manager.configurable_child_instances(parent_module)[mem_index]; + net_sink_module_id = module_manager.configurable_children( + parent_module, ModuleManager::e_config_child_type::PHYSICAL)[mem_index]; + net_sink_instance_id = module_manager.configurable_child_instances( + parent_module, ModuleManager::e_config_child_type::PHYSICAL)[mem_index]; net_sink_port_id = module_manager.find_module_port(net_sink_module_id, sink_port_name); } @@ -133,9 +139,15 @@ static void add_module_nets_to_ql_memory_bank_shift_register_module( /* Find the port name of previous memory module */ std::string src_port_name = circuit_lib.port_prefix(model_output_port); ModuleId net_src_module_id = - module_manager.configurable_children(parent_module).back(); + module_manager + .configurable_children(parent_module, + ModuleManager::e_config_child_type::PHYSICAL) + .back(); size_t net_src_instance_id = - module_manager.configurable_child_instances(parent_module).back(); + module_manager + .configurable_child_instances( + parent_module, ModuleManager::e_config_child_type::PHYSICAL) + .back(); ModulePortId net_src_port_id = module_manager.find_module_port(net_src_module_id, src_port_name); @@ -244,8 +256,9 @@ static ModuleId build_bl_shift_register_chain_module( size_t sram_mem_instance = module_manager.num_instance(mem_module, sram_mem_module); module_manager.add_child_module(mem_module, sram_mem_module); - module_manager.add_configurable_child(mem_module, sram_mem_module, - sram_mem_instance); + module_manager.add_configurable_child( + mem_module, sram_mem_module, sram_mem_instance, + ModuleManager::e_config_child_type::UNIFIED); /* Build module nets to wire bl outputs of sram modules to BL outputs of * memory module */ @@ -362,8 +375,9 @@ static ModuleId build_wl_shift_register_chain_module( size_t sram_mem_instance = module_manager.num_instance(mem_module, sram_mem_module); module_manager.add_child_module(mem_module, sram_mem_module); - module_manager.add_configurable_child(mem_module, sram_mem_module, - sram_mem_instance); + module_manager.add_configurable_child( + mem_module, sram_mem_module, sram_mem_instance, + ModuleManager::e_config_child_type::UNIFIED); /* Build module nets to wire wl outputs of sram modules to WL outputs of * memory module */ @@ -698,11 +712,16 @@ static void add_top_module_nets_cmos_ql_memory_bank_bl_decoder_config_bus( * Note: this MUST be done after adding all the module nets to other regular * configurable children */ - module_manager.add_configurable_child(top_module, bl_decoder_module, - curr_bl_decoder_instance_id); + module_manager.add_configurable_child( + top_module, bl_decoder_module, curr_bl_decoder_instance_id, + ModuleManager::e_config_child_type::UNIFIED); module_manager.add_configurable_child_to_region( top_module, config_region, bl_decoder_module, curr_bl_decoder_instance_id, - module_manager.configurable_children(top_module).size() - 1); + module_manager + .configurable_children(top_module, + ModuleManager::e_config_child_type::PHYSICAL) + .size() - + 1); } } @@ -967,11 +986,16 @@ static void add_top_module_nets_cmos_ql_memory_bank_wl_decoder_config_bus( * Note: this MUST be done after adding all the module nets to other regular * configurable children */ - module_manager.add_configurable_child(top_module, wl_decoder_module, - curr_wl_decoder_instance_id); + module_manager.add_configurable_child( + top_module, wl_decoder_module, curr_wl_decoder_instance_id, + ModuleManager::e_config_child_type::UNIFIED); module_manager.add_configurable_child_to_region( top_module, config_region, wl_decoder_module, curr_wl_decoder_instance_id, - module_manager.configurable_children(top_module).size() - 1); + module_manager + .configurable_children(top_module, + ModuleManager::e_config_child_type::PHYSICAL) + .size() - + 1); } } diff --git a/openfpga/src/fabric/fabric_key_writer.cpp b/openfpga/src/fabric/fabric_key_writer.cpp index 9a7e41791..cef0a79d4 100644 --- a/openfpga/src/fabric/fabric_key_writer.cpp +++ b/openfpga/src/fabric/fabric_key_writer.cpp @@ -32,7 +32,10 @@ static int add_module_keys_to_fabric_key(const ModuleManager& module_manager, return CMD_EXEC_SUCCESS; } /* Bypass modules which does not have any configurable children */ - if (module_manager.configurable_children(curr_module).empty()) { + if (module_manager + .configurable_children(curr_module, + ModuleManager::e_config_child_type::PHYSICAL) + .empty()) { return CMD_EXEC_SUCCESS; } /* Now create the module and add subkey one by one */ @@ -41,12 +44,15 @@ static int add_module_keys_to_fabric_key(const ModuleManager& module_manager, return CMD_EXEC_FATAL_ERROR; } size_t num_config_child = - module_manager.configurable_children(curr_module).size(); + module_manager + .configurable_children(curr_module, + ModuleManager::e_config_child_type::PHYSICAL) + .size(); for (size_t ichild = 0; ichild < num_config_child; ++ichild) { - ModuleId child_module = - module_manager.configurable_children(curr_module)[ichild]; - size_t child_instance = - module_manager.configurable_child_instances(curr_module)[ichild]; + ModuleId child_module = module_manager.configurable_children( + curr_module, ModuleManager::e_config_child_type::PHYSICAL)[ichild]; + size_t child_instance = module_manager.configurable_child_instances( + curr_module, ModuleManager::e_config_child_type::PHYSICAL)[ichild]; FabricSubKeyId sub_key = fabric_key.create_module_key(key_module_id); fabric_key.set_sub_key_name(sub_key, @@ -111,7 +117,11 @@ int write_fabric_key_to_xml_file( /* Build a fabric key database by visiting all the configurable children */ FabricKey fabric_key; - size_t num_keys = module_manager.configurable_children(top_module).size(); + size_t num_keys = + module_manager + .configurable_children(top_module, + ModuleManager::e_config_child_type::PHYSICAL) + .size(); fabric_key.reserve_keys(num_keys); diff --git a/openfpga/src/fabric/module_manager.cpp b/openfpga/src/fabric/module_manager.cpp index 9b35670cd..48d03095d 100644 --- a/openfpga/src/fabric/module_manager.cpp +++ b/openfpga/src/fabric/module_manager.cpp @@ -26,6 +26,17 @@ ModuleManager::module_range ModuleManager::modules() const { return vtr::make_range(ids_.begin(), ids_.end()); } +std::vector ModuleManager::modules_by_usage( + const ModuleManager::e_module_usage_type& usage) const { + std::vector module_list; + for (ModuleId curr_module : ids_) { + if (usages_[curr_module] == usage) { + module_list.push_back(curr_module); + } + } + return module_list; +} + /* Find all the ports belonging to a module */ ModuleManager::module_port_range ModuleManager::module_ports( const ModuleId& module) const { @@ -78,28 +89,56 @@ std::vector ModuleManager::child_module_instances( /* Find all the configurable child modules under a parent module */ std::vector ModuleManager::configurable_children( - const ModuleId& parent_module) const { + const ModuleId& parent_module, const e_config_child_type& type) const { /* Validate the module_id */ VTR_ASSERT(valid_module_id(parent_module)); - return configurable_children_[parent_module]; + if (type == ModuleManager::e_config_child_type::LOGICAL) { + return logical_configurable_children_[parent_module]; + } + VTR_ASSERT(type == ModuleManager::e_config_child_type::PHYSICAL); + return physical_configurable_children_[parent_module]; } /* Find all the instances of configurable child modules under a parent module */ std::vector ModuleManager::configurable_child_instances( - const ModuleId& parent_module) const { + const ModuleId& parent_module, const e_config_child_type& type) const { /* Validate the module_id */ VTR_ASSERT(valid_module_id(parent_module)); - return configurable_child_instances_[parent_module]; + if (type == ModuleManager::e_config_child_type::LOGICAL) { + return logical_configurable_child_instances_[parent_module]; + } + VTR_ASSERT(type == ModuleManager::e_config_child_type::PHYSICAL); + return physical_configurable_child_instances_[parent_module]; } std::vector> ModuleManager::configurable_child_coordinates( + const ModuleId& parent_module, const e_config_child_type& type) const { + /* Validate the module_id */ + VTR_ASSERT(valid_module_id(parent_module)); + VTR_ASSERT(type == ModuleManager::e_config_child_type::PHYSICAL); + + return physical_configurable_child_coordinates_[parent_module]; +} + +/* Find all the configurable child modules under a parent module */ +std::vector ModuleManager::logical2physical_configurable_children( const ModuleId& parent_module) const { /* Validate the module_id */ VTR_ASSERT(valid_module_id(parent_module)); - return configurable_child_coordinates_[parent_module]; + return logical2physical_configurable_children_[parent_module]; +} + +/* Find all the instances of configurable child modules under a parent module */ +std::vector +ModuleManager::logical2physical_configurable_child_instance_names( + const ModuleId& parent_module) const { + /* Validate the module_id */ + VTR_ASSERT(valid_module_id(parent_module)); + + return logical2physical_configurable_child_instance_names_[parent_module]; } /* Find all the configurable child modules under a parent module */ @@ -166,7 +205,7 @@ std::vector ModuleManager::region_configurable_children( for (const size_t& child_id : config_region_children_[parent_module][region]) { region_config_children.push_back( - configurable_children_[parent_module][child_id]); + physical_configurable_children_[parent_module][child_id]); } return region_config_children; @@ -185,7 +224,7 @@ std::vector ModuleManager::region_configurable_child_instances( for (const size_t& child_id : config_region_children_[parent_module][region]) { region_config_child_instances.push_back( - configurable_child_instances_[parent_module][child_id]); + physical_configurable_child_instances_[parent_module][child_id]); } return region_config_child_instances; @@ -205,7 +244,7 @@ ModuleManager::region_configurable_child_coordinates( 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]); + physical_configurable_child_coordinates_[parent_module][child_id]); } return region_config_child_coordinates; @@ -376,6 +415,16 @@ size_t ModuleManager::instance_id(const ModuleId& parent_module, return size_t(-1); } +size_t ModuleManager::num_configurable_children( + const ModuleId& parent_module, const e_config_child_type& type) const { + VTR_ASSERT(valid_module_id(parent_module)); + if (type == ModuleManager::e_config_child_type::LOGICAL) { + return logical_configurable_children_[parent_module].size(); + } + VTR_ASSERT(type == ModuleManager::e_config_child_type::PHYSICAL); + return physical_configurable_children_[parent_module].size(); +} + ModuleManager::e_module_port_type ModuleManager::port_type( const ModuleId& module, const ModulePortId& port) const { /* validate both module id and port id*/ @@ -612,6 +661,26 @@ bool ModuleManager::net_sink_exist(const ModuleId& module, return false; } +bool ModuleManager::unified_configurable_children( + const ModuleId& curr_module) const { + if (logical_configurable_children_[curr_module].size() != + physical_configurable_children_[curr_module].size()) { + return false; + } + for (size_t ichild = 0; + ichild < logical_configurable_children_[curr_module].size(); ++ichild) { + if (logical_configurable_children_[curr_module][ichild] != + physical_configurable_children_[curr_module][ichild]) { + return false; + } + if (logical_configurable_child_instances_[curr_module][ichild] != + physical_configurable_child_instances_[curr_module][ichild]) { + return false; + } + } + return true; +} + /****************************************************************************** * Private Accessors ******************************************************************************/ @@ -654,10 +723,15 @@ ModuleId ModuleManager::add_module(const std::string& name) { children_.emplace_back(); num_child_instances_.emplace_back(); child_instance_names_.emplace_back(); - configurable_children_.emplace_back(); - configurable_child_instances_.emplace_back(); - configurable_child_regions_.emplace_back(); - configurable_child_coordinates_.emplace_back(); + logical_configurable_children_.emplace_back(); + logical_configurable_child_instances_.emplace_back(); + physical_configurable_children_.emplace_back(); + physical_configurable_child_instances_.emplace_back(); + physical_configurable_child_regions_.emplace_back(); + physical_configurable_child_coordinates_.emplace_back(); + + logical2physical_configurable_children_.emplace_back(); + logical2physical_configurable_child_instance_names_.emplace_back(); config_region_ids_.emplace_back(); config_region_children_.emplace_back(); @@ -903,6 +977,7 @@ 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 e_config_child_type& type, const vtr::Point coord) { /* Validate the id of both parent and child modules */ VTR_ASSERT(valid_module_id(parent_module)); @@ -910,29 +985,108 @@ void ModuleManager::add_configurable_child(const ModuleId& parent_module, /* Ensure that the instance id is in range */ VTR_ASSERT(child_instance < num_instance(parent_module, child_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); + if (type == ModuleManager::e_config_child_type::LOGICAL || + type == ModuleManager::e_config_child_type::UNIFIED) { + logical_configurable_children_[parent_module].push_back(child_module); + logical_configurable_child_instances_[parent_module].push_back( + child_instance); + } + if (type == ModuleManager::e_config_child_type::PHYSICAL || + type == ModuleManager::e_config_child_type::UNIFIED) { + physical_configurable_children_[parent_module].push_back(child_module); + physical_configurable_child_instances_[parent_module].push_back( + child_instance); + physical_configurable_child_regions_[parent_module].push_back( + ConfigRegionId::INVALID()); + physical_configurable_child_coordinates_[parent_module].push_back(coord); + } + + if (type == ModuleManager::e_config_child_type::UNIFIED) { + logical2physical_configurable_children_[parent_module].push_back( + child_module); + logical2physical_configurable_child_instance_names_[parent_module] + .emplace_back(); + } else if (type == ModuleManager::e_config_child_type::LOGICAL) { + logical2physical_configurable_children_[parent_module].emplace_back(); + logical2physical_configurable_child_instance_names_[parent_module] + .emplace_back(); + } } -void ModuleManager::reserve_configurable_child(const ModuleId& parent_module, - const size_t& num_children) { +void ModuleManager::set_logical2physical_configurable_child( + const ModuleId& parent_module, const size_t& logical_child_id, + const ModuleId& physical_child_module) { + /* Sanity checks */ VTR_ASSERT(valid_module_id(parent_module)); - /* Do reserve when the number of children is larger than current size of lists - */ - if (num_children > configurable_children_[parent_module].size()) { - configurable_children_[parent_module].reserve(num_children); + VTR_ASSERT(logical_child_id < + num_configurable_children( + parent_module, ModuleManager::e_config_child_type::LOGICAL)); + /* Create the pair */ + logical2physical_configurable_children_[parent_module][logical_child_id] = + physical_child_module; +} + +void ModuleManager::set_logical2physical_configurable_child_instance_name( + const ModuleId& parent_module, const size_t& logical_child_id, + const std::string& physical_child_instance_name) { + /* Sanity checks */ + VTR_ASSERT(valid_module_id(parent_module)); + VTR_ASSERT(logical_child_id < + num_configurable_children( + parent_module, ModuleManager::e_config_child_type::LOGICAL)); + /* Create the pair */ + logical2physical_configurable_child_instance_names_ + [parent_module][logical_child_id] = physical_child_instance_name; +} + +void ModuleManager::reserve_configurable_child( + const ModuleId& parent_module, const size_t& num_children, + const e_config_child_type& type) { + VTR_ASSERT(valid_module_id(parent_module)); + if (type == ModuleManager::e_config_child_type::LOGICAL || + type == ModuleManager::e_config_child_type::UNIFIED) { + /* Do reserve when the number of children is larger than current size of + * lists + */ + if (num_children > logical_configurable_children_[parent_module].size()) { + logical_configurable_children_[parent_module].reserve(num_children); + } + if (num_children > + logical_configurable_child_instances_[parent_module].size()) { + logical_configurable_child_instances_[parent_module].reserve( + num_children); + } + if (num_children > + logical2physical_configurable_children_[parent_module].size()) { + logical2physical_configurable_children_[parent_module].reserve( + num_children); + } + if (num_children > + logical2physical_configurable_child_instance_names_[parent_module] + .size()) { + logical2physical_configurable_child_instance_names_[parent_module] + .reserve(num_children); + } } - if (num_children > configurable_child_instances_[parent_module].size()) { - configurable_child_instances_[parent_module].reserve(num_children); - } - 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); + if (type == ModuleManager::e_config_child_type::PHYSICAL || + type == ModuleManager::e_config_child_type::UNIFIED) { + if (num_children > physical_configurable_children_[parent_module].size()) { + physical_configurable_children_[parent_module].reserve(num_children); + } + if (num_children > + physical_configurable_child_instances_[parent_module].size()) { + physical_configurable_child_instances_[parent_module].reserve( + num_children); + } + if (num_children > + physical_configurable_child_regions_[parent_module].size()) { + physical_configurable_child_regions_[parent_module].reserve(num_children); + } + if (num_children > + physical_configurable_child_coordinates_[parent_module].size()) { + physical_configurable_child_coordinates_[parent_module].reserve( + num_children); + } } } @@ -961,23 +1115,28 @@ void ModuleManager::add_configurable_child_to_region( /* Ensure that the child module is in the configurable children list */ VTR_ASSERT(child_module == - configurable_children(parent_module)[config_child_id]); + configurable_children( + parent_module, + ModuleManager::e_config_child_type::PHYSICAL)[config_child_id]); VTR_ASSERT(child_instance == - configurable_child_instances(parent_module)[config_child_id]); + configurable_child_instances( + parent_module, + ModuleManager::e_config_child_type::PHYSICAL)[config_child_id]); /* If the child is already in another region, error out */ - if ((true == - valid_region_id( - parent_module, - configurable_child_regions_[parent_module][config_child_id])) && + if ((true == valid_region_id( + parent_module, + physical_configurable_child_regions_[parent_module] + [config_child_id])) && (config_region != - configurable_child_regions_[parent_module][config_child_id])) { + physical_configurable_child_regions_[parent_module][config_child_id])) { VTR_LOGF_ERROR( __FILE__, __LINE__, "Try to add a configurable child '%s[%lu]' to region '%lu' which is " "already added to another region '%lu'!\n", module_name(child_module).c_str(), child_instance, size_t(config_region), - size_t(configurable_child_regions_[parent_module][config_child_id])); + size_t( + physical_configurable_child_regions_[parent_module][config_child_id])); exit(1); } @@ -1299,10 +1458,15 @@ ModuleId ModuleManager::create_wrapper_module( void ModuleManager::clear_configurable_children(const ModuleId& parent_module) { VTR_ASSERT(valid_module_id(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(); + logical_configurable_children_[parent_module].clear(); + logical_configurable_child_instances_[parent_module].clear(); + physical_configurable_children_[parent_module].clear(); + physical_configurable_child_instances_[parent_module].clear(); + physical_configurable_child_regions_[parent_module].clear(); + physical_configurable_child_coordinates_[parent_module].clear(); + + logical2physical_configurable_children_[parent_module].clear(); + logical2physical_configurable_child_instance_names_[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 ce936add9..235719cbc 100644 --- a/openfpga/src/fabric/module_manager.h +++ b/openfpga/src/fabric/module_manager.h @@ -53,8 +53,9 @@ class ModuleManager { * port should be applied to modules */ enum e_module_usage_type { - MODULE_TOP, /* Top-level module */ - MODULE_CONFIG, /* Configuration modules, i.e., decoders, sram etc. */ + MODULE_TOP, /* Top-level module */ + MODULE_CONFIG, /* Configuration modules, i.e., decoders, sram etc. */ + MODULE_CONFIG_GROUP, /* Configuration modules, i.e., decoders, sram etc. */ MODULE_INTERC, /* Programmable interconnection, e.g., routing multiplexer etc. */ MODULE_GRID, /* Grids (programmable blocks) */ @@ -68,6 +69,15 @@ class ModuleManager { NUM_MODULE_USAGE_TYPES }; + /* Type of configurable child: + * - logical: represent a logical configurable block, which may not contain a + * physical memory inside + * - physical: represent a physical configurable block, which contains a + * physical memory inside + * - unified: a unified block whose physical memory is also the logical memory + */ + enum class e_config_child_type { LOGICAL, PHYSICAL, UNIFIED, NUM_TYPES }; + public: /* Public Constructors */ public: /* Type implementations */ /* @@ -156,6 +166,11 @@ class ModuleManager { public: /* Public aggregators */ /* Find all the modules */ module_range modules() const; + /** @brief find all the modules with a given usage. Note that this function is + * not optimized when the number of modules are large. In most cases, the + * number of modules are fairly small (less than 10k). */ + std::vector modules_by_usage( + const ModuleManager::e_module_usage_type& usage) const; /* Find all the ports belonging to a module */ module_port_range module_ports(const ModuleId& module) const; /* Find all the nets belonging to a module */ @@ -167,14 +182,27 @@ class ModuleManager { const ModuleId& parent_module, const ModuleId& child_module) const; /* Find all the configurable child modules under a parent module */ std::vector configurable_children( - const ModuleId& parent_module) const; + const ModuleId& parent_module, const e_config_child_type& type) const; /* Find all the instances of configurable child modules under a parent module */ std::vector configurable_child_instances( - const ModuleId& parent_module) const; + const ModuleId& parent_module, const e_config_child_type& type) const; /* Find the coordindate of a configurable child module under a parent module */ std::vector> configurable_child_coordinates( + const ModuleId& parent_module, const e_config_child_type& type) const; + + /* Find all the configurable child modules under a parent module + * Note that a physical configurable child module may be at + * another module; Only the logical child module is under the current parent + * module + */ + std::vector logical2physical_configurable_children( + const ModuleId& parent_module) const; + /* Find all the instance names of configurable child modules under a parent + * module + */ + std::vector logical2physical_configurable_child_instance_names( const ModuleId& parent_module) const; /* Find all the I/O child modules under a parent module */ @@ -195,16 +223,17 @@ class ModuleManager { /* Find all the regions */ region_range regions(const ModuleId& module) const; /* Find all the configurable child modules under a region of a parent module + * Note that we use logical children here */ std::vector region_configurable_children( const ModuleId& parent_module, const ConfigRegionId& region) const; /* Find all the instances of configurable child modules under a region of a - * parent module */ + * parent module; Note that we use logical children here */ 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 */ + * parent module; Note that we use logical children here */ std::vector> region_configurable_child_coordinates( const ModuleId& parent_module, const ConfigRegionId& region) const; @@ -238,6 +267,9 @@ class ModuleManager { size_t instance_id(const ModuleId& parent_module, const ModuleId& child_module, const std::string& instance_name) const; + /** @brief Count the number of logical configurable children */ + size_t num_configurable_children(const ModuleId& parent_module, + const e_config_child_type& type) const; /* Find the type of a port */ ModuleManager::e_module_port_type port_type(const ModuleId& module, const ModulePortId& port) const; @@ -295,6 +327,11 @@ class ModuleManager { const ModuleId& sink_module, const size_t& instance_id, const ModulePortId& sink_port, const size_t& sink_pin); + /** @brief Check if the configurable children under a given module are unified + * or not. If unified, it means that the logical configurable children are the + * same as the physical configurable children */ + bool unified_configurable_children(const ModuleId& curr_module) const; + private: /* Private accessors */ size_t find_child_module_index_in_parent_module( const ModuleId& parent_module, const ModuleId& child_module) const; @@ -357,18 +394,29 @@ class ModuleManager { */ void add_configurable_child( const ModuleId& module, const ModuleId& child_module, - const size_t& child_instance, + const size_t& child_instance, const e_config_child_type& type, const vtr::Point coord = vtr::Point(-1, -1)); + /** @brief Create a pair of mapping from a logical configurable child to a + * physical configurable child */ + void set_logical2physical_configurable_child( + const ModuleId& parent_module, const size_t& logical_child_id, + const ModuleId& physical_child_module); + /** @brief Create a pair of mapping from a logical configurable child to a + * physical configurable child */ + void set_logical2physical_configurable_child_instance_name( + const ModuleId& parent_module, const size_t& logical_child_id, + const std::string& physical_child_instance_name); /* Reserved a number of configurable children for memory efficiency */ void reserve_configurable_child(const ModuleId& module, - const size_t& num_children); + const size_t& num_children, + const e_config_child_type& type); /* Create a new configurable region under a module */ ConfigRegionId add_config_region(const ModuleId& module); /* Add a configurable child module to a region * Note: - * - The child module must be added as a configurable child to the parent - * module before calling this function! + * - The child module must be added as a physical configurable child to the + * parent module before calling this function! */ void add_configurable_child_to_region(const ModuleId& parent_module, const ConfigRegionId& config_region, @@ -511,23 +559,48 @@ class ModuleManager { * is configured first, etc. Note that the sequence can be totally different * from the children_ list This is really dependent how the configuration * protocol is organized which should be made by users/designers + * Note that there could be two types of configurable children under a module + * - logical: only contains virtual/feedthough memory blocks. A logical + * configurable child can only contain logical subchild. Logical memory block + * is required for architecture bitstream generation, because it carries + * logical information (the location of memory to its programmable resources) + * - physical: contains physical memory blocks. Logical memory blocks are + * mapped to the physical memory block. A physical memory block may contain + * coordinates and configuration regions which are required for fabric + * bitstream generation. */ vtr::vector> - configurable_children_; /* Child modules with configurable memory bits that - this module contain */ + logical_configurable_children_; /* Child modules with configurable memory + bits that this module contain */ vtr::vector> - configurable_child_instances_; /* Instances of child modules with + logical_configurable_child_instances_; /* Instances of child modules with + configurable memory bits that this module + contain */ + vtr::vector> + logical2physical_configurable_children_; /* Child modules with configurable + memory bits that this module contain */ + vtr::vector> + logical2physical_configurable_child_instance_names_; /* Instances of child + modules with configurable memory bits that + this module contain */ + + vtr::vector> + physical_configurable_children_; /* Child modules with configurable memory + bits that this module contain */ + vtr::vector> + physical_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 */ + physical_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 */ + physical_configurable_child_coordinates_; /* Relative coorindates of child + modules with configurable memory bits + that this module contain */ - /* Configurable regions to group the configurable children + /* Configurable regions to group the physical configurable children * Note: * - Each child can only be added a group */ diff --git a/openfpga/src/fpga_bitstream/build_device_bitstream.cpp b/openfpga/src/fpga_bitstream/build_device_bitstream.cpp index 1e283358e..d4a15986f 100644 --- a/openfpga/src/fpga_bitstream/build_device_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/build_device_bitstream.cpp @@ -35,15 +35,19 @@ static size_t rec_estimate_device_bitstream_num_blocks( * actually configurable memory elements * We skip them in couting */ - if (0 == module_manager.configurable_children(top_module).size()) { + if (0 == module_manager.num_configurable_children( + top_module, ModuleManager::e_config_child_type::PHYSICAL)) { return 0; } size_t num_configurable_children = - module_manager.configurable_children(top_module).size(); + module_manager + .configurable_children(top_module, + ModuleManager::e_config_child_type::PHYSICAL) + .size(); for (size_t ichild = 0; ichild < num_configurable_children; ++ichild) { - ModuleId child_module = - module_manager.configurable_children(top_module)[ichild]; + ModuleId child_module = module_manager.configurable_children( + top_module, ModuleManager::e_config_child_type::PHYSICAL)[ichild]; num_blocks += rec_estimate_device_bitstream_num_blocks(module_manager, child_module); } @@ -68,7 +72,8 @@ static size_t rec_estimate_device_bitstream_num_bits( /* If a child module has no configurable children, this is a leaf node * We can count it in. Otherwise, we should go recursively. */ - if (0 == module_manager.configurable_children(parent_module).size()) { + if (0 == module_manager.num_configurable_children( + parent_module, ModuleManager::e_config_child_type::PHYSICAL)) { return 1; } @@ -105,7 +110,10 @@ static size_t rec_estimate_device_bitstream_num_bits( VTR_ASSERT_SAFE(parent_module != top_module); size_t num_configurable_children = - module_manager.configurable_children(parent_module).size(); + module_manager + .configurable_children(parent_module, + ModuleManager::e_config_child_type::PHYSICAL) + .size(); /* Frame-based configuration protocol will have 1 decoder * if there are more than 1 configurable children @@ -116,8 +124,8 @@ static size_t rec_estimate_device_bitstream_num_bits( } for (size_t ichild = 0; ichild < num_configurable_children; ++ichild) { - ModuleId child_module = - module_manager.configurable_children(parent_module)[ichild]; + ModuleId child_module = module_manager.configurable_children( + parent_module, ModuleManager::e_config_child_type::PHYSICAL)[ichild]; num_bits += rec_estimate_device_bitstream_num_bits( module_manager, top_module, child_module, config_protocol); } @@ -193,7 +201,8 @@ BitstreamManager build_device_bitstream(const VprContext& vpr_ctx, /* Reserve child blocks for the top level block */ bitstream_manager.reserve_child_blocks( top_block, count_module_manager_module_configurable_children( - openfpga_ctx.module_graph(), top_module)); + openfpga_ctx.module_graph(), top_module, + ModuleManager::e_config_child_type::PHYSICAL)); /* Create bitstream from grids */ VTR_LOGV(verbose, "Building grid bitstream...\n"); diff --git a/openfpga/src/fpga_bitstream/build_fabric_bitstream.cpp b/openfpga/src/fpga_bitstream/build_fabric_bitstream.cpp index a5341217f..edf20681c 100644 --- a/openfpga/src/fpga_bitstream/build_fabric_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/build_fabric_bitstream.cpp @@ -74,12 +74,17 @@ static void rec_build_module_fabric_dependent_chain_bitstream( } else { for (size_t child_id = 0; child_id < - module_manager.configurable_children(parent_module).size(); + module_manager + .configurable_children( + parent_module, ModuleManager::e_config_child_type::PHYSICAL) + .size(); ++child_id) { - ModuleId child_module = - module_manager.configurable_children(parent_module)[child_id]; - size_t child_instance = - module_manager.configurable_child_instances(parent_module)[child_id]; + ModuleId child_module = module_manager.configurable_children( + parent_module, + ModuleManager::e_config_child_type::PHYSICAL)[child_id]; + size_t child_instance = module_manager.configurable_child_instances( + parent_module, + ModuleManager::e_config_child_type::PHYSICAL)[child_id]; /* Get the instance name and ensure it is not empty */ std::string instance_name = module_manager.instance_name( parent_module, child_module, child_instance); @@ -196,7 +201,8 @@ static void rec_build_module_fabric_dependent_memory_bank_bitstream( * - no need to exclude decoders as they are not there */ std::vector configurable_children = - module_manager.configurable_children(parent_module); + module_manager.configurable_children( + parent_module, ModuleManager::e_config_child_type::PHYSICAL); size_t num_configurable_children = configurable_children.size(); @@ -211,8 +217,9 @@ static void rec_build_module_fabric_dependent_memory_bank_bitstream( for (size_t child_id = 0; child_id < num_configurable_children; ++child_id) { ModuleId child_module = configurable_children[child_id]; - size_t child_instance = - module_manager.configurable_child_instances(parent_module)[child_id]; + size_t child_instance = module_manager.configurable_child_instances( + parent_module, + ModuleManager::e_config_child_type::PHYSICAL)[child_id]; /* Get the instance name and ensure it is not empty */ std::string instance_name = module_manager.instance_name( @@ -323,10 +330,11 @@ static void rec_build_module_fabric_dependent_frame_bitstream( config_region); } else { VTR_ASSERT(top_module != parent_module); - configurable_children = - module_manager.configurable_children(parent_module); + configurable_children = module_manager.configurable_children( + parent_module, ModuleManager::e_config_child_type::PHYSICAL); configurable_child_instances = - module_manager.configurable_child_instances(parent_module); + module_manager.configurable_child_instances( + parent_module, ModuleManager::e_config_child_type::PHYSICAL); } size_t num_configurable_children = configurable_children.size(); @@ -360,10 +368,13 @@ static void rec_build_module_fabric_dependent_frame_bitstream( /* The max address code size is the max address code size of all the * configurable children in all the regions */ - for (const ModuleId& child_module : - module_manager.configurable_children(parent_module)) { + for (const ModuleId& child_module : module_manager.configurable_children( + parent_module, ModuleManager::e_config_child_type::PHYSICAL)) { /* Bypass any decoder module (which no configurable children */ - if (module_manager.configurable_children(child_module).empty()) { + if (module_manager + .configurable_children( + child_module, ModuleManager::e_config_child_type::PHYSICAL) + .empty()) { continue; } const ModulePortId& child_addr_port_id = @@ -493,8 +504,8 @@ static void rec_build_module_fabric_dependent_frame_bitstream( parent_modules.back(), config_region); } else { VTR_ASSERT(top_module != parent_modules.back()); - configurable_children = - module_manager.configurable_children(parent_modules.back()); + configurable_children = module_manager.configurable_children( + parent_modules.back(), ModuleManager::e_config_child_type::PHYSICAL); } ModuleId decoder_module = configurable_children.back(); diff --git a/openfpga/src/fpga_bitstream/build_fabric_bitstream_memory_bank.cpp b/openfpga/src/fpga_bitstream/build_fabric_bitstream_memory_bank.cpp index 97fe97d90..8507bd199 100644 --- a/openfpga/src/fpga_bitstream/build_fabric_bitstream_memory_bank.cpp +++ b/openfpga/src/fpga_bitstream/build_fabric_bitstream_memory_bank.cpp @@ -123,7 +123,8 @@ static void rec_build_module_fabric_dependent_ql_memory_bank_regional_bitstream( * - no need to exclude decoders as they are not there */ std::vector configurable_children = - module_manager.configurable_children(parent_module); + module_manager.configurable_children( + parent_module, ModuleManager::e_config_child_type::PHYSICAL); size_t num_configurable_children = configurable_children.size(); @@ -138,8 +139,9 @@ static void rec_build_module_fabric_dependent_ql_memory_bank_regional_bitstream( for (size_t child_id = 0; child_id < num_configurable_children; ++child_id) { ModuleId child_module = configurable_children[child_id]; - size_t child_instance = - module_manager.configurable_child_instances(parent_module)[child_id]; + size_t child_instance = module_manager.configurable_child_instances( + parent_module, + ModuleManager::e_config_child_type::PHYSICAL)[child_id]; /* Get the instance name and ensure it is not empty */ std::string instance_name = module_manager.instance_name( diff --git a/openfpga/src/fpga_bitstream/build_grid_bitstream.cpp b/openfpga/src/fpga_bitstream/build_grid_bitstream.cpp index 19aa076c6..80342a20d 100644 --- a/openfpga/src/fpga_bitstream/build_grid_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/build_grid_bitstream.cpp @@ -50,10 +50,12 @@ static std::vector generate_mode_select_bitstream( *******************************************************************/ static void build_primitive_bitstream( BitstreamManager& bitstream_manager, + std::map& grouped_mem_inst_scoreboard, const ConfigBlockId& parent_configurable_block, const ModuleManager& module_manager, const CircuitLibrary& circuit_lib, const VprDeviceAnnotation& device_annotation, const PhysicalPb& physical_pb, - const PhysicalPbId& primitive_pb_id, t_pb_type* primitive_pb_type) { + const PhysicalPbId& primitive_pb_id, t_pb_type* primitive_pb_type, + const bool& verbose) { /* Ensure a valid physical pritimive pb */ if (nullptr == primitive_pb_type) { VTR_LOGF_ERROR(__FILE__, __LINE__, "Invalid primitive_pb_type!\n"); @@ -131,11 +133,34 @@ static void build_primitive_bitstream( mode_select_bitstream.size() == module_manager.module_port(mem_module, mem_out_port_id).get_width()); + /* If there is a feedthrough module, we should consider the scoreboard */ + std::string feedthru_mem_block_name = + generate_memory_module_name(circuit_lib, primitive_model, sram_models[0], + std::string(MEMORY_MODULE_POSTFIX), true); + ModuleId feedthru_mem_module = + module_manager.find_module(feedthru_mem_block_name); + if (module_manager.valid_module_id(feedthru_mem_module)) { + auto result = grouped_mem_inst_scoreboard.find(mem_block_name); + if (result == grouped_mem_inst_scoreboard.end()) { + /* Update scoreboard */ + grouped_mem_inst_scoreboard[mem_block_name] = 0; + } else { + grouped_mem_inst_scoreboard[mem_block_name]++; + mem_block_name = generate_instance_name( + mem_block_name, grouped_mem_inst_scoreboard[mem_block_name]); + } + } + /* Create a block for the bitstream which corresponds to the memory module * associated to the LUT */ ConfigBlockId mem_block = bitstream_manager.add_block(mem_block_name); bitstream_manager.add_child_block(parent_configurable_block, mem_block); + VTR_LOGV(verbose, "Added %lu bits to '%s' under '%s'\n", + mode_select_bitstream.size(), + bitstream_manager.block_name(mem_block).c_str(), + bitstream_manager.block_name(parent_configurable_block).c_str()); + /* Add the bitstream to the bitstream manager */ bitstream_manager.add_block_bits(mem_block, mode_select_bitstream); } @@ -153,13 +178,14 @@ static void build_primitive_bitstream( *******************************************************************/ static void build_physical_block_pin_interc_bitstream( BitstreamManager& bitstream_manager, + std::map& grouped_mem_inst_scoreboard, const ConfigBlockId& parent_configurable_block, const ModuleManager& module_manager, const CircuitLibrary& circuit_lib, const MuxLibrary& mux_lib, const AtomContext& atom_ctx, const VprDeviceAnnotation& device_annotation, const VprBitstreamAnnotation& bitstream_annotation, const PhysicalPb& physical_pb, t_pb_graph_pin* des_pb_graph_pin, - t_mode* physical_mode) { + t_mode* physical_mode, const bool& verbose) { /* Identify the number of fan-in (Consider interconnection edges of only * selected mode) */ t_interconnect* cur_interc = @@ -258,9 +284,6 @@ static void build_physical_block_pin_interc_bitstream( * physical_block */ std::string mem_block_name = generate_pb_memory_instance_name( GRID_MEM_INSTANCE_PREFIX, des_pb_graph_pin, std::string("")); - ConfigBlockId mux_mem_block = bitstream_manager.add_block(mem_block_name); - bitstream_manager.add_child_block(parent_configurable_block, - mux_mem_block); /* Find the module in module manager and ensure the bitstream size * matches! */ @@ -275,6 +298,32 @@ static void build_physical_block_pin_interc_bitstream( module_manager.module_port(mux_mem_module, mux_mem_out_port_id) .get_width()); + /* If there is a feedthrough module, we should consider the scoreboard */ + std::string feedthru_mem_block_name = generate_mux_subckt_name( + circuit_lib, mux_model, datapath_mux_size, + std::string(MEMORY_FEEDTHROUGH_MODULE_POSTFIX)); + ModuleId feedthru_mem_module = + module_manager.find_module(feedthru_mem_block_name); + if (module_manager.valid_module_id(feedthru_mem_module)) { + auto result = grouped_mem_inst_scoreboard.find(mem_block_name); + if (result == grouped_mem_inst_scoreboard.end()) { + /* Update scoreboard */ + grouped_mem_inst_scoreboard[mem_block_name] = 0; + } else { + grouped_mem_inst_scoreboard[mem_block_name]++; + mem_block_name = generate_instance_name( + mem_block_name, grouped_mem_inst_scoreboard[mem_block_name]); + } + } + ConfigBlockId mux_mem_block = bitstream_manager.add_block(mem_block_name); + bitstream_manager.add_child_block(parent_configurable_block, + mux_mem_block); + + VTR_LOGV(verbose, "Added %lu bits to '%s' under '%s'\n", + mux_bitstream.size(), + bitstream_manager.block_name(mux_mem_block).c_str(), + bitstream_manager.block_name(parent_configurable_block).c_str()); + /* Add the bistream to the bitstream manager */ bitstream_manager.add_block_bits(mux_mem_block, mux_bitstream); /* Record path ids, input and output nets */ @@ -324,13 +373,15 @@ static void build_physical_block_pin_interc_bitstream( *******************************************************************/ static void build_physical_block_interc_port_bitstream( BitstreamManager& bitstream_manager, + std::map& grouped_mem_inst_scoreboard, const ConfigBlockId& parent_configurable_block, const ModuleManager& module_manager, const CircuitLibrary& circuit_lib, const MuxLibrary& mux_lib, const AtomContext& atom_ctx, const VprDeviceAnnotation& device_annotation, const VprBitstreamAnnotation& bitstream_annotation, t_pb_graph_node* physical_pb_graph_node, const PhysicalPb& physical_pb, - const e_circuit_pb_port_type& pb_port_type, t_mode* physical_mode) { + const e_circuit_pb_port_type& pb_port_type, t_mode* physical_mode, + const bool& verbose) { switch (pb_port_type) { case CIRCUIT_PB_PORT_INPUT: for (int iport = 0; iport < physical_pb_graph_node->num_input_ports; @@ -338,10 +389,11 @@ static void build_physical_block_interc_port_bitstream( for (int ipin = 0; ipin < physical_pb_graph_node->num_input_pins[iport]; ++ipin) { build_physical_block_pin_interc_bitstream( - bitstream_manager, parent_configurable_block, module_manager, - circuit_lib, mux_lib, atom_ctx, device_annotation, - bitstream_annotation, physical_pb, - &(physical_pb_graph_node->input_pins[iport][ipin]), physical_mode); + bitstream_manager, grouped_mem_inst_scoreboard, + parent_configurable_block, module_manager, circuit_lib, mux_lib, + atom_ctx, device_annotation, bitstream_annotation, physical_pb, + &(physical_pb_graph_node->input_pins[iport][ipin]), physical_mode, + verbose); } } break; @@ -351,10 +403,11 @@ static void build_physical_block_interc_port_bitstream( for (int ipin = 0; ipin < physical_pb_graph_node->num_output_pins[iport]; ++ipin) { build_physical_block_pin_interc_bitstream( - bitstream_manager, parent_configurable_block, module_manager, - circuit_lib, mux_lib, atom_ctx, device_annotation, - bitstream_annotation, physical_pb, - &(physical_pb_graph_node->output_pins[iport][ipin]), physical_mode); + bitstream_manager, grouped_mem_inst_scoreboard, + parent_configurable_block, module_manager, circuit_lib, mux_lib, + atom_ctx, device_annotation, bitstream_annotation, physical_pb, + &(physical_pb_graph_node->output_pins[iport][ipin]), physical_mode, + verbose); } } break; @@ -364,10 +417,11 @@ static void build_physical_block_interc_port_bitstream( for (int ipin = 0; ipin < physical_pb_graph_node->num_clock_pins[iport]; ++ipin) { build_physical_block_pin_interc_bitstream( - bitstream_manager, parent_configurable_block, module_manager, - circuit_lib, mux_lib, atom_ctx, device_annotation, - bitstream_annotation, physical_pb, - &(physical_pb_graph_node->clock_pins[iport][ipin]), physical_mode); + bitstream_manager, grouped_mem_inst_scoreboard, + parent_configurable_block, module_manager, circuit_lib, mux_lib, + atom_ctx, device_annotation, bitstream_annotation, physical_pb, + &(physical_pb_graph_node->clock_pins[iport][ipin]), physical_mode, + verbose); } } break; @@ -383,13 +437,14 @@ static void build_physical_block_interc_port_bitstream( *******************************************************************/ static void build_physical_block_interc_bitstream( BitstreamManager& bitstream_manager, + std::map& grouped_mem_inst_scoreboard, const ConfigBlockId& parent_configurable_block, const ModuleManager& module_manager, const CircuitLibrary& circuit_lib, const MuxLibrary& mux_lib, const AtomContext& atom_ctx, const VprDeviceAnnotation& device_annotation, const VprBitstreamAnnotation& bitstream_annotation, t_pb_graph_node* physical_pb_graph_node, const PhysicalPb& physical_pb, - t_mode* physical_mode) { + t_mode* physical_mode, const bool& verbose) { /* Check if the pb_graph node is valid or not */ if (nullptr == physical_pb_graph_node) { VTR_LOGF_ERROR(__FILE__, __LINE__, "Invalid physical_pb_graph_node.\n"); @@ -407,9 +462,10 @@ static void build_physical_block_interc_bitstream( * Note: it is not applied to primitive pb_type! */ build_physical_block_interc_port_bitstream( - bitstream_manager, parent_configurable_block, module_manager, circuit_lib, - mux_lib, atom_ctx, device_annotation, bitstream_annotation, - physical_pb_graph_node, physical_pb, CIRCUIT_PB_PORT_OUTPUT, physical_mode); + bitstream_manager, grouped_mem_inst_scoreboard, parent_configurable_block, + module_manager, circuit_lib, mux_lib, atom_ctx, device_annotation, + bitstream_annotation, physical_pb_graph_node, physical_pb, + CIRCUIT_PB_PORT_OUTPUT, physical_mode, verbose); /* We check input_pins of child_pb_graph_node and its the input_edges * Iterate over the interconnections between inputs of physical_pb_graph_node @@ -429,14 +485,16 @@ static void build_physical_block_interc_bitstream( /* For each child_pb_graph_node input pins*/ build_physical_block_interc_port_bitstream( - bitstream_manager, parent_configurable_block, module_manager, - circuit_lib, mux_lib, atom_ctx, device_annotation, bitstream_annotation, - child_pb_graph_node, physical_pb, CIRCUIT_PB_PORT_INPUT, physical_mode); + bitstream_manager, grouped_mem_inst_scoreboard, + parent_configurable_block, module_manager, circuit_lib, mux_lib, + atom_ctx, device_annotation, bitstream_annotation, child_pb_graph_node, + physical_pb, CIRCUIT_PB_PORT_INPUT, physical_mode, verbose); /* For clock pins, we should do the same work */ build_physical_block_interc_port_bitstream( - bitstream_manager, parent_configurable_block, module_manager, - circuit_lib, mux_lib, atom_ctx, device_annotation, bitstream_annotation, - child_pb_graph_node, physical_pb, CIRCUIT_PB_PORT_CLOCK, physical_mode); + bitstream_manager, grouped_mem_inst_scoreboard, + parent_configurable_block, module_manager, circuit_lib, mux_lib, + atom_ctx, device_annotation, bitstream_annotation, child_pb_graph_node, + physical_pb, CIRCUIT_PB_PORT_CLOCK, physical_mode, verbose); } } } @@ -445,15 +503,14 @@ static void build_physical_block_interc_bitstream( * Generate bitstream for a LUT and add it to bitstream manager * This function supports both single-output and fracturable LUTs *******************************************************************/ -static void build_lut_bitstream(BitstreamManager& bitstream_manager, - const ConfigBlockId& parent_configurable_block, - const VprDeviceAnnotation& device_annotation, - const ModuleManager& module_manager, - const CircuitLibrary& circuit_lib, - const MuxLibrary& mux_lib, - const PhysicalPb& physical_pb, - const PhysicalPbId& lut_pb_id, - t_pb_type* lut_pb_type) { +static void build_lut_bitstream( + BitstreamManager& bitstream_manager, + std::map& grouped_mem_inst_scoreboard, + const ConfigBlockId& parent_configurable_block, + const VprDeviceAnnotation& device_annotation, + const ModuleManager& module_manager, const CircuitLibrary& circuit_lib, + const MuxLibrary& mux_lib, const PhysicalPb& physical_pb, + const PhysicalPbId& lut_pb_id, t_pb_type* lut_pb_type, const bool& verbose) { /* Ensure a valid physical pritimive pb */ if (nullptr == lut_pb_type) { VTR_LOGF_ERROR(__FILE__, __LINE__, "Invalid lut_pb_type!\n"); @@ -594,11 +651,33 @@ static void build_lut_bitstream(BitstreamManager& bitstream_manager, lut_bitstream.size() == module_manager.module_port(mem_module, mem_out_port_id).get_width()); + /* If there is a feedthrough module, we should consider the scoreboard */ + std::string feedthru_mem_block_name = + generate_memory_module_name(circuit_lib, lut_model, sram_models[0], + std::string(MEMORY_MODULE_POSTFIX), true); + ModuleId feedthru_mem_module = + module_manager.find_module(feedthru_mem_block_name); + if (module_manager.valid_module_id(feedthru_mem_module)) { + auto result = grouped_mem_inst_scoreboard.find(mem_block_name); + if (result == grouped_mem_inst_scoreboard.end()) { + /* Update scoreboard */ + grouped_mem_inst_scoreboard[mem_block_name] = 0; + } else { + grouped_mem_inst_scoreboard[mem_block_name]++; + mem_block_name = generate_instance_name( + mem_block_name, grouped_mem_inst_scoreboard[mem_block_name]); + } + } + /* Create a block for the bitstream which corresponds to the memory module * associated to the LUT */ ConfigBlockId mem_block = bitstream_manager.add_block(mem_block_name); bitstream_manager.add_child_block(parent_configurable_block, mem_block); + VTR_LOGV(verbose, "Added %lu bits to '%s' under '%s'\n", lut_bitstream.size(), + bitstream_manager.block_name(mem_block).c_str(), + bitstream_manager.block_name(parent_configurable_block).c_str()); + /* Add the bitstream to the bitstream manager */ bitstream_manager.add_block_bits(mem_block, lut_bitstream); } @@ -616,13 +695,15 @@ static void build_lut_bitstream(BitstreamManager& bitstream_manager, *******************************************************************/ static void rec_build_physical_block_bitstream( BitstreamManager& bitstream_manager, + std::map& grouped_mem_inst_scoreboard, const ConfigBlockId& parent_configurable_block, const ModuleManager& module_manager, const CircuitLibrary& circuit_lib, const MuxLibrary& mux_lib, const AtomContext& atom_ctx, const VprDeviceAnnotation& device_annotation, const VprBitstreamAnnotation& bitstream_annotation, const e_side& border_side, const PhysicalPb& physical_pb, const PhysicalPbId& pb_id, - t_pb_graph_node* physical_pb_graph_node, const size_t& pb_graph_node_index) { + t_pb_graph_node* physical_pb_graph_node, const size_t& pb_graph_node_index, + const bool& verbose) { /* Get the physical pb_type that is linked to the pb_graph node */ t_pb_type* physical_pb_type = physical_pb_graph_node->pb_type; @@ -636,7 +717,8 @@ static void rec_build_physical_block_bitstream( VTR_ASSERT(true == module_manager.valid_module_id(pb_module)); /* Skip module with no configurable children */ - if (0 == module_manager.configurable_children(pb_module).size()) { + if (0 == module_manager.num_configurable_children( + pb_module, ModuleManager::e_config_child_type::LOGICAL)) { return; } @@ -644,16 +726,21 @@ static void rec_build_physical_block_bitstream( * manager */ std::string pb_block_name = generate_physical_block_instance_name( physical_pb_type, pb_graph_node_index); - ConfigBlockId pb_configurable_block = - bitstream_manager.add_block(pb_block_name); - bitstream_manager.add_child_block(parent_configurable_block, - pb_configurable_block); - - /* Reserve child blocks for new created block */ - bitstream_manager.reserve_child_blocks( - parent_configurable_block, - count_module_manager_module_configurable_children(module_manager, - pb_module)); + /* If there are no physical memory blocks under the current module, use the + * previous module, which is the physical memory block */ + ConfigBlockId pb_configurable_block = parent_configurable_block; + if (0 < module_manager.num_configurable_children( + pb_module, ModuleManager::e_config_child_type::PHYSICAL)) { + pb_configurable_block = bitstream_manager.add_block(pb_block_name); + bitstream_manager.add_child_block(parent_configurable_block, + pb_configurable_block); + /* Reserve child blocks for new created block */ + bitstream_manager.reserve_child_blocks( + parent_configurable_block, + count_module_manager_module_configurable_children( + module_manager, pb_module, + ModuleManager::e_config_child_type::PHYSICAL)); + } /* Recursively finish all the child pb_types*/ if (false == is_primitive_pb_type(physical_pb_type)) { @@ -670,12 +757,12 @@ static void rec_build_physical_block_bitstream( } /* Go recursively */ rec_build_physical_block_bitstream( - bitstream_manager, pb_configurable_block, module_manager, circuit_lib, - mux_lib, atom_ctx, device_annotation, bitstream_annotation, - border_side, physical_pb, child_pb, + bitstream_manager, grouped_mem_inst_scoreboard, pb_configurable_block, + module_manager, circuit_lib, mux_lib, atom_ctx, device_annotation, + bitstream_annotation, border_side, physical_pb, child_pb, &(physical_pb_graph_node ->child_pb_graph_nodes[physical_mode->index][ipb][jpb]), - jpb); + jpb, verbose); } } } @@ -690,17 +777,19 @@ static void rec_build_physical_block_bitstream( /* Special case for LUT !!! * Mapped logical block information is stored in child_pbs of this pb!!! */ - build_lut_bitstream(bitstream_manager, pb_configurable_block, - device_annotation, module_manager, circuit_lib, - mux_lib, physical_pb, pb_id, physical_pb_type); + build_lut_bitstream(bitstream_manager, grouped_mem_inst_scoreboard, + pb_configurable_block, device_annotation, + module_manager, circuit_lib, mux_lib, physical_pb, + pb_id, physical_pb_type, verbose); break; case CIRCUIT_MODEL_FF: case CIRCUIT_MODEL_HARDLOGIC: case CIRCUIT_MODEL_IOPAD: /* For other types of blocks, we can apply a generic therapy */ build_primitive_bitstream( - bitstream_manager, pb_configurable_block, module_manager, circuit_lib, - device_annotation, physical_pb, pb_id, physical_pb_type); + bitstream_manager, grouped_mem_inst_scoreboard, pb_configurable_block, + module_manager, circuit_lib, device_annotation, physical_pb, pb_id, + physical_pb_type, verbose); break; default: VTR_LOGF_ERROR(__FILE__, __LINE__, @@ -714,9 +803,10 @@ static void rec_build_physical_block_bitstream( /* Generate the bitstream for the interconnection in this physical block */ build_physical_block_interc_bitstream( - bitstream_manager, pb_configurable_block, module_manager, circuit_lib, - mux_lib, atom_ctx, device_annotation, bitstream_annotation, - physical_pb_graph_node, physical_pb, physical_mode); + bitstream_manager, grouped_mem_inst_scoreboard, pb_configurable_block, + module_manager, circuit_lib, mux_lib, atom_ctx, device_annotation, + bitstream_annotation, physical_pb_graph_node, physical_pb, physical_mode, + verbose); } /******************************************************************** @@ -734,7 +824,8 @@ static void build_physical_block_bitstream( const VprClusteringAnnotation& cluster_annotation, const VprPlacementAnnotation& place_annotation, const VprBitstreamAnnotation& bitstream_annotation, const DeviceGrid& grids, - const vtr::Point& grid_coord, const e_side& border_side) { + const vtr::Point& grid_coord, const e_side& border_side, + const bool& verbose) { /* Create a block for the grid in bitstream manager */ t_physical_tile_type_ptr grid_type = grids.get_physical_type(grid_coord.x(), grid_coord.y()); @@ -748,7 +839,8 @@ static void build_physical_block_bitstream( VTR_ASSERT(true == module_manager.valid_module_id(grid_module)); /* Skip module with no configurable children */ - if (0 == module_manager.configurable_children(grid_module).size()) { + if (0 == module_manager.num_configurable_children( + grid_module, ModuleManager::e_config_child_type::LOGICAL)) { return; } @@ -770,7 +862,33 @@ static void build_physical_block_bitstream( /* Reserve child blocks for new created block */ bitstream_manager.reserve_child_blocks( grid_configurable_block, count_module_manager_module_configurable_children( - module_manager, grid_module)); + module_manager, grid_module, + ModuleManager::e_config_child_type::PHYSICAL)); + + /* Create a dedicated block for the non-unified configurable child */ + if (!module_manager.unified_configurable_children(grid_module)) { + VTR_ASSERT(1 == + module_manager + .configurable_children( + grid_module, ModuleManager::e_config_child_type::PHYSICAL) + .size()); + std::string phy_mem_instance_name = module_manager.instance_name( + grid_module, + module_manager.configurable_children( + grid_module, ModuleManager::e_config_child_type::PHYSICAL)[0], + module_manager.configurable_child_instances( + grid_module, ModuleManager::e_config_child_type::PHYSICAL)[0]); + ConfigBlockId grid_grouped_config_block = + bitstream_manager.add_block(phy_mem_instance_name); + VTR_LOGV( + verbose, + "Added grouped configurable memory block '%s' as a child to '%s'\n", + bitstream_manager.block_name(grid_grouped_config_block).c_str(), + bitstream_manager.block_name(grid_configurable_block).c_str()); + bitstream_manager.add_child_block(grid_configurable_block, + grid_grouped_config_block); + grid_configurable_block = grid_grouped_config_block; + } /* Iterate over the capacity of the grid * Now each physical tile may have a number of logical blocks @@ -780,6 +898,7 @@ static void build_physical_block_bitstream( * If you need different equivalent sites, you can always define * it as a mode under a */ + std::map grouped_mem_inst_scoreboard; for (size_t z = 0; z < place_annotation.grid_blocks(grid_coord).size(); ++z) { int sub_tile_index = device_annotation.physical_tile_z_to_subtile_index(grid_type, z); @@ -796,10 +915,11 @@ static void build_physical_block_bitstream( place_annotation.grid_blocks(grid_coord)[z]) { /* Recursively traverse the pb_graph and generate bitstream */ rec_build_physical_block_bitstream( - bitstream_manager, grid_configurable_block, module_manager, - circuit_lib, mux_lib, atom_ctx, device_annotation, - bitstream_annotation, border_side, PhysicalPb(), - PhysicalPbId::INVALID(), lb_type->pb_graph_head, z); + bitstream_manager, grouped_mem_inst_scoreboard, + grid_configurable_block, module_manager, circuit_lib, mux_lib, + atom_ctx, device_annotation, bitstream_annotation, border_side, + PhysicalPb(), PhysicalPbId::INVALID(), lb_type->pb_graph_head, z, + verbose); } else { const PhysicalPb& phy_pb = cluster_annotation.physical_pb( place_annotation.grid_blocks(grid_coord)[z]); @@ -811,10 +931,10 @@ static void build_physical_block_bitstream( /* Recursively traverse the pb_graph and generate bitstream */ rec_build_physical_block_bitstream( - bitstream_manager, grid_configurable_block, module_manager, - circuit_lib, mux_lib, atom_ctx, device_annotation, - bitstream_annotation, border_side, phy_pb, top_pb_id, pb_graph_head, - z); + bitstream_manager, grouped_mem_inst_scoreboard, + grid_configurable_block, module_manager, circuit_lib, mux_lib, + atom_ctx, device_annotation, bitstream_annotation, border_side, + phy_pb, top_pb_id, pb_graph_head, z, verbose); } } } @@ -873,7 +993,8 @@ void build_grid_bitstream( build_physical_block_bitstream( bitstream_manager, parent_block, module_manager, fabric_tile, curr_tile, circuit_lib, mux_lib, atom_ctx, device_annotation, cluster_annotation, - place_annotation, bitstream_annotation, grids, grid_coord, NUM_SIDES); + place_annotation, bitstream_annotation, grids, grid_coord, NUM_SIDES, + verbose); } } VTR_LOGV(verbose, "Done\n"); @@ -919,7 +1040,8 @@ void build_grid_bitstream( build_physical_block_bitstream( bitstream_manager, parent_block, module_manager, fabric_tile, curr_tile, circuit_lib, mux_lib, atom_ctx, device_annotation, cluster_annotation, - place_annotation, bitstream_annotation, grids, io_coordinate, io_side); + place_annotation, bitstream_annotation, grids, io_coordinate, io_side, + verbose); } } VTR_LOGV(verbose, "Done\n"); diff --git a/openfpga/src/fpga_bitstream/build_routing_bitstream.cpp b/openfpga/src/fpga_bitstream/build_routing_bitstream.cpp index fda7d6765..28b79e049 100644 --- a/openfpga/src/fpga_bitstream/build_routing_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/build_routing_bitstream.cpp @@ -37,7 +37,7 @@ static void build_switch_block_mux_bitstream( const MuxLibrary& mux_lib, const RRGraphView& rr_graph, const RRNodeId& cur_rr_node, const std::vector& drive_rr_nodes, const AtomContext& atom_ctx, const VprDeviceAnnotation& device_annotation, - const VprRoutingAnnotation& routing_annotation) { + const VprRoutingAnnotation& routing_annotation, const bool& verbose) { /* Check current rr_node is CHANX or CHANY*/ VTR_ASSERT((CHANX == rr_graph.node_type(cur_rr_node)) || (CHANY == rr_graph.node_type(cur_rr_node))); @@ -102,6 +102,12 @@ static void build_switch_block_mux_bitstream( module_manager.module_port(mux_mem_module, mux_mem_out_port_id) .get_width()); + VTR_LOGV( + verbose, "Added %lu bits to '%s' under '%s'\n", mux_bitstream.size(), + bitstream_manager.block_name(mux_mem_block).c_str(), + bitstream_manager.block_name(bitstream_manager.block_parent(mux_mem_block)) + .c_str()); + /* Add the bistream to the bitstream manager */ bitstream_manager.add_block_bits(mux_mem_block, mux_bitstream); /* Record path ids, input and output nets */ @@ -150,7 +156,7 @@ static void build_switch_block_interc_bitstream( const MuxLibrary& mux_lib, const RRGraphView& rr_graph, const AtomContext& atom_ctx, const VprDeviceAnnotation& device_annotation, const VprRoutingAnnotation& routing_annotation, const RRGSB& rr_gsb, - const e_side& chan_side, const size_t& chan_node_id) { + const e_side& chan_side, const size_t& chan_node_id, const bool& verbose) { std::vector driver_rr_nodes; /* Get the node */ @@ -179,11 +185,14 @@ static void build_switch_block_interc_bitstream( std::string("")); ConfigBlockId mux_mem_block = bitstream_manager.add_block(mem_block_name); bitstream_manager.add_child_block(sb_configurable_block, mux_mem_block); + VTR_LOGV(verbose, "Added '%s' under '%s'\n", + bitstream_manager.block_name(mux_mem_block).c_str(), + bitstream_manager.block_name(sb_configurable_block).c_str()); /* This is a routing multiplexer! Generate bitstream */ build_switch_block_mux_bitstream( bitstream_manager, mux_mem_block, module_manager, circuit_lib, mux_lib, rr_graph, cur_rr_node, driver_rr_nodes, atom_ctx, device_annotation, - routing_annotation); + routing_annotation, verbose); } /*Nothing should be done else*/ } @@ -204,7 +213,7 @@ static void build_switch_block_bitstream( const MuxLibrary& mux_lib, const AtomContext& atom_ctx, const VprDeviceAnnotation& device_annotation, const VprRoutingAnnotation& routing_annotation, const RRGraphView& rr_graph, - const RRGSB& rr_gsb) { + const RRGSB& rr_gsb, const bool& verbose) { /* Iterate over all the multiplexers */ for (size_t side = 0; side < rr_gsb.get_num_sides(); ++side) { SideManager side_manager(side); @@ -222,7 +231,7 @@ static void build_switch_block_bitstream( build_switch_block_interc_bitstream( bitstream_manager, sb_config_block, module_manager, circuit_lib, mux_lib, rr_graph, atom_ctx, device_annotation, routing_annotation, - rr_gsb, side_manager.get_side(), itrack); + rr_gsb, side_manager.get_side(), itrack, verbose); } } } @@ -240,7 +249,8 @@ static void build_connection_block_mux_bitstream( const MuxLibrary& mux_lib, const AtomContext& atom_ctx, const VprDeviceAnnotation& device_annotation, const VprRoutingAnnotation& routing_annotation, const RRGraphView& rr_graph, - const RRGSB& rr_gsb, const e_side& cb_ipin_side, const size_t& ipin_index) { + const RRGSB& rr_gsb, const e_side& cb_ipin_side, const size_t& ipin_index, + const bool& verbose) { RRNodeId src_rr_node = rr_gsb.get_ipin_node(cb_ipin_side, ipin_index); /* Find drive_rr_nodes*/ std::vector driver_rr_edges = @@ -308,6 +318,12 @@ static void build_connection_block_mux_bitstream( module_manager.module_port(mux_mem_module, mux_mem_out_port_id) .get_width()); + VTR_LOGV( + verbose, "Added %lu bits to '%s' under '%s'\n", mux_bitstream.size(), + bitstream_manager.block_name(mux_mem_block).c_str(), + bitstream_manager.block_name(bitstream_manager.block_parent(mux_mem_block)) + .c_str()); + /* Add the bistream to the bitstream manager */ bitstream_manager.add_block_bits(mux_mem_block, mux_bitstream); /* Record path ids, input and output nets */ @@ -381,11 +397,14 @@ static void build_connection_block_interc_bitstream( std::string("")); ConfigBlockId mux_mem_block = bitstream_manager.add_block(mem_block_name); bitstream_manager.add_child_block(cb_configurable_block, mux_mem_block); + VTR_LOGV(verbose, "Added '%s' under '%s'\n", + bitstream_manager.block_name(mux_mem_block).c_str(), + bitstream_manager.block_name(cb_configurable_block).c_str()); /* This is a routing multiplexer! Generate bitstream */ build_connection_block_mux_bitstream( bitstream_manager, mux_mem_block, module_manager, circuit_lib, mux_lib, atom_ctx, device_annotation, routing_annotation, rr_graph, rr_gsb, - cb_ipin_side, ipin_index); + cb_ipin_side, ipin_index, verbose); } /*Nothing should be done else*/ } @@ -486,8 +505,12 @@ static void build_connection_block_bitstreams( VTR_ASSERT(true == module_manager.valid_module_id(cb_module)); /* Bypass empty blocks which have none configurable children */ - if (0 == count_module_manager_module_configurable_children(module_manager, - cb_module)) { + if (0 == count_module_manager_module_configurable_children( + module_manager, cb_module, + ModuleManager::e_config_child_type::LOGICAL) && + 0 == count_module_manager_module_configurable_children( + module_manager, cb_module, + ModuleManager::e_config_child_type::PHYSICAL)) { continue; } @@ -527,8 +550,32 @@ static void build_connection_block_bitstreams( /* Reserve child blocks for new created block */ bitstream_manager.reserve_child_blocks( cb_configurable_block, - count_module_manager_module_configurable_children(module_manager, - cb_module)); + count_module_manager_module_configurable_children( + module_manager, cb_module, + ModuleManager::e_config_child_type::PHYSICAL)); + + /* Create a dedicated block for the non-unified configurable child */ + if (!module_manager.unified_configurable_children(cb_module)) { + VTR_ASSERT(1 == + module_manager + .configurable_children( + cb_module, ModuleManager::e_config_child_type::PHYSICAL) + .size()); + std::string phy_mem_instance_name = module_manager.instance_name( + cb_module, + module_manager.configurable_children( + cb_module, ModuleManager::e_config_child_type::PHYSICAL)[0], + module_manager.configurable_child_instances( + cb_module, ModuleManager::e_config_child_type::PHYSICAL)[0]); + ConfigBlockId cb_grouped_config_block = + bitstream_manager.add_block(phy_mem_instance_name); + bitstream_manager.add_child_block(cb_configurable_block, + cb_grouped_config_block); + VTR_LOGV(verbose, "Added '%s' as a child to '%s'\n", + bitstream_manager.block_name(cb_grouped_config_block).c_str(), + bitstream_manager.block_name(cb_configurable_block).c_str()); + cb_configurable_block = cb_grouped_config_block; + } build_connection_block_bitstream( bitstream_manager, cb_configurable_block, module_manager, circuit_lib, @@ -593,8 +640,12 @@ void build_routing_bitstream( VTR_ASSERT(true == module_manager.valid_module_id(sb_module)); /* Bypass empty blocks which have none configurable children */ - if (0 == count_module_manager_module_configurable_children(module_manager, - sb_module)) { + if (0 == count_module_manager_module_configurable_children( + module_manager, sb_module, + ModuleManager::e_config_child_type::LOGICAL) && + 0 == count_module_manager_module_configurable_children( + module_manager, sb_module, + ModuleManager::e_config_child_type::PHYSICAL)) { continue; } @@ -629,13 +680,37 @@ void build_routing_bitstream( /* Reserve child blocks for new created block */ bitstream_manager.reserve_child_blocks( sb_configurable_block, - count_module_manager_module_configurable_children(module_manager, - sb_module)); + count_module_manager_module_configurable_children( + module_manager, sb_module, + ModuleManager::e_config_child_type::PHYSICAL)); - build_switch_block_bitstream(bitstream_manager, sb_configurable_block, - module_manager, circuit_lib, mux_lib, - atom_ctx, device_annotation, - routing_annotation, rr_graph, rr_gsb); + /* Create a dedicated block for the non-unified configurable child */ + if (!module_manager.unified_configurable_children(sb_module)) { + VTR_ASSERT(1 == + module_manager + .configurable_children( + sb_module, ModuleManager::e_config_child_type::PHYSICAL) + .size()); + std::string phy_mem_instance_name = module_manager.instance_name( + sb_module, + module_manager.configurable_children( + sb_module, ModuleManager::e_config_child_type::PHYSICAL)[0], + module_manager.configurable_child_instances( + sb_module, ModuleManager::e_config_child_type::PHYSICAL)[0]); + ConfigBlockId sb_grouped_config_block = + bitstream_manager.add_block(phy_mem_instance_name); + bitstream_manager.add_child_block(sb_configurable_block, + sb_grouped_config_block); + VTR_LOGV(verbose, "Added '%s' as a child to '%s'\n", + bitstream_manager.block_name(sb_grouped_config_block).c_str(), + bitstream_manager.block_name(sb_configurable_block).c_str()); + sb_configurable_block = sb_grouped_config_block; + } + + build_switch_block_bitstream( + bitstream_manager, sb_configurable_block, module_manager, circuit_lib, + mux_lib, atom_ctx, device_annotation, routing_annotation, rr_graph, + rr_gsb, verbose); VTR_LOGV(verbose, "\tDone\n"); } diff --git a/openfpga/src/fpga_sdc/configuration_chain_sdc_writer.cpp b/openfpga/src/fpga_sdc/configuration_chain_sdc_writer.cpp index 1eadf6fda..9d6d21def 100644 --- a/openfpga/src/fpga_sdc/configuration_chain_sdc_writer.cpp +++ b/openfpga/src/fpga_sdc/configuration_chain_sdc_writer.cpp @@ -49,13 +49,17 @@ static void rec_print_pnr_sdc_constrain_configurable_chain( ModuleId& previous_module) { /* For each configurable child, we will go one level down in priority */ for (size_t child_index = 0; - child_index < module_manager.configurable_children(parent_module).size(); + child_index < + module_manager + .configurable_children(parent_module, + ModuleManager::e_config_child_type::PHYSICAL) + .size(); ++child_index) { std::string child_module_path = parent_module_path; - ModuleId child_module_id = - module_manager.configurable_children(parent_module)[child_index]; - size_t child_instance_id = - module_manager.configurable_child_instances(parent_module)[child_index]; + ModuleId child_module_id = module_manager.configurable_children( + parent_module, ModuleManager::e_config_child_type::PHYSICAL)[child_index]; + size_t child_instance_id = module_manager.configurable_child_instances( + parent_module, ModuleManager::e_config_child_type::PHYSICAL)[child_index]; std::string child_instance_name; if (true == module_manager @@ -79,7 +83,10 @@ static void rec_print_pnr_sdc_constrain_configurable_chain( /* If there is no configurable children any more, this is a leaf module, print * a SDC command for disable timing */ - if (0 < module_manager.configurable_children(parent_module).size()) { + if (0 < module_manager + .configurable_children(parent_module, + ModuleManager::e_config_child_type::PHYSICAL) + .size()) { return; } diff --git a/openfpga/src/fpga_sdc/sdc_memory_utils.cpp b/openfpga/src/fpga_sdc/sdc_memory_utils.cpp index 12d45b887..7d8df9541 100644 --- a/openfpga/src/fpga_sdc/sdc_memory_utils.cpp +++ b/openfpga/src/fpga_sdc/sdc_memory_utils.cpp @@ -45,13 +45,17 @@ void rec_print_pnr_sdc_disable_configurable_memory_module_output( /* For each configurable child, we will go one level down in priority */ for (size_t child_index = 0; - child_index < module_manager.configurable_children(parent_module).size(); + child_index < + module_manager + .configurable_children(parent_module, + ModuleManager::e_config_child_type::PHYSICAL) + .size(); ++child_index) { std::string child_module_path = parent_module_path; - ModuleId child_module_id = - module_manager.configurable_children(parent_module)[child_index]; - size_t child_instance_id = - module_manager.configurable_child_instances(parent_module)[child_index]; + ModuleId child_module_id = module_manager.configurable_children( + parent_module, ModuleManager::e_config_child_type::PHYSICAL)[child_index]; + size_t child_instance_id = module_manager.configurable_child_instances( + parent_module, ModuleManager::e_config_child_type::PHYSICAL)[child_index]; std::string child_instance_name; if (true == module_manager @@ -96,7 +100,10 @@ void rec_print_pnr_sdc_disable_configurable_memory_module_output( /* If there is no configurable children any more, this is a leaf module, print * a SDC command for disable timing */ - if (0 < module_manager.configurable_children(parent_module).size()) { + if (0 < module_manager + .configurable_children(parent_module, + ModuleManager::e_config_child_type::PHYSICAL) + .size()) { return; } diff --git a/openfpga/src/fpga_verilog/verilog_memory.cpp b/openfpga/src/fpga_verilog/verilog_memory.cpp index ef6903cd5..365ace6a5 100644 --- a/openfpga/src/fpga_verilog/verilog_memory.cpp +++ b/openfpga/src/fpga_verilog/verilog_memory.cpp @@ -17,6 +17,7 @@ #include "mux_utils.h" #include "openfpga_digest.h" #include "openfpga_naming.h" +#include "openfpga_reserved_words.h" #include "verilog_constants.h" #include "verilog_memory.h" #include "verilog_module_writer.h" @@ -51,7 +52,7 @@ static void print_verilog_mux_memory_module( circuit_lib, mux_model, find_mux_num_datapath_inputs(circuit_lib, mux_model, mux_graph.num_inputs()), - std::string(VERILOG_MEM_POSTFIX)); + std::string(MEMORY_MODULE_POSTFIX)); ModuleId mem_module = module_manager.find_module(module_name); VTR_ASSERT(true == module_manager.valid_module_id(mem_module)); /* Write the module content in Verilog format */ @@ -63,6 +64,28 @@ static void print_verilog_mux_memory_module( /* Add an empty line as a splitter */ fp << std::endl; + + /* Print feedthrough memory if exists */ + std::string feedthru_module_name = generate_mux_subckt_name( + circuit_lib, mux_model, + find_mux_num_datapath_inputs(circuit_lib, mux_model, + mux_graph.num_inputs()), + std::string(MEMORY_FEEDTHROUGH_MODULE_POSTFIX)); + ModuleId feedthru_mem_module = + module_manager.find_module(feedthru_module_name); + if (module_manager.valid_module_id(feedthru_mem_module)) { + VTR_ASSERT(true == module_manager.valid_module_id(feedthru_mem_module)); + /* Write the module content in Verilog format */ + write_verilog_module_to_file( + fp, module_manager, feedthru_mem_module, + options.explicit_port_mapping() || + circuit_lib.dump_explicit_port_map(mux_model), + options.default_net_type()); + + /* Add an empty line as a splitter */ + fp << std::endl; + } + break; } case CIRCUIT_MODEL_DESIGN_RRAM: @@ -174,7 +197,7 @@ void print_verilog_submodule_memories(const ModuleManager& module_manager, /* Create the module name for the memory block */ std::string module_name = generate_memory_module_name( - circuit_lib, model, sram_models[0], std::string(VERILOG_MEM_POSTFIX)); + circuit_lib, model, sram_models[0], std::string(MEMORY_MODULE_POSTFIX)); ModuleId mem_module = module_manager.find_module(module_name); VTR_ASSERT(true == module_manager.valid_module_id(mem_module)); @@ -186,6 +209,36 @@ void print_verilog_submodule_memories(const ModuleManager& module_manager, /* Add an empty line as a splitter */ fp << std::endl; + + /* Create the module name for the memory block */ + std::string feedthru_module_name = + generate_memory_module_name(circuit_lib, model, sram_models[0], + std::string(MEMORY_MODULE_POSTFIX), true); + + ModuleId feedthru_mem_module = + module_manager.find_module(feedthru_module_name); + if (module_manager.valid_module_id(feedthru_mem_module)) { + /* Write the module content in Verilog format */ + write_verilog_module_to_file(fp, module_manager, feedthru_mem_module, + options.explicit_port_mapping() || + circuit_lib.dump_explicit_port_map(model), + options.default_net_type()); + + /* Add an empty line as a splitter */ + fp << std::endl; + } + } + + /* Include memory group modules */ + for (ModuleId mem_group_module : module_manager.modules_by_usage( + ModuleManager::e_module_usage_type::MODULE_CONFIG_GROUP)) { + /* Write the module content in Verilog format */ + write_verilog_module_to_file(fp, module_manager, mem_group_module, + options.explicit_port_mapping(), + options.default_net_type()); + + /* Add an empty line as a splitter */ + fp << std::endl; } /* Close the file stream */ diff --git a/openfpga/src/utils/circuit_library_utils.cpp b/openfpga/src/utils/circuit_library_utils.cpp index abcac433c..729050e06 100644 --- a/openfpga/src/utils/circuit_library_utils.cpp +++ b/openfpga/src/utils/circuit_library_utils.cpp @@ -188,6 +188,7 @@ size_t find_circuit_num_config_bits( } switch (config_protocol_type) { + case CONFIG_MEM_FEEDTHROUGH: case CONFIG_MEM_STANDALONE: case CONFIG_MEM_SCAN_CHAIN: case CONFIG_MEM_QL_MEMORY_BANK: diff --git a/openfpga/src/utils/memory_utils.cpp b/openfpga/src/utils/memory_utils.cpp index df144e669..0abf95b07 100644 --- a/openfpga/src/utils/memory_utils.cpp +++ b/openfpga/src/utils/memory_utils.cpp @@ -2,9 +2,9 @@ * This file includes functions that are used for * generating ports for memory modules *********************************************************************/ -/* Headers from vtrutil library */ #include "memory_utils.h" +#include "command_exit_codes.h" #include "decoder_library_utils.h" #include "openfpga_naming.h" #include "vtr_assert.h" @@ -342,6 +342,12 @@ std::vector generate_sram_port_names( std::vector model_port_types; switch (sram_orgz_type) { + case CONFIG_MEM_FEEDTHROUGH: + /* Feed through wires are all inputs */ + model_port_types.push_back(CIRCUIT_MODEL_PORT_BL); /* Indicate mem port */ + model_port_types.push_back( + CIRCUIT_MODEL_PORT_BLB); /* Indicate mem_inv port */ + break; case CONFIG_MEM_SCAN_CHAIN: model_port_types.push_back(CIRCUIT_MODEL_PORT_INPUT); model_port_types.push_back(CIRCUIT_MODEL_PORT_OUTPUT); @@ -400,6 +406,7 @@ size_t generate_sram_port_size(const e_config_protocol_type sram_orgz_type, size_t sram_port_size = num_config_bits; switch (sram_orgz_type) { + case CONFIG_MEM_FEEDTHROUGH: case CONFIG_MEM_STANDALONE: break; case CONFIG_MEM_SCAN_CHAIN: @@ -490,4 +497,55 @@ size_t estimate_num_configurable_children_to_skip_by_config_protocol( return num_child_to_skip; } +int rec_find_physical_memory_children( + const ModuleManager& module_manager, const ModuleId& curr_module, + std::vector& physical_memory_children, + std::vector& physical_memory_instance_names, + const bool& verbose) { + if (module_manager + .configurable_children(curr_module, + ModuleManager::e_config_child_type::LOGICAL) + .empty()) { + return CMD_EXEC_SUCCESS; + } + for (size_t ichild = 0; + ichild < module_manager + .configurable_children( + curr_module, ModuleManager::e_config_child_type::LOGICAL) + .size(); + ++ichild) { + ModuleId logical_child = module_manager.configurable_children( + curr_module, ModuleManager::e_config_child_type::LOGICAL)[ichild]; + if (module_manager + .configurable_children(logical_child, + ModuleManager::e_config_child_type::LOGICAL) + .empty()) { + /* This is a leaf node, get the physical memory module */ + physical_memory_children.push_back( + module_manager.logical2physical_configurable_children( + curr_module)[ichild]); + physical_memory_instance_names.push_back( + module_manager.logical2physical_configurable_child_instance_names( + curr_module)[ichild]); + VTR_LOGV( + verbose, + "Collecting physical memory module '%s' with an instance name " + "'%s'...\n", + module_manager + .module_name(module_manager.logical2physical_configurable_children( + curr_module)[ichild]) + .c_str(), + module_manager + .logical2physical_configurable_child_instance_names( + curr_module)[ichild] + .c_str()); + } else { + rec_find_physical_memory_children( + module_manager, logical_child, physical_memory_children, + physical_memory_instance_names, verbose); + } + } + return CMD_EXEC_SUCCESS; +} + } /* end namespace openfpga */ diff --git a/openfpga/src/utils/memory_utils.h b/openfpga/src/utils/memory_utils.h index 59cf08953..184d0be74 100644 --- a/openfpga/src/utils/memory_utils.h +++ b/openfpga/src/utils/memory_utils.h @@ -4,6 +4,7 @@ /******************************************************************** * Include header files that are required by function declaration *******************************************************************/ +#include #include #include "circuit_types.h" @@ -53,6 +54,18 @@ size_t generate_pb_sram_port_size(const e_config_protocol_type sram_orgz_type, size_t estimate_num_configurable_children_to_skip_by_config_protocol( const ConfigProtocol& config_protocol, size_t curr_region_num_config_child); +/** + * @brief Find the physical memory child modules with a given root module + * This function will walk through the module tree in a recursive way until + * reaching the leaf node (which require configurable memories) Return a list of + * modules + */ +int rec_find_physical_memory_children( + const ModuleManager& module_manager, const ModuleId& curr_module, + std::vector& physical_memory_children, + std::vector& physical_memory_instance_names, + const bool& verbose); + } /* end namespace openfpga */ #endif diff --git a/openfpga/src/utils/module_manager_memory_utils.cpp b/openfpga/src/utils/module_manager_memory_utils.cpp index 918b27e8f..cf033e9ed 100644 --- a/openfpga/src/utils/module_manager_memory_utils.cpp +++ b/openfpga/src/utils/module_manager_memory_utils.cpp @@ -39,7 +39,10 @@ static bool submodule_memory_modules_match_fabric_key( const FabricKey& fabric_key, const FabricKeyModuleId& key_module_id) { /* If the length does not match, conclusion is easy to be made */ size_t len_module_memory = - module_manager.configurable_children(module_id).size(); + module_manager + .configurable_children(module_id, + ModuleManager::e_config_child_type::PHYSICAL) + .size(); size_t len_fabric_sub_key = fabric_key.sub_keys(key_module_id).size(); if (len_module_memory != len_fabric_sub_key) { return false; @@ -65,9 +68,11 @@ static bool submodule_memory_modules_match_fabric_key( inst_info.second = fabric_key.sub_key_value(key_id); } if (inst_info.first != - module_manager.configurable_children(module_id)[ikey] || + module_manager.configurable_children( + module_id, ModuleManager::e_config_child_type::PHYSICAL)[ikey] || inst_info.second != - module_manager.configurable_child_instances(module_id)[ikey]) { + module_manager.configurable_child_instances( + module_id, ModuleManager::e_config_child_type::PHYSICAL)[ikey]) { return false; } } @@ -80,6 +85,7 @@ static bool submodule_memory_modules_match_fabric_key( static bool update_submodule_memory_modules_from_fabric_key( ModuleManager& module_manager, const ModuleId& module_id, const CircuitLibrary& circuit_lib, const ConfigProtocol& config_protocol, + const ModuleManager::e_config_child_type& config_child_type, const FabricKey& fabric_key, const FabricKeyModuleId& key_module_id) { /* Reset the configurable children */ module_manager.clear_configurable_children(module_id); @@ -142,7 +148,8 @@ static bool update_submodule_memory_modules_from_fabric_key( /* Now we can add the child to configurable children of the top module */ module_manager.add_configurable_child(module_id, inst_info.first, - inst_info.second, vtr::Point()); + inst_info.second, config_child_type, + vtr::Point()); } return CMD_EXEC_SUCCESS; } @@ -152,9 +159,12 @@ static bool update_submodule_memory_modules_from_fabric_key( *******************************************************************/ static int remove_submodule_nets_cmos_memory_chain_config_bus( ModuleManager& module_manager, const ModuleId& parent_module, - const e_config_protocol_type& sram_orgz_type) { + const e_config_protocol_type& sram_orgz_type, + const ModuleManager::e_config_child_type& config_child_type) { for (size_t mem_index = 0; - mem_index < module_manager.configurable_children(parent_module).size(); + mem_index < + module_manager.configurable_children(parent_module, config_child_type) + .size(); ++mem_index) { ModuleId net_src_module_id; size_t net_src_instance_id; @@ -171,10 +181,10 @@ static int remove_submodule_nets_cmos_memory_chain_config_bus( } else { /* Find the port name of previous memory module */ std::string src_port_name = generate_configuration_chain_tail_name(); - net_src_module_id = - module_manager.configurable_children(parent_module)[mem_index - 1]; + net_src_module_id = module_manager.configurable_children( + parent_module, config_child_type)[mem_index - 1]; net_src_instance_id = module_manager.configurable_child_instances( - parent_module)[mem_index - 1]; + parent_module, config_child_type)[mem_index - 1]; net_src_port_id = module_manager.find_module_port(net_src_module_id, src_port_name); } @@ -201,9 +211,12 @@ static int remove_submodule_nets_cmos_memory_chain_config_bus( /* Find the port name of previous memory module */ std::string src_port_name = generate_configuration_chain_tail_name(); ModuleId net_src_module_id = - module_manager.configurable_children(parent_module).back(); + module_manager.configurable_children(parent_module, config_child_type) + .back(); size_t net_src_instance_id = - module_manager.configurable_child_instances(parent_module).back(); + module_manager + .configurable_child_instances(parent_module, config_child_type) + .back(); ModulePortId net_src_port_id = module_manager.find_module_port(net_src_module_id, src_port_name); @@ -229,11 +242,12 @@ static int remove_submodule_nets_cmos_memory_chain_config_bus( *******************************************************************/ static int remove_submodule_nets_cmos_memory_config_bus( ModuleManager& module_manager, const ModuleId& module_id, - const e_config_protocol_type& sram_orgz_type) { + const e_config_protocol_type& sram_orgz_type, + const ModuleManager::e_config_child_type& config_child_type) { switch (sram_orgz_type) { case CONFIG_MEM_SCAN_CHAIN: { return remove_submodule_nets_cmos_memory_chain_config_bus( - module_manager, module_id, sram_orgz_type); + module_manager, module_id, sram_orgz_type, config_child_type); break; } case CONFIG_MEM_STANDALONE: @@ -274,11 +288,12 @@ static int remove_submodule_nets_cmos_memory_config_bus( *******************************************************************/ static int remove_submodule_configurable_children_nets( ModuleManager& module_manager, const ModuleId& module_id, - const CircuitLibrary& circuit_lib, const ConfigProtocol& config_protocol) { + const CircuitLibrary& circuit_lib, const ConfigProtocol& config_protocol, + const ModuleManager::e_config_child_type& config_child_type) { switch (circuit_lib.design_tech_type(config_protocol.memory_model())) { case CIRCUIT_MODEL_DESIGN_CMOS: return remove_submodule_nets_cmos_memory_config_bus( - module_manager, module_id, config_protocol.type()); + module_manager, module_id, config_protocol.type(), config_child_type); break; case CIRCUIT_MODEL_DESIGN_RRAM: /* TODO: */ @@ -297,9 +312,12 @@ static int remove_submodule_configurable_children_nets( *******************************************************************/ static int rebuild_submodule_nets_cmos_memory_chain_config_bus( ModuleManager& module_manager, const ModuleId& parent_module, - const e_config_protocol_type& sram_orgz_type) { + const e_config_protocol_type& sram_orgz_type, + const ModuleManager::e_config_child_type& config_child_type) { for (size_t mem_index = 0; - mem_index < module_manager.configurable_children(parent_module).size(); + mem_index < + module_manager.configurable_children(parent_module, config_child_type) + .size(); ++mem_index) { ModuleId net_src_module_id; size_t net_src_instance_id; @@ -320,28 +338,28 @@ static int rebuild_submodule_nets_cmos_memory_chain_config_bus( /* Find the port name of next memory module */ std::string sink_port_name = generate_configuration_chain_head_name(); - net_sink_module_id = - module_manager.configurable_children(parent_module)[mem_index]; - net_sink_instance_id = - module_manager.configurable_child_instances(parent_module)[mem_index]; + net_sink_module_id = module_manager.configurable_children( + parent_module, config_child_type)[mem_index]; + net_sink_instance_id = module_manager.configurable_child_instances( + parent_module, config_child_type)[mem_index]; net_sink_port_id = module_manager.find_module_port(net_sink_module_id, sink_port_name); } else { /* Find the port name of previous memory module */ std::string src_port_name = generate_configuration_chain_tail_name(); - net_src_module_id = - module_manager.configurable_children(parent_module)[mem_index - 1]; + net_src_module_id = module_manager.configurable_children( + parent_module, config_child_type)[mem_index - 1]; net_src_instance_id = module_manager.configurable_child_instances( - parent_module)[mem_index - 1]; + parent_module, config_child_type)[mem_index - 1]; net_src_port_id = module_manager.find_module_port(net_src_module_id, src_port_name); /* Find the port name of next memory module */ std::string sink_port_name = generate_configuration_chain_head_name(); - net_sink_module_id = - module_manager.configurable_children(parent_module)[mem_index]; - net_sink_instance_id = - module_manager.configurable_child_instances(parent_module)[mem_index]; + net_sink_module_id = module_manager.configurable_children( + parent_module, config_child_type)[mem_index]; + net_sink_instance_id = module_manager.configurable_child_instances( + parent_module, config_child_type)[mem_index]; net_sink_port_id = module_manager.find_module_port(net_sink_module_id, sink_port_name); } @@ -375,9 +393,12 @@ static int rebuild_submodule_nets_cmos_memory_chain_config_bus( /* Find the port name of previous memory module */ std::string src_port_name = generate_configuration_chain_tail_name(); ModuleId net_src_module_id = - module_manager.configurable_children(parent_module).back(); + module_manager.configurable_children(parent_module, config_child_type) + .back(); size_t net_src_instance_id = - module_manager.configurable_child_instances(parent_module).back(); + module_manager + .configurable_child_instances(parent_module, config_child_type) + .back(); ModulePortId net_src_port_id = module_manager.find_module_port(net_src_module_id, src_port_name); @@ -418,11 +439,12 @@ static int rebuild_submodule_nets_cmos_memory_chain_config_bus( *******************************************************************/ static int rebuild_submodule_nets_cmos_memory_config_bus( ModuleManager& module_manager, const ModuleId& module_id, - const e_config_protocol_type& sram_orgz_type) { + const e_config_protocol_type& sram_orgz_type, + const ModuleManager::e_config_child_type& config_child_type) { switch (sram_orgz_type) { case CONFIG_MEM_SCAN_CHAIN: { return rebuild_submodule_nets_cmos_memory_chain_config_bus( - module_manager, module_id, sram_orgz_type); + module_manager, module_id, sram_orgz_type, config_child_type); break; } case CONFIG_MEM_STANDALONE: @@ -464,11 +486,12 @@ static int rebuild_submodule_nets_cmos_memory_config_bus( *******************************************************************/ static int rebuild_submodule_configurable_children_nets( ModuleManager& module_manager, const ModuleId& module_id, - const CircuitLibrary& circuit_lib, const ConfigProtocol& config_protocol) { + const CircuitLibrary& circuit_lib, const ConfigProtocol& config_protocol, + const ModuleManager::e_config_child_type& config_child_type) { switch (circuit_lib.design_tech_type(config_protocol.memory_model())) { case CIRCUIT_MODEL_DESIGN_CMOS: return rebuild_submodule_nets_cmos_memory_config_bus( - module_manager, module_id, config_protocol.type()); + module_manager, module_id, config_protocol.type(), config_child_type); break; case CIRCUIT_MODEL_DESIGN_RRAM: /* TODO: */ @@ -493,7 +516,8 @@ static int rebuild_submodule_configurable_children_nets( static int load_and_update_submodule_memory_modules_from_fabric_key( ModuleManager& module_manager, const ModuleId& module_id, const CircuitLibrary& circuit_lib, const ConfigProtocol& config_protocol, - const FabricKey& fabric_key, const FabricKeyModuleId& key_module_id) { + const FabricKey& fabric_key, const FabricKeyModuleId& key_module_id, + const bool& group_config_block) { int status = CMD_EXEC_SUCCESS; /* Compare the configurable children list */ if (submodule_memory_modules_match_fabric_key(module_manager, module_id, @@ -502,20 +526,24 @@ static int load_and_update_submodule_memory_modules_from_fabric_key( } /* Do not match, now remove all the nets for the configurable children */ status = remove_submodule_configurable_children_nets( - module_manager, module_id, circuit_lib, config_protocol); + module_manager, module_id, circuit_lib, config_protocol, + ModuleManager::e_config_child_type::PHYSICAL); if (status == CMD_EXEC_FATAL_ERROR) { return status; } /* Overwrite the configurable children list */ status = update_submodule_memory_modules_from_fabric_key( - module_manager, module_id, circuit_lib, config_protocol, fabric_key, - key_module_id); + module_manager, module_id, circuit_lib, config_protocol, + group_config_block ? ModuleManager::e_config_child_type::PHYSICAL + : ModuleManager::e_config_child_type::UNIFIED, + fabric_key, key_module_id); if (status == CMD_EXEC_FATAL_ERROR) { return status; } /* TODO: Create the nets for the new list of configurable children */ status = rebuild_submodule_configurable_children_nets( - module_manager, module_id, circuit_lib, config_protocol); + module_manager, module_id, circuit_lib, config_protocol, + ModuleManager::e_config_child_type::PHYSICAL); if (status == CMD_EXEC_FATAL_ERROR) { return status; } @@ -528,7 +556,8 @@ static int load_and_update_submodule_memory_modules_from_fabric_key( *******************************************************************/ int load_submodules_memory_modules_from_fabric_key( ModuleManager& module_manager, const CircuitLibrary& circuit_lib, - const ConfigProtocol& config_protocol, const FabricKey& fabric_key) { + const ConfigProtocol& config_protocol, const FabricKey& fabric_key, + const bool& group_config_block) { int status = CMD_EXEC_SUCCESS; for (FabricKeyModuleId key_module_id : fabric_key.modules()) { std::string module_name = fabric_key.module_name(key_module_id); @@ -544,7 +573,7 @@ int load_submodules_memory_modules_from_fabric_key( /* This is a valid module, try to load and update */ status = load_and_update_submodule_memory_modules_from_fabric_key( module_manager, module_id, circuit_lib, config_protocol, fabric_key, - key_module_id); + key_module_id, group_config_block); if (status == CMD_EXEC_FATAL_ERROR) { return status; } diff --git a/openfpga/src/utils/module_manager_memory_utils.h b/openfpga/src/utils/module_manager_memory_utils.h index a0573bc98..5f7a75b8e 100644 --- a/openfpga/src/utils/module_manager_memory_utils.h +++ b/openfpga/src/utils/module_manager_memory_utils.h @@ -34,7 +34,8 @@ namespace openfpga { int load_submodules_memory_modules_from_fabric_key( ModuleManager& module_manager, const CircuitLibrary& circuit_lib, - const ConfigProtocol& config_protocol, const FabricKey& fabric_key); + const ConfigProtocol& config_protocol, const FabricKey& fabric_key, + const bool& group_config_block); } /* end namespace openfpga */ diff --git a/openfpga/src/utils/module_manager_utils.cpp b/openfpga/src/utils/module_manager_utils.cpp index 37bbdd2cb..70a62d148 100644 --- a/openfpga/src/utils/module_manager_utils.cpp +++ b/openfpga/src/utils/module_manager_utils.cpp @@ -86,11 +86,14 @@ void reserve_module_manager_module_nets(ModuleManager& module_manager, *children as well ******************************************************************************/ size_t count_module_manager_module_configurable_children( - const ModuleManager& module_manager, const ModuleId& module) { + const ModuleManager& module_manager, const ModuleId& module, + const ModuleManager::e_config_child_type& config_child_type) { size_t num_config_children = 0; - for (const ModuleId& child : module_manager.configurable_children(module)) { - if (0 != module_manager.configurable_children(child).size()) { + for (const ModuleId& child : + module_manager.configurable_children(module, config_child_type)) { + if (0 != + module_manager.configurable_children(child, config_child_type).size()) { num_config_children++; } } @@ -342,6 +345,7 @@ void add_sram_ports_to_module_manager( /* Add ports to the module manager */ switch (sram_orgz_type) { + case CONFIG_MEM_FEEDTHROUGH: case CONFIG_MEM_STANDALONE: case CONFIG_MEM_QL_MEMORY_BANK: case CONFIG_MEM_MEMORY_BANK: { @@ -1017,7 +1021,8 @@ void add_module_nets_between_logic_and_memory_sram_bus( void add_module_nets_cmos_flatten_memory_config_bus( ModuleManager& module_manager, const ModuleId& parent_module, const e_config_protocol_type& sram_orgz_type, - const e_circuit_model_port_type& config_port_type) { + const e_circuit_model_port_type& config_port_type, + const ModuleManager::e_config_child_type& config_child_type) { /* A counter for the current pin id for the source port of parent module */ size_t cur_src_pin_id = 0; @@ -1039,7 +1044,8 @@ void add_module_nets_cmos_flatten_memory_config_bus( module_manager.module_port(net_src_module_id, net_src_port_id); for (size_t mem_index = 0; - mem_index < module_manager.configurable_children(parent_module).size(); + mem_index < module_manager.num_configurable_children(parent_module, + config_child_type); ++mem_index) { ModuleId net_sink_module_id; size_t net_sink_instance_id; @@ -1048,10 +1054,10 @@ void add_module_nets_cmos_flatten_memory_config_bus( /* Find the port name of next memory module */ std::string sink_port_name = generate_sram_port_name(sram_orgz_type, config_port_type); - net_sink_module_id = - module_manager.configurable_children(parent_module)[mem_index]; - net_sink_instance_id = - module_manager.configurable_child_instances(parent_module)[mem_index]; + net_sink_module_id = module_manager.configurable_children( + parent_module, config_child_type)[mem_index]; + net_sink_instance_id = module_manager.configurable_child_instances( + parent_module, config_child_type)[mem_index]; net_sink_port_id = module_manager.find_module_port(net_sink_module_id, sink_port_name); @@ -1105,7 +1111,8 @@ void add_module_nets_cmos_flatten_memory_config_bus( void add_module_nets_cmos_memory_bank_bl_config_bus( ModuleManager& module_manager, const ModuleId& parent_module, const e_config_protocol_type& sram_orgz_type, - const e_circuit_model_port_type& config_port_type) { + const e_circuit_model_port_type& config_port_type, + const ModuleManager::e_config_child_type& config_child_type) { /* A counter for the current pin id for the source port of parent module */ size_t cur_src_pin_id = 0; @@ -1122,15 +1129,17 @@ void add_module_nets_cmos_memory_bank_bl_config_bus( module_manager.module_port(net_src_module_id, net_src_port_id); for (size_t mem_index = 0; - mem_index < module_manager.configurable_children(parent_module).size(); + mem_index < + module_manager.configurable_children(parent_module, config_child_type) + .size(); ++mem_index) { /* Find the port name of next memory module */ std::string sink_port_name = generate_sram_port_name(sram_orgz_type, config_port_type); - ModuleId net_sink_module_id = - module_manager.configurable_children(parent_module)[mem_index]; - size_t net_sink_instance_id = - module_manager.configurable_child_instances(parent_module)[mem_index]; + ModuleId net_sink_module_id = module_manager.configurable_children( + parent_module, config_child_type)[mem_index]; + size_t net_sink_instance_id = module_manager.configurable_child_instances( + parent_module, config_child_type)[mem_index]; ModulePortId net_sink_port_id = module_manager.find_module_port(net_sink_module_id, sink_port_name); @@ -1188,7 +1197,8 @@ void add_module_nets_cmos_memory_bank_bl_config_bus( void add_module_nets_cmos_memory_bank_wl_config_bus( ModuleManager& module_manager, const ModuleId& parent_module, const e_config_protocol_type& sram_orgz_type, - const e_circuit_model_port_type& config_port_type) { + const e_circuit_model_port_type& config_port_type, + const ModuleManager::e_config_child_type& config_child_type) { /* A counter for the current pin id for the source port of parent module */ size_t cur_src_pin_id = 0; @@ -1217,15 +1227,17 @@ void add_module_nets_cmos_memory_bank_wl_config_bus( module_manager.module_port(net_src_module_id, net_bl_port_id); for (size_t mem_index = 0; - mem_index < module_manager.configurable_children(parent_module).size(); + mem_index < + module_manager.configurable_children(parent_module, config_child_type) + .size(); ++mem_index) { /* Find the port name of next memory module */ std::string sink_port_name = generate_sram_port_name(sram_orgz_type, config_port_type); - ModuleId net_sink_module_id = - module_manager.configurable_children(parent_module)[mem_index]; - size_t net_sink_instance_id = - module_manager.configurable_child_instances(parent_module)[mem_index]; + ModuleId net_sink_module_id = module_manager.configurable_children( + parent_module, config_child_type)[mem_index]; + size_t net_sink_instance_id = module_manager.configurable_child_instances( + parent_module, config_child_type)[mem_index]; ModulePortId net_sink_port_id = module_manager.find_module_port(net_sink_module_id, sink_port_name); @@ -1272,9 +1284,11 @@ void add_module_nets_cmos_memory_bank_wl_config_bus( *********************************************************************/ void add_module_nets_cmos_memory_chain_config_bus( ModuleManager& module_manager, const ModuleId& parent_module, - const e_config_protocol_type& sram_orgz_type) { + const e_config_protocol_type& sram_orgz_type, + const ModuleManager::e_config_child_type& config_child_type) { for (size_t mem_index = 0; - mem_index < module_manager.configurable_children(parent_module).size(); + mem_index < module_manager.num_configurable_children(parent_module, + config_child_type); ++mem_index) { ModuleId net_src_module_id; size_t net_src_instance_id; @@ -1295,28 +1309,28 @@ void add_module_nets_cmos_memory_chain_config_bus( /* Find the port name of next memory module */ std::string sink_port_name = generate_configuration_chain_head_name(); - net_sink_module_id = - module_manager.configurable_children(parent_module)[mem_index]; - net_sink_instance_id = - module_manager.configurable_child_instances(parent_module)[mem_index]; + net_sink_module_id = module_manager.configurable_children( + parent_module, config_child_type)[mem_index]; + net_sink_instance_id = module_manager.configurable_child_instances( + parent_module, config_child_type)[mem_index]; net_sink_port_id = module_manager.find_module_port(net_sink_module_id, sink_port_name); } else { /* Find the port name of previous memory module */ std::string src_port_name = generate_configuration_chain_tail_name(); - net_src_module_id = - module_manager.configurable_children(parent_module)[mem_index - 1]; + net_src_module_id = module_manager.configurable_children( + parent_module, config_child_type)[mem_index - 1]; net_src_instance_id = module_manager.configurable_child_instances( - parent_module)[mem_index - 1]; + parent_module, config_child_type)[mem_index - 1]; net_src_port_id = module_manager.find_module_port(net_src_module_id, src_port_name); /* Find the port name of next memory module */ std::string sink_port_name = generate_configuration_chain_head_name(); - net_sink_module_id = - module_manager.configurable_children(parent_module)[mem_index]; - net_sink_instance_id = - module_manager.configurable_child_instances(parent_module)[mem_index]; + net_sink_module_id = module_manager.configurable_children( + parent_module, config_child_type)[mem_index]; + net_sink_instance_id = module_manager.configurable_child_instances( + parent_module, config_child_type)[mem_index]; net_sink_port_id = module_manager.find_module_port(net_sink_module_id, sink_port_name); } @@ -1350,9 +1364,12 @@ void add_module_nets_cmos_memory_chain_config_bus( /* Find the port name of previous memory module */ std::string src_port_name = generate_configuration_chain_tail_name(); ModuleId net_src_module_id = - module_manager.configurable_children(parent_module).back(); + module_manager.configurable_children(parent_module, config_child_type) + .back(); size_t net_src_instance_id = - module_manager.configurable_child_instances(parent_module).back(); + module_manager + .configurable_child_instances(parent_module, config_child_type) + .back(); ModulePortId net_src_port_id = module_manager.find_module_port(net_src_module_id, src_port_name); @@ -1406,9 +1423,10 @@ void add_module_nets_cmos_memory_chain_config_bus( * *********************************************************************/ static void add_module_nets_cmos_memory_frame_short_config_bus( - ModuleManager& module_manager, const ModuleId& parent_module) { + ModuleManager& module_manager, const ModuleId& parent_module, + const ModuleManager::e_config_child_type& config_child_type) { std::vector configurable_children = - module_manager.configurable_children(parent_module); + module_manager.configurable_children(parent_module, config_child_type); VTR_ASSERT(1 == configurable_children.size()); ModuleId child_module = configurable_children[0]; @@ -1490,9 +1508,10 @@ static void add_module_nets_cmos_memory_frame_short_config_bus( *********************************************************************/ static void add_module_nets_cmos_memory_frame_decoder_config_bus( ModuleManager& module_manager, DecoderLibrary& decoder_lib, - const ModuleId& parent_module) { + const ModuleId& parent_module, + const ModuleManager::e_config_child_type& config_child_type) { std::vector configurable_children = - module_manager.configurable_children(parent_module); + module_manager.configurable_children(parent_module, config_child_type); /* Find the decoder specification */ size_t addr_size = @@ -1570,8 +1589,8 @@ static void add_module_nets_cmos_memory_frame_decoder_config_bus( for (size_t mem_index = 0; mem_index < configurable_children.size(); ++mem_index) { ModuleId child_module = configurable_children[mem_index]; - size_t child_instance = - module_manager.configurable_child_instances(parent_module)[mem_index]; + size_t child_instance = module_manager.configurable_child_instances( + parent_module, config_child_type)[mem_index]; ModulePortId child_addr_port = module_manager.find_module_port( child_module, std::string(DECODER_ADDRESS_PORT_NAME)); BasicPort child_addr_port_info = @@ -1602,8 +1621,8 @@ static void add_module_nets_cmos_memory_frame_decoder_config_bus( for (size_t mem_index = 0; mem_index < configurable_children.size(); ++mem_index) { ModuleId child_module = configurable_children[mem_index]; - size_t child_instance = - module_manager.configurable_child_instances(parent_module)[mem_index]; + size_t child_instance = module_manager.configurable_child_instances( + parent_module, config_child_type)[mem_index]; ModulePortId child_din_port = module_manager.find_module_port( child_module, std::string(DECODER_DATA_IN_PORT_NAME)); add_module_bus_nets(module_manager, parent_module, parent_module, 0, @@ -1623,8 +1642,8 @@ static void add_module_nets_cmos_memory_frame_decoder_config_bus( for (size_t mem_index = 0; mem_index < configurable_children.size(); ++mem_index) { ModuleId child_module = configurable_children[mem_index]; - size_t child_instance = - module_manager.configurable_child_instances(parent_module)[mem_index]; + size_t child_instance = module_manager.configurable_child_instances( + parent_module, config_child_type)[mem_index]; ModulePortId child_en_port = module_manager.find_module_port( child_module, std::string(DECODER_ENABLE_PORT_NAME)); BasicPort child_en_port_info = @@ -1648,7 +1667,9 @@ static void add_module_nets_cmos_memory_frame_decoder_config_bus( } /* Add the decoder as the last configurable children */ - module_manager.add_configurable_child(parent_module, decoder_module, 0); + module_manager.add_configurable_child( + parent_module, decoder_module, 0, + ModuleManager::e_config_child_type::UNIFIED); } /********************************************************************* @@ -1662,18 +1683,22 @@ static void add_module_nets_cmos_memory_frame_decoder_config_bus( **********************************************************************/ void add_module_nets_cmos_memory_frame_config_bus( ModuleManager& module_manager, DecoderLibrary& decoder_lib, - const ModuleId& parent_module) { - if (0 == module_manager.configurable_children(parent_module).size()) { + const ModuleId& parent_module, + const ModuleManager::e_config_child_type& config_child_type) { + if (0 == module_manager.num_configurable_children(parent_module, + config_child_type)) { return; } - if (1 == module_manager.configurable_children(parent_module).size()) { - add_module_nets_cmos_memory_frame_short_config_bus(module_manager, - parent_module); + if (1 == module_manager.num_configurable_children(parent_module, + config_child_type)) { + add_module_nets_cmos_memory_frame_short_config_bus( + module_manager, parent_module, config_child_type); } else { - VTR_ASSERT(1 < module_manager.configurable_children(parent_module).size()); + VTR_ASSERT(1 < module_manager.num_configurable_children(parent_module, + config_child_type)); add_module_nets_cmos_memory_frame_decoder_config_bus( - module_manager, decoder_lib, parent_module); + module_manager, decoder_lib, parent_module, config_child_type); } } @@ -1723,26 +1748,38 @@ void add_module_nets_cmos_memory_frame_config_bus( **********************************************************************/ static void add_module_nets_cmos_memory_config_bus( ModuleManager& module_manager, DecoderLibrary& decoder_lib, - const ModuleId& parent_module, const e_config_protocol_type& sram_orgz_type) { + const ModuleId& parent_module, const e_config_protocol_type& sram_orgz_type, + const ModuleManager::e_config_child_type& config_child_type) { switch (sram_orgz_type) { case CONFIG_MEM_SCAN_CHAIN: { add_module_nets_cmos_memory_chain_config_bus( - module_manager, parent_module, sram_orgz_type); + module_manager, parent_module, sram_orgz_type, config_child_type); break; } + case CONFIG_MEM_FEEDTHROUGH: + add_module_nets_cmos_flatten_memory_config_bus( + module_manager, parent_module, sram_orgz_type, CIRCUIT_MODEL_PORT_BL, + config_child_type); + add_module_nets_cmos_flatten_memory_config_bus( + module_manager, parent_module, sram_orgz_type, CIRCUIT_MODEL_PORT_BLB, + config_child_type); + break; case CONFIG_MEM_STANDALONE: case CONFIG_MEM_QL_MEMORY_BANK: case CONFIG_MEM_MEMORY_BANK: add_module_nets_cmos_flatten_memory_config_bus( - module_manager, parent_module, sram_orgz_type, CIRCUIT_MODEL_PORT_BL); + module_manager, parent_module, sram_orgz_type, CIRCUIT_MODEL_PORT_BL, + config_child_type); add_module_nets_cmos_flatten_memory_config_bus( - module_manager, parent_module, sram_orgz_type, CIRCUIT_MODEL_PORT_WL); + module_manager, parent_module, sram_orgz_type, CIRCUIT_MODEL_PORT_WL, + config_child_type); add_module_nets_cmos_flatten_memory_config_bus( - module_manager, parent_module, sram_orgz_type, CIRCUIT_MODEL_PORT_WLR); + module_manager, parent_module, sram_orgz_type, CIRCUIT_MODEL_PORT_WLR, + config_child_type); break; case CONFIG_MEM_FRAME_BASED: - add_module_nets_cmos_memory_frame_config_bus(module_manager, decoder_lib, - parent_module); + add_module_nets_cmos_memory_frame_config_bus( + module_manager, decoder_lib, parent_module, config_child_type); break; default: VTR_LOGF_ERROR(__FILE__, __LINE__, @@ -1788,31 +1825,37 @@ static void add_module_nets_cmos_memory_config_bus( **********************************************************************/ static void add_pb_module_nets_cmos_memory_config_bus( ModuleManager& module_manager, DecoderLibrary& decoder_lib, - const ModuleId& parent_module, const e_config_protocol_type& sram_orgz_type) { + const ModuleId& parent_module, const e_config_protocol_type& sram_orgz_type, + const ModuleManager::e_config_child_type& config_child_type) { switch (sram_orgz_type) { case CONFIG_MEM_SCAN_CHAIN: { add_module_nets_cmos_memory_chain_config_bus( - module_manager, parent_module, sram_orgz_type); + module_manager, parent_module, sram_orgz_type, config_child_type); break; } case CONFIG_MEM_STANDALONE: case CONFIG_MEM_QL_MEMORY_BANK: add_module_nets_cmos_memory_bank_bl_config_bus( - module_manager, parent_module, sram_orgz_type, CIRCUIT_MODEL_PORT_BL); + module_manager, parent_module, sram_orgz_type, CIRCUIT_MODEL_PORT_BL, + config_child_type); add_module_nets_cmos_memory_bank_wl_config_bus( - module_manager, parent_module, sram_orgz_type, CIRCUIT_MODEL_PORT_WL); + module_manager, parent_module, sram_orgz_type, CIRCUIT_MODEL_PORT_WL, + config_child_type); add_module_nets_cmos_memory_bank_wl_config_bus( - module_manager, parent_module, sram_orgz_type, CIRCUIT_MODEL_PORT_WLR); + module_manager, parent_module, sram_orgz_type, CIRCUIT_MODEL_PORT_WLR, + config_child_type); break; case CONFIG_MEM_MEMORY_BANK: add_module_nets_cmos_flatten_memory_config_bus( - module_manager, parent_module, sram_orgz_type, CIRCUIT_MODEL_PORT_BL); + module_manager, parent_module, sram_orgz_type, CIRCUIT_MODEL_PORT_BL, + config_child_type); add_module_nets_cmos_flatten_memory_config_bus( - module_manager, parent_module, sram_orgz_type, CIRCUIT_MODEL_PORT_WL); + module_manager, parent_module, sram_orgz_type, CIRCUIT_MODEL_PORT_WL, + config_child_type); break; case CONFIG_MEM_FRAME_BASED: - add_module_nets_cmos_memory_frame_config_bus(module_manager, decoder_lib, - parent_module); + add_module_nets_cmos_memory_frame_config_bus( + module_manager, decoder_lib, parent_module, config_child_type); break; default: VTR_LOGF_ERROR(__FILE__, __LINE__, @@ -1878,11 +1921,13 @@ static void add_pb_module_nets_cmos_memory_config_bus( void add_module_nets_memory_config_bus( ModuleManager& module_manager, DecoderLibrary& decoder_lib, const ModuleId& parent_module, const e_config_protocol_type& sram_orgz_type, - const e_circuit_model_design_tech& mem_tech) { + const e_circuit_model_design_tech& mem_tech, + const ModuleManager::e_config_child_type& config_child_type) { switch (mem_tech) { case CIRCUIT_MODEL_DESIGN_CMOS: add_module_nets_cmos_memory_config_bus(module_manager, decoder_lib, - parent_module, sram_orgz_type); + parent_module, sram_orgz_type, + config_child_type); break; case CIRCUIT_MODEL_DESIGN_RRAM: /* TODO: */ @@ -1909,11 +1954,13 @@ void add_module_nets_memory_config_bus( void add_pb_module_nets_memory_config_bus( ModuleManager& module_manager, DecoderLibrary& decoder_lib, const ModuleId& parent_module, const e_config_protocol_type& sram_orgz_type, - const e_circuit_model_design_tech& mem_tech) { + const e_circuit_model_design_tech& mem_tech, + const ModuleManager::e_config_child_type& config_child_type) { switch (mem_tech) { case CIRCUIT_MODEL_DESIGN_CMOS: add_pb_module_nets_cmos_memory_config_bus(module_manager, decoder_lib, - parent_module, sram_orgz_type); + parent_module, sram_orgz_type, + config_child_type); break; case CIRCUIT_MODEL_DESIGN_RRAM: /* TODO: */ @@ -2364,10 +2411,12 @@ size_t find_module_num_shared_config_bits_from_child_modules( size_t find_module_num_config_bits_from_child_modules( ModuleManager& module_manager, const ModuleId& module_id, const CircuitLibrary& circuit_lib, const CircuitModelId& sram_model, - const e_config_protocol_type& sram_orgz_type) { + const e_config_protocol_type& sram_orgz_type, + const ModuleManager::e_config_child_type& config_child_type) { size_t num_config_bits = 0; switch (sram_orgz_type) { + case CONFIG_MEM_FEEDTHROUGH: case CONFIG_MEM_STANDALONE: case CONFIG_MEM_SCAN_CHAIN: case CONFIG_MEM_QL_MEMORY_BANK: @@ -2377,7 +2426,7 @@ size_t find_module_num_config_bits_from_child_modules( * per configurable children */ for (const ModuleId& child : - module_manager.configurable_children(module_id)) { + module_manager.configurable_children(module_id, config_child_type)) { num_config_bits += find_module_num_config_bits( module_manager, child, circuit_lib, sram_model, sram_orgz_type); } @@ -2390,7 +2439,7 @@ size_t find_module_num_config_bits_from_child_modules( * - and the number of configurable children */ for (const ModuleId& child : - module_manager.configurable_children(module_id)) { + module_manager.configurable_children(module_id, config_child_type)) { size_t temp_num_config_bits = find_module_num_config_bits( module_manager, child, circuit_lib, sram_model, sram_orgz_type); num_config_bits = @@ -2400,9 +2449,11 @@ size_t find_module_num_config_bits_from_child_modules( /* 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.configurable_children(module_id).size()) { + if (1 < module_manager.num_configurable_children(module_id, + config_child_type)) { num_config_bits += find_mux_local_decoder_addr_size( - module_manager.configurable_children(module_id).size()); + module_manager.num_configurable_children(module_id, + config_child_type)); } break; diff --git a/openfpga/src/utils/module_manager_utils.h b/openfpga/src/utils/module_manager_utils.h index 8a3566df9..f55f73402 100644 --- a/openfpga/src/utils/module_manager_utils.h +++ b/openfpga/src/utils/module_manager_utils.h @@ -42,7 +42,8 @@ void reserve_module_manager_module_nets(ModuleManager& module_manager, const ModuleId& module); size_t count_module_manager_module_configurable_children( - const ModuleManager& module_manager, const ModuleId& module); + const ModuleManager& module_manager, const ModuleId& module, + const ModuleManager::e_config_child_type& config_child_type); std::pair find_module_manager_instance_module_info( const ModuleManager& module_manager, const ModuleId& parent, @@ -110,35 +111,42 @@ void add_module_nets_between_logic_and_memory_sram_bus( void add_module_nets_cmos_flatten_memory_config_bus( ModuleManager& module_manager, const ModuleId& parent_module, const e_config_protocol_type& sram_orgz_type, - const e_circuit_model_port_type& config_port_type); + const e_circuit_model_port_type& config_port_type, + const ModuleManager::e_config_child_type& config_child_type); void add_module_nets_cmos_memory_bank_bl_config_bus( ModuleManager& module_manager, const ModuleId& parent_module, const e_config_protocol_type& sram_orgz_type, - const e_circuit_model_port_type& config_port_type); + const e_circuit_model_port_type& config_port_type, + const ModuleManager::e_config_child_type& config_child_type); void add_module_nets_cmos_memory_bank_wl_config_bus( ModuleManager& module_manager, const ModuleId& parent_module, const e_config_protocol_type& sram_orgz_type, - const e_circuit_model_port_type& config_port_type); + const e_circuit_model_port_type& config_port_type, + const ModuleManager::e_config_child_type& config_child_type); void add_module_nets_cmos_memory_chain_config_bus( ModuleManager& module_manager, const ModuleId& parent_module, - const e_config_protocol_type& sram_orgz_type); + const e_config_protocol_type& sram_orgz_type, + const ModuleManager::e_config_child_type& config_child_type); void add_module_nets_cmos_memory_frame_config_bus( ModuleManager& module_manager, DecoderLibrary& decoder_lib, - const ModuleId& parent_module); + const ModuleId& parent_module, + const ModuleManager::e_config_child_type& config_child_type); void add_module_nets_memory_config_bus( ModuleManager& module_manager, DecoderLibrary& decoder_lib, const ModuleId& parent_module, const e_config_protocol_type& sram_orgz_type, - const e_circuit_model_design_tech& mem_tech); + const e_circuit_model_design_tech& mem_tech, + const ModuleManager::e_config_child_type& config_child_type); void add_pb_module_nets_memory_config_bus( ModuleManager& module_manager, DecoderLibrary& decoder_lib, const ModuleId& parent_module, const e_config_protocol_type& sram_orgz_type, - const e_circuit_model_design_tech& mem_tech); + const e_circuit_model_design_tech& mem_tech, + const ModuleManager::e_config_child_type& config_child_type); size_t find_module_num_shared_config_bits(const ModuleManager& module_manager, const ModuleId& module_id); @@ -170,7 +178,8 @@ size_t find_module_num_shared_config_bits_from_child_modules( size_t find_module_num_config_bits_from_child_modules( ModuleManager& module_manager, const ModuleId& module_id, const CircuitLibrary& circuit_lib, const CircuitModelId& sram_model, - const e_config_protocol_type& sram_orgz_type); + const e_config_protocol_type& sram_orgz_type, + const ModuleManager::e_config_child_type& config_child_type); ModuleNetId create_module_source_pin_net(ModuleManager& module_manager, const ModuleId& cur_module_id, diff --git a/openfpga_flow/openfpga_shell_scripts/group_config_block_full_testbench_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/group_config_block_full_testbench_example_script.openfpga new file mode 100644 index 000000000..5b60dc626 --- /dev/null +++ b/openfpga_flow/openfpga_shell_scripts/group_config_block_full_testbench_example_script.openfpga @@ -0,0 +1,74 @@ +# Run VPR for the 'and' design +#--write_rr_graph example_rr_graph.xml +vpr ${VPR_ARCH_FILE} ${VPR_TESTBENCH_BLIF} --clock_modeling route + +# Read OpenFPGA architecture definition +read_openfpga_arch -f ${OPENFPGA_ARCH_FILE} + +# Read OpenFPGA simulation settings +read_openfpga_simulation_setting -f ${OPENFPGA_SIM_SETTING_FILE} + +# Annotate the OpenFPGA architecture to VPR data base +# to debug use --verbose options +link_openfpga_arch --activity_file ${ACTIVITY_FILE} --sort_gsb_chan_node_in_edges + +# Check and correct any naming conflicts in the BLIF netlist +check_netlist_naming_conflict --fix --report ./netlist_renaming.xml + +# Apply fix-up to Look-Up Table truth tables based on packing results +lut_truth_table_fixup + +# Build the module graph +# - Enabled compression on routing architecture modules +# - Enable pin duplication on grid modules +build_fabric --compress_routing --group_config_block ${OPENFPGA_GROUP_TILE_CONFIG_OPTION} #--verbose +# Add a fpga core between fpga top and the underlying modules +${OPENFPGA_ADD_FPGA_CORE_MODULE} + +# Write the fabric hierarchy of module graph to a file +# This is used by hierarchical PnR flows +write_fabric_hierarchy --file ./fabric_hierarchy.txt + +# Repack the netlist to physical pbs +# This must be done before bitstream generator and testbench generation +# Strongly recommend it is done after all the fix-up have been applied +repack #--verbose + +# Build the bitstream +# - Output the fabric-independent bitstream to a file +build_architecture_bitstream --verbose --write_file fabric_independent_bitstream.xml + +# Build fabric-dependent bitstream +build_fabric_bitstream --verbose + +# Write fabric-dependent bitstream +write_fabric_bitstream --file fabric_bitstream.bit --format plain_text + +# Write the Verilog netlist for FPGA fabric +# - Enable the use of explicit port mapping in Verilog netlist +write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --print_user_defined_template --verbose + +# Write the Verilog testbench for FPGA fabric +# - We suggest the use of same output directory as fabric Verilog netlists +# - Must specify the reference benchmark file if you want to output any testbenches +# - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA +# - Enable pre-configured top-level testbench which is a fast verification skipping programming phase +# - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts +write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --include_signal_init --bitstream fabric_bitstream.bit + +# Write the SDC files for PnR backend +# - Turn on every options here +# FIXME: Not supported yet. +#write_pnr_sdc --file ./SDC + +# Write SDC to disable timing for configure ports +write_sdc_disable_timing_configure_ports --file ./SDC/disable_configure_ports.sdc + +# Write the SDC to run timing analysis for a mapped FPGA fabric +write_analysis_sdc --file ./SDC_analysis + +# Finish and exit OpenFPGA +exit + +# Note : +# To run verification at the end of the flow maintain source in ./SRC directory diff --git a/openfpga_flow/openfpga_shell_scripts/group_config_block_preconfig_testbench_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/group_config_block_preconfig_testbench_example_script.openfpga new file mode 100644 index 000000000..978feaa56 --- /dev/null +++ b/openfpga_flow/openfpga_shell_scripts/group_config_block_preconfig_testbench_example_script.openfpga @@ -0,0 +1,78 @@ +# Run VPR for the 'and' design +#--write_rr_graph example_rr_graph.xml +vpr ${VPR_ARCH_FILE} ${VPR_TESTBENCH_BLIF} --device ${OPENFPGA_VPR_DEVICE} --route_chan_width ${OPENFPGA_VPR_ROUTE_CHAN_WIDTH} --clock_modeling ideal ${OPENFPGA_VPR_EXTRA_OPTIONS} + +# Read OpenFPGA architecture definition +read_openfpga_arch -f ${OPENFPGA_ARCH_FILE} + +# Read OpenFPGA simulation settings +read_openfpga_simulation_setting -f ${OPENFPGA_SIM_SETTING_FILE} + +# Annotate the OpenFPGA architecture to VPR data base +# to debug use --verbose options +link_openfpga_arch --sort_gsb_chan_node_in_edges + +# Check and correct any naming conflicts in the BLIF netlist +check_netlist_naming_conflict --fix --report ./netlist_renaming.xml + +# Apply fix-up to Look-Up Table truth tables based on packing results +lut_truth_table_fixup + +# Optionally pb pin fixup +${OPENFPGA_PB_PIN_FIXUP_COMMAND} + +# Build the module graph +# - Enabled compression on routing architecture modules +# - Enable pin duplication on grid modules +build_fabric --compress_routing --group_config_block ${OPENFPGA_GROUP_TILE_CONFIG_OPTION} #--verbose +# Add a fpga core between fpga top and the underlying modules +${OPENFPGA_ADD_FPGA_CORE_MODULE} + +# Write the fabric hierarchy of module graph to a file +# This is used by hierarchical PnR flows +write_fabric_hierarchy --file ./fabric_hierarchy.txt + +# Repack the netlist to physical pbs +# This must be done before bitstream generator and testbench generation +# Strongly recommend it is done after all the fix-up have been applied +repack #--verbose + +# Build the bitstream +# - Output the fabric-independent bitstream to a file +build_architecture_bitstream --verbose --write_file fabric_independent_bitstream.xml + +# Build fabric-dependent bitstream +build_fabric_bitstream --verbose + +# Write fabric-dependent bitstream +write_fabric_bitstream --file fabric_bitstream.bit --format plain_text + +# Write the Verilog netlist for FPGA fabric +# - Enable the use of explicit port mapping in Verilog netlist +write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --print_user_defined_template --verbose + +# Write the Verilog testbench for FPGA fabric +# - We suggest the use of same output directory as fabric Verilog netlists +# - Must specify the reference benchmark file if you want to output any testbenches +# - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA +# - Enable pre-configured top-level testbench which is a fast verification skipping programming phase +# - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts +write_preconfigured_fabric_wrapper --embed_bitstream iverilog --file ./SRC ${OPENFPGA_VERILOG_TESTBENCH_OPTIONS} +write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} ${OPENFPGA_VERILOG_TESTBENCH_OPTIONS} + +# Write the SDC files for PnR backend +# - Turn on every options here +# FIXME: Not supported yet. +#write_pnr_sdc --file ./SDC + +# Write SDC to disable timing for configure ports +write_sdc_disable_timing_configure_ports --file ./SDC/disable_configure_ports.sdc + +# Write the SDC to run timing analysis for a mapped FPGA fabric +write_analysis_sdc --file ./SDC_analysis + +# Finish and exit OpenFPGA +exit + +# Note : +# To run verification at the end of the flow maintain source in ./SRC directory diff --git a/openfpga_flow/regression_test_scripts/basic_reg_test.sh b/openfpga_flow/regression_test_scripts/basic_reg_test.sh index ed9877c80..f88ceccc0 100755 --- a/openfpga_flow/regression_test_scripts/basic_reg_test.sh +++ b/openfpga_flow/regression_test_scripts/basic_reg_test.sh @@ -186,6 +186,10 @@ run-task basic_tests/tile_organization/homo_fabric_tile_adder_chain $@ run-task basic_tests/tile_organization/homo_fabric_tile_clkntwk $@ run-task basic_tests/tile_organization/hetero_fabric_tile $@ +echo -e "Testing group config block"; +run-task basic_tests/group_config_block/group_config_block_homo_full_testbench $@ +run-task basic_tests/group_config_block/group_config_block_homo_fabric_tile $@ + echo -e "Testing global port definition from tiles"; run-task basic_tests/global_tile_ports/global_tile_clock $@ run-task basic_tests/global_tile_ports/global_tile_reset $@ diff --git a/openfpga_flow/tasks/basic_tests/group_config_block/group_config_block_hetero_fabric_tile/config/task.conf b/openfpga_flow/tasks/basic_tests/group_config_block/group_config_block_hetero_fabric_tile/config/task.conf new file mode 100644 index 000000000..c8f54dda0 --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/group_config_block/group_config_block_hetero_fabric_tile/config/task.conf @@ -0,0 +1,55 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# Configuration file for running experiments +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# timeout_each_job : FPGA Task script splits fpga flow into multiple jobs +# Each job execute fpga_flow script on combination of architecture & benchmark +# timeout_each_job is timeout for each job +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +[GENERAL] +run_engine=openfpga_shell +power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml +power_analysis = false +spice_output=false +verilog_output=true +timeout_each_job = 20*60 +fpga_flow=yosys_vpr + +[OpenFPGA_SHELL] +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/group_config_block_preconfig_testbench_example_script.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_frac_N8_reset_softadder_register_scan_chain_dsp8_caravel_io_skywater130nm_fdhd_cc_openfpga.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/fixed_sim_openfpga.xml +openfpga_vpr_extra_options=--constant_net_method route --skip_sync_clustering_and_routing_results on +openfpga_pb_pin_fixup_command = pb_pin_fixup --verbose +openfpga_vpr_device=3x2 +openfpga_vpr_route_chan_width=60 +openfpga_group_tile_config_option=--group_tile ${PATH:TASK_DIR}/config/tile_config.xml +openfpga_verilog_testbench_options= +openfpga_add_fpga_core_module= + +[ARCHITECTURES] +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_frac_N8_tileable_reset_softadder_register_scan_chain_dsp8_nonLR_caravel_io_skywater130nm.xml + +[BENCHMARKS] +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/mac/mac_2/mac_2.v +bench1=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/mac/mac_4/mac_4.v +bench2=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/mac/mac_6/mac_6.v +bench3=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/mac/mac_8/mac_8.v + +[SYNTHESIS_PARAM] +# Yosys script parameters +bench_yosys_cell_sim_verilog_common=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k4_frac_N8_tileable_reset_softadder_register_scan_chain_dsp8_nonLR_caravel_io_skywater130nm_cell_sim.v +bench_yosys_dsp_map_verilog_common=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k4_frac_N8_tileable_reset_softadder_register_scan_chain_dsp8_nonLR_caravel_io_skywater130nm_dsp_map.v +bench_yosys_dsp_map_parameters_common=-D DSP_A_MAXWIDTH=8 -D DSP_B_MAXWIDTH=8 -D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 -D DSP_NAME=mult_8x8 +bench_read_verilog_options_common = -nolatches +bench_yosys_common=${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_yosys_vpr_dsp_flow.ys +bench_yosys_rewrite_common=${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_yosys_vpr_flow_with_rewrite.ys;${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_rewrite_flow.ys + +bench0_top = mac_2 +bench1_top = mac_4 +bench2_top = mac_6 +bench3_top = mac_8 + +[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] +end_flow_with_test= +vpr_fpga_verilog_formal_verification_top_netlist= diff --git a/openfpga_flow/tasks/basic_tests/group_config_block/group_config_block_hetero_fabric_tile/config/tile_config.xml b/openfpga_flow/tasks/basic_tests/group_config_block/group_config_block_hetero_fabric_tile/config/tile_config.xml new file mode 100644 index 000000000..1a1f3f6e8 --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/group_config_block/group_config_block_hetero_fabric_tile/config/tile_config.xml @@ -0,0 +1 @@ + diff --git a/openfpga_flow/tasks/basic_tests/group_config_block/group_config_block_homo_fabric_tile/config/task.conf b/openfpga_flow/tasks/basic_tests/group_config_block/group_config_block_homo_fabric_tile/config/task.conf new file mode 100644 index 000000000..283c7b751 --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/group_config_block/group_config_block_homo_fabric_tile/config/task.conf @@ -0,0 +1,36 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# Configuration file for running experiments +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# timeout_each_job : FPGA Task script splits fpga flow into multiple jobs +# Each job execute fpga_flow script on combination of architecture & benchmark +# timeout_each_job is timeout for each job +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +[GENERAL] +run_engine=openfpga_shell +power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml +power_analysis = true +spice_output=false +verilog_output=true +timeout_each_job = 20*60 +fpga_flow=yosys_vpr + +[OpenFPGA_SHELL] +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/group_config_block_full_testbench_example_script.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_cc_openfpga.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_group_tile_config_option=--group_tile ${PATH:TASK_DIR}/config/tile_config.xml +openfpga_add_fpga_core_module= + +[ARCHITECTURES] +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_TileOrgzTl_40nm.xml + +[BENCHMARKS] +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/or2/or2.v + +[SYNTHESIS_PARAM] +bench_read_verilog_options_common = -nolatches +bench0_top = or2 + +[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] +end_flow_with_test= diff --git a/openfpga_flow/tasks/basic_tests/group_config_block/group_config_block_homo_fabric_tile/config/tile_config.xml b/openfpga_flow/tasks/basic_tests/group_config_block/group_config_block_homo_fabric_tile/config/tile_config.xml new file mode 100644 index 000000000..1a1f3f6e8 --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/group_config_block/group_config_block_homo_fabric_tile/config/tile_config.xml @@ -0,0 +1 @@ + diff --git a/openfpga_flow/tasks/basic_tests/group_config_block/group_config_block_homo_fabric_tile_core_wrapper/config/task.conf b/openfpga_flow/tasks/basic_tests/group_config_block/group_config_block_homo_fabric_tile_core_wrapper/config/task.conf new file mode 100644 index 000000000..81af76bfa --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/group_config_block/group_config_block_homo_fabric_tile_core_wrapper/config/task.conf @@ -0,0 +1,36 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# Configuration file for running experiments +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# timeout_each_job : FPGA Task script splits fpga flow into multiple jobs +# Each job execute fpga_flow script on combination of architecture & benchmark +# timeout_each_job is timeout for each job +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +[GENERAL] +run_engine=openfpga_shell +power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml +power_analysis = true +spice_output=false +verilog_output=true +timeout_each_job = 20*60 +fpga_flow=yosys_vpr + +[OpenFPGA_SHELL] +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/group_config_block_full_testbench_example_script.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_cc_openfpga.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_group_tile_config_option=--group_tile ${PATH:TASK_DIR}/config/tile_config.xml +openfpga_add_fpga_core_module=add_fpga_core_to_fabric --instance_name fpga_core_inst + +[ARCHITECTURES] +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_TileOrgzTl_40nm.xml + +[BENCHMARKS] +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/or2/or2.v + +[SYNTHESIS_PARAM] +bench_read_verilog_options_common = -nolatches +bench0_top = or2 + +[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] +end_flow_with_test= diff --git a/openfpga_flow/tasks/basic_tests/group_config_block/group_config_block_homo_fabric_tile_core_wrapper/config/tile_config.xml b/openfpga_flow/tasks/basic_tests/group_config_block/group_config_block_homo_fabric_tile_core_wrapper/config/tile_config.xml new file mode 100644 index 000000000..1a1f3f6e8 --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/group_config_block/group_config_block_homo_fabric_tile_core_wrapper/config/tile_config.xml @@ -0,0 +1 @@ + diff --git a/openfpga_flow/tasks/basic_tests/group_config_block/group_config_block_homo_full_testbench/config/task.conf b/openfpga_flow/tasks/basic_tests/group_config_block/group_config_block_homo_full_testbench/config/task.conf new file mode 100644 index 000000000..30732a74d --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/group_config_block/group_config_block_homo_full_testbench/config/task.conf @@ -0,0 +1,36 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# Configuration file for running experiments +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# timeout_each_job : FPGA Task script splits fpga flow into multiple jobs +# Each job execute fpga_flow script on combination of architecture & benchmark +# timeout_each_job is timeout for each job +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +[GENERAL] +run_engine=openfpga_shell +power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml +power_analysis = true +spice_output=false +verilog_output=true +timeout_each_job = 20*60 +fpga_flow=yosys_vpr + +[OpenFPGA_SHELL] +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/group_config_block_full_testbench_example_script.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_cc_openfpga.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_group_tile_config_option= +openfpga_add_fpga_core_module= + +[ARCHITECTURES] +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_TileOrgzTl_40nm.xml + +[BENCHMARKS] +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/or2/or2.v + +[SYNTHESIS_PARAM] +bench_read_verilog_options_common = -nolatches +bench0_top = or2 + +[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] +end_flow_with_test=