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
|
//
// Copyright 2020 Ettus Research, a National Instruments Brand
//
// SPDX-License-Identifier: GPL-3.0-or-later
//
#include <uhd/utils/chdr/chdr_packet.hpp>
#include <uhdlib/rfnoc/chdr_packet_writer.hpp>
#include <boost/format.hpp>
namespace chdr_rfnoc = uhd::rfnoc::chdr;
namespace chdr_util = uhd::utils::chdr;
using namespace uhd;
chdr_util::chdr_packet::chdr_packet(uhd::rfnoc::chdr_w_t chdr_w,
chdr_rfnoc::chdr_header header,
std::vector<uint8_t> payload,
boost::optional<uint64_t> timestamp,
std::vector<uint64_t> mdata)
: _chdr_w(chdr_w)
, _header(header)
, _payload(std::move(payload))
, _timestamp(timestamp)
, _mdata(std::move(mdata))
{
set_header_lengths();
}
inline static uint64_t u64_to_host(uhd::endianness_t endianness, uint64_t word)
{
return (endianness == ENDIANNESS_BIG) ? uhd::ntohx<uint64_t>(word)
: uhd::wtohx<uint64_t>(word);
}
inline static uint64_t u64_from_host(uhd::endianness_t endianness, uint64_t word)
{
return (endianness == ENDIANNESS_BIG) ? uhd::htonx<uint64_t>(word)
: uhd::htowx<uint64_t>(word);
}
chdr_rfnoc::chdr_header chdr_util::chdr_packet::get_header() const
{
return this->_header;
}
void chdr_util::chdr_packet::set_header(chdr_rfnoc::chdr_header header)
{
_header = header;
set_header_lengths();
}
boost::optional<uint64_t> chdr_util::chdr_packet::get_timestamp() const
{
return this->_timestamp;
}
void chdr_util::chdr_packet::set_timestamp(boost::optional<uint64_t> timestamp)
{
_timestamp = timestamp;
set_header_lengths();
}
std::vector<uint8_t> chdr_util::chdr_packet::serialize_to_byte_vector(
endianness_t endianness) const
{
std::vector<uint8_t> buffer(get_packet_len(), 0);
serialize(buffer.begin(), buffer.end(), endianness);
return buffer;
}
void chdr_util::chdr_packet::serialize_ptr(
endianness_t endianness, void* start, void* end) const
{
size_t len = static_cast<uint8_t*>(end) - static_cast<uint8_t*>(start);
UHD_ASSERT_THROW(get_packet_len() <= len);
chdr_rfnoc::chdr_packet_factory factory(_chdr_w, endianness);
chdr_rfnoc::chdr_packet_writer::uptr packet_writer =
factory.make_generic(std::numeric_limits<size_t>::max());
chdr_rfnoc::chdr_header header = _header;
packet_writer->refresh(start, header, (_timestamp ? *_timestamp : 0));
uint64_t* mdata_ptr = static_cast<uint64_t*>(packet_writer->get_mdata_ptr());
auto mdata_src_begin = this->_mdata.begin();
auto mdata_src_end = this->_mdata.end();
std::transform(
mdata_src_begin, mdata_src_end, mdata_ptr, [endianness](uint64_t value) {
return u64_from_host(endianness, value);
});
uint8_t* payload_ptr = static_cast<uint8_t*>(packet_writer->get_payload_ptr());
std::copy(_payload.begin(), _payload.end(), payload_ptr);
}
chdr_util::chdr_packet chdr_util::chdr_packet::deserialize_ptr(
uhd::rfnoc::chdr_w_t chdr_w,
endianness_t endianness,
const void* start,
const void* end)
{
chdr_rfnoc::chdr_packet_factory factory(chdr_w, endianness);
chdr_rfnoc::chdr_packet_writer::uptr packet_writer =
factory.make_generic(std::numeric_limits<size_t>::max());
packet_writer->refresh(start);
chdr_rfnoc::chdr_header header = packet_writer->get_chdr_header();
boost::optional<uint64_t> timestamp = packet_writer->get_timestamp();
const size_t mdata_size_words = packet_writer->get_mdata_size() / 8;
const uint64_t* mdata_src_begin =
static_cast<const uint64_t*>(packet_writer->get_mdata_const_ptr());
const uint64_t* mdata_src_end = mdata_src_begin + mdata_size_words;
std::vector<uint64_t> mdata(mdata_size_words, 0);
uint64_t* mdata_ptr = mdata.data();
UHD_ASSERT_THROW(mdata_src_end < static_cast<const uint64_t*>(end));
std::transform(
mdata_src_begin, mdata_src_end, mdata_ptr, [endianness](uint64_t value) {
return u64_from_host(endianness, value);
});
size_t payload_size = packet_writer->get_payload_size();
const uint8_t* payload_begin =
static_cast<const uint8_t*>(packet_writer->get_payload_const_ptr());
const uint8_t* payload_end = payload_begin + payload_size;
std::vector<uint8_t> payload(payload_size, 0);
UHD_ASSERT_THROW(payload_end <= static_cast<const uint8_t*>(end));
std::copy(payload_begin, payload_end, payload.begin());
return chdr_util::chdr_packet(chdr_w, header, payload, timestamp, mdata);
}
void chdr_util::chdr_packet::set_metadata(std::vector<uint64_t> metadata)
{
_mdata = std::move(metadata);
set_header_lengths();
}
const std::vector<uint64_t>& chdr_util::chdr_packet::get_metadata() const
{
return _mdata;
}
size_t chdr_util::chdr_packet::get_packet_len() const
{
size_t chdr_w_bytes = uhd::rfnoc::chdr_w_to_bits(_chdr_w) / 8;
// The timestamp and header take up 2 chdr_w lengths only when CHDR_W = 64 bits and
// there is a timestamp (RFNoC Specifcation section 2.2.1)
return _payload.size() * sizeof(uint8_t) + _mdata.size() * sizeof(uint64_t)
+ ((_timestamp != boost::none && _chdr_w == uhd::rfnoc::CHDR_W_64) ? 2 : 1)
* chdr_w_bytes;
}
const std::vector<uint8_t>& chdr_util::chdr_packet::get_payload_bytes() const
{
return _payload;
}
void chdr_util::chdr_packet::set_payload_bytes(std::vector<uint8_t> bytes)
{
this->_payload = std::move(bytes);
set_header_lengths();
}
//! Return a string representation of this object
const std::string chdr_util::chdr_packet::to_string() const
{
return str(boost::format("chdr_packet{chdr_w:%u}\n%s")
% uhd::rfnoc::chdr_w_to_bits(_chdr_w) % _header.to_string());
}
|