blob: ed6553bf3e591d644b2a2b9bd2e0945d675e5637 (
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
|
//
// 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, const stream_buff_params_t fc_freq)
: _fc_freq(fc_freq), _epids(epids)
{
}
//! 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;
}
}
//! 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 */
|