From 1ac6e6f56100a7e8186481ab0715937759f52737 Mon Sep 17 00:00:00 2001 From: Martin Braun Date: Tue, 2 Jul 2019 11:59:34 -0700 Subject: utils: Add RFNoC-specific features to uhd_usrp_probe - --interactive-reg-shell $BLOCKID will let you peek and poke registers in an RFNoC block - Blocks and static connections are printed --- host/utils/uhd_usrp_probe.cpp | 129 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 120 insertions(+), 9 deletions(-) (limited to 'host/utils/uhd_usrp_probe.cpp') diff --git a/host/utils/uhd_usrp_probe.cpp b/host/utils/uhd_usrp_probe.cpp index 452753aeb..c35a5af23 100644 --- a/host/utils/uhd_usrp_probe.cpp +++ b/host/utils/uhd_usrp_probe.cpp @@ -14,10 +14,14 @@ #include #include #include +#include +#include +#include #include #include //for split #include #include +#include #include #include #include @@ -184,17 +188,34 @@ static std::string get_dboard_pp_string( return ss.str(); } - -static std::string get_rfnoc_pp_string(property_tree::sptr tree, const fs_path& path) +static std::string get_rfnoc_blocks_pp_string(rfnoc::rfnoc_graph::sptr graph) { std::stringstream ss; ss << "RFNoC blocks on this device:" << std::endl << std::endl; - for (const std::string& name : tree->list(path)) { + for (const std::string& name : graph->find_blocks("")) { ss << "* " << name << std::endl; } return ss.str(); } +static std::string get_rfnoc_connections_pp_string(rfnoc::rfnoc_graph::sptr graph) +{ + std::stringstream ss; + ss << "Static connections on this device:" << std::endl << std::endl; + for (const auto& edge : graph->enumerate_static_connections()) { + ss << "* " << edge.to_string() << std::endl; + } + return ss.str(); +} + +static std::string get_rfnoc_pp_string(rfnoc::rfnoc_graph::sptr graph) +{ + std::stringstream ss; + ss << make_border(get_rfnoc_blocks_pp_string(graph)); + ss << make_border(get_rfnoc_connections_pp_string(graph)); + return ss.str(); +} + static std::string get_mboard_pp_string(property_tree::sptr tree, const fs_path& path) { std::stringstream ss; @@ -270,9 +291,6 @@ static std::string get_mboard_pp_string(property_tree::sptr tree, const fs_path& get_dboard_pp_string("TX", tree, path / "dboards" / name)); } } - if (tree->exists(path / "xbar")) { - ss << make_border(get_rfnoc_pp_string(tree, path / "xbar")); - } } catch (const uhd::lookup_error& ex) { std::cout << "Exited device probe on " << ex.what() << std::endl; } @@ -300,6 +318,75 @@ void print_tree(const uhd::fs_path& path, uhd::property_tree::sptr tree) } } +namespace { + + uint32_t str2uint32(const std::string& str) + { + if (str.find("0x") == 0) { + return cast::hexstr_cast(str); + } + return boost::lexical_cast(str); + } + + void shell_print_help() + { + std::cout << "Commands:\n\n" + << "poke32 $addr $data : Write $data to $addr\n" + << "peek32 $addr : Read from $addr and print\n" + << "help : Show this\n" + << "quit : Terminate shell\n" + << std::endl; + } + + void run_interactive_regs_shell(rfnoc::noc_block_base::sptr blk_ctrl) + { + std::cout << "<<< Interactive Block Peeker/Poker >>>" << std::endl; + std::cout << "Type 'help' to get a list of commands." << std::endl; + while (true) { + std::string input; + std::cout << ">>> " <> command; + if (command == "poke32") { + std::string addr_s, data_s; + uint32_t addr, data; + try { + ss >> addr_s >> data_s; + addr = str2uint32(addr_s); + data = str2uint32(data_s); + } catch (std::exception&) { + std::cout << "Usage: poke32 $addr $data" << std::endl; + continue; + } + blk_ctrl->regs().poke32(addr, data); + } + if (command == "peek32") { + std::string addr_s; + uint32_t addr; + try { + ss >> addr_s; + addr = str2uint32(addr_s); + } catch (std::exception&) { + std::cout << "Usage: peek32 $addr" << std::endl; + continue; + } + std::cout << "==> " << std::hex << blk_ctrl->regs().peek32(addr) + << std::dec << std::endl; + } + + if (input == "help") { + shell_print_help(); + } + if (input == "quit") { + return; + } + } + } + +} + int UHD_SAFE_MAIN(int argc, char* argv[]) { po::options_description desc("Allowed options"); @@ -316,6 +403,7 @@ int UHD_SAFE_MAIN(int argc, char* argv[]) ("range", po::value(), "query a range (gain, bandwidth, frequency, ...) from the property tree") ("vector", "when querying a string, interpret that as std::vector") ("init-only", "skip all queries, only initialize device") + ("interactive-reg-iface", po::value(), "RFNoC devices only: Spawn a shell to interactively peek and poke registers on RFNoC blocks") ; // clang-format on @@ -336,6 +424,12 @@ int UHD_SAFE_MAIN(int argc, char* argv[]) device::sptr dev = device::make(vm["args"].as()); property_tree::sptr tree = dev->get_tree(); + rfnoc::rfnoc_graph::sptr graph; + try { + graph = rfnoc::rfnoc_graph::make(vm["args"].as()); + } catch (uhd::key_error&) { + // pass + } if (vm.count("string")) { if (vm.count("vector")) { @@ -382,10 +476,27 @@ int UHD_SAFE_MAIN(int argc, char* argv[]) return EXIT_SUCCESS; } - if (vm.count("tree") != 0) + if (vm.count("interactive-reg-iface")) { + if (!graph) { + std::cout << "ERROR: --interactive-reg-iface requires an RFNoC device!" + << std::endl; + return EXIT_FAILURE; + } + const rfnoc::block_id_t block_id(vm["interactive-reg-iface"].as()); + auto block_ctrl = graph->get_block(block_id); + run_interactive_regs_shell(block_ctrl); + return EXIT_SUCCESS; + } + + if (vm.count("tree") != 0) { print_tree("/", tree); - else if (not vm.count("init-only")) - std::cout << make_border(get_device_pp_string(tree)) << std::endl; + } else if (not vm.count("init-only")) { + std::string device_pp_string = get_device_pp_string(tree); + if (graph) { + device_pp_string += get_rfnoc_pp_string(graph); + } + std::cout << make_border(device_pp_string) << std::endl; + } return EXIT_SUCCESS; } -- cgit v1.2.3