aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib/include/uhdlib/rfnoc/rx_flow_ctrl_state.hpp
blob: 937baf982601163a68e0bd66955a16104fc219af (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
//
// Copyright 2019 Ettus Research, a National Instruments Brand
//
// SPDX-License-Identifier: GPL-3.0-or-later
//

#ifndef INCLUDED_LIBUHD_RFNOC_RX_FLOW_CTRL_STATE_HPP
#define INCLUDED_LIBUHD_RFNOC_RX_FLOW_CTRL_STATE_HPP

#include <uhd/utils/log.hpp>
#include <uhdlib/rfnoc/rfnoc_common.hpp>

namespace uhd { namespace rfnoc {

//! Class to manage rx flow control state
class rx_flow_ctrl_state
{
public:
    //! Constructor
    rx_flow_ctrl_state(const rfnoc::sep_id_pair_t epids) : _epids(epids) {}

    //! Initialize frequency parameters
    void initialize(const stream_buff_params_t fc_freq)
    {
        _fc_freq = fc_freq;
    }

    //! Resynchronize with transfer counts from the sender
    void resynchronize(const stream_buff_params_t counts)
    {
        if (_recv_counts.bytes != counts.bytes
            || _recv_counts.packets != counts.packets) {
            // If there is a discrepancy between the amount of data sent by
            // the device and received by the transport, adjust the counts
            // of data received and transferred to include the dropped data.
            auto bytes_dropped = counts.bytes - _recv_counts.bytes;
            auto pkts_dropped  = counts.packets - _recv_counts.packets;
            _xfer_counts.bytes += bytes_dropped;
            _xfer_counts.packets += pkts_dropped;

            UHD_LOGGER_DEBUG("rx_flow_ctrl_state")
                << "oh noes: bytes_sent=" << counts.bytes
                << "  bytes_received=" << _recv_counts.bytes
                << "  pkts_sent=" << counts.packets
                << "  pkts_received=" << _recv_counts.packets
                << " src_epid=" << _epids.first << " dst_epid=" << _epids.second
                << std::endl;

            _recv_counts = counts;
        }
    }

    //! Reset the transfer counts (happens during init)
    void reset_counts()
    {
        UHD_LOGGER_TRACE("rx_flow_ctrl_state")
            << "Resetting transfer counts" << std::endl;
        _recv_counts = {0, 0};
        _xfer_counts = {0, 0};
    }

    //! Update state when data is received
    void data_received(const size_t bytes)
    {
        _recv_counts.bytes += bytes;
        _recv_counts.packets++;
    }

    //! Update state when transfer is complete (buffer space freed)
    void xfer_done(const size_t bytes)
    {
        _xfer_counts.bytes += bytes;
        _xfer_counts.packets++;
    }

    //! Returns whether a flow control response is needed
    bool fc_resp_due() const
    {
        stream_buff_params_t accum_counts = {
            _xfer_counts.bytes - _last_fc_resp_counts.bytes,
            _xfer_counts.packets - _last_fc_resp_counts.packets};

        return accum_counts.bytes >= _fc_freq.bytes
               || accum_counts.packets >= _fc_freq.packets;
    }

    //! Update state after flow control response was sent
    void fc_resp_sent()
    {
        _last_fc_resp_counts = _xfer_counts;
    }

    //! Returns counts for completed transfers
    stream_buff_params_t get_xfer_counts() const
    {
        return _xfer_counts;
    }

    //! Returns counts for completed transfers
    stream_buff_params_t get_recv_counts() const
    {
        return _recv_counts;
    }

    //! Returns configured flow control frequency
    stream_buff_params_t get_fc_freq() const
    {
        return _fc_freq;
    }

private:
    // Counts for data received, including any data still in use
    stream_buff_params_t _recv_counts{0, 0};

    // Counts for data read and whose buffer space is ok to reuse
    stream_buff_params_t _xfer_counts{0, 0};

    // Counts sent in last flow control response
    stream_buff_params_t _last_fc_resp_counts{0, 0};

    // Frequency of flow control responses
    stream_buff_params_t _fc_freq{0, 0};

    // Endpoint ID for log messages
    const sep_id_pair_t _epids;
};

}} // namespace uhd::rfnoc

#endif /* INCLUDED_LIBUHD_RFNOC_RX_FLOW_CTRL_STATE_HPP */