Skip to content

Commit

Permalink
xrt-smi re-architecture patch 2 : Config Integration with xrt-smi exa…
Browse files Browse the repository at this point in the history
…mine (Xilinx#8696)

* Json config integration with examine

Signed-off-by: Akshay Tondak <[email protected]>

* config update for alveo devices

Signed-off-by: Akshay Tondak <[email protected]>

* xrt-smi examine help printing clean-up

Signed-off-by: Akshay Tondak <[email protected]>

* alveo config update

Signed-off-by: Akshay Tondak <[email protected]>

* Linting issue fix

Signed-off-by: Akshay Tondak <[email protected]>

---------

Signed-off-by: Akshay Tondak <[email protected]>
  • Loading branch information
aktondak authored Jan 17, 2025
1 parent 33c2eb5 commit 9cbbbba
Show file tree
Hide file tree
Showing 7 changed files with 262 additions and 102 deletions.
133 changes: 123 additions & 10 deletions src/runtime_src/core/pcie/linux/smi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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: '/<key>/<key>/...'",
"tag": "basic",
"option_type": "hidden",
"value_type" : "array"
}
]
},
{
Expand Down
96 changes: 35 additions & 61 deletions src/runtime_src/core/tools/common/SubCmdExamineInternal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,20 +27,11 @@ namespace po = boost::program_options;
#include <regex>

static ReportCollection fullReportCollection = {};
static boost::program_options::options_description common_options;
static std::map<std::string,std::vector<std::shared_ptr<JSONConfigurable>>> 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)
{

Expand All @@ -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<JSONConfigurable, Report>(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<decltype(m_device)>(&m_device), "The Bus:Device.Function (e.g., 0000:d8:00.0) device of interest")
("format,f", boost::program_options::value<decltype(m_format)>(&m_format)->implicit_value(""), (std::string("Report output format. Valid values are:\n") + formatOptionValues).c_str() )
("output,o", boost::program_options::value<decltype(m_output)>(&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<decltype(m_reportNames)>(&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<decltype(m_elementsFilter)>(&m_elementsFilter)->multitoken()->zero_tokens(), "Filters individual elements(s) from the report. Format: '/<key>/<key>/...'")
;
}

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<std::string> tempVec;
common_options.add_options()
("report,r", boost::program_options::value<decltype(tempVec)>(&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);
}
}

Expand All @@ -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())
{
Expand All @@ -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<std::string> reportsToRun(m_reportNames);
std::vector<std::string> reportsToRun(options.m_reportNames);
if (reportsToRun.empty()) {
reportsToRun.push_back("host");
}
Expand All @@ -169,15 +134,15 @@ 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<Report>(deviceClass, std::string("report"), fullReportCollection);

// Collect the reports to be processed
try {
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;
}

Expand All @@ -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();
Expand Down Expand Up @@ -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<std::string>() : "";
options.m_format = vm.count("format") ? vm["format"].as<std::string>() : "";
options.m_output = vm.count("output") ? vm["output"].as<std::string>() : "";
options.m_reportNames = vm.count("report") ? vm["report"].as<std::vector<std::string>>() : std::vector<std::string>();
options.m_help = vm.count("help") ? vm["help"].as<bool>() : false;
options.m_elementsFilter = vm.count("element") ? vm["element"].as<std::vector<std::string>>() : std::vector<std::string>();
}
18 changes: 11 additions & 7 deletions src/runtime_src/core/tools/common/SubCmdExamineInternal.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,15 @@
#include "tools/common/Report.h"
#include "tools/common/SubCmd.h"

struct SubCmdExamineOptions {
std::string m_device;
std::vector<std::string> m_reportNames;
std::vector<std::string> 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;
Expand All @@ -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<std::string> m_reportNames;
std::vector<std::string> m_elementsFilter;
std::string m_format;
std::string m_output;
bool m_help;
bool m_isUserDomain;
};

Expand Down
Loading

0 comments on commit 9cbbbba

Please sign in to comment.