1// 2// Copyright 2020 Ettus Research, a National Instruments Brand 3// 4// SPDX-License-Identifier: GPL-3.0-or-later 5// 6 7#pragma once 8 9#include <uhd/exception.hpp> 10#include <uhd/types/endianness.hpp> 11 12namespace chdr_rfnoc = uhd::rfnoc::chdr; 13namespace uhd { namespace utils { namespace chdr { 14 15template <typename payload_t> 16chdr_packet::chdr_packet(uhd::rfnoc::chdr_w_t chdr_w, 17 chdr_rfnoc::chdr_header header, 18 payload_t payload, 19 boost::optional<uint64_t> timestamp, 20 std::vector<uint64_t> metadata) 21 : chdr_packet(chdr_w, header, std::vector<uint8_t>(), timestamp, std::move(metadata)) 22{ 23 set_payload(payload); 24} 25 26template <typename OutputIterator> 27void chdr_packet::serialize( 28 OutputIterator first, OutputIterator last, uhd::endianness_t endianness) const 29{ 30 void* start = static_cast<void*>(&*first); 31 void* end = static_cast<void*>(&*last); 32 serialize_ptr(endianness, start, end); 33} 34 35template <typename InputIterator> 36chdr_packet chdr_packet::deserialize(uhd::rfnoc::chdr_w_t chdr_w, 37 InputIterator first, 38 InputIterator last, 39 uhd::endianness_t endianness) 40{ 41 void* start = static_cast<void*>(&*first); 42 void* end = static_cast<void*>(&*last); 43 return deserialize_ptr(chdr_w, endianness, start, end); 44} 45 46template <typename payload_t> 47payload_t chdr_packet::get_payload(uhd::endianness_t endianness) const 48{ 49 payload_t payload; 50 // Only Data Packets are allowed to have end on a incomplete CHDR_W length. 51 // This method is never called on a data packet. (They don't have a payload_t) 52 UHD_ASSERT_THROW(this->_payload.size() % sizeof(uint64_t) == 0) 53 auto conv_byte_order = [endianness](uint64_t x) -> uint64_t { 54 return (endianness == uhd::ENDIANNESS_BIG) ? uhd::htonx<uint64_t>(x) 55 : uhd::htowx<uint64_t>(x); 56 }; 57 payload.deserialize(reinterpret_cast<const uint64_t*>(this->_payload.data()), 58 this->_payload.size(), 59 conv_byte_order); 60 return payload; 61} 62 63template <typename payload_t> 64void chdr_packet::set_payload(payload_t payload, uhd::endianness_t endianness) 65{ 66 _header.set_pkt_type(chdr_rfnoc::payload_to_packet_type<payload_t>()); 67 // Meaning a 64 bit word (The basic unit of data for payloads) 68 size_t payload_len_words = payload.get_length(); 69 this->_payload.resize(payload_len_words * sizeof(uint64_t), 0); 70 auto conv_byte_order = [endianness](uint64_t x) -> uint64_t { 71 return (endianness == uhd::ENDIANNESS_BIG) ? uhd::htonx<uint64_t>(x) 72 : uhd::htowx<uint64_t>(x); 73 }; 74 payload.serialize(reinterpret_cast<uint64_t*>(this->_payload.data()), 75 this->_payload.size(), 76 conv_byte_order); 77 set_header_lengths(); 78} 79 80template <typename payload_t> 81const std::string chdr_packet::to_string_with_payload( 82 uhd::endianness_t endianness) const 83{ 84 payload_t payload = this->get_payload<payload_t>(endianness); 85 return to_string() + payload.to_string(); 86} 87 88template <> 89const std::string 90chdr_packet::to_string_with_payload<chdr_rfnoc::mgmt_payload>( 91 uhd::endianness_t endianness) const 92{ 93 chdr_rfnoc::mgmt_payload payload = 94 this->get_payload<chdr_rfnoc::mgmt_payload>(endianness); 95 return to_string() + payload.to_string() + payload.hops_to_string(); 96} 97 98}}}// namespace uhd::utils::chdr 99