aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--host/lib/include/CMakeLists.txt5
-rw-r--r--host/lib/include/uhdlib/usrp/common/mpmd_mb_controller.hpp17
-rw-r--r--host/lib/include/uhdlib/usrp/common/rpc.py152
-rw-r--r--host/lib/usrp/mpmd/mpmd_mb_controller.cpp55
-rw-r--r--host/lib/usrp/mpmd/mpmd_mboard_impl.cpp2
-rw-r--r--host/tests/CMakeLists.txt1
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