diff options
| author | Martin Braun <martin.braun@ettus.com> | 2019-06-07 21:37:15 -0700 | 
|---|---|---|
| committer | Martin Braun <martin.braun@ettus.com> | 2019-11-26 11:49:27 -0800 | 
| commit | 6bd43946a71173cbf0f1d318843ba34d6849dc30 (patch) | |
| tree | 35e0b46fc8e399718d6adafcda0929c86e0035ad | |
| parent | 491a74269e7d7d7589119c22f229c994d8a2c3f8 (diff) | |
| download | uhd-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.hpp | 29 | ||||
| -rw-r--r-- | host/include/uhd/rfnoc/node.hpp | 7 | ||||
| -rw-r--r-- | host/lib/include/uhdlib/rfnoc/block_container.hpp | 6 | ||||
| -rw-r--r-- | host/lib/include/uhdlib/rfnoc/node_accessor.hpp | 9 | ||||
| -rw-r--r-- | host/lib/rfnoc/block_container.cpp | 9 | ||||
| -rw-r--r-- | host/lib/rfnoc/noc_block_base.cpp | 13 | ||||
| -rw-r--r-- | host/lib/rfnoc/node.cpp | 5 | ||||
| -rw-r--r-- | host/lib/rfnoc/null_block_control.cpp | 8 | ||||
| -rw-r--r-- | host/lib/rfnoc/rfnoc_graph.cpp | 1 | ||||
| -rw-r--r-- | host/tests/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | host/tests/rfnoc_blocks_test.cpp | 6 | 
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)  | 
