diff options
-rw-r--r-- | host/lib/include/CMakeLists.txt | 5 | ||||
-rw-r--r-- | host/lib/include/uhdlib/usrp/common/mpmd_mb_controller.hpp | 17 | ||||
-rw-r--r-- | host/lib/include/uhdlib/usrp/common/rpc.py | 152 | ||||
-rw-r--r-- | host/lib/usrp/mpmd/mpmd_mb_controller.cpp | 55 | ||||
-rw-r--r-- | host/lib/usrp/mpmd/mpmd_mboard_impl.cpp | 2 | ||||
-rw-r--r-- | host/tests/CMakeLists.txt | 1 |
6 files changed, 195 insertions, 37 deletions
diff --git a/host/lib/include/CMakeLists.txt b/host/lib/include/CMakeLists.txt index fc1a6c4d5..d2ecd88ee 100644 --- a/host/lib/include/CMakeLists.txt +++ b/host/lib/include/CMakeLists.txt @@ -5,4 +5,9 @@ # include_directories(${CMAKE_CURRENT_SOURCE_DIR}) +include_directories(${CMAKE_CURRENT_BINARY_DIR}) +LIBUHD_PYTHON_GEN_SOURCE( + ${CMAKE_CURRENT_SOURCE_DIR}/uhdlib/usrp/common/rpc.py + ${CMAKE_CURRENT_BINARY_DIR}/uhdlib/usrp/common/rpc.hpp +) diff --git a/host/lib/include/uhdlib/usrp/common/mpmd_mb_controller.hpp b/host/lib/include/uhdlib/usrp/common/mpmd_mb_controller.hpp index 7285eb254..acdd361e4 100644 --- a/host/lib/include/uhdlib/usrp/common/mpmd_mb_controller.hpp +++ b/host/lib/include/uhdlib/usrp/common/mpmd_mb_controller.hpp @@ -7,6 +7,7 @@ #pragma once #include <uhd/rfnoc/mb_controller.hpp> +#include <uhdlib/usrp/common/rpc.hpp> #include <uhdlib/utils/rpc.hpp> #include <memory> @@ -23,12 +24,18 @@ class mpmd_mb_controller : public mb_controller public: using sptr = std::shared_ptr<mpmd_mb_controller>; - mpmd_mb_controller(uhd::rpc_client::sptr rpcc, uhd::device_addr_t device_info); + mpmd_mb_controller(uhd::usrp::mpmd_rpc_iface::sptr rpcc, uhd::device_addr_t device_info); //! Return reference to the RPC client uhd::rpc_client::sptr get_rpc_client() { - return _rpc; + return _rpc->get_raw_rpc_client(); + } + + template<typename T> + std::shared_ptr<T> dynamic_cast_rpc_as() + { + return std::dynamic_pointer_cast<T>(_rpc); } /************************************************************************** @@ -42,7 +49,7 @@ public: public: using sptr = std::shared_ptr<mpmd_timekeeper>; - mpmd_timekeeper(const size_t tk_idx, uhd::rpc_client::sptr rpc_client) + mpmd_timekeeper(const size_t tk_idx, uhd::usrp::mpmd_rpc_iface::sptr rpc_client) : _tk_idx(tk_idx), _rpc(rpc_client) { // nop @@ -62,7 +69,7 @@ public: private: const size_t _tk_idx; - uhd::rpc_client::sptr _rpc; + uhd::usrp::mpmd_rpc_iface::sptr _rpc; }; /************************************************************************** @@ -94,7 +101,7 @@ private: * Attributes *************************************************************************/ //! Reference to RPC interface - mutable uhd::rpc_client::sptr _rpc; + mutable uhd::usrp::mpmd_rpc_iface::sptr _rpc; uhd::device_addr_t _device_info; diff --git a/host/lib/include/uhdlib/usrp/common/rpc.py b/host/lib/include/uhdlib/usrp/common/rpc.py new file mode 100644 index 000000000..c484991a6 --- /dev/null +++ b/host/lib/include/uhdlib/usrp/common/rpc.py @@ -0,0 +1,152 @@ +# +# Copyright 2021 Ettus Research, a National Instruments Company +# +# SPDX-License-Identifier: GPL-3.0-or-later +# + +import re +import sys +from mako.template import Template + +class Function: + def __init__(self, return_type, function_name, args): + self.name = function_name + self.does_return = return_type != "void" + self.return_type = return_type + self.arg_names = [arg[1] for arg in args] + self.rpcname = f"\"{function_name}\"" + self.args = [" ".join(arg) for arg in args] + self.has_rpcprefix = False + + def enable_rpcprefix(self): + self.rpcname = f"_rpc_prefix + \"{self.name}\"" + self.has_rpcprefix = True + +class Interface: + def __init__(self, basename, functions, has_rpcprefix=False): + self.basename = basename + self.functions = functions + self.has_rpcprefix = has_rpcprefix + if has_rpcprefix: + for fn in self.functions: + fn.enable_rpcprefix() + +def fn_from_string(function_string): + m = re.match(r"^([a-zA-Z:<>,_0-9 ]+)\s+([a-zA-Z0-9_]+)\(([a-zA-Z0-9,_:&<> ]*)\)$", function_string) + return_type = m.group(1) + function_name = m.group(2) + args = m.group(3) + args = [arg.strip() for arg in args.split(",")] + args = [arg.split(" ") for arg in args if len(arg) > 0] + args = [(" ".join(arg[:-1]), arg[-1]) for arg in args] + return Function(return_type, function_name, args) + +IFACES = [ + Interface("mpmd_rpc", [ + fn_from_string("size_t get_num_timekeepers()"), + fn_from_string("std::vector<std::string> get_mb_sensors()"), + fn_from_string("sensor_value_t::sensor_map_t get_mb_sensor(const std::string& sensor)"), + fn_from_string("std::vector<std::string> get_gpio_banks()"), + fn_from_string("std::vector<std::string> get_gpio_srcs(const std::string& bank)"), + fn_from_string("bool supports_feature(const std::string& feature)"), + fn_from_string("void set_tick_period(size_t tick_index, uint64_t period_ns)"), + fn_from_string("uint64_t get_timekeeper_time(size_t timekeeper_idx, bool last_pps)"), + fn_from_string("void set_timekeeper_time(size_t timekeeper_idx, uint64_t ticks, bool last_pps)"), + fn_from_string("void set_time_source(const std::string& source)"), + fn_from_string("std::string get_time_source()"), + fn_from_string("std::vector<std::string> get_time_sources()"), + fn_from_string("void set_clock_source(const std::string& source)"), + fn_from_string("std::string get_clock_source()"), + fn_from_string("std::vector<std::string> get_clock_sources()"), + Function("void", "set_sync_source", [("const std::map<std::string, std::string>&", "source")]), + fn_from_string("std::map<std::string, std::string> get_sync_source()"), + fn_from_string("std::vector<std::map<std::string, std::string>> get_sync_sources()"), + fn_from_string("void set_clock_source_out(bool enb)"), + fn_from_string("void set_trigger_io(const std::string& direction)"), + fn_from_string("std::map<std::string, std::string> get_mb_eeprom()"), + fn_from_string("std::vector<std::string> get_gpio_src(const std::string& bank)"), + fn_from_string("void set_gpio_src(const std::string& bank, const std::vector<std::string>& src)"), + ]), +] + +COMMON_TMPL = """<% import time %>\ +/*********************************************************************** + * This file was generated by ${file} on ${time.strftime("%c")} + **********************************************************************/ + +// +// Copyright 2021 Ettus Research, a National Instruments Brand +// +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#pragma once + +#include <uhd/types/sensors.hpp> +#include <uhdlib/utils/rpc.hpp> +#include <stddef.h> +#include <memory> +#include <string> +#include <vector> + +namespace uhd { namespace usrp { + +%for iface in ifaces: + class ${iface.basename}_iface { + public: + using sptr = std::shared_ptr<${iface.basename}_iface>; + + %for function in iface.functions: + virtual ${function.return_type} ${function.name}(${",".join(function.args)}) = 0; + %endfor + + // Deprecated + virtual uhd::rpc_client::sptr get_raw_rpc_client() = 0; + }; + + class ${iface.basename} : public ${iface.basename}_iface { + public: + %if iface.has_rpcprefix: + ${iface.basename}(uhd::rpc_client::sptr rpc, const std::string& rpc_prefix) : _rpcc(rpc), _rpc_prefix(rpc_prefix) {} + %else: + ${iface.basename}(uhd::rpc_client::sptr rpc) : _rpcc(rpc) {} + %endif + + %for function in iface.functions: + ${function.return_type} ${function.name}(${",".join(function.args)}) override + { + %if function.does_return: + return _rpcc->request_with_token<${function.return_type}>(${",".join([function.rpcname] + function.arg_names)}); + %else: + _rpcc->notify_with_token(${",".join([function.rpcname] + function.arg_names)}); + %endif + } + %endfor + + // Deprecated + uhd::rpc_client::sptr get_raw_rpc_client() { return _rpcc; } + + private: + uhd::rpc_client::sptr _rpcc; + %if iface.has_rpcprefix: + const std::string _rpc_prefix; + %endif + }; +%endfor + +}} +""" + +def parse_tmpl(_tmpl_text, **kwargs): + return Template(_tmpl_text).render(**kwargs) + +if __name__ == '__main__': + out_file = sys.argv[1] + + code = parse_tmpl(COMMON_TMPL, + ifaces=IFACES, + file=__file__, + ) + + with open(out_file, 'w') as f: + f.write(code) diff --git a/host/lib/usrp/mpmd/mpmd_mb_controller.cpp b/host/lib/usrp/mpmd/mpmd_mb_controller.cpp index 0a9cc54f0..dba8713c4 100644 --- a/host/lib/usrp/mpmd/mpmd_mb_controller.cpp +++ b/host/lib/usrp/mpmd/mpmd_mb_controller.cpp @@ -15,25 +15,23 @@ constexpr size_t MPMD_DEFAULT_LONG_TIMEOUT = 30000; // ms } // namespace mpmd_mb_controller::mpmd_mb_controller( - uhd::rpc_client::sptr rpcc, uhd::device_addr_t device_info) + uhd::usrp::mpmd_rpc_iface::sptr rpcc, uhd::device_addr_t device_info) : _rpc(rpcc), _device_info(device_info) { - const size_t num_tks = _rpc->request_with_token<size_t>("get_num_timekeepers"); + const size_t num_tks = _rpc->get_num_timekeepers(); for (size_t tk_idx = 0; tk_idx < num_tks; tk_idx++) { register_timekeeper(tk_idx, std::make_shared<mpmd_timekeeper>(tk_idx, _rpc)); } // Enumerate sensors - auto sensor_list = - _rpc->request_with_token<std::vector<std::string>>("get_mb_sensors"); + auto sensor_list = _rpc->get_mb_sensors(); UHD_LOG_DEBUG("MPMD", "Found " << sensor_list.size() << " motherboard sensors."); _sensor_names.insert(sensor_list.cbegin(), sensor_list.cend()); // Enumerate GPIO banks that are under mb_controller control - _gpio_banks = _rpc->request_with_token<std::vector<std::string>>("get_gpio_banks"); + _gpio_banks = _rpc->get_gpio_banks(); for (const auto& bank : _gpio_banks) { - _gpio_srcs.insert({bank, - _rpc->request_with_token<std::vector<std::string>>("get_gpio_srcs", bank)}); + _gpio_srcs.insert({bank, _rpc->get_gpio_srcs(bank)}); } } @@ -42,27 +40,27 @@ mpmd_mb_controller::mpmd_mb_controller( *****************************************************************************/ uint64_t mpmd_mb_controller::mpmd_timekeeper::get_ticks_now() { - return _rpc->request_with_token<uint64_t>("get_timekeeper_time", _tk_idx, false); + return _rpc->get_timekeeper_time(_tk_idx, false); } uint64_t mpmd_mb_controller::mpmd_timekeeper::get_ticks_last_pps() { - return _rpc->request_with_token<uint64_t>("get_timekeeper_time", _tk_idx, true); + return _rpc->get_timekeeper_time(_tk_idx, true); } void mpmd_mb_controller::mpmd_timekeeper::set_ticks_now(const uint64_t ticks) { - _rpc->notify_with_token("set_timekeeper_time", _tk_idx, ticks, false); + _rpc->set_timekeeper_time(_tk_idx, ticks, false); } void mpmd_mb_controller::mpmd_timekeeper::set_ticks_next_pps(const uint64_t ticks) { - _rpc->notify_with_token("set_timekeeper_time", _tk_idx, ticks, true); + _rpc->set_timekeeper_time(_tk_idx, ticks, true); } void mpmd_mb_controller::mpmd_timekeeper::set_period(const uint64_t period_ns) { - _rpc->notify_with_token("set_tick_period", _tk_idx, period_ns); + _rpc->set_tick_period(_tk_idx, period_ns); } void mpmd_mb_controller::mpmd_timekeeper::update_tick_rate(const double tick_rate) @@ -80,32 +78,32 @@ std::string mpmd_mb_controller::get_mboard_name() const void mpmd_mb_controller::set_time_source(const std::string& source) { - _rpc->notify_with_token(MPMD_DEFAULT_LONG_TIMEOUT, "set_time_source", source); + _rpc->get_raw_rpc_client()->notify_with_token(MPMD_DEFAULT_LONG_TIMEOUT, "set_time_source", source); } std::string mpmd_mb_controller::get_time_source() const { - return _rpc->request_with_token<std::string>("get_time_source"); + return _rpc->get_time_source(); } std::vector<std::string> mpmd_mb_controller::get_time_sources() const { - return _rpc->request_with_token<std::vector<std::string>>("get_time_sources"); + return _rpc->get_time_sources(); } void mpmd_mb_controller::set_clock_source(const std::string& source) { - _rpc->notify_with_token(MPMD_DEFAULT_LONG_TIMEOUT, "set_clock_source", source); + _rpc->get_raw_rpc_client()->notify_with_token(MPMD_DEFAULT_LONG_TIMEOUT, "set_clock_source", source); } std::string mpmd_mb_controller::get_clock_source() const { - return _rpc->request_with_token<std::string>("get_clock_source"); + return _rpc->get_clock_source(); } std::vector<std::string> mpmd_mb_controller::get_clock_sources() const { - return _rpc->request_with_token<std::vector<std::string>>("get_clock_sources"); + return _rpc->get_clock_sources(); } void mpmd_mb_controller::set_sync_source( @@ -123,23 +121,20 @@ void mpmd_mb_controller::set_sync_source(const device_addr_t& sync_source) for (const auto& key : sync_source.keys()) { sync_source_map[key] = sync_source.get(key); } - _rpc->notify_with_token( - MPMD_DEFAULT_LONG_TIMEOUT, "set_clock_source", sync_source_map); + _rpc->get_raw_rpc_client()->notify_with_token( + MPMD_DEFAULT_LONG_TIMEOUT, "set_sync_source", sync_source_map); } device_addr_t mpmd_mb_controller::get_sync_source() const { - const auto sync_source_map = - _rpc->request_with_token<std::map<std::string, std::string>>("get_sync_source"); + const auto sync_source_map = _rpc->get_sync_source(); return device_addr_t(sync_source_map); } std::vector<device_addr_t> mpmd_mb_controller::get_sync_sources() { std::vector<device_addr_t> result; - const auto sync_sources = - _rpc->request_with_token<std::vector<std::map<std::string, std::string>>>( - "get_sync_sources"); + const auto sync_sources = _rpc->get_sync_sources(); for (auto& sync_source : sync_sources) { result.push_back(device_addr_t(sync_source)); } @@ -164,8 +159,7 @@ sensor_value_t mpmd_mb_controller::get_sensor(const std::string& name) if (!_sensor_names.count(name)) { throw uhd::key_error(std::string("Invalid motherboard sensor name: ") + name); } - return sensor_value_t( - _rpc->request_with_token<sensor_value_t::sensor_map_t>("get_mb_sensor", name)); + return sensor_value_t(_rpc->get_mb_sensor(name)); } std::vector<std::string> mpmd_mb_controller::get_sensor_names() @@ -176,8 +170,7 @@ std::vector<std::string> mpmd_mb_controller::get_sensor_names() uhd::usrp::mboard_eeprom_t mpmd_mb_controller::get_eeprom() { - auto mb_eeprom = - _rpc->request_with_token<std::map<std::string, std::string>>("get_mb_eeprom"); + auto mb_eeprom = _rpc->get_mb_eeprom(); uhd::usrp::mboard_eeprom_t mb_eeprom_dict(mb_eeprom.cbegin(), mb_eeprom.cend()); return mb_eeprom_dict; } @@ -202,7 +195,7 @@ std::vector<std::string> mpmd_mb_controller::get_gpio_src(const std::string& ban UHD_LOG_ERROR("MPMD", "Invalid GPIO bank: `" << bank << "'"); throw uhd::key_error(std::string("Invalid GPIO bank: ") + bank); } - return _rpc->request_with_token<std::vector<std::string>>("get_gpio_src", bank); + return _rpc->get_gpio_src(bank); } void mpmd_mb_controller::set_gpio_src( @@ -212,5 +205,5 @@ void mpmd_mb_controller::set_gpio_src( UHD_LOG_ERROR("MPMD", "Invalid GPIO bank: `" << bank << "'"); throw uhd::key_error(std::string("Invalid GPIO bank: ") + bank); } - _rpc->notify_with_token("set_gpio_src", bank, src); + _rpc->set_gpio_src(bank, src); } diff --git a/host/lib/usrp/mpmd/mpmd_mboard_impl.cpp b/host/lib/usrp/mpmd/mpmd_mboard_impl.cpp index 9fa0d43de..ac620f3e0 100644 --- a/host/lib/usrp/mpmd/mpmd_mboard_impl.cpp +++ b/host/lib/usrp/mpmd/mpmd_mboard_impl.cpp @@ -308,7 +308,7 @@ mpmd_mboard_impl::mpmd_mboard_impl( if (!mb_args.has_key("skip_init")) { // Initialize mb_iface and mb_controller mb_iface = std::make_unique<mpmd_mb_iface>(mb_args, rpc); - mb_ctrl = std::make_shared<rfnoc::mpmd_mb_controller>(rpc, device_info); + mb_ctrl = std::make_shared<rfnoc::mpmd_mb_controller>(std::make_shared<uhd::usrp::mpmd_rpc>(rpc), device_info); } // Note -- when skip_init is used, these are not initialized, and trying // to use them will result in a null pointer dereference exception! } diff --git a/host/tests/CMakeLists.txt b/host/tests/CMakeLists.txt index 99f4e5eaf..e2d192796 100644 --- a/host/tests/CMakeLists.txt +++ b/host/tests/CMakeLists.txt @@ -90,6 +90,7 @@ if(ENABLE_C_API) endif(ENABLE_C_API) include_directories("${CMAKE_SOURCE_DIR}/lib/include") +include_directories("${CMAKE_BINARY_DIR}/lib/include") include_directories("${CMAKE_CURRENT_SOURCE_DIR}/common") #for each source: build an executable, register it as a test |