1 // 2 // Copyright 2019 Ettus Research, a National Instruments Brand 3 // 4 // SPDX-License-Identifier: GPL-3.0-or-later 5 // 6 7 #pragma once 8 9 #include <uhd/rfnoc/register_iface_holder.hpp> 10 #include <uhdlib/rfnoc/chdr_ctrl_endpoint.hpp> 11 #include <chrono> 12 #include <cstdint> 13 #include <functional> 14 #include <memory> 15 #include <string> 16 #include <vector> 17 18 namespace uhd { namespace rfnoc { namespace detail { 19 20 /*! 21 * Class that uses a register_iface to read important configuration information from the 22 * RFNoC backend registers 23 */ 24 class client_zero : public uhd::rfnoc::register_iface_holder 25 { 26 public: 27 using sptr = std::shared_ptr<client_zero>; 28 29 static sptr make(chdr_ctrl_endpoint& chdr_ctrl_ep, sep_id_t dst_epid); 30 31 client_zero(register_iface::sptr reg); 32 33 //! Definition of an edge in the static router 34 struct edge_def_t 35 { 36 uint16_t src_blk_index; 37 uint8_t src_blk_port; 38 uint16_t dst_blk_index; 39 uint8_t dst_blk_port; 40 }; 41 42 //! Contents of the backend status block configuration register 43 struct block_config_info 44 { 45 uint8_t protover; 46 uint8_t num_inputs; 47 uint8_t num_outputs; 48 uint8_t ctrl_fifo_size; 49 uint8_t ctrl_max_async_msgs; 50 uint8_t data_mtu; 51 }; 52 53 //! Return the RFNoC protocol version for this motherboard get_proto_ver()54 uint16_t get_proto_ver() 55 { 56 return _proto_ver; 57 }; 58 59 //! Return the device type get_device_type()60 uint16_t get_device_type() 61 { 62 return _device_type; 63 }; 64 65 //! Return the number of blocks in our RFNoC graph get_num_blocks()66 size_t get_num_blocks() 67 { 68 return _num_blocks; 69 }; 70 71 //! Return the number of stream endpoints in our RFNoC graph get_num_stream_endpoints()72 size_t get_num_stream_endpoints() 73 { 74 return _num_stream_endpoints; 75 }; 76 77 //! Return the number of stream endpoints connected to the control crossbar get_num_ctrl_endpoints() const78 size_t get_num_ctrl_endpoints() const 79 { 80 return _num_ctrl_endpoints; 81 }; 82 83 //! Return the number of transports available get_num_transports()84 size_t get_num_transports() 85 { 86 return _num_transports; 87 }; 88 89 //! Return the control crossbar port of the block \p block_idx get_ctrl_xbar_port(const size_t block_idx) const90 size_t get_ctrl_xbar_port(const size_t block_idx) const 91 { 92 return 1 + _num_ctrl_endpoints + block_idx; 93 } 94 95 //! Return whether or not the device includes a CHDR crossbar has_chdr_crossbar()96 bool has_chdr_crossbar() 97 { 98 return _has_chdr_crossbar; 99 }; 100 101 //! Return the number of edges in our graph (the number of static connections) get_num_edges()102 size_t get_num_edges() 103 { 104 return _num_edges; 105 }; 106 107 //! Return a vector containing the edge definitions get_adjacency_list()108 std::vector<edge_def_t>& get_adjacency_list() 109 { 110 return _adjacency_list; 111 }; 112 113 /*! Return the NOC ID of the block located at `portno` 114 * 115 * \throws uhd::index_error if no NOC block is connected to the port 116 */ 117 uint32_t get_noc_id(uint16_t portno); 118 119 /*! Return whether the port is actively flushing 120 * 121 * \throws uhd::index_error if no NOC block is connected to the port 122 * \return boolean status 123 */ 124 bool get_flush_active(uint16_t portno); 125 126 /*! Return whether the port is done flushing 127 * 128 * \throws uhd::index_error if no NOC block is connected to the port 129 * \return boolean status 130 */ 131 bool get_flush_done(uint16_t portno); 132 133 /*! Returns once the port is done flushing 134 * 135 * Note: this function queries the port once every millisecond 136 * 137 * \param portno Port number 138 * \param timeout time, in milliseconds, to poll before quitting 139 * \throws uhd::index_error if no NOC block is connected to the port 140 * \return boolean whether or not the flush had completed in the timeout period 141 */ 142 bool poll_flush_done(uint16_t portno, std::chrono::milliseconds timeout); 143 144 /*! Set the port's hardware flush timeout 145 * 146 * \param timeout number of cycles the device waits for the flushing to complete 147 * \param portno Port number 148 * \throws uhd::index_error if no NOC block is connected to the port 149 */ 150 void set_flush_timeout(uint32_t timeout, uint16_t portno); 151 152 /*! Send a request to flush a port 153 * 154 * \param portno Port number 155 * \throws uhd::index_error if no NOC block is connected to the port 156 */ 157 void set_flush(uint16_t portno); 158 159 /*! Go through the entire flush process for a port 160 * 161 * \param portno Port number 162 * \throws uhd::index_error if no NOC block is connected to the port 163 * \return whether or not the flush succeeded 164 */ 165 bool complete_flush(uint16_t portno); 166 167 /*! Go through the entire flush process for all ports 168 * \return whether or not the flush succeeded 169 */ 170 bool complete_flush_all_blocks(); 171 172 /*! Reset a port's control logic 173 * 174 * It is recommended to flush a port calling this. 175 * 176 * \param portno Port number 177 * \throws uhd::index_error if no NOC block is connected to the port 178 */ 179 void reset_ctrl(uint16_t portno); 180 181 /*! Reset a port's CHDR logic 182 * 183 * It is recommended to flush a port calling this. 184 * 185 * \param portno Port number 186 * \throws uhd::index_error if no NOC block is connected to the port 187 */ 188 void reset_chdr(uint16_t portno); 189 190 /*! Get the port's configuration information 191 * 192 * \return Struct containing configuration information 193 */ 194 block_config_info get_block_info(uint16_t portno); 195 196 // TODO: handle callbacks? 197 198 private: 199 uint16_t _proto_ver; 200 uint16_t _device_type; 201 uint16_t _num_blocks; 202 uint16_t _num_stream_endpoints; 203 uint16_t _num_ctrl_endpoints; 204 uint16_t _num_transports; 205 bool _has_chdr_crossbar; 206 uint16_t _num_edges; 207 std::vector<edge_def_t> _adjacency_list; 208 209 std::vector<client_zero::edge_def_t> _get_adjacency_list(); 210 211 /* Helper function to determine if the given port number has a block connected 212 * 213 * \throws uhd::index_error if no NOC block is connected to the port 214 */ 215 void _check_port_number(uint16_t portno); 216 //! Translate port number to base address for the register 217 uint32_t _get_port_base_addr(uint16_t portno); 218 //! Helper function to get the backend control flush status flags 219 uint32_t _get_flush_status_flags(uint16_t portno); 220 }; 221 222 }}} /* namespace uhd::rfnoc::detail */ 223