diff options
author | Samuel O'Brien <sam.obrien@ni.com> | 2020-06-26 08:26:25 -0500 |
---|---|---|
committer | Aaron Rossetto <aaron.rossetto@ni.com> | 2020-07-13 15:21:52 -0500 |
commit | b0cb065111dc3f40b89bdda76e9bd98f3e70b72e (patch) | |
tree | 4d08118999692767bc018d0a21758562abe1a300 /host/lib/include/uhdlib/rfnoc/chdr_packet_writer.hpp | |
parent | 14d9452a15a6e65b01e19e0d5ce0c67afc060cc2 (diff) | |
download | uhd-b0cb065111dc3f40b89bdda76e9bd98f3e70b72e.tar.gz uhd-b0cb065111dc3f40b89bdda76e9bd98f3e70b72e.tar.bz2 uhd-b0cb065111dc3f40b89bdda76e9bd98f3e70b72e.zip |
rfnoc: Rename chdr_packet to chdr_packet_writer
It would be confusing to have two classes named chdr_packet. As it makes
more sense to name the new public chdr parser class chdr_packet, the
internal uhd::rfnoc::chdr::chdr_packet class is being renamed to
chdr_packet_writer to better represent its functionality.
Signed-off-by: Samuel O'Brien <sam.obrien@ni.com>
Diffstat (limited to 'host/lib/include/uhdlib/rfnoc/chdr_packet_writer.hpp')
-rw-r--r-- | host/lib/include/uhdlib/rfnoc/chdr_packet_writer.hpp | 325 |
1 files changed, 325 insertions, 0 deletions
diff --git a/host/lib/include/uhdlib/rfnoc/chdr_packet_writer.hpp b/host/lib/include/uhdlib/rfnoc/chdr_packet_writer.hpp new file mode 100644 index 000000000..6f1c264dd --- /dev/null +++ b/host/lib/include/uhdlib/rfnoc/chdr_packet_writer.hpp @@ -0,0 +1,325 @@ +// +// Copyright 2019 Ettus Research, a National Instruments Brand +// +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#pragma once + +#include <uhd/types/endianness.hpp> +#include <uhd/utils/byteswap.hpp> +#include <uhdlib/rfnoc/chdr_types.hpp> +#include <limits> + +namespace uhd { namespace rfnoc { namespace chdr { + +//---------------------------------------------------- +// Generic CHDR Packet Container +//---------------------------------------------------- + +//! A container class that wraps a generic buffer that contains a CHDR packet. The +// container provides a high level API to read and write the header, metadata and payload +// of the packet. The payload can be accessed as a generic buffer using this interface. +// +class chdr_packet_writer +{ +public: + //! A unique pointer to a const chdr_packet_writer. Useful as a read-only interface. + typedef std::unique_ptr<const chdr_packet_writer> cuptr; + //! A unique pointer to a non-const chdr_packet_writer. Useful as a read-write + //! interface. + typedef std::unique_ptr<chdr_packet_writer> uptr; + + virtual ~chdr_packet_writer() = 0; + + /*! Updates the underlying storage of this packet. This is a const method and is + * only useful for read-only (RX) access. + * + * \param pkt_buff Pointer to a buffer that contains the RX packet + */ + virtual void refresh(const void* pkt_buff) const = 0; + + /*! Updates the underlying storage of this packet, and populates it with the specified + * arguments. This is a non-const method and is useful for read-write (TX) access. + * + * \param pkt_buff Pointer to a buffer that should be populated with the TX packet + * \param header The CHDR header to fill into the TX packet + * \param timestamp The timestamp to fill into the TX packet (if requested) + */ + virtual void refresh(void* pkt_buff, chdr_header& header, uint64_t timestamp = 0) = 0; + + /*! Updates the CHDR header with the written payload size + * + * \param payload_size_bytes The payload size in bytes + */ + virtual void update_payload_size(size_t payload_size_bytes) = 0; + + /*! Returns a class that represents the contents of the CHDR header + * + * \return The CHDR header + */ + virtual chdr_header get_chdr_header() const = 0; + + /*! Returns the timestamp in the packet as an optional value + * + * \return A boost::optional which if initialized has the timestamp + */ + virtual boost::optional<uint64_t> get_timestamp() const = 0; + + /*! Returns the endianness of the metadata and payload buffers + * + * \return The byte order as a uhd::endianness_t + */ + virtual endianness_t get_byte_order() const = 0; + + /*! Returns the maximum transfer unit in bytes + * + * \return The maximum transfer unit in bytes + */ + virtual size_t get_mtu_bytes() const = 0; + + /*! Returns the metadata size in bytes + * + * \return The size in bytes + */ + virtual size_t get_mdata_size() const = 0; + + /*! Returns a const void pointer to the metadata section in the packet + * + * \return A pointer to the metadata + */ + virtual const void* get_mdata_const_ptr() const = 0; + + /*! Returns a non-const void pointer to the metadata section in the packet + * + * \return A pointer to the metadata + */ + virtual void* get_mdata_ptr() = 0; + + /*! Returns the payload size in bytes + * + * \return The size in bytes + */ + virtual size_t get_payload_size() const = 0; + + /*! Returns a const void pointer to the payload section in the packet + * + * \return A pointer to the payload + */ + virtual const void* get_payload_const_ptr() const = 0; + + /*! Returns a non-const void pointer to the payload section in the packet + * + * \return A pointer to the payload + */ + virtual void* get_payload_ptr() = 0; + + /*! Return the payload offset in bytes for a given type and num_mdata + * + * \param pkt_type The packet type for calculation + * \param num_mdata The number of metadata words for calculation + * \return The offset of the payload in a packet with the given params + */ + virtual size_t calculate_payload_offset( + const packet_type_t pkt_type, const uint8_t num_mdata = 0) const = 0; + + //! Shortcut to return the const metadata pointer cast as a specific type + template <typename data_t> + inline const data_t* get_mdata_const_ptr_as() const + { + return reinterpret_cast<const data_t*>(get_mdata_const_ptr()); + } + + //! Shortcut to return the non-const metadata pointer cast as a specific type + template <typename data_t> + inline data_t* get_mdata_ptr_as() + { + return reinterpret_cast<data_t*>(get_mdata_ptr()); + } + + //! Shortcut to return the const payload pointer cast as a specific type + template <typename data_t> + inline const data_t* get_payload_const_ptr_as() const + { + return reinterpret_cast<const data_t*>(get_payload_const_ptr()); + } + + //! Shortcut to return the non-const payload pointer cast as a specific type + template <typename data_t> + inline data_t* get_payload_ptr_as() + { + return reinterpret_cast<data_t*>(get_payload_ptr()); + } + + //! Return a function to convert a word of type data_t to host order + template <typename data_t> + const std::function<data_t(data_t)> conv_to_host() const + { + return (get_byte_order() == uhd::ENDIANNESS_BIG) ? uhd::ntohx<data_t> + : uhd::wtohx<data_t>; + } + + //! Return a function to convert a word of type data_t from host order + template <typename data_t> + const std::function<data_t(data_t)> conv_from_host() const + { + return (get_byte_order() == uhd::ENDIANNESS_BIG) ? uhd::htonx<data_t> + : uhd::htowx<data_t>; + } +}; + +//---------------------------------------------------- +// Container for specific CHDR Packets +//---------------------------------------------------- + +//! A container class that wraps a generic buffer that contains a CHDR packet. The +// container provides a high level API to read and write the header, metadata and payload +// of the packet. The payload can be accessed as a specific type that will be serialized +// and deserialized appropriately. +// +template <typename payload_t> +class chdr_packet_writer_specific +{ +public: + //! A unique pointer to a const chdr_packet_writer. Useful as a read-only interface. + typedef std::unique_ptr<const chdr_packet_writer_specific<payload_t>> cuptr; + //! A unique pointer to a non-const chdr_packet_writer. Useful as a read-write + //! interface. + typedef std::unique_ptr<chdr_packet_writer_specific<payload_t>> uptr; + + chdr_packet_writer_specific(chdr_packet_writer::uptr chdr_pkt) + : _chdr_pkt(std::move(chdr_pkt)) + { + } + ~chdr_packet_writer_specific() = default; + + //! Updates the underlying storage of this packet. This is a const method and is + // only useful for read-only access. + inline void refresh(const void* pkt_buff) const + { + _chdr_pkt->refresh(pkt_buff); + } + + //! Updates the underlying storage of this packet, and populates it with the specified + // arguments. This is a non-const method and is useful for read-write access. + inline void refresh(void* pkt_buff, chdr_header& header, const payload_t& payload) + { + payload.populate_header(header); + _chdr_pkt->refresh(pkt_buff, header); + size_t bytes_copied = payload.serialize(_chdr_pkt->get_payload_ptr_as<uint64_t>(), + _chdr_pkt->get_mtu_bytes(), + _chdr_pkt->conv_from_host<uint64_t>()); + _chdr_pkt->update_payload_size(bytes_copied); + header = _chdr_pkt->get_chdr_header(); + } + + //! Returns a class that represents the contents of the CHDR header + inline chdr_header get_chdr_header() const + { + return std::move(_chdr_pkt->get_chdr_header()); + } + + //! Returns a class that represents the contents of the CHDR payload + inline payload_t get_payload() const + { + payload_t payload; + payload.deserialize(_chdr_pkt->get_payload_const_ptr_as<uint64_t>(), + _chdr_pkt->get_payload_size() / sizeof(uint64_t), + _chdr_pkt->conv_to_host<uint64_t>()); + return payload; + } + + //! Fills the CHDR payload into the specified parameter + inline void fill_payload(payload_t& payload) const + { + payload.deserialize(_chdr_pkt->get_payload_const_ptr_as<uint64_t>(), + _chdr_pkt->get_payload_size() / sizeof(uint64_t), + _chdr_pkt->conv_to_host<uint64_t>()); + } + +private: + chdr_packet_writer::uptr _chdr_pkt; +}; + +//---------------------------------------------------- +// Specific CHDR packet types +//---------------------------------------------------- + +//! CHDR control packet +typedef chdr_packet_writer_specific<ctrl_payload> chdr_ctrl_packet; + +//! CHDR stream status packet +typedef chdr_packet_writer_specific<strs_payload> chdr_strs_packet; + +//! CHDR stream command packet +typedef chdr_packet_writer_specific<strc_payload> chdr_strc_packet; + +//! CHDR management packet +typedef chdr_packet_writer_specific<mgmt_payload> chdr_mgmt_packet; + +//---------------------------------------------------- +// CHDR packet factory +//---------------------------------------------------- + +//! A copyable and movable factory class that is capable of generating generic and +//! specific CHDR packet containers. +// +class chdr_packet_factory +{ +public: + //! A parametrized ctor that takes in all the info required to generate a CHDR packet + // + // \param chdr_w The CHDR width of the remote device + // \param endianness The endianness of the link being used (e.g., Ethernet + // typically uses big-endian, PCIe typically uses + // little-endian). Note: The host endianness is + // automatically derived. + chdr_packet_factory(chdr_w_t chdr_w, endianness_t endianness); + chdr_packet_factory() = delete; + chdr_packet_factory(const chdr_packet_factory& rhs) = default; + chdr_packet_factory(chdr_packet_factory&& rhs) = default; + + //! Makes a generic CHDR packet and transfers ownership to the client + chdr_packet_writer::uptr make_generic( + size_t mtu_bytes = std::numeric_limits<size_t>::max()) const; + + //! Makes a CHDR control packet and transfers ownership to the client + chdr_ctrl_packet::uptr make_ctrl( + size_t mtu_bytes = std::numeric_limits<size_t>::max()) const; + + //! Makes a CHDR stream status packet and transfers ownership to the client + chdr_strs_packet::uptr make_strs( + size_t mtu_bytes = std::numeric_limits<size_t>::max()) const; + + //! Makes a CHDR stream cmd packet and transfers ownership to the client + chdr_strc_packet::uptr make_strc( + size_t mtu_bytes = std::numeric_limits<size_t>::max()) const; + + //! Makes a CHDR management packet and transfers ownership to the client + chdr_mgmt_packet::uptr make_mgmt( + size_t mtu_bytes = std::numeric_limits<size_t>::max()) const; + + //! Get the CHDR width + inline chdr_w_t get_chdr_w() const + { + return _chdr_w; + } + + //! Get the link endianness + inline endianness_t get_endianness() const + { + return _endianness; + } + + //! Get the protocol version for RFNoC and the CHDR format + inline uint16_t get_protover() const + { + return RFNOC_PROTO_VER; + } + +private: + const chdr_w_t _chdr_w; + const endianness_t _endianness; +}; + +}}} // namespace uhd::rfnoc::chdr |