aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib/usrp/mpmd/mpmd_mb_iface.cpp
diff options
context:
space:
mode:
authorMartin Braun <martin.braun@ettus.com>2019-07-03 20:15:35 -0700
committerMartin Braun <martin.braun@ettus.com>2019-11-26 12:16:25 -0800
commitc256b9df6502536c2e451e690f1ad5962c664d1a (patch)
treea83ad13e6f5978bbe14bb3ecf8294ba1e3d28db4 /host/lib/usrp/mpmd/mpmd_mb_iface.cpp
parent9a8435ed998fc5c65257f4c55768750b227ab19e (diff)
downloaduhd-c256b9df6502536c2e451e690f1ad5962c664d1a.tar.gz
uhd-c256b9df6502536c2e451e690f1ad5962c664d1a.tar.bz2
uhd-c256b9df6502536c2e451e690f1ad5962c664d1a.zip
x300/mpmd: Port all RFNoC devices to the new RFNoC framework
Co-Authored-By: Alex Williams <alex.williams@ni.com> Co-Authored-By: Sugandha Gupta <sugandha.gupta@ettus.com> Co-Authored-By: Brent Stapleton <brent.stapleton@ettus.com> Co-Authored-By: Ciro Nishiguchi <ciro.nishiguchi@ni.com>
Diffstat (limited to 'host/lib/usrp/mpmd/mpmd_mb_iface.cpp')
-rw-r--r--host/lib/usrp/mpmd/mpmd_mb_iface.cpp301
1 files changed, 301 insertions, 0 deletions
diff --git a/host/lib/usrp/mpmd/mpmd_mb_iface.cpp b/host/lib/usrp/mpmd/mpmd_mb_iface.cpp
new file mode 100644
index 000000000..e713cc7a3
--- /dev/null
+++ b/host/lib/usrp/mpmd/mpmd_mb_iface.cpp
@@ -0,0 +1,301 @@
+//
+// Copyright 2018 Ettus Research, a National Instruments Company
+// Copyright 2019 Ettus Research, a National Instruments Brand
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+//
+
+#include "mpmd_mb_iface.hpp"
+#include "mpmd_link_if_mgr.hpp"
+#include <uhd/exception.hpp>
+#include <uhd/utils/log.hpp>
+#include <uhdlib/rfnoc/device_id.hpp>
+
+using namespace uhd::rfnoc;
+using namespace uhd::mpmd;
+
+mpmd_mboard_impl::mpmd_mb_iface::mpmd_mb_iface(
+ const uhd::device_addr_t& mb_args, uhd::rpc_client::sptr rpc)
+ : _mb_args(mb_args), _rpc(rpc), _link_if_mgr(xport::mpmd_link_if_mgr::make(mb_args))
+{
+ _remote_device_id = allocate_device_id();
+ UHD_LOG_TRACE("MPMD::MB_IFACE", "Assigning device_id " << _remote_device_id);
+ _rpc->notify_with_token("set_device_id", _remote_device_id);
+}
+
+/******************************************************************************
+ * mpmd_mb_iface API
+ *****************************************************************************/
+void mpmd_mboard_impl::mpmd_mb_iface::init()
+{
+ UHD_LOG_TRACE("MPMD::MB_IFACE", "Requesting clock ifaces...");
+ auto clock_ifaces = _rpc->request_with_token<clock_iface_list_t>("get_clocks");
+ for (auto& clock : clock_ifaces) {
+ auto iface = std::make_shared<uhd::rfnoc::clock_iface>(
+ clock.at("name"), std::stod(clock.at("freq")), clock.count("mutable"));
+ _clock_ifaces[clock.at("name")] = iface;
+ iface->set_running(true);
+ UHD_LOG_DEBUG("MPMD::MB_IFACE",
+ "Adding clock iface `"
+ << clock.at("name") << "`, frequency: " << (iface->get_freq() / 1e6)
+ << " MHz, mutable: " << (iface->is_mutable() ? "Yes" : "No"));
+ }
+ UHD_LOG_TRACE("MPMD::MB_IFACE", "Requesting CHDR link types...");
+ auto chdr_link_types =
+ _rpc->request_with_token<std::vector<std::string>>("get_chdr_link_types");
+ UHD_LOG_TRACE(
+ "MPMD::MB_IFACE", "Found " << chdr_link_types.size() << " link type(s)");
+ for (const auto& type : chdr_link_types) {
+ UHD_LOG_TRACE("MPMD::MB_IFACE", "Trying link type `" << type << "'");
+ const auto xport_info =
+ _rpc->request_with_token<xport::mpmd_link_if_mgr::xport_info_list_t>(
+ "get_chdr_link_options", type);
+ // User may have specified: addr=192.168.10.2, second_addr=
+ // MPM may have said: "my addresses are 192.168.10.2 and 192.168.20.2"
+ if (_link_if_mgr->connect(type, xport_info)) {
+ UHD_LOG_TRACE("MPMD::MB_IFACE", "Link type " << type << " successful.");
+ }
+ }
+
+ if (_link_if_mgr->get_num_links() == 0) {
+ UHD_LOG_ERROR("MPMD::MB_IFACE", "No CHDR connection available!");
+ throw uhd::runtime_error("No CHDR connection available!");
+ }
+
+ for (size_t link_idx = 0; link_idx < _link_if_mgr->get_num_links(); link_idx++) {
+ _local_device_id_map.emplace(allocate_device_id(), link_idx);
+ }
+}
+
+/******************************************************************************
+ * mb_iface API
+ *****************************************************************************/
+uint16_t mpmd_mboard_impl::mpmd_mb_iface::get_proto_ver()
+{
+ return _rpc->request_with_token<uint16_t>("get_proto_ver");
+}
+
+uhd::rfnoc::chdr_w_t mpmd_mboard_impl::mpmd_mb_iface::get_chdr_w()
+{
+ const auto chdr_w_bits = _rpc->request_with_token<size_t>("get_chdr_width");
+ switch (chdr_w_bits) {
+ case 512:
+ return CHDR_W_512;
+ case 256:
+ return CHDR_W_256;
+ case 128:
+ return CHDR_W_128;
+ case 64:
+ return CHDR_W_64;
+ }
+ throw uhd::runtime_error(std::string("Device reporting invalid CHDR width: ")
+ + std::to_string(chdr_w_bits));
+}
+
+uhd::endianness_t mpmd_mboard_impl::mpmd_mb_iface::get_endianness(
+ const uhd::rfnoc::device_id_t local_device_id)
+{
+ uhd::rfnoc::device_id_t lookup_id = local_device_id;
+ if (lookup_id == NULL_DEVICE_ID) {
+ for (auto& ids : _local_device_id_map) {
+ lookup_id = ids.first;
+ break;
+ }
+ }
+ const size_t link_idx = _local_device_id_map.at(lookup_id);
+ auto& pkt_factory = _link_if_mgr->get_packet_factory(link_idx);
+ return pkt_factory.get_endianness();
+}
+
+uhd::rfnoc::device_id_t mpmd_mboard_impl::mpmd_mb_iface::get_remote_device_id()
+{
+ return _remote_device_id;
+}
+
+std::vector<device_id_t> mpmd_mboard_impl::mpmd_mb_iface::get_local_device_ids()
+{
+ std::vector<device_id_t> device_ids;
+ for (auto& local_dev_id_pair : _local_device_id_map) {
+ device_ids.push_back(local_dev_id_pair.first);
+ }
+ return device_ids;
+}
+
+uhd::transport::adapter_id_t mpmd_mboard_impl::mpmd_mb_iface::get_adapter_id(
+ const uhd::rfnoc::device_id_t local_device_id)
+{
+ return _adapter_map.at(local_device_id);
+}
+
+void mpmd_mboard_impl::mpmd_mb_iface::reset_network()
+{
+ // FIXME
+}
+
+uhd::rfnoc::clock_iface::sptr mpmd_mboard_impl::mpmd_mb_iface::get_clock_iface(
+ const std::string& clock_name)
+{
+ if (_clock_ifaces.count(clock_name)) {
+ return _clock_ifaces.at(clock_name);
+ } else {
+ UHD_LOG_ERROR("MPMD::MB_IFACE", "Invalid timebase clock name: " + clock_name);
+ throw uhd::key_error(
+ "[MPMD_MB::IFACE] Invalid timebase clock name: " + clock_name);
+ }
+}
+
+uhd::rfnoc::chdr_ctrl_xport::sptr mpmd_mboard_impl::mpmd_mb_iface::make_ctrl_transport(
+ uhd::rfnoc::device_id_t local_device_id, const uhd::rfnoc::sep_id_t& local_epid)
+{
+ if (!_local_device_id_map.count(local_device_id)) {
+ throw uhd::key_error(std::string("[MPMD::MB_IFACE] Cannot create control "
+ "transport: Unknown local device ID ")
+ + std::to_string(local_device_id));
+ }
+ const size_t link_idx = _local_device_id_map.at(local_device_id);
+ uhd::transport::io_service::sptr io_srv;
+ uhd::transport::send_link_if::sptr send_link;
+ uhd::transport::recv_link_if::sptr recv_link;
+ std::tie(io_srv, send_link, std::ignore, recv_link, std::ignore, std::ignore) =
+ _link_if_mgr->get_link(
+ link_idx, uhd::transport::link_type_t::CTRL, uhd::device_addr_t());
+
+ /* Associate local device ID with the adapter */
+ _adapter_map[local_device_id] = send_link->get_send_adapter_id();
+
+ auto pkt_factory = _link_if_mgr->get_packet_factory(link_idx);
+ auto xport = uhd::rfnoc::chdr_ctrl_xport::make(io_srv,
+ send_link,
+ recv_link,
+ pkt_factory,
+ local_epid,
+ send_link->get_num_send_frames(),
+ recv_link->get_num_recv_frames());
+ return xport;
+}
+
+uhd::rfnoc::chdr_rx_data_xport::uptr
+mpmd_mboard_impl::mpmd_mb_iface::make_rx_data_transport(
+ uhd::rfnoc::mgmt::mgmt_portal& mgmt_portal,
+ const uhd::rfnoc::sep_addr_pair_t& addrs,
+ const uhd::rfnoc::sep_id_pair_t& epids,
+ const uhd::rfnoc::sw_buff_t pyld_buff_fmt,
+ const uhd::rfnoc::sw_buff_t mdata_buff_fmt,
+ const uhd::device_addr_t& xport_args)
+{
+ const uhd::rfnoc::sep_addr_t local_sep_addr = addrs.second;
+
+ if (!_local_device_id_map.count(local_sep_addr.first)) {
+ throw uhd::key_error(std::string("[MPMD::MB_IFACE] Cannot create RX data "
+ "transport: Unknown local device ID ")
+ + std::to_string(local_sep_addr.first));
+ }
+ const size_t link_idx = _local_device_id_map.at(local_sep_addr.first);
+
+ uhd::transport::io_service::sptr io_srv;
+ uhd::transport::send_link_if::sptr send_link;
+ uhd::transport::recv_link_if::sptr recv_link;
+ bool lossy_xport;
+ size_t recv_buff_size;
+ std::tie(io_srv, send_link, std::ignore, recv_link, recv_buff_size, lossy_xport) =
+ _link_if_mgr->get_link(
+ link_idx, uhd::transport::link_type_t::RX_DATA, xport_args);
+
+ /* Associate local device ID with the adapter */
+ _adapter_map[local_sep_addr.first] = send_link->get_send_adapter_id();
+
+ // TODO: configure this based on the transport type
+ const stream_buff_params_t recv_capacity = {
+ recv_buff_size, uhd::rfnoc::MAX_FC_CAPACITY_PKTS};
+
+ const double ratio = 1.0 / 32;
+
+ // Configure flow control frequency to use bytes only for UDP
+ stream_buff_params_t fc_freq = {
+ static_cast<uint64_t>(std::ceil(double(recv_buff_size) * ratio)),
+ uhd::rfnoc::MAX_FC_FREQ_PKTS};
+
+ stream_buff_params_t fc_headroom = {0, 0};
+
+ // Create the data transport
+ auto pkt_factory = _link_if_mgr->get_packet_factory(link_idx);
+ auto fc_params = chdr_rx_data_xport::configure_sep(io_srv,
+ recv_link,
+ send_link,
+ pkt_factory,
+ mgmt_portal,
+ epids,
+ pyld_buff_fmt,
+ mdata_buff_fmt,
+ recv_capacity,
+ fc_freq,
+ fc_headroom,
+ lossy_xport);
+ auto rx_xport = std::make_unique<chdr_rx_data_xport>(io_srv,
+ recv_link,
+ send_link,
+ pkt_factory,
+ epids,
+ recv_link->get_num_recv_frames(),
+ fc_params);
+
+ return rx_xport;
+}
+
+uhd::rfnoc::chdr_tx_data_xport::uptr
+mpmd_mboard_impl::mpmd_mb_iface::make_tx_data_transport(
+ uhd::rfnoc::mgmt::mgmt_portal& mgmt_portal,
+ const uhd::rfnoc::sep_addr_pair_t& addrs,
+ const uhd::rfnoc::sep_id_pair_t& epids,
+ const uhd::rfnoc::sw_buff_t pyld_buff_fmt,
+ const uhd::rfnoc::sw_buff_t mdata_buff_fmt,
+ const uhd::device_addr_t& xport_args)
+{
+ const uhd::rfnoc::sep_addr_t local_sep_addr = addrs.first;
+
+ if (!_local_device_id_map.count(local_sep_addr.first)) {
+ throw uhd::key_error(std::string("[MPMD::MB_IFACE] Cannot create TX data "
+ "transport: Unknown local device ID ")
+ + std::to_string(local_sep_addr.first));
+ }
+ const size_t link_idx = _local_device_id_map.at(local_sep_addr.first);
+
+ uhd::transport::io_service::sptr io_srv;
+ uhd::transport::send_link_if::sptr send_link;
+ uhd::transport::recv_link_if::sptr recv_link;
+ bool lossy_xport;
+ std::tie(io_srv, send_link, std::ignore, recv_link, std::ignore, lossy_xport) =
+ _link_if_mgr->get_link(
+ link_idx, uhd::transport::link_type_t::TX_DATA, xport_args);
+
+ /* Associate local device ID with the adapter */
+ _adapter_map[local_sep_addr.first] = send_link->get_send_adapter_id();
+
+ // TODO: configure this based on the transport type
+ const double fc_freq_ratio = 1.0 / 8;
+ const double fc_headroom_ratio = 0;
+
+ auto pkt_factory = _link_if_mgr->get_packet_factory(link_idx);
+ const auto buff_capacity = chdr_tx_data_xport::configure_sep(io_srv,
+ recv_link,
+ send_link,
+ pkt_factory,
+ mgmt_portal,
+ epids,
+ pyld_buff_fmt,
+ mdata_buff_fmt,
+ fc_freq_ratio,
+ fc_headroom_ratio);
+
+ // Create the data transport
+ auto tx_xport = std::make_unique<chdr_tx_data_xport>(io_srv,
+ recv_link,
+ send_link,
+ pkt_factory,
+ epids,
+ send_link->get_num_send_frames(),
+ buff_capacity);
+
+
+ return tx_xport;
+}