diff --git a/docs/source/manual/file_formats/index.rst b/docs/source/manual/file_formats/index.rst index f02218cd3..d1a77e2d0 100644 --- a/docs/source/manual/file_formats/index.rst +++ b/docs/source/manual/file_formats/index.rst @@ -21,3 +21,5 @@ OpenFPGA widely uses XML format for interchangable files bitstream_setting fabric_key + + io_mapping_file diff --git a/docs/source/manual/file_formats/io_mapping_file.rst b/docs/source/manual/file_formats/io_mapping_file.rst new file mode 100644 index 000000000..722f477f6 --- /dev/null +++ b/docs/source/manual/file_formats/io_mapping_file.rst @@ -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 + + + + + + + +.. option:: name="" + + 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="" + + The net name which is actually mapped to a pin, which should be consistent with net definition in your ``.blif`` file. + +.. option:: dir="" + + The direction of an I/O, which can be either ``input`` or ``output``. diff --git a/docs/source/manual/openfpga_shell/openfpga_commands/fpga_bitstream_commands.rst b/docs/source/manual/openfpga_shell/openfpga_commands/fpga_bitstream_commands.rst index d2461b5ef..fbe10e033 100644 --- a/docs/source/manual/openfpga_shell/openfpga_commands/fpga_bitstream_commands.rst +++ b/docs/source/manual/openfpga_shell/openfpga_commands/fpga_bitstream_commands.rst @@ -72,3 +72,19 @@ write_fabric_bitstream .. option:: --verbose Show verbose log + +write_io_mapping +~~~~~~~~~~~~~~~~ + + Output the I/O mapping information to a file + + .. option:: --file or -f + + 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 + + diff --git a/openfpga/src/base/io_map.cpp b/openfpga/src/base/io_map.cpp new file mode 100644 index 000000000..3012c4285 --- /dev/null +++ b/openfpga/src/base/io_map.cpp @@ -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 */ diff --git a/openfpga/src/base/io_map.h b/openfpga/src/base/io_map.h new file mode 100644 index 000000000..5bc378000 --- /dev/null +++ b/openfpga/src/base/io_map.h @@ -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::const_iterator io_map_iterator; + typedef vtr::Range 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 io_map_ids_; + vtr::vector io_ports_; + vtr::vector mapped_nets_; + vtr::vector io_directionality_; +}; + +} /* End namespace openfpga*/ + +#endif diff --git a/openfpga/src/base/io_map_fwd.h b/openfpga/src/base/io_map_fwd.h new file mode 100644 index 000000000..0de3e99c1 --- /dev/null +++ b/openfpga/src/base/io_map_fwd.h @@ -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 IoMapId; + +class IoMap; + +} /* end namespace openfpga */ + +#endif diff --git a/openfpga/src/base/openfpga_bitstream.cpp b/openfpga/src/base/openfpga_bitstream.cpp index c32e9ae87..c35017ba8 100644 --- a/openfpga/src/base/openfpga_bitstream.cpp +++ b/openfpga/src/base/openfpga_bitstream.cpp @@ -15,10 +15,14 @@ #include "read_xml_arch_bitstream.h" #include "write_xml_arch_bitstream.h" +#include "openfpga_naming.h" + #include "build_device_bitstream.h" #include "write_text_fabric_bitstream.h" #include "write_xml_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 global variables of VPR */ @@ -121,4 +125,44 @@ int write_fabric_bitstream(const OpenfpgaContext& openfpga_ctx, 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 */ diff --git a/openfpga/src/base/openfpga_bitstream.h b/openfpga/src/base/openfpga_bitstream.h index c210d6bab..2e438d56b 100644 --- a/openfpga/src/base/openfpga_bitstream.h +++ b/openfpga/src/base/openfpga_bitstream.h @@ -24,6 +24,9 @@ int build_fabric_bitstream(OpenfpgaContext& openfpga_ctx, int write_fabric_bitstream(const OpenfpgaContext& openfpga_ctx, 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 */ #endif diff --git a/openfpga/src/base/openfpga_bitstream_command.cpp b/openfpga/src/base/openfpga_bitstream_command.cpp index 6b7397a1c..3599bcac5 100644 --- a/openfpga/src/base/openfpga_bitstream_command.cpp +++ b/openfpga/src/base/openfpga_bitstream_command.cpp @@ -131,6 +131,36 @@ ShellCommandId add_openfpga_write_fabric_bitstream_command(openfpga::Shell& shell, + const ShellCommandClassId& cmd_class_id, + const std::vector& 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 *******************************************************************/ @@ -172,6 +202,14 @@ void add_openfpga_bitstream_commands(openfpga::Shell& shell) { std::vector cmd_dependency_write_fabric_bitstream; 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); + + /******************************** + * Command 'write_io_mapping' + */ + /* The 'write_io_mapping' command should NOT be executed before 'build_fabric' */ + std::vector 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 */ diff --git a/openfpga/src/fpga_bitstream/build_io_mapping_info.cpp b/openfpga/src/fpga_bitstream/build_io_mapping_info.cpp new file mode 100644 index 000000000..76fbda9a2 --- /dev/null +++ b/openfpga/src/fpga_bitstream/build_io_mapping_info.cpp @@ -0,0 +1,144 @@ +/******************************************************************** + * This file includes functions that build io mapping information + *******************************************************************/ +#include +#include +#include + +/* 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 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 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 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 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 */ diff --git a/openfpga/src/fpga_bitstream/build_io_mapping_info.h b/openfpga/src/fpga_bitstream/build_io_mapping_info.h new file mode 100644 index 000000000..615fafdd8 --- /dev/null +++ b/openfpga/src/fpga_bitstream/build_io_mapping_info.h @@ -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 +#include +#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 diff --git a/openfpga/src/fpga_bitstream/write_xml_io_mapping.cpp b/openfpga/src/fpga_bitstream/write_xml_io_mapping.cpp new file mode 100644 index 000000000..5b3f383b1 --- /dev/null +++ b/openfpga/src/fpga_bitstream/write_xml_io_mapping.cpp @@ -0,0 +1,145 @@ +/******************************************************************** + * This file includes functions that output io mapping information + * to files in XML format + *******************************************************************/ +#include +#include +#include + +/* 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 << 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 << "\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 << "\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 << "\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 */ diff --git a/openfpga/src/fpga_bitstream/write_xml_io_mapping.h b/openfpga/src/fpga_bitstream/write_xml_io_mapping.h new file mode 100644 index 000000000..330106141 --- /dev/null +++ b/openfpga/src/fpga_bitstream/write_xml_io_mapping.h @@ -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 +#include +#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 diff --git a/openfpga_flow/openfpga_shell_scripts/write_io_mapping_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/write_io_mapping_example_script.openfpga new file mode 100644 index 000000000..62735f8bd --- /dev/null +++ b/openfpga_flow/openfpga_shell_scripts/write_io_mapping_example_script.openfpga @@ -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 diff --git a/openfpga_flow/regression_test_scripts/fpga_bitstream_reg_test.sh b/openfpga_flow/regression_test_scripts/fpga_bitstream_reg_test.sh index db692c002..1f1eac786 100755 --- a/openfpga_flow/regression_test_scripts/fpga_bitstream_reg_test.sh +++ b/openfpga_flow/regression_test_scripts/fpga_bitstream_reg_test.sh @@ -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"; 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 diff --git a/openfpga_flow/tasks/fpga_bitstream/write_io_mapping/config/task.conf b/openfpga_flow/tasks/fpga_bitstream/write_io_mapping/config/task.conf new file mode 100644 index 000000000..a61ec038b --- /dev/null +++ b/openfpga_flow/tasks/fpga_bitstream/write_io_mapping/config/task.conf @@ -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]