Merge pull request #731 from lnis-uofu/io_constraints

Now OpenFPGA can output I/O location information to an XML file
This commit is contained in:
tangxifan 2022-07-26 15:41:08 -07:00 committed by GitHub
commit 65fa6f5b60
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 238 additions and 1 deletions

View File

@ -0,0 +1,51 @@
.. _file_format_io_info_file:
I/O Information File (.xml)
-----------------------
The I/O information file aims to show
- The number of I/O in an FPGA fabric
- The name of each I/O in an FPGA fabric
- The coordinate (in VPR domain) of each I/O in an FPGA fabric
An example of the file is shown as follows.
.. code-block:: xml
<io_coordinates>
<io pad="gfpga_pad_GPIO_PAD[0]" x="1" y="2" z="0"/>
<io pad="gfpga_pad_GPIO_PAD[1]" x="1" y="2" z="1"/>
<io pad="gfpga_pad_GPIO_PAD[2]" x="1" y="2" z="2"/>
<io pad="gfpga_pad_GPIO_PAD[3]" x="1" y="2" z="3"/>
<io pad="gfpga_pad_GPIO_PAD[4]" x="1" y="2" z="4"/>
<io pad="gfpga_pad_GPIO_PAD[5]" x="1" y="2" z="5"/>
<io pad="gfpga_pad_GPIO_PAD[6]" x="1" y="2" z="6"/>
<io pad="gfpga_pad_GPIO_PAD[7]" x="1" y="2" z="7"/>
<io pad="gfpga_pad_GPIO_PAD[8]" x="2" y="1" z="0"/>
<io pad="gfpga_pad_GPIO_PAD[9]" x="2" y="1" z="1"/>
<io pad="gfpga_pad_GPIO_PAD[10]" x="2" y="1" z="2"/>
<io pad="gfpga_pad_GPIO_PAD[11]" x="2" y="1" z="3"/>
<io pad="gfpga_pad_GPIO_PAD[12]" x="2" y="1" z="4"/>
<io pad="gfpga_pad_GPIO_PAD[13]" x="2" y="1" z="5"/>
<io pad="gfpga_pad_GPIO_PAD[14]" x="2" y="1" z="6"/>
<io pad="gfpga_pad_GPIO_PAD[15]" x="2" y="1" z="7"/>
</io_coordinates>
.. option:: pad="<string>"
The port name of the I/O in FPGA fabric, which should be a valid port defined in output Verilog netlist.
.. note:: You should be find the exact pin in the top-level module of FPGA fabric if you output the Verilog netlists.
.. option:: x="<int>"
The x coordinate of the I/O in VPR coordinate system.
.. option:: y="<int>"
The y coordinate of the I/O in VPR coordinate system.
.. option:: z="<int>"
The z coordinate of the I/O in VPR coordinate system.

View File

@ -217,3 +217,22 @@ write_fabric_hierarchy
Show verbose log
.. note:: This file is designed for hierarchical PnR flow, which requires the tree of Multiple-Instanced-Blocks (MIBs).
write_fabric_io_info
~~~~~~~~~~~~~~~~~~~~
Write the I/O information of FPGA fabric to an XML file
.. option:: --file <string> or -f <string>
Specify the file name to write the I/O information
.. option:: --no_time_stamp
Do not print time stamp in bitstream files
.. option:: --verbose
Show verbose log
.. note:: This file is designed for pin constraint file conversion.

View File

@ -1,7 +1,13 @@
/******************************************************************************
* Memember functions for data structure IoLocationMap
******************************************************************************/
/* Headers from vtrutil library */
#include "vtr_log.h"
#include "vtr_assert.h"
#include "vtr_time.h"
/* Headers from openfpgautil library */
#include "openfpga_digest.h"
#include "io_location_map.h"
@ -55,4 +61,79 @@ void IoLocationMap::set_io_index(const size_t& x,
io_indices_[x][y][z][io_port_name] = io_index;
}
int IoLocationMap::write_to_xml_file(const std::string& fname,
const bool& include_time_stamp,
const bool& verbose) const {
std::string timer_message = std::string("Write fabric I/O information to an XML file '") + fname + std::string("'");
std::string dir_path = format_dir_path(find_path_dir_name(fname));
/* Create directories */
create_directory(dir_path);
/* Start time count */
vtr::ScopedStartFinishTimer timer(timer_message);
/* Use default name if user does not provide one */
VTR_ASSERT(true != fname.empty());
/* Create a file handler*/
std::fstream fp;
/* Open a file */
fp.open(fname, std::fstream::out | std::fstream::trunc);
/* Validate the file stream */
check_file_stream(fname.c_str(), fp);
int err_code = 0;
/* Write XML head */
fp << "<!--" << std::endl;
fp << "\t- FPGA Fabric I/O Information" << std::endl;
fp << "\t- Generated by OpenFPGA" << std::endl;
auto end = std::chrono::system_clock::now();
std::time_t end_time = std::chrono::system_clock::to_time_t(end);
if (include_time_stamp) {
fp << "\t- Date: " << std::ctime(&end_time) ;
}
fp << "-->" << std::endl;
fp << std::endl;
fp << "<io_coordinates>\n";
size_t io_cnt = 0;
/* Walk through the fabric I/O location map data structure */
for (size_t x = 0; x < io_indices_.size(); ++x) {
for (size_t y = 0; y < io_indices_[x].size(); ++y) {
for (size_t z = 0; z < io_indices_[x][y].size(); ++z) {
for (const auto& name_id_pair : io_indices_[x][y][z]) {
fp << "\t" << "<io pad=\"" << name_id_pair.first << "[" << name_id_pair.second << "]\"";
fp << " " << "x=\"" << x << "\"";
fp << " " << "y=\"" << y << "\"";
fp << " " << "z=\"" << z << "\"";
fp << "/>";
fp << "\n";
io_cnt++;
}
}
}
}
/* Print an end to the file here */
fp << "</io_coordinates>\n";
/* close a file */
fp.close();
VTR_LOGV(verbose,
"Outputted %lu I/Os to XML file: %s\n",
io_cnt,
fname.c_str());
return err_code;
}
} /* end namespace openfpga */

