From adae7392e5a6b74b53f9cb954384685487d325bb Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 26 Aug 2023 12:54:12 -0700 Subject: [PATCH 1/7] [lib] developing fabric key assistant --- libs/libfabrickey/CMakeLists.txt | 1 + libs/libfabrickey/src/base/fabric_key.cpp | 29 +++ libs/libfabrickey/src/base/fabric_key.h | 5 + .../src/utils/check_fabric_key.cpp | 102 +++++++++++ .../libfabrickey/src/utils/check_fabric_key.h | 22 +++ .../test/fabric_key_assistant.cpp | 169 ++++++++++++++++++ 6 files changed, 328 insertions(+) create mode 100644 libs/libfabrickey/src/utils/check_fabric_key.cpp create mode 100644 libs/libfabrickey/src/utils/check_fabric_key.h create mode 100644 libs/libfabrickey/test/fabric_key_assistant.cpp diff --git a/libs/libfabrickey/CMakeLists.txt b/libs/libfabrickey/CMakeLists.txt index ac43927ac..8c01cc472 100644 --- a/libs/libfabrickey/CMakeLists.txt +++ b/libs/libfabrickey/CMakeLists.txt @@ -20,6 +20,7 @@ set_target_properties(libfabrickey PROPERTIES PREFIX "") #Avoid extra 'lib' pref #Specify link-time dependancies target_link_libraries(libfabrickey libopenfpgautil + libopenfpgashell libarchopenfpga libvtrutil libpugiutil) diff --git a/libs/libfabrickey/src/base/fabric_key.cpp b/libs/libfabrickey/src/base/fabric_key.cpp index b80d87204..12b92846b 100644 --- a/libs/libfabrickey/src/base/fabric_key.cpp +++ b/libs/libfabrickey/src/base/fabric_key.cpp @@ -55,6 +55,35 @@ std::vector FabricKey::sub_keys( /************************************************************************ * Public Accessors : Basic data query ***********************************************************************/ +size_t FabricKey::num_regions() const { + return region_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! */ + if (alias.empty()) { + 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_) { + if (key_alias(key_id) == alias) { + num_found_keys++; + } + } + std::vector found_keys; + found_keys.reserve(num_found_keys); + for (FabricKeyId key_id : key_ids_) { + if (key_alias(key_id) == alias) { + found_keys.push_back(key_id); + } + } + return found_keys; +} + std::vector FabricKey::region_keys( const FabricRegionId& region_id) const { /* validate the region_id */ diff --git a/libs/libfabrickey/src/base/fabric_key.h b/libs/libfabrickey/src/base/fabric_key.h index 7afd43af7..5ef9eb56c 100644 --- a/libs/libfabrickey/src/base/fabric_key.h +++ b/libs/libfabrickey/src/base/fabric_key.h @@ -75,6 +75,8 @@ class FabricKey { const FabricKeyModuleId& module_id) const; public: /* Public Accessors: Basic data query */ + size_t num_regions() const; + size_t num_keys() const; /* Access all the keys of a region */ std::vector region_keys(const FabricRegionId& region_id) const; /* Access the name of a key */ @@ -86,6 +88,9 @@ 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!!! */ + std::vector find_key_by_alias(const std::string& alias) const; + /* Check if there are any keys */ bool empty() const; diff --git a/libs/libfabrickey/src/utils/check_fabric_key.cpp b/libs/libfabrickey/src/utils/check_fabric_key.cpp new file mode 100644 index 000000000..30b9df07c --- /dev/null +++ b/libs/libfabrickey/src/utils/check_fabric_key.cpp @@ -0,0 +1,102 @@ +/************************************************************************ + * Check functions for the content of fabric key to avoid conflicts with + * other data structures + * These functions are not universal methods for the FabricKey class + * They are made to ease the development in some specific purposes + * Please classify such functions in this file + ***********************************************************************/ +#include "check_fabric_key.h" + +#include "vtr_assert.h" +#include "vtr_log.h" + +/* begin namespace openfpga */ +namespace openfpga { + +/** @brief Sanity checks for fabric key alias attribute: + * - Each alias should NOT be empty + * - Each alias should be defined only once! + */ +int check_fabric_key_alias(FabricKey& input_key, const bool& verbose) { + /* Check each key now */ + size_t num_errors = 0; + float progress = 0.; + size_t num_keys_checked = 0; + + std::map alias_count; + 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()); + if (curr_alias.empty()) { + 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); + if (result == alias_count.end()) { + alias_count[curr_alias] = 0; + } else { + alias_count[curr_alias] += 1; + } + num_keys_checked++; + } + 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); + 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()); + num_errors++; + } + } + + return num_errors; +} + +/** @brief Sanity checks for fabric key name and value attribute: + * - 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) { + /* Check each key now */ + size_t num_errors = 0; + float progress = 0.; + size_t num_keys_checked = 0; + + std::map> key_value_count; + for (FabricKeyId key_id : input_key.keys()) { + /* 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); + if (curr_name.empty()) { + 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); + if (result == key_value_count[curr_name].end()) { + key_value_count[curr_name][curr_value] = 0; + } else { + key_value_count[curr_name][curr_value] += 1; + } + num_keys_checked++; + } + 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); + num_errors++; + } + } + } + + 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 new file mode 100644 index 000000000..4849a99d8 --- /dev/null +++ b/libs/libfabrickey/src/utils/check_fabric_key.h @@ -0,0 +1,22 @@ +#ifndef CHECK_FABRIC_KEY_H +#define CHECK_FABRIC_KEY_H + +/******************************************************************** + * Include header files that are required by function declaration + *******************************************************************/ +#include "fabric_key.h" + +/******************************************************************** + * Function declaration + *******************************************************************/ + +/* begin namespace openfpga */ +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); + +} /* end namespace openfpga */ + +#endif diff --git a/libs/libfabrickey/test/fabric_key_assistant.cpp b/libs/libfabrickey/test/fabric_key_assistant.cpp new file mode 100644 index 000000000..77df8dc47 --- /dev/null +++ b/libs/libfabrickey/test/fabric_key_assistant.cpp @@ -0,0 +1,169 @@ +/******************************************************************** + * 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 fabric key */ +#include "command_exit_codes.h" +#include "command_echo.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) { + 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 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) { + 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()) { + /* 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()); + 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)); + 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)); + num_errors++; + } + num_keys_checked++; + } + return num_errors ? CMD_EXEC_FATAL_ERROR : 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 + */ +static int update_input_key(FabricKey& input_key, const 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()) { + /* 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()); + 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)); + 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)); + 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)); + num_keys_checked++; + } + return num_errors ? CMD_EXEC_FATAL_ERROR : CMD_EXEC_SUCCESS; +} + +/** @brief Checks to be done: + * - Number of configuration regions match + * - 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; + status = check_input_key(input_key, ref_key); + if (status != CMD_EXEC_SUCCESS) { + return 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 */ + 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"); + + /* 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)) { + /* Echo the command */ + print_command_options(cmd); + } 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 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); +} From cfaae55bda85b84073f78fcc9c5f7a53b53b8fc6 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 26 Aug 2023 13:19:18 -0700 Subject: [PATCH 2/7] [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); } From 97619fc5458b56a035231740475e2a9bee7bb45c Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 26 Aug 2023 18:07:08 -0700 Subject: [PATCH 3/7] [lib] add verbose output option to fabric key assistant --- .../test/fabric_key_assistant.cpp | 33 +++++++++++-------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/libs/libfabrickey/test/fabric_key_assistant.cpp b/libs/libfabrickey/test/fabric_key_assistant.cpp index fc69aa583..54831081e 100644 --- a/libs/libfabrickey/test/fabric_key_assistant.cpp +++ b/libs/libfabrickey/test/fabric_key_assistant.cpp @@ -31,7 +31,7 @@ static std::vector format_argv(const std::string& cmd_name, * - Each alias of reference key can be found in the input key */ static int check_input_and_ref_key_alias_match( - const openfpga::FabricKey& input_key, const openfpga::FabricKey& ref_key) { + const openfpga::FabricKey& input_key, const openfpga::FabricKey& ref_key, const bool& verbose) { size_t num_errors = 0; size_t num_keys_checked = 0; float progress = 0.; @@ -44,7 +44,7 @@ static int check_input_and_ref_key_alias_match( 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), + VTR_LOGV(verbose, "[%lu%] Checking key alias '%s'\r", size_t(progress), curr_alias.c_str()); if (input_found_keys.empty()) { VTR_LOG_ERROR( @@ -74,7 +74,8 @@ static int check_input_and_ref_key_alias_match( * - Number of keys match */ static int check_input_key(const openfpga::FabricKey& input_key, - const openfpga::FabricKey& ref_key) { + const openfpga::FabricKey& ref_key, + const bool& verbose) { if (ref_key.num_regions() != input_key.num_regions()) { VTR_LOG_ERROR( "Different number of configuration regions between reference key " @@ -92,20 +93,20 @@ static int check_input_key(const openfpga::FabricKey& input_key, 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); + curr_num_err = openfpga::check_fabric_key_alias(ref_key, verbose); 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); + curr_num_err = openfpga::check_fabric_key_names_and_values(ref_key, verbose); 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); + curr_num_err = openfpga::check_fabric_key_alias(input_key, verbose); 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); + num_errors += check_input_and_ref_key_alias_match(input_key, ref_key, verbose); return num_errors ? openfpga::CMD_EXEC_FATAL_ERROR : openfpga::CMD_EXEC_SUCCESS; } @@ -116,7 +117,8 @@ static int check_input_key(const openfpga::FabricKey& input_key, * the reference key */ static int update_input_key(openfpga::FabricKey& input_key, - const openfpga::FabricKey& ref_key) { + const openfpga::FabricKey& ref_key, + const bool& verbose) { size_t num_errors = 0; size_t num_keys_checked = 0; float progress = 0.; @@ -128,7 +130,7 @@ static int update_input_key(openfpga::FabricKey& input_key, 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), + VTR_LOGV(verbose, "[%lu%] Pairing key alias '%s'\r", size_t(progress), curr_alias.c_str()); if (ref_found_keys.empty()) { VTR_LOG_ERROR( @@ -147,7 +149,7 @@ static int update_input_key(openfpga::FabricKey& input_key, /* 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", size_t(progress), + VTR_LOGV(verbose, "[%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++; @@ -162,13 +164,14 @@ static int update_input_key(openfpga::FabricKey& input_key, * - Each alias can be found in the reference key */ static int check_and_update_input_key(openfpga::FabricKey& input_key, - const openfpga::FabricKey& ref_key) { + const openfpga::FabricKey& ref_key, + const bool& verbose) { int status = openfpga::CMD_EXEC_SUCCESS; - status = check_input_key(input_key, ref_key); + status = check_input_key(input_key, ref_key, verbose); if (status != openfpga::CMD_EXEC_SUCCESS) { return openfpga::CMD_EXEC_FATAL_ERROR; } - return update_input_key(input_key, ref_key); + return update_input_key(input_key, ref_key, verbose); } int main(int argc, const char** argv) { @@ -184,6 +187,8 @@ int main(int argc, const char** argv) { 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_verbose = + cmd.add_option("verbose", false, "Show verbose outputs"); openfpga::CommandOptionId opt_help = cmd.add_option("help", false, "Show help desk"); @@ -214,7 +219,7 @@ int main(int argc, const char** argv) { 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)) { + if (check_and_update_input_key(input_key, ref_key, cmd_ctx.option_enable(cmd, opt_verbose))) { return openfpga::CMD_EXEC_FATAL_ERROR; } From ac5873bac290d96546d9c0526879022e5458d21d Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 26 Aug 2023 18:12:25 -0700 Subject: [PATCH 4/7] [lib] fixed some bugs in message show --- libs/libfabrickey/test/fabric_key_assistant.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/libfabrickey/test/fabric_key_assistant.cpp b/libs/libfabrickey/test/fabric_key_assistant.cpp index 54831081e..380a730a5 100644 --- a/libs/libfabrickey/test/fabric_key_assistant.cpp +++ b/libs/libfabrickey/test/fabric_key_assistant.cpp @@ -57,7 +57,7 @@ static int check_input_and_ref_key_alias_match( 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)); + curr_alias.c_str(), size_t(key_id), input_found_keys.size()); num_errors++; } num_keys_checked++; From 3273728bc3f2762fe7d76fa5c6c341ed63264320 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 26 Aug 2023 18:15:30 -0700 Subject: [PATCH 5/7] [lib] code format --- .../test/fabric_key_assistant.cpp | 27 ++++++++++--------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/libs/libfabrickey/test/fabric_key_assistant.cpp b/libs/libfabrickey/test/fabric_key_assistant.cpp index 380a730a5..c0befce57 100644 --- a/libs/libfabrickey/test/fabric_key_assistant.cpp +++ b/libs/libfabrickey/test/fabric_key_assistant.cpp @@ -31,7 +31,8 @@ static std::vector format_argv(const std::string& cmd_name, * - Each alias of reference key can be found in the input key */ static int check_input_and_ref_key_alias_match( - const openfpga::FabricKey& input_key, const openfpga::FabricKey& ref_key, const bool& verbose) { + const openfpga::FabricKey& input_key, const openfpga::FabricKey& ref_key, + const bool& verbose) { size_t num_errors = 0; size_t num_keys_checked = 0; float progress = 0.; @@ -45,17 +46,17 @@ static int check_input_and_ref_key_alias_match( progress = static_cast(num_keys_checked) / static_cast(ref_key.num_keys()) * 100.0; VTR_LOGV(verbose, "[%lu%] Checking key alias '%s'\r", size_t(progress), - curr_alias.c_str()); + curr_alias.c_str()); if (input_found_keys.empty()) { VTR_LOG_ERROR( - "\nInvalid alias '%s' in the reference key (id='%lu'), which does not " + "Invalid 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 " + "Invalid alias '%s' in the input key (id='%lu'), which have been " "found %lu times!\n", curr_alias.c_str(), size_t(key_id), input_found_keys.size()); num_errors++; @@ -106,7 +107,8 @@ static int check_input_key(const openfpga::FabricKey& input_key, 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, verbose); + num_errors += + check_input_and_ref_key_alias_match(input_key, ref_key, verbose); return num_errors ? openfpga::CMD_EXEC_FATAL_ERROR : openfpga::CMD_EXEC_SUCCESS; } @@ -131,17 +133,17 @@ static int update_input_key(openfpga::FabricKey& input_key, progress = static_cast(num_keys_checked) / static_cast(input_key.num_keys()) * 100.0; VTR_LOGV(verbose, "[%lu%] Pairing key alias '%s'\r", size_t(progress), - curr_alias.c_str()); + curr_alias.c_str()); if (ref_found_keys.empty()) { VTR_LOG_ERROR( - "\nInvalid alias '%s' in the input key (id='%lu'), which does not " + "Invalid 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 " + "Invalid 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++; @@ -149,9 +151,9 @@ static int update_input_key(openfpga::FabricKey& input_key, /* 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_LOGV(verbose, "[%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)); + VTR_LOGV(verbose, "[%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 ? openfpga::CMD_EXEC_FATAL_ERROR @@ -219,7 +221,8 @@ int main(int argc, const char** argv) { 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, cmd_ctx.option_enable(cmd, opt_verbose))) { + if (check_and_update_input_key(input_key, ref_key, + cmd_ctx.option_enable(cmd, opt_verbose))) { return openfpga::CMD_EXEC_FATAL_ERROR; } From f53e05f1507d909797306db6a3e4ce177aa94ed1 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 26 Aug 2023 18:46:43 -0700 Subject: [PATCH 6/7] [doc] add utility tool: fabric key assistant --- docs/source/manual/index.rst | 2 + .../manual/utilities/fabric_key_assistant.rst | 50 +++++++++++++++++++ docs/source/manual/utilities/index.rst | 13 +++++ 3 files changed, 65 insertions(+) create mode 100644 docs/source/manual/utilities/fabric_key_assistant.rst create mode 100644 docs/source/manual/utilities/index.rst diff --git a/docs/source/manual/index.rst b/docs/source/manual/index.rst index a00dce30a..fd4f4df56 100644 --- a/docs/source/manual/index.rst +++ b/docs/source/manual/index.rst @@ -18,3 +18,5 @@ file_formats/index + utilities/index + diff --git a/docs/source/manual/utilities/fabric_key_assistant.rst b/docs/source/manual/utilities/fabric_key_assistant.rst new file mode 100644 index 000000000..9bd525b91 --- /dev/null +++ b/docs/source/manual/utilities/fabric_key_assistant.rst @@ -0,0 +1,50 @@ +.. _utility_fabric_key_assistant: + +Fabric Key Assistant +-------------------- + +Fabric Key Assistant is a tool to help users to craft fabric key files. +Note that crafting a fabric key is not an easy task for engineers, as its complexity grows exponentially with FPGA sizes. +This tool is developed to assist engineers when finalizing fabric key files. +It can apply sanity checks on hand-crafted fabric key files, helping engineers to correct and debug. +The tool includes the following options: + +.. option:: --reference + + Specifiy a reference fabric key file, which has been already validated by OpenFPGA. For example, the reference fabric key can be a file which is written by OpenFPGA as a default key. The reference fabric key file is treated as the baseline, on which the input fabric key file will be compared to. + + .. note:: The reference fabric key should contain all the syntax, e.g., ``name``, ``value`` and ``alias``. + +.. option:: --input + + Specify the input fabric key file, which is typically hand-crafted by users. Sanity checks will be applied to the input fabric key file by comparing the reference. + + .. note:: The input fabric key should contain only the syntax ``alias``. + +.. option:: --output + + Specify the output fabric key file, which is an updated version of the input fabric key file. Difference from the input file, the output file contains ``name`` and ``value``, which is added by linking the ``alias`` from input file to reference file. For example, the reference fabric key includes a key: + +.. code-block:: xml + + + + while the input fabric key includes a key: + +.. code-block:: xml + + + + the resulting output fabric key file includes a key: + +.. code-block:: xml + + + +.. option:: --verbose + + To enable verbose output + +.. option:: --help + + Show help desk diff --git a/docs/source/manual/utilities/index.rst b/docs/source/manual/utilities/index.rst new file mode 100644 index 000000000..a51774314 --- /dev/null +++ b/docs/source/manual/utilities/index.rst @@ -0,0 +1,13 @@ +Utilities +--------- + +OpenFPGA contains a number of utility tools to help users to craft files. + + +.. _utilities: + Utility Tools + +.. toctree:: + :maxdepth: 2 + + fabric_key_assistant From 3bc5c3b3b781ba2a886dfe314a33c9800de986f2 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 26 Aug 2023 18:56:11 -0700 Subject: [PATCH 7/7] [doc] add links --- docs/source/manual/utilities/fabric_key_assistant.rst | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/docs/source/manual/utilities/fabric_key_assistant.rst b/docs/source/manual/utilities/fabric_key_assistant.rst index 9bd525b91..4625366d2 100644 --- a/docs/source/manual/utilities/fabric_key_assistant.rst +++ b/docs/source/manual/utilities/fabric_key_assistant.rst @@ -3,10 +3,13 @@ Fabric Key Assistant -------------------- -Fabric Key Assistant is a tool to help users to craft fabric key files. +Fabric Key Assistant is a tool to help users to craft fabric key files (see details in :ref:`file_formats_fabric_key`). Note that crafting a fabric key is not an easy task for engineers, as its complexity grows exponentially with FPGA sizes. This tool is developed to assist engineers when finalizing fabric key files. It can apply sanity checks on hand-crafted fabric key files, helping engineers to correct and debug. + +The tool can be found at ``/build/libs/libfabrickey/test/fabric_key_assistant`` + The tool includes the following options: .. option:: --reference @@ -29,13 +32,13 @@ The tool includes the following options: - while the input fabric key includes a key: +while the input fabric key includes a key: .. code-block:: xml - the resulting output fabric key file includes a key: +the resulting output fabric key file includes a key: .. code-block:: xml