aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrent Stapleton <brent.stapleton@ettus.com>2019-06-04 16:59:22 -0700
committerMartin Braun <martin.braun@ettus.com>2019-11-26 11:49:27 -0800
commit58cecd867bd9f061b0b0072bb3338372498e1be3 (patch)
treebc28e2403f647b6195dc18d12d833f938541ab5e
parent3da938f1242219fdf993576dcfdce7440a63c044 (diff)
downloaduhd-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.hpp5
-rw-r--r--host/lib/rfnoc/client_zero.cpp36
-rw-r--r--host/lib/rfnoc/rfnoc_graph.cpp33
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
*************************************************************************/