diff options
author | Martin Braun <martin.braun@ettus.com> | 2019-05-24 14:46:39 -0700 |
---|---|---|
committer | Martin Braun <martin.braun@ettus.com> | 2019-11-26 11:49:16 -0800 |
commit | 1ed37cdfda93e430037ee4028ec5ac70ab223b1b (patch) | |
tree | 16c20409cf18b0747b107092ed64c3beab4f6e89 | |
parent | de6dfccc835ad46b5f4362caae66a37651716ab2 (diff) | |
download | uhd-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.txt | 2 | ||||
-rw-r--r-- | host/include/uhd/rfnoc/noc_block_base.hpp | 21 | ||||
-rw-r--r-- | host/include/uhd/rfnoc/noc_block_make_args.hpp | 44 | ||||
-rw-r--r-- | host/include/uhd/rfnoc/registry.hpp | 78 | ||||
-rw-r--r-- | host/lib/include/uhdlib/rfnoc/factory.hpp | 32 | ||||
-rw-r--r-- | host/lib/rfnoc/CMakeLists.txt | 2 | ||||
-rw-r--r-- | host/lib/rfnoc/noc_block_base.cpp | 18 | ||||
-rw-r--r-- | host/lib/rfnoc/registry_factory.cpp | 88 |
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)}; +} |