diff options
| -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       *************************************************************************/  | 
