diff options
author | Martin Braun <martin.braun@ettus.com> | 2019-05-15 10:26:44 -0700 |
---|---|---|
committer | Martin Braun <martin.braun@ettus.com> | 2019-11-26 11:49:14 -0800 |
commit | b8a6c64d6012ab1ec0b3b843fccec2d990d440a3 (patch) | |
tree | 31a99d71af5a6aa2db2a7c9f2a7d19986a2d3856 /host/include | |
parent | d6251df6347390e74784b2fbe116b0e64780547e (diff) | |
download | uhd-b8a6c64d6012ab1ec0b3b843fccec2d990d440a3.tar.gz uhd-b8a6c64d6012ab1ec0b3b843fccec2d990d440a3.tar.bz2 uhd-b8a6c64d6012ab1ec0b3b843fccec2d990d440a3.zip |
rfnoc: Add action API
- Added action_info class
- Allow to send actions from node to node
- Allow to post actions into nodes
- Allow to set default forwarding policies
- Added unit tests
Diffstat (limited to 'host/include')
-rw-r--r-- | host/include/uhd/rfnoc/CMakeLists.txt | 1 | ||||
-rw-r--r-- | host/include/uhd/rfnoc/actions.hpp | 50 | ||||
-rw-r--r-- | host/include/uhd/rfnoc/defaults.hpp | 45 | ||||
-rw-r--r-- | host/include/uhd/rfnoc/node.hpp | 108 |
4 files changed, 187 insertions, 17 deletions
diff --git a/host/include/uhd/rfnoc/CMakeLists.txt b/host/include/uhd/rfnoc/CMakeLists.txt index 894d4fda4..052d44090 100644 --- a/host/include/uhd/rfnoc/CMakeLists.txt +++ b/host/include/uhd/rfnoc/CMakeLists.txt @@ -13,6 +13,7 @@ if(ENABLE_RFNOC) blockdef.hpp block_id.hpp constants.hpp + defaults.hpp dirtifier.hpp graph.hpp node_ctrl_base.hpp diff --git a/host/include/uhd/rfnoc/actions.hpp b/host/include/uhd/rfnoc/actions.hpp new file mode 100644 index 000000000..ac454827c --- /dev/null +++ b/host/include/uhd/rfnoc/actions.hpp @@ -0,0 +1,50 @@ +// +// Copyright 2019 Ettus Research, a National Instruments Brand +// +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#ifndef INCLUDED_LIBUHD_RFNOC_ACTIONS_HPP +#define INCLUDED_LIBUHD_RFNOC_ACTIONS_HPP + +#include <uhd/config.hpp> +#include <string> +#include <vector> +#include <memory> + +namespace uhd { namespace rfnoc { + +/*! Container for an action + * + * In the RFNoC context, an action is comparable to a command. Nodes in the + * graph can send each other actions. action_info is the payload of such an + * action message. Nodes pass shared pointers to action_info objects between + * each other to avoid costly copies of large action_info objects. + */ +struct UHD_API action_info +{ +public: + using sptr = std::shared_ptr<action_info>; + //! A unique counter for this action + const size_t id; + //! A string identifier for this action + std::string key; + //! An arbitrary payload. It is up to consumers and producers to + // (de-)serialize it. + std::vector<uint8_t> payload; + + //! Factory function + static sptr make(const std::string& key="") + { + //return std::make_shared<action_info>(key); + return sptr(new action_info(key)); + } + +private: + action_info(const std::string& key); +}; + +}} /* namespace uhd::rfnoc */ + +#endif /* INCLUDED_LIBUHD_RFNOC_ACTIONS_HPP */ + diff --git a/host/include/uhd/rfnoc/defaults.hpp b/host/include/uhd/rfnoc/defaults.hpp new file mode 100644 index 000000000..3eb9e1d30 --- /dev/null +++ b/host/include/uhd/rfnoc/defaults.hpp @@ -0,0 +1,45 @@ +// +// Copyright 2014 Ettus Research LLC +// Copyright 2018 Ettus Research, a National Instruments Company +// +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#ifndef INCLUDED_LIBUHD_RFNOC_DEFAULTS_HPP +#define INCLUDED_LIBUHD_RFNOC_DEFAULTS_HPP + +#include <string> + +namespace uhd { namespace rfnoc { + +static const std::string CLOCK_KEY_GRAPH("__graph__"); + +static const std::string PROP_KEY_DECIM("decim"); +static const std::string PROP_KEY_SAMP_RATE("samp_rate"); +static const std::string PROP_KEY_SCALING("scaling"); +static const std::string PROP_KEY_TYPE("type"); +static const std::string PROP_KEY_FREQ("freq"); +static const std::string PROP_KEY_TICK_RATE("tick_rate"); +static const std::string PROP_KEY_SPP("spp"); + +static const std::string NODE_ID_SEP("SEP"); + +using io_type_t = std::string; +static const io_type_t IO_TYPE_SC16 = "sc16"; + +static const std::string ACTION_KEY_STREAM_CMD("stream_cmd"); +static const std::string ACTION_KEY_RX_EVENT("rx_event"); + +//! If the block name can't be automatically detected, this name is used +static const std::string DEFAULT_BLOCK_NAME = "Block"; +//! This NOC-ID is used to look up the default block +static const uint32_t DEFAULT_NOC_ID = 0xFFFFFFFF; +static const double DEFAULT_TICK_RATE = 1.0; +// Whenever we need a default spp value use this, unless there are some +// block/device-specific constraints. It will keep the frame size below 1500. +static const int DEFAULT_SPP = 1996; + +}} // namespace uhd::rfnoc + +#endif /* INCLUDED_LIBUHD_RFNOC_DEFAULTS_HPP */ + diff --git a/host/include/uhd/rfnoc/node.hpp b/host/include/uhd/rfnoc/node.hpp index 1e634ecea..54c66c985 100644 --- a/host/include/uhd/rfnoc/node.hpp +++ b/host/include/uhd/rfnoc/node.hpp @@ -7,13 +7,14 @@ #ifndef INCLUDED_LIBUHD_RFNOC_NODE_HPP #define INCLUDED_LIBUHD_RFNOC_NODE_HPP -#include <uhd/rfnoc/property.hpp> +#include <uhd/rfnoc/actions.hpp> #include <uhd/rfnoc/dirtifier.hpp> -#include <uhd/utils/scope_exit.hpp> +#include <uhd/rfnoc/property.hpp> #include <uhd/utils/log.hpp> -#include <boost/graph/adjacency_list.hpp> +#include <uhd/utils/scope_exit.hpp> #include <unordered_map> #include <unordered_set> +#include <boost/graph/adjacency_list.hpp> #include <functional> #include <memory> #include <mutex> @@ -34,6 +35,8 @@ class UHD_API node_t public: using resolver_fn_t = std::function<void(void)>; using resolve_callback_t = std::function<void(void)>; + using action_handler_t = + std::function<void(const res_source_info&, action_info::sptr)>; //! Types of property/action forwarding for those not defined by the block itself enum class forwarding_policy_t { @@ -134,11 +137,6 @@ public: const prop_data_t& get_property( const std::string& id, const size_t instance = 0) /* mutable */; - /****************************************** - * Action Specific - ******************************************/ - // TBW - protected: /****************************************** * Internal Registration Functions @@ -207,20 +205,58 @@ protected: void set_prop_forwarding_policy( forwarding_policy_t policy, const std::string& prop_id = ""); + /****************************************** + * Internal action forwarding + ******************************************/ /*! Handle a request to perform an action. The default action handler * ignores user action and forwards port actions. * - * \param handler The function that is called to handle the action + * \param id The action ID for which this action handler is valid. The first + * argument to the handler will be a uhd::rfnoc::action_info::sptr, + * and its `id` value will match this parameter (unless the same + * action handler is registered multiple times). + * If this function was previously called with the same `id` value, + * the previous action handler is overwritten. + * \param handler The function that is called to handle the action. It needs + * to accept a uhd::rfnoc::res_source_info object, and a + * uhd::rfnoc::action_info::sptr. */ - // void register_action_handler(std::function< - // void(const action_info& info, const res_source_info& src) - //> handler); + void register_action_handler(const std::string& id, action_handler_t&& handler); + + /*! Set an action forwarding policy + * + * Whenever this node is asked to handle an action that is not registered, + * this is how the node knows what to do with the action. For example, the + * FIFO block controller will almost always want to pass on actions to + * the next block. + * + * This method can be called more than once, and it will overwrite previous + * policies. + * Typically, this function should only ever be called from within the + * constructor. + * + * \param policy The policy that is applied (see also forwarding_policy_t). + * \param action_key The action key that this forwarding policy is applied + * to. If \p action_key is not given, it will apply to all + * properties, unless a different policy was given with a + * matching key. + */ + void set_action_forwarding_policy( + forwarding_policy_t policy, const std::string& action_key = ""); + + /*! Post an action to an up- or downstream node in the graph. + * + * If the action is posted to an edge which is not connected, the action + * is lost. + * + * \param edge_info The edge to which this action is posted. If + * edge_info.type == INPUT_EDGE, the that means the action + * will be posted to an upstream node, on port edge_info.instance. + * \param action A reference to the action info object. + * \throws uhd::runtime_error if edge_info is not either INPUT_EDGE or OUTPUT_EDGE + */ + void post_action(const res_source_info& edge_info, action_info::sptr action); - /****************************************** - * Internal action forwarding - ******************************************/ - // TBW - // //! A dirtifyer object, useful for properties that always need updating. static dirtifier_t ALWAYS_DIRTY; @@ -369,6 +405,27 @@ private: property_base_t* incoming_prop, const size_t incoming_port); /************************************************************************** + * Action-Related Methods + *************************************************************************/ + /*! Sets a callback that this node can call if it wants to post actions to + * other nodes. + */ + void set_post_action_callback(action_handler_t&& post_handler) + { + _post_action_cb = std::move(post_handler); + } + + /*! This function gets called by the framework when there's a new action for + * this node. It will then dispatch appropriate action handlers. + * + * \param src_info Tells us on which edge this came in. If + * src_info.type == INPUT_EDGE, then we received this action + * on an input edge. + * \param action A reference to the action object + */ + void receive_action(const res_source_info& src_info, action_info::sptr action); + + /************************************************************************** * Private helpers *************************************************************************/ //! Return true if this node has a port that matches \p port_info @@ -414,6 +471,23 @@ private: std::unordered_map<std::string, forwarding_policy_t> _prop_fwd_policies{{ "", forwarding_policy_t::ONE_TO_ONE}}; + /************************************************************************** + * Action-related attributes + *************************************************************************/ + mutable std::mutex _action_mutex; + + //! Storage for action handlers + std::unordered_map<std::string, action_handler_t> _action_handlers; + + //! Default action forwarding policies + std::unordered_map<std::string, forwarding_policy_t> _action_fwd_policies{{ + "", forwarding_policy_t::ONE_TO_ONE}}; + + //! Callback which allows us to post actions to other nodes in the graph + // + // The default callback will simply drop actions + action_handler_t _post_action_cb = [](const res_source_info&, + action_info::sptr) { /* nop */ }; }; // class node_t }} /* namespace uhd::rfnoc */ |