aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTrung Tran <trung.tran@ettus.com>2019-04-08 10:04:30 -0700
committerMartin Braun <martin.braun@ettus.com>2019-11-26 11:49:13 -0800
commit1341959e0448d5ba77258f9cca2893b8095247e1 (patch)
tree22947fae8057821155a31804ad4541a60446c867
parentefb1d5a4729ea892ea03b8d0265aae9e8fadfff1 (diff)
downloaduhd-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.hpp57
-rw-r--r--host/include/uhd/rfnoc/chdr/chdr_packet.hpp154
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 */