Merge branch 'master' into micro_benchmarks
This commit is contained in:
commit
a5e40fbb21
|
@ -91,7 +91,6 @@ else ()
|
||||||
"-D__USE_FIXED_PROTOTYPES__"
|
"-D__USE_FIXED_PROTOTYPES__"
|
||||||
"-ansi"
|
"-ansi"
|
||||||
"-Wshadow"
|
"-Wshadow"
|
||||||
"-Wcast-allign"
|
|
||||||
"-Wno-write-strings"
|
"-Wno-write-strings"
|
||||||
"-D_POSIX_SOURCE"
|
"-D_POSIX_SOURCE"
|
||||||
"-Wall" #Most warnings, typically good
|
"-Wall" #Most warnings, typically good
|
||||||
|
|
|
@ -21,3 +21,5 @@ OpenFPGA widely uses XML format for interchangable files
|
||||||
bitstream_setting
|
bitstream_setting
|
||||||
|
|
||||||
fabric_key
|
fabric_key
|
||||||
|
|
||||||
|
io_mapping_file
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
.. _file_format_io_mapping_file:
|
||||||
|
|
||||||
|
I/O Mapping File (.xml)
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
The I/O mapping file aims to show
|
||||||
|
|
||||||
|
- What nets have been mapped to each I/O
|
||||||
|
- What is the directionality of each mapped I/O
|
||||||
|
|
||||||
|
An example of design constraints is shown as follows.
|
||||||
|
|
||||||
|
.. code-block:: xml
|
||||||
|
|
||||||
|
<io_mapping>
|
||||||
|
<io name="gfpga_pad_GPIO_PAD[6:6]" net="a" dir="input"/>
|
||||||
|
<io name="gfpga_pad_GPIO_PAD[1:1]" net="b" dir="input"/>
|
||||||
|
<io name="gfpga_pad_GPIO_PAD[9:9]" net="out_c" dir="output"/>
|
||||||
|
</io_mapping>
|
||||||
|
|
||||||
|
.. option:: name="<string>"
|
||||||
|
|
||||||
|
The pin name of the FPGA fabric which has been mapped, which should be a valid pin defined in OpenFPGA architecture description.
|
||||||
|
|
||||||
|
.. note:: You should be find the exact pin in the top-level module of FPGA fabric if you output the Verilog netlists.
|
||||||
|
|
||||||
|
.. option:: net="<string>"
|
||||||
|
|
||||||
|
The net name which is actually mapped to a pin, which should be consistent with net definition in your ``.blif`` file.
|
||||||
|
|
||||||
|
.. option:: dir="<string>"
|
||||||
|
|
||||||
|
The direction of an I/O, which can be either ``input`` or ``output``.
|
|
@ -72,3 +72,19 @@ write_fabric_bitstream
|
||||||
.. option:: --verbose
|
.. option:: --verbose
|
||||||
|
|
||||||
Show verbose log
|
Show verbose log
|
||||||
|
|
||||||
|
write_io_mapping
|
||||||
|
~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Output the I/O mapping information to a file
|
||||||
|
|
||||||
|
.. option:: --file <string> or -f <string>
|
||||||
|
|
||||||
|
Specify the file name where the I/O mapping will be outputted to.
|
||||||
|
See file formats in :ref:`file_format_io_mapping_file`.
|
||||||
|
|
||||||
|
.. option:: --verbose
|
||||||
|
|
||||||
|
Show verbose log
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* Memember functions for data structure IoMap
|
||||||
|
******************************************************************************/
|
||||||
|
#include "vtr_assert.h"
|
||||||
|
|
||||||
|
#include "io_map.h"
|
||||||
|
|
||||||
|
/* begin namespace openfpga */
|
||||||
|
namespace openfpga {
|
||||||
|
|
||||||
|
IoMap::io_map_range IoMap::io_map() const {
|
||||||
|
return vtr::make_range(io_map_ids_.begin(), io_map_ids_.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
BasicPort IoMap::io_port(IoMapId io_map_id) const {
|
||||||
|
VTR_ASSERT(valid_io_map_id(io_map_id));
|
||||||
|
return io_ports_[io_map_id];
|
||||||
|
}
|
||||||
|
|
||||||
|
BasicPort IoMap::io_net(IoMapId io_map_id) const {
|
||||||
|
VTR_ASSERT(valid_io_map_id(io_map_id));
|
||||||
|
return mapped_nets_[io_map_id];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IoMap::is_io_output(IoMapId io_map_id) const {
|
||||||
|
VTR_ASSERT(valid_io_map_id(io_map_id));
|
||||||
|
return IoMap::IO_MAP_DIR_OUTPUT == io_directionality_[io_map_id];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IoMap::is_io_input(IoMapId io_map_id) const {
|
||||||
|
VTR_ASSERT(valid_io_map_id(io_map_id));
|
||||||
|
return IoMap::IO_MAP_DIR_INPUT == io_directionality_[io_map_id];
|
||||||
|
}
|
||||||
|
|
||||||
|
IoMapId IoMap::create_io_mapping(const BasicPort& port,
|
||||||
|
const BasicPort& net,
|
||||||
|
IoMap::e_direction dir) {
|
||||||
|
/* Create a new id */
|
||||||
|
IoMapId io_map_id = IoMapId(io_map_ids_.size());
|
||||||
|
io_map_ids_.push_back(io_map_id);
|
||||||
|
|
||||||
|
/* Allocate related attributes */
|
||||||
|
io_ports_.push_back(port);
|
||||||
|
mapped_nets_.push_back(net);
|
||||||
|
io_directionality_.push_back(dir);
|
||||||
|
|
||||||
|
return io_map_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IoMap::valid_io_map_id(IoMapId io_map_id) const {
|
||||||
|
return (size_t(io_map_id) < io_map_ids_.size()) && (io_map_id == io_map_ids_[io_map_id]);
|
||||||
|
}
|
||||||
|
|
||||||
|
} /* end namespace openfpga */
|
|
@ -0,0 +1,59 @@
|
||||||
|
#ifndef IO_MAP_H
|
||||||
|
#define IO_MAP_H
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* Include header files required by the data structure definition
|
||||||
|
*******************************************************************/
|
||||||
|
#include "vtr_vector.h"
|
||||||
|
#include "openfpga_port.h"
|
||||||
|
#include "io_map_fwd.h"
|
||||||
|
|
||||||
|
/* Begin namespace openfpga */
|
||||||
|
namespace openfpga {
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* This is a data structure storing io mapping information
|
||||||
|
* - the net-to-I/O mapping
|
||||||
|
* - each I/O directionality
|
||||||
|
*******************************************************************/
|
||||||
|
class IoMap {
|
||||||
|
public: /* Types and ranges */
|
||||||
|
enum e_direction {
|
||||||
|
IO_MAP_DIR_INPUT,
|
||||||
|
IO_MAP_DIR_OUTPUT,
|
||||||
|
NUM_IO_MAP_DIR_TYPES
|
||||||
|
};
|
||||||
|
typedef vtr::vector<IoMapId, IoMapId>::const_iterator io_map_iterator;
|
||||||
|
typedef vtr::Range<io_map_iterator> io_map_range;
|
||||||
|
public: /* Public aggregators */
|
||||||
|
/* Find all io mapping */
|
||||||
|
io_map_range io_map() const;
|
||||||
|
|
||||||
|
/* Get the port of the io that is mapped */
|
||||||
|
BasicPort io_port(IoMapId io_map_id) const;
|
||||||
|
|
||||||
|
/* Get the net of the io that is mapped to */
|
||||||
|
BasicPort io_net(IoMapId io_map_id) const;
|
||||||
|
|
||||||
|
/* Query on if an io is configured as an input */
|
||||||
|
bool is_io_input(IoMapId io_map_id) const;
|
||||||
|
|
||||||
|
/* Query on if an io is configured as an output */
|
||||||
|
bool is_io_output(IoMapId io_map_id) const;
|
||||||
|
public: /* Public mutators */
|
||||||
|
/* Create a new I/O mapping */
|
||||||
|
IoMapId create_io_mapping(const BasicPort& port,
|
||||||
|
const BasicPort& net,
|
||||||
|
e_direction dir);
|
||||||
|
public: /* Public validators/invalidators */
|
||||||
|
bool valid_io_map_id(IoMapId io_map_id) const;
|
||||||
|
private: /* Internal Data */
|
||||||
|
vtr::vector<IoMapId, IoMapId> io_map_ids_;
|
||||||
|
vtr::vector<IoMapId, BasicPort> io_ports_;
|
||||||
|
vtr::vector<IoMapId, BasicPort> mapped_nets_;
|
||||||
|
vtr::vector<IoMapId, e_direction> io_directionality_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} /* End namespace openfpga*/
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,23 @@
|
||||||
|
/**************************************************
|
||||||
|
* This file includes only declarations for
|
||||||
|
* the data structures for IoMap
|
||||||
|
* Please refer to io_map.h for more details
|
||||||
|
*************************************************/
|
||||||
|
#ifndef IO_MAP_FWD_H
|
||||||
|
#define IO_MAP_FWD_H
|
||||||
|
|
||||||
|
#include "vtr_strong_id.h"
|
||||||
|
|
||||||
|
/* begin namespace openfpga */
|
||||||
|
namespace openfpga {
|
||||||
|
|
||||||
|
/* Strong Ids */
|
||||||
|
struct io_map_id_tag;
|
||||||
|
|
||||||
|
typedef vtr::StrongId<io_map_id_tag> IoMapId;
|
||||||
|
|
||||||
|
class IoMap;
|
||||||
|
|
||||||
|
} /* end namespace openfpga */
|
||||||
|
|
||||||
|
#endif
|
|
@ -15,10 +15,14 @@
|
||||||
#include "read_xml_arch_bitstream.h"
|
#include "read_xml_arch_bitstream.h"
|
||||||
#include "write_xml_arch_bitstream.h"
|
#include "write_xml_arch_bitstream.h"
|
||||||
|
|
||||||
|
#include "openfpga_naming.h"
|
||||||
|
|
||||||
#include "build_device_bitstream.h"
|
#include "build_device_bitstream.h"
|
||||||
#include "write_text_fabric_bitstream.h"
|
#include "write_text_fabric_bitstream.h"
|
||||||
#include "write_xml_fabric_bitstream.h"
|
#include "write_xml_fabric_bitstream.h"
|
||||||
#include "build_fabric_bitstream.h"
|
#include "build_fabric_bitstream.h"
|
||||||
|
#include "build_io_mapping_info.h"
|
||||||
|
#include "write_xml_io_mapping.h"
|
||||||
#include "openfpga_bitstream.h"
|
#include "openfpga_bitstream.h"
|
||||||
|
|
||||||
/* Include global variables of VPR */
|
/* Include global variables of VPR */
|
||||||
|
@ -121,4 +125,44 @@ int write_fabric_bitstream(const OpenfpgaContext& openfpga_ctx,
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* A wrapper function to call the write_io_mapping() in FPGA bitstream
|
||||||
|
*******************************************************************/
|
||||||
|
int write_io_mapping(const OpenfpgaContext& openfpga_ctx,
|
||||||
|
const Command& cmd, const CommandContext& cmd_context) {
|
||||||
|
|
||||||
|
CommandOptionId opt_verbose = cmd.option("verbose");
|
||||||
|
CommandOptionId opt_file = cmd.option("file");
|
||||||
|
|
||||||
|
/* Write fabric bitstream if required */
|
||||||
|
int status = CMD_EXEC_SUCCESS;
|
||||||
|
|
||||||
|
VTR_ASSERT(true == cmd_context.option_enable(cmd, opt_file));
|
||||||
|
|
||||||
|
std::string src_dir_path = find_path_dir_name(cmd_context.option_value(cmd, opt_file));
|
||||||
|
|
||||||
|
/* Create directories */
|
||||||
|
create_directory(src_dir_path);
|
||||||
|
|
||||||
|
/* Create a module as the top-level fabric, and add it to the module manager */
|
||||||
|
std::string top_module_name = generate_fpga_top_module_name();
|
||||||
|
ModuleId top_module = openfpga_ctx.module_graph().find_module(top_module_name);
|
||||||
|
VTR_ASSERT(true == openfpga_ctx.module_graph().valid_module_id(top_module));
|
||||||
|
|
||||||
|
IoMap io_map = build_fpga_io_mapping_info(openfpga_ctx.module_graph(),
|
||||||
|
top_module,
|
||||||
|
g_vpr_ctx.atom(),
|
||||||
|
g_vpr_ctx.placement(),
|
||||||
|
openfpga_ctx.io_location_map(),
|
||||||
|
openfpga_ctx.vpr_netlist_annotation(),
|
||||||
|
std::string(),
|
||||||
|
std::string());
|
||||||
|
|
||||||
|
status = write_io_mapping_to_xml_file(io_map,
|
||||||
|
cmd_context.option_value(cmd, opt_file),
|
||||||
|
cmd_context.option_enable(cmd, opt_verbose));
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
} /* end namespace openfpga */
|
} /* end namespace openfpga */
|
||||||
|
|
|
@ -24,6 +24,9 @@ int build_fabric_bitstream(OpenfpgaContext& openfpga_ctx,
|
||||||
int write_fabric_bitstream(const OpenfpgaContext& openfpga_ctx,
|
int write_fabric_bitstream(const OpenfpgaContext& openfpga_ctx,
|
||||||
const Command& cmd, const CommandContext& cmd_context);
|
const Command& cmd, const CommandContext& cmd_context);
|
||||||
|
|
||||||
|
int write_io_mapping(const OpenfpgaContext& openfpga_ctx,
|
||||||
|
const Command& cmd, const CommandContext& cmd_context);
|
||||||
|
|
||||||
} /* end namespace openfpga */
|
} /* end namespace openfpga */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -131,6 +131,36 @@ ShellCommandId add_openfpga_write_fabric_bitstream_command(openfpga::Shell<Openf
|
||||||
return shell_cmd_id;
|
return shell_cmd_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* - Add a command to Shell environment: write_io_mapping
|
||||||
|
* - Add associated options
|
||||||
|
* - Add command dependency
|
||||||
|
*******************************************************************/
|
||||||
|
static
|
||||||
|
ShellCommandId add_openfpga_write_io_mapping_command(openfpga::Shell<OpenfpgaContext>& shell,
|
||||||
|
const ShellCommandClassId& cmd_class_id,
|
||||||
|
const std::vector<ShellCommandId>& dependent_cmds) {
|
||||||
|
Command shell_cmd("write_io_mapping");
|
||||||
|
|
||||||
|
/* Add an option '--file' in short '-f'*/
|
||||||
|
CommandOptionId opt_file = shell_cmd.add_option("file", true, "file path to output the io mapping information");
|
||||||
|
shell_cmd.set_option_short_name(opt_file, "f");
|
||||||
|
shell_cmd.set_option_require_value(opt_file, openfpga::OPT_STRING);
|
||||||
|
|
||||||
|
/* Add an option '--verbose' */
|
||||||
|
shell_cmd.add_option("verbose", false, "Enable verbose output");
|
||||||
|
|
||||||
|
/* Add command 'fabric_bitstream' to the Shell */
|
||||||
|
ShellCommandId shell_cmd_id = shell.add_command(shell_cmd, "Write the I/O mapping information to a file");
|
||||||
|
shell.set_command_class(shell_cmd_id, cmd_class_id);
|
||||||
|
shell.set_command_execute_function(shell_cmd_id, write_io_mapping);
|
||||||
|
|
||||||
|
/* Add command dependency to the Shell */
|
||||||
|
shell.set_command_dependency(shell_cmd_id, dependent_cmds);
|
||||||
|
|
||||||
|
return shell_cmd_id;
|
||||||
|
}
|
||||||
|
|
||||||
/********************************************************************
|
/********************************************************************
|
||||||
* Top-level function to add all the commands related to FPGA-Bitstream
|
* Top-level function to add all the commands related to FPGA-Bitstream
|
||||||
*******************************************************************/
|
*******************************************************************/
|
||||||
|
@ -172,6 +202,14 @@ void add_openfpga_bitstream_commands(openfpga::Shell<OpenfpgaContext>& shell) {
|
||||||
std::vector<ShellCommandId> cmd_dependency_write_fabric_bitstream;
|
std::vector<ShellCommandId> cmd_dependency_write_fabric_bitstream;
|
||||||
cmd_dependency_write_fabric_bitstream.push_back(shell_cmd_build_fabric_bitstream_id);
|
cmd_dependency_write_fabric_bitstream.push_back(shell_cmd_build_fabric_bitstream_id);
|
||||||
add_openfpga_write_fabric_bitstream_command(shell, openfpga_bitstream_cmd_class, cmd_dependency_write_fabric_bitstream);
|
add_openfpga_write_fabric_bitstream_command(shell, openfpga_bitstream_cmd_class, cmd_dependency_write_fabric_bitstream);
|
||||||
|
|
||||||
|
/********************************
|
||||||
|
* Command 'write_io_mapping'
|
||||||
|
*/
|
||||||
|
/* The 'write_io_mapping' command should NOT be executed before 'build_fabric' */
|
||||||
|
std::vector<ShellCommandId> cmd_dependency_write_io_mapping;
|
||||||
|
cmd_dependency_write_io_mapping.push_back(shell_cmd_build_fabric_id);
|
||||||
|
add_openfpga_write_io_mapping_command(shell, openfpga_bitstream_cmd_class, cmd_dependency_write_io_mapping);
|
||||||
}
|
}
|
||||||
|
|
||||||
} /* end namespace openfpga */
|
} /* end namespace openfpga */
|
||||||
|
|
|
@ -0,0 +1,144 @@
|
||||||
|
/********************************************************************
|
||||||
|
* This file includes functions that build io mapping information
|
||||||
|
*******************************************************************/
|
||||||
|
#include <chrono>
|
||||||
|
#include <ctime>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
/* Headers from vtrutil library */
|
||||||
|
#include "vtr_assert.h"
|
||||||
|
#include "vtr_log.h"
|
||||||
|
#include "vtr_time.h"
|
||||||
|
|
||||||
|
/* Headers from archopenfpga library */
|
||||||
|
#include "openfpga_naming.h"
|
||||||
|
|
||||||
|
#include "module_manager_utils.h"
|
||||||
|
#include "build_io_mapping_info.h"
|
||||||
|
|
||||||
|
/* begin namespace openfpga */
|
||||||
|
namespace openfpga {
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* This function
|
||||||
|
* - builds the net-to-I/O mapping
|
||||||
|
* - identifies each I/O directionality
|
||||||
|
* - return a database containing the above information
|
||||||
|
*
|
||||||
|
* TODO: This function duplicates codes from
|
||||||
|
* function: print_verilog_testbench_connect_fpga_ios() in
|
||||||
|
* source file: verilog_testbench_utils.cpp
|
||||||
|
* Should consider how to merge the codes and share same builder function
|
||||||
|
*******************************************************************/
|
||||||
|
IoMap build_fpga_io_mapping_info(const ModuleManager& module_manager,
|
||||||
|
const ModuleId& top_module,
|
||||||
|
const AtomContext& atom_ctx,
|
||||||
|
const PlacementContext& place_ctx,
|
||||||
|
const IoLocationMap& io_location_map,
|
||||||
|
const VprNetlistAnnotation& netlist_annotation,
|
||||||
|
const std::string& io_input_port_name_postfix,
|
||||||
|
const std::string& io_output_port_name_postfix) {
|
||||||
|
IoMap io_map;
|
||||||
|
|
||||||
|
/* Only mappable i/o ports can be considered */
|
||||||
|
std::vector<ModulePortId> module_io_ports;
|
||||||
|
for (const ModuleManager::e_module_port_type& module_io_port_type : MODULE_IO_PORT_TYPES) {
|
||||||
|
for (const ModulePortId& gpio_port_id : module_manager.module_port_ids_by_type(top_module, module_io_port_type)) {
|
||||||
|
/* Only care mappable I/O */
|
||||||
|
if (false == module_manager.port_is_mappable_io(top_module, gpio_port_id)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
module_io_ports.push_back(gpio_port_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Type mapping between VPR block and Module port */
|
||||||
|
std::map<AtomBlockType, ModuleManager::e_module_port_type> atom_block_type_to_module_port_type;
|
||||||
|
atom_block_type_to_module_port_type[AtomBlockType::INPAD] = ModuleManager::MODULE_GPIN_PORT;
|
||||||
|
atom_block_type_to_module_port_type[AtomBlockType::OUTPAD] = ModuleManager::MODULE_GPOUT_PORT;
|
||||||
|
|
||||||
|
/* Type mapping between VPR block and io mapping direction */
|
||||||
|
std::map<AtomBlockType, IoMap::e_direction> atom_block_type_to_io_map_direction;
|
||||||
|
atom_block_type_to_io_map_direction[AtomBlockType::INPAD] = IoMap::IO_MAP_DIR_INPUT;
|
||||||
|
atom_block_type_to_io_map_direction[AtomBlockType::OUTPAD] = IoMap::IO_MAP_DIR_OUTPUT;
|
||||||
|
|
||||||
|
for (const AtomBlockId& atom_blk : atom_ctx.nlist.blocks()) {
|
||||||
|
/* Bypass non-I/O atom blocks ! */
|
||||||
|
if ( (AtomBlockType::INPAD != atom_ctx.nlist.block_type(atom_blk))
|
||||||
|
&& (AtomBlockType::OUTPAD != atom_ctx.nlist.block_type(atom_blk)) ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If there is a GPIO port, use it directly
|
||||||
|
* Otherwise, should find a GPIN for INPAD
|
||||||
|
* or should find a GPOUT for OUTPAD
|
||||||
|
*/
|
||||||
|
std::pair<ModulePortId, size_t> mapped_module_io_info = std::make_pair(ModulePortId::INVALID(), -1);
|
||||||
|
for (const ModulePortId& module_io_port_id : module_io_ports) {
|
||||||
|
const BasicPort& module_io_port = module_manager.module_port(top_module, module_io_port_id);
|
||||||
|
|
||||||
|
/* Find the index of the mapped GPIO in top-level FPGA fabric */
|
||||||
|
size_t temp_io_index = io_location_map.io_index(place_ctx.block_locs[atom_ctx.lookup.atom_clb(atom_blk)].loc.x,
|
||||||
|
place_ctx.block_locs[atom_ctx.lookup.atom_clb(atom_blk)].loc.y,
|
||||||
|
place_ctx.block_locs[atom_ctx.lookup.atom_clb(atom_blk)].loc.z,
|
||||||
|
module_io_port.get_name());
|
||||||
|
|
||||||
|
/* Bypass invalid index (not mapped to this GPIO port) */
|
||||||
|
if (size_t(-1) == temp_io_index) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If the port is an GPIO port, just use it */
|
||||||
|
if (ModuleManager::MODULE_GPIO_PORT == module_manager.port_type(top_module, module_io_port_id)) {
|
||||||
|
mapped_module_io_info = std::make_pair(module_io_port_id, temp_io_index);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If this is an INPAD, we can use an GPIN port (if available) */
|
||||||
|
if (atom_block_type_to_module_port_type[atom_ctx.nlist.block_type(atom_blk)] == module_manager.port_type(top_module, module_io_port_id)) {
|
||||||
|
mapped_module_io_info = std::make_pair(module_io_port_id, temp_io_index);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We must find a valid one */
|
||||||
|
VTR_ASSERT(true == module_manager.valid_module_port_id(top_module, mapped_module_io_info.first));
|
||||||
|
VTR_ASSERT(size_t(-1) != mapped_module_io_info.second);
|
||||||
|
|
||||||
|
/* Ensure that IO index is in range */
|
||||||
|
BasicPort module_mapped_io_port = module_manager.module_port(top_module, mapped_module_io_info.first);
|
||||||
|
size_t io_index = mapped_module_io_info.second;
|
||||||
|
|
||||||
|
/* Set the port pin index */
|
||||||
|
VTR_ASSERT(io_index < module_mapped_io_port.get_width());
|
||||||
|
module_mapped_io_port.set_width(io_index, io_index);
|
||||||
|
|
||||||
|
/* The block may be renamed as it contains special characters which violate Verilog syntax */
|
||||||
|
std::string block_name = atom_ctx.nlist.block_name(atom_blk);
|
||||||
|
if (true == netlist_annotation.is_block_renamed(atom_blk)) {
|
||||||
|
block_name = netlist_annotation.block_name(atom_blk);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create the port for benchmark I/O, due to BLIF benchmark, each I/O always has a size of 1
|
||||||
|
* In addition, the input and output ports may have different postfix in naming
|
||||||
|
* due to verification context! Here, we give full customization on naming
|
||||||
|
*/
|
||||||
|
BasicPort benchmark_io_port;
|
||||||
|
if (AtomBlockType::INPAD == atom_ctx.nlist.block_type(atom_blk)) {
|
||||||
|
benchmark_io_port.set_name(std::string(block_name + io_input_port_name_postfix));
|
||||||
|
benchmark_io_port.set_width(1);
|
||||||
|
} else {
|
||||||
|
VTR_ASSERT(AtomBlockType::OUTPAD == atom_ctx.nlist.block_type(atom_blk));
|
||||||
|
benchmark_io_port.set_name(std::string(block_name + io_output_port_name_postfix));
|
||||||
|
benchmark_io_port.set_width(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
io_map.create_io_mapping(module_mapped_io_port,
|
||||||
|
benchmark_io_port,
|
||||||
|
atom_block_type_to_io_map_direction[atom_ctx.nlist.block_type(atom_blk)]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return io_map;
|
||||||
|
}
|
||||||
|
|
||||||
|
} /* end namespace openfpga */
|
|
@ -0,0 +1,33 @@
|
||||||
|
#ifndef BUILD_IO_MAPPING_INFO_H
|
||||||
|
#define BUILD_IO_MAPPING_INFO_H
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* Include header files that are required by function declaration
|
||||||
|
*******************************************************************/
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include "module_manager.h"
|
||||||
|
#include "vpr_context.h"
|
||||||
|
#include "io_location_map.h"
|
||||||
|
#include "io_map.h"
|
||||||
|
#include "vpr_netlist_annotation.h"
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* Function declaration
|
||||||
|
*******************************************************************/
|
||||||
|
|
||||||
|
/* begin namespace openfpga */
|
||||||
|
namespace openfpga {
|
||||||
|
|
||||||
|
IoMap build_fpga_io_mapping_info(const ModuleManager& module_manager,
|
||||||
|
const ModuleId& top_module,
|
||||||
|
const AtomContext& atom_ctx,
|
||||||
|
const PlacementContext& place_ctx,
|
||||||
|
const IoLocationMap& io_location_map,
|
||||||
|
const VprNetlistAnnotation& netlist_annotation,
|
||||||
|
const std::string& io_input_port_name_postfix,
|
||||||
|
const std::string& io_output_port_name_postfix);
|
||||||
|
|
||||||
|
} /* end namespace openfpga */
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,145 @@
|
||||||
|
/********************************************************************
|
||||||
|
* This file includes functions that output io mapping information
|
||||||
|
* to files in XML format
|
||||||
|
*******************************************************************/
|
||||||
|
#include <chrono>
|
||||||
|
#include <ctime>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
/* Headers from vtrutil library */
|
||||||
|
#include "vtr_assert.h"
|
||||||
|
#include "vtr_log.h"
|
||||||
|
#include "vtr_time.h"
|
||||||
|
|
||||||
|
/* Headers from openfpgautil library */
|
||||||
|
#include "openfpga_digest.h"
|
||||||
|
|
||||||
|
/* Headers from archopenfpga library */
|
||||||
|
#include "openfpga_naming.h"
|
||||||
|
|
||||||
|
#include "openfpga_version.h"
|
||||||
|
|
||||||
|
#include "build_io_mapping_info.h"
|
||||||
|
#include "write_xml_io_mapping.h"
|
||||||
|
|
||||||
|
/* begin namespace openfpga */
|
||||||
|
namespace openfpga {
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* This function write header information to an I/O mapping file
|
||||||
|
*******************************************************************/
|
||||||
|
static
|
||||||
|
void write_io_mapping_xml_file_head(std::fstream& fp) {
|
||||||
|
valid_file_stream(fp);
|
||||||
|
|
||||||
|
auto end = std::chrono::system_clock::now();
|
||||||
|
std::time_t end_time = std::chrono::system_clock::to_time_t(end);
|
||||||
|
|
||||||
|
fp << "<!--" << std::endl;
|
||||||
|
fp << "\t- I/O mapping" << std::endl;
|
||||||
|
fp << "\t- Version: " << openfpga::VERSION << std::endl;
|
||||||
|
fp << "\t- Date: " << std::ctime(&end_time) ;
|
||||||
|
fp << "-->" << std::endl;
|
||||||
|
fp << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* Write an io mapping pair to an XML file
|
||||||
|
*
|
||||||
|
* Return:
|
||||||
|
* - 0 if succeed
|
||||||
|
* - 1 if critical errors occured
|
||||||
|
*******************************************************************/
|
||||||
|
static
|
||||||
|
int write_io_mapping_pair_to_xml_file(std::fstream& fp,
|
||||||
|
const IoMap& io_map,
|
||||||
|
const IoMapId& io_map_id,
|
||||||
|
int xml_hierarchy_depth) {
|
||||||
|
if (false == valid_file_stream(fp)) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
write_tab_to_file(fp, xml_hierarchy_depth);
|
||||||
|
|
||||||
|
BasicPort io_port = io_map.io_port(io_map_id);
|
||||||
|
fp << "<io ";
|
||||||
|
fp << "name=\"" << io_port.get_name().c_str() << "[" << io_port.get_lsb() << ":" << io_port.get_msb() << "]" << "\"";
|
||||||
|
|
||||||
|
VTR_ASSERT(1 == io_map.io_net(io_map_id).get_width());
|
||||||
|
fp << " net=\"" << io_map.io_net(io_map_id).get_name().c_str() << "\"";
|
||||||
|
|
||||||
|
if (io_map.is_io_input(io_map_id)) {
|
||||||
|
fp << " dir=\"" << "input" << "\"";
|
||||||
|
} else {
|
||||||
|
VTR_ASSERT_SAFE(io_map.is_io_output(io_map_id));
|
||||||
|
fp << " dir=\"" << "output" << "\"";
|
||||||
|
}
|
||||||
|
|
||||||
|
fp << "/>\n";
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* Write the io mapping information to an XML file
|
||||||
|
* Notes:
|
||||||
|
* - This file is designed for users to learn
|
||||||
|
* - what nets are mapped to each I/O is mapped, io[0] -> netA
|
||||||
|
* - what directionality is applied to each I/O, io[0] -> input
|
||||||
|
*
|
||||||
|
* Return:
|
||||||
|
* - 0 if succeed
|
||||||
|
* - 1 if critical errors occured
|
||||||
|
*******************************************************************/
|
||||||
|
int write_io_mapping_to_xml_file(const IoMap& io_map,
|
||||||
|
const std::string& fname,
|
||||||
|
const bool& verbose) {
|
||||||
|
/* Ensure that we have a valid file name */
|
||||||
|
if (true == fname.empty()) {
|
||||||
|
VTR_LOG_ERROR("Received empty file name to output io_mapping!\n\tPlease specify a valid file name.\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string timer_message = std::string("Write I/O mapping into xml file '") + fname + std::string("'");
|
||||||
|
vtr::ScopedStartFinishTimer timer(timer_message);
|
||||||
|
|
||||||
|
/* Create the file stream */
|
||||||
|
std::fstream fp;
|
||||||
|
fp.open(fname, std::fstream::out | std::fstream::trunc);
|
||||||
|
|
||||||
|
check_file_stream(fname.c_str(), fp);
|
||||||
|
|
||||||
|
/* Write XML head */
|
||||||
|
write_io_mapping_xml_file_head(fp);
|
||||||
|
|
||||||
|
int xml_hierarchy_depth = 0;
|
||||||
|
fp << "<io_mapping>\n";
|
||||||
|
|
||||||
|
/* Output fabric bitstream to the file */
|
||||||
|
int status = 0;
|
||||||
|
int io_map_cnt = 0;
|
||||||
|
for (const auto& io_map_id : io_map.io_map()) {
|
||||||
|
status = write_io_mapping_pair_to_xml_file(fp,
|
||||||
|
io_map, io_map_id,
|
||||||
|
xml_hierarchy_depth + 1);
|
||||||
|
io_map_cnt++;
|
||||||
|
if (1 == status) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Print an end to the file here */
|
||||||
|
fp << "</io_mapping>\n";
|
||||||
|
|
||||||
|
VTR_LOGV(verbose,
|
||||||
|
"Outputted %d I/O mapping to file '%s'\n",
|
||||||
|
io_map_cnt,
|
||||||
|
fname.c_str());
|
||||||
|
|
||||||
|
/* Close file handler */
|
||||||
|
fp.close();
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
} /* end namespace openfpga */
|
|
@ -0,0 +1,25 @@
|
||||||
|
#ifndef WRITE_XML_IO_MAPPING_H
|
||||||
|
#define WRITE_XML_IO_MAPPING_H
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* Include header files that are required by function declaration
|
||||||
|
*******************************************************************/
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include "vpr_context.h"
|
||||||
|
#include "io_map.h"
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* Function declaration
|
||||||
|
*******************************************************************/
|
||||||
|
|
||||||
|
/* begin namespace openfpga */
|
||||||
|
namespace openfpga {
|
||||||
|
|
||||||
|
int write_io_mapping_to_xml_file(const IoMap& io_map,
|
||||||
|
const std::string& fname,
|
||||||
|
const bool& verbose);
|
||||||
|
|
||||||
|
} /* end namespace openfpga */
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,38 @@
|
||||||
|
# Run VPR for the 'and' design
|
||||||
|
#--write_rr_graph example_rr_graph.xml
|
||||||
|
vpr ${VPR_ARCH_FILE} ${VPR_TESTBENCH_BLIF} --clock_modeling route --absorb_buffer_luts off
|
||||||
|
|
||||||
|
# Read OpenFPGA architecture definition
|
||||||
|
read_openfpga_arch -f ${OPENFPGA_ARCH_FILE}
|
||||||
|
|
||||||
|
# Read OpenFPGA simulation settings
|
||||||
|
read_openfpga_simulation_setting -f ${OPENFPGA_SIM_SETTING_FILE}
|
||||||
|
|
||||||
|
# Annotate the OpenFPGA architecture to VPR data base
|
||||||
|
# to debug use --verbose options
|
||||||
|
link_openfpga_arch --activity_file ${ACTIVITY_FILE} --sort_gsb_chan_node_in_edges
|
||||||
|
|
||||||
|
# Check and correct any naming conflicts in the BLIF netlist
|
||||||
|
check_netlist_naming_conflict --fix --report ./netlist_renaming.xml
|
||||||
|
|
||||||
|
# Apply fix-up to clustering nets based on routing results
|
||||||
|
pb_pin_fixup --verbose
|
||||||
|
|
||||||
|
# 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
|
||||||
|
# - Enabled frame view creation to save runtime and memory
|
||||||
|
# Note that this is turned on when bitstream generation
|
||||||
|
# is the ONLY purpose of the flow!!!
|
||||||
|
build_fabric --compress_routing --frame_view #--verbose
|
||||||
|
|
||||||
|
# Write I/O net mapping information
|
||||||
|
write_io_mapping --file io_mapping.xml --verbose
|
||||||
|
|
||||||
|
# Finish and exit OpenFPGA
|
||||||
|
exit
|
||||||
|
|
||||||
|
# Note :
|
||||||
|
# To run verification at the end of the flow maintain source in ./SRC directory
|
|
@ -25,3 +25,6 @@ run-task fpga_bitstream/repack_wire_lut --debug --show_thread_logs
|
||||||
|
|
||||||
echo -e "Testing overloading default paths for programmable interconnect when generating bitstream";
|
echo -e "Testing overloading default paths for programmable interconnect when generating bitstream";
|
||||||
run-task fpga_bitstream/overload_mux_default_path --debug --show_thread_logs
|
run-task fpga_bitstream/overload_mux_default_path --debug --show_thread_logs
|
||||||
|
|
||||||
|
echo -e "Testing outputting I/O mapping result to file";
|
||||||
|
run-task fpga_bitstream/write_io_mapping --debug --show_thread_logs
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
|
||||||
|
# Configuration file for running experiments
|
||||||
|
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
|
||||||
|
# timeout_each_job : FPGA Task script splits fpga flow into multiple jobs
|
||||||
|
# Each job execute fpga_flow script on combination of architecture & benchmark
|
||||||
|
# timeout_each_job is timeout for each job
|
||||||
|
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
|
||||||
|
|
||||||
|
[GENERAL]
|
||||||
|
run_engine=openfpga_shell
|
||||||
|
power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml
|
||||||
|
power_analysis = true
|
||||||
|
spice_output=false
|
||||||
|
verilog_output=true
|
||||||
|
timeout_each_job = 20*60
|
||||||
|
fpga_flow=yosys_vpr
|
||||||
|
|
||||||
|
[OpenFPGA_SHELL]
|
||||||
|
openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/write_io_mapping_example_script.openfpga
|
||||||
|
openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k6_frac_N10_40nm_openfpga.xml
|
||||||
|
openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml
|
||||||
|
|
||||||
|
[ARCHITECTURES]
|
||||||
|
arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k6_frac_N10_tileable_40nm.xml
|
||||||
|
|
||||||
|
[BENCHMARKS]
|
||||||
|
bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.v
|
||||||
|
|
||||||
|
[SYNTHESIS_PARAM]
|
||||||
|
bench0_top = and2
|
||||||
|
|
||||||
|
[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH]
|
Loading…
Reference in New Issue