aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib
diff options
context:
space:
mode:
authorMartin Braun <martin.braun@ettus.com>2019-05-31 22:11:42 -0700
committerMartin Braun <martin.braun@ettus.com>2019-11-26 11:49:23 -0800
commitfaa4786e025e787c196eec99f213da0d51a1f87e (patch)
tree17e39f93b0251e6e87e25d37775f10e55c0119fe /host/lib
parent0200aedf4497d5bc4ddf9f3a071ed5395e605f2d (diff)
downloaduhd-faa4786e025e787c196eec99f213da0d51a1f87e.tar.gz
uhd-faa4786e025e787c196eec99f213da0d51a1f87e.tar.bz2
uhd-faa4786e025e787c196eec99f213da0d51a1f87e.zip
rfnoc: Add mb_controller API
The mb_controller is an interface to hardware-specific functions of the motherboard. The API works in two ways: - The user can request access to it, and thus interact directly with the motherboard - RFNoC blocks can request access to it, if they need to interact with the motherboard themselves.
Diffstat (limited to 'host/lib')
-rw-r--r--host/lib/include/uhdlib/rfnoc/factory.hpp5
-rw-r--r--host/lib/rfnoc/CMakeLists.txt1
-rw-r--r--host/lib/rfnoc/mb_controller.cpp73
-rw-r--r--host/lib/rfnoc/noc_block_base.cpp6
-rw-r--r--host/lib/rfnoc/registry_factory.cpp40
-rw-r--r--host/lib/rfnoc/rfnoc_graph.cpp13
6 files changed, 137 insertions, 1 deletions
diff --git a/host/lib/include/uhdlib/rfnoc/factory.hpp b/host/lib/include/uhdlib/rfnoc/factory.hpp
index 3305dda3e..8d1fb27a0 100644
--- a/host/lib/include/uhdlib/rfnoc/factory.hpp
+++ b/host/lib/include/uhdlib/rfnoc/factory.hpp
@@ -24,8 +24,11 @@ public:
*/
static std::pair<registry::factory_t, std::string>
get_block_factory(noc_block_base::noc_id_t noc_id);
-};
+ /*! Check if this block has requested access to the motherboard controller
+ */
+ static bool has_requested_mb_access(noc_block_base::noc_id_t noc_id);
+};
}} /* namespace uhd::rfnoc */
diff --git a/host/lib/rfnoc/CMakeLists.txt b/host/lib/rfnoc/CMakeLists.txt
index 127ad6ffd..d62489484 100644
--- a/host/lib/rfnoc/CMakeLists.txt
+++ b/host/lib/rfnoc/CMakeLists.txt
@@ -30,6 +30,7 @@ LIBUHD_APPEND_SOURCES(
${CMAKE_CURRENT_SOURCE_DIR}/legacy_compat.cpp
${CMAKE_CURRENT_SOURCE_DIR}/link_stream_manager.cpp
${CMAKE_CURRENT_SOURCE_DIR}/graph_stream_manager.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/mb_controller.cpp
${CMAKE_CURRENT_SOURCE_DIR}/noc_block_base.cpp
${CMAKE_CURRENT_SOURCE_DIR}/node_ctrl_base.cpp
${CMAKE_CURRENT_SOURCE_DIR}/node.cpp
diff --git a/host/lib/rfnoc/mb_controller.cpp b/host/lib/rfnoc/mb_controller.cpp
new file mode 100644
index 000000000..10d5ebe47
--- /dev/null
+++ b/host/lib/rfnoc/mb_controller.cpp
@@ -0,0 +1,73 @@
+//
+// Copyright 2019 Ettus Research, a National Instruments Brand
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+//
+
+#include <uhd/rfnoc/mb_controller.hpp>
+#include <uhd/exception.hpp>
+#include <atomic>
+
+using namespace uhd::rfnoc;
+
+
+/******************************************************************************
+ * Timekeeper API
+ *****************************************************************************/
+mb_controller::timekeeper::timekeeper()
+{
+ // nop
+}
+
+uhd::time_spec_t mb_controller::timekeeper::get_time_now()
+{
+ return time_spec_t::from_ticks(get_ticks_now(), _tick_rate);
+}
+
+uhd::time_spec_t mb_controller::timekeeper::get_time_last_pps()
+{
+ return time_spec_t::from_ticks(get_ticks_last_pps(), _tick_rate);
+}
+
+void mb_controller::timekeeper::set_time_now(const uhd::time_spec_t &time)
+{
+ set_ticks_now(time.to_ticks(_tick_rate));
+}
+
+void mb_controller::timekeeper::set_time_next_pps(const uhd::time_spec_t &time)
+{
+ set_ticks_next_pps(time.to_ticks(_tick_rate));
+}
+
+void mb_controller::timekeeper::set_tick_rate(const double tick_rate)
+{
+ if (_tick_rate == tick_rate) {
+ return;
+ }
+ _tick_rate = tick_rate;
+
+ // The period is the inverse of the tick rate, normalized by nanoseconds,
+ // and represented as Q32 (e.g., period == 1ns means period_ns == 1<<32)
+ const uint64_t period_ns = static_cast<uint64_t>(1e9 / tick_rate * (uint64_t(1) << 32));
+ set_period(period_ns);
+}
+
+size_t mb_controller::get_num_timekeepers() const
+{
+ return _timekeepers.size();
+}
+
+mb_controller::timekeeper::sptr mb_controller::get_timekeeper(const size_t tk_idx) const
+{
+ if (!_timekeepers.count(tk_idx)) {
+ throw uhd::index_error(
+ std::string("No timekeeper with index ") + std::to_string(tk_idx));
+ }
+
+ return _timekeepers.at(tk_idx);
+}
+
+void mb_controller::register_timekeeper(const size_t idx, timekeeper::sptr tk)
+{
+ _timekeepers.emplace(idx, std::move(tk));
+}
diff --git a/host/lib/rfnoc/noc_block_base.cpp b/host/lib/rfnoc/noc_block_base.cpp
index 2bbf52928..0b2d456b2 100644
--- a/host/lib/rfnoc/noc_block_base.cpp
+++ b/host/lib/rfnoc/noc_block_base.cpp
@@ -24,6 +24,7 @@ noc_block_base::noc_block_base(make_args_ptr make_args)
, _num_input_ports(make_args->num_input_ports)
, _num_output_ports(make_args->num_output_ports)
, _clock_iface(make_args->clk_iface)
+ , _mb_controller(std::move(make_args->mb_control))
{
// First, create one tick_rate property for every port
_tick_rate_props.reserve(get_num_input_ports() + get_num_output_ports());
@@ -87,3 +88,8 @@ void noc_block_base::_set_tick_rate(const double tick_rate)
_clock_iface->set_freq(tick_rate);
_tick_rate = tick_rate;
}
+
+std::shared_ptr<mb_controller> noc_block_base::get_mb_controller()
+{
+ return _mb_controller;
+}
diff --git a/host/lib/rfnoc/registry_factory.cpp b/host/lib/rfnoc/registry_factory.cpp
index e9ad4f89c..d03cb183a 100644
--- a/host/lib/rfnoc/registry_factory.cpp
+++ b/host/lib/rfnoc/registry_factory.cpp
@@ -35,6 +35,17 @@ using block_descriptor_reg_t =
UHD_SINGLETON_FCN(block_descriptor_reg_t, get_descriptor_block_registry);
///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+// These registries are for blocks that have requested motherboard access
+using block_direct_mb_access_req_t = std::unordered_set<noc_block_base::noc_id_t>;
+UHD_SINGLETON_FCN(block_direct_mb_access_req_t, get_direct_block_mb_access_requested);
+//
+// This is the descriptor registry:
+using block_descriptor_mb_access_req_t = std::unordered_set<std::string>;
+UHD_SINGLETON_FCN(
+ block_descriptor_mb_access_req_t, get_descriptor_block_mb_access_requested);
+///////////////////////////////////////////////////////////////////////////////
+
/******************************************************************************
* Registry functions
*
@@ -68,6 +79,20 @@ void registry::register_block_descriptor(
get_descriptor_block_registry().emplace(block_key, std::move(factory_fn));
}
+void registry::request_mb_access(noc_block_base::noc_id_t noc_id)
+{
+ if (!get_direct_block_mb_access_requested().count(noc_id)) {
+ get_direct_block_mb_access_requested().emplace(noc_id);
+ }
+}
+
+void registry::request_mb_access(const std::string& block_key)
+{
+ if (!get_descriptor_block_mb_access_requested().count(block_key)) {
+ get_descriptor_block_mb_access_requested().emplace(block_key);
+ }
+}
+
/******************************************************************************
* Factory functions
*****************************************************************************/
@@ -87,3 +112,18 @@ std::pair<registry::factory_t, std::string> factory::get_block_factory(
auto& block_info = get_direct_block_registry().at(noc_id);
return {std::get<1>(block_info), std::get<0>(block_info)};
}
+
+bool factory::has_requested_mb_access(noc_block_base::noc_id_t noc_id)
+{
+ if (get_direct_block_mb_access_requested().count(noc_id)) {
+ return true;
+ }
+
+ // FIXME tbw:
+ // - Map noc_id to block key
+ // - Check that key's descriptor
+ // - If that block has requested MB access, stash the noc ID in
+ // get_direct_block_mb_access_requested() for faster lookups in the future
+
+ return false;
+}
diff --git a/host/lib/rfnoc/rfnoc_graph.cpp b/host/lib/rfnoc/rfnoc_graph.cpp
index fef2ccccb..22c9b7294 100644
--- a/host/lib/rfnoc/rfnoc_graph.cpp
+++ b/host/lib/rfnoc/rfnoc_graph.cpp
@@ -6,6 +6,7 @@
#include <uhd/rfnoc/node.hpp>
#include <uhd/rfnoc_graph.hpp>
+#include <uhd/rfnoc/mb_controller.hpp>
#include <uhdlib/rfnoc/block_container.hpp>
#include <uhdlib/rfnoc/graph.hpp>
#include <uhdlib/rfnoc/rfnoc_device.hpp>
@@ -90,6 +91,16 @@ public:
throw uhd::not_implemented_error("");
}
+ std::shared_ptr<mb_controller> get_mb_controller(const size_t mb_index = 0)
+ {
+ if (!_mb_controllers.count(mb_index)) {
+ throw uhd::index_error(
+ std::string("Could not get mb controller for motherboard index ")
+ + std::to_string(mb_index));
+ }
+ return _mb_controllers.at(mb_index);
+ }
+
private:
/**************************************************************************
* Device Setup
@@ -148,6 +159,8 @@ private:
//! Reference to the graph
std::unique_ptr<detail::graph_t> _graph;
+ //! Stash a list of motherboard controllers
+ std::unordered_map<size_t, mb_controller::sptr> _mb_controllers;
}; /* class rfnoc_graph_impl */