From 0a94763422523247e018a5f865025b810bcc10aa Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 22 Sep 2023 18:16:01 -0700 Subject: [PATCH] [lib] add module rename assistant --- .../src/base/module_name_map.cpp | 15 ++ .../libnamemanager/src/base/module_name_map.h | 6 + .../test/module_rename_assistant.cpp | 159 ++++++++++++++++++ 3 files changed, 180 insertions(+) create mode 100644 libs/libnamemanager/test/module_rename_assistant.cpp diff --git a/libs/libnamemanager/src/base/module_name_map.cpp b/libs/libnamemanager/src/base/module_name_map.cpp index d0024b346b..606dcc25c9 100644 --- a/libs/libnamemanager/src/base/module_name_map.cpp +++ b/libs/libnamemanager/src/base/module_name_map.cpp @@ -32,6 +32,21 @@ bool ModuleNameMap::name_exist(const std::string& tag) const { return result != tag2names_.end(); } +std::string ModuleNameMap::tag(const std::string& name) const { + auto result = name2tags_.find(name); + if (result == name2tags_.end()) { + VTR_LOG_ERROR("The given customized name '%s' does not exist!\n", + name.c_str()); + return std::string(); + } + return result->second; +} + +bool ModuleNameMap::tag_exist(const std::string& name) const { + auto result = name2tags_.find(name); + return result != name2tags_.end(); +} + std::vector ModuleNameMap::tags() const { std::vector keys; for (auto const& element : tag2names_) { diff --git a/libs/libnamemanager/src/base/module_name_map.h b/libs/libnamemanager/src/base/module_name_map.h index 0beb48c1a1..f3f82d9be0 100644 --- a/libs/libnamemanager/src/base/module_name_map.h +++ b/libs/libnamemanager/src/base/module_name_map.h @@ -22,6 +22,12 @@ class ModuleNameMap { /** @brief Check if a name does exist with a given tag. Return true if there * is a tag-to-name mapping */ bool name_exist(const std::string& tag) const; + /** @brief Check if a tag does exist with a given name. Return true if there + * is a name-to-tag mapping */ + bool tag_exist(const std::string& name) const; + /** @brief Get tag with a given name */ + std::string tag(const std::string& name) const; + /** @brief return a list of all the current keys */ std::vector tags() const; diff --git a/libs/libnamemanager/test/module_rename_assistant.cpp b/libs/libnamemanager/test/module_rename_assistant.cpp new file mode 100644 index 0000000000..a4e662f02b --- /dev/null +++ b/libs/libnamemanager/test/module_rename_assistant.cpp @@ -0,0 +1,159 @@ +/******************************************************************** + * Unit test functions to validate the correctness of + * 1. parser of data structures + * 2. writer of data structures + *******************************************************************/ +/* Headers from vtrutils */ +#include "vtr_assert.h" +#include "vtr_log.h" + +/* Headers from readarchopenfpga */ +#include "command_echo.h" +#include "command_exit_codes.h" +#include "command_parser.h" +#include "read_xml_module_name_map.h" +#include "write_xml_module_name_map.h" + +/** @brief Initialize the options from command-line inputs and organize in the + * format that is ready for parsing */ +static std::vector format_argv(const std::string& cmd_name, + int argc, const char** argv) { + std::vector cmd_opts; + cmd_opts.push_back(cmd_name); + for (int iarg = 1; iarg < argc; ++iarg) { + cmd_opts.push_back(std::string(argv[iarg])); + } + return cmd_opts; +} + +/** @brief Convert module renaming rules from fabric A (ref -> renamed) to + * fabric B (given the ref only) Here is an example Fabric A reference names: + * + * Fabric A renamed: + * + * Fabric B reference names: + * + * We want a renamed version for fabric B is + * + */ +int rename_module_names_for_fabricB_from_fabricA( + const openfpga::ModuleNameMap& refA_module_names, + const openfpga::ModuleNameMap& renamedA_module_names, + const openfpga::ModuleNameMap& refB_module_names, + openfpga::ModuleNameMap& renamedB_module_names, const bool& verbose) { + /* Ensure a clear start */ + renamedB_module_names.clear(); + for (std::string ref_tag : refA_module_names.tags()) { + std::string ref_given = refA_module_names.name(ref_tag); + if (!renamedA_module_names.name_exist(ref_tag)) { + VTR_LOG_ERROR( + "Fail to find given name for default '%s' in the hand-crafted module " + "names of fabric A!\n", + ref_tag.c_str()); + return openfpga::CMD_EXEC_FATAL_ERROR; + } + std::string renamed_given = renamedA_module_names.name(ref_tag); + /* Now find the same given name in refB */ + if (!refB_module_names.tag_exist(ref_given)) { + VTR_LOG_ERROR( + "Fail to find default name for the given name '%s' in the reference " + "module names of fabric B!\n", + ref_given.c_str()); + return openfpga::CMD_EXEC_FATAL_ERROR; + } + std::string refB_tag = refB_module_names.tag(ref_given); + /* Add the new pair to the renamed modules for fabric B */ + renamedB_module_names.set_tag_to_name_pair(refB_tag, renamed_given); + VTR_LOGV(verbose, + "Successfully pair default name '%s' to given '%s' for fabric B\n", + refB_tag.c_str(), renamed_given.c_str()); + } + return openfpga::CMD_EXEC_FATAL_ERROR; +} + +int main(int argc, const char** argv) { + /* Create a new command and Initialize the options available in the user + * interface */ + openfpga::Command cmd("module_rename_assistant"); + openfpga::CommandOptionId opt_refA = + cmd.add_option("reference_fabricA_names", true, + "Specify the reference module name file for fabric A"); + cmd.set_option_require_value(opt_refA, openfpga::OPT_STRING); + openfpga::CommandOptionId opt_renamedA = + cmd.add_option("renamed_fabricA_names", true, + "Specify the hand-crafted module name file for fabric A"); + cmd.set_option_require_value(opt_renamedA, openfpga::OPT_STRING); + openfpga::CommandOptionId opt_refB = + cmd.add_option("reference_fabricB_names", true, + "Specify the reference module name file for fabric B"); + cmd.set_option_require_value(opt_refB, openfpga::OPT_STRING); + openfpga::CommandOptionId opt_renamedB = cmd.add_option( + "output", true, + "Specify the renamed module name file for fabric B to be outputted"); + cmd.set_option_require_value(opt_renamedB, openfpga::OPT_STRING); + openfpga::CommandOptionId opt_no_time_stamp = cmd.add_option( + "no_time_stamp", false, "Include time stamps in output file"); + openfpga::CommandOptionId opt_verbose = + cmd.add_option("verbose", false, "Show verbose outputs"); + openfpga::CommandOptionId opt_help = + cmd.add_option("help", false, "Show help desk"); + + /* Parse the option, to avoid issues, we use the command name to replace the + * argv[0] */ + std::vector cmd_opts = format_argv(cmd.name(), argc, argv); + + openfpga::CommandContext cmd_ctx(cmd); + if (false == parse_command(cmd_opts, cmd, cmd_ctx) || + cmd_ctx.option_enable(cmd, opt_help)) { + /* Echo the command */ + print_command_options(cmd); + return openfpga::CMD_EXEC_FATAL_ERROR; + } else { + /* Let user to confirm selected options */ + print_command_context(cmd, cmd_ctx); + } + + int status = 0; + + VTR_LOG( + "Read the reference module names for fabric A from an XML file: %s.\n", + cmd_ctx.option_value(cmd, opt_refA).c_str()); + openfpga::ModuleNameMap refA_module_names; + status = openfpga::read_xml_module_name_map( + cmd_ctx.option_value(cmd, opt_refA).c_str(), refA_module_names); + if (status != openfpga::CMD_EXEC_SUCCESS) { + return status; + } + + VTR_LOG( + "Read the reference module names for fabric B from an XML file: %s.\n", + cmd_ctx.option_value(cmd, opt_refB).c_str()); + openfpga::ModuleNameMap refB_module_names; + status = openfpga::read_xml_module_name_map( + cmd_ctx.option_value(cmd, opt_refB).c_str(), refB_module_names); + if (status != openfpga::CMD_EXEC_SUCCESS) { + return status; + } + + VTR_LOG("Read the renamed module names for fabric A from an XML file: %s.\n", + cmd_ctx.option_value(cmd, opt_renamedA).c_str()); + openfpga::ModuleNameMap renamedA_module_names; + status = openfpga::read_xml_module_name_map( + cmd_ctx.option_value(cmd, opt_renamedA).c_str(), renamedA_module_names); + if (status != openfpga::CMD_EXEC_SUCCESS) { + return status; + } + + /* Now apply name mapping from fabric A to fabric B */ + openfpga::ModuleNameMap renamedB_module_names; + status = rename_module_names_for_fabricB_from_fabricA( + refA_module_names, renamedA_module_names, refB_module_names, + renamedB_module_names, cmd_ctx.option_enable(cmd, opt_verbose)); + + VTR_LOG("Write the renamed module names for fabric B to an XML file: %s.\n", + cmd_ctx.option_value(cmd, opt_renamedB).c_str()); + return openfpga::write_xml_module_name_map( + cmd_ctx.option_value(cmd, opt_renamedB).c_str(), renamedB_module_names, + !cmd_ctx.option_enable(cmd, opt_no_time_stamp), + cmd_ctx.option_enable(cmd, opt_verbose)); +}