aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Braun <martin.braun@ettus.com>2019-06-07 21:37:15 -0700
committerMartin Braun <martin.braun@ettus.com>2019-11-26 11:49:27 -0800
commit6bd43946a71173cbf0f1d318843ba34d6849dc30 (patch)
tree35e0b46fc8e399718d6adafcda0929c86e0035ad
parent491a74269e7d7d7589119c22f229c994d8a2c3f8 (diff)
downloaduhd-6bd43946a71173cbf0f1d318843ba34d6849dc30.tar.gz
uhd-6bd43946a71173cbf0f1d318843ba34d6849dc30.tar.bz2
uhd-6bd43946a71173cbf0f1d318843ba34d6849dc30.zip
rfnoc: Add shutdown feature to blocks
On destruction, the rfnoc_graph will call shutdown() on all blocks. This allows a safe de-initialization of blocks independent of the lifetime of the noc_block_base::sptr. Also adds the shutdown feature to null_block_control.
-rw-r--r--host/include/uhd/rfnoc/noc_block_base.hpp29
-rw-r--r--host/include/uhd/rfnoc/node.hpp7
-rw-r--r--host/lib/include/uhdlib/rfnoc/block_container.hpp6
-rw-r--r--host/lib/include/uhdlib/rfnoc/node_accessor.hpp9
-rw-r--r--host/lib/rfnoc/block_container.cpp9
-rw-r--r--host/lib/rfnoc/noc_block_base.cpp13
-rw-r--r--host/lib/rfnoc/node.cpp5
-rw-r--r--host/lib/rfnoc/null_block_control.cpp8
-rw-r--r--host/lib/rfnoc/rfnoc_graph.cpp1
-rw-r--r--host/tests/CMakeLists.txt1
-rw-r--r--host/tests/rfnoc_blocks_test.cpp6
11 files changed, 91 insertions, 3 deletions
diff --git a/host/include/uhd/rfnoc/noc_block_base.hpp b/host/include/uhd/rfnoc/noc_block_base.hpp
index e951ffc72..45a1f5738 100644
--- a/host/include/uhd/rfnoc/noc_block_base.hpp
+++ b/host/include/uhd/rfnoc/noc_block_base.hpp
@@ -160,6 +160,25 @@ protected:
*/
std::shared_ptr<mb_controller> get_mb_controller();
+ /*! Safely de-initialize the block
+ *
+ * This function is called by the framework when the RFNoC session is about
+ * to finish to allow blocks to safely perform actions to shut down a block.
+ * For example, if your block is producing samples, like a radio or signal
+ * generator, this is a good place to issue a "stop" command.
+ *
+ * After this function is called, register access is no more possible. So
+ * make sure not to interact with regs() after this was called. Future
+ * access to regs() won't throw, but will print error messages and do
+ * nothing.
+ *
+ * The rationale for having this separate from the destructor is because
+ * rfnoc_graph allows exporting references to blocks, and this function
+ * ensures that blocks are safely shut down when the rest of the device
+ * control goes away.
+ */
+ virtual void deinit();
+
private:
/*! Update the tick rate of this block
*
@@ -168,6 +187,16 @@ private:
*/
void _set_tick_rate(const double tick_rate);
+ /*! Perform a shutdown sequence.
+ *
+ * - Call deinit()
+ * - Invalidate regs()
+ */
+ void shutdown();
+
+ /**************************************************************************
+ * Attributes
+ **************************************************************************/
//! This block's Noc-ID
noc_id_t _noc_id;
diff --git a/host/include/uhd/rfnoc/node.hpp b/host/include/uhd/rfnoc/node.hpp
index f9a1272e1..04b3d863f 100644
--- a/host/include/uhd/rfnoc/node.hpp
+++ b/host/include/uhd/rfnoc/node.hpp
@@ -350,6 +350,13 @@ protected:
virtual bool check_topology(const std::vector<size_t>& connected_inputs,
const std::vector<size_t>& connected_outputs);
+ /*! Perform a shutdown sequence
+ *
+ * This is mostly relevant for noc_block_base implementations. See also
+ * noc_block_base::shutdown().
+ */
+ virtual void shutdown();
+
/**************************************************************************
* Attributes
*************************************************************************/
diff --git a/host/lib/include/uhdlib/rfnoc/block_container.hpp b/host/lib/include/uhdlib/rfnoc/block_container.hpp
index e32feed52..b43a7bc61 100644
--- a/host/lib/include/uhdlib/rfnoc/block_container.hpp
+++ b/host/lib/include/uhdlib/rfnoc/block_container.hpp
@@ -43,6 +43,12 @@ public:
*/
noc_block_base::sptr get_block(const block_id_t& block_id) const;
+ /*! Call shutdown() on all blocks
+ *
+ * After calling this, blocks won't be able to do anything anymore!
+ */
+ void shutdown();
+
private:
//! Lock access to the storage
mutable std::mutex _mutex;
diff --git a/host/lib/include/uhdlib/rfnoc/node_accessor.hpp b/host/lib/include/uhdlib/rfnoc/node_accessor.hpp
index 3351c5531..93e2733cf 100644
--- a/host/lib/include/uhdlib/rfnoc/node_accessor.hpp
+++ b/host/lib/include/uhdlib/rfnoc/node_accessor.hpp
@@ -108,6 +108,15 @@ public:
{
return node->check_topology(connected_inputs, connected_outputs);
}
+
+ /*! Put a node into shutdown
+ *
+ * See node_t::shutdown(), and also noc_block_base::shutdown() for details.
+ */
+ void shutdown(node_t* node)
+ {
+ node->shutdown();
+ }
};
diff --git a/host/lib/rfnoc/block_container.cpp b/host/lib/rfnoc/block_container.cpp
index 0151b228b..6bbb3828b 100644
--- a/host/lib/rfnoc/block_container.cpp
+++ b/host/lib/rfnoc/block_container.cpp
@@ -6,6 +6,7 @@
#include <uhd/utils/log.hpp>
#include <uhdlib/rfnoc/block_container.hpp>
+#include <uhdlib/rfnoc/node_accessor.hpp>
#include <boost/format.hpp>
#include <algorithm>
@@ -72,3 +73,11 @@ noc_block_base::sptr block_container_t::get_block(const block_id_t& block_id) co
return *block_itr;
}
+void block_container_t::shutdown()
+{
+ node_accessor_t node_accessor{};
+ for (auto it = _blocks.begin(); it != _blocks.end(); ++it) {
+ node_accessor.shutdown(it->get());
+ }
+
+}
diff --git a/host/lib/rfnoc/noc_block_base.cpp b/host/lib/rfnoc/noc_block_base.cpp
index 6e72decfe..c0d8cf2a9 100644
--- a/host/lib/rfnoc/noc_block_base.cpp
+++ b/host/lib/rfnoc/noc_block_base.cpp
@@ -113,7 +113,20 @@ void noc_block_base::_set_tick_rate(const double tick_rate)
_tick_rate = tick_rate;
}
+void noc_block_base::shutdown()
+{
+ RFNOC_LOG_TRACE("Calling deinit()");
+ deinit();
+ RFNOC_LOG_DEBUG("Invalidating register interface");
+ update_reg_iface();
+}
+
std::shared_ptr<mb_controller> noc_block_base::get_mb_controller()
{
return _mb_controller;
}
+
+void noc_block_base::deinit()
+{
+ RFNOC_LOG_DEBUG("deinit() called, but not implemented.");
+}
diff --git a/host/lib/rfnoc/node.cpp b/host/lib/rfnoc/node.cpp
index 7eff22eab..b3ad2b380 100644
--- a/host/lib/rfnoc/node.cpp
+++ b/host/lib/rfnoc/node.cpp
@@ -540,6 +540,11 @@ void node_t::receive_action(const res_source_info& src_info, action_info::sptr a
}
}
+void node_t::shutdown()
+{
+ RFNOC_LOG_DEBUG("shutdown() not implemented.");
+}
+
bool node_t::_has_port(const res_source_info& port_info) const
{
return (port_info.type == res_source_info::INPUT_EDGE
diff --git a/host/lib/rfnoc/null_block_control.cpp b/host/lib/rfnoc/null_block_control.cpp
index be0738b76..21042453d 100644
--- a/host/lib/rfnoc/null_block_control.cpp
+++ b/host/lib/rfnoc/null_block_control.cpp
@@ -162,9 +162,11 @@ private:
});
}
- /**************************************************************************
- * FPGA communication (register IO)
- *************************************************************************/
+ void deinit()
+ {
+ issue_stream_cmd(stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS);
+ }
+
/**************************************************************************
* Attributes
diff --git a/host/lib/rfnoc/rfnoc_graph.cpp b/host/lib/rfnoc/rfnoc_graph.cpp
index 201920366..5b2277284 100644
--- a/host/lib/rfnoc/rfnoc_graph.cpp
+++ b/host/lib/rfnoc/rfnoc_graph.cpp
@@ -38,6 +38,7 @@ public:
~rfnoc_graph_impl()
{
_graph.reset();
+ _block_registry->shutdown();
}
/**************************************************************************
diff --git a/host/tests/CMakeLists.txt b/host/tests/CMakeLists.txt
index df891b7e2..d6ad6d777 100644
--- a/host/tests/CMakeLists.txt
+++ b/host/tests/CMakeLists.txt
@@ -252,6 +252,7 @@ UHD_ADD_NONAPI_TEST(
${CMAKE_SOURCE_DIR}/lib/rfnoc/ddc_block_control.cpp
${CMAKE_SOURCE_DIR}/lib/rfnoc/null_block_control.cpp
${CMAKE_SOURCE_DIR}/lib/rfnoc/radio_control_impl.cpp
+ ${CMAKE_SOURCE_DIR}/lib/rfnoc/register_iface_holder.cpp
${CMAKE_SOURCE_DIR}/lib/usrp/cores/dsp_core_utils.cpp
)
diff --git a/host/tests/rfnoc_blocks_test.cpp b/host/tests/rfnoc_blocks_test.cpp
index 1832fc6ae..b69b6f9f8 100644
--- a/host/tests/rfnoc_blocks_test.cpp
+++ b/host/tests/rfnoc_blocks_test.cpp
@@ -125,6 +125,12 @@ BOOST_AUTO_TEST_CASE(test_null_block)
stream_cmd.stream_mode = stream_cmd_t::STREAM_MODE_START_CONTINUOUS;
test_null->issue_stream_cmd(stream_cmd);
BOOST_CHECK_EQUAL(get_mem(null_block_control::REG_CTRL_STATUS) & 0x2, 0x2);
+ node_accessor.shutdown(test_null.get());
+ BOOST_CHECK_EQUAL(get_mem(null_block_control::REG_CTRL_STATUS) & 0x2, 0x0);
+ test_null->issue_stream_cmd(stream_cmd);
+ UHD_LOG_INFO("TEST", "Expected error message here ^^^");
+ // The last issue_stream_cmd should do nothing b/c we called shutdown
+ BOOST_CHECK_EQUAL(get_mem(null_block_control::REG_CTRL_STATUS) & 0x2, 0x0);
}
BOOST_AUTO_TEST_CASE(test_ddc_block)