aboutsummaryrefslogtreecommitdiffstats
path: root/host/include
diff options
context:
space:
mode:
authorrobot-rover <sam.obrien@ni.com>2020-06-11 16:34:07 -0500
committerAaron Rossetto <aaron.rossetto@ni.com>2020-07-13 15:21:52 -0500
commit22837edfe20feb57c24f2a55edbb65757b3fab6a (patch)
treea7aed19205f2851ab8e32e52093fbbe761ac9e86 /host/include
parentb0cb065111dc3f40b89bdda76e9bd98f3e70b72e (diff)
downloaduhd-22837edfe20feb57c24f2a55edbb65757b3fab6a.tar.gz
uhd-22837edfe20feb57c24f2a55edbb65757b3fab6a.tar.bz2
uhd-22837edfe20feb57c24f2a55edbb65757b3fab6a.zip
utils: Expose CHDR Types in Public API
This commit exposes uhdlib/rfnoc/chdr_types.hpp in the public includes. Additionally, it takes some types from uhdlib/rfnoc/rfnoc_common.hpp and exposes them publicly in uhd/rfnoc/rfnoc_types.hpp. Finally, one constant is moved from uhdlib/rfnoc/rfnoc_common.hpp to uhd/rfnoc/constants.hpp Signed-off-by: robot-rover <sam.obrien@ni.com>
Diffstat (limited to 'host/include')
-rw-r--r--host/include/uhd/rfnoc/CMakeLists.txt2
-rw-r--r--host/include/uhd/rfnoc/chdr_types.hpp877
-rw-r--r--host/include/uhd/rfnoc/constants.hpp2
-rw-r--r--host/include/uhd/rfnoc/rfnoc_types.hpp39
4 files changed, 920 insertions, 0 deletions
diff --git a/host/include/uhd/rfnoc/CMakeLists.txt b/host/include/uhd/rfnoc/CMakeLists.txt
index 33d324a4d..805a59a4f 100644
--- a/host/include/uhd/rfnoc/CMakeLists.txt
+++ b/host/include/uhd/rfnoc/CMakeLists.txt
@@ -12,6 +12,7 @@ UHD_INSTALL(FILES
block_id.hpp
blockdef.hpp
constants.hpp
+ chdr_types.hpp
defaults.hpp
dirtifier.hpp
filter_node.hpp
@@ -28,6 +29,7 @@ UHD_INSTALL(FILES
register_iface_holder.hpp
registry.hpp
res_source_info.hpp
+ rfnoc_types.hpp
traffic_counter.hpp
# Block controllers
addsub_block_control.hpp
diff --git a/host/include/uhd/rfnoc/chdr_types.hpp b/host/include/uhd/rfnoc/chdr_types.hpp
new file mode 100644
index 000000000..2f6c27c84
--- /dev/null
+++ b/host/include/uhd/rfnoc/chdr_types.hpp
@@ -0,0 +1,877 @@
+//
+// Copyright 2019 Ettus Research, a National Instruments Brand
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+//
+
+#pragma once
+
+#include <uhd/rfnoc/rfnoc_types.hpp>
+#include <uhd/types/endianness.hpp>
+#include <uhd/utils/byteswap.hpp>
+#include <boost/optional.hpp>
+#include <list>
+#include <memory>
+#include <vector>
+
+namespace uhd { namespace rfnoc { namespace chdr {
+
+enum packet_type_t {
+ PKT_TYPE_MGMT = 0x0, //! Management packet
+ PKT_TYPE_STRS = 0x1, //! Stream status
+ PKT_TYPE_STRC = 0x2, //! Stream Command
+ PKT_TYPE_CTRL = 0x4, //! Control Transaction
+ PKT_TYPE_DATA_NO_TS = 0x6, //! Data Packet without TimeStamp
+ PKT_TYPE_DATA_WITH_TS = 0x7, //! Data Packet with TimeStamp
+};
+
+//----------------------------------------------------
+// CHDR Header
+//----------------------------------------------------
+
+class chdr_header
+{
+public: // Functions
+ chdr_header() = default;
+ chdr_header(const chdr_header& rhs) = default;
+ chdr_header(chdr_header&& rhs) = default;
+
+ //! Unpack the header from a uint64_t
+ chdr_header(uint64_t flat_hdr) : _flat_hdr(flat_hdr) {}
+
+ //! Get the virtual channel field (6 bits)
+ inline uint8_t get_vc() const
+ {
+ return get_field<uint8_t>(_flat_hdr, VC_OFFSET, VC_WIDTH);
+ }
+
+ //! Set the virtual channel field (6 bits)
+ inline void set_vc(uint8_t vc)
+ {
+ _flat_hdr = set_field(_flat_hdr, vc, VC_OFFSET, VC_WIDTH);
+ }
+
+ //! Get the end-of-burst flag (1 bit)
+ inline bool get_eob() const
+ {
+ return get_field<bool>(_flat_hdr, EOB_OFFSET, EOB_WIDTH);
+ }
+
+ //! Set the end-of-burst flag (1 bit)
+ inline void set_eob(bool eob)
+ {
+ _flat_hdr = set_field(_flat_hdr, eob, EOB_OFFSET, EOB_WIDTH);
+ }
+
+ //! Get the end-of-vector flag (1 bit)
+ inline bool get_eov() const
+ {
+ return get_field<bool>(_flat_hdr, EOV_OFFSET, EOV_WIDTH);
+ }
+
+ //! Set the end-of-vector flag (1 bit)
+ inline void set_eov(bool eov)
+ {
+ _flat_hdr = set_field(_flat_hdr, eov, EOV_OFFSET, EOV_WIDTH);
+ }
+
+ //! Get the packet type field (3 bits)
+ inline packet_type_t get_pkt_type() const
+ {
+ return get_field<packet_type_t>(_flat_hdr, PKT_TYPE_OFFSET, PKT_TYPE_WIDTH);
+ }
+
+ //! Set the packet type field (3 bits)
+ inline void set_pkt_type(packet_type_t pkt_type)
+ {
+ _flat_hdr = set_field(_flat_hdr, pkt_type, PKT_TYPE_OFFSET, PKT_TYPE_WIDTH);
+ }
+
+ //! Get number of metadata words field (5 bits)
+ inline uint8_t get_num_mdata() const
+ {
+ return get_field<uint8_t>(_flat_hdr, NUM_MDATA_OFFSET, NUM_MDATA_WIDTH);
+ }
+
+ //! Set number of metadata words field (5 bits)
+ inline void set_num_mdata(uint8_t num_mdata)
+ {
+ _flat_hdr = set_field(_flat_hdr, num_mdata, NUM_MDATA_OFFSET, NUM_MDATA_WIDTH);
+ }
+
+ //! Get the sequence number field (16 bits)
+ inline uint16_t get_seq_num() const
+ {
+ return get_field<uint16_t>(_flat_hdr, SEQ_NUM_OFFSET, SEQ_NUM_WIDTH);
+ }
+
+ //! Set the sequence number field (16 bits)
+ inline void set_seq_num(uint16_t seq_num)
+ {
+ _flat_hdr = set_field(_flat_hdr, seq_num, SEQ_NUM_OFFSET, SEQ_NUM_WIDTH);
+ }
+
+ //! Get the packet length field (16 bits)
+ inline uint16_t get_length() const
+ {
+ return get_field<uint16_t>(_flat_hdr, LENGTH_OFFSET, LENGTH_WIDTH);
+ }
+
+ //! Set the packet length field (16 bits)
+ inline void set_length(uint16_t length)
+ {
+ _flat_hdr = set_field(_flat_hdr, length, LENGTH_OFFSET, LENGTH_WIDTH);
+ }
+
+ //! Get the destination EPID field (16 bits)
+ inline uint16_t get_dst_epid() const
+ {
+ return get_field<uint16_t>(_flat_hdr, DST_EPID_OFFSET, DST_EPID_WIDTH);
+ }
+
+ //! Set the destination EPID field (16 bits)
+ inline void set_dst_epid(uint16_t dst_epid)
+ {
+ _flat_hdr = set_field(_flat_hdr, dst_epid, DST_EPID_OFFSET, DST_EPID_WIDTH);
+ }
+
+ //! Pack the header into a uint64_t
+ inline uint64_t pack() const
+ {
+ return _flat_hdr;
+ }
+
+ //! Pack the header into a uint64_t as an implicit cast
+ inline operator uint64_t() const
+ {
+ return pack();
+ }
+
+ //! Comparison operator (==)
+ inline bool operator==(const chdr_header& rhs) const
+ {
+ return _flat_hdr == rhs._flat_hdr;
+ }
+
+ //! Comparison operator (!=)
+ inline bool operator!=(const chdr_header& rhs) const
+ {
+ return _flat_hdr != rhs._flat_hdr;
+ }
+
+ //! Assignment operator (=) from a chdr_header
+ inline const chdr_header& operator=(const chdr_header& rhs)
+ {
+ _flat_hdr = rhs._flat_hdr;
+ return *this;
+ }
+
+ //! Assignment operator (=) from a uint64_t
+ inline const chdr_header& operator=(const uint64_t& rhs)
+ {
+ _flat_hdr = rhs;
+ return *this;
+ }
+
+private:
+ // The flattened representation of the header stored in host order
+ uint64_t _flat_hdr = 0;
+
+ static constexpr size_t VC_WIDTH = 6;
+ static constexpr size_t EOB_WIDTH = 1;
+ static constexpr size_t EOV_WIDTH = 1;
+ static constexpr size_t PKT_TYPE_WIDTH = 3;
+ static constexpr size_t NUM_MDATA_WIDTH = 5;
+ static constexpr size_t SEQ_NUM_WIDTH = 16;
+ static constexpr size_t LENGTH_WIDTH = 16;
+ static constexpr size_t DST_EPID_WIDTH = 16;
+
+ static constexpr size_t VC_OFFSET = 58;
+ static constexpr size_t EOB_OFFSET = 57;
+ static constexpr size_t EOV_OFFSET = 56;
+ static constexpr size_t PKT_TYPE_OFFSET = 53;
+ static constexpr size_t NUM_MDATA_OFFSET = 48;
+ static constexpr size_t SEQ_NUM_OFFSET = 32;
+ static constexpr size_t LENGTH_OFFSET = 16;
+ static constexpr size_t DST_EPID_OFFSET = 0;
+
+ static inline uint64_t mask(const size_t width)
+ {
+ return ((uint64_t(1) << width) - 1);
+ }
+
+ template <typename field_t>
+ static inline field_t get_field(
+ const uint64_t flat_hdr, const size_t offset, const size_t width)
+ {
+ return static_cast<field_t>((flat_hdr >> offset) & mask(width));
+ }
+
+ template <typename field_t>
+ static inline uint64_t set_field(const uint64_t old_val,
+ const field_t field,
+ const size_t offset,
+ const size_t width)
+ {
+ return (old_val & ~(mask(width) << offset))
+ | ((static_cast<uint64_t>(field) & mask(width)) << offset);
+ }
+};
+
+
+//----------------------------------------------------
+// CHDR Control Packet Payload
+//----------------------------------------------------
+
+enum ctrl_status_t {
+ CMD_OKAY = 0x0, //! Transaction successful
+ CMD_CMDERR = 0x1, //! Slave asserted a command error
+ CMD_TSERR = 0x2, //! Slave asserted a time stamp error
+ CMD_WARNING = 0x3, //! Slave asserted non-critical error
+};
+
+enum ctrl_opcode_t {
+ OP_SLEEP = 0x0,
+ OP_WRITE = 0x1,
+ OP_READ = 0x2,
+ OP_READ_WRITE = 0x3,
+ OP_BLOCK_WRITE = 0x4,
+ OP_BLOCK_READ = 0x5,
+ OP_POLL = 0x6,
+ OP_USER1 = 0xA,
+ OP_USER2 = 0xB,
+ OP_USER3 = 0xC,
+ OP_USER4 = 0xD,
+ OP_USER5 = 0xE,
+ OP_USER6 = 0xF,
+};
+
+class ctrl_payload
+{
+public: // Members
+ //! Destination port for transaction (10 bits)
+ uint16_t dst_port = 0;
+ //! Source port for transaction (10 bits)
+ uint16_t src_port = 0;
+ //! Sequence number (6 bits)
+ uint8_t seq_num = 0;
+ //! Has Time Flag (1 bit) and timestamp (64 bits)
+ boost::optional<uint64_t> timestamp = boost::none;
+ //! Is Acknowledgment Flag (1 bit)
+ bool is_ack = false;
+ //! Source endpoint ID of transaction (16 bits)
+ uint16_t src_epid = 0;
+ //! Address for transaction (20 bits)
+ uint32_t address = 0;
+ //! Data for transaction (vector of 32 bits)
+ std::vector<uint32_t> data_vtr = {0};
+ //! Byte-enable mask for transaction (4 bits)
+ uint8_t byte_enable = 0xF;
+ //! Operation code (4 bits)
+ ctrl_opcode_t op_code = OP_SLEEP;
+ //! Transaction status (4 bits)
+ ctrl_status_t status = CMD_OKAY;
+
+public: // Functions
+ ctrl_payload() = default;
+ ctrl_payload(const ctrl_payload& rhs) = default;
+ ctrl_payload(ctrl_payload&& rhs) = default;
+
+ ctrl_payload& operator=(const ctrl_payload& rhs) = default;
+
+ //! Populate the header for this type of packet
+ void populate_header(chdr_header& header) const;
+
+ //! Serialize the payload to a uint64_t buffer
+ size_t serialize(uint64_t* buff,
+ size_t max_size_bytes,
+ const std::function<uint64_t(uint64_t)>& conv_byte_order) const;
+
+ //! Serialize the payload to a uint64_t buffer (no conversion function)
+ template <endianness_t endianness>
+ size_t serialize(uint64_t* buff, size_t max_size_bytes) const
+ {
+ auto conv_byte_order = [](uint64_t x) -> uint64_t {
+ return (endianness == uhd::ENDIANNESS_BIG) ? uhd::htonx<uint64_t>(x)
+ : uhd::htowx<uint64_t>(x);
+ };
+ return serialize(buff, max_size_bytes, conv_byte_order);
+ }
+
+ //! Deserialize the payload from a uint64_t buffer
+ void deserialize(const uint64_t* buff,
+ size_t num_elems,
+ const std::function<uint64_t(uint64_t)>& conv_byte_order);
+
+ //! Deserialize the payload from a uint64_t buffer (no conversion function)
+ template <endianness_t endianness>
+ void deserialize(const uint64_t* buff, size_t num_elems)
+ {
+ auto conv_byte_order = [](uint64_t x) -> uint64_t {
+ return (endianness == uhd::ENDIANNESS_BIG) ? uhd::ntohx<uint64_t>(x)
+ : uhd::wtohx<uint64_t>(x);
+ };
+ deserialize(buff, num_elems, conv_byte_order);
+ }
+
+ // Return whether or not we have a valid timestamp
+ bool has_timestamp() const
+ {
+ return bool(timestamp);
+ }
+
+ //! Comparison operator (==)
+ bool operator==(const ctrl_payload& rhs) const;
+
+ //! Comparison operator (!=)
+ inline bool operator!=(const ctrl_payload& rhs) const
+ {
+ return !(*this == rhs);
+ }
+
+ //! Return a string representation of this object
+ const std::string to_string() const;
+
+private:
+ static constexpr size_t DST_PORT_WIDTH = 10;
+ static constexpr size_t SRC_PORT_WIDTH = 10;
+ static constexpr size_t NUM_DATA_WIDTH = 4;
+ static constexpr size_t SEQ_NUM_WIDTH = 6;
+ static constexpr size_t HAS_TIME_WIDTH = 1;
+ static constexpr size_t IS_ACK_WIDTH = 1;
+ static constexpr size_t SRC_EPID_WIDTH = 16;
+ static constexpr size_t ADDRESS_WIDTH = 20;
+ static constexpr size_t BYTE_ENABLE_WIDTH = 4;
+ static constexpr size_t OPCODE_WIDTH = 4;
+ static constexpr size_t STATUS_WIDTH = 2;
+
+ // Offsets assume 64-bit alignment
+ static constexpr size_t DST_PORT_OFFSET = 0;
+ static constexpr size_t SRC_PORT_OFFSET = 10;
+ static constexpr size_t NUM_DATA_OFFSET = 20;
+ static constexpr size_t SEQ_NUM_OFFSET = 24;
+ static constexpr size_t HAS_TIME_OFFSET = 30;
+ static constexpr size_t IS_ACK_OFFSET = 31;
+ static constexpr size_t SRC_EPID_OFFSET = 32;
+ static constexpr size_t ADDRESS_OFFSET = 0;
+ static constexpr size_t BYTE_ENABLE_OFFSET = 20;
+ static constexpr size_t OPCODE_OFFSET = 24;
+ static constexpr size_t STATUS_OFFSET = 30;
+ static constexpr size_t LO_DATA_OFFSET = 0;
+ static constexpr size_t HI_DATA_OFFSET = 32;
+};
+
+//----------------------------------------------------
+// CHDR Stream Status Packet Payload
+//----------------------------------------------------
+
+enum strs_status_t {
+ STRS_OKAY = 0x0, //! No error
+ STRS_CMDERR = 0x1, //! A stream command signalled an error
+ STRS_SEQERR = 0x2, //! Packet out of sequence (sequence error)
+ STRS_DATAERR = 0x3, //! Data integrity check failed
+ STRS_RTERR = 0x4, //! Unexpected destination (routing error)
+};
+
+class strs_payload
+{
+public: // Members
+ //! The source EPID for the stream (16 bits)
+ uint16_t src_epid = 0;
+ //! The status of the stream (4 bits)
+ strs_status_t status = STRS_OKAY;
+ //! Buffer capacity in bytes (40 bits)
+ uint64_t capacity_bytes = 0;
+ //! Buffer capacity in packets (24 bits)
+ uint32_t capacity_pkts = 0;
+ //! Transfer count in bytes (64 bits)
+ uint64_t xfer_count_bytes = 0;
+ //! Transfer count in packets (40 bits)
+ uint64_t xfer_count_pkts = 0;
+ //! Buffer info (16 bits)
+ uint16_t buff_info = 0;
+ //! Extended status info (48 bits)
+ uint64_t status_info = 0;
+
+public: // Functions
+ strs_payload() = default;
+ strs_payload(const strs_payload& rhs) = default;
+ strs_payload(strs_payload&& rhs) = default;
+
+ strs_payload& operator=(const strs_payload& rhs) = default;
+
+ //! Populate the header for this type of packet
+ void populate_header(chdr_header& header) const;
+
+ //! Serialize the payload to a uint64_t buffer
+ size_t serialize(uint64_t* buff,
+ size_t max_size_bytes,
+ const std::function<uint64_t(uint64_t)>& conv_byte_order) const;
+
+ //! Serialize the payload to a uint64_t buffer (no conversion function)
+ template <endianness_t endianness>
+ size_t serialize(uint64_t* buff, size_t max_size_bytes) const
+ {
+ auto conv_byte_order = [](uint64_t x) -> uint64_t {
+ return (endianness == uhd::ENDIANNESS_BIG) ? uhd::htonx<uint64_t>(x)
+ : uhd::htowx<uint64_t>(x);
+ };
+ return serialize(buff, max_size_bytes, conv_byte_order);
+ }
+
+ //! Deserialize the payload from a uint64_t buffer
+ void deserialize(const uint64_t* buff,
+ size_t num_elems,
+ const std::function<uint64_t(uint64_t)>& conv_byte_order);
+
+ //! Deserialize the payload from a uint64_t buffer (no conversion function)
+ template <endianness_t endianness>
+ void deserialize(const uint64_t* buff, size_t num_elems)
+ {
+ auto conv_byte_order = [](uint64_t x) -> uint64_t {
+ return (endianness == uhd::ENDIANNESS_BIG) ? uhd::ntohx<uint64_t>(x)
+ : uhd::wtohx<uint64_t>(x);
+ };
+ deserialize(buff, num_elems, conv_byte_order);
+ }
+
+ //! Comparison operator (==)
+ bool operator==(const strs_payload& rhs) const;
+
+ //! Comparison operator (!=)
+ inline bool operator!=(const strs_payload& rhs) const
+ {
+ return !(*this == rhs);
+ }
+
+ //! Return a string representation of this object
+ const std::string to_string() const;
+
+private:
+ static constexpr size_t SRC_EPID_WIDTH = 16;
+ static constexpr size_t STATUS_WIDTH = 4;
+ static constexpr size_t CAPACITY_BYTES_WIDTH = 40;
+ static constexpr size_t CAPACITY_PKTS_WIDTH = 24;
+ static constexpr size_t XFER_COUNT_PKTS_WIDTH = 40;
+ static constexpr size_t BUFF_INFO_WIDTH = 16;
+ static constexpr size_t STATUS_INFO_WIDTH = 48;
+
+ // Offsets assume 64-bit alignment
+ static constexpr size_t SRC_EPID_OFFSET = 0;
+ static constexpr size_t STATUS_OFFSET = 16;
+ static constexpr size_t CAPACITY_BYTES_OFFSET = 24;
+ static constexpr size_t CAPACITY_PKTS_OFFSET = 0;
+ static constexpr size_t XFER_COUNT_PKTS_OFFSET = 24;
+ static constexpr size_t BUFF_INFO_OFFSET = 0;
+ static constexpr size_t STATUS_INFO_OFFSET = 16;
+};
+
+//----------------------------------------------------
+// CHDR Stream Command Packet Payload
+//----------------------------------------------------
+
+enum strc_op_code_t {
+ STRC_INIT = 0x0, //! Initialize stream
+ STRC_PING = 0x1, //! Trigger a stream status response
+ STRC_RESYNC = 0x2, //! Re-synchronize flow control
+};
+
+class strc_payload
+{
+public: // Members
+ //! The source EPID for the stream (16 bits)
+ uint16_t src_epid = 0;
+ //! Operation code for the command (4 bits)
+ strc_op_code_t op_code = STRC_INIT;
+ //! Data associated with the operation (4 bits)
+ uint8_t op_data = 0;
+ //! Number of packets to use for operation (40 bits)
+ uint64_t num_pkts = 0;
+ //! Number of bytes to use for operation (64 bits)
+ uint64_t num_bytes = 0;
+ //! Worst-case size of a strc packet (including header)
+ static constexpr size_t MAX_PACKET_SIZE = 128;
+
+public: // Functions
+ strc_payload() = default;
+ strc_payload(const strc_payload& rhs) = default;
+ strc_payload(strc_payload&& rhs) = default;
+
+ strc_payload& operator=(const strc_payload& rhs) = default;
+
+ //! Populate the header for this type of packet
+ void populate_header(chdr_header& header) const;
+
+ //! Serialize the payload to a uint64_t buffer
+ size_t serialize(uint64_t* buff,
+ size_t max_size_bytes,
+ const std::function<uint64_t(uint64_t)>& conv_byte_order) const;
+
+ //! Serialize the payload to a uint64_t buffer (no conversion function)
+ template <endianness_t endianness>
+ size_t serialize(uint64_t* buff, size_t max_size_bytes) const
+ {
+ auto conv_byte_order = [](uint64_t x) -> uint64_t {
+ return (endianness == uhd::ENDIANNESS_BIG) ? uhd::htonx<uint64_t>(x)
+ : uhd::htowx<uint64_t>(x);
+ };
+ return serialize(buff, max_size_bytes, conv_byte_order);
+ }
+
+ //! Deserialize the payload from a uint64_t buffer
+ void deserialize(const uint64_t* buff,
+ size_t num_elems,
+ const std::function<uint64_t(uint64_t)>& conv_byte_order);
+
+ //! Deserialize the payload from a uint64_t buffer (no conversion function)
+ template <endianness_t endianness>
+ void deserialize(const uint64_t* buff, size_t num_elems)
+ {
+ auto conv_byte_order = [](uint64_t x) -> uint64_t {
+ return (endianness == uhd::ENDIANNESS_BIG) ? uhd::ntohx<uint64_t>(x)
+ : uhd::wtohx<uint64_t>(x);
+ };
+ deserialize(buff, num_elems, conv_byte_order);
+ }
+
+ //! Comparison operator (==)
+ bool operator==(const strc_payload& rhs) const;
+
+ //! Comparison operator (!=)
+ inline bool operator!=(const strc_payload& rhs) const
+ {
+ return !(*this == rhs);
+ }
+
+ //! Return a string representation of this object
+ const std::string to_string() const;
+
+private:
+ static constexpr size_t SRC_EPID_WIDTH = 16;
+ static constexpr size_t OP_CODE_WIDTH = 4;
+ static constexpr size_t OP_DATA_WIDTH = 4;
+ static constexpr size_t NUM_PKTS_WIDTH = 40;
+
+ // Offsets assume 64-bit alignment
+ static constexpr size_t SRC_EPID_OFFSET = 0;
+ static constexpr size_t OP_CODE_OFFSET = 16;
+ static constexpr size_t OP_DATA_OFFSET = 20;
+ static constexpr size_t NUM_PKTS_OFFSET = 24;
+};
+
+//----------------------------------------------------
+// CHDR Management Packet Payload
+//----------------------------------------------------
+
+//! A class that represents a single management operation
+// An operation consists of an operation code and some
+// payload associated with that operation.
+class mgmt_op_t
+{
+public:
+ // Operation code
+ enum op_code_t {
+ //! Do nothing
+ MGMT_OP_NOP = 0,
+ //! Advertise this operation to the outside logic
+ MGMT_OP_ADVERTISE = 1,
+ //! Select the next destination for routing
+ MGMT_OP_SEL_DEST = 2,
+ //! Return the management packet back to its source
+ MGMT_OP_RETURN = 3,
+ //! Request information about the current node
+ MGMT_OP_INFO_REQ = 4,
+ //! A response to an information request
+ MGMT_OP_INFO_RESP = 5,
+ //! Perform a configuration write on the node
+ MGMT_OP_CFG_WR_REQ = 6,
+ //! Perform a configuration read on the node
+ MGMT_OP_CFG_RD_REQ = 7,
+ //! A response to a configuration read
+ MGMT_OP_CFG_RD_RESP = 8
+ };
+
+ //! The payload for an operation is 48 bits wide.
+ using payload_t = uint64_t;
+
+ //! An interpretation class for the payload for MGMT_OP_SEL_DEST
+ struct sel_dest_payload
+ {
+ const uint16_t dest;
+
+ sel_dest_payload(uint16_t dest_) : dest(dest_) {}
+ sel_dest_payload(payload_t payload_) : dest(static_cast<uint16_t>(payload_)) {}
+ operator payload_t() const
+ {
+ return static_cast<payload_t>(dest);
+ }
+ };
+
+ //! An interpretation class for the payload for MGMT_OP_CFG_WR_REQ,
+ //! MGMT_OP_CFG_RD_REQ and MGMT_OP_CFG_RD_RESP
+ struct cfg_payload
+ {
+ const uint16_t addr;
+ const uint32_t data;
+
+ cfg_payload(uint16_t addr_, uint32_t data_ = 0) : addr(addr_), data(data_) {}
+ cfg_payload(payload_t payload_)
+ : addr(static_cast<uint16_t>(payload_ >> 0))
+ , data(static_cast<uint32_t>(payload_ >> 16))
+ {
+ }
+ operator payload_t() const
+ {
+ return ((static_cast<payload_t>(data) << 16) | static_cast<payload_t>(addr));
+ }
+ };
+
+ //! An interpretation class for the payload for MGMT_OP_INFO_RESP
+ struct node_info_payload
+ {
+ const uint16_t device_id;
+ const uint8_t node_type;
+ const uint16_t node_inst;
+ const uint32_t ext_info;
+
+ node_info_payload(uint16_t device_id_,
+ uint8_t node_type_,
+ uint16_t node_inst_,
+ uint32_t ext_info_)
+ : device_id(device_id_)
+ , node_type(node_type_)
+ , node_inst(node_inst_)
+ , ext_info(ext_info_)
+ {
+ }
+ node_info_payload(payload_t payload_)
+ : device_id(static_cast<uint16_t>(payload_ >> 0))
+ , node_type(static_cast<uint8_t>((payload_ >> 16) & 0xF))
+ , node_inst(static_cast<uint16_t>((payload_ >> 20) & 0x3FF))
+ , ext_info(static_cast<uint32_t>((payload_ >> 30) & 0x3FFFF))
+ {
+ }
+ operator payload_t() const
+ {
+ return ((static_cast<payload_t>(device_id) << 0)
+ | (static_cast<payload_t>(node_type & 0xF) << 16)
+ | (static_cast<payload_t>(node_inst & 0x3FF) << 20)
+ | (static_cast<payload_t>(ext_info & 0x3FFFF) << 30));
+ }
+ };
+
+ mgmt_op_t(const op_code_t op_code, const payload_t op_payload = 0)
+ : _op_code(op_code), _op_payload(op_payload)
+ {
+ }
+ mgmt_op_t(const mgmt_op_t& rhs) = default;
+
+ //! Get the op-code for this transaction
+ inline op_code_t get_op_code() const
+ {
+ return _op_code;
+ }
+
+ //! Get the payload for this transaction
+ inline uint64_t get_op_payload() const
+ {
+ return _op_payload;
+ }
+
+ //! Comparison operator (==)
+ inline bool operator==(const mgmt_op_t& rhs) const
+ {
+ return (_op_code == rhs._op_code) && (_op_payload == rhs._op_payload);
+ }
+
+private:
+ op_code_t _op_code;
+ payload_t _op_payload;
+};
+
+//! A class that represents a single management hop
+// A hop is a collection for management transactions for
+// a single node.
+class mgmt_hop_t
+{
+public:
+ mgmt_hop_t() = default;
+ mgmt_hop_t(const mgmt_hop_t& rhs) = default;
+
+ //! Add a management operation to this hop.
+ // Operations are added to the hop in FIFO order and executed in FIFO order.
+ inline void add_op(const mgmt_op_t& op)
+ {
+ _ops.push_back(op);
+ }
+
+ //! Get the number of management operations in this hop
+ inline size_t get_num_ops() const
+ {
+ return _ops.size();
+ }
+
+ //! Get the n'th operation in the hop
+ inline const mgmt_op_t& get_op(size_t i) const
+ {
+ return _ops.at(i);
+ }
+
+ //! Serialize the payload to a uint64_t buffer
+ // The RFNoC Specification section 2.2.6 specifies that for chdr widths
+ // greater than 64, all MSBs are 0, so we pad out the hop based on the width
+ size_t serialize(std::vector<uint64_t>& target,
+ const std::function<uint64_t(uint64_t)>& conv_byte_order,
+ const size_t padding_size) const;
+
+ //! Deserialize the payload from a uint64_t buffer
+ // The RFNoC Specification section 2.2.6 specifies that for chdr widths
+ // greater than 64, all MSBs are 0, so we remove padding based on the width
+ void deserialize(std::list<uint64_t>& src,
+ const std::function<uint64_t(uint64_t)>& conv_byte_order,
+ const size_t padding_size);
+
+ //! Comparison operator (==)
+ inline bool operator==(const mgmt_hop_t& rhs) const
+ {
+ return _ops == rhs._ops;
+ }
+
+private:
+ std::vector<mgmt_op_t> _ops;
+};
+
+//! A class that represents a complete multi-hop management transaction
+// A transaction is a collection of hops, where each hop is a collection
+// of management transactions.
+class mgmt_payload
+{
+public:
+ mgmt_payload() = default;
+ mgmt_payload(const mgmt_payload& rhs) = default;
+ mgmt_payload(mgmt_payload&& rhs) = default;
+
+ mgmt_payload& operator=(const mgmt_payload& rhs) = default;
+
+ inline void set_header(sep_id_t src_epid, uint16_t protover, chdr_w_t chdr_w)
+ {
+ set_src_epid(src_epid);
+ set_chdr_w(chdr_w);
+ set_proto_ver(protover);
+ }
+
+ //! Add a management hop to this transaction
+ // Hops are added to the hop in FIFO order and executed in FIFO order.
+ inline void add_hop(const mgmt_hop_t& hop)
+ {
+ _hops.push_back(hop);
+ }
+
+ //! Get the number of management hops in this hop
+ inline size_t get_num_hops() const
+ {
+ return _hops.size();
+ }
+
+ //! Get the n'th hop in the transaction
+ inline const mgmt_hop_t& get_hop(size_t i) const
+ {
+ return _hops.at(i);
+ }
+
+ inline size_t get_size_bytes() const
+ {
+ size_t num_lines = 1; /* header */
+ for (const auto& hop : _hops) {
+ num_lines += hop.get_num_ops();
+ }
+ return num_lines * (chdr_w_to_bits(_chdr_w) / 8);
+ }
+
+ //! Populate the header for this type of packet
+ void populate_header(chdr_header& header) const;
+
+ //! Serialize the payload to a uint64_t buffer
+ size_t serialize(uint64_t* buff,
+ size_t max_size_bytes,
+ const std::function<uint64_t(uint64_t)>& conv_byte_order) const;
+
+ //! Serialize the payload to a uint64_t buffer (no conversion function)
+ template <endianness_t endianness>
+ size_t serialize(uint64_t* buff, size_t max_size_bytes) const
+ {
+ auto conv_byte_order = [](uint64_t x) -> uint64_t {
+ return (endianness == uhd::ENDIANNESS_BIG) ? uhd::htonx<uint64_t>(x)
+ : uhd::htowx<uint64_t>(x);
+ };
+ return serialize(buff, max_size_bytes, conv_byte_order);
+ }
+
+ //! Deserialize the payload from a uint64_t buffer
+ void deserialize(const uint64_t* buff,
+ size_t num_elems,
+ const std::function<uint64_t(uint64_t)>& conv_byte_order);
+
+ //! Deserialize the payload from a uint64_t buffer (no conversion function)
+ template <endianness_t endianness>
+ void deserialize(const uint64_t* buff, size_t num_elems)
+ {
+ auto conv_byte_order = [](uint64_t x) -> uint64_t {
+ return (endianness == uhd::ENDIANNESS_BIG) ? uhd::ntohx<uint64_t>(x)
+ : uhd::wtohx<uint64_t>(x);
+ };
+ deserialize(buff, num_elems, conv_byte_order);
+ }
+
+ //! Return a string representation of this object
+ const std::string to_string() const;
+
+ //! Return the source EPID for this transaction
+ inline sep_id_t get_src_epid() const
+ {
+ return _src_epid;
+ }
+
+ //! Set the source EPID for this transaction
+ inline void set_src_epid(sep_id_t src_epid)
+ {
+ _src_epid = src_epid;
+ }
+
+ //! Comparison operator (==)
+ bool operator==(const mgmt_payload& rhs) const;
+
+ //! Return the CHDR_W for this transaction
+ inline chdr_w_t get_chdr_w() const
+ {
+ return _chdr_w;
+ }
+
+ //! Set the CHDR_W for this transaction
+ inline void set_chdr_w(chdr_w_t chdr_w)
+ {
+ _chdr_w = chdr_w;
+ _padding_size = (chdr_w_to_bits(_chdr_w) / 64) - 1;
+ }
+
+ //! Return the protocol version for this transaction
+ inline uint16_t get_proto_ver() const
+ {
+ return _protover;
+ }
+
+ //! Set the protocol version for this transaction
+ inline void set_proto_ver(uint16_t proto_ver)
+ {
+ _protover = proto_ver;
+ }
+
+private:
+ sep_id_t _src_epid = 0;
+ uint16_t _protover = 0;
+ chdr_w_t _chdr_w = CHDR_W_64;
+ std::vector<mgmt_hop_t> _hops;
+ size_t _padding_size = 0;
+};
+
+}}} // namespace uhd::rfnoc::chdr
diff --git a/host/include/uhd/rfnoc/constants.hpp b/host/include/uhd/rfnoc/constants.hpp
index 5029206a0..c27911549 100644
--- a/host/include/uhd/rfnoc/constants.hpp
+++ b/host/include/uhd/rfnoc/constants.hpp
@@ -15,6 +15,8 @@
namespace uhd { namespace rfnoc {
+constexpr uint16_t RFNOC_PROTO_VER = 0x0100;
+
static const size_t NOC_SHELL_COMPAT_MAJOR = 5;
static const size_t NOC_SHELL_COMPAT_MINOR = 1;
diff --git a/host/include/uhd/rfnoc/rfnoc_types.hpp b/host/include/uhd/rfnoc/rfnoc_types.hpp
new file mode 100644
index 000000000..beb79324f
--- /dev/null
+++ b/host/include/uhd/rfnoc/rfnoc_types.hpp
@@ -0,0 +1,39 @@
+//
+// Copyright 2019 Ettus Research, a National Instruments Brand
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+//
+
+#pragma once
+
+#include <memory>
+
+namespace uhd { namespace rfnoc {
+
+//----------------------------------------------
+// Types
+//----------------------------------------------
+
+//! Type that indicates the CHDR Width in bits
+enum chdr_w_t { CHDR_W_64 = 0, CHDR_W_128 = 1, CHDR_W_256 = 2, CHDR_W_512 = 3 };
+//! Conversion from chdr_w_t to a number of bits
+constexpr size_t chdr_w_to_bits(chdr_w_t chdr_w)
+{
+ switch (chdr_w) {
+ case CHDR_W_64:
+ return 64;
+ case CHDR_W_128:
+ return 128;
+ case CHDR_W_256:
+ return 256;
+ case CHDR_W_512:
+ return 512;
+ default:
+ return 0;
+ }
+}
+
+//! Stream Endpoint ID Type
+using sep_id_t = uint16_t;
+
+}} // namespace uhd::rfnoc