From 8bd9ae02fdd51c978e463120739850f6e8ab2b1f Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 23 Jun 2023 11:09:33 -0700 Subject: [PATCH] [core] io name map now supports dummy port direction --- libs/libionamemap/src/base/io_name_map.cpp | 56 ++++++++++++++----- libs/libionamemap/src/base/io_name_map.h | 32 +++++++---- .../src/io/io_name_map_xml_constants.h | 4 +- .../src/io/read_xml_io_name_map.cpp | 10 +++- .../src/io/write_xml_io_name_map.cpp | 4 ++ .../src/base/openfpga_build_fabric_template.h | 8 ++- .../fabric/build_fpga_core_wrapper_module.cpp | 54 ++++++++++-------- .../fabric/build_fpga_core_wrapper_module.h | 5 +- 8 files changed, 116 insertions(+), 57 deletions(-) diff --git a/libs/libionamemap/src/base/io_name_map.cpp b/libs/libionamemap/src/base/io_name_map.cpp index 0ab9069be..88d153c35 100644 --- a/libs/libionamemap/src/base/io_name_map.cpp +++ b/libs/libionamemap/src/base/io_name_map.cpp @@ -119,7 +119,8 @@ bool IoNameMap::fpga_top_port_is_dummy(const BasicPort& fpga_top_port) const { return !fpga_core_port(fpga_top_port).is_valid(); } -IoNameMap::e_dummy_port_direction IoNameMap::fpga_top_dummy_port_direction(const BasicPort& fpga_top_port) const { +IoNameMap::e_dummy_port_direction IoNameMap::fpga_top_dummy_port_direction( + const BasicPort& fpga_top_port) const { for (auto& kv : dummy_port_direction_) { BasicPort cand = str2port(kv.first); if (cand.contained(fpga_top_port)) { @@ -131,7 +132,9 @@ IoNameMap::e_dummy_port_direction IoNameMap::fpga_top_dummy_port_direction(const } bool IoNameMap::empty() const { - return top2core_io_name_keys_.empty() && top2core_io_name_map_.empty() && core2top_io_name_keys_.empty() && core2top_io_name_map_.empty() && dummy_port_direction_.empty(); + return top2core_io_name_keys_.empty() && top2core_io_name_map_.empty() && + core2top_io_name_keys_.empty() && core2top_io_name_map_.empty() && + dummy_port_direction_.empty(); } int IoNameMap::set_io_pair(const BasicPort& fpga_top_port, @@ -203,7 +206,8 @@ int IoNameMap::set_io_pair(const BasicPort& fpga_top_port, return CMD_EXEC_SUCCESS; } -int IoNameMap::set_dummy_io(const BasicPort& fpga_top_port, const e_dummy_port_direction& direction) { +int IoNameMap::set_dummy_io(const BasicPort& fpga_top_port, + const e_dummy_port_direction& direction) { /* Must be a true dummy port, none of its pins have been paired! */ std::string top_port_str = port2str(fpga_top_port); /* First, find the pin name matching */ @@ -236,7 +240,8 @@ int IoNameMap::set_dummy_io(const BasicPort& fpga_top_port, const e_dummy_port_d if (kv.second != direction) { /* Throw a error because the dummy pin should NOT be mapped before! */ VTR_LOG_ERROR( - "Dummy port '%s' of fpga_top is already assigned to a different direction through another dummy port definition '%s'!\n", + "Dummy port '%s' of fpga_top is already assigned to a different " + "direction through another dummy port definition '%s'!\n", port2str(fpga_top_port).c_str(), port2str(cand).c_str()); return CMD_EXEC_FATAL_ERROR; } @@ -246,7 +251,7 @@ int IoNameMap::set_dummy_io(const BasicPort& fpga_top_port, const e_dummy_port_d } if (!dir_defined) { dummy_port_direction_[top_port_str] = direction; - } + } return CMD_EXEC_SUCCESS; } @@ -258,20 +263,43 @@ BasicPort IoNameMap::str2port(const std::string& port_str) const { return PortParser(port_str).port(); } -IoNameMap::e_dummy_port_direction IoNameMap::str2dummy_port_dir(const std::string& dir_str, const bool& verbose) const { - for (int itype = IoNameMap::e_dummy_port_direction::INPUT; itype != IoNameMap::e_dummy_direction::NUM_TYPES; ++itype) { - if (dir_str == std::string(DUMMY_PORT_DIR_STRING_[itype])) { - return static_case(itype); - } - } +std::string IoNameMap::dummy_port_dir_all2str() const { std::string full_types = "["; - for (int itype = IoNameMap::e_dummy_port_direction::INPUT; itype != IoNameMap::e_dummy_direction::NUM_TYPES; ++itype) { + for (int itype = size_t(IoNameMap::e_dummy_port_direction::INPUT); + itype != size_t(IoNameMap::e_dummy_port_direction::NUM_TYPES); ++itype) { full_types += std::string(DUMMY_PORT_DIR_STRING_[itype]) + std::string("|"); - } + } full_types.pop_back(); full_types += "]"; - VTR_LOGV_ERROR(verbose, "Invalid direction for dummy port! Expect %s\n", full_types.c_str()); + return full_types; +} + +IoNameMap::e_dummy_port_direction IoNameMap::str2dummy_port_dir( + const std::string& dir_str, const bool& verbose) const { + for (int itype = size_t(IoNameMap::e_dummy_port_direction::INPUT); + itype != size_t(IoNameMap::e_dummy_port_direction::NUM_TYPES); ++itype) { + if (dir_str == std::string(DUMMY_PORT_DIR_STRING_[itype])) { + return static_cast(itype); + } + } + VTR_LOGV_ERROR(verbose, "Invalid direction for dummy port! Expect %s\n", + dummy_port_dir_all2str().c_str()); return IoNameMap::e_dummy_port_direction::NUM_TYPES; } +std::string IoNameMap::dummy_port_dir2str(const e_dummy_port_direction& dir, + const bool& verbose) const { + if (!valid_dummy_port_direction(dir)) { + VTR_LOGV_ERROR(verbose, "Invalid direction for dummy port! Expect %s\n", + dummy_port_dir_all2str().c_str()); + return std::string(); + } + return std::string(DUMMY_PORT_DIR_STRING_[size_t(dir)]); +} + +bool IoNameMap::valid_dummy_port_direction( + const IoNameMap::e_dummy_port_direction& direction) const { + return direction != IoNameMap::e_dummy_port_direction::NUM_TYPES; +} + } /* end namespace openfpga */ diff --git a/libs/libionamemap/src/base/io_name_map.h b/libs/libionamemap/src/base/io_name_map.h index 1db529dec..fb24772e5 100644 --- a/libs/libionamemap/src/base/io_name_map.h +++ b/libs/libionamemap/src/base/io_name_map.h @@ -20,12 +20,8 @@ namespace openfpga { */ class IoNameMap { public: /* Types */ - enum class e_dummy_port_direction { - INPUT = 0, - OUTPUT, - INOUT, - NUM_TYPES - }; + enum class e_dummy_port_direction { INPUT = 0, OUTPUT, INOUT, NUM_TYPES }; + public: /* Public accessors */ /** @brief Get all the fpga top ports */ std::vector fpga_top_ports() const; @@ -38,7 +34,8 @@ class IoNameMap { /** @brief Identify if the fpga_top port is dummy or not */ bool fpga_top_port_is_dummy(const BasicPort& fpga_top_port) const; /** @brief Get the direction of a dummy port */ - e_dummy_port_direction fpga_top_dummy_port_direction(const BasicPort& fpga_top_port) const; + e_dummy_port_direction fpga_top_dummy_port_direction( + const BasicPort& fpga_top_port) const; /** @brief Identify if there are any naming rules inside */ bool empty() const; @@ -49,17 +46,29 @@ class IoNameMap { const BasicPort& fpga_core_port); /** @brief Add a dummy port at the fpga top, which is not mapped any port at * fpga_core */ - int set_dummy_io(const BasicPort& fpga_top_port, const e_dummy_port_direction& direction); + int set_dummy_io(const BasicPort& fpga_top_port, + const e_dummy_port_direction& direction); public: /* Public utility */ - /** @brief Parse the dummy port direction from string to valid type. Parser error can be turned on */ - e_dummy_port_direction str2dummy_port_dir(const std::string& dir_str, const bool& verbose = false) const; + /** @brief Parse the dummy port direction from string to valid type. Parser + * error can be turned on */ + e_dummy_port_direction str2dummy_port_dir(const std::string& dir_str, + const bool& verbose = false) const; + /** @brief Output the string representing dummy port direction */ + std::string dummy_port_dir2str(const e_dummy_port_direction& dir, + const bool& verbose = false) const; + /** @brief Validate the dummy port direction */ + bool valid_dummy_port_direction( + const e_dummy_port_direction& direction) const; private: /* Internal utility */ /* Convert a port info to string, which can be used to store keys */ std::string port2str(const BasicPort& port) const; /* Convert a string to port, which can be used to echo internal info */ BasicPort str2port(const std::string& port_str) const; + /* Generate a string include all the valid directions of the dummy port. + * Useful for printing debugging messages */ + std::string dummy_port_dir_all2str() const; private: /* Internal Data */ /* fpga_top -> fpga_core io_name_keys. Use the port name to find all the port @@ -76,7 +85,8 @@ class IoNameMap { std::map dummy_port_direction_; /* Constants */ - std::array DUMMY_PORT_DIR_STRING_; + std::array + DUMMY_PORT_DIR_STRING_; }; } /* End namespace openfpga*/ diff --git a/libs/libionamemap/src/io/io_name_map_xml_constants.h b/libs/libionamemap/src/io/io_name_map_xml_constants.h index 199be5305..f7d7fe74e 100644 --- a/libs/libionamemap/src/io/io_name_map_xml_constants.h +++ b/libs/libionamemap/src/io/io_name_map_xml_constants.h @@ -10,6 +10,8 @@ constexpr const char* XML_IO_NAME_MAP_ATTRIBUTE_CORE_NAME = "core_name"; constexpr const char* XML_IO_NAME_MAP_ATTRIBUTE_IS_DUMMY = "is_dummy"; constexpr const char* XML_IO_NAME_MAP_ATTRIBUTE_DIRECTION = "direction"; -constexpr std::array XML_IO_NAME_MAP_DUMMY_PORT_DIRECTION_STRING = {{"input", "output", "inout"}}; //String versions of side orientations +constexpr std::array + XML_IO_NAME_MAP_DUMMY_PORT_DIRECTION_STRING = { + {"input", "output", "inout"}}; // String versions of side orientations #endif diff --git a/libs/libionamemap/src/io/read_xml_io_name_map.cpp b/libs/libionamemap/src/io/read_xml_io_name_map.cpp index 1c9f40437..4fc9f231a 100644 --- a/libs/libionamemap/src/io/read_xml_io_name_map.cpp +++ b/libs/libionamemap/src/io/read_xml_io_name_map.cpp @@ -11,6 +11,7 @@ /* Headers from vtr util library */ #include "vtr_assert.h" +#include "vtr_log.h" #include "vtr_time.h" /* Headers from libopenfpga util library */ @@ -45,12 +46,15 @@ static int read_xml_io_map_port(pugi::xml_node& xml_port, std::string dir_str = get_attribute(xml_port, XML_IO_NAME_MAP_ATTRIBUTE_DIRECTION, loc_data) .as_string(); - IoNameMap::e_dummy_port_direction dummy_port_dir = io_name_map.str2dummy_port_dir(dir_str, true); + IoNameMap::e_dummy_port_direction dummy_port_dir = + io_name_map.str2dummy_port_dir(dir_str, true); if (!io_name_map.valid_dummy_port_direction(dummy_port_dir)) { - VTR_LOG_ERROR("Invalid direction for dummy port '%s'!\n", top_port.to_verilog_string().c_str()); + VTR_LOG_ERROR("Invalid direction for dummy port '%s'!\n", + top_port.to_verilog_string().c_str()); return CMD_EXEC_FATAL_ERROR; } - return io_name_map.set_dummy_io(top_port, dummy_port_dir); /* Early return */ + return io_name_map.set_dummy_io(top_port, + dummy_port_dir); /* Early return */ } /* This is not a dummy io, create the io mapping */ diff --git a/libs/libionamemap/src/io/write_xml_io_name_map.cpp b/libs/libionamemap/src/io/write_xml_io_name_map.cpp index 951aaabc3..2b52f7a23 100644 --- a/libs/libionamemap/src/io/write_xml_io_name_map.cpp +++ b/libs/libionamemap/src/io/write_xml_io_name_map.cpp @@ -44,6 +44,10 @@ static int write_xml_io_map_port(std::fstream& fp, const IoNameMap& io_name_map, if (io_name_map.fpga_top_port_is_dummy(fpga_top_port)) { write_xml_attribute(fp, XML_IO_NAME_MAP_ATTRIBUTE_IS_DUMMY, "true"); + IoNameMap::e_dummy_port_direction dir = + io_name_map.fpga_top_dummy_port_direction(fpga_top_port); + write_xml_attribute(fp, XML_IO_NAME_MAP_ATTRIBUTE_DIRECTION, + io_name_map.dummy_port_dir2str(dir, true).c_str()); } else { BasicPort fpga_core_port = io_name_map.fpga_core_port(fpga_top_port); write_xml_attribute(fp, XML_IO_NAME_MAP_ATTRIBUTE_CORE_NAME, diff --git a/openfpga/src/base/openfpga_build_fabric_template.h b/openfpga/src/base/openfpga_build_fabric_template.h index df6cb68a5..51ee39b07 100644 --- a/openfpga/src/base/openfpga_build_fabric_template.h +++ b/openfpga/src/base/openfpga_build_fabric_template.h @@ -6,6 +6,7 @@ #include "build_device_module.h" #include "build_fabric_global_port_info.h" #include "build_fabric_io_location_map.h" +#include "build_fpga_core_wrapper_module.h" #include "command.h" #include "command_context.h" #include "command_exit_codes.h" @@ -254,12 +255,13 @@ int add_fpga_core_to_fabric_template(T& openfpga_ctx, const Command& cmd, IoNameMap io_name_map; CommandOptionId opt_io_naming = cmd.option("io_naming"); if (true == cmd_context.option_enable(cmd, opt_io_naming)) { - read_xml_io_name_map(cmd_context.option_value(cmd, opt_io_naming), io_name_map); + read_xml_io_name_map(cmd_context.option_value(cmd, opt_io_naming).c_str(), + io_name_map); } return add_fpga_core_to_device_module_graph( - openfpga_ctx.mutable_module_graph(), io_name_map, core_inst_name, frame_view, - verbose_output); + openfpga_ctx.mutable_module_graph(), io_name_map, core_inst_name, + frame_view, verbose_output); } } /* end namespace openfpga */ diff --git a/openfpga/src/fabric/build_fpga_core_wrapper_module.cpp b/openfpga/src/fabric/build_fpga_core_wrapper_module.cpp index b36b690fb..7aa741dde 100644 --- a/openfpga/src/fabric/build_fpga_core_wrapper_module.cpp +++ b/openfpga/src/fabric/build_fpga_core_wrapper_module.cpp @@ -9,9 +9,9 @@ #include "vtr_time.h" /* Headers from openfpgashell library */ +#include "build_fpga_core_wrapper_module.h" #include "command_exit_codes.h" #include "openfpga_naming.h" -#include "build_fpga_core_wrapper_module.h" /* begin namespace openfpga */ namespace openfpga { @@ -19,14 +19,10 @@ namespace openfpga { /******************************************************************** * Create a custom fpga_top module by applying naming rules *******************************************************************/ -static -int create_fpga_top_module_using_naming_rules(ModuleManager& module_manager, - const ModuleId& core_module, - const std::string& top_module_name, - const IoNameMap& io_naming, - const std::string& instance_name, - const bool& add_nets, - const bool& verbose) { +static int create_fpga_top_module_using_naming_rules( + ModuleManager& module_manager, const ModuleId& core_module, + const std::string& top_module_name, const IoNameMap& io_naming, + const std::string& instance_name, const bool& add_nets, const bool& verbose) { /* Create a new module with the given name */ ModuleId wrapper_module = module_manager.add_module(top_module_name); if (!wrapper_module) { @@ -34,41 +30,50 @@ int create_fpga_top_module_using_naming_rules(ModuleManager& module_manager, } /* Add the existing module as an instance */ module_manager.add_child_module(wrapper_module, core_module, false); - module_manager.set_child_instance_name(wrapper_module, core_module, 0, instance_name); + module_manager.set_child_instance_name(wrapper_module, core_module, 0, + instance_name); /* TODO: Add ports from I/O naming rules: * - Add ports which has been defined in the naming rules * - Add ports from the core module, which does not appear in the naming rules */ for (BasicPort top_port : io_naming.fpga_top_ports()) { - /* For dummy port, just add it. Port type should be defined from io naming rules */ + /* For dummy port, just add it. Port type should be defined from io naming + * rules */ if (io_naming.fpga_top_port_is_dummy(top_port)) { - ModuleManager::e_module_port_type port_type = ModuleManager::e_module_port_type::MODULE_INOUT_PORT; - if (IoNameMap::e_dummy_port_direction::INPUT == io_naming.fpga_top_dummy_port_direction(top_port)) { + ModuleManager::e_module_port_type port_type = + ModuleManager::e_module_port_type::MODULE_INOUT_PORT; + if (IoNameMap::e_dummy_port_direction::INPUT == + io_naming.fpga_top_dummy_port_direction(top_port)) { port_type = ModuleManager::e_module_port_type::MODULE_INPUT_PORT; - } else if (IoNameMap::e_dummy_port_direction::OUTPUT == io_naming.fpga_top_dummy_port_direction(top_port)) { + } else if (IoNameMap::e_dummy_port_direction::OUTPUT == + io_naming.fpga_top_dummy_port_direction(top_port)) { port_type = ModuleManager::e_module_port_type::MODULE_OUTPUT_PORT; - } else if (IoNameMap::e_dummy_port_direction::INOUT == io_naming.fpga_top_dummy_port_direction(top_port)); + } else if (IoNameMap::e_dummy_port_direction::INOUT == + io_naming.fpga_top_dummy_port_direction(top_port)) { port_type = ModuleManager::e_module_port_type::MODULE_INOUT_PORT; } else { - VTR_LOG_ERROR("fpga_top dummy port '%s' has an invalid direction. Expect [input|output|inout]!\n", top_port.to_verilog_string().c_str()); + VTR_LOG_ERROR( + "fpga_top dummy port '%s' has an invalid direction. Expect " + "[input|output|inout]!\n", + top_port.to_verilog_string().c_str()); return CMD_EXEC_FATAL_ERROR; - } + } module_manager.add_port(wrapper_module, top_port, port_type); continue; /* Finish for this port addition */ } /* Get the port type which should be same as the fpga_core port */ - BasicPort core_port : io_naming.fpga_core_port(top_port); + BasicPort core_port = io_naming.fpga_core_port(top_port); if (!core_port.is_valid()) { - VTR_LOG_ERROR("fpga_top port '%s' is not mapped to any fpga_core port!\n", core_port.to_verilog_string().c_str()); + VTR_LOG_ERROR("fpga_top port '%s' is not mapped to any fpga_core port!\n", + core_port.to_verilog_string().c_str()); return CMD_EXEC_FATAL_ERROR; } - //module_manager.add_port(wrapper_module, top_port, ); + // module_manager.add_port(wrapper_module, top_port, ); } /* TODO: Add nets */ if (add_nets) { - } /* TODO: Update the fabric global ports */ @@ -103,7 +108,8 @@ int add_fpga_core_to_device_module_graph(ModuleManager& module_manager, top_module_name.c_str(), core_module_name.c_str()); /* Create a wrapper module under the existing fpga_top - * - if there are no io naming rules, just use the default API to create a wrapper + * - if there are no io naming rules, just use the default API to create a + * wrapper * - if there are io naming rules, use dedicated function to handle */ ModuleId new_top_module; @@ -117,7 +123,9 @@ int add_fpga_core_to_device_module_graph(ModuleManager& module_manager, return CMD_EXEC_FATAL_ERROR; } } else { - status = create_fpga_top_module_using_naming_rules(module_manager, top_module, top_module_name, io_naming, core_inst_name, !frame_view, verbose); + status = create_fpga_top_module_using_naming_rules( + module_manager, top_module, top_module_name, io_naming, core_inst_name, + !frame_view, verbose); if (CMD_EXEC_SUCCESS != status) { return CMD_EXEC_FATAL_ERROR; } diff --git a/openfpga/src/fabric/build_fpga_core_wrapper_module.h b/openfpga/src/fabric/build_fpga_core_wrapper_module.h index 1ba1fcbfb..3520f6d8b 100644 --- a/openfpga/src/fabric/build_fpga_core_wrapper_module.h +++ b/openfpga/src/fabric/build_fpga_core_wrapper_module.h @@ -4,10 +4,11 @@ /******************************************************************** * Include header files that are required by function declaration *******************************************************************/ -#include "module_manager.h" -#include "io_name_map.h" #include +#include "io_name_map.h" +#include "module_manager.h" + /******************************************************************** * Function declaration *******************************************************************/