aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib
diff options
context:
space:
mode:
Diffstat (limited to 'host/lib')
-rw-r--r--host/lib/rfnoc/chdr_types.cpp124
-rw-r--r--host/lib/utils/CMakeLists.txt2
-rw-r--r--host/lib/utils/chdr/CMakeLists.txt9
-rw-r--r--host/lib/utils/chdr/chdr_packet.cpp168
4 files changed, 303 insertions, 0 deletions
diff --git a/host/lib/rfnoc/chdr_types.cpp b/host/lib/rfnoc/chdr_types.cpp
index 3cb68ff9a..3978c8694 100644
--- a/host/lib/rfnoc/chdr_types.cpp
+++ b/host/lib/rfnoc/chdr_types.cpp
@@ -9,6 +9,7 @@
#include <uhd/types/endianness.hpp>
#include <boost/format.hpp>
#include <cassert>
+#include <sstream>
using namespace uhd;
using namespace uhd::rfnoc::chdr;
@@ -141,6 +142,17 @@ void ctrl_payload::deserialize(const uint64_t* buff,
UHD_ASSERT_THROW(ptr <= max_size_bytes);
}
+size_t ctrl_payload::get_length() const
+{
+ size_t length = 1;
+ if (this->has_timestamp()) {
+ length += 1;
+ }
+ size_t operations = 1 + this->data_vtr.size();
+ length += operations / 2 + operations % 2;
+ return length;
+}
+
bool ctrl_payload::operator==(const ctrl_payload& rhs) const
{
return (dst_port == rhs.dst_port) && (src_port == rhs.src_port)
@@ -241,6 +253,11 @@ void strs_payload::deserialize(const uint64_t* buff,
status_info = get_field_u64<uint64_t>(word3, STATUS_INFO_OFFSET, STATUS_INFO_WIDTH);
}
+size_t strs_payload::get_length() const
+{
+ return 4;
+}
+
bool strs_payload::operator==(const strs_payload& rhs) const
{
return (src_epid == rhs.src_epid) && (status == rhs.status)
@@ -310,6 +327,11 @@ void strc_payload::deserialize(const uint64_t* buff,
num_bytes = conv_byte_order(buff[1]);
}
+size_t strc_payload::get_length() const
+{
+ return 2;
+}
+
bool strc_payload::operator==(const strc_payload& rhs) const
{
return (src_epid == rhs.src_epid) && (op_code == rhs.op_code)
@@ -328,6 +350,74 @@ const std::string strc_payload::to_string() const
// CHDR Management Payload
//----------------------------------------------------
+const std::string mgmt_op_t::to_string() const
+{
+ std::stringstream stream;
+ switch (get_op_code()) {
+ case mgmt_op_t::MGMT_OP_NOP:
+ stream << "NOP";
+ break;
+ case mgmt_op_t::MGMT_OP_ADVERTISE:
+ stream << "ADVERTISE";
+ break;
+ case mgmt_op_t::MGMT_OP_SEL_DEST:
+ stream << "SEL_DEST";
+ break;
+ case mgmt_op_t::MGMT_OP_RETURN:
+ stream << "RETURN";
+ break;
+ case mgmt_op_t::MGMT_OP_INFO_REQ:
+ stream << "INFO_REQ";
+ break;
+ case mgmt_op_t::MGMT_OP_INFO_RESP:
+ stream << "INFO_RESP";
+ break;
+ case mgmt_op_t::MGMT_OP_CFG_WR_REQ:
+ stream << "CFG_WR_REQ";
+ break;
+ case mgmt_op_t::MGMT_OP_CFG_RD_REQ:
+ stream << "CFG_RD_REQ";
+ break;
+ case mgmt_op_t::MGMT_OP_CFG_RD_RESP:
+ stream << "CFG_RD_RESP";
+ break;
+ default:
+ UHD_THROW_INVALID_CODE_PATH();
+ }
+ stream << ": ";
+ switch (get_op_code()) {
+ case mgmt_op_t::MGMT_OP_SEL_DEST: {
+ mgmt_op_t::sel_dest_payload payload = static_cast<uint64_t>(get_op_payload());
+ stream << "dest:" << payload.dest;
+ break;
+ }
+ case mgmt_op_t::MGMT_OP_CFG_WR_REQ:
+ case mgmt_op_t::MGMT_OP_CFG_RD_REQ:
+ case mgmt_op_t::MGMT_OP_CFG_RD_RESP: {
+ mgmt_op_t::cfg_payload payload = static_cast<uint64_t>(get_op_payload());
+ stream << str(
+ boost::format("addr:0x%08x, data:0x%08x") % payload.addr % payload.data);
+ break;
+ }
+ case mgmt_op_t::MGMT_OP_INFO_REQ:
+ case mgmt_op_t::MGMT_OP_INFO_RESP: {
+ mgmt_op_t::node_info_payload payload =
+ static_cast<uint64_t>(get_op_payload());
+ stream << "device_id:" << payload.device_id
+ << ", node_type:" << payload.node_type
+ << ", node_inst:" << payload.node_inst
+ << ", ext_info:" << payload.ext_info;
+ break;
+ }
+ default: {
+ stream << "-";
+ break;
+ }
+ }
+ stream << "\n";
+ return stream.str();
+}
+
//! Serialize this hop into a list of 64-bit words
size_t mgmt_hop_t::serialize(std::vector<uint64_t>& target,
const std::function<uint64_t(uint64_t)>& conv_byte_order,
@@ -369,6 +459,21 @@ void mgmt_hop_t::deserialize(std::list<uint64_t>& src,
} while (ops_remaining > 0);
}
+const std::string mgmt_hop_t::to_string() const
+{
+ std::stringstream stream;
+ for (size_t op_index = 0; op_index < get_num_ops(); op_index++) {
+ if (op_index == 0) {
+ stream << " -> ";
+ } else {
+ stream << " ";
+ }
+ const mgmt_op_t& op = get_op(op_index);
+ stream << op.to_string();
+ }
+ return stream.str();
+}
+
void mgmt_payload::populate_header(chdr_header& header) const
{
header.set_pkt_type(PKT_TYPE_MGMT);
@@ -440,6 +545,15 @@ void mgmt_payload::deserialize(const uint64_t* buff,
}
}
+size_t mgmt_payload::get_length() const
+{
+ size_t length = 1 + _padding_size; /* header */
+ for (const auto& hop : this->_hops) {
+ length += hop.get_num_ops() + _padding_size;
+ }
+ return length;
+}
+
const std::string mgmt_payload::to_string() const
{
return str(boost::format(
@@ -447,6 +561,16 @@ const std::string mgmt_payload::to_string() const
% _src_epid % int(_chdr_w) % _protover % _hops.size());
}
+const std::string mgmt_payload::hops_to_string() const
+{
+ std::stringstream stream;
+ for (size_t hop_index = 0; hop_index < get_num_hops(); hop_index++) {
+ const mgmt_hop_t& hop = get_hop(hop_index);
+ stream << hop.to_string();
+ }
+ return stream.str();
+}
+
bool mgmt_payload::operator==(const mgmt_payload& rhs) const
{
diff --git a/host/lib/utils/CMakeLists.txt b/host/lib/utils/CMakeLists.txt
index aa06e2c45..7e95d8c28 100644
--- a/host/lib/utils/CMakeLists.txt
+++ b/host/lib/utils/CMakeLists.txt
@@ -9,6 +9,8 @@
# This file included, use CMake directory variables
########################################################################
+INCLUDE_SUBDIRECTORY(chdr)
+
########################################################################
# Setup defines for process scheduling
########################################################################
diff --git a/host/lib/utils/chdr/CMakeLists.txt b/host/lib/utils/chdr/CMakeLists.txt
new file mode 100644
index 000000000..04f1180d4
--- /dev/null
+++ b/host/lib/utils/chdr/CMakeLists.txt
@@ -0,0 +1,9 @@
+#
+# Copyright 2020 Ettus Research, a National Instruments Brand
+#
+# SPDX-License-Identifier: GPL-3.0-or-later
+#
+
+LIBUHD_APPEND_SOURCES(
+ ${CMAKE_CURRENT_SOURCE_DIR}/chdr_packet.cpp
+)
diff --git a/host/lib/utils/chdr/chdr_packet.cpp b/host/lib/utils/chdr/chdr_packet.cpp
new file mode 100644
index 000000000..6a0e3f8bb
--- /dev/null
+++ b/host/lib/utils/chdr/chdr_packet.cpp
@@ -0,0 +1,168 @@
+//
+// Copyright 2020 Ettus Research, a National Instruments Brand
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+//
+
+#include <uhd/utils/chdr/chdr_packet.hpp>
+#include <uhdlib/rfnoc/chdr_packet_writer.hpp>
+#include <boost/format.hpp>
+
+namespace chdr_rfnoc = uhd::rfnoc::chdr;
+namespace chdr_util = uhd::utils::chdr;
+using namespace uhd;
+
+chdr_util::chdr_packet::chdr_packet(uhd::rfnoc::chdr_w_t chdr_w,
+ chdr_rfnoc::chdr_header header,
+ std::vector<uint8_t> payload,
+ boost::optional<uint64_t> timestamp,
+ std::vector<uint64_t> mdata)
+ : _chdr_w(chdr_w)
+ , _header(header)
+ , _payload(std::move(payload))
+ , _timestamp(timestamp)
+ , _mdata(std::move(mdata))
+{
+ set_header_lengths();
+}
+
+inline static uint64_t u64_to_host(uhd::endianness_t endianness, uint64_t word)
+{
+ return (endianness == ENDIANNESS_BIG) ? uhd::ntohx<uint64_t>(word)
+ : uhd::wtohx<uint64_t>(word);
+}
+
+inline static uint64_t u64_from_host(uhd::endianness_t endianness, uint64_t word)
+{
+ return (endianness == ENDIANNESS_BIG) ? uhd::htonx<uint64_t>(word)
+ : uhd::htowx<uint64_t>(word);
+}
+
+chdr_rfnoc::chdr_header chdr_util::chdr_packet::get_header() const
+{
+ return this->_header;
+}
+
+void chdr_util::chdr_packet::set_header(chdr_rfnoc::chdr_header header)
+{
+ _header = header;
+ set_header_lengths();
+}
+
+boost::optional<uint64_t> chdr_util::chdr_packet::get_timestamp() const
+{
+ return this->_timestamp;
+}
+
+void chdr_util::chdr_packet::set_timestamp(boost::optional<uint64_t> timestamp)
+{
+ _timestamp = timestamp;
+ set_header_lengths();
+}
+
+std::vector<uint8_t> chdr_util::chdr_packet::serialize_to_byte_vector(
+ endianness_t endianness) const
+{
+ std::vector<uint8_t> buffer(get_packet_len(), 0);
+ serialize(buffer.begin(), buffer.end(), endianness);
+ return buffer;
+}
+
+void chdr_util::chdr_packet::serialize_ptr(
+ endianness_t endianness, void* start, void* end) const
+{
+ size_t len = static_cast<uint8_t*>(end) - static_cast<uint8_t*>(start);
+ UHD_ASSERT_THROW(get_packet_len() <= len);
+ chdr_rfnoc::chdr_packet_factory factory(_chdr_w, endianness);
+ chdr_rfnoc::chdr_packet_writer::uptr packet_writer =
+ factory.make_generic(std::numeric_limits<size_t>::max());
+ chdr_rfnoc::chdr_header header = _header;
+ packet_writer->refresh(start, header, (_timestamp ? *_timestamp : 0));
+
+ uint64_t* mdata_ptr = static_cast<uint64_t*>(packet_writer->get_mdata_ptr());
+ auto mdata_src_begin = this->_mdata.begin();
+ auto mdata_src_end = this->_mdata.end();
+ std::transform(
+ mdata_src_begin, mdata_src_end, mdata_ptr, [endianness](uint64_t value) {
+ return u64_from_host(endianness, value);
+ });
+
+ uint8_t* payload_ptr = static_cast<uint8_t*>(packet_writer->get_payload_ptr());
+ std::copy(_payload.begin(), _payload.end(), payload_ptr);
+}
+
+chdr_util::chdr_packet chdr_util::chdr_packet::deserialize_ptr(
+ uhd::rfnoc::chdr_w_t chdr_w,
+ endianness_t endianness,
+ const void* start,
+ const void* end)
+{
+ chdr_rfnoc::chdr_packet_factory factory(chdr_w, endianness);
+ chdr_rfnoc::chdr_packet_writer::uptr packet_writer =
+ factory.make_generic(std::numeric_limits<size_t>::max());
+ packet_writer->refresh(start);
+
+ chdr_rfnoc::chdr_header header = packet_writer->get_chdr_header();
+ boost::optional<uint64_t> timestamp = packet_writer->get_timestamp();
+
+ const size_t mdata_size_words = packet_writer->get_mdata_size() / 8;
+ const uint64_t* mdata_src_begin =
+ static_cast<const uint64_t*>(packet_writer->get_mdata_const_ptr());
+ const uint64_t* mdata_src_end = mdata_src_begin + mdata_size_words;
+ std::vector<uint64_t> mdata(mdata_size_words, 0);
+ uint64_t* mdata_ptr = mdata.data();
+ UHD_ASSERT_THROW(mdata_src_end < static_cast<const uint64_t*>(end));
+ std::transform(
+ mdata_src_begin, mdata_src_end, mdata_ptr, [endianness](uint64_t value) {
+ return u64_from_host(endianness, value);
+ });
+
+ size_t payload_size = packet_writer->get_payload_size();
+ const uint8_t* payload_begin =
+ static_cast<const uint8_t*>(packet_writer->get_payload_const_ptr());
+ const uint8_t* payload_end = payload_begin + payload_size;
+ std::vector<uint8_t> payload(payload_size, 0);
+ UHD_ASSERT_THROW(payload_end <= static_cast<const uint8_t*>(end));
+ std::copy(payload_begin, payload_end, payload.begin());
+
+ return chdr_util::chdr_packet(chdr_w, header, payload, timestamp, mdata);
+}
+
+void chdr_util::chdr_packet::set_metadata(std::vector<uint64_t> metadata)
+{
+ _mdata = std::move(metadata);
+ set_header_lengths();
+}
+
+const std::vector<uint64_t>& chdr_util::chdr_packet::get_metadata() const
+{
+ return _mdata;
+}
+
+size_t chdr_util::chdr_packet::get_packet_len() const
+{
+ size_t chdr_w_bytes = uhd::rfnoc::chdr_w_to_bits(_chdr_w) / 8;
+ // The timestamp and header take up 2 chdr_w lengths only when CHDR_W = 64 bits and
+ // there is a timestamp (RFNoC Specifcation section 2.2.1)
+ return _payload.size() * sizeof(uint8_t) + _mdata.size() * sizeof(uint64_t)
+ + ((_timestamp != boost::none && _chdr_w == uhd::rfnoc::CHDR_W_64) ? 2 : 1)
+ * chdr_w_bytes;
+}
+
+const std::vector<uint8_t>& chdr_util::chdr_packet::get_payload_bytes() const
+{
+ return _payload;
+}
+
+void chdr_util::chdr_packet::set_payload_bytes(std::vector<uint8_t> bytes)
+{
+ this->_payload = std::move(bytes);
+ set_header_lengths();
+}
+
+//! Return a string representation of this object
+const std::string chdr_util::chdr_packet::to_string() const
+{
+ return str(boost::format("chdr_packet{chdr_w:%u}\n%s")
+ % uhd::rfnoc::chdr_w_to_bits(_chdr_w) % _header.to_string());
+}