1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright © 2020-2021 Collabora, Ltd. 3bf215546Sopenharmony_ci * Author: Antonio Caggiano <antonio.caggiano@collabora.com> 4bf215546Sopenharmony_ci * 5bf215546Sopenharmony_ci * SPDX-License-Identifier: MIT 6bf215546Sopenharmony_ci */ 7bf215546Sopenharmony_ci 8bf215546Sopenharmony_ci#include <pps/pps_driver.h> 9bf215546Sopenharmony_ci 10bf215546Sopenharmony_ci#include <charconv> 11bf215546Sopenharmony_ci#include <cstdlib> 12bf215546Sopenharmony_ci#include <cstring> 13bf215546Sopenharmony_ci#include <optional> 14bf215546Sopenharmony_ci#include <thread> 15bf215546Sopenharmony_ci 16bf215546Sopenharmony_ci#include <docopt/docopt.h> 17bf215546Sopenharmony_ci 18bf215546Sopenharmony_cistatic const char *USAGE = 19bf215546Sopenharmony_ci R"(pps-config 20bf215546Sopenharmony_ci 21bf215546Sopenharmony_ci Usage: 22bf215546Sopenharmony_ci pps-config info 23bf215546Sopenharmony_ci pps-config dump [--gpu=<n>] [--ids=<n>] [--sec=<n>] 24bf215546Sopenharmony_ci pps-config groups [--gpu=<n>] 25bf215546Sopenharmony_ci pps-config counters [--gpu=<n>] 26bf215546Sopenharmony_ci pps-config (-h | --help) 27bf215546Sopenharmony_ci pps-config --version 28bf215546Sopenharmony_ci 29bf215546Sopenharmony_ci Options: 30bf215546Sopenharmony_ci -h --help Show this screen. 31bf215546Sopenharmony_ci --version Show version. 32bf215546Sopenharmony_ci --gpu=<n> GPU number to query [default: 0]. 33bf215546Sopenharmony_ci --ids=<n> Comma separated list of numbers. 34bf215546Sopenharmony_ci --sec=<n> Seconds to wait before dumping performance counters [default: 1]. 35bf215546Sopenharmony_ci)"; 36bf215546Sopenharmony_ci 37bf215546Sopenharmony_ci// Tool running mode 38bf215546Sopenharmony_cienum class Mode { 39bf215546Sopenharmony_ci // Show help message 40bf215546Sopenharmony_ci Help, 41bf215546Sopenharmony_ci 42bf215546Sopenharmony_ci // Show system information 43bf215546Sopenharmony_ci Info, 44bf215546Sopenharmony_ci 45bf215546Sopenharmony_ci // Show list of available counters 46bf215546Sopenharmony_ci Counters, 47bf215546Sopenharmony_ci 48bf215546Sopenharmony_ci // Groups 49bf215546Sopenharmony_ci Groups, 50bf215546Sopenharmony_ci 51bf215546Sopenharmony_ci // Dump performance counters 52bf215546Sopenharmony_ci Dump, 53bf215546Sopenharmony_ci}; 54bf215546Sopenharmony_ci 55bf215546Sopenharmony_cistd::vector<std::string_view> split(const std::string &list, const std::string &separator) 56bf215546Sopenharmony_ci{ 57bf215546Sopenharmony_ci std::vector<std::string_view> ret; 58bf215546Sopenharmony_ci std::string_view list_view = list; 59bf215546Sopenharmony_ci while (!list_view.empty()) { 60bf215546Sopenharmony_ci size_t pos = list_view.find(separator); 61bf215546Sopenharmony_ci if (pos == std::string::npos) { 62bf215546Sopenharmony_ci ret.push_back(list_view); 63bf215546Sopenharmony_ci break; 64bf215546Sopenharmony_ci } 65bf215546Sopenharmony_ci ret.push_back(list_view.substr(0, pos)); 66bf215546Sopenharmony_ci list_view = list_view.substr(pos + separator.length(), list_view.length()); 67bf215546Sopenharmony_ci } 68bf215546Sopenharmony_ci return ret; 69bf215546Sopenharmony_ci} 70bf215546Sopenharmony_ci 71bf215546Sopenharmony_cistd::optional<uint32_t> to_counter_id(const std::string_view &view) 72bf215546Sopenharmony_ci{ 73bf215546Sopenharmony_ci uint32_t counter_id = 0; 74bf215546Sopenharmony_ci 75bf215546Sopenharmony_ci auto res = std::from_chars(view.data(), view.data() + view.size(), counter_id); 76bf215546Sopenharmony_ci if (res.ec == std::errc::invalid_argument) { 77bf215546Sopenharmony_ci return std::nullopt; 78bf215546Sopenharmony_ci } 79bf215546Sopenharmony_ci 80bf215546Sopenharmony_ci return counter_id; 81bf215546Sopenharmony_ci} 82bf215546Sopenharmony_ci 83bf215546Sopenharmony_ciint main(int argc, const char **argv) 84bf215546Sopenharmony_ci{ 85bf215546Sopenharmony_ci using namespace pps; 86bf215546Sopenharmony_ci 87bf215546Sopenharmony_ci Mode mode = Mode::Help; 88bf215546Sopenharmony_ci auto secs = std::chrono::seconds(1); 89bf215546Sopenharmony_ci uint32_t gpu_num = 0; 90bf215546Sopenharmony_ci std::vector<uint32_t> counter_ids; 91bf215546Sopenharmony_ci 92bf215546Sopenharmony_ci auto args = 93bf215546Sopenharmony_ci docopt::docopt(USAGE, {std::next(argv), std::next(argv, argc)}, true, "pps-config 0.3"); 94bf215546Sopenharmony_ci 95bf215546Sopenharmony_ci if (args["info"].asBool()) { 96bf215546Sopenharmony_ci mode = Mode::Info; 97bf215546Sopenharmony_ci } 98bf215546Sopenharmony_ci 99bf215546Sopenharmony_ci if (args["dump"].asBool()) { 100bf215546Sopenharmony_ci mode = Mode::Dump; 101bf215546Sopenharmony_ci } 102bf215546Sopenharmony_ci 103bf215546Sopenharmony_ci if (args["--gpu"]) { 104bf215546Sopenharmony_ci gpu_num = static_cast<uint32_t>(args["--gpu"].asLong()); 105bf215546Sopenharmony_ci } 106bf215546Sopenharmony_ci 107bf215546Sopenharmony_ci if (args["--ids"]) { 108bf215546Sopenharmony_ci auto comma_separated_list = args["--ids"].asString(); 109bf215546Sopenharmony_ci std::vector<std::string_view> ids_list = split(comma_separated_list, ","); 110bf215546Sopenharmony_ci 111bf215546Sopenharmony_ci for (auto &id : ids_list) { 112bf215546Sopenharmony_ci if (auto counter_id = to_counter_id(id)) { 113bf215546Sopenharmony_ci counter_ids.push_back(*counter_id); 114bf215546Sopenharmony_ci } else { 115bf215546Sopenharmony_ci fprintf(stderr, "Failed to parse counter ids: %s\n", comma_separated_list.c_str()); 116bf215546Sopenharmony_ci return EXIT_FAILURE; 117bf215546Sopenharmony_ci } 118bf215546Sopenharmony_ci } 119bf215546Sopenharmony_ci } 120bf215546Sopenharmony_ci 121bf215546Sopenharmony_ci if (args["--sec"]) { 122bf215546Sopenharmony_ci secs = std::chrono::seconds(args["--sec"].asLong()); 123bf215546Sopenharmony_ci } 124bf215546Sopenharmony_ci 125bf215546Sopenharmony_ci if (args["groups"].asBool()) { 126bf215546Sopenharmony_ci mode = Mode::Groups; 127bf215546Sopenharmony_ci } 128bf215546Sopenharmony_ci 129bf215546Sopenharmony_ci if (args["counters"].asBool()) { 130bf215546Sopenharmony_ci mode = Mode::Counters; 131bf215546Sopenharmony_ci } 132bf215546Sopenharmony_ci 133bf215546Sopenharmony_ci // Docopt shows the help message for us 134bf215546Sopenharmony_ci if (mode == Mode::Help) { 135bf215546Sopenharmony_ci return EXIT_SUCCESS; 136bf215546Sopenharmony_ci } 137bf215546Sopenharmony_ci 138bf215546Sopenharmony_ci switch (mode) { 139bf215546Sopenharmony_ci default: 140bf215546Sopenharmony_ci break; 141bf215546Sopenharmony_ci case Mode::Info: { 142bf215546Sopenharmony_ci // Header: device name, and whether it is supported or not 143bf215546Sopenharmony_ci printf("#%4s %16s %16s\n", "num", "device", "support"); 144bf215546Sopenharmony_ci 145bf215546Sopenharmony_ci auto devices = DrmDevice::create_all(); 146bf215546Sopenharmony_ci for (auto &device : devices) { 147bf215546Sopenharmony_ci auto gpu_num = device.gpu_num; 148bf215546Sopenharmony_ci auto name = device.name; 149bf215546Sopenharmony_ci auto driver = Driver::get_driver(std::move(device)); 150bf215546Sopenharmony_ci printf(" %4u %16s %16s\n", gpu_num, name.c_str(), driver ? "yes" : "no"); 151bf215546Sopenharmony_ci } 152bf215546Sopenharmony_ci 153bf215546Sopenharmony_ci break; 154bf215546Sopenharmony_ci } 155bf215546Sopenharmony_ci case Mode::Dump: { 156bf215546Sopenharmony_ci if (auto device = DrmDevice::create(gpu_num)) { 157bf215546Sopenharmony_ci if (auto driver = Driver::get_driver(std::move(device.value()))) { 158bf215546Sopenharmony_ci driver->init_perfcnt(); 159bf215546Sopenharmony_ci 160bf215546Sopenharmony_ci // Enable counters 161bf215546Sopenharmony_ci if (counter_ids.empty()) { 162bf215546Sopenharmony_ci driver->enable_all_counters(); 163bf215546Sopenharmony_ci } else { 164bf215546Sopenharmony_ci for (auto id : counter_ids) { 165bf215546Sopenharmony_ci driver->enable_counter(id); 166bf215546Sopenharmony_ci } 167bf215546Sopenharmony_ci } 168bf215546Sopenharmony_ci 169bf215546Sopenharmony_ci driver->enable_perfcnt(std::chrono::nanoseconds(secs).count()); 170bf215546Sopenharmony_ci std::this_thread::sleep_for(std::chrono::seconds(secs)); 171bf215546Sopenharmony_ci 172bf215546Sopenharmony_ci // Try dumping until it succeeds 173bf215546Sopenharmony_ci while (!driver->dump_perfcnt()) 174bf215546Sopenharmony_ci ; 175bf215546Sopenharmony_ci // Try collecting samples until it succeeds 176bf215546Sopenharmony_ci while (!driver->next()) 177bf215546Sopenharmony_ci ; 178bf215546Sopenharmony_ci 179bf215546Sopenharmony_ci printf("#%32s %32s\n", "counter", "value"); 180bf215546Sopenharmony_ci for (auto &counter : driver->enabled_counters) { 181bf215546Sopenharmony_ci printf(" %32s ", counter.name.c_str()); 182bf215546Sopenharmony_ci auto value = counter.get_value(*driver); 183bf215546Sopenharmony_ci if (auto d_val = std::get_if<double>(&value)) { 184bf215546Sopenharmony_ci printf("%32f\n", *d_val); 185bf215546Sopenharmony_ci } else if (auto i_val = std::get_if<int64_t>(&value)) 186bf215546Sopenharmony_ci printf("%32li\n", *i_val); 187bf215546Sopenharmony_ci else { 188bf215546Sopenharmony_ci printf("%32s\n", "error"); 189bf215546Sopenharmony_ci } 190bf215546Sopenharmony_ci } 191bf215546Sopenharmony_ci } 192bf215546Sopenharmony_ci } 193bf215546Sopenharmony_ci break; 194bf215546Sopenharmony_ci } 195bf215546Sopenharmony_ci case Mode::Groups: { 196bf215546Sopenharmony_ci if (auto device = DrmDevice::create(gpu_num)) { 197bf215546Sopenharmony_ci if (auto driver = Driver::get_driver(std::move(device.value()))) { 198bf215546Sopenharmony_ci driver->init_perfcnt(); 199bf215546Sopenharmony_ci printf("#%4s %32s\n", "id", "name"); 200bf215546Sopenharmony_ci 201bf215546Sopenharmony_ci for (auto &group : driver->groups) { 202bf215546Sopenharmony_ci printf(" %4u %32s\n", group.id, group.name.c_str()); 203bf215546Sopenharmony_ci } 204bf215546Sopenharmony_ci } 205bf215546Sopenharmony_ci } 206bf215546Sopenharmony_ci 207bf215546Sopenharmony_ci break; 208bf215546Sopenharmony_ci } 209bf215546Sopenharmony_ci case Mode::Counters: { 210bf215546Sopenharmony_ci if (auto device = DrmDevice::create(gpu_num)) { 211bf215546Sopenharmony_ci if (auto driver = Driver::get_driver(std::move(device.value()))) { 212bf215546Sopenharmony_ci driver->init_perfcnt(); 213bf215546Sopenharmony_ci printf("#%4s %32s\n", "id", "name"); 214bf215546Sopenharmony_ci 215bf215546Sopenharmony_ci for (uint32_t i = 0; i < driver->counters.size(); ++i) { 216bf215546Sopenharmony_ci auto &counter = driver->counters[i]; 217bf215546Sopenharmony_ci printf(" %4u %32s\n", counter.id, counter.name.c_str()); 218bf215546Sopenharmony_ci } 219bf215546Sopenharmony_ci } 220bf215546Sopenharmony_ci } 221bf215546Sopenharmony_ci 222bf215546Sopenharmony_ci break; 223bf215546Sopenharmony_ci } 224bf215546Sopenharmony_ci } // switch 225bf215546Sopenharmony_ci 226bf215546Sopenharmony_ci return EXIT_SUCCESS; 227bf215546Sopenharmony_ci} 228