diff options
author | Trung Tran <trung.tran@ettus.com> | 2019-04-08 10:04:30 -0700 |
---|---|---|
committer | Martin Braun <martin.braun@ettus.com> | 2019-11-26 11:49:13 -0800 |
commit | 1341959e0448d5ba77258f9cca2893b8095247e1 (patch) | |
tree | 22947fae8057821155a31804ad4541a60446c867 | |
parent | efb1d5a4729ea892ea03b8d0265aae9e8fadfff1 (diff) | |
download | uhd-1341959e0448d5ba77258f9cca2893b8095247e1.tar.gz uhd-1341959e0448d5ba77258f9cca2893b8095247e1.tar.bz2 uhd-1341959e0448d5ba77258f9cca2893b8095247e1.zip |
rfnoc: add chdr packet interface
This is a generic CHDR interface that abstracts out the bus width.
-rw-r--r-- | host/include/uhd/rfnoc/chdr/chdr_header.hpp | 57 | ||||
-rw-r--r-- | host/include/uhd/rfnoc/chdr/chdr_packet.hpp | 154 |
2 files changed, 196 insertions, 15 deletions
diff --git a/host/include/uhd/rfnoc/chdr/chdr_header.hpp b/host/include/uhd/rfnoc/chdr/chdr_header.hpp index bd6d71fd1..1fdbdc0b5 100644 --- a/host/include/uhd/rfnoc/chdr/chdr_header.hpp +++ b/host/include/uhd/rfnoc/chdr/chdr_header.hpp @@ -9,7 +9,9 @@ #include <uhd/types/endianness.hpp> #include <uhd/utils/byteswap.hpp> +#include <uhd/exception.hpp> #include <cassert> +#include <memory> namespace uhd { namespace rfnoc { namespace chdr { @@ -35,13 +37,40 @@ enum class packet_type_t { PACKET_TYPE_DATA_WITH_TS = 0x7, // Data Packet with TimeStamp }; + +class chdr_header_iface +{ +public: + using uptr = std::unique_ptr<chdr_header_iface>; + + static uptr make(size_t chdr_w, uint64_t header_val); + static uptr make(size_t chdr_w, packet_type_t pkt_type); + virtual size_t get_word_size() const = 0; + virtual uint64_t get() const = 0; + virtual uint8_t get_flags() const = 0; + virtual packet_type_t get_pkt_type() const = 0; + virtual uint8_t get_num_metadata() const = 0; + virtual uint8_t get_num_bytes_metadata() const = 0; + virtual uint16_t get_seq_num() const = 0; + virtual uint16_t get_length() const = 0; + virtual uint16_t get_dst_epid() const = 0; + virtual size_t get_num_words_payload() const = 0; + virtual size_t get_num_bytes_payload() const = 0; + virtual size_t get_metadata_offset() const = 0; + virtual size_t get_payload_offset() const = 0; + virtual void set_flags(uint8_t flags) = 0; + virtual void set_seq_num(uint16_t seq_num) = 0; + virtual void set_dst_epid(uint16_t dst_epid) = 0; + virtual void set_packet_size(size_t num_payload, size_t num_metadata = 0) = 0; +}; + /*! Header information of a data packet * This is the first 64-bit */ -template <size_t chdr_w> class chdr_header +template <size_t chdr_w> +class chdr_header : public chdr_header_iface { public: - ~chdr_header() = default; chdr_header(packet_type_t packet_type) @@ -49,9 +78,7 @@ public: _set_pkt_type(packet_type); } - chdr_header(uint64_t header_val) : _header_val(header_val) - { - } + chdr_header(uint64_t header_val) : _header_val(header_val) {} /*! Return the word size in bytes */ @@ -233,6 +260,26 @@ private: } }; +chdr_header_iface::uptr chdr_header_iface::make(size_t chdr_w, uint64_t header_val) +{ + if (chdr_w == 256) + return uptr(new chdr_header<256>(header_val)); + else + return uptr(new chdr_header<64>(header_val)); +} + +chdr_header_iface::uptr chdr_header_iface::make(size_t chdr_w, packet_type_t pkt_type) +{ + switch (chdr_w) { + case 256: + return uptr(new chdr_header<256>(pkt_type)); + case 64: + return uptr(new chdr_header<64>(pkt_type)); + default: + UHD_THROW_INVALID_CODE_PATH(); + } +} + }}} // namespace uhd::rfnoc::chdr #endif /* INCLUDED_RFNOC_CHDR_HEADER_HPP */ diff --git a/host/include/uhd/rfnoc/chdr/chdr_packet.hpp b/host/include/uhd/rfnoc/chdr/chdr_packet.hpp index 89716679a..0a2ae68f3 100644 --- a/host/include/uhd/rfnoc/chdr/chdr_packet.hpp +++ b/host/include/uhd/rfnoc/chdr/chdr_packet.hpp @@ -8,10 +8,31 @@ #define INCLUDED_RFNOC_CHDR_DATA_PACKET_HPP #include <uhd/rfnoc/chdr/chdr_header.hpp> +#include <uhd/exception.hpp> #include <cassert> +#include <memory> namespace uhd { namespace rfnoc { namespace chdr { +class chdr_packet_iface +{ +public: + typedef std::unique_ptr<chdr_packet_iface> uptr; + static uptr make(void* pkt_buff); + static uptr make(size_t chdr_w, endianness_t endianness, void* pkt_buff); + static uptr make( + size_t chdr_w, endianness_t endianness, uint64_t header_val, void* pkt_buff); + virtual uint64_t get_header_val() const = 0; + virtual void set_header_val(uint64_t header_val) = 0; + virtual uint64_t get_timestamp() const = 0; + virtual void set_timestamp(uint64_t timestamp) = 0; + virtual uint64_t* metadata_ptr_of_type_uint64_t() const = 0; + virtual uint32_t* metadata_ptr_of_type_uint32_t() const = 0; + virtual uint64_t* payload_ptr_of_type_uint64_t() const = 0; + virtual uint32_t* payload_ptr_of_type_uint32_t() const = 0; + virtual uint16_t* payload_ptr_of_type_uint16_t() const = 0; +}; + /*! CHDR Packet Abstraction Class * * This class wraps a pointer to a buffer containing a CHDR packet. It also @@ -26,7 +47,7 @@ namespace uhd { namespace rfnoc { namespace chdr { * NOTE: This assumes the host is little-endian. */ template <size_t chdr_w, endianness_t endianness> -class chdr_packet +class chdr_packet : public chdr_packet_iface { public: typedef chdr_header<chdr_w> header_t; @@ -73,12 +94,36 @@ public: /*! Get a copy of the header data (the first 64-bit of the CHDR packet) * * This copy will be in native byte order. - */ + */ inline header_t get_header() const { return _header; } + /*! Get a copy of the 64-bit value of the packet header (the first 64-bit + * of the CHDR packet) + * + * This copy will be in native byte order. + */ + inline uint64_t get_header_val() const + { + return _header.get(); + } + + /*! Set 64-bit value of the packet header (the first 64-bit of the CHDR + * packet) + * + * This set 64_bit value will swap byte to native byte order. + */ + inline void set_header_val(uint64_t header_val) + { + if (endianness == endianness_t::ENDIANNESS_BIG) { + _header = header_t(ntohx<uint64_t>(header_val)); + } else { + _header = header_t(header_val); + } + } + /*! Return the pointer to the first byte of metadata of this CHDR packet * * Note: This class does no bounds checking. It is up to the user to only @@ -95,11 +140,12 @@ public: * // size is zero): * metadata_ptr[metadata_size] = 0xF0; * ~~~ - */ - template <typename data_t> inline data_t* metadata_ptr_of_type() const + */ + template <typename data_t> + inline data_t* metadata_ptr_of_type() const { return reinterpret_cast<data_t*>( - reinterpret_cast<char*>(_pkt_buff) + _header.get_metadata_offset()); + reinterpret_cast<char*>(_pkt_buff) + _header.get_metadata_offset()); } /*! Get 64-bit timestamp of this CHDR packet in native byte order @@ -111,7 +157,7 @@ public: { assert(_header.get_pkt_type() == packet_type_t::PACKET_TYPE_DATA_WITH_TS); return endianness_t::ENDIANNESS_BIG ? ntohx<uint64_t>(*(_pkt_buff + 1)) - : *(_pkt_buff + 1); + : *(_pkt_buff + 1); } /*! Set 64-bit timestamp of this CHDR packet. @@ -125,7 +171,7 @@ public: { assert(_header.get_pkt_type() == packet_type_t::PACKET_TYPE_DATA_WITH_TS); *(_pkt_buff + 1) = endianness_t::ENDIANNESS_BIG ? htonx<uint64_t>(timestamp) - : timestamp; + : timestamp; } /*! Return the pointer to the first payload byte of this CHDR packet @@ -143,11 +189,42 @@ public: * // exception. Instead, it could even segfault: * payload_ptr[payload_size] = 0xF0; * ~~~ - */ - template <typename payload_t> inline payload_t* payload_ptr_of_type() const + */ + template <typename payload_t> + inline payload_t* payload_ptr_of_type() const { return reinterpret_cast<payload_t*>( - reinterpret_cast<char*>(_pkt_buff) + _header.get_payload_offset()); + reinterpret_cast<char*>(_pkt_buff) + _header.get_payload_offset()); + } + + inline uint64_t* payload_ptr_of_type_uint64_t() const + { + return reinterpret_cast<uint64_t*>( + reinterpret_cast<char*>(_pkt_buff) + _header.get_payload_offset()); + } + + inline uint32_t* payload_ptr_of_type_uint32_t() const + { + return reinterpret_cast<uint32_t*>( + reinterpret_cast<char*>(_pkt_buff) + _header.get_payload_offset()); + } + + inline uint16_t* payload_ptr_of_type_uint16_t() const + { + return reinterpret_cast<uint16_t*>( + reinterpret_cast<char*>(_pkt_buff) + _header.get_payload_offset()); + } + + inline uint64_t* metadata_ptr_of_type_uint64_t() const + { + return reinterpret_cast<uint64_t*>( + reinterpret_cast<char*>(_pkt_buff) + _header.get_metadata_offset()); + } + + inline uint32_t* metadata_ptr_of_type_uint32_t() const + { + return reinterpret_cast<uint32_t*>( + reinterpret_cast<char*>(_pkt_buff) + _header.get_metadata_offset()); } private: @@ -155,6 +232,63 @@ private: header_t _header = header_t(0); }; +chdr_packet_iface::uptr chdr_packet_iface::make(void* pkt_buff) +{ + return uptr(new chdr_packet<64, ENDIANNESS_LITTLE>(pkt_buff)); +} + +chdr_packet_iface::uptr chdr_packet_iface::make( + size_t chdr_w, endianness_t endianness, void* pkt_buff) +{ + if (endianness == ENDIANNESS_BIG) { + switch (chdr_w) { + case 256: + return uptr(new chdr_packet<256, ENDIANNESS_BIG>(pkt_buff)); + case 64: + return uptr(new chdr_packet<64, ENDIANNESS_BIG>(pkt_buff)); + default: + UHD_THROW_INVALID_CODE_PATH(); + } + } else { + switch (chdr_w) { + case 256: + return uptr(new chdr_packet<256, ENDIANNESS_LITTLE>(pkt_buff)); + case 64: + return uptr(new chdr_packet<64, ENDIANNESS_LITTLE>(pkt_buff)); + default: + UHD_THROW_INVALID_CODE_PATH(); + } + } +} + +chdr_packet_iface::uptr chdr_packet_iface::make( + size_t chdr_w, endianness_t endianness, uint64_t header_val, void* pkt_buff) +{ + if (endianness == ENDIANNESS_BIG) { + switch (chdr_w) { + case 256: + return uptr(new chdr_packet<256, ENDIANNESS_BIG>( + chdr_header<256>(header_val), pkt_buff)); + case 64: + return uptr(new chdr_packet<64, ENDIANNESS_BIG>( + chdr_header<64>(header_val), pkt_buff)); + default: + UHD_THROW_INVALID_CODE_PATH(); + } + } else { + switch (chdr_w) { + case 256: + return uptr(new chdr_packet<256, ENDIANNESS_LITTLE>( + chdr_header<256>(header_val), pkt_buff)); + case 64: + return uptr(new chdr_packet<64, ENDIANNESS_LITTLE>( + chdr_header<64>(header_val), pkt_buff)); + default: + UHD_THROW_INVALID_CODE_PATH(); + } + } +} + }}} // namespace uhd::rfnoc::chdr #endif /* INCLUDED_RFNOC_CHDR_DATA_PACKET_HPP */ |