uhd: Remove boost:: from chdr_packet and update docs

- Replace boost::optional with std::optional, making uhd::utils::chdr::
  chdr_packet Boost-free
- Update the docstrings in that class

Note that this an API break for any users of chdr_packet (unless they
were using the Python API, then there's no change).
This commit is contained in:
Martin Braun 2026-01-14 10:48:06 +01:00 committed by Jörg Hofrichter
parent ab8ec99733
commit 6f77deaa16
5 changed files with 61 additions and 29 deletions

View File

@ -10,10 +10,9 @@
#include <uhd/rfnoc/chdr_types.hpp>
#include <uhd/rfnoc/rfnoc_types.hpp>
#include <uhd/types/endianness.hpp>
#include <boost/none.hpp>
#include <boost/optional.hpp>
#include <cstddef>
#include <cstdint>
#include <optional>
#include <string>
#include <vector>
@ -21,31 +20,57 @@ namespace uhd { namespace utils { namespace chdr {
/*! A Generic class that represents a CHDR Packet
*
* Whether the packet has a specific type of payload is not specified
* This class is not used by UHD, it is a helper class for writing tests or
* other types of utilities. The class has the capability of representing any
* CHDR packet, and serializing this class into a CHDR packet (or deserializing
* from a buffer to populate this class). It is not optimized for high
* performance.
* For example, this is used in UHD unit tests, and in the USRP simulator to
* provide an easy way to generate CHDR packets from Python.
*
* Whether the packet has a specific type of payload is not specified, but of
* course the CHDR header can be set as desired, and a payload can be provided
* to the constructor.
*/
class UHD_API chdr_packet
{
public:
/*! Constructs a CHDR Packet from a header and a payload
*
* timestamp and metadata are optional and will be empty if omitted
* This is commonly used to create a non-data packet (e.g., control,
* stream status, etc.).
*
* \param chdr_w CHDR width
* \param header CHDR header
* \param payload The payload object (e.g., a chdr_rfnoc::ctrl_payload if
* that's the type of payload_t).
* \param timestamp Timestamp, defaults to no timestamp in the header.
* \param metadata Metadata, defaults to no metadata.
*/
template <typename payload_t>
chdr_packet(uhd::rfnoc::chdr_w_t chdr_w,
uhd::rfnoc::chdr::chdr_header header,
payload_t payload,
boost::optional<uint64_t> timestamp = boost::none,
std::vector<uint64_t> metadata = {});
std::optional<uint64_t> timestamp = {},
std::vector<uint64_t> metadata = {});
/*! Construct a CHDR Packet from a header and raw payload words
*
* timestamp and metadata are optional and will be empty if omitted
* This is the typical way to construct data packets, or to manually
* construct non-data packets by bypassing the corresponding payload types.
*
* \param chdr_w CHDR width
* \param header CHDR header
* \param payload_data The payload data as bytes, i.e., whatever follows
* the CHDR header.
* \param timestamp Timestamp, defaults to no timestamp in the header.
* \param metadata Metadata, defaults to no metadata.
*/
chdr_packet(uhd::rfnoc::chdr_w_t chdr_w,
uhd::rfnoc::chdr::chdr_header header,
std::vector<uint8_t> payload_data,
boost::optional<uint64_t> timestamp = boost::none,
std::vector<uint64_t> mdata = {});
std::optional<uint64_t> timestamp = {},
std::vector<uint64_t> metadata = {});
/*! Returns the contents of the CHDR header
*
@ -61,15 +86,16 @@ public:
/*! Returns the timestamp in the packet as an optional value
*
* \return A boost::optional which if initialized has the timestamp
* \return A std::optional which if initialized has the timestamp
*/
boost::optional<uint64_t> get_timestamp() const;
std::optional<uint64_t> get_timestamp() const;
/*! Sets the timestamp in the packet
*
* \param timestamp the timestamp to set, or boost::none for no timestamp
* \param timestamp the timestamp to set, or an empty optional for no
* timestamp
*/
void set_timestamp(boost::optional<uint64_t> timestamp);
void set_timestamp(std::optional<uint64_t> timestamp);
/*! Returns a const reference to the metadata
*
@ -162,19 +188,22 @@ public:
private:
void serialize_ptr(endianness_t endianness, void* start, void* end) const;
static chdr_packet deserialize_ptr(uhd::rfnoc::chdr_w_t chdr_w,
endianness_t endianness,
const void* start,
const void* end);
inline void set_header_lengths()
{
_header.set_num_mdata(_mdata.size() / (uhd::rfnoc::chdr_w_to_bits(_chdr_w) / 64));
_header.set_length(get_packet_len());
}
uhd::rfnoc::chdr_w_t _chdr_w;
uhd::rfnoc::chdr::chdr_header _header;
std::vector<uint8_t> _payload;
boost::optional<uint64_t> _timestamp;
std::optional<uint64_t> _timestamp;
std::vector<uint64_t> _mdata;
};

View File

@ -16,7 +16,7 @@ template <typename payload_t>
chdr_packet::chdr_packet(uhd::rfnoc::chdr_w_t chdr_w,
chdr_rfnoc::chdr_header header,
payload_t payload,
boost::optional<uint64_t> timestamp,
std::optional<uint64_t> timestamp,
std::vector<uint64_t> metadata)
: chdr_packet(chdr_w, header, std::vector<uint8_t>(), timestamp, std::move(metadata))
{

View File

@ -15,7 +15,7 @@ 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::optional<uint64_t> timestamp,
std::vector<uint64_t> mdata)
: _chdr_w(chdr_w)
, _header(header)
@ -49,12 +49,12 @@ void chdr_util::chdr_packet::set_header(chdr_rfnoc::chdr_header header)
set_header_lengths();
}
boost::optional<uint64_t> chdr_util::chdr_packet::get_timestamp() const
std::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)
void chdr_util::chdr_packet::set_timestamp(std::optional<uint64_t> timestamp)
{
_timestamp = timestamp;
set_header_lengths();
@ -102,8 +102,11 @@ chdr_util::chdr_packet chdr_util::chdr_packet::deserialize_ptr(
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();
chdr_rfnoc::chdr_header header = packet_writer->get_chdr_header();
std::optional<uint64_t> timestamp{};
if (bool(packet_writer->get_timestamp())) {
timestamp = *packet_writer->get_timestamp();
}
const size_t mdata_size_words = packet_writer->get_mdata_size() / 8;
const uint64_t* mdata_src_begin =
@ -142,10 +145,10 @@ const std::vector<uint64_t>& chdr_util::chdr_packet::get_metadata() const
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)
// The timestamp and header take up 2 chdr_w lengths only when CHDR_W = 64
// bits and there is a timestamp (RFNoC Specification 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)
+ ((bool(_timestamp) && _chdr_w == uhd::rfnoc::CHDR_W_64) ? 2 : 1)
* chdr_w_bytes;
}

View File

@ -30,14 +30,14 @@ void export_utils_with_payload(
.def(py::init([](uhd::rfnoc::chdr_w_t chdr_w,
chdr_rfnoc::chdr_header header,
payload_t payload,
boost::optional<uint64_t> timestamp,
std::optional<uint64_t> timestamp,
std::vector<uint64_t> metadata) {
return chdr_packet(chdr_w, header, payload, timestamp, metadata);
}),
py::arg("chdr_w"),
py::arg("header"),
py::arg("payload"),
py::arg("timestamp") = boost::optional<uint64_t>(),
py::arg("timestamp") = std::optional<uint64_t>(),
py::arg("metadata") = std::vector<uint64_t>())
.def(get_payload_name.c_str(),
&chdr_packet::get_payload<payload_t>,
@ -68,7 +68,7 @@ void export_utils(py::module& m)
.def(py::init([](uhd::rfnoc::chdr_w_t chdr_w,
chdr_rfnoc::chdr_header header,
py::bytes& payload,
boost::optional<uint64_t> timestamp,
std::optional<uint64_t> timestamp,
py::bytes& metadata) {
return chdr_packet(chdr_w,
header,
@ -79,7 +79,7 @@ void export_utils(py::module& m)
py::arg("chdr_w"),
py::arg("header"),
py::arg("payload"),
py::arg("timestamp") = boost::optional<uint64_t>(),
py::arg("timestamp") = std::optional<uint64_t>(),
py::arg("metadata") = py::bytes())
// Methods
.def("__str__", &chdr_packet::to_string)

View File

@ -173,7 +173,7 @@ chdr_util::chdr_packet make_data_packet0()
header.set_length(8000);
header.set_dst_epid(3);
header.set_seq_num(1);
boost::optional<uint64_t> timestamp(0x7C40C83);
std::optional<uint64_t> timestamp(0x7C40C83);
uint8_t* data_src;
size_t data_len;
std::tie(data_src, data_len) = data_packet::peer1[9];
@ -190,7 +190,7 @@ chdr_util::chdr_packet make_data_packet1()
header.set_dst_epid(3);
header.set_eob(true);
header.set_seq_num(1716);
boost::optional<uint64_t> timestamp(0x21452B97);
std::optional<uint64_t> timestamp(0x21452B97);
uint8_t* data_src;
size_t data_len;
std::tie(data_src, data_len) = data_packet::eob_packet_data;