blob: 65fc1b0939bf084bd50d4f6f1e50a92dea78c309 (
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
|
//
// Copyright 2019 Ettus Research, a National Instruments Brand
//
// SPDX-License-Identifier: GPL-3.0-or-later
//
#ifndef INCLUDED_LIBUHD_RFNOC_TX_FLOW_CTRL_STATE_HPP
#define INCLUDED_LIBUHD_RFNOC_TX_FLOW_CTRL_STATE_HPP
#include <uhdlib/rfnoc/rfnoc_common.hpp>
namespace uhd { namespace rfnoc {
//! Class to manage tx flow control state
class tx_flow_ctrl_state
{
public:
//! Updates destination capacity
void set_dest_capacity(const stream_buff_params_t& capacity)
{
_dest_capacity = capacity;
}
//! Updates destination received count
void update_dest_recv_count(const stream_buff_params_t& recv_count)
{
_recv_counts = recv_count;
}
/*! Returns whether the destination has buffer space for the requested
* packet size
*/
bool dest_has_space(const size_t packet_size)
{
// The stream endpoint only cares about bytes, the packet count is not
// important to determine the space available.
const auto buffer_fullness = _xfer_counts.bytes - _recv_counts.bytes;
const auto space_available = _dest_capacity.bytes - buffer_fullness;
return space_available >= packet_size;
}
//! Increments transfer count with amount of data sent
void data_sent(const size_t packet_size)
{
_xfer_counts.bytes += packet_size;
_xfer_counts.packets++;
// Request an fc resync after we have transferred a number of bytes >=
// to the destination capacity. There is no strict requirement on how
// often we need to send this, as it is only needed to correct for
// dropped packets. One buffer's worth of bytes is probably a good
// cadence.
if (_xfer_counts.bytes - _last_fc_resync_bytes >= _dest_capacity.bytes) {
_fc_resync_req = true;
}
}
/*! Returns whether an fc resync request is pending. The policy we use
* here is to send an fc resync every time we send a number of bytes
* equal to the destination buffer capacity.
*/
bool get_fc_resync_req_pending() const
{
return _fc_resync_req;
}
//! Clears fc resync request pending status
void clear_fc_resync_req_pending()
{
_fc_resync_req = false;
_last_fc_resync_bytes = _xfer_counts.bytes;
}
//! Returns counts for packets sent
stream_buff_params_t get_xfer_counts() const
{
return _xfer_counts;
}
private:
// Counts for data sent
stream_buff_params_t _xfer_counts{0, 0};
// Counts for data received by the destination
stream_buff_params_t _recv_counts{0, 0};
// Buffer size at the destination
stream_buff_params_t _dest_capacity{0, 0};
// Counts sent in last flow control resync
size_t _last_fc_resync_bytes = 0;
// Track when to send ack packets
bool _fc_resync_req = false;
};
}} // namespace uhd::rfnoc
#endif /* INCLUDED_LIBUHD_RFNOC_TX_FLOW_CTRL_STATE_HPP */
|