diff options
author | Brent Stapleton <brent.stapleton@ettus.com> | 2019-06-04 16:59:22 -0700 |
---|---|---|
committer | Martin Braun <martin.braun@ettus.com> | 2019-11-26 11:49:27 -0800 |
commit | 58cecd867bd9f061b0b0072bb3338372498e1be3 (patch) | |
tree | bc28e2403f647b6195dc18d12d833f938541ab5e | |
parent | 3da938f1242219fdf993576dcfdce7440a63c044 (diff) | |
download | uhd-58cecd867bd9f061b0b0072bb3338372498e1be3.tar.gz uhd-58cecd867bd9f061b0b0072bb3338372498e1be3.tar.bz2 uhd-58cecd867bd9f061b0b0072bb3338372498e1be3.zip |
rfnoc: flushing and reset blocks on graph creation
During construction of the rfnoc_graph, flush and reset each block in
each motherboard we need to enumerate. This will ensure that each
block is in a clean state when we construct it's block controller.
-rw-r--r-- | host/lib/include/uhdlib/rfnoc/client_zero.hpp | 5 | ||||
-rw-r--r-- | host/lib/rfnoc/client_zero.cpp | 36 | ||||
-rw-r--r-- | host/lib/rfnoc/rfnoc_graph.cpp | 33 |
3 files changed, 71 insertions, 3 deletions
diff --git a/host/lib/include/uhdlib/rfnoc/client_zero.hpp b/host/lib/include/uhdlib/rfnoc/client_zero.hpp index 52330bffa..b9bcb32e5 100644 --- a/host/lib/include/uhdlib/rfnoc/client_zero.hpp +++ b/host/lib/include/uhdlib/rfnoc/client_zero.hpp @@ -153,6 +153,11 @@ public: */ bool complete_flush(uint16_t portno); + /*! Go through the entire flush process for all ports + * \throws uhd::runtime_error if flush failed + */ + void complete_flush_all_blocks(); + /*! Reset a port's control logic * * It is recommended to flush a port calling this. diff --git a/host/lib/rfnoc/client_zero.cpp b/host/lib/rfnoc/client_zero.cpp index 6d0e47203..f5a54fd62 100644 --- a/host/lib/rfnoc/client_zero.cpp +++ b/host/lib/rfnoc/client_zero.cpp @@ -68,7 +68,7 @@ client_zero::client_zero(register_iface::sptr reg) // Set the default flushing timeout for each block for (uint16_t portno = 1 + get_num_stream_endpoints(); - portno < (get_num_blocks() + get_num_stream_endpoints()); + portno < (1 + get_num_blocks() + get_num_stream_endpoints()); ++portno) { set_flush_timeout(DEFAULT_FLUSH_TIMEOUT, portno); } @@ -154,6 +154,40 @@ bool client_zero::complete_flush(uint16_t portno) return poll_flush_done(portno); } +void client_zero::complete_flush_all_blocks() +{ + const size_t num_blocks = get_num_blocks(); + const size_t first_block_port = 1 + get_num_stream_endpoints(); + + // Issue flush commands + auto flush_done = std::vector<bool>(); + for (size_t portno = 0; portno < num_blocks; ++portno) { + auto block_portno = portno + first_block_port; + set_flush(block_portno); + flush_done.push_back(false); + } + + // Poll for flush done + auto start = std::chrono::steady_clock::now(); + size_t flushes_done = 0; + while (flushes_done < num_blocks) { + for (size_t portno = 0; portno < num_blocks; ++portno) { + if (flush_done[portno]) { + continue; + } + if (std::chrono::steady_clock::now() > (start + DEFAULT_POLL_TIMEOUT)) { + throw uhd::runtime_error( + str(boost::format("Timeout while flushing port %d") % portno)); + } + auto block_portno = portno + first_block_port; + if (get_flush_done(block_portno)) { + flush_done[portno] = true; + flushes_done++; + } + } + } +} + void client_zero::reset_ctrl(uint16_t portno) { _check_port_number(portno); diff --git a/host/lib/rfnoc/rfnoc_graph.cpp b/host/lib/rfnoc/rfnoc_graph.cpp index 04b13a374..22fc8aee5 100644 --- a/host/lib/rfnoc/rfnoc_graph.cpp +++ b/host/lib/rfnoc/rfnoc_graph.cpp @@ -174,9 +174,19 @@ private: // Ask GSM to allow us to talk to our remote mb sep_addr_t ctrl_sep_addr(mb.get_remote_device_id(), 0); _gsm->connect_host_to_device(ctrl_sep_addr); + // Grab and stash the Client Zero for this mboard detail::client_zero::sptr mb_cz = _gsm->get_client_zero(ctrl_sep_addr); - const size_t num_blocks = mb_cz->get_num_blocks(); - const size_t first_block_port = 1 + mb_cz->get_num_stream_endpoints(); + _client_zeros.emplace(mb_idx, mb_cz); + + const size_t num_blocks = mb_cz->get_num_blocks(); + const size_t first_block_port = 1 + mb_cz->get_num_stream_endpoints(); + + /* Flush and reset each block in the mboard + * We do this before we enumerate the blocks to ensure they're in a clean + * state before we construct their block controller, and so that we don't + * reset any setting that the block controller writes + */ + _flush_and_reset_mboard(mb_idx, mb_cz, num_blocks, first_block_port); // Make a map to count the number of each block we have std::unordered_map<std::string, uint16_t> block_count_map; @@ -369,6 +379,25 @@ private: % std::get<1>(strm_info).bytes % std::get<1>(strm_info).packets; } + //! Flush and reset each connected port on the mboard + void _flush_and_reset_mboard(size_t mb_idx, + detail::client_zero::sptr mb_cz, + const size_t num_blocks, + const size_t first_block_port) + { + UHD_LOG_TRACE("RFNOC::GRAPH", + std::string("Flushing and resetting blocks on mboard ") + + std::to_string(mb_idx)); + + mb_cz->complete_flush_all_blocks(); + + // Reset + for (size_t portno = 0; portno < num_blocks; ++portno) { + auto block_portno = portno + first_block_port; + mb_cz->reset_chdr(block_portno); + mb_cz->reset_ctrl(block_portno); + } + } /************************************************************************** * Attributes *************************************************************************/ |