aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib/rfnoc/chdr_packet.cpp
diff options
context:
space:
mode:
authorAshish Chaudhari <ashish@ettus.com>2019-05-25 00:14:36 -0700
committerMartin Braun <martin.braun@ettus.com>2019-11-26 11:49:20 -0800
commitb4bc85ac972b2e4f3e8e0b092947267f9f8aeee4 (patch)
treef3128013bf71d44ece3b408db6a03177c6fd5f56 /host/lib/rfnoc/chdr_packet.cpp
parent1e65500d791461be9aa7a2d2646d463f536f49e3 (diff)
downloaduhd-b4bc85ac972b2e4f3e8e0b092947267f9f8aeee4.tar.gz
uhd-b4bc85ac972b2e4f3e8e0b092947267f9f8aeee4.tar.bz2
uhd-b4bc85ac972b2e4f3e8e0b092947267f9f8aeee4.zip
rfnoc: Moved chdr types/packet class out of chdr dir
- Moved chdr_packet and chdr_types from rfnoc/chdr to rfnoc and updated all references - Moved non-CHDR definitions to rfnoc_common.hpp
Diffstat (limited to 'host/lib/rfnoc/chdr_packet.cpp')
-rw-r--r--host/lib/rfnoc/chdr_packet.cpp214
1 files changed, 214 insertions, 0 deletions
diff --git a/host/lib/rfnoc/chdr_packet.cpp b/host/lib/rfnoc/chdr_packet.cpp
new file mode 100644
index 000000000..653181c04
--- /dev/null
+++ b/host/lib/rfnoc/chdr_packet.cpp
@@ -0,0 +1,214 @@
+//
+// Copyright 2019 Ettus Research, a National Instruments Brand
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+//
+
+#include <uhdlib/rfnoc/chdr_packet.hpp>
+#include <cassert>
+#include <functional>
+#include <memory>
+
+using namespace uhd;
+using namespace uhd::rfnoc;
+using namespace uhd::rfnoc::chdr;
+
+chdr_packet::~chdr_packet() = default;
+
+//------------------------------------------------------------
+// chdr_packet
+//------------------------------------------------------------
+// endianness is the link endianness, not the host endianness
+template <size_t chdr_w, endianness_t endianness>
+class chdr_packet_impl : public chdr_packet
+{
+public:
+ chdr_packet_impl() = delete;
+ chdr_packet_impl(size_t mtu_bytes) : _mtu_bytes(mtu_bytes) {}
+ ~chdr_packet_impl() = default;
+
+ virtual void refresh(const void* pkt_buff) const
+ {
+ assert(pkt_buff);
+ _pkt_buff = const_cast<uint64_t*>(reinterpret_cast<const uint64_t*>(pkt_buff));
+ _compute_mdata_offset();
+ }
+
+ virtual void refresh(void* pkt_buff, chdr_header& header, uint64_t timestamp = 0)
+ {
+ assert(pkt_buff);
+ _pkt_buff = reinterpret_cast<uint64_t*>(pkt_buff);
+ _pkt_buff[0] = u64_from_host(header);
+ if (_has_timestamp(header)) {
+ _pkt_buff[1] = u64_from_host(timestamp);
+ }
+ _compute_mdata_offset();
+ }
+
+ virtual void update_payload_size(size_t payload_size_bytes)
+ {
+ chdr_header header = get_chdr_header();
+ header.set_length(((_mdata_offset + header.get_num_mdata()) * chdr_w_bytes)
+ + payload_size_bytes);
+ _pkt_buff[0] = u64_from_host(header);
+ }
+
+ virtual endianness_t get_byte_order() const
+ {
+ return endianness;
+ }
+
+ virtual size_t get_mtu_bytes() const
+ {
+ return _mtu_bytes;
+ }
+
+ virtual chdr_header get_chdr_header() const
+ {
+ assert(_pkt_buff);
+ return std::move(chdr_header(u64_to_host(_pkt_buff[0])));
+ }
+
+ virtual boost::optional<uint64_t> get_timestamp() const
+ {
+ if (_has_timestamp(get_chdr_header())) {
+ // In a unit64_t buffer, the timestamp is always immediately after the header
+ // regardless of chdr_w.
+ return u64_to_host(_pkt_buff[1]);
+ } else {
+ return boost::none;
+ }
+ }
+
+ virtual size_t get_mdata_size() const
+ {
+ return get_chdr_header().get_num_mdata() * chdr_w_bytes;
+ }
+
+ virtual const void* get_mdata_const_ptr() const
+ {
+ return const_cast<void*>(
+ const_cast<chdr_packet_impl<chdr_w, endianness>*>(this)->get_mdata_ptr());
+ }
+
+ virtual void* get_mdata_ptr()
+ {
+ return reinterpret_cast<void*>(_pkt_buff + (chdr_w_stride * _mdata_offset));
+ }
+
+ virtual size_t get_payload_size() const
+ {
+ return get_chdr_header().get_length() - get_mdata_size()
+ - (chdr_w_bytes * _mdata_offset);
+ }
+
+ virtual const void* get_payload_const_ptr() const
+ {
+ return const_cast<void*>(
+ const_cast<chdr_packet_impl<chdr_w, endianness>*>(this)->get_payload_ptr());
+ }
+
+ virtual void* get_payload_ptr()
+ {
+ return reinterpret_cast<void*>(
+ _pkt_buff
+ + (chdr_w_stride * (_mdata_offset + get_chdr_header().get_num_mdata())));
+ }
+
+private:
+ inline bool _has_timestamp(const chdr_header& header) const
+ {
+ return (header.get_pkt_type() == PKT_TYPE_DATA_WITH_TS);
+ }
+
+ inline void _compute_mdata_offset() const
+ {
+ // The metadata offset depends on the chdr_w and whether we have a timestamp
+ if (chdr_w == 64) {
+ _mdata_offset = _has_timestamp(get_chdr_header()) ? 2 : 1;
+ } else {
+ _mdata_offset = 1;
+ }
+ }
+
+ inline static uint64_t u64_to_host(uint64_t word)
+ {
+ return (endianness == ENDIANNESS_BIG) ? uhd::ntohx<uint64_t>(word)
+ : uhd::wtohx<uint64_t>(word);
+ }
+
+ inline static uint64_t u64_from_host(uint64_t word)
+ {
+ return (endianness == ENDIANNESS_BIG) ? uhd::htonx<uint64_t>(word)
+ : uhd::htowx<uint64_t>(word);
+ }
+
+ static const size_t chdr_w_bytes = (chdr_w / 8);
+ static const size_t chdr_w_stride = (chdr_w / 64);
+
+ // Packet state
+ const size_t _mtu_bytes = 0;
+ mutable uint64_t* _pkt_buff = nullptr;
+ mutable size_t _mdata_offset = 0;
+};
+
+chdr_packet_factory::chdr_packet_factory(chdr_w_t chdr_w, endianness_t endianness)
+ : _chdr_w(chdr_w), _endianness(endianness)
+{
+}
+
+chdr_packet::uptr chdr_packet_factory::make_generic(size_t mtu_bytes) const
+{
+ if (_endianness == ENDIANNESS_BIG) {
+ switch (_chdr_w) {
+ case CHDR_W_512:
+ return std::make_unique<chdr_packet_impl<512, ENDIANNESS_BIG>>(mtu_bytes);
+ case CHDR_W_256:
+ return std::make_unique<chdr_packet_impl<256, ENDIANNESS_BIG>>(mtu_bytes);
+ case CHDR_W_128:
+ return std::make_unique<chdr_packet_impl<128, ENDIANNESS_BIG>>(mtu_bytes);
+ case CHDR_W_64:
+ return std::make_unique<chdr_packet_impl<64, ENDIANNESS_BIG>>(mtu_bytes);
+ default:
+ assert(0);
+ }
+ } else {
+ switch (_chdr_w) {
+ case CHDR_W_512:
+ return std::make_unique<chdr_packet_impl<512, ENDIANNESS_LITTLE>>(
+ mtu_bytes);
+ case CHDR_W_256:
+ return std::make_unique<chdr_packet_impl<256, ENDIANNESS_LITTLE>>(
+ mtu_bytes);
+ case CHDR_W_128:
+ return std::make_unique<chdr_packet_impl<128, ENDIANNESS_LITTLE>>(
+ mtu_bytes);
+ case CHDR_W_64:
+ return std::make_unique<chdr_packet_impl<64, ENDIANNESS_LITTLE>>(
+ mtu_bytes);
+ default:
+ assert(0);
+ }
+ }
+ return chdr_packet::uptr();
+}
+
+chdr_ctrl_packet::uptr chdr_packet_factory::make_ctrl(size_t mtu_bytes) const
+{
+ return std::make_unique<chdr_ctrl_packet>(make_generic(mtu_bytes));
+}
+
+chdr_strs_packet::uptr chdr_packet_factory::make_strs(size_t mtu_bytes) const
+{
+ return std::make_unique<chdr_strs_packet>(make_generic(mtu_bytes));
+}
+
+chdr_strc_packet::uptr chdr_packet_factory::make_strc(size_t mtu_bytes) const
+{
+ return std::make_unique<chdr_strc_packet>(make_generic(mtu_bytes));
+}
+
+chdr_mgmt_packet::uptr chdr_packet_factory::make_mgmt(size_t mtu_bytes) const
+{
+ return std::make_unique<chdr_mgmt_packet>(make_generic(mtu_bytes));
+}