diff options
author | Martin Braun <martin.braun@ettus.com> | 2017-06-01 00:04:24 -0700 |
---|---|---|
committer | Martin Braun <martin.braun@ettus.com> | 2017-12-22 15:03:58 -0800 |
commit | cd03692e92c0f44fbd45875a8782dd6febee0f68 (patch) | |
tree | 713a158a05f9fc5f461ee49ac1e8e68956ff4024 /host/lib/usrp | |
parent | 3c50e39d644767ea3f668bbf2146ea4c636ce8e2 (diff) | |
download | uhd-cd03692e92c0f44fbd45875a8782dd6febee0f68.tar.gz uhd-cd03692e92c0f44fbd45875a8782dd6febee0f68.tar.bz2 uhd-cd03692e92c0f44fbd45875a8782dd6febee0f68.zip |
mpmd: Refactored code to allow multi-device initialization
Diffstat (limited to 'host/lib/usrp')
-rw-r--r-- | host/lib/usrp/mpmd/CMakeLists.txt | 5 | ||||
-rw-r--r-- | host/lib/usrp/mpmd/mpmd_impl.cpp | 226 | ||||
-rw-r--r-- | host/lib/usrp/mpmd/mpmd_impl.hpp | 53 | ||||
-rw-r--r-- | host/lib/usrp/mpmd/mpmd_mboard_impl.cpp | 111 |
4 files changed, 247 insertions, 148 deletions
diff --git a/host/lib/usrp/mpmd/CMakeLists.txt b/host/lib/usrp/mpmd/CMakeLists.txt index 5ff1f36eb..a5f2fb184 100644 --- a/host/lib/usrp/mpmd/CMakeLists.txt +++ b/host/lib/usrp/mpmd/CMakeLists.txt @@ -15,12 +15,9 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. # -######################################################################## -# This file included, use CMake directory variables -######################################################################## - IF(ENABLE_MPMD) LIBUHD_APPEND_SOURCES( ${CMAKE_CURRENT_SOURCE_DIR}/mpmd_impl.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/mpmd_mboard_impl.cpp ) ENDIF(ENABLE_MPMD) diff --git a/host/lib/usrp/mpmd/mpmd_impl.cpp b/host/lib/usrp/mpmd/mpmd_impl.cpp index 2464a71cd..353258aeb 100644 --- a/host/lib/usrp/mpmd/mpmd_impl.cpp +++ b/host/lib/usrp/mpmd/mpmd_impl.cpp @@ -36,99 +36,97 @@ using namespace uhd; -mpmd_mboard_impl::mpmd_mboard_impl(const std::string& addr) - : rpc(uhd::rpc_client::make(addr, MPM_RPC_PORT)) +/***************************************************************************** + * Structors + ****************************************************************************/ +mpmd_impl::mpmd_impl(const device_addr_t& device_args) + : usrp::device3_impl() + , _device_addr(device_args) + , _sid_framer(0) { - UHD_LOG_TRACE("MPMD", "Initializing mboard, IP address: " << addr); - std::map<std::string, std::string> _dev_info = - rpc->call<dev_info>("get_device_info"); - device_info = - dict<std::string, std::string>(_dev_info.begin(), _dev_info.end()); - // Get initial claim on mboard - _rpc_token = rpc->call<std::string>("claim", "UHD - Session 01"); // TODO make this configurable with device_addr, and provide better defaults - if (_rpc_token.empty()){ - throw uhd::value_error("mpmd device claiming failed!"); + UHD_LOGGER_INFO("MPMD") + << "MPMD initialization sequence. Device args: " + << device_args.to_string(); + + for (const std::string& key : device_args.keys()) { + if (key.find("recv") != std::string::npos) { + recv_args[key] = device_args[key]; + } + if (key.find("send") != std::string::npos) { + send_args[key] = device_args[key]; + } + } + + const device_addrs_t mb_args = separate_device_addr(device_args); + _mb.reserve(mb_args.size()); + for (size_t mb_i = 0; mb_i < mb_args.size(); ++mb_i) { + _mb.push_back(setup_mb(mb_i, mb_args[mb_i])); + setup_rfnoc_blocks(mb_i, mb_args[mb_i]); } - rpc->set_token(_rpc_token); - _claimer_task = task::make([this] { - if (not this->claim()) { - throw uhd::value_error("mpmd device reclaiming loop failed!"); - }; - boost::this_thread::sleep_for(boost::chrono::milliseconds(1000)); - }); - // std::vector<std::string> data_ifaces = - // rpc.call<std::vector<std::string>>("get_interfaces", _rpc_token); - - // discover path to device and tell MPM our MAC address seen at the data - // interfaces - // move this into make_transport - //for (const auto& iface : data_ifaces) { - //std::vector<std::string> addrs = rpc.call<std::vector<std::string>>( - //"get_interface_addrs", _rpc_token, iface); - //for (const auto& iface_addr : addrs) { - //if (rpc_client(iface_addr, MPM_RPC_PORT) - //.call<bool>("probe_interface", _rpc_token)) { - //data_interfaces.emplace(iface, iface_addr); - //break; - //} - //} - //} + + // TODO read this from the device info + _tree->create<std::string>("/name").set("MPMD - Series device"); + + auto filtered_block_args = device_args; // TODO actually filter + setup_rpc_blocks(filtered_block_args); } -uhd::sid_t mpmd_mboard_impl::allocate_sid(const uint16_t port, - const uhd::sid_t address, - const uint32_t xbar_src_addr, - const uint32_t xbar_src_port) -{ - const uint32_t sid = rpc->call_with_token<uint32_t>( - "allocate_sid", - port, address.get(), xbar_src_addr, xbar_src_port +mpmd_impl::~mpmd_impl() {} + +/***************************************************************************** + * Private methods + ****************************************************************************/ +mpmd_mboard_impl::uptr mpmd_impl::setup_mb( + const size_t mb_index, + const uhd::device_addr_t& device_args +) { + UHD_LOG_DEBUG("MPMD", + "Initializing mboard " << mb_index << ". Device args: " + << device_args.to_string() ); - return sid; -} -mpmd_mboard_impl::~mpmd_mboard_impl() {} + const fs_path mb_path = fs_path("/mboards") / mb_index; + auto mb = mpmd_mboard_impl::make(device_args["addr"]); + _tree->create<std::string>(mb_path / "name") + .set(mb->device_info.get("type", "UNKNOWN")); + _tree->create<std::string>(mb_path / "serial") + .set(mb->device_info.get("serial", "n/a")); + _tree->create<std::string>(mb_path / "connection") + .set(mb->device_info.get("connection", "remote")); -mpmd_mboard_impl::uptr mpmd_mboard_impl::make(const std::string& addr) -{ - mpmd_mboard_impl::uptr mb = - mpmd_mboard_impl::uptr(new mpmd_mboard_impl(addr)); - // implicit move - return mb; -} + // Do real MTU discovery (something similar like X300 but with MPM) -bool mpmd_mboard_impl::claim() -{ - return rpc->call_with_token<bool>("reclaim"); -} + _tree->create<size_t>(mb_path / "mtu/recv").set(1500); + _tree->create<size_t>(mb_path / "mtu/send").set(1500); + _tree->create<size_t>(mb_path / "link_max_rate").set(1e9 / 8); -mpmd_impl::mpmd_impl(const device_addr_t& device_addr) - : usrp::device3_impl() - , _device_addr(device_addr) - , _sid_framer(0) -{ - UHD_LOGGER_INFO("MPMD") - << "MPMD initialization sequence. Device args: " - << device_addr.to_string(); - const device_addrs_t device_args = separate_device_addr(device_addr); - _mb.reserve(device_args.size()); - for (size_t mb_i = 0; mb_i < device_args.size(); ++mb_i) { - _mb.push_back(setup_mb(mb_i, device_args[mb_i])); - } + // query more information about FPGA/MPM + // Call init on periph_manager, this will init the dboards/mboard, maybe + // even selfcal and everything - // TODO read this from the device info - _tree->create<std::string>("/name").set("MPMD - Series device"); + // Query time/clock sources on mboards/dboards + // Throw rpc calls with boost bind into the property tree? + + + // implicit move + return mb; +} - const size_t mb_index = 0; - const size_t num_xbars = _mb[mb_index]->rpc->call<size_t>("get_num_xbars"); - UHD_ASSERT_THROW(num_xbars >= 1); - if (num_xbars > 1) { +void mpmd_impl::setup_rfnoc_blocks( + const size_t mb_index, + const uhd::device_addr_t& ctrl_xport_args +) { + auto mb = _mb[mb_index].get(); + mb->num_xbars = mb->rpc->call<size_t>("get_num_xbars"); + UHD_ASSERT_THROW(mb->num_xbars >= 1); + if (mb->num_xbars > 1) { UHD_LOG_WARNING("MPMD", "Only using first crossbar"); } + // TODO loop over all xbars const size_t xbar_index = 0; - const size_t num_blocks = _mb[mb_index]->rpc->call<size_t>("get_num_blocks", xbar_index); - const size_t base_port = _mb[mb_index]->rpc->call<size_t>("get_base_port", xbar_index); + const size_t num_blocks = mb->rpc->call<size_t>("get_num_blocks", xbar_index); + const size_t base_port = mb->rpc->call<size_t>("get_base_port", xbar_index); UHD_LOG_TRACE("MPMD", "Enumerating RFNoC blocks for xbar " << xbar_index << ". Total blocks: " << num_blocks << @@ -140,78 +138,37 @@ mpmd_impl::mpmd_impl(const device_addr_t& device_addr) num_blocks, base_port, uhd::sid_t(0x0200), // TODO don't hardcode - device_addr + ctrl_xport_args ); } catch (const std::exception &ex) { UHD_LOGGER_ERROR("MPMD") - << "Failure during device initialization: " + << "Failure during block enumeration: " << ex.what(); throw uhd::runtime_error("Failed to run enumerate_rfnoc_blocks()"); } +} +void mpmd_impl::setup_rpc_blocks(const device_addr_t &block_args) +{ for (const auto &block_ctrl: _rfnoc_block_ctrl) { auto rpc_block_id = block_ctrl->get_block_id(); if (has_block<uhd::rfnoc::rpc_block_ctrl>(block_ctrl->get_block_id())) { const size_t mboard_idx = rpc_block_id.get_device_no(); UHD_LOGGER_DEBUG("MPMD") << "Adding RPC access to block: " << rpc_block_id - << " Extra device args: " << device_args[mboard_idx].to_string() + << " Block args: " << block_args.to_string() ; get_block_ctrl<uhd::rfnoc::rpc_block_ctrl>(rpc_block_id) - ->set_rpc_client(_mb[mboard_idx]->rpc, device_args[mboard_idx]); + ->set_rpc_client(_mb[mboard_idx]->rpc, block_args); } } } -mpmd_impl::~mpmd_impl() {} - -mpmd_mboard_impl::uptr mpmd_impl::setup_mb(const size_t mb_i, - const uhd::device_addr_t& dev_addr) -{ - const fs_path mb_path = "/mboards/" + std::to_string(mb_i); - mpmd_mboard_impl::uptr mb = mpmd_mboard_impl::make(dev_addr["addr"]); - mb->initialization_done = false; - std::vector<std::string> addrs; - const std::string eth0_addr = dev_addr["addr"]; - _tree->create<std::string>(mb_path / "name") - .set(mb->device_info.get("type", "")); - _tree->create<std::string>(mb_path / "serial") - .set(mb->device_info.get("serial", "")); - _tree->create<std::string>(mb_path / "connection") - .set(mb->device_info.get("connection", "remote")); - - for (const std::string& key : dev_addr.keys()) { - if (key.find("recv") != std::string::npos) - mb->recv_args[key] = dev_addr[key]; - if (key.find("send") != std::string::npos) - mb->send_args[key] = dev_addr[key]; - } - - // Do real MTU discovery (something similar like X300 but with MPM) - - _tree->create<size_t>(mb_path / "mtu/recv").set(1500); - _tree->create<size_t>(mb_path / "mtu/send").set(1500); - _tree->create<size_t>(mb_path / "link_max_rate").set(1e9 / 8); - - // query more information about FPGA/MPM - - // Call init on periph_manager, this will init the dboards/mboard, maybe - // even selfcal and everything - - // Query time/clock sources on mboards/dboards - // Throw rpc calls with boost bind into the property tree? - - // Query rfnoc blocks on the device (MPM may know about them?) - - // call enumerate rfnoc_blocks on the device - - // configure radio? - - // implicit move - return mb; -} +/***************************************************************************** + * API + ****************************************************************************/ // TODO this does not consider the liberio use case! uhd::device_addr_t mpmd_impl::get_rx_hints(size_t /* mb_index */) { @@ -294,6 +251,9 @@ both_xports_t mpmd_impl::make_transport(const sid_t& address, return xports; } +/***************************************************************************** + * Find, Factory & Registry + ****************************************************************************/ device_addrs_t mpmd_find_with_addr(const device_addr_t& hint_) { transport::udp_simple::sptr comm = transport::udp_simple::make_broadcast( @@ -337,10 +297,10 @@ device_addrs_t mpmd_find_with_addr(const device_addr_t& hint_) device_addr_t new_addr; new_addr["addr"] = recv_addr; new_addr["type"] = "mpmd"; // hwd will overwrite this - // remove ident string and put other informations into device_addr dict + // remove ident string and put other informations into device_args dict result.erase(result.begin()); // parse key-value pairs in the discovery string and add them to the - // device_addr + // device_args for (const auto& el : result) { std::vector<std::string> value; boost::algorithm::split(value, el, @@ -409,9 +369,9 @@ device_addrs_t mpmd_find(const device_addr_t& hint_) return addrs; } -static device::sptr mpmd_make(const device_addr_t& device_addr) +static device::sptr mpmd_make(const device_addr_t& device_args) { - return device::sptr(boost::make_shared<mpmd_impl>(device_addr)); + return device::sptr(boost::make_shared<mpmd_impl>(device_args)); } UHD_STATIC_BLOCK(register_mpmd_device) diff --git a/host/lib/usrp/mpmd/mpmd_impl.hpp b/host/lib/usrp/mpmd/mpmd_impl.hpp index 9a8b25ba0..6af2e4385 100644 --- a/host/lib/usrp/mpmd/mpmd_impl.hpp +++ b/host/lib/usrp/mpmd/mpmd_impl.hpp @@ -34,6 +34,7 @@ static const char MPM_DISCOVERY_CMD[] = "MPM-DISC"; static const char MPM_ECHO_CMD[] = "MPM-ECHO"; static const size_t MPMD_10GE_DATA_FRAME_MAX_SIZE = 8000; // CHDR packet size in bytes + struct frame_size_t { size_t recv_frame_size; @@ -46,35 +47,49 @@ struct frame_size_t class mpmd_mboard_impl { public: + /*** Types ***************************************************************/ using uptr = std::unique_ptr<mpmd_mboard_impl>; using dev_info = std::map<std::string, std::string>; + + /*** Structors ***********************************************************/ mpmd_mboard_impl(const std::string& addr); ~mpmd_mboard_impl(); + + /*** Factory *************************************************************/ static uptr make(const std::string& addr); - bool initialization_done = false; + /*** Public attributes ***************************************************/ + //! Device information is read back via MPM and stored here. uhd::dict<std::string, std::string> device_info; - uhd::dict<std::string, std::string> recv_args; - uhd::dict<std::string, std::string> send_args; - std::map<std::string, std::string> data_interfaces; - std::string loaded_fpga_image; - std::string xport_path; - /*! Reference the RPC client for this motherboard + //! Number of RFNoC crossbars on this device + size_t num_xbars = 0; + + /*! Reference to the RPC client for this motherboard * * We store a shared ptr, because we might share it with some of the RFNoC * blocks. */ uhd::rpc_client::sptr rpc; + + + /************************************************************************* + * API + ************************************************************************/ uhd::sid_t allocate_sid(const uint16_t port, const uhd::sid_t address, const uint32_t xbar_src_addr, const uint32_t xbar_src_dst); private: + /*! Renew the claim onto the device. + * + * This is meant to be called repeatedly, e.g., using a UHD task. + */ bool claim(); - std::string generate_token() const; - std::string _rpc_token; + + /*! Continuously reclaims the device. + */ uhd::task::sptr _claimer_task; }; @@ -91,19 +106,35 @@ class mpmd_impl : public uhd::usrp::device3_impl mpmd_impl(const uhd::device_addr_t& device_addr); ~mpmd_impl(); - mpmd_mboard_impl::uptr setup_mb(const size_t mb_i, - const uhd::device_addr_t& dev_addr); uhd::both_xports_t make_transport(const uhd::sid_t&, uhd::usrp::device3_impl::xport_type_t, const uhd::device_addr_t&); private: + mpmd_mboard_impl::uptr setup_mb( + const size_t mb_i, + const uhd::device_addr_t& dev_addr + ); + + void setup_rfnoc_blocks( + const size_t mb_i, + const uhd::device_addr_t& dev_addr + ); + + //! Configure all blocks that require access to an RPC client + void setup_rpc_blocks(const uhd::device_addr_t &block_args); + uhd::device_addr_t get_rx_hints(size_t mb_index); + uhd::dict<std::string, std::string> recv_args; + uhd::dict<std::string, std::string> send_args; + uhd::device_addr_t _device_addr; std::vector<mpmd_mboard_impl::uptr> _mb; size_t _sid_framer; }; + uhd::device_addrs_t mpmd_find(const uhd::device_addr_t& hint_); + #endif /* INCLUDED_MPMD_IMPL_HPP */ // vim: sw=4 expandtab: diff --git a/host/lib/usrp/mpmd/mpmd_mboard_impl.cpp b/host/lib/usrp/mpmd/mpmd_mboard_impl.cpp new file mode 100644 index 000000000..46e8d23a9 --- /dev/null +++ b/host/lib/usrp/mpmd/mpmd_mboard_impl.cpp @@ -0,0 +1,111 @@ +// +// Copyright 2017 Ettus Research (National Instruments) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +// + +#include "mpmd_impl.hpp" +#include <chrono> +#include <thread> + +namespace { + const size_t MPMD_RECLAIM_INTERVAL_MS = 1000; +} + +using namespace uhd; + +/***************************************************************************** + * Structors + ****************************************************************************/ +mpmd_mboard_impl::mpmd_mboard_impl(const std::string& ip_addr) + : rpc(uhd::rpc_client::make(ip_addr, MPM_RPC_PORT)) +{ + UHD_LOG_TRACE("MPMD", "Initializing mboard, IP address: " << ip_addr); + auto _dev_info = rpc->call<dev_info>("get_device_info"); + device_info = + dict<std::string, std::string>(_dev_info.begin(), _dev_info.end()); + // Get initial claim on mboard + auto rpc_token = rpc->call<std::string>("claim", "UHD - Session 01"); // TODO make this configurable with device_addr, and provide better defaults + if (rpc_token.empty()) { + throw uhd::value_error("mpmd device claiming failed!"); + } + rpc->set_token(rpc_token); + _claimer_task = task::make([this] { + if (not this->claim()) { + throw uhd::value_error("mpmd device reclaiming loop failed!"); + }; + std::this_thread::sleep_for( + std::chrono::milliseconds(MPMD_RECLAIM_INTERVAL_MS) + ); + }); + + // std::vector<std::string> data_ifaces = + // rpc.call<std::vector<std::string>>("get_interfaces", rpc_token); + + // discover path to device and tell MPM our MAC address seen at the data + // interfaces + // move this into make_transport + //for (const auto& iface : data_ifaces) { + //std::vector<std::string> addrs = rpc.call<std::vector<std::string>>( + //"get_interface_addrs", _rpc_token, iface); + //for (const auto& iface_addr : addrs) { + //if (rpc_client(iface_addr, MPM_RPC_PORT) + //.call<bool>("probe_interface", _rpc_token)) { + //data_interfaces.emplace(iface, iface_addr); + //break; + //} + //} + //} +} + +mpmd_mboard_impl::~mpmd_mboard_impl() +{ + /* nop */ +} + +/***************************************************************************** + * API + ****************************************************************************/ +uhd::sid_t mpmd_mboard_impl::allocate_sid(const uint16_t port, + const uhd::sid_t address, + const uint32_t xbar_src_addr, + const uint32_t xbar_src_port) +{ + const auto sid = rpc->call_with_token<uint32_t>( + "allocate_sid", + port, address.get(), xbar_src_addr, xbar_src_port + ); + return uhd::sid_t(sid); +} + + +/***************************************************************************** + * Private methods + ****************************************************************************/ +bool mpmd_mboard_impl::claim() +{ + return rpc->call_with_token<bool>("reclaim"); +} + +/***************************************************************************** + * Factory + ****************************************************************************/ +mpmd_mboard_impl::uptr mpmd_mboard_impl::make(const std::string& addr) +{ + mpmd_mboard_impl::uptr mb = + mpmd_mboard_impl::uptr(new mpmd_mboard_impl(addr)); + // implicit move + return mb; +} + |