diff options
author | Martin Braun <martin.braun@ettus.com> | 2019-07-23 10:13:38 -0700 |
---|---|---|
committer | Martin Braun <martin.braun@ettus.com> | 2019-11-26 11:49:32 -0800 |
commit | 83abb81e61beec213f9f83843d6fab637a578f4a (patch) | |
tree | c3b95387f4251138f9374cd49b834b04ee10e408 /host | |
parent | 053306f2934e6ac61f03783c36eeff6b2c5ffe0f (diff) | |
download | uhd-83abb81e61beec213f9f83843d6fab637a578f4a.tar.gz uhd-83abb81e61beec213f9f83843d6fab637a578f4a.tar.bz2 uhd-83abb81e61beec213f9f83843d6fab637a578f4a.zip |
rfnoc: actions: Allow sending actions to self
Sending actions to self is useful because calling post_action() from
within an action handler will not actually trigger the action. Instead,
it will defer delivery of the action. Allowing sending actions to self
will allow to add another action, in deterministic order, and the
execution of another action handler.
Diffstat (limited to 'host')
-rw-r--r-- | host/lib/include/uhdlib/rfnoc/node_accessor.hpp | 10 | ||||
-rw-r--r-- | host/lib/rfnoc/graph.cpp | 47 | ||||
-rw-r--r-- | host/lib/rfnoc/node.cpp | 6 | ||||
-rw-r--r-- | host/tests/actions_test.cpp | 7 |
4 files changed, 48 insertions, 22 deletions
diff --git a/host/lib/include/uhdlib/rfnoc/node_accessor.hpp b/host/lib/include/uhdlib/rfnoc/node_accessor.hpp index 93e2733cf..517d2b517 100644 --- a/host/lib/include/uhdlib/rfnoc/node_accessor.hpp +++ b/host/lib/include/uhdlib/rfnoc/node_accessor.hpp @@ -98,6 +98,16 @@ public: node->receive_action(port_info, action); } + /*! Fake a post_action() call from this node + * + * This will call node_t::post_action() (see that for details). + */ + void post_action( + node_t* node, const res_source_info& edge_info, action_info::sptr action) + { + node->post_action(edge_info, action); + } + /*! Check topology for this block * * See node_t::check_topology() for details diff --git a/host/lib/rfnoc/graph.cpp b/host/lib/rfnoc/graph.cpp index 174d72389..ff5fde1e9 100644 --- a/host/lib/rfnoc/graph.cpp +++ b/host/lib/rfnoc/graph.cpp @@ -390,29 +390,36 @@ void graph_t::enqueue_action( _action_queue.pop_front(); // Find the node that is supposed to receive this action, and if we find - // something, then send the action - auto recipient_info = - _find_neighbour(_node_map.at(action_src_node), action_src_port); - if (recipient_info.first == nullptr) { - UHD_LOG_WARNING(LOG_ID, - "Cannot forward action " - << action->key << " from " << src_node->get_unique_id() - << ":" << src_edge.to_string() << ", no neighbour found!"); + // something, then send the action. If the source port's type is USER, + // that means the action is meant for us. + node_ref_t recipient_node; + res_source_info recipient_port(action_src_port); + + if (action_src_port.type == res_source_info::USER) { + recipient_node = action_src_node; + recipient_port = action_src_port; } else { - node_ref_t recipient_node = recipient_info.first; - res_source_info recipient_port = { - res_source_info::invert_edge(action_src_port.type), + auto recipient_info = + _find_neighbour(_node_map.at(action_src_node), action_src_port); + recipient_node = recipient_info.first; + if (recipient_node == nullptr) { + UHD_LOG_WARNING(LOG_ID, + "Cannot forward action " + << action->key << " from " << src_node->get_unique_id() << ":" + << src_edge.to_string() << ", no neighbour found!"); + continue; + } + recipient_port = {res_source_info::invert_edge(action_src_port.type), action_src_port.type == res_source_info::INPUT_EDGE - ? recipient_info.second.dst_port - : recipient_info.second.src_port}; - // The following call can cause other nodes to add more actions to - // the end of _action_queue! - UHD_LOG_TRACE(LOG_ID, - "Now delivering action " << next_action_sptr->key << "#" - << next_action_sptr->id); - node_accessor_t{}.send_action( - recipient_node, recipient_port, next_action_sptr); + ? recipient_info.second.src_port + : recipient_info.second.dst_port}; } + // The following call can cause other nodes to add more actions to + // the end of _action_queue! + UHD_LOG_TRACE(LOG_ID, + "Now delivering action " << next_action_sptr->key << "#" + << next_action_sptr->id); + node_accessor_t{}.send_action(recipient_node, recipient_port, next_action_sptr); } UHD_LOG_TRACE(LOG_ID, "Delivered all actions, terminating action handling."); diff --git a/host/lib/rfnoc/node.cpp b/host/lib/rfnoc/node.cpp index d97588bab..8709df9ef 100644 --- a/host/lib/rfnoc/node.cpp +++ b/host/lib/rfnoc/node.cpp @@ -495,6 +495,12 @@ void node_t::receive_action(const res_source_info& src_info, action_info::sptr a return; } + // We won't forward actions if they were for us + if (src_info.type == res_source_info::USER) { + RFNOC_LOG_TRACE("Dropping USER action " << action->key << "#" << action->id); + return; + } + // Otherwise, we need to figure out the correct default action handling: const auto fwd_policy = [&](const std::string& id) { if (_action_fwd_policies.count(id)) { diff --git a/host/tests/actions_test.cpp b/host/tests/actions_test.cpp index 2f9d9a702..20e2bdf6e 100644 --- a/host/tests/actions_test.cpp +++ b/host/tests/actions_test.cpp @@ -43,11 +43,14 @@ BOOST_AUTO_TEST_CASE(test_actions_single_node) mock_radio.update_fwd_policy(node_t::forwarding_policy_t::ONE_TO_ALL_OUT); node_accessor.send_action(&mock_radio, {res_source_info::INPUT_EDGE, 0}, other_cmd); + uhd::rfnoc::detail::graph_t graph{}; + graph.connect(&mock_radio, &mock_radio, {0, 0, graph_edge_t::DYNAMIC, false}); + graph.commit(); stream_cmd = stream_cmd_action_info::make(uhd::stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_DONE); stream_cmd->stream_cmd.num_samps = 37; - node_accessor.send_action(&mock_radio, {res_source_info::USER, 0}, stream_cmd); - BOOST_CHECK_EQUAL(mock_radio.last_num_samps, 37); + node_accessor.post_action(&mock_radio, {res_source_info::USER, 0}, stream_cmd); + BOOST_REQUIRE_EQUAL(mock_radio.last_num_samps, 37); } BOOST_AUTO_TEST_CASE(test_actions_simple_graph) |