diff --git a/VERSION.md b/VERSION.md
index 3612f61d0..131773157 100644
--- a/VERSION.md
+++ b/VERSION.md
@@ -1 +1 @@
-1.2.1979
+1.2.1986
diff --git a/docs/source/manual/file_formats/fabric_pin_physical_location_file.rst b/docs/source/manual/file_formats/fabric_pin_physical_location_file.rst
new file mode 100644
index 000000000..ee24916e7
--- /dev/null
+++ b/docs/source/manual/file_formats/fabric_pin_physical_location_file.rst
@@ -0,0 +1,109 @@
+.. _file_format_fabric_pin_physical_location_file:
+
+Fabric Pin Physical Location File (.xml)
+----------------------------------------
+
+This file is generated by command :ref:`openfpga_setup_commands_write_fabric_pin_physical_location`
+
+
+The fabric pin physical location file aims to show
+
+- Pin names of each module in an eFPGA fabric
+- Preferred physical side of each pin on its module
+
+This file is created for pin guidelines during physical design steps
+
+An example of the file is shown as follows.
+
+.. code-block:: xml
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+.. option:: name=""
+
+ The module name in FPGA fabric, which should be a valid module defined in output Verilog netlist.
+
+ .. note:: You should be find the exact module in the FPGA fabric if you output the Verilog netlists.
+
+.. option:: pin=""
+
+ The name of the pin in FPGA fabric. Note that all the bus port will be flatten in this file.
+
+ .. note:: You should be find the exact pin in the module if you output the Verilog netlists.
+
+.. option:: side=""
+
+ The physical side of the pin should appear on the perimeter of the module.
diff --git a/docs/source/manual/file_formats/index.rst b/docs/source/manual/file_formats/index.rst
index 6ec94c3b9..1038c6b81 100644
--- a/docs/source/manual/file_formats/index.rst
+++ b/docs/source/manual/file_formats/index.rst
@@ -41,3 +41,5 @@ OpenFPGA widely uses XML format for interchangeable files
module_naming_file
tile_config_file
+
+ fabric_pin_physical_location_file
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 9ea4b2145..9374971a4 100644
--- a/docs/source/manual/openfpga_shell/openfpga_commands/setup_commands.rst
+++ b/docs/source/manual/openfpga_shell/openfpga_commands/setup_commands.rst
@@ -392,7 +392,7 @@ write_fabric_io_info
.. option:: --no_time_stamp
- Do not print time stamp in bitstream files
+ Do not print time stamp in output files
.. option:: --verbose
@@ -433,7 +433,7 @@ pcf2place
.. option:: --no_time_stamp
- Do not print time stamp in bitstream files
+ Do not print time stamp in output files
.. option:: --verbose
@@ -467,7 +467,34 @@ write_module_naming_rules
.. option:: --no_time_stamp
- Do not print time stamp in bitstream files
+ Do not print time stamp in output files
+
+ .. option:: --verbose
+
+ Show verbose log
+
+.. _openfpga_setup_commands_write_fabric_pin_physical_location:
+
+write_fabric_pin_physical_location
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ Output the physical location of each pin for each module of an FPGA fabric to a given file
+
+ .. option:: --file
+
+ Specify the file path to be written to. See details in :ref:`file_format_fabric_pin_physical_location_file`.
+
+ .. option:: --module
+
+ Specify the name of modules to be considered. Support regular expression, e.g., ``tile*``. When provided, only pins of selected modules will be outputted. By default, a wildcard ``*`` is considered, which means all the modules will be considered.
+
+ .. option:: --show_invalid_side
+
+ Show sides for each pin, even these pin does not have a specific valid side. This is mainly used for debugging.
+
+ .. option:: --no_time_stamp
+
+ Do not print time stamp in output files
.. option:: --verbose
diff --git a/openfpga/src/base/openfpga_build_fabric_template.h b/openfpga/src/base/openfpga_build_fabric_template.h
index 63e623398..830e730d4 100644
--- a/openfpga/src/base/openfpga_build_fabric_template.h
+++ b/openfpga/src/base/openfpga_build_fabric_template.h
@@ -23,6 +23,7 @@
#include "rename_modules.h"
#include "vtr_log.h"
#include "vtr_time.h"
+#include "write_xml_fabric_pin_physical_location.h"
#include "write_xml_module_name_map.h"
/* begin namespace openfpga */
@@ -419,6 +420,41 @@ int write_module_naming_rules_template(const T& openfpga_ctx,
cmd_context.option_enable(cmd, opt_verbose));
}
+/********************************************************************
+ * Write fabric pin physical location to a file
+ *******************************************************************/
+template
+int write_fabric_pin_physical_location_template(
+ const T& openfpga_ctx, const Command& cmd,
+ const CommandContext& cmd_context) {
+ CommandOptionId opt_verbose = cmd.option("verbose");
+ CommandOptionId opt_no_time_stamp = cmd.option("no_time_stamp");
+ CommandOptionId opt_show_invalid_side = cmd.option("show_invalid_side");
+
+ /* Check the option '--file' is enabled or not
+ * Actually, it must be enabled as the shell interface will check
+ * before reaching this fuction
+ */
+ CommandOptionId opt_file = cmd.option("file");
+ VTR_ASSERT(true == cmd_context.option_enable(cmd, opt_file));
+ VTR_ASSERT(false == cmd_context.option_value(cmd, opt_file).empty());
+
+ std::string file_name = cmd_context.option_value(cmd, opt_file);
+
+ std::string module_name("*"); /* Use a wildcard for everything */
+ CommandOptionId opt_module = cmd.option("module");
+ if (true == cmd_context.option_enable(cmd, opt_module)) {
+ module_name = cmd_context.option_value(cmd, opt_module);
+ }
+
+ /* Write hierarchy to a file */
+ return write_xml_fabric_pin_physical_location(
+ file_name.c_str(), module_name, openfpga_ctx.module_graph(),
+ cmd_context.option_enable(cmd, opt_show_invalid_side),
+ !cmd_context.option_enable(cmd, opt_no_time_stamp),
+ cmd_context.option_enable(cmd, opt_verbose));
+}
+
} /* end namespace openfpga */
#endif
diff --git a/openfpga/src/base/openfpga_naming.cpp b/openfpga/src/base/openfpga_naming.cpp
index b80c3ba36..c76273935 100644
--- a/openfpga/src/base/openfpga_naming.cpp
+++ b/openfpga/src/base/openfpga_naming.cpp
@@ -413,6 +413,35 @@ std::string generate_sb_module_track_port_name(const t_rr_type& chan_type,
return port_name;
}
+/*********************************************************************
+ * Get the physical side for a routing track in a Connection Block module
+ * Upper_location: specify if an upper/lower prefix to be added.
+ * The location indicates where the bus port should be
+ * placed on the perimeter of the connection block
+ * - For X-directional CB:
+ * - upper is the left side
+ * - lower is the right side
+ * - For Y-directional CB:
+ * - upper is the bottom side
+ * - lower is the top side
+ *********************************************************************/
+e_side get_cb_module_track_port_side(const t_rr_type& chan_type,
+ const bool& upper_location) {
+ /* Channel must be either CHANX or CHANY */
+ VTR_ASSERT((CHANX == chan_type) || (CHANY == chan_type));
+
+ /* Create a map between chan_type and module_prefix */
+ std::map> port_side_map;
+ /* TODO: use a constexpr string to replace the fixed name? */
+ /* IMPORTANT: This part must be consistent with the mapping in the
+ * generate_cb_module_track_port_name() !!! */
+ port_side_map[CHANX][true] = LEFT;
+ port_side_map[CHANX][false] = RIGHT;
+ port_side_map[CHANY][true] = BOTTOM;
+ port_side_map[CHANY][false] = TOP;
+ return port_side_map[chan_type][upper_location];
+}
+
/*********************************************************************
* Generate the port name for a routing track in a Connection Block module
* This function is created to ease the PnR for each unique routing module
diff --git a/openfpga/src/base/openfpga_naming.h b/openfpga/src/base/openfpga_naming.h
index 378a2836a..bbad6e510 100644
--- a/openfpga/src/base/openfpga_naming.h
+++ b/openfpga/src/base/openfpga_naming.h
@@ -97,6 +97,9 @@ std::string generate_sb_module_track_port_name(const t_rr_type& chan_type,
const e_side& module_side,
const PORTS& port_direction);
+e_side get_cb_module_track_port_side(const t_rr_type& chan_type,
+ const bool& upper_location);
+
std::string generate_cb_module_track_port_name(const t_rr_type& chan_type,
const PORTS& port_direction,
const bool& upper_location);
diff --git a/openfpga/src/base/openfpga_setup_command_template.h b/openfpga/src/base/openfpga_setup_command_template.h
index 96d8e3e3b..bbd3ae8f6 100644
--- a/openfpga/src/base/openfpga_setup_command_template.h
+++ b/openfpga/src/base/openfpga_setup_command_template.h
@@ -858,6 +858,55 @@ ShellCommandId add_write_module_naming_rules_command_template(
return shell_cmd_id;
}
+/********************************************************************
+ * - Add a command to Shell environment: write_pin_physical_location
+ * - Add associated options
+ * - Add command dependency
+ *******************************************************************/
+template
+ShellCommandId add_write_fabric_pin_physical_location_command_template(
+ openfpga::Shell& shell, const ShellCommandClassId& cmd_class_id,
+ const std::vector& dependent_cmds, const bool& hidden) {
+ Command shell_cmd("write_fabric_pin_physical_location");
+ /* Add an option '--file' in short '-f'*/
+ CommandOptionId opt_file = shell_cmd.add_option(
+ "file", true,
+ "file path to the XML file that contains pin physical location");
+ shell_cmd.set_option_short_name(opt_file, "f");
+ shell_cmd.set_option_require_value(opt_file, openfpga::OPT_STRING);
+
+ /* Add an option '--module'*/
+ CommandOptionId opt_module = shell_cmd.add_option(
+ "module", false,
+ "specify the module whose pin physical location should be outputted");
+ shell_cmd.set_option_require_value(opt_module, openfpga::OPT_STRING);
+
+ /* Add an option '--no_time_stamp' */
+ shell_cmd.add_option("no_time_stamp", false,
+ "Do not print time stamp in output files");
+
+ shell_cmd.add_option(
+ "show_invalid_side", false,
+ "Include pins with invalid sides in output files. Recommended for "
+ "debugging as the output file may include a lot of useless information");
+
+ shell_cmd.add_option("verbose", false, "Show verbose outputs");
+
+ /* Add command to the Shell */
+ ShellCommandId shell_cmd_id = shell.add_command(
+ shell_cmd,
+ "Output the pin physical location of an FPGA fabric to a given file",
+ hidden);
+ shell.set_command_class(shell_cmd_id, cmd_class_id);
+ shell.set_command_const_execute_function(
+ shell_cmd_id, write_fabric_pin_physical_location_template);
+
+ /* Add command dependency to the Shell */
+ shell.set_command_dependency(shell_cmd_id, dependent_cmds);
+
+ return shell_cmd_id;
+}
+
template
void add_setup_command_templates(openfpga::Shell& shell,
const bool& hidden = false) {
@@ -1098,6 +1147,17 @@ void add_setup_command_templates(openfpga::Shell& shell,
add_write_module_naming_rules_command_template(
shell, openfpga_setup_cmd_class, cmd_dependency_write_module_naming_rules,
hidden);
+
+ /********************************
+ * Command 'write_fabric_pin_physical_location'
+ */
+ /* The command should NOT be executed before 'build_fabric' */
+ std::vector cmd_dependency_write_fabric_pin_physical_location;
+ cmd_dependency_write_fabric_pin_physical_location.push_back(
+ build_fabric_cmd_id);
+ add_write_fabric_pin_physical_location_command_template(
+ shell, openfpga_setup_cmd_class,
+ cmd_dependency_write_fabric_pin_physical_location, hidden);
}
} /* end namespace openfpga */
diff --git a/openfpga/src/fabric/build_grid_module_duplicated_pins.cpp b/openfpga/src/fabric/build_grid_module_duplicated_pins.cpp
index cae215259..32304bdc7 100644
--- a/openfpga/src/fabric/build_grid_module_duplicated_pins.cpp
+++ b/openfpga/src/fabric/build_grid_module_duplicated_pins.cpp
@@ -123,8 +123,10 @@ void add_grid_module_duplicated_pb_type_ports(
}
BasicPort grid_port(port_name, 0, 0);
/* Add the port to the module */
- module_manager.add_port(grid_module, grid_port,
- pin_type2type_map[pin_class_type]);
+ ModulePortId grid_port_id = module_manager.add_port(
+ grid_module, grid_port, pin_type2type_map[pin_class_type]);
+ /* Set port side */
+ module_manager.set_port_side(grid_module, grid_port_id, side);
} else {
/* For each DRIVER pin, we create two copies.
* One with a postfix of upper, indicating it is located on the
@@ -136,15 +138,19 @@ void add_grid_module_duplicated_pb_type_ports(
iwidth, iheight, subtile_index, side, pin_info, true);
BasicPort grid_upper_port(upper_port_name, 0, 0);
/* Add the port to the module */
- module_manager.add_port(grid_module, grid_upper_port,
- pin_type2type_map[pin_class_type]);
+ ModulePortId grid_upper_port_id = module_manager.add_port(
+ grid_module, grid_upper_port, pin_type2type_map[pin_class_type]);
+ /* Set port side */
+ module_manager.set_port_side(grid_module, grid_upper_port_id, side);
std::string lower_port_name = generate_grid_duplicated_port_name(
iwidth, iheight, subtile_index, side, pin_info, false);
BasicPort grid_lower_port(lower_port_name, 0, 0);
/* Add the port to the module */
- module_manager.add_port(grid_module, grid_lower_port,
- pin_type2type_map[pin_class_type]);
+ ModulePortId grid_lower_port_id = module_manager.add_port(
+ grid_module, grid_lower_port, pin_type2type_map[pin_class_type]);
+ /* Set port side */
+ module_manager.set_port_side(grid_module, grid_lower_port_id, side);
}
}
}
diff --git a/openfpga/src/fabric/build_grid_modules.cpp b/openfpga/src/fabric/build_grid_modules.cpp
index 3883d430b..eaa24246b 100644
--- a/openfpga/src/fabric/build_grid_modules.cpp
+++ b/openfpga/src/fabric/build_grid_modules.cpp
@@ -103,8 +103,10 @@ static void add_grid_module_pb_type_ports(
}
BasicPort grid_port(port_name, 0, 0);
/* Add the port to the module */
- module_manager.add_port(grid_module, grid_port,
- pin_type2type_map[pin_class_type]);
+ ModulePortId grid_port_id = module_manager.add_port(
+ grid_module, grid_port, pin_type2type_map[pin_class_type]);
+ /* Set port side */
+ module_manager.set_port_side(grid_module, grid_port_id, side);
}
}
}
diff --git a/openfpga/src/fabric/build_routing_modules.cpp b/openfpga/src/fabric/build_routing_modules.cpp
index d552a611c..bed03d5fd 100644
--- a/openfpga/src/fabric/build_routing_modules.cpp
+++ b/openfpga/src/fabric/build_routing_modules.cpp
@@ -435,6 +435,9 @@ static void build_switch_block_module(
BasicPort chan_input_port(chan_input_port_name, chan_input_port_size);
ModulePortId chan_input_port_id = module_manager.add_port(
sb_module, chan_input_port, ModuleManager::MODULE_INPUT_PORT);
+ /* Add side to the port */
+ module_manager.set_port_side(sb_module, chan_input_port_id,
+ side_manager.get_side());
/* Cache the input net */
for (const size_t& pin : chan_input_port.pins()) {
@@ -446,8 +449,11 @@ static void build_switch_block_module(
std::string chan_output_port_name = generate_sb_module_track_port_name(
chan_type, side_manager.get_side(), OUT_PORT);
BasicPort chan_output_port(chan_output_port_name, chan_output_port_size);
- module_manager.add_port(sb_module, chan_output_port,
- ModuleManager::MODULE_OUTPUT_PORT);
+ ModulePortId chan_output_port_id = module_manager.add_port(
+ sb_module, chan_output_port, ModuleManager::MODULE_OUTPUT_PORT);
+ /* Add side to the port */
+ module_manager.set_port_side(sb_module, chan_output_port_id,
+ side_manager.get_side());
}
/* Dump OPINs of adjacent CLBs */
@@ -468,6 +474,9 @@ static void build_switch_block_module(
/* Grid outputs are inputs of switch blocks */
ModulePortId input_port_id = module_manager.add_port(
sb_module, module_port, ModuleManager::MODULE_INPUT_PORT);
+ /* Add side to the port */
+ module_manager.set_port_side(sb_module, input_port_id,
+ side_manager.get_side());
/* Cache the input net */
ModuleNetId net = create_module_source_pin_net(
@@ -925,6 +934,9 @@ static void build_connection_block_module(
rr_gsb.get_cb_chan_width(cb_type) / 2);
ModulePortId chan_upper_input_port_id = module_manager.add_port(
cb_module, chan_upper_input_port, ModuleManager::MODULE_INPUT_PORT);
+ /* Add side to the port */
+ module_manager.set_port_side(cb_module, chan_upper_input_port_id,
+ get_cb_module_track_port_side(cb_type, true));
/* Lower input port: W/2 == 1 tracks */
std::string chan_lower_input_port_name =
@@ -933,6 +945,9 @@ static void build_connection_block_module(
rr_gsb.get_cb_chan_width(cb_type) / 2);
ModulePortId chan_lower_input_port_id = module_manager.add_port(
cb_module, chan_lower_input_port, ModuleManager::MODULE_INPUT_PORT);
+ /* Add side to the port */
+ module_manager.set_port_side(cb_module, chan_lower_input_port_id,
+ get_cb_module_track_port_side(cb_type, false));
/* Upper output port: W/2 == 0 tracks */
std::string chan_upper_output_port_name =
@@ -941,6 +956,9 @@ static void build_connection_block_module(
rr_gsb.get_cb_chan_width(cb_type) / 2);
ModulePortId chan_upper_output_port_id = module_manager.add_port(
cb_module, chan_upper_output_port, ModuleManager::MODULE_OUTPUT_PORT);
+ /* Add side to the port */
+ module_manager.set_port_side(cb_module, chan_upper_output_port_id,
+ get_cb_module_track_port_side(cb_type, true));
/* Lower output port: W/2 == 1 tracks */
std::string chan_lower_output_port_name =
@@ -949,6 +967,9 @@ static void build_connection_block_module(
rr_gsb.get_cb_chan_width(cb_type) / 2);
ModulePortId chan_lower_output_port_id = module_manager.add_port(
cb_module, chan_lower_output_port, ModuleManager::MODULE_OUTPUT_PORT);
+ /* Add side to the port */
+ module_manager.set_port_side(cb_module, chan_lower_output_port_id,
+ get_cb_module_track_port_side(cb_type, false));
/* Add the input pins of grids, which are output ports of the connection block
*/
@@ -965,8 +986,10 @@ static void build_connection_block_module(
BasicPort module_port(port_name,
1); /* Every grid output has a port size of 1 */
/* Grid outputs are inputs of switch blocks */
- module_manager.add_port(cb_module, module_port,
- ModuleManager::MODULE_OUTPUT_PORT);
+ ModulePortId module_port_id = module_manager.add_port(
+ cb_module, module_port, ModuleManager::MODULE_OUTPUT_PORT);
+ /* Add side to the port */
+ module_manager.set_port_side(cb_module, module_port_id, cb_ipin_side);
}
}
diff --git a/openfpga/src/fabric/build_tile_modules.cpp b/openfpga/src/fabric/build_tile_modules.cpp
index caf82f075..277295868 100644
--- a/openfpga/src/fabric/build_tile_modules.cpp
+++ b/openfpga/src/fabric/build_tile_modules.cpp
@@ -211,6 +211,10 @@ static int build_tile_module_port_and_nets_between_sb_and_pb(
ModulePortId src_tile_port_id = module_manager.add_port(
tile_module, src_grid_port,
ModuleManager::e_module_port_type::MODULE_INPUT_PORT);
+ /* Set port side, inherit from the child module */
+ module_manager.set_port_side(
+ tile_module, src_tile_port_id,
+ module_manager.port_side(sink_sb_module, sink_sb_port_id));
VTR_LOGV(
verbose,
"Adding ports '%s' to tile as required by the switch block '%s'...\n",
@@ -442,6 +446,10 @@ static int build_tile_module_port_and_nets_between_cb_and_pb(
ModulePortId sink_tile_port_id = module_manager.add_port(
tile_module, src_cb_port,
ModuleManager::e_module_port_type::MODULE_OUTPUT_PORT);
+ /* Set port side, inherit from the child module */
+ module_manager.set_port_side(
+ tile_module, sink_tile_port_id,
+ module_manager.port_side(src_cb_module, src_cb_port_id));
VTR_LOGV(verbose,
"Adding ports '%s' to tile as required by the connection "
"block '%s'...\n",
@@ -739,6 +747,10 @@ static int build_tile_module_port_and_nets_between_sb_and_cb(
ModulePortId tile_chan_output_port_id = module_manager.add_port(
tile_module, chan_output_port,
ModuleManager::e_module_port_type::MODULE_OUTPUT_PORT);
+ /* Set port side, inherit from the child module */
+ module_manager.set_port_side(
+ tile_module, tile_chan_output_port_id,
+ module_manager.port_side(sb_module_id, sb_chan_output_port_id));
VTR_LOGV(
verbose,
"Adding ports '%s' to tile as required by the switch block '%s'...\n",
@@ -816,6 +828,10 @@ static int build_tile_module_one_port_from_cb(
* avoid naming conflicts */
ModulePortId tile_module_port_id =
module_manager.add_port(tile_module, tile_chan_port, chan_port_type);
+ /* Set port side, inherit from the child module */
+ module_manager.set_port_side(
+ tile_module, tile_module_port_id,
+ module_manager.port_side(cb_module, chan_port_id));
if (!frame_view) {
for (size_t pin_id = 0; pin_id < chan_port.pins().size(); ++pin_id) {
@@ -1161,6 +1177,10 @@ static int build_tile_port_and_nets_from_pb(
ModulePortId tile_module_port_id = module_manager.add_port(
tile_module, pb_port,
ModuleManager::e_module_port_type::MODULE_OUTPUT_PORT);
+ /* Set port side, inherit from the child module */
+ module_manager.set_port_side(
+ tile_module, tile_module_port_id,
+ module_manager.port_side(pb_module, pb_module_port_id));
if (!frame_view) {
ModuleNetId net = create_module_source_pin_net(
module_manager, tile_module, pb_module, pb_instance,
diff --git a/openfpga/src/fabric/fabric_pin_physical_location_xml_constants.h b/openfpga/src/fabric/fabric_pin_physical_location_xml_constants.h
new file mode 100644
index 000000000..70ff67a6d
--- /dev/null
+++ b/openfpga/src/fabric/fabric_pin_physical_location_xml_constants.h
@@ -0,0 +1,13 @@
+#ifndef FABRIC_PIN_PHYSICAL_LOCATION_XML_CONSTANTS_H
+#define FABRIC_PIN_PHYSICAL_LOCATION_XML_CONSTANTS_H
+
+/* Constants required by XML parser */
+
+constexpr const char* XML_PINLOC_ROOT_NAME = "pin_location";
+constexpr const char* XML_MODULE_NODE_NAME = "module";
+constexpr const char* XML_MODULE_ATTRIBUTE_NAME = "name";
+constexpr const char* XML_MODULE_PINLOC_NODE_NAME = "loc";
+constexpr const char* XML_MODULE_PINLOC_ATTRIBUTE_PIN = "pin";
+constexpr const char* XML_MODULE_PINLOC_ATTRIBUTE_SIDE = "side";
+
+#endif
diff --git a/openfpga/src/fabric/module_manager.cpp b/openfpga/src/fabric/module_manager.cpp
index 48d03095d..178a3b33f 100644
--- a/openfpga/src/fabric/module_manager.cpp
+++ b/openfpga/src/fabric/module_manager.cpp
@@ -304,6 +304,12 @@ std::vector ModuleManager::module_ports_by_type(
return ports;
}
+e_side ModuleManager::port_side(const ModuleId& module_id,
+ const ModulePortId& port_id) const {
+ VTR_ASSERT(valid_module_port_id(module_id, port_id));
+ return port_sides_[module_id][port_id];
+}
+
/* Find a list of port ids of a module by a given types */
std::vector ModuleManager::module_port_ids_by_type(
const ModuleId& module_id, const enum e_module_port_type& port_type) const {
@@ -746,6 +752,7 @@ ModuleId ModuleManager::add_module(const std::string& name) {
port_is_wire_.emplace_back();
port_is_mappable_io_.emplace_back();
port_is_register_.emplace_back();
+ port_sides_.emplace_back();
port_preproc_flags_.emplace_back();
num_nets_.emplace_back(0);
@@ -789,6 +796,8 @@ ModulePortId ModuleManager::add_port(const ModuleId& module,
port_ids_[module].push_back(port);
ports_[module].push_back(port_info);
port_types_[module].push_back(port_type);
+ /* Deposit invalid value for each side */
+ port_sides_[module].push_back(NUM_SIDES);
port_is_wire_[module].push_back(false);
port_is_mappable_io_[module].push_back(false);
port_is_register_[module].push_back(false);
@@ -893,6 +902,15 @@ void ModuleManager::set_port_preproc_flag(const ModuleId& module,
port_preproc_flags_[module][port] = preproc_flag;
}
+/* Set the side for a pin of a port port */
+void ModuleManager::set_port_side(const ModuleId& module,
+ const ModulePortId& port,
+ const e_side& pin_side) {
+ /* Must find something, otherwise drop an error */
+ VTR_ASSERT(valid_module_port_id(module, port));
+ port_sides_[module][port] = pin_side;
+}
+
/* Add a child module to a parent module */
void ModuleManager::add_child_module(const ModuleId& parent_module,
const ModuleId& child_module,
diff --git a/openfpga/src/fabric/module_manager.h b/openfpga/src/fabric/module_manager.h
index 235719cbc..6f9f2e267 100644
--- a/openfpga/src/fabric/module_manager.h
+++ b/openfpga/src/fabric/module_manager.h
@@ -9,6 +9,7 @@
#include "module_manager_fwd.h"
#include "openfpga_port.h"
+#include "physical_types.h"
#include "vtr_geometry.h"
#include "vtr_vector.h"
@@ -273,6 +274,10 @@ class ModuleManager {
/* Find the type of a port */
ModuleManager::e_module_port_type port_type(const ModuleId& module,
const ModulePortId& port) const;
+ /* Get the physical side of a port. Note that not every pin has a valid side.
+ * An invalid value NUM_SIDES will be returned when the pin does not has a
+ * specific physical location */
+ e_side port_side(const ModuleId& module, const ModulePortId& port) const;
/* Find if a port is a wire connection */
bool port_is_wire(const ModuleId& module, const ModulePortId& port) const;
/* Find if a port is mappable to an I/O from users' implementations */
@@ -369,6 +374,11 @@ class ModuleManager {
/* Set the preprocessing flag for a port */
void set_port_preproc_flag(const ModuleId& module, const ModulePortId& port,
const std::string& preproc_flag);
+ /* Set side to a given pin of a module port. Note that the pin id must be a
+ * valid one. Otherwise, abort and error out. The valid pin range can be get
+ * from module_port().pins() */
+ void set_port_side(const ModuleId& module, const ModulePortId& port,
+ const e_side& pin_side);
/** @brief Add a child module to a parent module.
* By default, it considers the child module as an I/O child, and update the
* children list of I/O modules inside It not needed, just turn it off. Then
@@ -626,6 +636,8 @@ class ModuleManager {
ports_; /* List of ports for each Module */
vtr::vector>
port_types_; /* Type of ports */
+ vtr::vector>
+ port_sides_; /* Type of ports */
vtr::vector>
port_is_mappable_io_; /* If the port is mappable to an I/O for user's
implementations */
diff --git a/openfpga/src/fabric/write_xml_fabric_pin_physical_location.cpp b/openfpga/src/fabric/write_xml_fabric_pin_physical_location.cpp
new file mode 100644
index 000000000..959d7c252
--- /dev/null
+++ b/openfpga/src/fabric/write_xml_fabric_pin_physical_location.cpp
@@ -0,0 +1,192 @@
+/***************************************************************************************
+ * Output internal structure of module graph to XML format
+ ***************************************************************************************/
+/* Headers from system goes first */
+#include
+#include
+#include
+#include
+#include
+
+/* Headers from vtrutil library */
+#include "vtr_assert.h"
+#include "vtr_log.h"
+#include "vtr_time.h"
+
+/* Headers from openfpgautil library */
+#include "command_exit_codes.h"
+#include "openfpga_digest.h"
+#include "openfpga_side_manager.h"
+
+/* Headers from arch openfpga library */
+#include "fabric_pin_physical_location_xml_constants.h"
+#include "write_xml_fabric_pin_physical_location.h"
+#include "write_xml_utils.h"
+
+/* begin namespace openfpga */
+namespace openfpga {
+
+/********************************************************************
+ * This function write header information to a pin location file
+ *******************************************************************/
+static void write_xml_fabric_pin_physical_location_file_head(
+ std::fstream& fp, const bool& include_time_stamp) {
+ valid_file_stream(fp);
+
+ fp << "" << std::endl;
+ fp << std::endl;
+}
+
+/********************************************************************
+ * This function write header information to a pin location file
+ *******************************************************************/
+static int write_xml_fabric_module_pin_phy_loc(
+ std::fstream& fp, const ModuleManager& module_manager,
+ const ModuleId& curr_module, const bool& show_invalid_side,
+ const bool& verbose) {
+ valid_file_stream(fp);
+
+ /* If show invalid side is off, we should check if there is any valid side. If
+ * there are not any, skip this module */
+ bool skip_curr_module = true;
+ for (ModulePortId curr_port_id : module_manager.module_ports(curr_module)) {
+ SideManager side_mgr(module_manager.port_side(curr_module, curr_port_id));
+ if (side_mgr.validate()) {
+ skip_curr_module = false;
+ break;
+ }
+ }
+
+ if (!show_invalid_side && skip_curr_module) {
+ VTR_LOGV(verbose, "Skip module '%s' as it contains no valid sides\n",
+ module_manager.module_name(curr_module).c_str());
+ return CMD_EXEC_SUCCESS;
+ }
+ /* Print a head */
+ write_tab_to_file(fp, 1);
+ fp << "<" << XML_MODULE_NODE_NAME;
+ write_xml_attribute(fp, XML_MODULE_ATTRIBUTE_NAME,
+ module_manager.module_name(curr_module).c_str());
+ fp << ">"
+ << "\n";
+
+ size_t cnt = 0;
+ for (ModulePortId curr_port_id : module_manager.module_ports(curr_module)) {
+ BasicPort curr_port = module_manager.module_port(curr_module, curr_port_id);
+ SideManager side_mgr(module_manager.port_side(curr_module, curr_port_id));
+ if (!side_mgr.validate() && !show_invalid_side) {
+ continue;
+ }
+ for (int curr_pin_id : curr_port.pins()) {
+ BasicPort curr_pin(curr_port.get_name(), curr_pin_id, curr_pin_id);
+ std::string curr_port_str = generate_xml_port_name(curr_pin);
+ write_tab_to_file(fp, 2);
+ fp << "<" << XML_MODULE_PINLOC_NODE_NAME;
+ write_xml_attribute(fp, XML_MODULE_PINLOC_ATTRIBUTE_PIN,
+ curr_port_str.c_str());
+ write_xml_attribute(fp, XML_MODULE_PINLOC_ATTRIBUTE_SIDE,
+ side_mgr.c_str());
+ fp << "/>";
+ fp << std::endl;
+ }
+ cnt++;
+ }
+ VTR_LOGV(verbose, "Output %lu ports with physical sides for module '%s'\n",
+ cnt, module_manager.module_name(curr_module).c_str());
+
+ /* Print a tail */
+ write_tab_to_file(fp, 1);
+ fp << "" << XML_MODULE_NODE_NAME;
+ fp << ">"
+ << "\n";
+
+ return CMD_EXEC_SUCCESS;
+}
+
+/********************************************************************
+ * Top-level function
+ *******************************************************************/
+int write_xml_fabric_pin_physical_location(const char* fname,
+ const std::string& module_name,
+ const ModuleManager& module_manager,
+ const bool& show_invalid_side,
+ const bool& include_time_stamp,
+ const bool& verbose) {
+ vtr::ScopedStartFinishTimer timer("Write fabric pin physical location");
+
+ /* Create a file handler */
+ std::fstream fp;
+ /* Open the file stream */
+ fp.open(std::string(fname), std::fstream::out | std::fstream::trunc);
+
+ /* Validate the file stream */
+ openfpga::check_file_stream(fname, fp);
+
+ write_xml_fabric_pin_physical_location_file_head(fp, include_time_stamp);
+
+ /* Write the root node */
+ fp << "<" << XML_PINLOC_ROOT_NAME;
+ fp << ">"
+ << "\n";
+
+ /* If module name is not specified, walk through all the modules and write
+ * physical pin location when any is specified */
+ short cnt = 0;
+ /* Use regular expression to capture the module whose name matches the pattern
+ */
+ for (ModuleId curr_module : module_manager.modules()) {
+ std::string curr_module_name = module_manager.module_name(curr_module);
+ std::string pattern = module_name;
+ std::regex star_replace("\\*");
+ std::regex questionmark_replace("\\?");
+ std::string wildcard_pattern =
+ std::regex_replace(std::regex_replace(pattern, star_replace, ".*"),
+ questionmark_replace, ".");
+ std::regex wildcard_regex(wildcard_pattern);
+ if (!std::regex_match(curr_module_name, wildcard_regex)) {
+ continue;
+ }
+ VTR_LOGV(verbose, "Outputted pin physical location of module '%s'.\n",
+ curr_module_name.c_str());
+ /* Write the pin physical location for this module */
+ int err_code = write_xml_fabric_module_pin_phy_loc(
+ fp, module_manager, curr_module, show_invalid_side, verbose);
+ if (err_code != CMD_EXEC_SUCCESS) {
+ return CMD_EXEC_FATAL_ERROR;
+ }
+ cnt++;
+ }
+
+ /* Finish writing the root node */
+ fp << "" << XML_PINLOC_ROOT_NAME << ">"
+ << "\n";
+
+ /* Close the file stream */
+ fp.close();
+
+ /* If there is no match, error out! */
+ if (cnt == 0) {
+ VTR_LOG_ERROR(
+ "Invalid regular expression for module name '%s' which does not match "
+ "any in current fabric!\n",
+ module_name.c_str());
+ return CMD_EXEC_FATAL_ERROR;
+ }
+
+ VTR_LOGV(verbose, "Outputted %lu modules with pin physical location.\n", cnt);
+
+ return CMD_EXEC_SUCCESS;
+}
+
+} /* end namespace openfpga */
diff --git a/openfpga/src/fabric/write_xml_fabric_pin_physical_location.h b/openfpga/src/fabric/write_xml_fabric_pin_physical_location.h
new file mode 100644
index 000000000..6dd0ef214
--- /dev/null
+++ b/openfpga/src/fabric/write_xml_fabric_pin_physical_location.h
@@ -0,0 +1,27 @@
+#ifndef WRITE_XML_FABRIC_PIN_PHYSICAL_LOCATION_H
+#define WRITE_XML_FABRIC_PIN_PHYSICAL_LOCATION_H
+
+/********************************************************************
+ * Include header files that are required by function declaration
+ *******************************************************************/
+#include
+
+#include "module_manager.h"
+
+/********************************************************************
+ * Function declaration
+ *******************************************************************/
+
+/* begin namespace openfpga */
+namespace openfpga {
+
+int write_xml_fabric_pin_physical_location(const char* fname,
+ const std::string& module_name,
+ const ModuleManager& module_manager,
+ const bool& show_invalid_side,
+ const bool& include_time_stamp,
+ const bool& verbose);
+
+} /* end namespace openfpga */
+
+#endif
diff --git a/openfpga_flow/openfpga_shell_scripts/group_tile_write_fabric_pin_phy_loc_preconfig_testbench_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/group_tile_write_fabric_pin_phy_loc_preconfig_testbench_example_script.openfpga
new file mode 100644
index 000000000..fe95685a5
--- /dev/null
+++ b/openfpga_flow/openfpga_shell_scripts/group_tile_write_fabric_pin_phy_loc_preconfig_testbench_example_script.openfpga
@@ -0,0 +1,79 @@
+# 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
+
+# Optionally pb pin fixup
+${OPENFPGA_PB_PIN_FIXUP_COMMAND}
+
+# 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_tile ${OPENFPGA_GROUP_TILE_CONFIG_FILE} #--verbose
+
+# Write fabric phyiscal pin location to file
+write_fabric_pin_physical_location --file ${OPENFPGA_FABRIC_PIN_PHY_LOC_FILE} ${OPENFPGA_FABRIC_PIN_PHY_LOC_MODULE} --verbose
+
+# 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/openfpga_shell_scripts/no_time_stamp_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/no_time_stamp_example_script.openfpga
index b9b0e4086..32b475aae 100644
--- a/openfpga_flow/openfpga_shell_scripts/no_time_stamp_example_script.openfpga
+++ b/openfpga_flow/openfpga_shell_scripts/no_time_stamp_example_script.openfpga
@@ -32,6 +32,7 @@ write_fabric_hierarchy --file ./fabric_hierarchy.txt
# Write the fabric I/O attributes to a file
# This is used by pin constraint files
write_fabric_io_info --file ${OPENFPGA_OUTPUT_DIR}/fabric_io_location.xml --verbose --no_time_stamp
+write_fabric_pin_physical_location --file ${OPENFPGA_OUTPUT_DIR}/fabric_pin_phy_loc.xml --verbose --no_time_stamp --module *
# Write gsb to XML
write_gsb_to_xml --file ${OPENFPGA_OUTPUT_DIR}/gsb_xml --verbose
diff --git a/openfpga_flow/regression_test_scripts/basic_reg_test.sh b/openfpga_flow/regression_test_scripts/basic_reg_test.sh
index fbe30d871..a268b0a6f 100755
--- a/openfpga_flow/regression_test_scripts/basic_reg_test.sh
+++ b/openfpga_flow/regression_test_scripts/basic_reg_test.sh
@@ -253,6 +253,12 @@ run-task basic_tests/write_gsb/write_gsb_to_xml_compress_routing $@
run-task basic_tests/write_gsb/write_unique_gsb_to_xml $@
run-task basic_tests/write_gsb/write_unique_gsb_to_xml_compress_routing $@
+echo -e "Testing fabric pin physical location file"
+run-task basic_tests/write_fabric_pin_phy_loc/write_fabric_pin_phy_loc_default $@
+run-task basic_tests/write_fabric_pin_phy_loc/write_fabric_pin_phy_loc_for_tiles $@
+run-task basic_tests/write_fabric_pin_phy_loc/write_fabric_pin_phy_loc_show_invalid_sides $@
+run-task basic_tests/write_fabric_pin_phy_loc/write_fabric_pin_phy_loc_wildcards $@
+
echo -e "Testing bus group features";
run-task basic_tests/bus_group/preconfig_testbench_explicit_mapping $@
run-task basic_tests/bus_group/preconfig_testbench_implicit_mapping $@
diff --git a/openfpga_flow/scripts/arch_file_updater.py b/openfpga_flow/scripts/arch_file_updater.py
index 3538ec7f3..1ef9c3786 100644
--- a/openfpga_flow/scripts/arch_file_updater.py
+++ b/openfpga_flow/scripts/arch_file_updater.py
@@ -26,6 +26,7 @@
#####################################################################
logging.basicConfig(format="%(levelname)s: %(message)s", level=logging.INFO)
+
#####################################################################
# Upgrade an architecture XML file from version 1.1 syntax to version 1.2
# Change rules:
diff --git a/openfpga_flow/scripts/io_sequence_visualizer.py b/openfpga_flow/scripts/io_sequence_visualizer.py
index d80acf1f2..cf435f217 100644
--- a/openfpga_flow/scripts/io_sequence_visualizer.py
+++ b/openfpga_flow/scripts/io_sequence_visualizer.py
@@ -13,6 +13,7 @@
Author: Ganesh Gore
"""
+
import math
import svgwrite
from svgwrite.container import Group
diff --git a/openfpga_flow/scripts/run_fpga_flow.py b/openfpga_flow/scripts/run_fpga_flow.py
index 3ad7bec8f..1cb3bc8a6 100644
--- a/openfpga_flow/scripts/run_fpga_flow.py
+++ b/openfpga_flow/scripts/run_fpga_flow.py
@@ -674,9 +674,11 @@ def create_yosys_params():
ys_params["READ_HDL_FILE"] += " ".join(
[
"verific",
- "-L " + ys_params["VERIFIC_SEARCH_LIB"]
- if "VERIFIC_SEARCH_LIB" in ys_params
- else "",
+ (
+ "-L " + ys_params["VERIFIC_SEARCH_LIB"]
+ if "VERIFIC_SEARCH_LIB" in ys_params
+ else ""
+ ),
standard,
" ".join([shlex.quote(src) for src in sources]),
"\n",
diff --git a/openfpga_flow/tasks/basic_tests/no_time_stamp/device_1x1/golden_outputs_no_time_stamp/fabric_pin_phy_loc.xml b/openfpga_flow/tasks/basic_tests/no_time_stamp/device_1x1/golden_outputs_no_time_stamp/fabric_pin_phy_loc.xml
new file mode 100644
index 000000000..603d120a5
--- /dev/null
+++ b/openfpga_flow/tasks/basic_tests/no_time_stamp/device_1x1/golden_outputs_no_time_stamp/fabric_pin_phy_loc.xml
@@ -0,0 +1,644 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/openfpga_flow/tasks/basic_tests/no_time_stamp/device_4x4/golden_outputs_no_time_stamp/fabric_pin_phy_loc.xml b/openfpga_flow/tasks/basic_tests/no_time_stamp/device_4x4/golden_outputs_no_time_stamp/fabric_pin_phy_loc.xml
new file mode 100644
index 000000000..e30e971a2
--- /dev/null
+++ b/openfpga_flow/tasks/basic_tests/no_time_stamp/device_4x4/golden_outputs_no_time_stamp/fabric_pin_phy_loc.xml
@@ -0,0 +1,1061 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/openfpga_flow/tasks/basic_tests/no_time_stamp/dump_waveform/golden_outputs_no_time_stamp/fabric_pin_phy_loc.xml b/openfpga_flow/tasks/basic_tests/no_time_stamp/dump_waveform/golden_outputs_no_time_stamp/fabric_pin_phy_loc.xml
new file mode 100644
index 000000000..603d120a5
--- /dev/null
+++ b/openfpga_flow/tasks/basic_tests/no_time_stamp/dump_waveform/golden_outputs_no_time_stamp/fabric_pin_phy_loc.xml
@@ -0,0 +1,644 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/openfpga_flow/tasks/basic_tests/no_time_stamp/no_cout_in_gsb/golden_outputs_no_time_stamp/fabric_pin_phy_loc.xml b/openfpga_flow/tasks/basic_tests/no_time_stamp/no_cout_in_gsb/golden_outputs_no_time_stamp/fabric_pin_phy_loc.xml
new file mode 100644
index 000000000..124109017
--- /dev/null
+++ b/openfpga_flow/tasks/basic_tests/no_time_stamp/no_cout_in_gsb/golden_outputs_no_time_stamp/fabric_pin_phy_loc.xml
@@ -0,0 +1,1105 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/openfpga_flow/tasks/basic_tests/write_fabric_pin_phy_loc/write_fabric_pin_phy_loc_default/config/task.conf b/openfpga_flow/tasks/basic_tests/write_fabric_pin_phy_loc/write_fabric_pin_phy_loc_default/config/task.conf
new file mode 100644
index 000000000..094b80b88
--- /dev/null
+++ b/openfpga_flow/tasks/basic_tests/write_fabric_pin_phy_loc/write_fabric_pin_phy_loc_default/config/task.conf
@@ -0,0 +1,43 @@
+# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
+# 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_tile_write_fabric_pin_phy_loc_preconfig_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/fixed_sim_openfpga.xml
+openfpga_vpr_extra_options=
+openfpga_pb_pin_fixup_command=
+openfpga_vpr_device=auto
+openfpga_vpr_route_chan_width=20
+openfpga_group_tile_config_file=${PATH:TASK_DIR}/config/tile_config.xml
+openfpga_verilog_testbench_options=--explicit_port_mapping
+openfpga_fabric_pin_phy_loc_file=fabric_pin_phy_loc.xml
+openfpga_fabric_pin_phy_loc_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=
+vpr_fpga_verilog_formal_verification_top_netlist=
diff --git a/openfpga_flow/tasks/basic_tests/write_fabric_pin_phy_loc/write_fabric_pin_phy_loc_default/config/tile_config.xml b/openfpga_flow/tasks/basic_tests/write_fabric_pin_phy_loc/write_fabric_pin_phy_loc_default/config/tile_config.xml
new file mode 100644
index 000000000..1a1f3f6e8
--- /dev/null
+++ b/openfpga_flow/tasks/basic_tests/write_fabric_pin_phy_loc/write_fabric_pin_phy_loc_default/config/tile_config.xml
@@ -0,0 +1 @@
+
diff --git a/openfpga_flow/tasks/basic_tests/write_fabric_pin_phy_loc/write_fabric_pin_phy_loc_for_tiles/config/task.conf b/openfpga_flow/tasks/basic_tests/write_fabric_pin_phy_loc/write_fabric_pin_phy_loc_for_tiles/config/task.conf
new file mode 100644
index 000000000..a8fcda0db
--- /dev/null
+++ b/openfpga_flow/tasks/basic_tests/write_fabric_pin_phy_loc/write_fabric_pin_phy_loc_for_tiles/config/task.conf
@@ -0,0 +1,43 @@
+# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
+# 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_tile_write_fabric_pin_phy_loc_preconfig_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/fixed_sim_openfpga.xml
+openfpga_vpr_extra_options=
+openfpga_pb_pin_fixup_command=
+openfpga_vpr_device=auto
+openfpga_vpr_route_chan_width=20
+openfpga_group_tile_config_file=${PATH:TASK_DIR}/config/tile_config.xml
+openfpga_verilog_testbench_options=--explicit_port_mapping
+openfpga_fabric_pin_phy_loc_file=fabric_pin_phy_loc.xml
+openfpga_fabric_pin_phy_loc_module=--module tile*
+
+[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=
+vpr_fpga_verilog_formal_verification_top_netlist=
diff --git a/openfpga_flow/tasks/basic_tests/write_fabric_pin_phy_loc/write_fabric_pin_phy_loc_for_tiles/config/tile_config.xml b/openfpga_flow/tasks/basic_tests/write_fabric_pin_phy_loc/write_fabric_pin_phy_loc_for_tiles/config/tile_config.xml
new file mode 100644
index 000000000..1a1f3f6e8
--- /dev/null
+++ b/openfpga_flow/tasks/basic_tests/write_fabric_pin_phy_loc/write_fabric_pin_phy_loc_for_tiles/config/tile_config.xml
@@ -0,0 +1 @@
+
diff --git a/openfpga_flow/tasks/basic_tests/write_fabric_pin_phy_loc/write_fabric_pin_phy_loc_show_invalid_sides/config/task.conf b/openfpga_flow/tasks/basic_tests/write_fabric_pin_phy_loc/write_fabric_pin_phy_loc_show_invalid_sides/config/task.conf
new file mode 100644
index 000000000..a6abb1e92
--- /dev/null
+++ b/openfpga_flow/tasks/basic_tests/write_fabric_pin_phy_loc/write_fabric_pin_phy_loc_show_invalid_sides/config/task.conf
@@ -0,0 +1,43 @@
+# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
+# 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_tile_write_fabric_pin_phy_loc_preconfig_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/fixed_sim_openfpga.xml
+openfpga_vpr_extra_options=
+openfpga_pb_pin_fixup_command=
+openfpga_vpr_device=auto
+openfpga_vpr_route_chan_width=20
+openfpga_group_tile_config_file=${PATH:TASK_DIR}/config/tile_config.xml
+openfpga_verilog_testbench_options=--explicit_port_mapping
+openfpga_fabric_pin_phy_loc_file=fabric_pin_phy_loc.xml
+openfpga_fabric_pin_phy_loc_module=--module tile* --show_invalid_side
+
+[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=
+vpr_fpga_verilog_formal_verification_top_netlist=
diff --git a/openfpga_flow/tasks/basic_tests/write_fabric_pin_phy_loc/write_fabric_pin_phy_loc_show_invalid_sides/config/tile_config.xml b/openfpga_flow/tasks/basic_tests/write_fabric_pin_phy_loc/write_fabric_pin_phy_loc_show_invalid_sides/config/tile_config.xml
new file mode 100644
index 000000000..1a1f3f6e8
--- /dev/null
+++ b/openfpga_flow/tasks/basic_tests/write_fabric_pin_phy_loc/write_fabric_pin_phy_loc_show_invalid_sides/config/tile_config.xml
@@ -0,0 +1 @@
+
diff --git a/openfpga_flow/tasks/basic_tests/write_fabric_pin_phy_loc/write_fabric_pin_phy_loc_wildcards/config/task.conf b/openfpga_flow/tasks/basic_tests/write_fabric_pin_phy_loc/write_fabric_pin_phy_loc_wildcards/config/task.conf
new file mode 100644
index 000000000..1382ad6f0
--- /dev/null
+++ b/openfpga_flow/tasks/basic_tests/write_fabric_pin_phy_loc/write_fabric_pin_phy_loc_wildcards/config/task.conf
@@ -0,0 +1,43 @@
+# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
+# 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_tile_write_fabric_pin_phy_loc_preconfig_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/fixed_sim_openfpga.xml
+openfpga_vpr_extra_options=
+openfpga_pb_pin_fixup_command=
+openfpga_vpr_device=auto
+openfpga_vpr_route_chan_width=20
+openfpga_group_tile_config_file=${PATH:TASK_DIR}/config/tile_config.xml
+openfpga_verilog_testbench_options=--explicit_port_mapping
+openfpga_fabric_pin_phy_loc_file=fabric_pin_phy_loc.xml
+openfpga_fabric_pin_phy_loc_module=--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=
+vpr_fpga_verilog_formal_verification_top_netlist=
diff --git a/openfpga_flow/tasks/basic_tests/write_fabric_pin_phy_loc/write_fabric_pin_phy_loc_wildcards/config/tile_config.xml b/openfpga_flow/tasks/basic_tests/write_fabric_pin_phy_loc/write_fabric_pin_phy_loc_wildcards/config/tile_config.xml
new file mode 100644
index 000000000..1a1f3f6e8
--- /dev/null
+++ b/openfpga_flow/tasks/basic_tests/write_fabric_pin_phy_loc/write_fabric_pin_phy_loc_wildcards/config/tile_config.xml
@@ -0,0 +1 @@
+
diff --git a/requirements.txt b/requirements.txt
index 889fe9159..502bfc8e0 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -5,5 +5,5 @@ pyverilog
# Python linter and formatter
click==8.0.2 # Our version of black needs an older version of click (https://stackoverflow.com/questions/71673404/importerror-cannot-import-name-unicodefun-from-click)
-black==20.8b1
+black==24.3.0
pylint==2.7.4
diff --git a/yosys b/yosys
index 0a854cf4c..47bdb3e32 160000
--- a/yosys
+++ b/yosys
@@ -1 +1 @@
-Subproject commit 0a854cf4cea669dd78c9a29657c29a70a651ec6d
+Subproject commit 47bdb3e32f71add7a48ec6215e9838048d52609a