diff options
author | Ashish Chaudhari <ashish@ettus.com> | 2019-05-25 00:14:36 -0700 |
---|---|---|
committer | Martin Braun <martin.braun@ettus.com> | 2019-11-26 11:49:20 -0800 |
commit | b4bc85ac972b2e4f3e8e0b092947267f9f8aeee4 (patch) | |
tree | f3128013bf71d44ece3b408db6a03177c6fd5f56 /host/lib/rfnoc/chdr_packet.cpp | |
parent | 1e65500d791461be9aa7a2d2646d463f536f49e3 (diff) | |
download | uhd-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.cpp | 214 |
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)); +} |