From cfaae55bda85b84073f78fcc9c5f7a53b53b8fc6 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 26 Aug 2023 13:19:18 -0700 Subject: [PATCH] [lib] debugged fabric key assistant --- libs/libfabrickey/src/base/fabric_key.cpp | 18 +- libs/libfabrickey/src/base/fabric_key.h | 5 +- .../src/utils/check_fabric_key.cpp | 41 ++-- .../libfabrickey/src/utils/check_fabric_key.h | 3 +- .../test/fabric_key_assistant.cpp | 202 +++++++++++------- 5 files changed, 172 insertions(+), 97 deletions(-) diff --git a/libs/libfabrickey/src/base/fabric_key.cpp b/libs/libfabrickey/src/base/fabric_key.cpp index 12b92846b..a6558a258 100644 --- a/libs/libfabrickey/src/base/fabric_key.cpp +++ b/libs/libfabrickey/src/base/fabric_key.cpp @@ -55,18 +55,18 @@ std::vector FabricKey::sub_keys( /************************************************************************ * Public Accessors : Basic data query ***********************************************************************/ -size_t FabricKey::num_regions() const { - return region_ids_.size(); -} +size_t FabricKey::num_regions() const { return region_ids_.size(); } -size_t FabricKey::num_keys() const { - return key_ids_.size(); -} +size_t FabricKey::num_keys() const { return key_ids_.size(); } -std::vector find_key_by_alias(const std::string& alias) const { - /* Throw warning on empty alias which may cause unexpected results: whole key is dumped! */ +std::vector FabricKey::find_key_by_alias( + const std::string& alias) const { + /* Throw warning on empty alias which may cause unexpected results: whole key + * is dumped! */ if (alias.empty()) { - VTR_LOG_WARN("Empty alias is given! This may cause unexpected results, i.e., a whole data base is dumped!\n"); + VTR_LOG_WARN( + "Empty alias is given! This may cause unexpected results, i.e., a whole " + "data base is dumped!\n"); } size_t num_found_keys = 0; for (FabricKeyId key_id : key_ids_) { diff --git a/libs/libfabrickey/src/base/fabric_key.h b/libs/libfabrickey/src/base/fabric_key.h index 5ef9eb56c..3982cb8b8 100644 --- a/libs/libfabrickey/src/base/fabric_key.h +++ b/libs/libfabrickey/src/base/fabric_key.h @@ -88,7 +88,10 @@ class FabricKey { /* Access the coordinate of a key */ vtr::Point key_coordinate(const FabricKeyId& key_id) const; - /** @brief Find valid key ids for a given alias. Note that you should NOT send an empty alias which may cause a complete list of key ids to be returned (extremely inefficent and NOT useful). Suggest to check if the existing fabric key contains valid alias for each key before calling this API!!! */ + /** @brief Find valid key ids for a given alias. Note that you should NOT send + * an empty alias which may cause a complete list of key ids to be returned + * (extremely inefficent and NOT useful). Suggest to check if the existing + * fabric key contains valid alias for each key before calling this API!!! */ std::vector find_key_by_alias(const std::string& alias) const; /* Check if there are any keys */ diff --git a/libs/libfabrickey/src/utils/check_fabric_key.cpp b/libs/libfabrickey/src/utils/check_fabric_key.cpp index 30b9df07c..1e8964a33 100644 --- a/libs/libfabrickey/src/utils/check_fabric_key.cpp +++ b/libs/libfabrickey/src/utils/check_fabric_key.cpp @@ -17,7 +17,7 @@ namespace openfpga { * - Each alias should NOT be empty * - Each alias should be defined only once! */ -int check_fabric_key_alias(FabricKey& input_key, const bool& verbose) { +int check_fabric_key_alias(const FabricKey& input_key, const bool& verbose) { /* Check each key now */ size_t num_errors = 0; float progress = 0.; @@ -27,10 +27,14 @@ int check_fabric_key_alias(FabricKey& input_key, const bool& verbose) { for (FabricKeyId key_id : input_key.keys()) { /* Note that this is slow. May consider to build a map first */ std::string curr_alias = input_key.key_alias(key_id); - progress = static_cast(num_keys_checked) / static_cast(input_key.num_keys()) * 100.0; - VTR_LOGV(verbose, "[%lu\%] Checking key alias '%s'\r", progress, curr_alias.c_str()); + progress = static_cast(num_keys_checked) / + static_cast(input_key.num_keys()) * 100.0; + VTR_LOGV(verbose, "[%lu%] Checking key alias '%s'\r", size_t(progress), + curr_alias.c_str()); if (curr_alias.empty()) { - VTR_LOG_ERROR("Empty key alias (id='%lu') found in keys which is invalid!\n", size_t(key_id)); + VTR_LOG_ERROR( + "Empty key alias (id='%lu') found in keys which is invalid!\n", + size_t(key_id)); num_errors++; } auto result = alias_count.find(curr_alias); @@ -44,12 +48,16 @@ int check_fabric_key_alias(FabricKey& input_key, const bool& verbose) { for (const auto& kv : alias_count) { if (kv.second > 1) { std::string key_id_str; - std::vector found_keys = input_key.find_key_by_alias(curr_alias); + std::vector found_keys = + input_key.find_key_by_alias(kv.first); for (FabricKeyId found_key_id : found_keys) { key_id_str += std::to_string(size_t(found_key_id)) + ","; } - found_keys.pop(); /* Remove last comma */ - VTR_LOG_ERROR("Duplicated key alias '%s' found %lu times in keys (ids: %s), which is invalid!\n", kv.first.c_str(), kv.second, key_id_str.c_str()); + key_id_str.pop_back(); /* Remove last comma */ + VTR_LOG_ERROR( + "Duplicated key alias '%s' found %lu times in keys (ids: %s), which is " + "invalid!\n", + kv.first.c_str(), kv.second, key_id_str.c_str()); num_errors++; } } @@ -61,7 +69,8 @@ int check_fabric_key_alias(FabricKey& input_key, const bool& verbose) { * - Each name should not be empty * - Each value should be larger than zero ! */ -int check_fabric_key_names_and_values(FabricKey& input_key, const bool& verbose) { +int check_fabric_key_names_and_values(const FabricKey& input_key, + const bool& verbose) { /* Check each key now */ size_t num_errors = 0; float progress = 0.; @@ -72,10 +81,14 @@ int check_fabric_key_names_and_values(FabricKey& input_key, const bool& verbose) /* Note that this is slow. May consider to build a map first */ std::string curr_name = input_key.key_name(key_id); size_t curr_value = input_key.key_value(key_id); - progress = static_cast(num_keys_checked) / static_cast(input_key.num_keys()) * 100.0; - VTR_LOGV(verbose, "[%lu\%] Checking key names and values '(%s, %lu)'\r", progress, curr_name.c_str(), curr_value); + progress = static_cast(num_keys_checked) / + static_cast(input_key.num_keys()) * 100.0; + VTR_LOGV(verbose, "[%lu%] Checking key names and values '(%s, %lu)'\r", + size_t(progress), curr_name.c_str(), curr_value); if (curr_name.empty()) { - VTR_LOG_ERROR("Empty key name (id='%lu') found in keys which is invalid!\n", size_t(key_id)); + VTR_LOG_ERROR( + "Empty key name (id='%lu') found in keys which is invalid!\n", + size_t(key_id)); num_errors++; } auto result = key_value_count[curr_name].find(curr_value); @@ -89,7 +102,10 @@ int check_fabric_key_names_and_values(FabricKey& input_key, const bool& verbose) for (const auto& key_name_kv : key_value_count) { for (const auto& key_value_kv : key_name_kv.second) { if (key_value_kv.second > 1) { - VTR_LOG_ERROR("Duplicated key name and value pair (%s, %lu) found %lu times in keys, which is invalid!\n", key_name_kv.first.c_str(), key_value_kv.first, key_value_kv.second); + VTR_LOG_ERROR( + "Duplicated key name and value pair (%s, %lu) found %lu times in " + "keys, which is invalid!\n", + key_name_kv.first.c_str(), key_value_kv.first, key_value_kv.second); num_errors++; } } @@ -98,5 +114,4 @@ int check_fabric_key_names_and_values(FabricKey& input_key, const bool& verbose) return num_errors; } - } /* end namespace openfpga */ diff --git a/libs/libfabrickey/src/utils/check_fabric_key.h b/libs/libfabrickey/src/utils/check_fabric_key.h index 4849a99d8..63f3f31db 100644 --- a/libs/libfabrickey/src/utils/check_fabric_key.h +++ b/libs/libfabrickey/src/utils/check_fabric_key.h @@ -15,7 +15,8 @@ namespace openfpga { int check_fabric_key_alias(const FabricKey& input_key, const bool& verbose); -int check_fabric_key_names_values(const FabricKey& input_key, const bool& verbose); +int check_fabric_key_names_and_values(const FabricKey& input_key, + const bool& verbose); } /* end namespace openfpga */ diff --git a/libs/libfabrickey/test/fabric_key_assistant.cpp b/libs/libfabrickey/test/fabric_key_assistant.cpp index 77df8dc47..fc69aa583 100644 --- a/libs/libfabrickey/test/fabric_key_assistant.cpp +++ b/libs/libfabrickey/test/fabric_key_assistant.cpp @@ -8,15 +8,17 @@ #include "vtr_log.h" /* Headers from fabric key */ -#include "command_exit_codes.h" +#include "check_fabric_key.h" #include "command_echo.h" +#include "command_exit_codes.h" #include "command_parser.h" #include "read_xml_fabric_key.h" #include "write_xml_fabric_key.h" -#include "check_fabric_key.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) { +/** @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) { @@ -25,92 +27,133 @@ static std::vector format_argv(const std::string& cmd_name, int arg return cmd_opts; } -/** @brief Checks to be done: - * - Number of configuration regions match - * - Number of keys match - */ -static int check_input_key(FabricKey& input_key, const FabricKey& ref_key) { - if (ref_key.num_regions() != input_key.num_regions()) { - VTR_LOG_ERROR("Different number of configuration regions between reference key (='%lu') and input key ('=%lu')!\n", ref_key.num_regions(), input_key.num_regions()); - return CMD_EXEC_FATAL_ERROR; - } - if (ref_key.num_keys() != input_key.num_keys()) { - VTR_LOG_ERROR("Different number of keys between reference key (='%lu') and input key ('=%lu')!\n", ref_key.num_keys(), input_key.num_keys()); - return CMD_EXEC_FATAL_ERROR; - } - size_t num_errors = 0; - size_t curr_num_err = 0; - VTR_LOG("Checking key alias in reference key...\n"); - curr_num_err = check_fabric_key_alias(ref_key, true); - VTR_LOG("Checking key alias in reference key... %s\n", curr_num_err ? "[Fail]" : "[Pass]"); - VTR_LOG("Checking key names and values in reference key...\n"); - curr_num_err = check_fabric_key_names_and_values(ref_key, true); - num_errors += curr_num_err; - VTR_LOG("Checking key names and valus in reference key... %s\n", curr_num_err ? "[Fail]" : "[Pass]"); - VTR_LOG("Checking key alias in input key...\n"); - curr_num_err = check_fabric_key_alias(input_key, true); - num_errors += curr_num_err; - VTR_LOG("Checking key alias in input key... %s\n", curr_num_err ? "[Fail]" : "[Pass]"); - return num_errors ? CMD_EXEC_FATAL_ERROR : CMD_EXEC_SUCCESS; -} - /** @brief Checks to be done: * - Each alias of reference key can be found in the input key */ -static int check_input_and_ref_key_alias_match(FabricKey& input_key, const FabricKey& ref_key) { +static int check_input_and_ref_key_alias_match( + const openfpga::FabricKey& input_key, const openfpga::FabricKey& ref_key) { size_t num_errors = 0; size_t num_keys_checked = 0; float progress = 0.; - VTR_LOG("Checking key alias matching between reference key and input keys...\n"); - for (FabricKeyId key_id : ref_key.keys()) { + VTR_LOG( + "Checking key alias matching between reference key and input keys...\n"); + for (openfpga::FabricKeyId key_id : ref_key.keys()) { /* Note that this is slow. May consider to build a map first */ std::string curr_alias = ref_key.key_alias(key_id); - std::vector input_found_keys = input_key.find_key_by_alias(curr_alias); - progress = static_cast(num_keys_checked) / static_cast(ref_key.num_keys()) * 100.0; - VTR_LOG("[%lu\%] Checking key alias '%s'\r", progress, curr_alias.c_str()); + std::vector input_found_keys = + input_key.find_key_by_alias(curr_alias); + progress = static_cast(num_keys_checked) / + static_cast(ref_key.num_keys()) * 100.0; + VTR_LOG("[%lu%] Checking key alias '%s'\r", size_t(progress), + curr_alias.c_str()); if (input_found_keys.empty()) { - VTR_LOG_ERROR("\nInvalid alias '%s' in the reference key (id='%lu'), which does not exist in the input key!\n", curr_alias.c_str(), size_t(key_id)); + VTR_LOG_ERROR( + "\nInvalid alias '%s' in the reference key (id='%lu'), which does not " + "exist in the input key!\n", + curr_alias.c_str(), size_t(key_id)); num_errors++; } if (input_found_keys.size() > 1) { - VTR_LOG_ERROR("\nInvalid alias '%s' in the input key (id='%lu'), which have been found %lu times!\n", curr_alias.c_str(), size_t(key_id)); + VTR_LOG_ERROR( + "\nInvalid alias '%s' in the input key (id='%lu'), which have been " + "found %lu times!\n", + curr_alias.c_str(), size_t(key_id)); num_errors++; } num_keys_checked++; } - return num_errors ? CMD_EXEC_FATAL_ERROR : CMD_EXEC_SUCCESS; + VTR_LOG( + "Checking key alias matching between reference key and input keys... %s\n", + num_errors ? "[Fail]" : "[Pass]"); + return num_errors ? openfpga::CMD_EXEC_FATAL_ERROR + : openfpga::CMD_EXEC_SUCCESS; +} + +/** @brief Checks to be done: + * - Number of configuration regions match + * - Number of keys match + */ +static int check_input_key(const openfpga::FabricKey& input_key, + const openfpga::FabricKey& ref_key) { + if (ref_key.num_regions() != input_key.num_regions()) { + VTR_LOG_ERROR( + "Different number of configuration regions between reference key " + "(='%lu') and input key ('=%lu')!\n", + ref_key.num_regions(), input_key.num_regions()); + return openfpga::CMD_EXEC_FATAL_ERROR; + } + if (ref_key.num_keys() != input_key.num_keys()) { + VTR_LOG_ERROR( + "Different number of keys between reference key (='%lu') and input key " + "('=%lu')!\n", + ref_key.num_keys(), input_key.num_keys()); + return openfpga::CMD_EXEC_FATAL_ERROR; + } + size_t num_errors = 0; + size_t curr_num_err = 0; + VTR_LOG("Checking key alias in reference key...\n"); + curr_num_err = openfpga::check_fabric_key_alias(ref_key, true); + VTR_LOG("Checking key alias in reference key... %s\n", + curr_num_err ? "[Fail]" : "[Pass]"); + VTR_LOG("Checking key names and values in reference key...\n"); + curr_num_err = openfpga::check_fabric_key_names_and_values(ref_key, true); + num_errors += curr_num_err; + VTR_LOG("Checking key names and valus in reference key... %s\n", + curr_num_err ? "[Fail]" : "[Pass]"); + VTR_LOG("Checking key alias in input key...\n"); + curr_num_err = openfpga::check_fabric_key_alias(input_key, true); + num_errors += curr_num_err; + VTR_LOG("Checking key alias in input key... %s\n", + curr_num_err ? "[Fail]" : "[Pass]"); + num_errors += check_input_and_ref_key_alias_match(input_key, ref_key); + return num_errors ? openfpga::CMD_EXEC_FATAL_ERROR + : openfpga::CMD_EXEC_SUCCESS; } /** @brief Checks to be done: * - Each alias of input key can be found in the reference key - * - Update input key with pair of name and value which matches the alias from the reference key + * - Update input key with pair of name and value which matches the alias from + * the reference key */ -static int update_input_key(FabricKey& input_key, const FabricKey& ref_key) { +static int update_input_key(openfpga::FabricKey& input_key, + const openfpga::FabricKey& ref_key) { size_t num_errors = 0; size_t num_keys_checked = 0; float progress = 0.; VTR_LOG("Pairing key alias between reference key and input keys...\n"); - for (FabricKeyId key_id : input_key.keys()) { + for (openfpga::FabricKeyId key_id : input_key.keys()) { /* Note that this is slow. May consider to build a map first */ std::string curr_alias = input_key.key_alias(key_id); - std::vector ref_found_keys = ref_key.find_key_by_alias(curr_alias); - progress = static_cast(num_keys_checked) / static_cast(input_key.num_keys()) * 100.0; - VTR_LOG("[%lu\%] Pairing key alias '%s'\r", progress, curr_alias.c_str()); + std::vector ref_found_keys = + ref_key.find_key_by_alias(curr_alias); + progress = static_cast(num_keys_checked) / + static_cast(input_key.num_keys()) * 100.0; + VTR_LOG("[%lu%] Pairing key alias '%s'\r", size_t(progress), + curr_alias.c_str()); if (ref_found_keys.empty()) { - VTR_LOG_ERROR("\nInvalid alias '%s' in the input key (id='%lu'), which does not exist in the reference key!\n", curr_alias.c_str(), size_t(key_id)); + VTR_LOG_ERROR( + "\nInvalid alias '%s' in the input key (id='%lu'), which does not " + "exist in the reference key!\n", + curr_alias.c_str(), size_t(key_id)); num_errors++; } if (ref_found_keys.size() > 1) { - VTR_LOG_ERROR("\nInvalid alias '%s' in the reference key (id='%lu'), which have been found %lu times!\n", curr_alias.c_str(), size_t(key_id)); + VTR_LOG_ERROR( + "\nInvalid alias '%s' in the reference key (id='%lu'), which have been " + "found %lu times!\n", + curr_alias.c_str(), size_t(key_id)); num_errors++; } /* Now we have a key, get the name and value, and update input key */ input_key.set_key_name(key_id, ref_key.key_name(ref_found_keys[0])); input_key.set_key_value(key_id, ref_key.key_value(ref_found_keys[0])); - VTR_LOG("[%lu\%] Pairing key alias '%s' -> ('%s', %lu)\r", progress, curr_alias.c_str(), input_key.key_name(key_id).c_str(), input_key.key_value(key_id)); + VTR_LOG("[%lu%] Pairing key alias '%s' -> ('%s', %lu)\r", size_t(progress), + curr_alias.c_str(), input_key.key_name(key_id).c_str(), + input_key.key_value(key_id)); num_keys_checked++; } - return num_errors ? CMD_EXEC_FATAL_ERROR : CMD_EXEC_SUCCESS; + return num_errors ? openfpga::CMD_EXEC_FATAL_ERROR + : openfpga::CMD_EXEC_SUCCESS; } /** @brief Checks to be done: @@ -118,52 +161,65 @@ static int update_input_key(FabricKey& input_key, const FabricKey& ref_key) { * - Number of keys match * - Each alias can be found in the reference key */ -static int check_and_update_input_key(FabricKey& input_key, const FabricKey& ref_key) { - int status = CMD_EXEC_SUCCESS; +static int check_and_update_input_key(openfpga::FabricKey& input_key, + const openfpga::FabricKey& ref_key) { + int status = openfpga::CMD_EXEC_SUCCESS; status = check_input_key(input_key, ref_key); - if (status != CMD_EXEC_SUCCESS) { - return CMD_EXEC_FATAL_ERROR; + if (status != openfpga::CMD_EXEC_SUCCESS) { + return openfpga::CMD_EXEC_FATAL_ERROR; } return update_input_key(input_key, ref_key); } - int main(int argc, const char** argv) { - /* Create a new command and Initialize the options available in the user interface */ + /* Create a new command and Initialize the options available in the user + * interface */ openfpga::Command cmd("fabric_key_assistant"); - openfpga::CommandOptionId opt_ref = cmd.add_option("reference", true, "Specify the reference fabric key file"); - cmd.set_option_require_value(opt_ref, OPT_STRING); - openfpga::CommandOptionId opt_input = cmd.add_option("input", true, "Specify the hand-crafted fabric key file"); - cmd.set_option_require_value(opt_input, OPT_STRING); - openfpga::CommandOptionId opt_output = cmd.add_option("output", true, "Specify the final fabric key file to be outputted"); - cmd.set_option_require_value(opt_output, OPT_STRING); - openfpga::CommandOptionId opt_help = cmd.add_option("help", true, "Show help desk"); + openfpga::CommandOptionId opt_ref = + cmd.add_option("reference", true, "Specify the reference fabric key file"); + cmd.set_option_require_value(opt_ref, openfpga::OPT_STRING); + openfpga::CommandOptionId opt_input = + cmd.add_option("input", true, "Specify the hand-crafted fabric key file"); + cmd.set_option_require_value(opt_input, openfpga::OPT_STRING); + openfpga::CommandOptionId opt_output = cmd.add_option( + "output", true, "Specify the final fabric key file to be outputted"); + cmd.set_option_require_value(opt_output, openfpga::OPT_STRING); + 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); - CommandContext cmd_ctx(cmd); - if (false == parse_command(cmd_opts, cmd, cmd_ctx)) { + 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); } /* Parse the fabric key from an XML file */ - VTR_LOG("Read the reference fabric key from an XML file: %s.\n", cmd_ctx.option_value(cmd, opt_ref).c_str()); - openfpga::FabricKey ref_key = openfpga::read_xml_fabric_key(cmd_ctx.option_value(cmd, opt_ref).c_str()); + VTR_LOG("Read the reference fabric key from an XML file: %s.\n", + cmd_ctx.option_value(cmd, opt_ref).c_str()); + openfpga::FabricKey ref_key = + openfpga::read_xml_fabric_key(cmd_ctx.option_value(cmd, opt_ref).c_str()); - VTR_LOG("Read the hand-crafted fabric key from an XML file: %s.\n", cmd_ctx.option_value(cmd, opt_input).c_str()); - openfpga::FabricKey input_key = openfpga::read_xml_fabric_key(cmd_ctx.option_value(cmd, opt_input).c_str()); + VTR_LOG("Read the hand-crafted fabric key from an XML file: %s.\n", + cmd_ctx.option_value(cmd, opt_input).c_str()); + openfpga::FabricKey input_key = + openfpga::read_xml_fabric_key(cmd_ctx.option_value(cmd, opt_input).c_str()); /* Check the input key */ if (check_and_update_input_key(input_key, ref_key)) { return openfpga::CMD_EXEC_FATAL_ERROR; } - VTR_LOG("Write the final fabric key to an XML file: %s.\n", cmd_ctx.option_value(cmd, opt_output).c_str()); - return openfpga::write_xml_fabric_key(cmd_ctx.option_value(cmd, opt_output).c_str(), input_key); + VTR_LOG("Write the final fabric key to an XML file: %s.\n", + cmd_ctx.option_value(cmd, opt_output).c_str()); + return openfpga::write_xml_fabric_key( + cmd_ctx.option_value(cmd, opt_output).c_str(), input_key); }