aboutsummaryrefslogtreecommitdiffstats
path: root/host/include
diff options
context:
space:
mode:
authorMartin Braun <martin.braun@ettus.com>2019-05-15 10:26:44 -0700
committerMartin Braun <martin.braun@ettus.com>2019-11-26 11:49:14 -0800
commitb8a6c64d6012ab1ec0b3b843fccec2d990d440a3 (patch)
tree31a99d71af5a6aa2db2a7c9f2a7d19986a2d3856 /host/include
parentd6251df6347390e74784b2fbe116b0e64780547e (diff)
downloaduhd-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.txt1
-rw-r--r--host/include/uhd/rfnoc/actions.hpp50
-rw-r--r--host/include/uhd/rfnoc/defaults.hpp45
-rw-r--r--host/include/uhd/rfnoc/node.hpp108
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 */