aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib
diff options
context:
space:
mode:
Diffstat (limited to 'host/lib')
-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
5 files changed, 59 insertions, 10 deletions
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);