aboutsummaryrefslogtreecommitdiffstats
path: root/host
diff options
context:
space:
mode:
Diffstat (limited to 'host')
-rw-r--r--host/include/uhd/rfnoc/chdr_types.hpp3
-rw-r--r--host/include/uhd/rfnoc/rfnoc_types.hpp12
-rw-r--r--host/include/uhd/transport/adapter_id.hpp3
-rw-r--r--host/lib/include/uhdlib/rfnoc/link_stream_manager.hpp13
-rw-r--r--host/lib/include/uhdlib/rfnoc/mgmt_portal.hpp3
-rw-r--r--host/lib/include/uhdlib/rfnoc/rfnoc_common.hpp19
-rw-r--r--host/lib/rfnoc/graph_stream_manager.cpp11
-rw-r--r--host/lib/rfnoc/mgmt_portal.cpp23
8 files changed, 74 insertions, 13 deletions
diff --git a/host/include/uhd/rfnoc/chdr_types.hpp b/host/include/uhd/rfnoc/chdr_types.hpp
index e6c5e3912..f4acee28b 100644
--- a/host/include/uhd/rfnoc/chdr_types.hpp
+++ b/host/include/uhd/rfnoc/chdr_types.hpp
@@ -610,6 +610,9 @@ class UHD_API mgmt_op_t
{
public:
// Operation code
+ // Note that a management packet has 8 bits available for op codes. The
+ // values for these enums are used to construct the packets, so these values
+ // must match the values in rfnoc_chdr_internal_utils.vh.
enum op_code_t {
//! Do nothing
MGMT_OP_NOP = 0,
diff --git a/host/include/uhd/rfnoc/rfnoc_types.hpp b/host/include/uhd/rfnoc/rfnoc_types.hpp
index 123bf82f1..ebf8a08ad 100644
--- a/host/include/uhd/rfnoc/rfnoc_types.hpp
+++ b/host/include/uhd/rfnoc/rfnoc_types.hpp
@@ -11,9 +11,9 @@
namespace uhd { namespace rfnoc {
-//----------------------------------------------
-// Types
-//----------------------------------------------
+//-----------------------------------------------------------------------------
+// Types (note: internal types are defined in rfnoc_common.hpp)
+//-----------------------------------------------------------------------------
//! 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 };
@@ -50,6 +50,12 @@ constexpr size_t chdr_w_to_bits(chdr_w_t chdr_w)
}
//! Stream Endpoint ID Type
+// Stream endpoints within a graph are unique. They are assigned dynamically
+// during runtime when needed. Stream endpoints exist both in the host as well
+// as in the devices. See also sep_addr_t. The value of any sep_id_t is
+// meaningless, it provides no information on where the SEP is physically
+// located. In comments and variables, it is often abbreviated as "EPID"
+// ("endpoint ID").
using sep_id_t = uint16_t;
}} // namespace uhd::rfnoc
diff --git a/host/include/uhd/transport/adapter_id.hpp b/host/include/uhd/transport/adapter_id.hpp
index 8f8c40aa1..5859147e3 100644
--- a/host/include/uhd/transport/adapter_id.hpp
+++ b/host/include/uhd/transport/adapter_id.hpp
@@ -11,6 +11,9 @@
namespace uhd { namespace transport {
//! Host transport adapter ID
+// The adapter ID is a unique identifier for the physical connection. For example,
+// if the UHD session is using two separate Ethernet cables, each plugged into
+// its own Ethernet port, then there would be two adapter IDs available (0 and 1).
using adapter_id_t = size_t;
//! NULL/unassigned host transport adapter ID
static const adapter_id_t NULL_ADAPTER_ID = 0;
diff --git a/host/lib/include/uhdlib/rfnoc/link_stream_manager.hpp b/host/lib/include/uhdlib/rfnoc/link_stream_manager.hpp
index 4357a2d58..d4e2aba46 100644
--- a/host/lib/include/uhdlib/rfnoc/link_stream_manager.hpp
+++ b/host/lib/include/uhdlib/rfnoc/link_stream_manager.hpp
@@ -40,12 +40,25 @@ public:
/*! \brief Get the software device ID associated with this instance
*
+ * For every link to a device, we create a unique device ID. For example,
+ * if there are two USRPs in the graph, each connected with a single
+ * Ethernet connection, there would be two link managers, and therefore also
+ * two device IDs on the host side.
+ * If we access a single USRP using two Ethernet connections, then we still
+ * have two link stream managers, each with its own unique device ID on the
+ * host side.
+ * The device IDs are allocated in the mb_iface associated with this device
+ * during discovery.
+ *
* \return The software device ID associated with this instance
*/
virtual device_id_t get_self_device_id() const = 0;
/*! \brief Get the transport adapter ID associated with this instance
*
+ * See also uhd::transport::adapter_id_t. For example, when using two
+ * separate Ethernet ports, there would be two adapter IDs.
+ *
* \return The adapter ID associated with this instance
*/
virtual uhd::transport::adapter_id_t get_adapter_id() const = 0;
diff --git a/host/lib/include/uhdlib/rfnoc/mgmt_portal.hpp b/host/lib/include/uhdlib/rfnoc/mgmt_portal.hpp
index 069ad9604..dcb93772b 100644
--- a/host/lib/include/uhdlib/rfnoc/mgmt_portal.hpp
+++ b/host/lib/include/uhdlib/rfnoc/mgmt_portal.hpp
@@ -19,7 +19,8 @@ namespace uhd { namespace rfnoc { namespace mgmt {
//! A portal to perform low-level management operations from an endpoint
//
// This object provides an interface to send management commands from a software stream
-// endpoint. There must one instance of this object per software stream endpoint.
+// endpoint. There must one instance of this object per software stream endpoint
+// (i.e., every link_stream_manager owns one of these).
// The management portal is capable of discovering all endpoints reachable from the
// transport associated with it. It can then setup routes and configure stream endpoints
// downstream.
diff --git a/host/lib/include/uhdlib/rfnoc/rfnoc_common.hpp b/host/lib/include/uhdlib/rfnoc/rfnoc_common.hpp
index 7b2900832..72b06fa46 100644
--- a/host/lib/include/uhdlib/rfnoc/rfnoc_common.hpp
+++ b/host/lib/include/uhdlib/rfnoc/rfnoc_common.hpp
@@ -9,18 +9,31 @@
#include <uhd/rfnoc/defaults.hpp>
#include <uhd/rfnoc/rfnoc_types.hpp>
#include <memory>
+#include <utility>
namespace uhd { namespace rfnoc {
-//----------------------------------------------
-// Types
-//----------------------------------------------
+//-----------------------------------------------------------------------------
+// Types that are private to UHD
+// (there are more in rfnoc_types.hpp that are public)
+//-----------------------------------------------------------------------------
//! Device ID Type
+// Every USRP in the RFNoC graph will have *one* device_id. It is programmed
+// into the device during initialization through a non-RFNoC mechanism (e.g.,
+// via MPM or the ZPU).
using device_id_t = uint16_t;
//! Stream Endpoint Instance Number Type
+// These instance numbers are unique within a device (they are simply counted
+// up), but are not unique in a graph (every USRP will have its own set of SEPs).
using sep_inst_t = uint16_t;
//! Stream Endpoint Physical Address Type
+// This combination of device ID and SEP instance is unique in a graph. Note
+// that for the most part, we map an sep_addr_t to a sep_id_t. This limits us to
+// 2**16 combinations of device IDs and SEP instances, but that is more than
+// enough for all practical applications. We use sep_id_t when we need a compact
+// 16-bit address (e.g., in a CHDR header). We use a sep_addr_t when we need to
+// know which device this endpoint belongs to.
using sep_addr_t = std::pair<device_id_t, sep_inst_t>;
//! Stream Endpoint Physical Address Type (first = source, second = destination)
using sep_addr_pair_t = std::pair<sep_addr_t, sep_addr_t>;
diff --git a/host/lib/rfnoc/graph_stream_manager.cpp b/host/lib/rfnoc/graph_stream_manager.cpp
index fdf294006..fbabae36a 100644
--- a/host/lib/rfnoc/graph_stream_manager.cpp
+++ b/host/lib/rfnoc/graph_stream_manager.cpp
@@ -239,6 +239,17 @@ public:
}
private:
+ //! Return the local device ID over which we can reach a destination
+ //
+ // \param dst_addr The destination address (device/instance pair) for which
+ // we are finding a local device ID
+ // \param adapter If provided (i.e., if not NULL_ADAPTER_ID) then only this
+ // adapter index is used to find local device IDs. If it is
+ // not given (i.e. if equal to NULL_ADAPTER_ID), then this
+ // function will use heuristics to choose an adapter.
+ // \param link_type The type of link for which we're finding a local device
+ // ID. When \p adapter is NULL_ADAPTER_ID, then we use this
+ // in our heuristics for choosing an adapter.
device_id_t _check_dst_and_find_src(sep_addr_t dst_addr,
uhd::transport::adapter_id_t adapter,
uhd::transport::link_type_t link_type) const
diff --git a/host/lib/rfnoc/mgmt_portal.cpp b/host/lib/rfnoc/mgmt_portal.cpp
index 0a0a696a5..56160ae82 100644
--- a/host/lib/rfnoc/mgmt_portal.cpp
+++ b/host/lib/rfnoc/mgmt_portal.cpp
@@ -95,6 +95,10 @@ struct node_id_t
//! The instance number of this node in the device
sep_inst_t inst = 0;
//! Extended info about node (not used for comparisons)
+ // The value depends on the node type. For example, this includes number of
+ // ports on a crossbar, data/ctrl capability for SEPs, or transport subtype
+ // for transport adapters.
+ // It contains up to 18 bits of information.
uint32_t extended_info = 0;
// ctors and operators
@@ -178,7 +182,7 @@ std::string to_string(const node_addr_t& node_addr)
mgmt_portal::~mgmt_portal() {}
//---------------------------------------------------------------
-// Stream Manager Implementation
+// Management Portal Implementation
//---------------------------------------------------------------
class mgmt_portal_impl : public mgmt_portal
{
@@ -307,9 +311,13 @@ public:
std::lock_guard<std::recursive_mutex> lock(_mutex);
auto my_epid = xport.get_epid();
- // Lookup the physical stream endpoint address using the endpoint ID
+ // Look up the physical stream endpoint address using the endpoint ID
+ // node_addr contains the route to the host SEP to the destination SEP
const node_addr_t& node_addr = _lookup_sep_node_addr(dst_epid);
+ // Initialize all nodes between host and destination SEP. This will
+ // program all nodes to do the reverse routing (how to send packets to
+ // my_epid, i.e. back to the host).
node_addr_t route_addr = node_addr_t();
route_addr.push_back(std::make_pair(_my_node_id, next_dest_t(-1)));
for (const auto& addr_pair : node_addr) {
@@ -354,7 +362,7 @@ public:
}
} break;
case node_type::NODE_TYPE_STRM_EP: {
- // Stream are not involved in routing, so do nothing
+ // Stream endpoints are not involved in routing, so do nothing
} break;
default: {
UHD_THROW_INVALID_CODE_PATH();
@@ -367,8 +375,8 @@ public:
}
// If we follow this route then we should end up at a stream endpoint
- // so add an extra hop and return the packet back with the node info we will
- // sanity check it later
+ // so add an extra hop and return the packet back with the node info.
+ // We will sanity check it later
mgmt_hop_t discover_hop;
discover_hop.add_op(mgmt_op_t(mgmt_op_t::MGMT_OP_INFO_REQ));
discover_hop.add_op(mgmt_op_t(mgmt_op_t::MGMT_OP_RETURN));
@@ -410,6 +418,9 @@ public:
const node_addr_t& src_node_addr = _node_addr_map.at(node_id_t(src_addr));
// Find a common parent (could be faster than n^2 but meh, this is easier)
+ // Note: This is *not* finding the fastest path from dst_addr to src_addr.
+ // This using the existing routes we have, and finding a route through
+ // a common parent that also needs to be a crossbar.
for (const auto& dnode : dst_node_addr) {
for (const auto& snode : src_node_addr) {
if (dnode.first == snode.first
@@ -822,7 +833,7 @@ private: // Functions
const node_id_t& curr_node = addr_pair.first;
const next_dest_t& curr_dest = addr_pair.second;
if (curr_node.type != node_type::NODE_TYPE_STRM_EP) {
- // If a node is a crossbar, then it have have a non-negative destination
+ // If a node is a crossbar, then it must have a non-negative destination
UHD_ASSERT_THROW(
(curr_node.type != node_type::NODE_TYPE_XBAR || curr_dest >= 0));
_push_advance_hop(transaction, curr_dest);