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:
commit
65fa6f5b60
|
@ -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.
|
|
@ -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.
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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_;
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue