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