diff --git a/src/runtime_src/core/pcie/linux/smi.cpp b/src/runtime_src/core/pcie/linux/smi.cpp index 3ffa55af0d..69e284bad3 100644 --- a/src/runtime_src/core/pcie/linux/smi.cpp +++ b/src/runtime_src/core/pcie/linux/smi.cpp @@ -150,33 +150,146 @@ static constexpr std::string_view xrt_smi_config = [ { "name": "device", + "alias": "d", "description": "The Bus:Device.Function (e.g., 0000:d8:00.0) device of interest", - "tag": "devl", + "tag": "basic", + "default_value": "", + "option_type": "common", "value_type": "string" }, { "name": "format", - "description": "Report output format", - "tag": "devl", + "alias": "f", + "description": ["Report output format. Valid values are:", + "\n\tJSON - Latest JSON schema", + "\n\tJSON-2020.2 - JSON 2020.2 schema" + ], + "tag": "basic", + "default_value": "", + "option_type": "common", "value_type": "string" }, + { + "name": "output", + "alias": "o", + "description" : "Direct the output to the given file", + "tag": "basic", + "default_value": "", + "option_type": "common", + "value_type" : "string" + }, + { + "name": "help", + "alias": "h", + "description" : "Help to use this sub-command", + "tag": "basic", + "default_value": "", + "option_type": "common", + "value_type" : "none" + }, { "name": "report", - "description": "The type of report to be produced. Reports currently available are:", + "alias": "r", + "description": ["The type of report to be produced. Reports currently available are:", + "\n\taie - AIE metadata in xclbin", + "\n\taiemem - AIE memory tile information", + "\n\taieshim - AIE shim tile status", + "\n\tdebug-ip-status - Status of Debug IPs present in xclbin loaded on device", + "\n\tdynamic-regions - Information about the xclbin and the compute units", + "\n\telectrical - Electrical and power sensors present on the device", + "\n\terror - Asyncronus Error present on the device", + "\n\tfirewall - Firewall status", + "\n\tmailbox - Mailbox metrics of the device", + "\n\tmechanical - Mechanical sensors on and surrounding the device", + "\n\tmemory - Memory information present on the device", + "\n\tpcie-info - Pcie information of the device", + "\n\tqspi-status - QSPI write protection status", + "\n\tthermal - Thermal sensors present on the device" + ], "tag": "basic", + "option_type": "common", + "value_type": "array", "options": [ { - "name": "aie-partitions", + "name": "aie", + "tag": "basic", + "description": "AIE metadata in xclbin" + }, + { + "name": "aiemem", + "tag": "basic", + "description": "AIE memory tile information" + }, + { + "name": "aieshim", "tag": "basic", - "description": "AIE partition information" + "description": "AIE shim tile status" }, { - "name": "telemetry", - "tag": "devl", - "description": "Telemetry data for the device" + "name": "debug-ip-status", + "tag": "basic", + "description": "Status of Debug IPs present in xclbin loaded on device" + }, + { + "name": "dynamic-regions", + "tag": "basic", + "description": "Information about the xclbin and the compute units" + }, + { + "name": "electrical", + "tag": "basic", + "description": "Electrical and power sensors present on the device" + }, + { + "name": "error", + "tag": "basic", + "description": "Asyncronus Error present on the device" + }, + { + "name": "firewall", + "tag": "basic", + "description": "Firewall status" + }, + { + "name": "mailbox", + "tag": "basic", + "description": "Mailbox metrics of the device" + }, + { + "name": "mechanical", + "tag": "basic", + "description": "Mechanical sensors on and surrounding the device" + }, + { + "name": "memory", + "tag": "basic", + "description": "Memory information present on the device" + }, + { + "name": "pcie-info", + "tag": "basic", + "description": "Pcie information of the device" + }, + { + "name": "qspi-status", + "tag": "basic", + "description": "QSPI write protection status" + }, + { + "name": "thermal", + "tag": "basic", + "description": "Thermal sensors present on the device" } ] - } + }, + { + "name": "element", + "alias": "e", + "description" : "Filters individual elements(s) from the report. Format: '///...'", + "tag": "basic", + "option_type": "hidden", + "value_type" : "array" + } ] }, { diff --git a/src/runtime_src/core/tools/common/SubCmdExamineInternal.cpp b/src/runtime_src/core/tools/common/SubCmdExamineInternal.cpp index dd6f109240..00b04bba80 100644 --- a/src/runtime_src/core/tools/common/SubCmdExamineInternal.cpp +++ b/src/runtime_src/core/tools/common/SubCmdExamineInternal.cpp @@ -27,20 +27,11 @@ namespace po = boost::program_options; #include static ReportCollection fullReportCollection = {}; -static boost::program_options::options_description common_options; -static std::map>> jsonOptions; -static XBUtilities::VectorPairStrings common_reports; // ----- C L A S S M E T H O D S ------------------------------------------- SubCmdExamineInternal::SubCmdExamineInternal(bool _isHidden, bool _isDepricated, bool _isPreliminary, bool _isUserDomain, const boost::property_tree::ptree& configurations) : SubCmd("examine", _isUserDomain ? "Status of the system and device" : "Returns detail information for the specified device.") - , m_device("") - , m_reportNames() - , m_elementsFilter() - , m_format("") - , m_output("") - , m_help(false) , m_isUserDomain(_isUserDomain) { @@ -56,44 +47,16 @@ SubCmdExamineInternal::SubCmdExamineInternal(bool _isHidden, bool _isDepricated, for (const auto& option : uniqueReportCollection) fullReportCollection.push_back(option); - - const auto& configs = JSONConfigurable::parse_configuration_tree(configurations); - jsonOptions = JSONConfigurable::extract_subcmd_config(fullReportCollection, configs, getConfigName(), std::string("report")); - - common_reports.emplace_back("all", "All known reports are produced"); - static const std::string reportOptionValues = XBU::create_suboption_list_map("", jsonOptions, common_reports); - static const std::string formatOptionValues = XBU::create_suboption_list_string(Report::getSchemaDescriptionVector()); - common_options.add_options() - ("device,d", boost::program_options::value(&m_device), "The Bus:Device.Function (e.g., 0000:d8:00.0) device of interest") - ("format,f", boost::program_options::value(&m_format)->implicit_value(""), (std::string("Report output format. Valid values are:\n") + formatOptionValues).c_str() ) - ("output,o", boost::program_options::value(&m_output)->implicit_value(""), "Direct the output to the given file") - ("help", boost::program_options::bool_switch(&m_help), "Help to use this sub-command") - ; - - m_commonOptions.add(common_options); - m_commonOptions.add_options() - ("report,r", boost::program_options::value(&m_reportNames)->multitoken()->zero_tokens(),(std::string("The type of report to be produced. Reports currently available are:\n") + reportOptionValues).c_str() ) - ; - - if (m_isUserDomain) - m_hiddenOptions.add_options() - ("element,e", boost::program_options::value(&m_elementsFilter)->multitoken()->zero_tokens(), "Filters individual elements(s) from the report. Format: '///...'") - ; } void -SubCmdExamineInternal::print_help_internal() const +SubCmdExamineInternal::print_help_internal(const SubCmdExamineOptions& options) const { - if (m_device.empty()) + if (options.m_device.empty()) printHelp(); else { - const std::string deviceClass = XBU::get_device_class(m_device, m_isUserDomain); - static const std::string reportOptionValues = XBU::create_suboption_list_map(deviceClass, jsonOptions, common_reports); - std::vector tempVec; - common_options.add_options() - ("report,r", boost::program_options::value(&tempVec)->multitoken(), (std::string("The type of report to be produced. Reports currently available are:\n") + reportOptionValues).c_str() ) - ; - printHelp(common_options, m_hiddenOptions, deviceClass); + const std::string deviceClass = XBU::get_device_class(options.m_device, m_isUserDomain); + printHelp(m_commonOptions, m_hiddenOptions, deviceClass); } } @@ -104,8 +67,10 @@ SubCmdExamineInternal::execute(const SubCmdOptions& _options) const // Parse sub-command ... po::variables_map vm; + SubCmdExamineOptions options; try{ const auto unrecognized_options = process_arguments(vm, _options, false); + fill_option_values(vm, options); if (!unrecognized_options.empty()) { @@ -119,48 +84,48 @@ SubCmdExamineInternal::execute(const SubCmdOptions& _options) const catch (const boost::program_options::error& e) { std::cerr << boost::format("ERROR: %s\n") % e.what(); - print_help_internal(); + print_help_internal(options); throw xrt_core::error(std::errc::operation_canceled); } // Check to see if help was requested - if (m_help) { - print_help_internal(); + if (options.m_help) { + print_help_internal(options); return; } - const auto validated_format = m_format.empty() ? "json" : m_format; + const auto validated_format = options.m_format.empty() ? "json" : options.m_format; Report::SchemaVersion schemaVersion = Report::getSchemaDescription(validated_format).schemaVersion; try{ - if (vm.count("output") && m_output.empty()) + if (vm.count("output") && options.m_output.empty()) throw xrt_core::error("Output file not specified"); - if (vm.count("report") && m_reportNames.empty()) + if (vm.count("report") && options.m_reportNames.empty()) throw xrt_core::error("No report given to be produced"); - if (vm.count("element") && m_elementsFilter.empty()) + if (vm.count("element") && options.m_elementsFilter.empty()) throw xrt_core::error("No element filter given to be produced"); // DRC check // When json is specified, make sure an accompanying output file is also specified - if (!m_format.empty() && m_output.empty()) + if (!options.m_format.empty() && options.m_output.empty()) throw xrt_core::error("Please specify an output file to redirect the json to"); if (schemaVersion == Report::SchemaVersion::unknown) throw xrt_core::error((boost::format("ERROR: Unsupported --format option value '%s'. Supported values can be found in --format's help section below.") % validated_format).str()); - if (!m_output.empty() && std::filesystem::exists(m_output) && !XBU::getForce()) - throw xrt_core::error((boost::format("ERROR: The output file '%s' already exists. Please either remove it or execute this command again with the '--force' option to overwrite it.") % m_output).str()); + if (!options.m_output.empty() && std::filesystem::exists(options.m_output) && !XBU::getForce()) + throw xrt_core::error((boost::format("ERROR: The output file '%s' already exists. Please either remove it or execute this command again with the '--force' option to overwrite it.") % options.m_output).str()); } catch (const xrt_core::error& e) { // Catch only the exceptions that we have generated earlier std::cerr << boost::format("ERROR: %s\n") % e.what(); - print_help_internal(); + print_help_internal(options); throw xrt_core::error(std::errc::operation_canceled); } // Determine report level - std::vector reportsToRun(m_reportNames); + std::vector reportsToRun(options.m_reportNames); if (reportsToRun.empty()) { reportsToRun.push_back("host"); } @@ -169,7 +134,7 @@ SubCmdExamineInternal::execute(const SubCmdOptions& _options) const ReportCollection reportsToProcess; // Reports of interest // Filter out reports that are not compatible for the device - const std::string deviceClass = XBU::get_device_class(m_device, m_isUserDomain); + const std::string deviceClass = XBU::get_device_class(options.m_device, m_isUserDomain); ReportCollection runnableReports = validateConfigurables(deviceClass, std::string("report"), fullReportCollection); // Collect the reports to be processed @@ -177,7 +142,7 @@ SubCmdExamineInternal::execute(const SubCmdOptions& _options) const XBU::collect_and_validate_reports(runnableReports, reportsToRun, reportsToProcess); } catch (const xrt_core::error& e) { std::cerr << boost::format("ERROR: %s\n") % e.what(); - print_help_internal(); + print_help_internal(options); return; } @@ -186,7 +151,7 @@ SubCmdExamineInternal::execute(const SubCmdOptions& _options) const try { if(reportsToProcess.size() > 1 || reportsToRun.front().compare("host") != 0) - device = XBU::get_device(boost::algorithm::to_lower_copy(m_device), m_isUserDomain /*inUserDomain*/); + device = XBU::get_device(boost::algorithm::to_lower_copy(options.m_device), m_isUserDomain /*inUserDomain*/); } catch (const std::runtime_error& e) { // Catch only the exceptions that we have generated earlier std::cerr << boost::format("ERROR: %s\n") % e.what(); @@ -224,26 +189,35 @@ SubCmdExamineInternal::execute(const SubCmdOptions& _options) const // Create the report std::ostringstream oSchemaOutput; try { - XBU::produce_reports(device, reportsToProcess, schemaVersion, m_elementsFilter, std::cout, oSchemaOutput); + XBU::produce_reports(device, reportsToProcess, schemaVersion, options.m_elementsFilter, std::cout, oSchemaOutput); } catch (const std::exception&) { // Exception is thrown at the end of this function to allow for report writing is_report_output_valid = false; } // -- Write output file ---------------------------------------------- - if (!m_output.empty()) { + if (!options.m_output.empty()) { std::ofstream fOutput; - fOutput.open(m_output, std::ios::out | std::ios::binary); + fOutput.open(options.m_output, std::ios::out | std::ios::binary); if (!fOutput.is_open()) { - std::cerr << boost::format("Unable to open the file '%s' for writing.") % m_output << std::endl; + std::cerr << boost::format("Unable to open the file '%s' for writing.") % options.m_output << std::endl; throw xrt_core::error(std::errc::operation_canceled); } fOutput << oSchemaOutput.str(); - std::cout << boost::format("Successfully wrote the %s file: %s") % validated_format % m_output << std::endl; + std::cout << boost::format("Successfully wrote the %s file: %s") % validated_format % options.m_output << std::endl; } if (!is_report_output_valid) throw xrt_core::error(std::errc::operation_canceled); } +void SubCmdExamineInternal::fill_option_values(const po::variables_map& vm, SubCmdExamineOptions& options) const +{ + options.m_device = vm.count("device") ? vm["device"].as() : ""; + options.m_format = vm.count("format") ? vm["format"].as() : ""; + options.m_output = vm.count("output") ? vm["output"].as() : ""; + options.m_reportNames = vm.count("report") ? vm["report"].as>() : std::vector(); + options.m_help = vm.count("help") ? vm["help"].as() : false; + options.m_elementsFilter = vm.count("element") ? vm["element"].as>() : std::vector(); +} diff --git a/src/runtime_src/core/tools/common/SubCmdExamineInternal.h b/src/runtime_src/core/tools/common/SubCmdExamineInternal.h index 809c4fa29a..c800e193f6 100644 --- a/src/runtime_src/core/tools/common/SubCmdExamineInternal.h +++ b/src/runtime_src/core/tools/common/SubCmdExamineInternal.h @@ -7,6 +7,15 @@ #include "tools/common/Report.h" #include "tools/common/SubCmd.h" +struct SubCmdExamineOptions { + std::string m_device; + std::vector m_reportNames; + std::vector m_elementsFilter; + std::string m_format; + std::string m_output; + bool m_help; +}; + class SubCmdExamineInternal : public SubCmd { public: virtual void execute(const SubCmdOptions &_options) const; @@ -18,14 +27,9 @@ class SubCmdExamineInternal : public SubCmd { static ReportCollection uniqueReportCollection; private: - void print_help_internal() const; + void fill_option_values(const boost::program_options::variables_map& vm, SubCmdExamineOptions& options) const; + void print_help_internal(const SubCmdExamineOptions&) const; - std::string m_device; - std::vector m_reportNames; - std::vector m_elementsFilter; - std::string m_format; - std::string m_output; - bool m_help; bool m_isUserDomain; }; diff --git a/src/runtime_src/core/tools/common/SubCmdJsonObjects.cpp b/src/runtime_src/core/tools/common/SubCmdJsonObjects.cpp index 748e8a7ece..79d848ca95 100644 --- a/src/runtime_src/core/tools/common/SubCmdJsonObjects.cpp +++ b/src/runtime_src/core/tools/common/SubCmdJsonObjects.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -29,10 +30,34 @@ static std::unordered_map valueTypeMap = { OptionBasic::OptionBasic(const pt::ptree& configurations) : m_name(configurations.get(std::string(const_name_literal))), - m_description(configurations.get(std::string(const_description_literal))), + m_description(concatenate(configurations, std::string(const_description_literal))), m_tag(configurations.get(std::string(const_tag_literal))) {} +std::string +OptionBasic::concatenate(const pt::ptree& pt, const std::string& path) const +{ + try { + const auto& child = pt.get_child(path); + + // Check if the path is a list + if (child.empty()) { + // Return the single string value + return pt.get(path); + } + else { + // If the child has size, it means its a list. Concatenate strings from the list + return std::accumulate(child.begin(), child.end(), std::string(), + [](const std::string& acc, const boost::property_tree::ptree::value_type& item) { + return acc + item.second.get_value(); + }); + } + } catch (const pt::ptree_error& e) { + std::cerr << "Error: " << e.what() << std::endl; + return ""; + } +} + void OptionBasic::printOption() const { diff --git a/src/runtime_src/core/tools/common/SubCmdJsonObjects.h b/src/runtime_src/core/tools/common/SubCmdJsonObjects.h index 05d6d47323..bce0e18097 100644 --- a/src/runtime_src/core/tools/common/SubCmdJsonObjects.h +++ b/src/runtime_src/core/tools/common/SubCmdJsonObjects.h @@ -32,6 +32,7 @@ class OptionBasic { OptionBasic(const pt::ptree& configurations); + std::string concatenate(const pt::ptree& pt, const std::string& path) const; std::string getName() const { return m_name; } std::string getDescription() const { return m_description; } std::string getTag() const { return m_tag; } diff --git a/src/runtime_src/core/tools/common/XBMain.cpp b/src/runtime_src/core/tools/common/XBMain.cpp index 0b2b560d80..8bbcae84fb 100644 --- a/src/runtime_src/core/tools/common/XBMain.cpp +++ b/src/runtime_src/core/tools/common/XBMain.cpp @@ -179,23 +179,21 @@ void main_(int argc, char** argv, * instead of xrt-smi. * If the device is not found, then load the default xrt-smi config. */ - if (isUserDomain) { - std::shared_ptr device; - boost::property_tree::ptree configTreeMain; - std::string config; - try { - device = XBU::get_device(boost::algorithm::to_lower_copy(sDevice), isUserDomain); - } catch (...) { - device = nullptr; - } - if (device) - config = xrt_core::device_query(device, xrt_core::query::xrt_smi_config::type::options_config); - else - config = XBU::loadDefaultSmiConfig(); - std::istringstream command_config_stream(config); - boost::property_tree::read_json(command_config_stream, configTreeMain); - subCommand->setOptionConfig(configTreeMain); + std::shared_ptr device; + boost::property_tree::ptree configTreeMain; + std::string config; + try { + device = XBU::get_device(boost::algorithm::to_lower_copy(sDevice), isUserDomain); + } catch (...) { + device = nullptr; } + if (device) + config = xrt_core::device_query(device, xrt_core::query::xrt_smi_config::type::options_config); + else + config = XBU::loadDefaultSmiConfig(); + std::istringstream command_config_stream(config); + boost::property_tree::read_json(command_config_stream, configTreeMain); + subCommand->setOptionConfig(configTreeMain); // -- Execute the sub-command subCommand->execute(subcmd_options); diff --git a/src/runtime_src/core/tools/common/XBUtilities.cpp b/src/runtime_src/core/tools/common/XBUtilities.cpp index 001bfb5e37..9f632258eb 100755 --- a/src/runtime_src/core/tools/common/XBUtilities.cpp +++ b/src/runtime_src/core/tools/common/XBUtilities.cpp @@ -780,7 +780,7 @@ XBUtilities::loadDefaultSmiConfig() { return std::string( R"( - { +{ "subcommands": [{ "name" : "validate", @@ -924,33 +924,78 @@ XBUtilities::loadDefaultSmiConfig() [ { "name": "device", + "alias": "d", "description": "The Bus:Device.Function (e.g., 0000:d8:00.0) device of interest", - "tag": "devl", + "tag": "basic", + "default_value": "", + "option_type": "common", "value_type": "string" }, { "name": "format", + "alias": "f", "description": "Report output format", - "tag": "devl", + "tag": "basic", + "default_value": "json", + "options_type": "common", "value_type": "string" }, + { + "name": "output", + "alias": "o", + "description" : "Direct the output to the given file", + "tag": "basic", + "default_value": "", + "option_type": "common", + "value_type" : "string" + }, + { + "name": "help", + "alias": "h", + "description" : "Help to use this sub-command", + "tag": "basic", + "default_value": "", + "option_type": "common", + "value_type" : "none" + }, { "name": "report", + "alias": "r", "description": "The type of report to be produced. Reports currently available are:", "tag": "basic", + "option_type": "common", + "value_type": "array", "options": [ + { + "name": "host", + "tag": "basic", + "description": "Host information" + }, + { + "name": "platform", + "tag": "basic", + "description": "Platforms flashed on the device" + }, { "name": "aie-partitions", "tag": "basic", "description": "AIE partition information" }, { - "name": "telemetry", - "tag": "devl", + "name": "tememetry", + "tag": "basic", "description": "Telemetry data for the device" } ] - } + }, + { + "name": "element", + "alias": "e", + "description" : "Filters individual elements(s) from the report. Format: '///...'", + "tag": "basic", + "option_type": "hidden", + "value_type" : "array" + } ] }, { @@ -973,7 +1018,7 @@ XBUtilities::loadDefaultSmiConfig() } ] }] -} +} )" ); }// end of namespace XBValidateUtils