diff options
-rw-r--r-- | host/include/uhd/rfnoc_graph.hpp | 16 | ||||
-rw-r--r-- | host/lib/include/uhdlib/rfnoc/graph.hpp | 15 | ||||
-rw-r--r-- | host/lib/rfnoc/graph.cpp | 23 | ||||
-rw-r--r-- | host/lib/rfnoc/rfnoc_graph.cpp | 10 | ||||
-rw-r--r-- | host/tests/actions_test.cpp | 2 | ||||
-rw-r--r-- | host/tests/rfnoc_detailgraph_test.cpp | 4 | ||||
-rw-r--r-- | host/tests/rfnoc_propprop_test.cpp | 15 |
7 files changed, 74 insertions, 11 deletions
diff --git a/host/include/uhd/rfnoc_graph.hpp b/host/include/uhd/rfnoc_graph.hpp index 630f79751..a0a9bf907 100644 --- a/host/include/uhd/rfnoc_graph.hpp +++ b/host/include/uhd/rfnoc_graph.hpp @@ -203,6 +203,22 @@ public: */ std::vector<graph_edge_t> enumerate_connections(); + /*! Commit graph and run initial checks + * + * This method needs to be called when the graph is ready for action. + * It will run checks on the graph and run a property propagation. + * + * \throws uhd::resolve_error if the properties fail to resolve. + */ + virtual void commit() = 0; + + /*! Release graph: Opposite of commit() + * + * Calling this will disable property propagation until commit() has been + * called an equal number of times. + */ + virtual void release() = 0; + /****************************************** * Streaming ******************************************/ diff --git a/host/lib/include/uhdlib/rfnoc/graph.hpp b/host/lib/include/uhdlib/rfnoc/graph.hpp index fdb4525d1..49dc62551 100644 --- a/host/lib/include/uhdlib/rfnoc/graph.hpp +++ b/host/lib/include/uhdlib/rfnoc/graph.hpp @@ -14,6 +14,7 @@ #include <tuple> #include <memory> #include <deque> +#include <atomic> namespace uhd { namespace rfnoc { namespace detail { @@ -44,7 +45,7 @@ public: //const size_t dst_port); // - /*! Run initial checks for graph + /*! Commit graph and run initial checks * * This method can be called anytime, but it's intended to be called when * the graph has been committed. It will run checks on the graph and run a @@ -52,8 +53,14 @@ public: * * \throws uhd::resolve_error if the properties fail to resolve. */ - void initialize(); + void commit(); + /*! Opposite of commit() + * + * Calling this will disable property propagation until commit() has been + * called an equal number of times. + */ + void release(); private: friend class graph_accessor_t; @@ -254,6 +261,10 @@ private: //! Mutex for to avoid the user from sending one message before another // message is sent std::recursive_mutex _action_mutex; + + //! This counter gets decremented everytime commit() is called. When zero, + // the graph is committed. + std::atomic<size_t> _release_count{1}; }; diff --git a/host/lib/rfnoc/graph.cpp b/host/lib/rfnoc/graph.cpp index d311a00bd..f687e8984 100644 --- a/host/lib/rfnoc/graph.cpp +++ b/host/lib/rfnoc/graph.cpp @@ -173,12 +173,21 @@ void graph_t::connect(node_ref_t src_node, node_ref_t dst_node, graph_edge_t edg } } -void graph_t::initialize() +void graph_t::commit() { - UHD_LOG_DEBUG(LOG_ID, "Initializing graph."); + if (_release_count) { + _release_count--; + } + UHD_LOG_TRACE(LOG_ID, "graph::commit() => " << _release_count.load()); resolve_all_properties(); } +void graph_t::release() +{ + UHD_LOG_TRACE(LOG_ID, "graph::release() => " << _release_count.load()); + _release_count++; +} + /****************************************************************************** * Private methods to be called by friends @@ -188,6 +197,9 @@ void graph_t::resolve_all_properties() if (boost::num_vertices(_graph) == 0) { return; } + if (_release_count) { + return; + } node_accessor_t node_accessor{}; // First, find the node on which we'll start. @@ -323,6 +335,13 @@ void graph_t::resolve_all_properties() void graph_t::enqueue_action( node_ref_t src_node, res_source_info src_edge, action_info::sptr action) { + if (_release_count) { + UHD_LOG_WARNING(LOG_ID, + "Action propagation is not enabled, graph is not committed! Will not " + "propagate action `" + << action->key << "'"); + return; + } // First, make sure that once we start action handling, no other node from // a different thread can throw in their own actions std::lock_guard<std::recursive_mutex> l(_action_mutex); diff --git a/host/lib/rfnoc/rfnoc_graph.cpp b/host/lib/rfnoc/rfnoc_graph.cpp index 22c9b7294..94d59da05 100644 --- a/host/lib/rfnoc/rfnoc_graph.cpp +++ b/host/lib/rfnoc/rfnoc_graph.cpp @@ -101,6 +101,16 @@ public: return _mb_controllers.at(mb_index); } + void commit() + { + _graph->commit(); + } + + void release() + { + _graph->release(); + } + private: /************************************************************************** * Device Setup diff --git a/host/tests/actions_test.cpp b/host/tests/actions_test.cpp index b5feb2521..9218ad231 100644 --- a/host/tests/actions_test.cpp +++ b/host/tests/actions_test.cpp @@ -64,7 +64,7 @@ BOOST_AUTO_TEST_CASE(test_actions_simple_graph) graph.connect(&mock_rx_radio, &mock_ddc, {0, 0, graph_edge_t::DYNAMIC, true}); graph.connect(&mock_ddc, &mock_fifo, {0, 0, graph_edge_t::DYNAMIC, true}); graph.connect(&mock_fifo, &mock_streamer, {0, 0, graph_edge_t::DYNAMIC, true}); - graph.initialize(); + graph.commit(); // Force the DDC to actually set a decimation rate != 1 mock_streamer.set_property<double>("samp_rate", 10e6, 0); diff --git a/host/tests/rfnoc_detailgraph_test.cpp b/host/tests/rfnoc_detailgraph_test.cpp index 6273430e6..efae9ff4f 100644 --- a/host/tests/rfnoc_detailgraph_test.cpp +++ b/host/tests/rfnoc_detailgraph_test.cpp @@ -151,7 +151,7 @@ BOOST_AUTO_TEST_CASE(test_graph) topo_sorted_nodes.at(0)->get_unique_id(), mock_rx_radio.get_unique_id()); // Now initialize the graph (will force a call to resolve_all_properties()) - graph.initialize(); + graph.commit(); // This will be ignored graph.connect(&mock_rx_radio, &mock_tx_radio, edge_info); @@ -195,7 +195,7 @@ BOOST_AUTO_TEST_CASE(test_graph_unresolvable) // Now create the graph and commit: graph.connect(&mock_rx_radio, &mock_tx_radio, edge_info); - graph.initialize(); + graph.commit(); // Now set a property that will cause the graph to fail to resolve: BOOST_REQUIRE_THROW(mock_tx_radio.set_property<double>("master_clock_rate", 100e6, 0), diff --git a/host/tests/rfnoc_propprop_test.cpp b/host/tests/rfnoc_propprop_test.cpp index 20d7d96f5..8942a59f0 100644 --- a/host/tests/rfnoc_propprop_test.cpp +++ b/host/tests/rfnoc_propprop_test.cpp @@ -246,7 +246,7 @@ BOOST_AUTO_TEST_CASE(test_graph_resolve_ddc_radio) // Now create the graph and commit: graph.connect(&mock_rx_radio, &mock_ddc, edge_info); graph.connect(&mock_ddc, &mock_tx_radio, edge_info); - graph.initialize(); + graph.commit(); BOOST_CHECK_EQUAL(mock_ddc._decim.get(), 1); mock_tx_radio.set_property<double>("master_clock_rate", 100e6, 0); @@ -256,6 +256,13 @@ BOOST_AUTO_TEST_CASE(test_graph_resolve_ddc_radio) mock_ddc.set_property<int>("decim", 42, 0); // It will bounce back: BOOST_CHECK_EQUAL(mock_ddc._decim.get(), 2); + + graph.release(); + mock_tx_radio.set_property<double>("master_clock_rate", 200e6, 0); + // Won't change yet: + BOOST_CHECK_EQUAL(mock_ddc._decim.get(), 2); + graph.commit(); + BOOST_CHECK_EQUAL(mock_ddc._decim.get(), 1); } @@ -284,7 +291,7 @@ BOOST_AUTO_TEST_CASE(test_graph_catch_invalid_graph) // Now create the graph and commit: graph.connect(&mock_rx_radio, &mock_tx_radio, edge_info); - BOOST_REQUIRE_THROW(graph.initialize(), uhd::resolve_error); + BOOST_REQUIRE_THROW(graph.commit(), uhd::resolve_error); UHD_LOG_INFO("TEST", "^^^ Expected an error message."); } @@ -314,7 +321,7 @@ BOOST_AUTO_TEST_CASE(test_graph_ro_prop) // Now create the graph and commit: graph.connect(&mock_rx_radio, &mock_tx_radio, edge_info); - graph.initialize(); + graph.commit(); const size_t rx_rssi_resolver_count = mock_rx_radio.rssi_resolver_count; UHD_LOG_DEBUG("TEST", "RX RSSI: " << mock_rx_radio.get_property<double>("rssi")); @@ -408,7 +415,7 @@ BOOST_AUTO_TEST_CASE(test_graph_crisscross_fifo) graph.connect(&mock_fifo, &mock_tx_radio0, {1, 0, graph_edge_t::DYNAMIC, true}); graph.connect(&mock_fifo, &mock_tx_radio1, {0, 0, graph_edge_t::DYNAMIC, true}); UHD_LOG_INFO("TEST", "Now testing criss-cross prop resolution"); - graph.initialize(); + graph.commit(); } BOOST_AUTO_TEST_CASE(test_circular_deps) |