diff options
author | Martin Braun <martin.braun@ettus.com> | 2019-08-20 10:00:47 -0700 |
---|---|---|
committer | Martin Braun <martin.braun@ettus.com> | 2019-11-26 12:16:25 -0800 |
commit | 7d69dcdcc318ccdf87038b732acbf2bf7c087b60 (patch) | |
tree | 8179f2f4a14be591d7c856f77f13687b45f9a454 /host/lib/rfnoc/legacy_compat.cpp | |
parent | 1ac6e6f56100a7e8186481ab0715937759f52737 (diff) | |
download | uhd-7d69dcdcc318ccdf87038b732acbf2bf7c087b60.tar.gz uhd-7d69dcdcc318ccdf87038b732acbf2bf7c087b60.tar.bz2 uhd-7d69dcdcc318ccdf87038b732acbf2bf7c087b60.zip |
Remove proto-RFNoC files
This commit removes all files and parts of files that are used by
proto-RFNoC only.
uhd: Fix include CMakeLists.txt, add missing files
Diffstat (limited to 'host/lib/rfnoc/legacy_compat.cpp')
-rw-r--r-- | host/lib/rfnoc/legacy_compat.cpp | 1179 |
1 files changed, 0 insertions, 1179 deletions
diff --git a/host/lib/rfnoc/legacy_compat.cpp b/host/lib/rfnoc/legacy_compat.cpp deleted file mode 100644 index 91de361df..000000000 --- a/host/lib/rfnoc/legacy_compat.cpp +++ /dev/null @@ -1,1179 +0,0 @@ -// -// Copyright 2016 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#include "../usrp/device3/device3_impl.hpp" -#include <uhd/property_tree.hpp> -#include <uhd/rfnoc/ddc_block_ctrl.hpp> -#include <uhd/rfnoc/graph.hpp> -#include <uhd/rfnoc/radio_ctrl.hpp> -#include <uhd/stream.hpp> -#include <uhd/transport/chdr.hpp> -#include <uhd/types/direction.hpp> -#include <uhd/types/ranges.hpp> -#include <uhd/types/stream_cmd.hpp> -#include <uhd/usrp/multi_usrp.hpp> -#include <uhd/usrp/subdev_spec.hpp> -#include <uhd/utils/log.hpp> -#include <uhdlib/rfnoc/legacy_compat.hpp> -#include <boost/make_shared.hpp> -#include <set> - -#define UHD_LEGACY_LOG() UHD_LOGGER_TRACE("RFNOC") - -using namespace uhd::rfnoc; -using uhd::stream_cmd_t; -using uhd::usrp::subdev_spec_pair_t; -using uhd::usrp::subdev_spec_t; - -/************************************************************************ - * Constants and globals - ***********************************************************************/ -static const std::string RADIO_BLOCK_NAME = "Radio"; -static const std::string DFIFO_BLOCK_NAME = "DmaFIFO"; -static const std::string SFIFO_BLOCK_NAME = "FIFO"; -static const std::string DDC_BLOCK_NAME = "DDC"; -static const std::string DUC_BLOCK_NAME = "DUC"; -static const size_t MAX_BYTES_PER_HEADER = - uhd::transport::vrt::chdr::max_if_hdr_words64 * sizeof(uint64_t); -static const size_t BYTES_PER_SAMPLE = 4; // We currently only support sc16 -static boost::mutex _make_mutex; -static const std::vector<std::string> LEGACY_BLOCKS_LIST = { - RADIO_BLOCK_NAME, DFIFO_BLOCK_NAME, SFIFO_BLOCK_NAME, DDC_BLOCK_NAME, DUC_BLOCK_NAME}; -typedef std::vector<source_block_ctrl_base::sptr> source_block_list_t; -typedef std::vector<sink_block_ctrl_base::sptr> sink_block_list_t; -typedef std::map<std::string, std::pair<source_block_list_t, sink_block_list_t>> - block_name_to_block_map_t; -typedef std::pair<source_block_ctrl_base::sptr, size_t> source_port_t; -typedef std::pair<sink_block_ctrl_base::sptr, size_t> sink_port_t; -/************************************************************************ - * Static helpers - ***********************************************************************/ -static uhd::fs_path mb_root(const size_t mboard) -{ - return uhd::fs_path("/mboards") / mboard; -} - -size_t num_ports(const uhd::property_tree::sptr& tree, - const std::string& block_name, - const std::string& in_out) -{ - return tree - ->list(uhd::fs_path("/mboards/0/xbar") / str(boost::format("%s_0") % block_name) - / "ports" / in_out) - .size(); -} - -size_t calc_num_tx_chans_per_radio(const uhd::property_tree::sptr& tree, - const size_t num_radios_per_board, - const bool has_ducs, - const bool has_dmafifo) -{ - const size_t num_radio_ports = num_ports(tree, RADIO_BLOCK_NAME, "in"); - if (has_ducs) { - return std::min(num_radio_ports, num_ports(tree, DUC_BLOCK_NAME, "in")); - } - - if (not has_dmafifo) { - return num_radio_ports; - } - - const size_t num_dmafifo_ports_per_radio = - num_ports(tree, DFIFO_BLOCK_NAME, "in") / num_radios_per_board; - UHD_ASSERT_THROW(num_dmafifo_ports_per_radio); - - return std::min(num_radio_ports, num_dmafifo_ports_per_radio); -} - -/*! Recreate passed property without bound subscribers. Maintains current property value. - */ -template <typename T> -static void recreate_property(const uhd::fs_path& path, uhd::property_tree::sptr& tree) -{ - T temp = tree->access<T>(path).get(); - tree->remove(path); - tree->create<T>(path).set(temp); -} - -/************************************************************************ - * Class Definition - ***********************************************************************/ -class legacy_compat_impl : public legacy_compat -{ -public: - /************************************************************************ - * Structors and Initialization - ***********************************************************************/ - legacy_compat_impl(uhd::device3::sptr device, const uhd::device_addr_t& args) - : _device(device) - , _tree(device->get_tree()) - , _has_ducs(not args.has_key("skip_duc") - and not device->find_blocks(DUC_BLOCK_NAME).empty()) - , _has_ddcs(not args.has_key("skip_ddc") - and not device->find_blocks(DDC_BLOCK_NAME).empty()) - , _has_dmafifo(not args.has_key("skip_dram") - and not device->find_blocks(DFIFO_BLOCK_NAME).empty()) - , _has_sramfifo(not args.has_key("skip_sram") - and not device->find_blocks(SFIFO_BLOCK_NAME).empty()) - , _num_mboards(_tree->list("/mboards").size()) - , _num_radios_per_board(device->find_blocks<radio_ctrl>("0/Radio").size()) - , // These might throw, maybe we catch that and provide a nicer error message. - _num_tx_chans_per_radio(calc_num_tx_chans_per_radio( - _tree, _num_radios_per_board, _has_ducs, _has_dmafifo)) - , _num_rx_chans_per_radio( - _has_ddcs ? std::min(num_ports(_tree, RADIO_BLOCK_NAME, "out"), - num_ports(_tree, DDC_BLOCK_NAME, "out")) - : num_ports(_tree, RADIO_BLOCK_NAME, "out")) - , _rx_spp(get_block_ctrl<radio_ctrl>(0, RADIO_BLOCK_NAME, 0)->get_arg<int>("spp")) - , _tx_spp(_rx_spp) - , _rx_channel_map(_num_mboards, std::vector<radio_port_pair_t>()) - , _tx_channel_map(_num_mboards, std::vector<radio_port_pair_t>()) - { - _device->clear(); - check_available_periphs(); // Throws if invalid configuration. - setup_prop_tree(); - if (_tree->exists("/mboards/0/mtu/send")) { - _tx_spp = (_tree->access<size_t>("/mboards/0/mtu/send").get() - - MAX_BYTES_PER_HEADER) - / BYTES_PER_SAMPLE; - } - connect_blocks(); - if (args.has_key("skip_ddc")) { - UHD_LEGACY_LOG() << "[legacy_compat] Skipping DDCs by user request."; - } else if (not _has_ddcs) { - UHD_LOGGER_WARNING("RFNOC") - << "[legacy_compat] No DDCs detected. You will only be able to receive " - "at the radio frontend rate."; - } - if (args.has_key("skip_duc")) { - UHD_LEGACY_LOG() << "[legacy_compat] Skipping DUCs by user request."; - } else if (not _has_ducs) { - UHD_LOGGER_WARNING("RFNOC") - << "[legacy_compat] No DUCs detected. You will only be able to transmit " - "at the radio frontend rate."; - } - if (args.has_key("skip_dram")) { - UHD_LEGACY_LOG() << "[legacy_compat] Skipping DRAM by user request."; - } - if (args.has_key("skip_sram")) { - UHD_LEGACY_LOG() << "[legacy_compat] Skipping SRAM by user request."; - } - if (not _has_dmafifo and not _has_sramfifo) { - UHD_LOGGER_WARNING("RFNOC") << "[legacy_compat] No FIFO detected. Higher " - "transmit rates may encounter errors."; - } - for (size_t mboard = 0; mboard < _num_mboards; mboard++) { - for (size_t radio = 0; radio < _num_radios_per_board; radio++) { - auto radio_block_ctrl = - get_block_ctrl<radio_ctrl>(mboard, "Radio", radio); - for (size_t port = 0; port < _num_rx_chans_per_radio; port++) { - if (!radio_block_ctrl->get_dboard_fe_from_chan( - port, uhd::RX_DIRECTION) - .empty()) { - _rx_channel_map[mboard].push_back({radio, port}); - } - } - for (size_t port = 0; port < _num_tx_chans_per_radio; port++) { - if (!radio_block_ctrl->get_dboard_fe_from_chan( - port, uhd::TX_DIRECTION) - .empty()) { - _tx_channel_map[mboard].push_back({radio, port}); - } - } - } - - update_sample_rate_on_blocks(mboard); - } - } - - ~legacy_compat_impl() - { - remove_prop_subscribers(); - } - - /************************************************************************ - * API Calls - ***********************************************************************/ - inline uhd::fs_path rx_dsp_root( - const size_t mboard_idx, const size_t dsp_index, const size_t port_index) - { - return mb_root(mboard_idx) / "xbar" - / str(boost::format("%s_%d") % DDC_BLOCK_NAME % dsp_index) / "legacy_api" - / port_index; - } - - uhd::fs_path rx_dsp_root(const size_t mboard_idx, const size_t chan) - { - // The DSP index is the same as the radio index - size_t dsp_index = _rx_channel_map[mboard_idx][chan].radio_index; - size_t port_index = _rx_channel_map[mboard_idx][chan].port_index; - - if (not _has_ddcs) { - return mb_root(mboard_idx) / "rx_dsps" / dsp_index / port_index; - } - - return rx_dsp_root(mboard_idx, dsp_index, port_index); - } - - inline uhd::fs_path tx_dsp_root( - const size_t mboard_idx, const size_t dsp_index, const size_t port_index) - { - return mb_root(mboard_idx) / "xbar" - / str(boost::format("%s_%d") % DUC_BLOCK_NAME % dsp_index) / "legacy_api" - / port_index; - } - - uhd::fs_path tx_dsp_root(const size_t mboard_idx, const size_t chan) - { - // The DSP index is the same as the radio index - size_t dsp_index = _tx_channel_map[mboard_idx][chan].radio_index; - size_t port_index = _tx_channel_map[mboard_idx][chan].port_index; - - if (not _has_ducs) { - return mb_root(mboard_idx) / "tx_dsps" / dsp_index / port_index; - } - - return tx_dsp_root(mboard_idx, dsp_index, port_index); - } - - uhd::fs_path rx_fe_root(const size_t mboard_idx, const size_t chan) - { - size_t radio_index = _rx_channel_map[mboard_idx][chan].radio_index; - size_t port_index = _rx_channel_map[mboard_idx][chan].port_index; - return uhd::fs_path( - str(boost::format("/mboards/%d/xbar/%s_%d/rx_fe_corrections/%d/") % mboard_idx - % RADIO_BLOCK_NAME % radio_index % port_index)); - } - - uhd::fs_path tx_fe_root(const size_t mboard_idx, const size_t chan) - { - size_t radio_index = _tx_channel_map[mboard_idx][chan].radio_index; - size_t port_index = _tx_channel_map[mboard_idx][chan].port_index; - return uhd::fs_path( - str(boost::format("/mboards/%d/xbar/%s_%d/tx_fe_corrections/%d/") % mboard_idx - % RADIO_BLOCK_NAME % radio_index % port_index)); - } - //! Get all legacy blocks from the LEGACY_BLOCK_LIST return in a form of - // {BLOCK_NAME: <{source_block_pointer},{sink_block_pointer}>} - block_name_to_block_map_t get_legacy_blocks(uhd::device3::sptr _device) - { - block_name_to_block_map_t result; - for (auto each_block_name : LEGACY_BLOCKS_LIST) { - std::vector<block_id_t> block_list = _device->find_blocks(each_block_name); - std::pair<source_block_list_t, sink_block_list_t> ss_pair; - source_block_list_t src_list; - sink_block_list_t snk_list; - for (auto each_block : block_list) { - uhd::rfnoc::source_block_ctrl_base::sptr src = - _device->get_block_ctrl<source_block_ctrl_base>(each_block); - src_list.push_back(src); - uhd::rfnoc::sink_block_ctrl_base::sptr snk = - _device->get_block_ctrl<sink_block_ctrl_base>(each_block); - snk_list.push_back(snk); - } - ss_pair = std::make_pair(src_list, snk_list); - result[each_block_name] = ss_pair; - } - return result; - } - - void issue_stream_cmd(const stream_cmd_t& stream_cmd, size_t mboard, size_t chan) - { - UHD_LEGACY_LOG() << "[legacy_compat] issue_stream_cmd() "; - const size_t& radio_index = _rx_channel_map[mboard][chan].radio_index; - const size_t& port_index = _rx_channel_map[mboard][chan].port_index; - if (_has_ddcs) { - get_block_ctrl<ddc_block_ctrl>(mboard, DDC_BLOCK_NAME, radio_index) - ->issue_stream_cmd(stream_cmd, port_index); - } else { - get_block_ctrl<radio_ctrl>(mboard, RADIO_BLOCK_NAME, radio_index) - ->issue_stream_cmd(stream_cmd, port_index); - } - } - - //! Sets block_id<N> and block_port<N> in the streamer args, otherwise forwards the - //! call - uhd::rx_streamer::sptr get_rx_stream(const uhd::stream_args_t& args_) - { - uhd::stream_args_t args(args_); - if (args.otw_format.empty()) { - args.otw_format = "sc16"; - } - _update_stream_args_for_streaming<uhd::RX_DIRECTION>(args, _rx_channel_map); - UHD_LEGACY_LOG() << "[legacy_compat] rx stream args: " << args.args.to_string(); - uhd::rx_streamer::sptr streamer = _device->get_rx_stream(args); - for (const size_t chan : args.channels) { - _rx_stream_cache[chan] = streamer; - } - return streamer; - } - - //! Sets block_id<N> and block_port<N> in the streamer args, otherwise forwards the - //! call. - // If spp is in the args, update the radios. If it's not set, copy the value from the - // radios. - uhd::tx_streamer::sptr get_tx_stream(const uhd::stream_args_t& args_) - { - uhd::stream_args_t args(args_); - if (args.otw_format.empty()) { - args.otw_format = "sc16"; - } - _update_stream_args_for_streaming<uhd::TX_DIRECTION>(args, _tx_channel_map); - UHD_LEGACY_LOG() << "[legacy_compat] tx stream args: " << args.args.to_string(); - uhd::tx_streamer::sptr streamer = _device->get_tx_stream(args); - for (const size_t chan : args.channels) { - _tx_stream_cache[chan] = streamer; - } - return streamer; - } - - double get_tick_rate(const size_t mboard_idx = 0) - { - return _tree->access<double>(mb_root(mboard_idx) / "tick_rate").get(); - } - - uhd::meta_range_t lambda_get_samp_rate_range(const size_t mboard_idx, - const size_t radio_idx, - const size_t chan, - uhd::direction_t dir) - { - radio_ctrl::sptr radio_sptr = - get_block_ctrl<radio_ctrl>(mboard_idx, RADIO_BLOCK_NAME, radio_idx); - const double samp_rate = (dir == uhd::TX_DIRECTION) - ? radio_sptr->get_input_samp_rate(chan) - : radio_sptr->get_output_samp_rate(chan); - - return uhd::meta_range_t(samp_rate, samp_rate, 0.0); - } - - void set_tick_rate(const double tick_rate, const size_t mboard_idx = 0) - { - _tree->access<double>(mb_root(mboard_idx) / "tick_rate").set(tick_rate); - for (size_t radio = 0; radio < _num_radios_per_board; radio++) { - auto radio_block_ctrl = - get_block_ctrl<radio_ctrl>(mboard_idx, "Radio", radio); - radio_block_ctrl->set_rate(tick_rate); - } - update_sample_rate_on_blocks(mboard_idx); - } - - void set_rx_rate(const double rate, const size_t chan) - { - if (not _has_ddcs) { - return; - } - - // Set DDC values: - if (chan == uhd::usrp::multi_usrp::ALL_CHANS) { - for (size_t mboard_idx = 0; mboard_idx < _rx_channel_map.size(); - mboard_idx++) { - for (size_t chan_idx = 0; chan_idx < _rx_channel_map[mboard_idx].size(); - chan_idx++) { - const size_t dsp_index = - _rx_channel_map[mboard_idx][chan_idx].radio_index; - const size_t port_index = - _rx_channel_map[mboard_idx][chan_idx].port_index; - _tree - ->access<double>( - rx_dsp_root(mboard_idx, dsp_index, port_index) / "rate/value") - .set(rate); - } - } - } else { - std::set<size_t> chans_to_change{chan}; - if (_rx_stream_cache.count(chan)) { - uhd::rx_streamer::sptr str_ptr = _rx_stream_cache[chan].lock(); - if (str_ptr) { - for (const rx_stream_map_type::value_type& chan_streamer_pair : - _rx_stream_cache) { - if (chan_streamer_pair.second.lock() == str_ptr) { - chans_to_change.insert(chan_streamer_pair.first); - } - } - } - } - for (const size_t this_chan : chans_to_change) { - size_t mboard, mb_chan; - chan_to_mcp<uhd::RX_DIRECTION>( - this_chan, _rx_channel_map, mboard, mb_chan); - const size_t dsp_index = _rx_channel_map[mboard][mb_chan].radio_index; - const size_t port_index = _rx_channel_map[mboard][mb_chan].port_index; - _tree - ->access<double>( - rx_dsp_root(mboard, dsp_index, port_index) / "rate/value") - .set(rate); - } - } - } - - void set_tx_rate(const double rate, const size_t chan) - { - if (not _has_ducs) { - return; - } - - // Set DUC values: - if (chan == uhd::usrp::multi_usrp::ALL_CHANS) { - for (size_t mboard_idx = 0; mboard_idx < _tx_channel_map.size(); - mboard_idx++) { - for (size_t chan_idx = 0; chan_idx < _tx_channel_map[mboard_idx].size(); - chan_idx++) { - const size_t dsp_index = - _tx_channel_map[mboard_idx][chan_idx].radio_index; - const size_t port_index = - _tx_channel_map[mboard_idx][chan_idx].port_index; - _tree - ->access<double>( - tx_dsp_root(mboard_idx, dsp_index, port_index) / "rate/value") - .set(rate); - } - } - } else { - std::set<size_t> chans_to_change{chan}; - if (_tx_stream_cache.count(chan)) { - uhd::tx_streamer::sptr str_ptr = _tx_stream_cache[chan].lock(); - if (str_ptr) { - for (const tx_stream_map_type::value_type& chan_streamer_pair : - _tx_stream_cache) { - if (chan_streamer_pair.second.lock() == str_ptr) { - chans_to_change.insert(chan_streamer_pair.first); - } - } - } - } - for (const size_t this_chan : chans_to_change) { - size_t mboard, mb_chan; - chan_to_mcp<uhd::TX_DIRECTION>( - this_chan, _tx_channel_map, mboard, mb_chan); - const size_t dsp_index = _tx_channel_map[mboard][mb_chan].radio_index; - const size_t port_index = _tx_channel_map[mboard][mb_chan].port_index; - _tree - ->access<double>( - tx_dsp_root(mboard, dsp_index, port_index) / "rate/value") - .set(rate); - } - } - } - -private: // types - struct radio_port_pair_t - { - radio_port_pair_t(const size_t radio = 0, const size_t port = 0) - : radio_index(radio), port_index(port) - { - } - size_t radio_index; - size_t port_index; - }; - //! Map: _rx_channel_map[mboard_idx][chan_idx] => (Radio, Port) - // Container is not a std::map because we need to guarantee contiguous - // ports and correct order anyway. - typedef std::vector<std::vector<radio_port_pair_t>> chan_map_t; - -private: // methods - /************************************************************************ - * Private helpers - ***********************************************************************/ - std::string get_slot_name(const size_t radio_index) - { - if (radio_index == 0) { - return "A"; - } else if (radio_index == 1) { - return "B"; - } else if (radio_index == 2) { - return "C"; - } else if (radio_index == 3) { - return "D"; - } else { - throw uhd::index_error(str( - boost::format("[legacy_compat]: radio index %u out of supported range.") - % radio_index)); - } - } - - size_t get_radio_index(const std::string slot_name) - { - if (slot_name == "A") { - return 0; - } else if (slot_name == "B") { - return 1; - } else if (slot_name == "C") { - return 2; - } else if (slot_name == "D") { - return 3; - } else { - throw uhd::key_error( - str(boost::format( - "[legacy_compat]: radio slot name %s out of supported range.") - % slot_name)); - } - } - - template <typename block_type> - inline typename block_type::sptr get_block_ctrl( - const size_t mboard_idx, const std::string& name, const size_t block_count) - { - block_id_t block_id(mboard_idx, name, block_count); - return _device->get_block_ctrl<block_type>(block_id); - } - - template <uhd::direction_t dir> - inline void chan_to_mcp(const size_t chan, - const chan_map_t& chan_map, - size_t& mboard_idx, - size_t& mb_chan_idx) - { - mboard_idx = 0; - mb_chan_idx = chan; - while (mb_chan_idx >= chan_map[mboard_idx].size()) { - mb_chan_idx -= chan_map[mboard_idx++].size(); - } - if (mboard_idx >= chan_map.size()) { - throw uhd::index_error( - str(boost::format("[legacy_compat]: %s channel %u out of range for given " - "frontend configuration.") - % (dir == uhd::TX_DIRECTION ? "TX" : "RX") % chan)); - } - } - - template <uhd::direction_t dir> - void _update_stream_args_for_streaming( - uhd::stream_args_t& args, const chan_map_t& chan_map) - { - // If the user provides spp, that value is always applied. If it's - // different from what we thought it was, we need to update the blocks. - // If it's not provided, we provide our own spp value. - const size_t args_spp = args.args.cast<size_t>("spp", 0); - if (dir == uhd::RX_DIRECTION) { - size_t target_spp = _rx_spp; - if (args.args.has_key("spp") and args_spp != _rx_spp) { - target_spp = args_spp; - // TODO: Update flow control on the blocks - } else { - for (size_t mboard = 0; mboard < _num_mboards; mboard++) { - for (size_t radio = 0; radio < _num_radios_per_board; radio++) { - const size_t this_spp = - get_block_ctrl<radio_ctrl>(mboard, RADIO_BLOCK_NAME, radio) - ->get_arg<int>("spp"); - target_spp = std::min(this_spp, target_spp); - } - } - } - for (size_t mboard = 0; mboard < _num_mboards; mboard++) { - for (size_t radio = 0; radio < _num_radios_per_board; radio++) { - get_block_ctrl<radio_ctrl>(mboard, RADIO_BLOCK_NAME, radio) - ->set_arg<int>("spp", target_spp); - } - } - _rx_spp = target_spp; - args.args["spp"] = str(boost::format("%d") % _rx_spp); - } else { - if (args.args.has_key("spp") and args_spp != _tx_spp) { - _tx_spp = args_spp; - // TODO: Update flow control on the blocks - } else { - args.args["spp"] = str(boost::format("%d") % _tx_spp); - } - } - - if (args.channels.empty()) { - args.channels = std::vector<size_t>(1, 0); - } - for (size_t i = 0; i < args.channels.size(); i++) { - const size_t stream_arg_chan_idx = args.channels[i]; - // Determine which mboard, and on that mboard, which channel this is: - size_t mboard_idx, this_mboard_chan_idx; - chan_to_mcp<dir>( - stream_arg_chan_idx, chan_map, mboard_idx, this_mboard_chan_idx); - // Map that mboard and channel to a block: - const size_t radio_index = - chan_map[mboard_idx][this_mboard_chan_idx].radio_index; - size_t port_index = chan_map[mboard_idx][this_mboard_chan_idx].port_index; - auto block_and_port = - _get_streamer_block_id_and_port<dir>(mboard_idx, radio_index, port_index); - auto block_name = block_and_port.first.to_string(); - port_index = block_and_port.second; - args.args[str(boost::format("block_id%d") % stream_arg_chan_idx)] = - block_name; - args.args[str(boost::format("block_port%d") % stream_arg_chan_idx)] = - str(boost::format("%d") % port_index); - // Map radio to channel (for in-band response) - args.args[str(boost::format("radio_id%d") % stream_arg_chan_idx)] = - block_id_t(mboard_idx, RADIO_BLOCK_NAME, radio_index).to_string(); - args.args[str(boost::format("radio_port%d") % stream_arg_chan_idx)] = - str(boost::format("%d") - % chan_map[mboard_idx][this_mboard_chan_idx].port_index); - } - } - - //! Given mboard_index(m), radio_index(r), and port_index(p), - // this function returns the index of a block on the input block list that match - // m,r,p - template <typename T> - size_t find_block(const std::vector<T>& port_list, - const size_t& m, - const size_t& r, - const size_t& p) - { - size_t index = 0; - for (auto port : port_list) { - auto block_id = (port.first)->get_block_id(); - if (p == port.second && r == block_id.get_block_count() - && m == block_id.get_device_no()) { - return index; - } - index++; - } - throw uhd::runtime_error( - (boost::format( - "Could not find block in list for device %d, radio %d, and port %d") - % m % r % p) - .str()); - } - - template <uhd::direction_t dir> - std::pair<block_id_t, size_t> _get_streamer_block_id_and_port( - const size_t& mboard_idx, const size_t& radio_index, const size_t& port_index) - { - block_name_to_block_map_t legacy_block_map = get_legacy_blocks(_device); - if (dir == uhd::TX_DIRECTION) { - auto radio_snk_flat = - _flatten_blocks_by_n_ports(legacy_block_map[RADIO_BLOCK_NAME].second); - size_t index_snk = find_block<sink_port_t>( - radio_snk_flat, mboard_idx, radio_index, port_index); - if (_has_sramfifo) { - auto sfifo_snk_flat = - _flatten_blocks_by_n_ports(legacy_block_map[SFIFO_BLOCK_NAME].second); - UHD_ASSERT_THROW(index_snk < sfifo_snk_flat.size()); - auto sfifo_block = sfifo_snk_flat[index_snk].first->get_block_id(); - return std::make_pair(sfifo_block, sfifo_snk_flat[index_snk].second); - } else if (_has_dmafifo) { - auto dfifo_snk_flat = - _flatten_blocks_by_n_ports(legacy_block_map[DFIFO_BLOCK_NAME].second); - UHD_ASSERT_THROW(index_snk < dfifo_snk_flat.size()); - auto dfifo_block = dfifo_snk_flat[index_snk].first->get_block_id(); - return std::make_pair(dfifo_block, dfifo_snk_flat[index_snk].second); - } else { - if (_has_ducs) { - return std::make_pair( - block_id_t(mboard_idx, DUC_BLOCK_NAME, radio_index).to_string(), - port_index); - auto duc_snk_flat = _flatten_blocks_by_n_ports( - legacy_block_map[DUC_BLOCK_NAME].second); - UHD_ASSERT_THROW(index_snk < duc_snk_flat.size()); - auto duc_block = duc_snk_flat[index_snk].first->get_block_id(); - return std::make_pair(duc_block, duc_snk_flat[index_snk].second); - } else { - return std::make_pair( - block_id_t(mboard_idx, RADIO_BLOCK_NAME, radio_index).to_string(), - port_index); - } - } - } else { - auto radio_src_flat = - _flatten_blocks_by_n_ports(legacy_block_map[RADIO_BLOCK_NAME].first); - size_t index_src = find_block<source_port_t>( - radio_src_flat, mboard_idx, radio_index, port_index); - if (_has_ddcs) { - auto ddc_src_flat = - _flatten_blocks_by_n_ports(legacy_block_map[DDC_BLOCK_NAME].first); - UHD_ASSERT_THROW(index_src < ddc_src_flat.size()); - auto ddc_block = ddc_src_flat[index_src].first->get_block_id(); - return std::make_pair(ddc_block, ddc_src_flat[index_src].second); - } else { - return std::make_pair( - block_id_t(mboard_idx, RADIO_BLOCK_NAME, radio_index).to_string(), - port_index); - } - } - } - /************************************************************************ - * Initialization - ***********************************************************************/ - /*! Check this device has all the required peripherals. - * - * Check rules: - * - Every mboard needs the same number of radios. - * - For every radio block, there must be DDC and a DUC block, - * with matching number of ports. - * - * \throw uhd::runtime_error if any of these checks fail. - */ - void check_available_periphs() - { - if (_num_radios_per_board == 0) { - throw uhd::runtime_error( - "For legacy APIs, all devices require at least one radio."); - } - block_id_t radio_block_id(0, RADIO_BLOCK_NAME); - block_id_t duc_block_id(0, DUC_BLOCK_NAME); - block_id_t ddc_block_id(0, DDC_BLOCK_NAME); - block_id_t fifo_block_id(0, DFIFO_BLOCK_NAME, 0); - for (size_t i = 0; i < _num_mboards; i++) { - radio_block_id.set_device_no(i); - duc_block_id.set_device_no(i); - ddc_block_id.set_device_no(i); - fifo_block_id.set_device_no(i); - for (size_t k = 0; k < _num_radios_per_board; k++) { - radio_block_id.set_block_count(k); - duc_block_id.set_block_count(k); - ddc_block_id.set_block_count(k); - // Only one FIFO per crossbar, so don't set block count for that block - if (not _device->has_block(radio_block_id) - or (_has_ducs and not _device->has_block(duc_block_id)) - or (_has_ddcs and not _device->has_block(ddc_block_id)) - or (_has_dmafifo and not _device->has_block(fifo_block_id))) { - throw uhd::runtime_error("For legacy APIs, all devices require the " - "same number of radios, DDCs and DUCs."); - } - - const size_t this_spp = get_block_ctrl<radio_ctrl>(i, RADIO_BLOCK_NAME, k) - ->get_arg<int>("spp"); - if (this_spp != _rx_spp) { - UHD_LOGGER_WARNING("RFNOC") << str( - boost::format( - "[legacy compat] Radios have differing spp values: %s has " - "%d, others have %d. UHD will use smaller spp value for all " - "connections. Performance might be not optimal.") - % radio_block_id.to_string() % this_spp % _rx_spp); - } - } - } - } - - /*! Initialize properties in property tree to match legacy mode - */ - void setup_prop_tree() - { - for (size_t mboard_idx = 0; mboard_idx < _num_mboards; mboard_idx++) { - uhd::fs_path root = mb_root(mboard_idx); - // Subdev specs - if (_tree->exists(root / "tx_subdev_spec")) { - _tree->access<subdev_spec_t>(root / "tx_subdev_spec") - .add_coerced_subscriber( - boost::bind(&legacy_compat_impl::set_subdev_spec, - this, - _1, - mboard_idx, - uhd::TX_DIRECTION)) - .update() - .set_publisher(boost::bind(&legacy_compat_impl::get_subdev_spec, - this, - mboard_idx, - uhd::TX_DIRECTION)); - } else { - _tree->create<subdev_spec_t>(root / "tx_subdev_spec") - .add_coerced_subscriber( - boost::bind(&legacy_compat_impl::set_subdev_spec, - this, - _1, - mboard_idx, - uhd::TX_DIRECTION)) - .set_publisher(boost::bind(&legacy_compat_impl::get_subdev_spec, - this, - mboard_idx, - uhd::TX_DIRECTION)); - } - - if (_tree->exists(root / "rx_subdev_spec")) { - _tree->access<subdev_spec_t>(root / "rx_subdev_spec") - .add_coerced_subscriber( - boost::bind(&legacy_compat_impl::set_subdev_spec, - this, - _1, - mboard_idx, - uhd::RX_DIRECTION)) - .update() - .set_publisher(boost::bind(&legacy_compat_impl::get_subdev_spec, - this, - mboard_idx, - uhd::RX_DIRECTION)); - } else { - _tree->create<subdev_spec_t>(root / "rx_subdev_spec") - .add_coerced_subscriber( - boost::bind(&legacy_compat_impl::set_subdev_spec, - this, - _1, - mboard_idx, - uhd::RX_DIRECTION)) - .set_publisher(boost::bind(&legacy_compat_impl::get_subdev_spec, - this, - mboard_idx, - uhd::RX_DIRECTION)); - } - - if (not _has_ddcs) { - for (size_t radio_idx = 0; radio_idx < _num_radios_per_board; - radio_idx++) { - for (size_t chan = 0; chan < _num_rx_chans_per_radio; chan++) { - const uhd::fs_path rx_dsp_base_path( - mb_root(mboard_idx) / "rx_dsps" / radio_idx / chan); - _tree->create<double>(rx_dsp_base_path / "rate/value") - .set(0.0) - .set_publisher(boost::bind(&radio_ctrl::get_output_samp_rate, - get_block_ctrl<radio_ctrl>( - mboard_idx, RADIO_BLOCK_NAME, radio_idx), - chan)); - _tree->create<uhd::meta_range_t>(rx_dsp_base_path / "rate/range") - .set_publisher(boost::bind( - &legacy_compat_impl::lambda_get_samp_rate_range, - this, - mboard_idx, - radio_idx, - chan, - uhd::RX_DIRECTION)); - _tree->create<double>(rx_dsp_base_path / "freq/value") - .set_publisher([]() { return 0.0; }); - _tree->create<uhd::meta_range_t>(rx_dsp_base_path / "freq/range") - .set_publisher( - []() { return uhd::meta_range_t(0.0, 0.0, 0.0); }); - } - } - } /* if not _has_ddcs */ - if (not _has_ducs) { - for (size_t radio_idx = 0; radio_idx < _num_radios_per_board; - radio_idx++) { - for (size_t chan = 0; chan < _num_tx_chans_per_radio; chan++) { - const uhd::fs_path tx_dsp_base_path( - mb_root(mboard_idx) / "tx_dsps" / radio_idx / chan); - _tree->create<double>(tx_dsp_base_path / "rate/value") - .set(0.0) - .set_publisher(boost::bind(&radio_ctrl::get_input_samp_rate, - get_block_ctrl<radio_ctrl>( - mboard_idx, RADIO_BLOCK_NAME, radio_idx), - chan)); - _tree->create<uhd::meta_range_t>(tx_dsp_base_path / "rate/range") - .set_publisher(boost::bind( - &legacy_compat_impl::lambda_get_samp_rate_range, - this, - mboard_idx, - radio_idx, - chan, - uhd::TX_DIRECTION)); - _tree->create<double>(tx_dsp_base_path / "freq/value") - .set_publisher([]() { return 0.0; }); - _tree->create<uhd::meta_range_t>(tx_dsp_base_path / "freq/range") - .set_publisher( - []() { return uhd::meta_range_t(0.0, 0.0, 0.0); }); - } - } - } /* if not _has_ducs */ - } - } - - - /*! Remove properties with bound functions in property tree and recreate - */ - void remove_prop_subscribers() - { - for (size_t mboard_idx = 0; mboard_idx < _num_mboards; mboard_idx++) { - uhd::fs_path root = mb_root(mboard_idx); - // Subdev specs - if (_tree->exists(root / "tx_subdev_spec")) { - recreate_property<subdev_spec_t>(root / "tx_subdev_spec", _tree); - } - - if (_tree->exists(root / "rx_subdev_spec")) { - recreate_property<subdev_spec_t>(root / "rx_subdev_spec", _tree); - } - } - } - - //! Flatten and sort a block list into a list of <block, port_index> - // For a block list {b0 ,b1} where each block has ports {p0, p1}, this will - // return {<b0,p0> <b0,p1> <b1,p0> <b1,p1>} - std::vector<source_port_t> _flatten_blocks_by_n_ports(source_block_list_t block_list) - { - std::vector<source_port_t> result; - for (auto block : block_list) { - for (auto port : block->get_output_ports()) { - result.push_back(std::make_pair(block, port)); - } - } - return result; - } - - //! Flatten and sort a block list into a list of <block, port_index> - // For a block list {b0 ,b1} where each block has ports {p0, p1}, this will - // return {<b0,p0> <b0,p1> <b1,p0> <b1,p1>} - std::vector<sink_port_t> _flatten_blocks_by_n_ports(sink_block_list_t block_list) - { - std::vector<sink_port_t> result; - for (auto block : block_list) { - for (auto port : block->get_input_ports()) { - result.push_back(std::make_pair(block, port)); - } - } - return result; - } - - template <typename T> - std::vector<std::pair<T, size_t>> _filter_flattened_blocks( - const std::vector<std::pair<T, size_t>>& blocks, size_t device_number) - { - const auto pred = [&device_number](const std::pair<T, size_t>& block) { - return (block.first->get_block_id().get_device_no() == device_number); - }; - - std::vector<std::pair<T, size_t>> result; - std::copy_if(blocks.begin(), blocks.end(), std::back_inserter(result), pred); - return result; - } - - /*! Default block connections. - * - * Tx connections: - * - * [Host] => DMA FIFO => DUC => Radio - * - * Note: There is only one DMA FIFO per crossbar, with twice the number of ports. - * - * Rx connections: - * - * Radio => DDC => [Host] - * - * Streamers are *not* generated here. - */ - void connect_blocks() - { - const size_t rx_bpp = _rx_spp * BYTES_PER_SAMPLE + MAX_BYTES_PER_HEADER; - const size_t tx_bpp = _tx_spp * BYTES_PER_SAMPLE + MAX_BYTES_PER_HEADER; - _graph = _device->create_graph("legacy"); - - block_name_to_block_map_t legacy_block_map = get_legacy_blocks(_device); - // create a list of all devices in the legacy block map - std::set<size_t> device_numbers; - for (const auto& block_list : legacy_block_map) { - for (const auto& block : block_list.second.first) { - device_numbers.insert(block->get_block_id().get_device_no()); - } - for (const auto& block : block_list.second.second) { - device_numbers.insert(block->get_block_id().get_device_no()); - } - } - - // Generate lists of all available ports in the graph - // RX connections: - // Radio => DDC - auto radio_sources = - _flatten_blocks_by_n_ports(legacy_block_map[RADIO_BLOCK_NAME].first); - auto ddc_sinks = - _flatten_blocks_by_n_ports(legacy_block_map[DDC_BLOCK_NAME].second); - - // TX connections: - // DUC => Radio - auto duc_sources = - _flatten_blocks_by_n_ports(legacy_block_map[DUC_BLOCK_NAME].first); - auto radio_sinks = - _flatten_blocks_by_n_ports(legacy_block_map[RADIO_BLOCK_NAME].second); - - // FIFO (SRAM or DMA) => DUC - auto duc_sinks = - _flatten_blocks_by_n_ports(legacy_block_map[DUC_BLOCK_NAME].second); - auto sfifo_sources = - _flatten_blocks_by_n_ports(legacy_block_map[SFIFO_BLOCK_NAME].first); - auto dfifo_sources = - _flatten_blocks_by_n_ports(legacy_block_map[DFIFO_BLOCK_NAME].first); - - for (const auto& device_number : device_numbers) { - // for RX, if there are DDCs, connect them to the radios - if (_has_ddcs) { - auto filtered_radio_sources = - _filter_flattened_blocks(radio_sources, device_number); - auto filtered_ddc_sinks = - _filter_flattened_blocks(ddc_sinks, device_number); - UHD_ASSERT_THROW( - filtered_radio_sources.size() <= filtered_ddc_sinks.size()); - - for (size_t i = 0; i < filtered_radio_sources.size(); ++i) { - _graph->connect(filtered_radio_sources[i].first->get_block_id(), - filtered_radio_sources[i].second, - filtered_ddc_sinks[i].first->get_block_id(), - filtered_ddc_sinks[i].second, - rx_bpp); - } - } - - // for TX, if there are DUCs, connect them to the radios - if (_has_ducs) { - auto filtered_duc_sources = - _filter_flattened_blocks(duc_sources, device_number); - auto filtered_radio_sinks = - _filter_flattened_blocks(radio_sinks, device_number); - - UHD_ASSERT_THROW( - filtered_duc_sources.size() <= filtered_radio_sinks.size()); - - for (size_t i = 0; i < filtered_duc_sources.size(); ++i) { - _graph->connect(filtered_duc_sources[i].first->get_block_id(), - filtered_duc_sources[i].second, - filtered_radio_sinks[i].first->get_block_id(), - filtered_radio_sinks[i].second, - tx_bpp); - } - } - - // for TX, if there are SRAM or DMA fifos, connect them to the DUCs - // (or radios, if there are no DUCs) - if (_has_sramfifo or _has_dmafifo) { - auto filtered_sources = - (_has_sramfifo) - ? _filter_flattened_blocks(sfifo_sources, device_number) - : _filter_flattened_blocks(dfifo_sources, device_number); - auto filtered_sinks = - (_has_ducs) ? _filter_flattened_blocks(duc_sinks, device_number) - : _filter_flattened_blocks(radio_sinks, device_number); - - if (filtered_sources.size() < filtered_sinks.size()) { - UHD_LOG_WARNING("RFNOC", - "[legacy compat] Not enough FIFO ports to connect, not all TX " - "sinks will be connected"); - } - - for (size_t i = 0; i < filtered_sources.size(); ++i) { - _graph->connect(filtered_sources[i].first->get_block_id(), - filtered_sources[i].second, - filtered_sinks[i].first->get_block_id(), - filtered_sinks[i].second, - tx_bpp); - } - } - } - } - - - /************************************************************************ - * Subdev translation - ***********************************************************************/ - /*! Subdev -> (Radio, Port) - * - * Example: Device is X300, subdev spec is 'A:0 B:0', we have 2 radios. - * Then we map to ((0, 0), (1, 0)). I.e., zero-th port on radio 0 and - * radio 1, respectively. - */ - void set_subdev_spec( - const subdev_spec_t& spec, const size_t mboard, const uhd::direction_t dir) - { - UHD_ASSERT_THROW(mboard < _num_mboards); - chan_map_t& chan_map = (dir == uhd::TX_DIRECTION) ? _tx_channel_map - : _rx_channel_map; - - std::vector<radio_port_pair_t> new_mapping(spec.size()); - for (size_t i = 0; i < spec.size(); i++) { - const size_t new_radio_index = get_radio_index(spec[i].db_name); - radio_ctrl::sptr radio = - get_block_ctrl<radio_ctrl>(mboard, "Radio", new_radio_index); - size_t new_port_index = radio->get_chan_from_dboard_fe(spec[i].sd_name, dir); - auto port_size = (dir == uhd::TX_DIRECTION) - ? radio->get_input_ports().size() - : radio->get_output_ports().size(); - auto default_index = (dir == uhd::TX_DIRECTION) - ? radio->get_input_ports().at(0) - : radio->get_output_ports().at(0); - if (new_port_index >= port_size) { - new_port_index = default_index; - } - - radio_port_pair_t new_radio_port_pair(new_radio_index, new_port_index); - new_mapping[i] = new_radio_port_pair; - } - chan_map[mboard] = new_mapping; - } - - subdev_spec_t get_subdev_spec(const size_t mboard, const uhd::direction_t dir) - { - UHD_ASSERT_THROW(mboard < _num_mboards); - subdev_spec_t subdev_spec; - chan_map_t& chan_map = (dir == uhd::TX_DIRECTION) ? _tx_channel_map - : _rx_channel_map; - for (size_t chan_idx = 0; chan_idx < chan_map[mboard].size(); chan_idx++) { - const size_t radio_index = chan_map[mboard][chan_idx].radio_index; - const size_t port_index = chan_map[mboard][chan_idx].port_index; - const std::string new_db_name = get_slot_name(radio_index); - const std::string new_sd_name = - get_block_ctrl<radio_ctrl>(mboard, "Radio", radio_index) - ->get_dboard_fe_from_chan(port_index, dir); - subdev_spec_pair_t new_pair(new_db_name, new_sd_name); - subdev_spec.push_back(new_pair); - } - - return subdev_spec; - } - - void update_sample_rate_on_blocks(const size_t mboard_idx) - { - block_id_t radio_block_id(mboard_idx, RADIO_BLOCK_NAME); - block_id_t duc_block_id(mboard_idx, DUC_BLOCK_NAME); - block_id_t ddc_block_id(mboard_idx, DDC_BLOCK_NAME); - - for (size_t radio = 0; radio < _num_radios_per_board; radio++) { - radio_block_id.set_block_count(radio); - duc_block_id.set_block_count(radio); - ddc_block_id.set_block_count(radio); - radio_ctrl::sptr radio_sptr = - _device->get_block_ctrl<radio_ctrl>(radio_block_id); - for (size_t chan = 0; chan < _num_rx_chans_per_radio and _has_ddcs; chan++) { - const double radio_output_rate = radio_sptr->get_output_samp_rate(chan); - _device->get_block_ctrl(ddc_block_id) - ->set_arg<double>("input_rate", radio_output_rate, chan); - } - for (size_t chan = 0; chan < _num_tx_chans_per_radio and _has_ducs; chan++) { - const double radio_input_rate = radio_sptr->get_input_samp_rate(chan); - _device->get_block_ctrl(duc_block_id) - ->set_arg<double>("output_rate", radio_input_rate, chan); - } - } - } - -private: // attributes - uhd::device3::sptr _device; - uhd::property_tree::sptr _tree; - - const bool _has_ducs; - const bool _has_ddcs; - const bool _has_dmafifo; - const bool _has_sramfifo; - const size_t _num_mboards; - const size_t _num_radios_per_board; - const size_t _num_tx_chans_per_radio; - const size_t _num_rx_chans_per_radio; - size_t _rx_spp; - size_t _tx_spp; - - chan_map_t _rx_channel_map; - chan_map_t _tx_channel_map; - - //! Stores a weak pointer for every streamer that's generated through this API. - // Key is the channel number (same format as e.g. the set_rx_rate() call). - typedef std::map<size_t, boost::weak_ptr<uhd::rx_streamer>> rx_stream_map_type; - rx_stream_map_type _rx_stream_cache; - typedef std::map<size_t, boost::weak_ptr<uhd::tx_streamer>> tx_stream_map_type; - tx_stream_map_type _tx_stream_cache; - - graph::sptr _graph; -}; - -legacy_compat::sptr legacy_compat::make( - uhd::device3::sptr device, const uhd::device_addr_t& args) -{ - boost::lock_guard<boost::mutex> lock(_make_mutex); - UHD_ASSERT_THROW(bool(device)); - static std::map<void*, boost::weak_ptr<legacy_compat>> legacy_cache; - - if (legacy_cache.count(device.get()) - and not legacy_cache.at(device.get()).expired()) { - legacy_compat::sptr legacy_compat_copy = legacy_cache.at(device.get()).lock(); - UHD_ASSERT_THROW(bool(legacy_compat_copy)); - UHD_LEGACY_LOG() - << "[legacy_compat] Using existing legacy compat object for this device."; - return legacy_compat_copy; - } - - legacy_compat::sptr new_legacy_compat = - boost::make_shared<legacy_compat_impl>(device, args); - legacy_cache[device.get()] = new_legacy_compat; - return new_legacy_compat; -} |