diff options
author | robot-rover <sam.obrien@ni.com> | 2020-06-11 16:34:07 -0500 |
---|---|---|
committer | Aaron Rossetto <aaron.rossetto@ni.com> | 2020-07-13 15:21:52 -0500 |
commit | 22837edfe20feb57c24f2a55edbb65757b3fab6a (patch) | |
tree | a7aed19205f2851ab8e32e52093fbbe761ac9e86 /host/include | |
parent | b0cb065111dc3f40b89bdda76e9bd98f3e70b72e (diff) | |
download | uhd-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.txt | 2 | ||||
-rw-r--r-- | host/include/uhd/rfnoc/chdr_types.hpp | 877 | ||||
-rw-r--r-- | host/include/uhd/rfnoc/constants.hpp | 2 | ||||
-rw-r--r-- | host/include/uhd/rfnoc/rfnoc_types.hpp | 39 |
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 |