aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Braun <martin.braun@ettus.com>2019-05-24 14:46:39 -0700
committerMartin Braun <martin.braun@ettus.com>2019-11-26 11:49:16 -0800
commit1ed37cdfda93e430037ee4028ec5ac70ab223b1b (patch)
tree16c20409cf18b0747b107092ed64c3beab4f6e89
parentde6dfccc835ad46b5f4362caae66a37651716ab2 (diff)
downloaduhd-1ed37cdfda93e430037ee4028ec5ac70ab223b1b.tar.gz
uhd-1ed37cdfda93e430037ee4028ec5ac70ab223b1b.tar.bz2
uhd-1ed37cdfda93e430037ee4028ec5ac70ab223b1b.zip
rfnoc: Add block registry/factory and make_args
- noc_block_base now has a ctor defined - The registry stores factory functions to the individual Noc-Block implementations
-rw-r--r--host/include/uhd/rfnoc/CMakeLists.txt2
-rw-r--r--host/include/uhd/rfnoc/noc_block_base.hpp21
-rw-r--r--host/include/uhd/rfnoc/noc_block_make_args.hpp44
-rw-r--r--host/include/uhd/rfnoc/registry.hpp78
-rw-r--r--host/lib/include/uhdlib/rfnoc/factory.hpp32
-rw-r--r--host/lib/rfnoc/CMakeLists.txt2
-rw-r--r--host/lib/rfnoc/noc_block_base.cpp18
-rw-r--r--host/lib/rfnoc/registry_factory.cpp88
8 files changed, 283 insertions, 2 deletions
diff --git a/host/include/uhd/rfnoc/CMakeLists.txt b/host/include/uhd/rfnoc/CMakeLists.txt
index 319240578..41826a9cb 100644
--- a/host/include/uhd/rfnoc/CMakeLists.txt
+++ b/host/include/uhd/rfnoc/CMakeLists.txt
@@ -16,11 +16,13 @@ if(ENABLE_RFNOC)
defaults.hpp
dirtifier.hpp
graph.hpp
+ noc_block_make_args.hpp
node_ctrl_base.hpp
node_ctrl_base.ipp
node.hpp
node.ipp
rate_node_ctrl.hpp
+ registry.hpp
scalar_node_ctrl.hpp
sink_block_ctrl_base.hpp
sink_node_ctrl.hpp
diff --git a/host/include/uhd/rfnoc/noc_block_base.hpp b/host/include/uhd/rfnoc/noc_block_base.hpp
index 0adcfdafb..b671e6525 100644
--- a/host/include/uhd/rfnoc/noc_block_base.hpp
+++ b/host/include/uhd/rfnoc/noc_block_base.hpp
@@ -13,8 +13,12 @@
#include <uhd/rfnoc/register_iface_holder.hpp>
//! Shorthand for block constructor
-#define UHD_RFNOC_BLOCK_CONSTRUCTOR(CLASS_NAME) \
- CLASS_NAME##_impl(make_args_ptr make_args) : noc_block_base(std::move(make_args))
+#define RFNOC_BLOCK_CONSTRUCTOR(CLASS_NAME) \
+ CLASS_NAME##_impl(make_args_ptr make_args) : CLASS_NAME(std::move(make_args))
+
+#define RFNOC_DECLARE_BLOCK(CLASS_NAME) \
+ using sptr = std::shared_ptr<CLASS_NAME>;\
+ CLASS_NAME(make_args_ptr make_args) : noc_block_base(std::move(make_args)) {}
namespace uhd { namespace rfnoc {
@@ -42,6 +46,14 @@ public:
*/
using noc_id_t = uint32_t;
+ //! Forward declaration for the constructor arguments
+ struct make_args_t;
+
+ //! Opaque pointer to the constructor arguments
+ using make_args_ptr = std::unique_ptr<make_args_t>;
+
+ virtual ~noc_block_base();
+
/**************************************************************************
* node_t API calls
*************************************************************************/
@@ -71,6 +83,9 @@ public:
*/
const block_id_t& get_block_id() const { return _block_id; }
+protected:
+ noc_block_base(make_args_ptr make_args);
+
private:
//! This block's Noc-ID
noc_id_t _noc_id;
@@ -89,4 +104,6 @@ private:
}} /* namespace uhd::rfnoc */
+#include <uhd/rfnoc/noc_block_make_args.hpp>
+
#endif /* INCLUDED_LIBUHD_NOC_BLOCK_BASE_HPP */
diff --git a/host/include/uhd/rfnoc/noc_block_make_args.hpp b/host/include/uhd/rfnoc/noc_block_make_args.hpp
new file mode 100644
index 000000000..8a4b1f5ad
--- /dev/null
+++ b/host/include/uhd/rfnoc/noc_block_make_args.hpp
@@ -0,0 +1,44 @@
+//
+// Copyright 2019 Ettus Research, a National Instruments Brand
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+//
+
+#ifndef INCLUDED_LIBUHD_NOC_BLOCK_MAKE_ARGS_HPP
+#define INCLUDED_LIBUHD_NOC_BLOCK_MAKE_ARGS_HPP
+
+#include <uhd/rfnoc/noc_block_base.hpp>
+#include <uhd/rfnoc/register_iface.hpp>
+#include <uhd/property_tree.hpp>
+
+namespace uhd { namespace rfnoc {
+
+/*! Data structure to hold the arguments passed into the noc_block_base ctor
+ *
+ * We want to hide these from the user, so she can't futz around with them.
+ * Hence the opaque pointer, and non-UHD_API implementation.
+ */
+struct noc_block_base::make_args_t
+{
+ //! Noc-ID
+ noc_id_t noc_id;
+
+ //! Block ID (e.g. 0/Radio#0)
+ block_id_t block_id;
+
+ //! Number of input ports (gets reported from the FPGA)
+ size_t num_input_ports;
+
+ //! Number of output ports (gets reported from the FPGA)
+ size_t num_output_ports;
+
+ //! Register interface to this block's register space
+ register_iface::sptr reg_iface;
+
+ //! The subtree for this block
+ uhd::property_tree::sptr tree;
+};
+
+}} /* namespace uhd::rfnoc */
+
+#endif /* INCLUDED_LIBUHD_NOC_BLOCK_MAKE_ARGS_HPP */
diff --git a/host/include/uhd/rfnoc/registry.hpp b/host/include/uhd/rfnoc/registry.hpp
new file mode 100644
index 000000000..18d896205
--- /dev/null
+++ b/host/include/uhd/rfnoc/registry.hpp
@@ -0,0 +1,78 @@
+//
+// Copyright 2019 Ettus Research, a National Instruments Brand
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+//
+
+#ifndef INCLUDED_LIBUHD_RFNOC_REGISTRY_HPP
+#define INCLUDED_LIBUHD_RFNOC_REGISTRY_HPP
+
+#include <uhd/config.hpp>
+#include <uhd/rfnoc/noc_block_base.hpp>
+#include <uhd/utils/static.hpp>
+#include <functional>
+#include <string>
+
+//! This macro must be placed inside a block implementation file
+// after the class definition
+#define UHD_RFNOC_BLOCK_REGISTER_DIRECT(CLASS_NAME, NOC_ID, BLOCK_NAME) \
+ uhd::rfnoc::noc_block_base::sptr CLASS_NAME##_make( \
+ uhd::rfnoc::noc_block_base::make_args_ptr make_args) \
+ { \
+ return std::make_shared<CLASS_NAME##_impl>(std::move(make_args)); \
+ } \
+ UHD_STATIC_BLOCK(register_rfnoc_##CLASS_NAME) \
+ { \
+ uhd::rfnoc::registry::register_block_direct( \
+ NOC_ID, BLOCK_NAME, &CLASS_NAME##_make); \
+ }
+
+namespace uhd { namespace rfnoc {
+
+/*! RFNoC Block Registry
+ *
+ * A container for various functions to register blocks
+ */
+class UHD_API registry
+{
+public:
+ using factory_t = std::function<noc_block_base::sptr(noc_block_base::make_args_ptr)>;
+
+ /*! Register a block that does not use a block descriptor file
+ *
+ * Note: It is highly recommended to use the UHD_RFNOC_BLOCK_REGISTER_DIRECT()
+ * macro instead of calling this function.
+ *
+ * Use this registry function for blocks that do not read from a textual
+ * description (block descriptor file).
+ *
+ * If the Noc-ID is already registered, it will print an error to stderr and
+ * ignore the new block.
+ *
+ * \param noc_id The 32-bit Noc-ID for this block (e.g. 0xDDC00000)
+ * \param block_name The name used for the block ID (e.g. "Radio")
+ * \param factory_fn A factory function that returns a reference to the
+ * block
+ */
+ static void register_block_direct(noc_block_base::noc_id_t noc_id,
+ const std::string& block_name,
+ factory_t factory_fn);
+
+ /*! Register a block that does use a block descriptor file
+ *
+ * Use this registry function for blocks that also have a textual
+ * description (block descriptor file).
+ *
+ * For these blocks, the framework will first look up the Noc-ID from the
+ * blocks on the FPGA, and then find the corresponding block key by
+ * searching all the availble block descriptor files. When such a key is
+ * found, it will be used to find a block that was previously registered
+ * here.
+ */
+ static void register_block_descriptor(const std::string& block_key,
+ factory_t factory_fn);
+};
+
+}} /* namespace uhd::rfnoc */
+
+#endif /* INCLUDED_LIBUHD_RFNOC_REGISTRY_HPP */
diff --git a/host/lib/include/uhdlib/rfnoc/factory.hpp b/host/lib/include/uhdlib/rfnoc/factory.hpp
new file mode 100644
index 000000000..3305dda3e
--- /dev/null
+++ b/host/lib/include/uhdlib/rfnoc/factory.hpp
@@ -0,0 +1,32 @@
+//
+// Copyright 2019 Ettus Research, a National Instruments Brand
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+//
+
+#ifndef INCLUDED_LIBUHD_RFNOC_FACTORY_HPP
+#define INCLUDED_LIBUHD_RFNOC_FACTORY_HPP
+
+#include <uhd/rfnoc/registry.hpp>
+#include <uhd/rfnoc/noc_block_base.hpp>
+
+namespace uhd { namespace rfnoc {
+
+/*! Container for factory functionality
+ */
+class factory
+{
+public:
+ /*! Return a factory function for an RFNoC block based on the Noc-ID
+ *
+ * \returns a pair: factory function, and block name
+ * \throws uhd::lookup_error if no block is found
+ */
+ static std::pair<registry::factory_t, std::string>
+ get_block_factory(noc_block_base::noc_id_t noc_id);
+};
+
+
+}} /* namespace uhd::rfnoc */
+
+#endif /* INCLUDED_LIBUHD_RFNOC_FACTORY_HPP */
diff --git a/host/lib/rfnoc/CMakeLists.txt b/host/lib/rfnoc/CMakeLists.txt
index 2c13c1819..57a5253a7 100644
--- a/host/lib/rfnoc/CMakeLists.txt
+++ b/host/lib/rfnoc/CMakeLists.txt
@@ -1,6 +1,7 @@
#
# Copyright 2014-2015,2017 Ettus Research LLC
# Copyright 2018 Ettus Research, a National Instruments Company
+# Copyright 2019 Ettus Research, a National Instruments Brand
#
# SPDX-License-Identifier: GPL-3.0-or-later
#
@@ -30,6 +31,7 @@ LIBUHD_APPEND_SOURCES(
${CMAKE_CURRENT_SOURCE_DIR}/rate_node_ctrl.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ctrlport_endpoint.cpp
${CMAKE_CURRENT_SOURCE_DIR}/chdr_ctrl_endpoint.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/registry_factory.cpp
${CMAKE_CURRENT_SOURCE_DIR}/rx_stream_terminator.cpp
${CMAKE_CURRENT_SOURCE_DIR}/scalar_node_ctrl.cpp
${CMAKE_CURRENT_SOURCE_DIR}/sink_block_ctrl_base.cpp
diff --git a/host/lib/rfnoc/noc_block_base.cpp b/host/lib/rfnoc/noc_block_base.cpp
index 3cacc455b..838e05e74 100644
--- a/host/lib/rfnoc/noc_block_base.cpp
+++ b/host/lib/rfnoc/noc_block_base.cpp
@@ -5,7 +5,25 @@
//
#include <uhd/rfnoc/noc_block_base.hpp>
+#include <uhd/rfnoc/register_iface.hpp>
#include <uhd/exception.hpp>
using namespace uhd::rfnoc;
+/******************************************************************************
+ * Structors
+ *****************************************************************************/
+noc_block_base::noc_block_base(make_args_ptr make_args)
+ : register_iface_holder(std::move(make_args->reg_iface))
+ , _noc_id(make_args->noc_id)
+ , _block_id(make_args->block_id)
+ , _num_input_ports(make_args->num_input_ports)
+ , _num_output_ports(make_args->num_output_ports)
+{
+}
+
+noc_block_base::~noc_block_base()
+{
+ // nop
+}
+
diff --git a/host/lib/rfnoc/registry_factory.cpp b/host/lib/rfnoc/registry_factory.cpp
new file mode 100644
index 000000000..cf7b897f7
--- /dev/null
+++ b/host/lib/rfnoc/registry_factory.cpp
@@ -0,0 +1,88 @@
+//
+// Copyright 2019 Ettus Research, a National Instruments Brand
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+//
+
+#include <uhd/exception.hpp>
+#include <uhd/rfnoc/registry.hpp>
+#include <uhd/utils/static.hpp>
+#include <uhdlib/rfnoc/factory.hpp>
+#include <unordered_map>
+#include <iomanip>
+#include <iostream>
+#include <sstream>
+
+using namespace uhd::rfnoc;
+
+///////////////////////////////////////////////////////////////////////////////
+// There are two registries:
+// - The "direct" registry, which is for blocks that do not have a block
+// descriptor file
+// - The "descriptor" registry, which is for blocks that *do* have a block
+// descriptor file
+//
+// This is the direct registry:
+using block_direct_reg_t = std::unordered_map<noc_block_base::noc_id_t,
+ std::tuple<std::string /* block_name */,
+ registry::factory_t>>;
+UHD_SINGLETON_FCN(block_direct_reg_t, get_direct_block_registry);
+//
+// This is the descriptor registry:
+using block_descriptor_reg_t =
+ std::unordered_map<std::string /* block_key */, registry::factory_t>;
+UHD_SINGLETON_FCN(block_descriptor_reg_t, get_descriptor_block_registry);
+///////////////////////////////////////////////////////////////////////////////
+
+/******************************************************************************
+ * Registry functions
+ *
+ * Note: Don't use UHD_LOG_*, since all of this can be executed in a static
+ * fashion.
+ *****************************************************************************/
+void registry::register_block_direct(noc_block_base::noc_id_t noc_id,
+ const std::string& block_name,
+ factory_t factory_fn)
+{
+ if (get_direct_block_registry().count(noc_id)) {
+ std::cerr
+ << "[REGISTRY] WARNING: Attempting to overwrite previously registered RFNoC "
+ "block with Noc-ID 0x"
+ << std::hex << noc_id << std::dec << std::endl;
+ return;
+ }
+ get_direct_block_registry().emplace(
+ noc_id, std::make_tuple(block_name, std::move(factory_fn)));
+}
+
+void registry::register_block_descriptor(
+ const std::string& block_key, factory_t factory_fn)
+{
+ if (get_descriptor_block_registry().count(block_key)) {
+ std::cerr << "WARNING: Attempting to overwriting previously registered RFNoC "
+ "block with block key"
+ << block_key << std::endl;
+ return;
+ }
+ get_descriptor_block_registry().emplace(block_key, std::move(factory_fn));
+}
+
+/******************************************************************************
+ * Factory functions
+ *****************************************************************************/
+std::pair<registry::factory_t, std::string> factory::get_block_factory(
+ noc_block_base::noc_id_t noc_id)
+{
+ // First, check the descriptor registry
+ // FIXME TODO
+
+ // Second, check the direct registry
+ if (!get_direct_block_registry().count(noc_id)) {
+ UHD_LOG_WARNING("RFNOC::BLOCK_FACTORY",
+ "Could not find block with Noc-ID "
+ << std::hex << std::setw(sizeof(noc_block_base::noc_id_t) * 2) << noc_id);
+ throw uhd::key_error("Block not found!");
+ }
+ auto& block_info = get_direct_block_registry().at(noc_id);
+ return {std::get<1>(block_info), std::get<0>(block_info)};
+}