aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib/include/uhdlib/rfnoc/client_zero.hpp
blob: c6d3e879b623679b84acc798bcfea02d74c57d90 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
//
// Copyright 2019 Ettus Research, a National Instruments Brand
//
// SPDX-License-Identifier: GPL-3.0-or-later
//

#ifndef INCLUDED_LIBUHD_CLIENT_ZERO_HPP
#define INCLUDED_LIBUHD_CLIENT_ZERO_HPP

#include <uhd/rfnoc/register_iface_holder.hpp>
#include <uhdlib/rfnoc/chdr_ctrl_endpoint.hpp>
#include <chrono>
#include <cstdint>
#include <functional>
#include <memory>
#include <string>
#include <vector>

namespace uhd { namespace rfnoc { namespace detail {

/*!
 * Class that uses a register_iface to read important configuration information from the
 * RFNoC backend registers
 */
class client_zero : public uhd::rfnoc::register_iface_holder
{
public:
    client_zero(register_iface::sptr reg);

    //! Definition of an edge in the static router
    struct edge_def_t
    {
        uint16_t src_blk_index;
        uint8_t src_blk_port;
        uint16_t dst_blk_index;
        uint8_t dst_blk_port;
    };

    //! Contents of the backend status block configuration register
    struct block_config_info
    {
        uint8_t protover;
        uint8_t num_inputs;
        uint8_t num_outputs;
        uint8_t ctrl_fifo_size;
        uint8_t ctrl_max_async_msgs;
        uint8_t data_mtu;
    };

    //! Return the RFNoC protocol version for this motherboard
    uint16_t get_proto_ver()
    {
        return _proto_ver;
    };

    //! Return the device type
    uint16_t get_device_type()
    {
        return _device_type;
    };

    //! Return the number of blocks in our RFNoC graph
    size_t get_num_blocks()
    {
        return _num_blocks;
    };

    //! Return the number of stream endpoints in our RFNoC graph
    size_t get_num_stream_endpoints()
    {
        return _num_stream_endpoints;
    };

    //! Return the number of transports available
    size_t get_num_transports()
    {
        return _num_transports;
    };

    //! Return whether or not the device includes a CHDR crossbar
    bool has_chdr_crossbar()
    {
        return _has_chdr_crossbar;
    };

    //! Return the number of edges in our graph (the number of static connections)
    size_t get_num_edges()
    {
        return _num_edges;
    };

    //! Return a vector containing the edge definitions
    std::vector<edge_def_t>& get_adjacency_list()
    {
        return _adjacency_list;
    };

    /*! Return the NOC ID of the block located at `portno`
     *
     * \throws uhd::index_error if no NOC block is connected to the port
     */
    uint32_t get_noc_id(uint16_t portno);

    /*! Return whether the port is actively flushing
     *
     * \throws uhd::index_error if no NOC block is connected to the port
     * \return boolean status
     */
    bool get_flush_active(uint16_t portno);

    /*! Return whether the port is done flushing
     *
     * \throws uhd::index_error if no NOC block is connected to the port
     * \return boolean status
     */
    bool get_flush_done(uint16_t portno);

    /*! Returns once the port is done flushing
     *
     * Note: this function queries the port once every millisecond
     *
     * \param portno Port number
     * \param timeout time, in milliseconds, to poll before quitting
     * \throws uhd::index_error if no NOC block is connected to the port
     * \return boolean whether or not the flush had completed in the timeout period
     */
    bool poll_flush_done(uint16_t portno, std::chrono::milliseconds timeout);

    /*! Set the port's hardware flush timeout
     *
     * \param timeout number of cycles the device waits for the flushing to complete
     * \param portno Port number
     * \throws uhd::index_error if no NOC block is connected to the port
     */
    void set_flush_timeout(uint32_t timeout, uint16_t portno);

    /*! Send a request to flush a port
     *
     * \param portno Port number
     * \throws uhd::index_error if no NOC block is connected to the port
     */
    void set_flush(uint16_t portno);

    /*! Go through the entire flush process for a port
     *
     * \param portno Port number
     * \throws uhd::index_error if no NOC block is connected to the port
     * \return whether or not the flush succeeded
     */
    bool complete_flush(uint16_t portno);

    /*! Reset a port's control logic
     *
     * It is recommended to flush a port calling this.
     *
     * \param portno Port number
     * \throws uhd::index_error if no NOC block is connected to the port
     */
    void reset_ctrl(uint16_t portno);

    /*! Reset a port's CHDR logic
     *
     * It is recommended to flush a port calling this.
     *
     * \param portno Port number
     * \throws uhd::index_error if no NOC block is connected to the port
     */
    void reset_chdr(uint16_t portno);

    /*! Get the port's configuration information
     *
     * \return Struct containing configuration information
     */
    block_config_info get_block_info(uint16_t portno);

    // TODO: handle callbacks?

private:
    uint16_t _proto_ver;
    uint16_t _device_type;
    uint16_t _num_blocks;
    uint16_t _num_stream_endpoints;
    uint16_t _num_transports;
    bool _has_chdr_crossbar;
    uint16_t _num_edges;
    std::vector<edge_def_t> _adjacency_list;

    std::vector<client_zero::edge_def_t> _get_adjacency_list();

    /* Helper function to determine if the given port number has a block connected
     *
     * \throws uhd::index_error if no NOC block is connected to the port
     */
    void _check_port_number(uint16_t portno);
    //! Translate port number to base address for the register
    uint32_t _get_port_base_addr(uint16_t portno);
    //! Helper function to get the backend control flush status flags
    uint32_t _get_flush_status_flags(uint16_t portno);
};

}}} /* namespace uhd::rfnoc::detail */

#endif /* INCLUDED_LIBUHD_CLIENT_ZERO_HPP */