View File

@ -40,6 +40,10 @@ class IoLocationMap {
const size_t& z,
const std::string& io_port_name,
const size_t& io_index);
public: /* Public writer */
int write_to_xml_file(const std::string& fname,
const bool& include_time_stamp,
const bool& verbose) const;
private: /* Internal Data */
/* I/O index fast lookup by [x][y][z] location */
std::vector<std::vector<std::vector<std::map<std::string, size_t>>>> io_indices_;

View File

@ -147,7 +147,7 @@ int build_fabric(OpenfpgaContext& openfpga_ctx,
}
/********************************************************************
* Build the module graph for FPGA device
* Write hierarchy of the module graph for FPGA device to a file
*******************************************************************/
int write_fabric_hierarchy(const OpenfpgaContext& openfpga_ctx,
const Command& cmd, const CommandContext& cmd_context) {
@ -184,4 +184,30 @@ int write_fabric_hierarchy(const OpenfpgaContext& openfpga_ctx,
cmd_context.option_enable(cmd, opt_verbose));
}
/********************************************************************
* Write the I/O information of module graph to a file
*******************************************************************/
int write_fabric_io_info(const OpenfpgaContext& 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");
/* 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);
/* Write hierarchy to a file */
return openfpga_ctx.io_location_map().write_to_xml_file(file_name,
!cmd_context.option_enable(cmd, opt_no_time_stamp),
cmd_context.option_enable(cmd, opt_verbose));
}
} /* end namespace openfpga */

View File

@ -21,6 +21,9 @@ int build_fabric(OpenfpgaContext& openfpga_ctx,
int write_fabric_hierarchy(const OpenfpgaContext& openfpga_ctx,
const Command& cmd, const CommandContext& cmd_context);
int write_fabric_io_info(const OpenfpgaContext& openfpga_ctx,
const Command& cmd, const CommandContext& cmd_context);
} /* end namespace openfpga */
#endif

View File

@ -388,6 +388,39 @@ ShellCommandId add_openfpga_write_fabric_hierarchy_command(openfpga::Shell<Openf
return shell_cmd_id;
}
/********************************************************************
* - Add a command to Shell environment: write_fabric_io_info
* - Add associated options
* - Add command dependency
*******************************************************************/
static
ShellCommandId add_openfpga_write_fabric_io_info_command(openfpga::Shell<OpenfpgaContext>& shell,
const ShellCommandClassId& cmd_class_id,
const std::vector<ShellCommandId>& dependent_cmds) {
Command shell_cmd("write_fabric_io_info");
/* Add an option '--file' in short '-f'*/
CommandOptionId opt_file = shell_cmd.add_option("file", true, "file path to output the I/O information");
shell_cmd.set_option_short_name(opt_file, "f");
shell_cmd.set_option_require_value(opt_file, 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");
/* Add an option '--verbose' */
shell_cmd.add_option("verbose", false, "Enable verbose output");
/* Add command the Shell */
ShellCommandId shell_cmd_id = shell.add_command(shell_cmd, "Write the I/O information, e.g., locations and similar attributes, to a file");
shell.set_command_class(shell_cmd_id, cmd_class_id);
shell.set_command_execute_function(shell_cmd_id, write_fabric_io_info);
/* Add command dependency to the Shell */
shell.set_command_dependency(shell_cmd_id, dependent_cmds);
return shell_cmd_id;
}
void add_openfpga_setup_commands(openfpga::Shell<OpenfpgaContext>& shell) {
/* Get the unique id of 'vpr' command which is to be used in creating the dependency graph */
const ShellCommandId& vpr_cmd_id = shell.command(std::string("vpr"));
@ -515,6 +548,14 @@ void add_openfpga_setup_commands(openfpga::Shell<OpenfpgaContext>& shell) {
add_openfpga_write_fabric_hierarchy_command(shell,
openfpga_setup_cmd_class,
write_fabric_hie_dependent_cmds);
/********************************
* Command 'write_fabric_io_info'
*/
/* The 'write_fabric_io_info' command should NOT be executed before 'build_fabric' */
std::vector<ShellCommandId> cmd_dependency_write_fabric_io_info;
cmd_dependency_write_fabric_io_info.push_back(build_fabric_cmd_id);
add_openfpga_write_fabric_io_info_command(shell, openfpga_setup_cmd_class, cmd_dependency_write_fabric_io_info);
}
} /* end namespace openfpga */

View File

@ -24,6 +24,10 @@ build_fabric --compress_routing #--verbose
# This is used by hierarchical PnR flows
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 ./fabric_io_location.xml --verbose
# Write the Verilog netlist for FPGA fabric
# - Enable the use of explicit port mapping in Verilog netlist
write_fabric_verilog --file ${OPENFPGA_VERILOG_OUTPUT_DIR}/SRC --explicit_port_mapping --include_timing --print_user_defined_template --verbose

View File

@ -32,6 +32,10 @@ build_fabric --compress_routing #--verbose
# This is used by hierarchical PnR flows
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 ./fabric_io_location.xml --verbose --no_time_stamp
# 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

View File

@ -30,6 +30,10 @@ build_fabric --compress_routing #--verbose
# This is used by hierarchical PnR flows
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 ./fabric_io_location.xml --verbose --no_time_stamp
# 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