diff options
Diffstat (limited to 'host/lib')
-rw-r--r-- | host/lib/include/uhdlib/rfnoc/link_stream_manager.hpp | 13 | ||||
-rw-r--r-- | host/lib/include/uhdlib/rfnoc/mgmt_portal.hpp | 3 | ||||
-rw-r--r-- | host/lib/include/uhdlib/rfnoc/rfnoc_common.hpp | 19 | ||||
-rw-r--r-- | host/lib/rfnoc/graph_stream_manager.cpp | 11 | ||||
-rw-r--r-- | host/lib/rfnoc/mgmt_portal.cpp | 23 |
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); |