diff options
218 files changed, 244 insertions, 22930 deletions
diff --git a/host/CMakeLists.txt b/host/CMakeLists.txt index 17af21824..53e5cba7e 100644 --- a/host/CMakeLists.txt +++ b/host/CMakeLists.txt @@ -301,8 +301,6 @@ link_directories(${Boost_LIBRARY_DIRS})  ########################################################################  # Additional settings for build environment  ######################################################################## -# Note: RFNoC never gets fully disabled, but the public APIs do -set(ENABLE_RFNOC ON CACHE BOOL "Export RFNoC includes and symbols")  include(UHDGlobalDefs)  include(UHDLog) @@ -470,12 +468,7 @@ endforeach(Boost_Comp)  if(ENABLE_USB)      list(APPEND UHD_LINK_LIST_STATIC "usb-1.0")  endif(ENABLE_USB) -# UHDConfig.cmake also needs UHD_RFNOC_FOUND -if(ENABLE_RFNOC) -    set(UHD_RFNOC_FOUND "TRUE") -else() -    set(UHD_RFNOC_FOUND "FALSE") -endif(ENABLE_RFNOC) +set(UHD_RFNOC_FOUND "TRUE")  configure_file(      ${CMAKE_SOURCE_DIR}/cmake/Modules/UHDConfigVersion.cmake.in diff --git a/host/cmake/Modules/UHDGlobalDefs.cmake b/host/cmake/Modules/UHDGlobalDefs.cmake index a10d256b5..a137de569 100644 --- a/host/cmake/Modules/UHDGlobalDefs.cmake +++ b/host/cmake/Modules/UHDGlobalDefs.cmake @@ -16,10 +16,5 @@ else()      math(EXPR UHD_VERSION_ADDED "1000000 * ${UHD_VERSION_MAJOR} + 10000 * ${UHD_VERSION_API} + 100 * ${UHD_VERSION_ABI} + ${UHD_VERSION_PATCH}")  endif(UHD_VERSION_DEVEL) -## RFNoC -if(ENABLE_RFNOC) -    add_definitions(-DUHD_RFNOC_ENABLED) -endif(ENABLE_RFNOC) -  ## make sure the code knows about config.h  add_definitions(-DHAVE_CONFIG_H) diff --git a/host/docs/CMakeLists.txt b/host/docs/CMakeLists.txt index 8df7c1069..08e4a6766 100644 --- a/host/docs/CMakeLists.txt +++ b/host/docs/CMakeLists.txt @@ -37,9 +37,6 @@ if(ENABLE_MANUAL)      set(DOXYGEN_FPGA_MANUAL_REFERENCE "<a href=\"http://files.ettus.com/manual/md_fpga.html\">Part III: FPGA Manual</a>")      set(DOXYGEN_STRIP_EXTRA "")      set(DOXYGEN_EXCLUDE_DIRS "") -    if(NOT ENABLE_RFNOC) -        set(DOXYGEN_EXCLUDE_DIRS "${DOXYGEN_EXCLUDE_DIRS} ${CMAKE_SOURCE_DIR}/include/uhd/rfnoc") -    endif(NOT ENABLE_RFNOC)      # Now, check if we have the FPGA sources as well.      # If so, pull them in:      if(HAS_FPGA_SUBMODULE) @@ -73,7 +70,7 @@ if(ENABLE_DOXYGEN)      file(GLOB_RECURSE header_files ${CMAKE_SOURCE_DIR}/include/*.hpp)      file(GLOB_RECURSE h_files ${CMAKE_SOURCE_DIR}/include/*.h)      list(APPEND header_files ${h_files}) -    set(DOXYGEN_DEPENDENCIES ${DOXYGEN_DEPENDENCIES} ${header_files} "${CMAKE_SOURCE_DIR}/lib/rfnoc/nocscript/gen_basic_funcs.py") +    set(DOXYGEN_DEPENDENCIES ${DOXYGEN_DEPENDENCIES} ${header_files})      if(ENABLE_DOXYGEN_FULL)          set(DOXYGEN_INPUT_DIRS "${DOXYGEN_INPUT_DIRS} ${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/lib ${CMAKE_SOURCE_DIR}/python")      else(ENABLE_DOXYGEN_FULL) diff --git a/host/docs/block_desc_files.dox b/host/docs/block_desc_files.dox deleted file mode 100644 index 20f54e24a..000000000 --- a/host/docs/block_desc_files.dox +++ /dev/null @@ -1,16 +0,0 @@ -/*! \page page_rfnoc_descriptor_file RFNoC Block Descriptor Files - - -\section rfnoc_descriptor_file_nocscript NocScript - -NocScript is a simple DSL designed to augment block definition files for RFNoC. - -\li Statically Typed -\li No implicit typecasting -\li Very few operators - -See \subpage page_nocscript_funcs for a full function reference. - -*/ -// vim:ft=doxygen: - diff --git a/host/docs/mainpage.dox.in b/host/docs/mainpage.dox.in index ebe509fc8..4b3371a57 100644 --- a/host/docs/mainpage.dox.in +++ b/host/docs/mainpage.dox.in @@ -13,7 +13,6 @@ Follow these links to get to the section of the manual you wish to consult, or u  \li \subpage page_devices "Part I: Devices & Usage Manual"  \li \subpage page_uhd "Part II: UHD Development Manual"  \li @DOXYGEN_FPGA_MANUAL_REFERENCE@ -\li \subpage page_rfnoc "Part IV: RFNoC Development Manual"  ### Further Information diff --git a/host/docs/rfnoc.dox b/host/docs/rfnoc.dox deleted file mode 100644 index 602b75b46..000000000 --- a/host/docs/rfnoc.dox +++ /dev/null @@ -1,6 +0,0 @@ -/*! \page page_rfnoc RFNoC Development Manual - -\li \subpage page_rfnoc_descriptor_file - -*/ -// vim:ft=doxygen: diff --git a/host/examples/CMakeLists.txt b/host/examples/CMakeLists.txt index 735795d55..8578e2035 100644 --- a/host/examples/CMakeLists.txt +++ b/host/examples/CMakeLists.txt @@ -28,19 +28,13 @@ set(example_sources      latency_test.cpp      gpio.cpp      sync_to_gps.cpp +    rfnoc_nullsource_ce_rx.cpp +    rfnoc_rx_to_file.cpp +    #rfnoc_radio_loopback.cpp +    #benchmark_streamer.cpp +    #replay_samples_from_file.cpp  ) -if(ENABLE_RFNOC) -    list(APPEND -        example_sources -        rfnoc_nullsource_ce_rx.cpp -        rfnoc_rx_to_file.cpp -        rfnoc_radio_loopback.cpp -        replay_samples_from_file.cpp -        benchmark_streamer.cpp -    ) -endif(ENABLE_RFNOC) -  if(ENABLE_OCTOCLOCK)      list(APPEND example_sources test_clock_synch.cpp)  endif(ENABLE_OCTOCLOCK) diff --git a/host/examples/benchmark_streamer.cpp b/host/examples/benchmark_streamer.cpp index 2b82acf7e..c2f3a4b2c 100644 --- a/host/examples/benchmark_streamer.cpp +++ b/host/examples/benchmark_streamer.cpp @@ -5,7 +5,6 @@  //  #include <uhd/convert.hpp> -#include <uhd/device3.hpp>  #include <uhd/rfnoc/block_ctrl.hpp>  #include <uhd/rfnoc/ddc_block_ctrl.hpp>  #include <uhd/rfnoc/duc_block_ctrl.hpp> diff --git a/host/examples/rfnoc_nullsource_ce_rx.cpp b/host/examples/rfnoc_nullsource_ce_rx.cpp index 640e5bcff..368b6ab5d 100644 --- a/host/examples/rfnoc_nullsource_ce_rx.cpp +++ b/host/examples/rfnoc_nullsource_ce_rx.cpp @@ -20,7 +20,6 @@  // crossbar (provided it has stream-through capabilities)  // and then streams the result to the host, writing it into a file. -#include <uhd/device3.hpp>  #include <uhd/exception.hpp>  #include <uhd/rfnoc/block_control.hpp>  #include <uhd/rfnoc/null_block_control.hpp> diff --git a/host/examples/rfnoc_radio_loopback.cpp b/host/examples/rfnoc_radio_loopback.cpp index 92046eebc..dffe30b3b 100644 --- a/host/examples/rfnoc_radio_loopback.cpp +++ b/host/examples/rfnoc_radio_loopback.cpp @@ -8,7 +8,6 @@  // Example UHD/RFNoC application: Connect an rx radio to a tx radio and  // run a loopback. -#include <uhd/device3.hpp>  #include <uhd/rfnoc/radio_ctrl.hpp>  #include <uhd/utils/math.hpp>  #include <uhd/utils/safe_main.hpp> diff --git a/host/include/uhd/CMakeLists.txt b/host/include/uhd/CMakeLists.txt index 95770038e..429d4fe63 100644 --- a/host/include/uhd/CMakeLists.txt +++ b/host/include/uhd/CMakeLists.txt @@ -1,13 +1,11 @@  #  # Copyright 2010-2011,2013-2015 Ettus Research LLC  # Copyright 2018 Ettus Research, a National Instruments Company +# Copyright 2019 Ettus Research, a National Instruments Brand  #  # SPDX-License-Identifier: GPL-3.0-or-later  # -# This is a temporary include - remove once rfnoc is replaced by erfnoc -add_subdirectory(erfnoc) -  add_subdirectory(rfnoc)  add_subdirectory(transport)  add_subdirectory(types) @@ -35,14 +33,6 @@ UHD_INSTALL(FILES      COMPONENT headers  ) -if(ENABLE_RFNOC) -    UHD_INSTALL(FILES -        device3.hpp -        DESTINATION ${INCLUDE_DIR}/uhd -        COMPONENT headers -    ) -endif(ENABLE_RFNOC) -  if(ENABLE_C_API)      UHD_INSTALL(FILES          config.h diff --git a/host/include/uhd/config.hpp b/host/include/uhd/config.hpp index 383159005..812006ab5 100644 --- a/host/include/uhd/config.hpp +++ b/host/include/uhd/config.hpp @@ -111,13 +111,6 @@ typedef ptrdiff_t ssize_t;  #    endif // UHD_DLL_EXPORTS  #endif // UHD_STATIC_LIB -#ifdef UHD_RFNOC_ENABLED -#    define UHD_RFNOC_API UHD_API -#else -#    define UHD_RFNOC_API -#endif // UHD_RFNOC_ENABLED - -  // Platform defines for conditional parts of headers:  // Taken from boost/config/select_platform_config.hpp,  // however, we define macros, not strings for platforms. diff --git a/host/include/uhd/device3.hpp b/host/include/uhd/device3.hpp deleted file mode 100644 index c4d0d94fe..000000000 --- a/host/include/uhd/device3.hpp +++ /dev/null @@ -1,145 +0,0 @@ -// -// Copyright 2014-2016 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// Copyright 2019 Ettus Research, a National Instruments Brand -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#ifndef INCLUDED_UHD_DEVICE3_HPP -#define INCLUDED_UHD_DEVICE3_HPP - -#include <uhd/device.hpp> -#include <uhd/rfnoc/block_ctrl_base.hpp> -#include <uhd/rfnoc/graph.hpp> -#include <boost/core/demangle.hpp> -#include <boost/thread/mutex.hpp> -#include <vector> - -namespace uhd { - -/*! - * \brief Extends uhd::device for third-generation USRP devices. - * - * Generation-3 devices are characterized by the following traits: - * - They support RFNoC (RF Network-on-Chip). - * - Data transport uses the compressed VITA (CVITA/CHDR) data format. - */ -class UHD_API device3 : public uhd::device -{ -public: -    typedef boost::shared_ptr<device3> sptr; - -    //! Same as uhd::device::make(), but will fail if not actually a device3 -    static sptr make(const device_addr_t& hint, const size_t which = 0); - -    virtual rfnoc::graph::sptr create_graph(const std::string& name = "") = 0; - -    /*! Reset blocks after a stream. -     * -     * TODO write docs -     */ -    void clear(); - -    /*! \brief Checks if an RFNoC block exists on the device. -     * -     * \param block_id Canonical block name (e.g. "0/FFT_1"). -     * \return true if a block with the specified id exists -     * \note this access is not thread safe if peformed during block enumeration -     */ -    bool has_block(const rfnoc::block_id_t& block_id) const; - -    /*! Same as has_block(), but with a type check. -     * -     * \return true if a block of type T with the specified id exists -     * \note this access is not thread safe if peformed during block enumeration -     */ -    template <typename T> bool has_block(const rfnoc::block_id_t& block_id) const -    { -        if (has_block(block_id)) { -            return bool(boost::dynamic_pointer_cast<T>(get_block_ctrl(block_id))); -        } else { -            return false; -        } -    } - -    /*! \brief Returns a block controller class for an RFNoC block. -     * -     * If the given block ID is not valid (i.e. such a block does not exist -     * on this device), it will throw a uhd::lookup_error. -     * -     * \param block_id Canonical block name (e.g. "0/FFT_1"). -     * \note this access is not thread safe if peformed during block enumeration -     */ -    rfnoc::block_ctrl_base::sptr get_block_ctrl(const rfnoc::block_id_t& block_id) const; - -    /*! Same as get_block_ctrl(), but with a type cast. -     * -     * If you have a block controller class that is derived from block_ctrl_base, -     * use this function to access its specific methods. -     * If the given block ID is not valid (i.e. such a block does not exist -     * on this device) or if the type does not match, it will throw a uhd::lookup_error. -     * -     * \code{.cpp} -     * // Assume DEV is a device3::sptr -     * uhd::rfnoc::my_block_ctrl::sptr block_controller = -     * get_block_ctrl<my_block_ctrl>("0/MyBlock_0"); -     * block_controller->my_own_block_method(); -     * \endcode -     * \note this access is not thread safe if peformed during block enumeration -     */ -    template <typename T> -    boost::shared_ptr<T> get_block_ctrl(const rfnoc::block_id_t& block_id) const -    { -        boost::shared_ptr<T> blk = -            boost::dynamic_pointer_cast<T>(get_block_ctrl(block_id)); -        if (blk) { -            return blk; -        } else { -            throw uhd::lookup_error(str( -                boost::format("This device does not have a block of type %s with ID: %s") -                % boost::core::demangle(typeid(T).name()) % block_id.to_string())); -        } -    } - -    /*! Returns the block ids of all blocks that match the specified hint -     * Uses block_ctrl_base::match() internally. -     * If no matching block is found, it returns an empty vector. -     * -     * To access specialized block controller classes (i.e. derived from block_ctrl_base), -     * use the templated version of this function, e.g. -     * \code{.cpp} -     * // Assume DEV is a device3::sptr -     * null_block_ctrl::sptr null_block = -     * DEV->find_blocks<null_block_ctrl>("NullSrcSink"); \endcode \note this access is not -     * thread safe if peformed during block enumeration -     */ -    std::vector<rfnoc::block_id_t> find_blocks(const std::string& block_id_hint) const; - -    /*! Type-cast version of find_blocks(). -     */ -    template <typename T> -    std::vector<rfnoc::block_id_t> find_blocks(const std::string& block_id_hint) const -    { -        std::vector<rfnoc::block_id_t> all_block_ids = find_blocks(block_id_hint); -        std::vector<rfnoc::block_id_t> filt_block_ids; -        for (size_t i = 0; i < all_block_ids.size(); i++) { -            if (has_block<T>(all_block_ids[i])) { -                filt_block_ids.push_back(all_block_ids[i]); -            } -        } -        return filt_block_ids; -    } - -protected: -    //! List of *all* RFNoC blocks available on this device. -    //  It is the responsibility of the deriving class to make -    //  sure this gets correctly populated. -    std::vector<rfnoc::block_ctrl_base::sptr> _rfnoc_block_ctrl; -    //! Mutex to protect access to members -    boost::mutex _block_ctrl_mutex; -}; - -} // namespace uhd - -#endif /* INCLUDED_UHD_DEVICE3_HPP */ diff --git a/host/include/uhd/erfnoc/CMakeLists.txt b/host/include/uhd/erfnoc/CMakeLists.txt deleted file mode 100644 index e4eddaea2..000000000 --- a/host/include/uhd/erfnoc/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -# -# Copyright 2019 Ettus Research, a National Instruments Company -# -# SPDX-License-Identifier: GPL-3.0-or-later -# - -add_subdirectory(blocks) -add_subdirectory(core)
\ No newline at end of file diff --git a/host/include/uhd/erfnoc/core/CMakeLists.txt b/host/include/uhd/erfnoc/core/CMakeLists.txt deleted file mode 100644 index ef7904789..000000000 --- a/host/include/uhd/erfnoc/core/CMakeLists.txt +++ /dev/null @@ -1,20 +0,0 @@ -# -# Copyright 2019 Ettus Research, a National Instruments Company -# -# SPDX-License-Identifier: GPL-3.0-or-later -# - -file(GLOB yml_files "*.yml") -file(GLOB json_files "*.json") - -# We always need this, even when RFNoC is 'disabled' -UHD_INSTALL( -    FILES ${yml_files} -    DESTINATION ${PKG_DATA_DIR}/erfnoc/core -    COMPONENT headers # TODO: Different component -) -UHD_INSTALL( -    FILES ${json_files} -    DESTINATION ${PKG_DATA_DIR}/erfnoc/core -    COMPONENT headers # TODO: Different component -)
\ No newline at end of file diff --git a/host/include/uhd/rfnoc/CMakeLists.txt b/host/include/uhd/rfnoc/CMakeLists.txt index d65332dac..20c8cc38a 100644 --- a/host/include/uhd/rfnoc/CMakeLists.txt +++ b/host/include/uhd/rfnoc/CMakeLists.txt @@ -1,58 +1,45 @@  #  # Copyright 2014-2016 Ettus Research LLC  # Copyright 2018 Ettus Research, a National Instruments Company +# Copyright 2019 Ettus Research, a National Instruments Brand  #  # SPDX-License-Identifier: GPL-3.0-or-later  # -if(ENABLE_RFNOC) -    UHD_INSTALL(FILES -        # Infrastructure -        block_ctrl_base.hpp -        block_ctrl.hpp -        block_control.hpp -        blockdef.hpp -        block_id.hpp -        constants.hpp -        defaults.hpp -        dirtifier.hpp -        graph.hpp -        graph_edge.hpp -        mb_controller.hpp -        noc_block_make_args.hpp -        node_ctrl_base.hpp -        node_ctrl_base.ipp -        node.hpp -        node.ipp -        rate_node_ctrl.hpp -        registry.hpp -        scalar_node_ctrl.hpp -        sink_block_ctrl_base.hpp -        sink_node_ctrl.hpp -        source_block_ctrl_base.hpp -        source_node_ctrl.hpp -        stream_sig.hpp -        terminator_node_ctrl.hpp -        tick_node_ctrl.hpp -        # Block controllers -        ddc_block_control.hpp -        duc_block_control.hpp -        ddc_block_ctrl.hpp -        dma_fifo_block_ctrl.hpp -        duc_block_ctrl.hpp -        fir_block_ctrl.hpp -        null_block_ctrl.hpp -        null_block_control.hpp -        radio_ctrl.hpp -        radio_control.hpp -        replay_block_ctrl.hpp -        siggen_block_ctrl.hpp -        window_block_ctrl.hpp -        register_iface.hpp -        DESTINATION ${INCLUDE_DIR}/uhd/rfnoc -        COMPONENT headers -    ) -endif(ENABLE_RFNOC) +UHD_INSTALL(FILES +    # Infrastructure +    actions.hpp +    block_id.hpp +    blockdef.hpp +    constants.hpp +    defaults.hpp +    dirtifier.hpp +    filter_node.hpp +    graph_edge.hpp +    mb_controller.hpp +    noc_block_base.hpp +    noc_block_make_args.hpp +    node.hpp +    node.ipp +    property.hpp +    property.ipp +    radio_control.hpp +    register_iface.hpp +    register_iface_holder.hpp +    registry.hpp +    res_source_info.hpp +    traffic_counter.hpp +    # Block controllers +    block_control.hpp +    ddc_block_control.hpp +    duc_block_control.hpp +    null_block_control.hpp +    radio_control.hpp + +    DESTINATION ${INCLUDE_DIR}/uhd/rfnoc +    COMPONENT headers +) +  add_subdirectory(blocks) -#add_subdirectory(components) +add_subdirectory(core) diff --git a/host/include/uhd/rfnoc/block_ctrl.hpp b/host/include/uhd/rfnoc/block_ctrl.hpp deleted file mode 100644 index c26ee0f85..000000000 --- a/host/include/uhd/rfnoc/block_ctrl.hpp +++ /dev/null @@ -1,36 +0,0 @@ -// -// Copyright 2014 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#ifndef INCLUDED_LIBUHD_RFNOC_BLOCK_CTRL_HPP -#define INCLUDED_LIBUHD_RFNOC_BLOCK_CTRL_HPP - -#include <uhd/rfnoc/sink_block_ctrl_base.hpp> -#include <uhd/rfnoc/source_block_ctrl_base.hpp> - -namespace uhd { namespace rfnoc { - -/*! \brief This is the default implementation of a block_ctrl_base. - * - * For most blocks, this will be a sufficient implementation. All registers - * can be set by sr_write(). The default behaviour of functions is documented - * in uhd::rfnoc::block_ctrl_base. - */ -class UHD_RFNOC_API block_ctrl : public source_block_ctrl_base, -                                 public sink_block_ctrl_base -{ -public: -    // Required macro in RFNoC block classes -    UHD_RFNOC_BLOCK_OBJECT(block_ctrl) - -    // Nothing else here -- all function definitions are in block_ctrl_base, -    // source_block_ctrl_base and sink_block_ctrl_base - -}; /* class block_ctrl*/ - -}} /* namespace uhd::rfnoc */ - -#endif /* INCLUDED_LIBUHD_RFNOC_BLOCK_CTRL_HPP */ diff --git a/host/include/uhd/rfnoc/block_ctrl_base.hpp b/host/include/uhd/rfnoc/block_ctrl_base.hpp deleted file mode 100644 index 7ad2dc67e..000000000 --- a/host/include/uhd/rfnoc/block_ctrl_base.hpp +++ /dev/null @@ -1,436 +0,0 @@ -// -// Copyright 2014-2016 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#ifndef INCLUDED_LIBUHD_BLOCK_CTRL_BASE_HPP -#define INCLUDED_LIBUHD_BLOCK_CTRL_BASE_HPP - -#include <uhd/property_tree.hpp> -#include <uhd/rfnoc/block_id.hpp> -#include <uhd/rfnoc/blockdef.hpp> -#include <uhd/rfnoc/constants.hpp> -#include <uhd/rfnoc/node_ctrl_base.hpp> -#include <uhd/rfnoc/stream_sig.hpp> -#include <uhd/stream.hpp> -#include <uhd/types/sid.hpp> -#include <uhd/types/stream_cmd.hpp> -#include <uhd/types/wb_iface.hpp> -#include <uhd/utils/static.hpp> -#include <stdint.h> -#include <boost/shared_ptr.hpp> - -namespace uhd { namespace rfnoc { -// Forward declarations -class ctrl_iface; -namespace nocscript { -class block_iface; -} - - -// TODO: Move this out of public section -struct make_args_t -{ -    make_args_t(const std::string& key = "") -        : device_index(0), block_name(""), block_key(key) -    { -    } - -    //! A valid interface that allows us to read and write registers -    std::map<size_t, boost::shared_ptr<ctrl_iface> > ctrl_ifaces; -    //! This block's base address (address of block port 0) -    uint32_t base_address; -    //! The device index (or motherboard index). -    size_t device_index; -    //! A property tree for this motherboard. Example: If the root a device's -    //  property tree is /mboards/0, pass a subtree starting at /mboards/0 -    //  to the constructor. -    uhd::property_tree::sptr tree; -    //! The name of the block as it will be addressed -    std::string block_name; -    //! The key of the block, i.e. how it was registered -    std::string block_key; -}; - -//! This macro must be put in the public section of an RFNoC -// block class -#define UHD_RFNOC_BLOCK_OBJECT(class_name) typedef boost::shared_ptr<class_name> sptr; - -//! Shorthand for block constructor -#define UHD_RFNOC_BLOCK_CONSTRUCTOR(CLASS_NAME) \ -    CLASS_NAME##_impl(const make_args_t& make_args) : block_ctrl_base(make_args) - -//! This macro must be placed inside a block implementation file -// after the class definition -#define UHD_RFNOC_BLOCK_REGISTER(CLASS_NAME, BLOCK_NAME)                             \ -    block_ctrl_base::sptr CLASS_NAME##_make(const make_args_t& make_args)            \ -    {                                                                                \ -        return block_ctrl_base::sptr(new CLASS_NAME##_impl(make_args));              \ -    }                                                                                \ -    UHD_STATIC_BLOCK(register_rfnoc_##CLASS_NAME)                                    \ -    {                                                                                \ -        uhd::rfnoc::block_ctrl_base::register_block(&CLASS_NAME##_make, BLOCK_NAME); \ -    } - -/*! \brief Base class for all RFNoC block controller objects. - * - * For RFNoC, block controller objects must be derived from - * uhd::rfnoc::block_ctrl_base. This class provides all functions - * that a block *must* provide. Typically, you would not derive - * a block controller class directly from block_ctrl_base, but - * from a class such as uhd::usrp::rfnoc::source_block_ctrl_base or - * uhd::usrp::rfnoc::sink_block_ctrl_base which extends its functionality. - */ -class UHD_RFNOC_API block_ctrl_base; -class block_ctrl_base : virtual public node_ctrl_base -{ -public: -    /*********************************************************************** -     * Types -     **********************************************************************/ -    typedef boost::shared_ptr<block_ctrl_base> sptr; -    typedef boost::function<sptr(const make_args_t&)> make_t; - -    /*********************************************************************** -     * Factory functions -     **********************************************************************/ - -    /*! Register a block controller class into the discovery and factory system. -     * -     * Note: It is not recommended to call this function directly. -     * Rather, use the UHD_RFNOC_BLOCK_REGISTER() macro, which will set up -     * the discovery and factory system correctly. -     * -     * \param make A factory function that makes a block controller object -     * \param name A unique block name, e.g. 'FFT'. If a block has this block name, -     *             it will use \p make to generate the block controller class. -     */ -    static void register_block(const make_t& make, const std::string& name); - -    /*! -     * \brief Create a block controller class given a NoC-ID or a block name. -     * -     * If a block name is given in \p make_args, it will directly try to -     * generate a block of this type. If no block name is given, it will -     * look up a name using the NoC-ID and use that. -     * If it can't find a suitable block controller class, it will generate -     * a uhd::rfnoc::block_ctrl. However, if a block name *is* specified, -     * it will throw a uhd::runtime_error if this block type is not registered. -     * -     * \param make_args Valid make args. -     * \param noc_id The 64-Bit NoC-ID. -     * \return a shared pointer to a new device instance -     */ -    static sptr make(const make_args_t& make_args, uint64_t noc_id = ~0); - -    /*********************************************************************** -     * Block Communication and Control -     * -     * These functions do not require communication with the FPGA. -     **********************************************************************/ - -    /*! Returns the 16-Bit address for this block. -     */ -    uint32_t get_address(size_t block_port = 0); - -    /*! Returns the unique block ID for this block (e.g. "0/FFT_1"). -     */ -    block_id_t get_block_id() const -    { -        return _block_id; -    }; - -    /*! Shorthand for get_block_id().to_string() -     */ -    std::string unique_id() const -    { -        return _block_id.to_string(); -    }; - -    /*********************************************************************** -     * FPGA control & communication -     **********************************************************************/ - -    /*! Returns a list of valid ports that can be used for sr_write(), sr_read() etc. -     */ -    std::vector<size_t> get_ctrl_ports() const; - -    /*! Allows setting one register on the settings bus. -     * -     * Note: There is no address translation ("memory mapping") necessary. -     * Register 0 is 0, 1 is 1 etc. -     * -     * \param reg The settings register to write to. -     * \param data New value of this register. -     * \param port Port on which to write -     */ -    void sr_write(const uint32_t reg, const uint32_t data, const size_t port = 0); - -    /*! Allows setting one register on the settings bus. -     * -     * Like sr_write(), but takes a register name as argument. -     * -     * \param reg The settings register to write to. -     * \param data New value of this register. -     * \param port Port on which to write -     * \throw uhd::key_error if \p reg is not a valid register name -     * -     */ -    void sr_write(const std::string& reg, const uint32_t data, const size_t port = 0); - -    /*! Allows reading one register on the settings bus (64-Bit version). -     * -     * \param reg The settings register to be read. -     * \param port Port on which to read -     * -     * Returns the readback value. -     */ -    uint64_t sr_read64(const settingsbus_reg_t reg, const size_t port = 0); - -    /*! Allows reading one register on the settings bus (32-Bit version). -     * -     * \param reg The settings register to be read. -     * \param port Port on which to read -     * -     * Returns the readback value. -     */ -    uint32_t sr_read32(const settingsbus_reg_t reg, const size_t port = 0); - -    /*! Allows reading one user-defined register (64-Bit version). -     * -     * This is a shorthand for setting the requested address -     * through sr_write() and then reading SR_READBACK_REG_USER -     * with sr_read64(). -     * -     * \param addr The user register address. -     * \param port Port on which to read -     * \returns the readback value. -     */ -    uint64_t user_reg_read64(const uint32_t addr, const size_t port = 0); - -    /*! Allows reading one user-defined register (64-Bit version). -     * -     * Identical to user_reg_read64(), but takes a register name -     * instead of a numeric address. The register name must be -     * defined in the block definition file. -     * -     * \param reg The user register address. -     * \param port Port on which to read -     * \returns the readback value. -     * \throws uhd::key_error if \p reg is not a valid register name -     */ -    uint64_t user_reg_read64(const std::string& reg, const size_t port = 0); - -    /*! Allows reading one user-defined register (32-Bit version). -     * -     * This is a shorthand for setting the requested address -     * through sr_write() and then reading SR_READBACK_REG_USER -     * with sr_read32(). -     * -     * \param addr The user register address. -     * \param port Port on which to read -     * \returns the readback value. -     */ -    uint32_t user_reg_read32(const uint32_t addr, const size_t port = 0); - -    /*! Allows reading one user-defined register (32-Bit version). -     * -     * Identical to user_reg_read32(), but takes a register name -     * instead of a numeric address. The register name must be -     * defined in the block definition file. -     * -     * \param reg The user register name. -     * \param port Destination port from which to read. -     * \returns the readback value. -     * \throws uhd::key_error if \p reg is not a valid register name -     */ -    uint32_t user_reg_read32(const std::string& reg, const size_t port = 0); - - -    /*! Sets a command time for all future command packets. -     * -     * \throws uhd::assertion_error if the underlying interface does not -     *         actually support timing. -     */ -    void set_command_time(const time_spec_t& time_spec, const size_t port = ANY_PORT); - -    /*! Returns the current command time for all future command packets. -     * -     * \returns the command time as a time_spec_t. -     */ -    time_spec_t get_command_time(const size_t port = 0); - -    /*! Sets a tick rate for the command timebase. -     * -     * \param tick_rate The tick rate in Hz -     * \param port Port -     */ -    void set_command_tick_rate(const double tick_rate, const size_t port = ANY_PORT); - -    /*! Resets the command time. -     * Any command packet after this call will no longer have a time associated -     * with it. -     * -     * \throws uhd::assertion_error if the underlying interface does not -     *         actually support timing. -     */ -    void clear_command_time(const size_t port); - -    /*! Reset block after streaming operation. -     * -     * This does the following: -     * - Reset flow control (sequence numbers etc.) -     * - Clear the list of connected blocks -     * -     * Internally, rfnoc::node_ctrl_base::clear() and _clear() are called -     * (in that order). -     * -     * Between runs, it can be necessary to call this method, -     * or blocks might be left hanging in a streaming state, and can get -     * confused when a new application starts. -     * -     * For custom behaviour, overwrite _clear(). If you do so, you must take -     * take care of resetting flow control yourself. -     * -     * TODO: Find better name (it disconnects, clears FC...) -     */ -    void clear(); - -    /*********************************************************************** -     * Argument handling -     **********************************************************************/ -    /*! Set multiple block args. Calls set_arg() for all individual items. -     * -     * Note that this function will silently ignore any keys in \p args that -     * aren't already registered as block arguments. -     */ -    void set_args(const uhd::device_addr_t& args, const size_t port = 0); - -    //! Set a specific block argument. \p val is converted to the corresponding -    // data type using by looking up its type in the block definition. -    void set_arg(const std::string& key, const std::string& val, const size_t port = 0); - -    //! Direct access to set a block argument. -    template <typename T> -    void set_arg(const std::string& key, const T& val, const size_t port = 0) -    { -        _tree->access<T>(get_arg_path(key, port) / "value").set(val); -    } - -    //! Return all block arguments as a device_addr_t. -    uhd::device_addr_t get_args(const size_t port = 0) const; - -    //! Return a single block argument in string format. -    std::string get_arg(const std::string& key, const size_t port = 0) const; - -    //! Direct access to get a block argument. -    template <typename T> -    T get_arg(const std::string& key, const size_t port = 0) const -    { -        return _tree->access<T>(get_arg_path(key, port) / "value").get(); -    } - -    std::string get_arg_type(const std::string& key, const size_t port = 0) const; - -protected: -    /*********************************************************************** -     * Structors -     **********************************************************************/ -    block_ctrl_base(void){}; // To allow pure virtual (interface) sub-classes -    virtual ~block_ctrl_base(); - -    /*! Constructor. This is only called from the internal block factory! -     * -     * \param make_args All arguments to this constructor are passed in this object. -     *                  Its details are subject to change. Use the -     * UHD_RFNOC_BLOCK_CONSTRUCTOR() macro to set up your block's constructor in a -     * portable fashion. -     */ -    block_ctrl_base(const make_args_t& make_args); - -    /*********************************************************************** -     * Helpers -     **********************************************************************/ -    stream_sig_t _resolve_port_def(const blockdef::port_t& port_def) const; - -    //! Return the property tree path to a block argument \p key on \p port -    uhd::fs_path get_arg_path(const std::string& key, size_t port = 0) const -    { -        return _root_path / "args" / port / key; -    }; - -    //! Get a control interface object for block port \p block_port -    timed_wb_iface::sptr get_ctrl_iface(const size_t block_port); - -    /*********************************************************************** -     * Hooks & Derivables -     **********************************************************************/ - -    //! Override this function if your block does something else -    // than reset register SR_CLEAR_TX_FC. -    virtual void _clear(const size_t port = 0); - -    //! Override this function if your block needs to specially handle -    // setting the command time -    virtual void _set_command_time( -        const time_spec_t& time_spec, const size_t port = ANY_PORT); -    /*********************************************************************** -     * Protected members -     **********************************************************************/ - -    //! Property sub-tree -    uhd::property_tree::sptr _tree; - -    //! Root node of this block's properties -    uhd::fs_path _root_path; - -    //! Block definition (stores info about the block such as ports) -    blockdef::sptr _block_def; - -private: -    //! Helper function to initialize the port definition nodes in the prop tree -    void _init_port_defs(const std::string& direction, -        blockdef::ports_t ports, -        const size_t first_port_index = 0); - -    //! Helper function to initialize the block args (used by ctor only) -    void _init_block_args(); - -    //! Helper to create a lambda to read tick rate -    double get_command_tick_rate(const size_t port); - -    //! Helper to start flushing for this block -    void _start_drain(const size_t port = 0); - -    //! Helper to flush any in-flight packets for this block -    bool _flush(const size_t port = 0); - -    /*********************************************************************** -     * Private members -     **********************************************************************/ -    //! Objects to actually send and receive the commands -    std::map<size_t, boost::shared_ptr<ctrl_iface> > _ctrl_ifaces; -    std::map<size_t, time_spec_t> _cmd_timespecs; -    std::map<size_t, double> _cmd_tickrates; - -    //! The base address of this block (the address of block port 0) -    uint32_t _base_address; - -    //! 64-bit NoC ID of this block -    uint64_t _noc_id; - -    //! noc_shell compat number, as one 64-bit number [major,minor] -    uint64_t _compat_num; - -    //! The (unique) block ID. -    block_id_t _block_id; - -    //! Interface to NocScript parser -    boost::shared_ptr<nocscript::block_iface> _nocscript_iface; -}; /* class block_ctrl_base */ - -}} /* namespace uhd::rfnoc */ - -#endif /* INCLUDED_LIBUHD_BLOCK_CTRL_BASE_HPP */ diff --git a/host/include/uhd/rfnoc/block_id.hpp b/host/include/uhd/rfnoc/block_id.hpp index 77b2ba5a0..106fb394f 100644 --- a/host/include/uhd/rfnoc/block_id.hpp +++ b/host/include/uhd/rfnoc/block_id.hpp @@ -37,7 +37,7 @@ namespace rfnoc {   *   * This class can represent these block IDs.   */ -class UHD_RFNOC_API block_id_t +class UHD_API block_id_t  {  public:      block_id_t(); diff --git a/host/include/uhd/rfnoc/blockdef.hpp b/host/include/uhd/rfnoc/blockdef.hpp index 30c5219e1..e35c8e234 100644 --- a/host/include/uhd/rfnoc/blockdef.hpp +++ b/host/include/uhd/rfnoc/blockdef.hpp @@ -19,7 +19,7 @@ namespace uhd { namespace rfnoc {  /*! Reads and stores block definitions for blocks and components.   */ -class UHD_RFNOC_API blockdef : public boost::enable_shared_from_this<blockdef> +class UHD_API blockdef : public boost::enable_shared_from_this<blockdef>  {  public:      typedef boost::shared_ptr<blockdef> sptr; diff --git a/host/include/uhd/rfnoc/blocks/CMakeLists.txt b/host/include/uhd/rfnoc/blocks/CMakeLists.txt index 08537673a..28e33f651 100644 --- a/host/include/uhd/rfnoc/blocks/CMakeLists.txt +++ b/host/include/uhd/rfnoc/blocks/CMakeLists.txt @@ -1,15 +1,14 @@  # -# Copyright 2014-2016 Ettus Research LLC -# Copyright 2018 Ettus Research, a National Instruments Company +# Copyright 2019 Ettus Research, a National Instruments Company  #  # SPDX-License-Identifier: GPL-3.0-or-later  # -file(GLOB xml_files "*.xml") +file(GLOB yml_files "*.yml")  # We always need this, even when RFNoC is 'disabled'  UHD_INSTALL( -    FILES ${xml_files} +    FILES ${yml_files}      DESTINATION ${PKG_DATA_DIR}/rfnoc/blocks      COMPONENT headers # TODO: Different component  ) diff --git a/host/include/uhd/rfnoc/blocks/addsub.xml b/host/include/uhd/rfnoc/blocks/addsub.xml deleted file mode 100644 index 2412e5022..000000000 --- a/host/include/uhd/rfnoc/blocks/addsub.xml +++ /dev/null @@ -1,50 +0,0 @@ -<!--This defines one NoC-Block.--> -<nocblock> -  <!--The Adder & Subtractor takes inputs from Block Ports 0 & 1 and--> -  <!--outputs the addition / subtraction of the values on Block Ports 0 & 1.--> -  <!--- Block Port 0 + Block Port 1 => Block Port 0--> -  <!--- Block Port 0 - Block Port 1 => Block Port 1--> -  <name>Adder & Subtractor</name> -  <blockname>AddSub</blockname> -  <ids> -    <id revision="0">ADD0</id> -  </ids> -  <!--Order matters. The first listed port is port 0, etc.--> -  <ports> -    <sink> -      <name>in0</name> -      <type>sc16</type> -      <port>0</port> -    </sink> -    <sink> -      <name>in1</name> -      <type>sc16</type> -      <port>1</port> -    </sink> -    <source> -      <name>sum</name> -      <type>sc16</type> -    </source> -    <source> -      <name>diff</name> -      <type>sc16</type> -    </source> -  </ports> -  <!--<components>--> -    <!--<component>--> -      <!--<key revision="1">nocshell</key>--> -    <!--</component>--> -    <!--<component srbase="0">--> -      <!--[>Will look for a component with this key:<]--> -      <!--<key revision="1">componentname</key>--> -    <!--</component>--> -  <!--</components>--> -  <!--<connection>--> -    <!--<source port="0">nocshell</source>--> -    <!--<sink port="0">componentname</sink>--> -  <!--</connection>--> -  <!--<connection>--> -    <!--<source port="0">componentname</source>--> -    <!--<sink port="0">nocshell</sink>--> -  <!--</connection>--> -</nocblock> diff --git a/host/include/uhd/rfnoc/blocks/block.xml b/host/include/uhd/rfnoc/blocks/block.xml deleted file mode 100644 index dfe616c45..000000000 --- a/host/include/uhd/rfnoc/blocks/block.xml +++ /dev/null @@ -1,17 +0,0 @@ -<!--Default XML file--> -<nocblock> -  <name>Block</name> -  <blockname>Block</blockname> -  <ids> -    <id revision="0">FFFFFFFFFFFFFFFF</id> -  </ids> -  <!--One input, one output. If this is used, better have all the info the C++ file.--> -  <ports> -    <sink> -      <name>in</name> -    </sink> -    <source> -      <name>out</name> -    </source> -  </ports> -</nocblock> diff --git a/host/include/uhd/rfnoc/blocks/ddc.xml b/host/include/uhd/rfnoc/blocks/ddc.xml deleted file mode 100644 index 43e325c0e..000000000 --- a/host/include/uhd/rfnoc/blocks/ddc.xml +++ /dev/null @@ -1,154 +0,0 @@ -<!--This defines one NoC-Block.--> -<nocblock> -  <name>Rx DSP (DDC/CORDIC)</name> -  <blockname>DDC</blockname> -  <key>DDC</key> -  <!--There can be several of these:--> -  <ids> -    <id revision="0">DDC0000000000000</id> -  </ids> -  <!-- Registers --> -  <registers> -    <!-- AXI rate change block registers --> -    <setreg> -      <name>N</name> -      <address>128</address> -    </setreg> -    <setreg> -      <name>M</name> -      <address>129</address> -    </setreg> -    <setreg> -      <!-- 1 bit, enable clear user --> -      <name>CONFIG</name> -      <address>130</address> -    </setreg> -    <!-- DDC block registers --> -    <setreg> -      <!-- DDS phase increment word --> -      <name>DDS_FREQ</name> -      <address>132</address> -    </setreg> -    <setreg> -      <!-- Scaling factor to compensate for gain through filters and CORDIC --> -      <name>SCALE_IQ</name> -      <address>133</address> -    </setreg> -    <setreg> -      <!-- DDC control word, 10 bits total, 2 bits for Halfbands, 8 bits for CIC rate --> -      <name>DECIM_WORD</name> -      <address>134</address> -    </setreg> -    <setreg> -      <!-- Real mode, swap IQ --> -      <name>MODE</name> -      <address>135</address> -    </setreg> -    <setreg> -      <!-- Filter coefficients reload --> -      <name>RELOAD</name> -      <address>136</address> -    </setreg> -  </registers> -  <!-- Args --> -  <args> -    <arg> -      <name>freq</name> -      <type>double</type> -      <value>0.0</value> -      <port>0</port> -      <!--<action>--> -          <!--SR_WRITE("CORDIC_FREQ", $cordic_freq)--> -      <!--</action>--> -      <!--FIXME Calculate this properly--> -    </arg> -    <arg> -      <name>input_rate</name> -      <type>double</type> -      <value>1.0</value> -      <port>0</port> -      <check>GE($input_rate, 0.0)</check> -      <check_message>The input rate must be a positive value (in Hz).</check_message> -    </arg> -    <arg> -      <name>output_rate</name> -      <type>double</type> -      <value>1.0</value> -      <port>0</port> -      <check>GE($output_rate, 0.0)</check> -      <check_message>The output rate must be a positive value (in Hz).</check_message> -    </arg> -    <arg> -      <name>fullscale</name> -      <type>double</type> -      <value>1.0</value> -      <port>0</port> -      <check>GE($fullscale, 0.0)</check> -    </arg> -    <arg> -      <name>scalar_correction</name> -      <type>double</type> -      <value>1.0</value> -      <port>0</port> -    </arg> -    <arg> -      <name>freq</name> -      <type>double</type> -      <value>0.0</value> -      <port>1</port> -      <!--<action>--> -          <!--SR_WRITE("CORDIC_FREQ", $cordic_freq)--> -      <!--</action>--> -      <!--FIXME Calculate this properly--> -    </arg> -    <arg> -      <name>input_rate</name> -      <type>double</type> -      <value>1.0</value> -      <port>1</port> -      <check>GE($input_rate, 0.0)</check> -      <check_message>The input rate must be a positive value (in Hz).</check_message> -    </arg> -    <arg> -      <name>output_rate</name> -      <type>double</type> -      <value>1.0</value> -      <port>1</port> -      <check>GE($output_rate, 0.0)</check> -      <check_message>The output rate must be a positive value (in Hz).</check_message> -    </arg> -    <arg> -      <name>fullscale</name> -      <type>double</type> -      <value>1.0</value> -      <port>1</port> -      <check>GE($fullscale, 0.0)</check> -    </arg> -    <arg> -      <name>scalar_correction</name> -      <type>double</type> -      <value>1.0</value> -      <port>1</port> -    </arg> -  </args> -  <!--All the connections to the outside world are listed in 'ports':--> -  <ports> -    <sink> -      <name>in0</name> -      <type>sc16</type> -    </sink> -    <sink> -      <name>in1</name> -      <type>sc16</type> -    </sink> -    <source> -      <name>out0</name> -      <type>sc16</type> -    </source> -    <source> -      <name>out1</name> -      <type>sc16</type> -    </source> -  </ports> -</nocblock> - diff --git a/host/include/uhd/erfnoc/blocks/ddc_1x64.yml b/host/include/uhd/rfnoc/blocks/ddc_1x64.yml index 3d21ea527..3d21ea527 100644 --- a/host/include/uhd/erfnoc/blocks/ddc_1x64.yml +++ b/host/include/uhd/rfnoc/blocks/ddc_1x64.yml diff --git a/host/include/uhd/erfnoc/blocks/ddc_2x64.yml b/host/include/uhd/rfnoc/blocks/ddc_2x64.yml index a79a07c8f..a79a07c8f 100644 --- a/host/include/uhd/erfnoc/blocks/ddc_2x64.yml +++ b/host/include/uhd/rfnoc/blocks/ddc_2x64.yml diff --git a/host/include/uhd/rfnoc/blocks/ddc_eiscat.xml b/host/include/uhd/rfnoc/blocks/ddc_eiscat.xml deleted file mode 100644 index df39ce891..000000000 --- a/host/include/uhd/rfnoc/blocks/ddc_eiscat.xml +++ /dev/null @@ -1,331 +0,0 @@ -<!--This defines one NoC-Block.--> -<nocblock> -  <name>EISCAT Rx DSP (DDC/CORDIC)</name> -  <blockname>DDC</blockname> -  <key>DDC</key> -  <!--There can be several of these:--> -  <ids> -    <id revision="0">DDC5E15CA7000000</id> -  </ids> -  <!-- Registers --> -  <registers> -    <!-- AXI rate change block registers --> -    <setreg> -      <name>N</name> -      <address>128</address> -    </setreg> -    <setreg> -      <name>M</name> -      <address>129</address> -    </setreg> -    <setreg> -      <!-- 1 bit, enable clear user --> -      <name>CONFIG</name> -      <address>130</address> -    </setreg> -    <!-- DDC block registers --> -    <setreg> -      <!-- DDS phase increment word --> -      <name>DDS_FREQ</name> -      <address>132</address> -    </setreg> -    <setreg> -      <!-- Scaling factor to compensate for gain through filters and CORDIC --> -      <name>SCALE_IQ</name> -      <address>133</address> -    </setreg> -    <setreg> -      <!-- DDC control word, 10 bits total, 2 bits for Halfbands, 8 bits for CIC rate --> -      <name>DECIM_WORD</name> -      <address>134</address> -    </setreg> -    <setreg> -      <!-- Real mode, swap IQ --> -      <!-- Real mode = bit 1, swap IQ = bit 0 --> -      <name>MODE</name> -      <address>135</address> -    </setreg> -    <setreg> -      <!-- Filter coefficients reload --> -      <name>RELOAD</name> -      <address>136</address> -    </setreg> -  </registers> -  <!-- Args --> -  <args> -    <arg> -      <name>freq</name> -      <type>double</type> -      <value>0.0</value> -      <port>0</port> -      <!--<action>--> -          <!--SR_WRITE("CORDIC_FREQ", $cordic_freq)--> -      <!--</action>--> -      <!--FIXME Calculate this properly--> -    </arg> -    <arg> -      <name>mode</name> -      <type>int</type> -      <value>2</value> -      <port>0</port> -      <action>SR_WRITE("MODE", $mode)</action> -    </arg> -    <arg> -      <name>input_rate</name> -      <type>double</type> -      <value>1.0</value> -      <port>0</port> -      <check>GE($input_rate, 0.0)</check> -      <check_message>The input rate must be a positive value (in Hz).</check_message> -    </arg> -    <arg> -      <name>output_rate</name> -      <type>double</type> -      <value>1.0</value> -      <port>0</port> -      <check>GE($output_rate, 0.0)</check> -      <check_message>The output rate must be a positive value (in Hz).</check_message> -    </arg> -    <arg> -      <name>fullscale</name> -      <type>double</type> -      <value>1.0</value> -      <port>0</port> -      <check>GE($fullscale, 0.0)</check> -    </arg> -    <arg> -      <name>scalar_correction</name> -      <type>double</type> -      <value>1.0</value> -      <port>0</port> -    </arg> -    <arg> -      <name>freq</name> -      <type>double</type> -      <value>0.0</value> -      <port>1</port> -      <!--<action>--> -          <!--SR_WRITE("CORDIC_FREQ", $cordic_freq)--> -      <!--</action>--> -      <!--FIXME Calculate this properly--> -    </arg> -    <arg> -      <name>mode</name> -      <type>int</type> -      <value>2</value> -      <port>1</port> -      <action>SR_WRITE("MODE", $mode)</action> -    </arg> -    <arg> -      <name>input_rate</name> -      <type>double</type> -      <value>1.0</value> -      <port>1</port> -      <check>GE($input_rate, 0.0)</check> -      <check_message>The input rate must be a positive value (in Hz).</check_message> -    </arg> -    <arg> -      <name>output_rate</name> -      <type>double</type> -      <value>1.0</value> -      <port>1</port> -      <check>GE($output_rate, 0.0)</check> -      <check_message>The output rate must be a positive value (in Hz).</check_message> -    </arg> -    <arg> -      <name>fullscale</name> -      <type>double</type> -      <value>1.0</value> -      <port>1</port> -      <check>GE($fullscale, 0.0)</check> -    </arg> -    <arg> -      <name>scalar_correction</name> -      <type>double</type> -      <value>1.0</value> -      <port>1</port> -    </arg> -    <arg> -      <name>freq</name> -      <type>double</type> -      <value>0.0</value> -      <port>2</port> -      <!--<action>--> -          <!--SR_WRITE("CORDIC_FREQ", $cordic_freq)--> -      <!--</action>--> -      <!--FIXME Calculate this properly--> -    </arg> -    <arg> -      <name>mode</name> -      <type>int</type> -      <value>2</value> -      <port>2</port> -      <action>SR_WRITE("MODE", $mode)</action> -    </arg> -    <arg> -      <name>input_rate</name> -      <type>double</type> -      <value>1.0</value> -      <port>2</port> -      <check>GE($input_rate, 0.0)</check> -      <check_message>The input rate must be a positive value (in Hz).</check_message> -    </arg> -    <arg> -      <name>output_rate</name> -      <type>double</type> -      <value>1.0</value> -      <port>2</port> -      <check>GE($output_rate, 0.0)</check> -      <check_message>The output rate must be a positive value (in Hz).</check_message> -    </arg> -    <arg> -      <name>fullscale</name> -      <type>double</type> -      <value>1.0</value> -      <port>2</port> -      <check>GE($fullscale, 0.0)</check> -    </arg> -    <arg> -      <name>scalar_correction</name> -      <type>double</type> -      <value>1.0</value> -      <port>2</port> -    </arg> -    <arg> -      <name>freq</name> -      <type>double</type> -      <value>0.0</value> -      <port>3</port> -      <!--<action>--> -          <!--SR_WRITE("CORDIC_FREQ", $cordic_freq)--> -      <!--</action>--> -      <!--FIXME Calculate this properly--> -    </arg> -    <arg> -      <name>mode</name> -      <type>int</type> -      <value>2</value> -      <port>3</port> -      <action>SR_WRITE("MODE", $mode)</action> -    </arg> -    <arg> -      <name>input_rate</name> -      <type>double</type> -      <value>1.0</value> -      <port>3</port> -      <check>GE($input_rate, 0.0)</check> -      <check_message>The input rate must be a positive value (in Hz).</check_message> -    </arg> -    <arg> -      <name>output_rate</name> -      <type>double</type> -      <value>1.0</value> -      <port>3</port> -      <check>GE($output_rate, 0.0)</check> -      <check_message>The output rate must be a positive value (in Hz).</check_message> -    </arg> -    <arg> -      <name>fullscale</name> -      <type>double</type> -      <value>1.0</value> -      <port>3</port> -      <check>GE($fullscale, 0.0)</check> -    </arg> -    <arg> -      <name>scalar_correction</name> -      <type>double</type> -      <value>1.0</value> -      <port>3</port> -    </arg> -    <arg> -      <name>freq</name> -      <type>double</type> -      <value>0.0</value> -      <port>4</port> -      <!--<action>--> -          <!--SR_WRITE("CORDIC_FREQ", $cordic_freq)--> -      <!--</action>--> -      <!--FIXME Calculate this properly--> -    </arg> -    <arg> -      <name>mode</name> -      <type>int</type> -      <value>2</value> -      <port>4</port> -      <action>SR_WRITE("MODE", $mode)</action> -    </arg> -    <arg> -      <name>input_rate</name> -      <type>double</type> -      <value>1.0</value> -      <port>4</port> -      <check>GE($input_rate, 0.0)</check> -      <check_message>The input rate must be a positive value (in Hz).</check_message> -    </arg> -    <arg> -      <name>output_rate</name> -      <type>double</type> -      <value>1.0</value> -      <port>4</port> -      <check>GE($output_rate, 0.0)</check> -      <check_message>The output rate must be a positive value (in Hz).</check_message> -    </arg> -    <arg> -      <name>fullscale</name> -      <type>double</type> -      <value>1.0</value> -      <port>4</port> -      <check>GE($fullscale, 0.0)</check> -    </arg> -    <arg> -      <name>scalar_correction</name> -      <type>double</type> -      <value>1.0</value> -      <port>4</port> -    </arg> -  </args> -  <!--All the connections to the outside world are listed in 'ports':--> -  <ports> -    <sink> -      <name>in0</name> -      <type>s16</type> -    </sink> -    <sink> -      <name>in1</name> -      <type>s16</type> -    </sink> -    <sink> -      <name>in2</name> -      <type>s16</type> -    </sink> -    <sink> -      <name>in3</name> -      <type>s16</type> -    </sink> -    <sink> -      <name>in4</name> -      <type>s16</type> -    </sink> -    <source> -      <name>out0</name> -      <type>sc16</type> -    </source> -    <source> -      <name>out1</name> -      <type>sc16</type> -    </source> -    <source> -      <name>out2</name> -      <type>sc16</type> -    </source> -    <source> -      <name>out3</name> -      <type>sc16</type> -    </source> -    <source> -      <name>out4</name> -      <type>sc16</type> -    </source> -  </ports> -</nocblock> - diff --git a/host/include/uhd/rfnoc/blocks/ddc_single.xml b/host/include/uhd/rfnoc/blocks/ddc_single.xml deleted file mode 100644 index 1843adb5b..000000000 --- a/host/include/uhd/rfnoc/blocks/ddc_single.xml +++ /dev/null @@ -1,117 +0,0 @@ -<!--This defines one NoC-Block.--> -<nocblock> -  <name>Rx DSP (DDC/CORDIC)</name> -  <blockname>DDC</blockname> -  <key>DDC</key> -  <!--There can be several of these:--> -  <ids> -    <id revision="0">DDC0000000000001</id> -  </ids> -  <!-- Registers --> -  <registers> -    <!-- AXI rate change block registers --> -    <setreg> -      <name>N</name> -      <address>128</address> -    </setreg> -    <setreg> -      <name>M</name> -      <address>129</address> -    </setreg> -    <setreg> -      <!-- 1 bit, enable clear user --> -      <name>CONFIG</name> -      <address>130</address> -    </setreg> -    <!-- DDC block registers --> -    <setreg> -      <!-- DDS phase increment word --> -      <name>DDS_FREQ</name> -      <address>132</address> -    </setreg> -    <setreg> -      <!-- Scaling factor to compensate for gain through filters and CORDIC --> -      <name>SCALE_IQ</name> -      <address>133</address> -    </setreg> -    <setreg> -      <!-- DDC control word, 10 bits total, 2 bits for Halfbands, 8 bits for CIC rate --> -      <name>DECIM_WORD</name> -      <address>134</address> -    </setreg> -    <setreg> -      <!-- Real mode, swap IQ --> -      <name>MODE</name> -      <address>135</address> -    </setreg> -    <setreg> -      <!-- Filter coefficients reload --> -      <name>RELOAD</name> -      <address>136</address> -    </setreg> -  </registers> -  <!-- Args --> -  <args> -    <arg> -      <name>freq</name> -      <type>double</type> -      <value>0.0</value> -      <port>0</port> -      <!--<action>--> -          <!--SR_WRITE("CORDIC_FREQ", $cordic_freq)--> -      <!--</action>--> -      <!--FIXME Calculate this properly--> -    </arg> -    <arg> -      <name>input_rate</name> -      <type>double</type> -      <value>1.0</value> -      <port>0</port> -      <check>GE($input_rate, 0.0)</check> -      <check_message>The input rate must be a positive value (in Hz).</check_message> -    </arg> -    <arg> -      <name>output_rate</name> -      <type>double</type> -      <value>1.0</value> -      <port>0</port> -      <check>GE($output_rate, 0.0)</check> -      <check_message>The output rate must be a positive value (in Hz).</check_message> -    </arg> -    <arg> -      <name>fullscale</name> -      <type>double</type> -      <value>1.0</value> -      <port>0</port> -      <check>GE($fullscale, 0.0)</check> -    </arg> -    <arg> -      <name>scalar_correction</name> -      <type>double</type> -      <value>1.0</value> -      <port>0</port> -    </arg> -    <arg> -      <name>freq</name> -      <type>double</type> -      <value>0.0</value> -      <port>1</port> -      <!--<action>--> -          <!--SR_WRITE("CORDIC_FREQ", $cordic_freq)--> -      <!--</action>--> -      <!--FIXME Calculate this properly--> -    </arg> -  </args> -  <!--All the connections to the outside world are listed in 'ports':--> -  <ports> -    <sink> -      <name>in0</name> -      <type>sc16</type> -    </sink> -    <source> -      <name>out0</name> -      <type>sc16</type> -    </source> -  </ports> -</nocblock> - diff --git a/host/include/uhd/rfnoc/blocks/debug.xml b/host/include/uhd/rfnoc/blocks/debug.xml deleted file mode 100644 index 9210b8c2c..000000000 --- a/host/include/uhd/rfnoc/blocks/debug.xml +++ /dev/null @@ -1,49 +0,0 @@ -<nocblock> -  <name>Debug</name> -  <blockname>Debug</blockname> -  <!--There can be several of these:--> -  <ids> -    <id revision="0">DEB1200000000000</id> -  </ids> -  <!-- Registers --> -  <registers> -    <setreg> -      <name>CONFIG</name> -      <address>128</address> -    </setreg> -    <setreg> -      <name>PAYLOAD_SIZE</name> -      <address>129</address> -    </setreg> -  </registers> -  <!-- Args --> -  <args> -    <arg> -      <name>config</name> -      <type>int</type> -      <value>0</value> -      <action>SR_WRITE("CONFIG", $config)</action> -    </arg> -    <arg> -      <name>spp</name> -      <type>int</type> -      <value>64</value> -      <action>SR_WRITE("PAYLOAD_SIZE", $spp)</action> -    </arg> -  </args> -  <!-- Ports --> -  <ports> -    <sink> -      <name>in</name> -      <type>sc16</type> -    </sink> -    <source> -      <name>out</name> -      <type>sc16</type> -    </source> -    <source> -      <name>stats</name> -      <type>sc16</type> -    </source> -  </ports> -</nocblock> diff --git a/host/include/uhd/rfnoc/blocks/digital_gain.xml b/host/include/uhd/rfnoc/blocks/digital_gain.xml deleted file mode 100644 index 8d22dec04..000000000 --- a/host/include/uhd/rfnoc/blocks/digital_gain.xml +++ /dev/null @@ -1,39 +0,0 @@ -<nocblock> -  <name>Digital Gain</name> -  <blockname>DigitalGain</blockname> -  <!--There can be several of these:--> -  <ids> -    <id revision="0">B160</id> -  </ids> -  <!-- Registers --> -  <registers> -    <setreg> -      <name>GAIN</name> -      <address>128</address> -    </setreg> -  </registers> -  <!-- Args --> -  <args> -    <arg> -      <name>gain</name> -      <type>double</type> -      <value>1.0</value> -      <check>GE($gain, 0.0) AND LE($gain, 32767.0)</check> -      <check_message>Invalid gain.</check_message> -      <action> -        SR_WRITE("GAIN", IROUND($gain)) -      </action> -    </arg> -  </args> -  <!-- Ports --> -  <ports> -    <sink> -      <name>in0</name> -      <type>sc16</type> -    </sink> -    <source> -      <name>out0</name> -      <type>sc16</type> -    </source> -  </ports> -</nocblock> diff --git a/host/include/uhd/rfnoc/blocks/dma_fifo.xml b/host/include/uhd/rfnoc/blocks/dma_fifo.xml deleted file mode 100644 index 0de791b22..000000000 --- a/host/include/uhd/rfnoc/blocks/dma_fifo.xml +++ /dev/null @@ -1,64 +0,0 @@ -<!--This defines one NoC-Block.--> -<nocblock> -  <name>DMA FIFO</name> -  <blockname>DmaFIFO</blockname> -  <key>DmaFIFO</key> -  <!--There can be several of these:--> -  <ids> -    <id revision="0">F1F0D00000000000</id> -  </ids> -  <!-- Registers --> -  <registers> -  </registers> -  <!-- Args --> -  <args> -    <arg> -      <name>base_addr</name> -      <type>int</type> -      <!--<value>0</value>--> -      <port>0</port> -      <check>EQUAL($base_addr, 0) OR IS_PWR_OF_2($base_addr)</check> -      <check_message>The base address must be 0 or a positive power of 2.</check_message> -    </arg> -    <arg> -      <name>depth</name> -      <type>int</type> -      <!--<value>33554432</value>--> -      <port>0</port> -      <check>IS_PWR_OF_2($depth)</check> -      <check_message>The FIFO depth must be a positive power of 2.</check_message> -    </arg> -    <arg> -      <name>base_addr</name> -      <type>int</type> -      <!--<value>33554432</value>--> -      <port>1</port> -      <check>EQUAL($base_addr, 0) OR IS_PWR_OF_2($base_addr)</check> -      <check_message>The base address must be 0 or a positive power of 2.</check_message> -    </arg> -    <arg> -      <name>depth</name> -      <type>int</type> -      <!--<value>33554432</value>--> -      <port>1</port> -      <check>IS_PWR_OF_2($depth)</check> -      <check_message>The FIFO depth must be a positive power of 2.</check_message> -    </arg> -  </args> -  <!--All the connections to the outside world are listed in 'ports':--> -  <ports> -    <sink> -      <name>in0</name> -    </sink> -    <sink> -      <name>in1</name> -    </sink> -    <source> -      <name>out0</name> -    </source> -    <source> -      <name>out1</name> -    </source> -  </ports> -</nocblock> - diff --git a/host/include/uhd/rfnoc/blocks/dma_fifo_x4.xml b/host/include/uhd/rfnoc/blocks/dma_fifo_x4.xml deleted file mode 100644 index b02e7c8c9..000000000 --- a/host/include/uhd/rfnoc/blocks/dma_fifo_x4.xml +++ /dev/null @@ -1,109 +0,0 @@ -<!--This defines one NoC-Block.--> -<nocblock> -  <name>DMA FIFO</name> -  <blockname>DmaFIFO</blockname> -  <key>DmaFIFO</key> -  <!--There can be several of these:--> -  <ids> -    <id revision="0">F1F0D00000000004</id> -  </ids> -  <!-- Registers --> -  <registers> -  </registers> -  <!-- Args --> -  <args> -    <arg> -      <name>base_addr</name> -      <type>int</type> -      <!--<value>0</value>--> -      <port>0</port> -      <check>EQUAL($base_addr, 0) OR IS_PWR_OF_2($base_addr)</check> -      <check_message>The base address must be 0 or a positive power of 2.</check_message> -    </arg> -    <arg> -      <name>depth</name> -      <type>int</type> -      <!--<value>33554432</value>--> -      <port>0</port> -      <check>IS_PWR_OF_2($depth)</check> -      <check_message>The FIFO depth must be a positive power of 2.</check_message> -    </arg> -    <arg> -      <name>base_addr</name> -      <type>int</type> -      <!--<value>33554432</value>--> -      <port>1</port> -      <check>EQUAL($base_addr, 0) OR IS_PWR_OF_2($base_addr)</check> -      <check_message>The base address must be 0 or a positive power of 2.</check_message> -    </arg> -    <arg> -      <name>depth</name> -      <type>int</type> -      <!--<value>33554432</value>--> -      <port>1</port> -      <check>IS_PWR_OF_2($depth)</check> -      <check_message>The FIFO depth must be a positive power of 2.</check_message> -    </arg> -    <arg> -      <name>base_addr</name> -      <type>int</type> -      <!--<value>67108864</value>--> -      <port>2</port> -      <check>EQUAL($base_addr, 0) OR IS_PWR_OF_2($base_addr)</check> -      <check_message>The base address must be 0 or a positive power of 2.</check_message> -    </arg> -    <arg> -      <name>depth</name> -      <type>int</type> -      <!--<value>33554432</value>--> -      <port>2</port> -      <check>IS_PWR_OF_2($depth)</check> -      <check_message>The FIFO depth must be a positive power of 2.</check_message> -    </arg> -    <arg> -      <name>base_addr</name> -      <type>int</type> -      <!--<value>100663296</value>--> -      <port>3</port> -      <check>EQUAL($base_addr, 0) OR IS_PWR_OF_2($base_addr)</check> -      <check_message>The base address must be 0 or a positive power of 2.</check_message> -    </arg> -    <arg> -      <name>depth</name> -      <type>int</type> -      <!--<value>33554432</value>--> -      <port>3</port> -      <check>IS_PWR_OF_2($depth)</check> -      <check_message>The FIFO depth must be a positive power of 2.</check_message> -    </arg> - -  </args> -  <!--All the connections to the outside world are listed in 'ports':--> -  <ports> -    <sink> -      <name>in0</name> -    </sink> -    <sink> -      <name>in1</name> -    </sink> -    <sink> -      <name>in2</name> -    </sink> -    <sink> -      <name>in3</name> -    </sink> -    <source> -      <name>out0</name> -    </source> -    <source> -      <name>out1</name> -    </source> -    <source> -      <name>out2</name> -    </source> -    <source> -      <name>out3</name> -    </source> -  </ports> -</nocblock> - diff --git a/host/include/uhd/rfnoc/blocks/duc.xml b/host/include/uhd/rfnoc/blocks/duc.xml deleted file mode 100644 index ea83942da..000000000 --- a/host/include/uhd/rfnoc/blocks/duc.xml +++ /dev/null @@ -1,145 +0,0 @@ -<!--This defines one NoC-Block.--> -<nocblock> -  <name>Tx DSP (DUC/CORDIC)</name> -  <blockname>DUC</blockname> -  <key>DUC</key> -  <!--There can be several of these:--> -  <ids> -    <id revision="0">D0C0000000000002</id> -  </ids> -  <!-- Registers --> -  <registers> -    <!-- AXI rate change block registers --> -    <setreg> -      <name>N</name> -      <address>128</address> -    </setreg> -    <setreg> -      <name>M</name> -      <address>129</address> -    </setreg> -    <setreg> -      <!-- 1 bit, enable clear user --> -      <name>CONFIG</name> -      <address>130</address> -    </setreg> -    <!-- DUC block registers --> -    <setreg> -      <name>INTERP_WORD</name> <!--Includes the half-bands and the CIC--> -      <address>131</address> -    </setreg> -    <setreg> -      <name>DDS_FREQ</name> -      <address>132</address> -    </setreg> -    <setreg> -      <name>SCALE_IQ</name> -      <address>133</address> -    </setreg> -  </registers> -  <!-- Args --> -  <args> -    <arg> -      <name>freq</name> -      <type>double</type> -      <value>0.0</value> -      <port>0</port> -      <!--<action>--> -          <!--SR_WRITE("CORDIC_FREQ", $cordic_freq)--> -      <!--</action>--> -      <!--FIXME Calculate this properly--> -    </arg> -    <arg> -      <name>input_rate</name> -      <type>double</type> -      <value>1.0</value> -      <port>0</port> -      <check>GE($input_rate, 0.0)</check> -      <check_message>The input rate must be a positive value (in Hz).</check_message> -    </arg> -    <arg> -      <name>output_rate</name> -      <type>double</type> -      <value>1.0</value> -      <port>0</port> -      <check>GE($output_rate, 0.0)</check> -      <check_message>The output rate must be a positive value (in Hz).</check_message> -    </arg> -    <arg> -      <name>fullscale</name> -      <type>double</type> -      <value>1.0</value> -      <port>0</port> -      <check>GE($fullscale, 0.0)</check> -      <check_message>The output rate must be a positive value (in Hz).</check_message> -      <!--FIXME Calculate this properly--> -    </arg> -    <arg> -      <name>scalar_correction</name> -      <type>double</type> -      <value>1.0</value> -      <port>0</port> -    </arg> -    <arg> -      <name>freq</name> -      <type>double</type> -      <value>0.0</value> -      <port>1</port> -      <!--<action>--> -          <!--SR_WRITE("CORDIC_FREQ", $cordic_freq)--> -      <!--</action>--> -      <!--FIXME Calculate this properly--> -    </arg> -    <arg> -      <name>input_rate</name> -      <type>double</type> -      <value>1.0</value> -      <port>1</port> -      <check>GE($input_rate, 0.0)</check> -      <check_message>The input rate must be a positive value (in Hz).</check_message> -    </arg> -    <arg> -      <name>output_rate</name> -      <type>double</type> -      <value>1.0</value> -      <port>1</port> -      <check>GE($output_rate, 0.0)</check> -      <check_message>The output rate must be a positive value (in Hz).</check_message> -    </arg> -    <arg> -      <name>fullscale</name> -      <type>double</type> -      <value>1.0</value> -      <port>1</port> -      <check>GE($fullscale, 0.0)</check> -      <check_message>The output rate must be a positive value (in Hz).</check_message> -      <!--FIXME Calculate this properly--> -    </arg> -    <arg> -      <name>scalar_correction</name> -      <type>double</type> -      <value>1.0</value> -      <port>1</port> -    </arg> -</args> -  <!--All the connections to the outside world are listed in 'ports':--> -  <ports> -    <sink> -      <name>in0</name> -      <type>sc16</type> -    </sink> -    <source> -      <name>out0</name> -      <type>sc16</type> -    </source> -    <sink> -      <name>in1</name> -      <type>sc16</type> -    </sink> -    <source> -      <name>out1</name> -      <type>sc16</type> -    </source> -  </ports> -</nocblock> - diff --git a/host/include/uhd/erfnoc/blocks/duc_1x64.yml b/host/include/uhd/rfnoc/blocks/duc_1x64.yml index 515f426f2..515f426f2 100644 --- a/host/include/uhd/erfnoc/blocks/duc_1x64.yml +++ b/host/include/uhd/rfnoc/blocks/duc_1x64.yml diff --git a/host/include/uhd/erfnoc/blocks/duc_2x64.yml b/host/include/uhd/rfnoc/blocks/duc_2x64.yml index fd8add930..fd8add930 100644 --- a/host/include/uhd/erfnoc/blocks/duc_2x64.yml +++ b/host/include/uhd/rfnoc/blocks/duc_2x64.yml diff --git a/host/include/uhd/rfnoc/blocks/duc_single.xml b/host/include/uhd/rfnoc/blocks/duc_single.xml deleted file mode 100644 index 235788989..000000000 --- a/host/include/uhd/rfnoc/blocks/duc_single.xml +++ /dev/null @@ -1,96 +0,0 @@ -<!--This defines one NoC-Block.--> -<nocblock> -  <name>Tx DSP (DUC/CORDIC)</name> -  <blockname>DUC</blockname> -  <key>DUC</key> -  <!--There can be several of these:--> -  <ids> -    <id revision="0">D0C0000000000000</id> -  </ids> -  <!-- Registers --> -  <registers> -    <!-- AXI rate change block registers --> -    <setreg> -      <name>N</name> -      <address>128</address> -    </setreg> -    <setreg> -      <name>M</name> -      <address>129</address> -    </setreg> -    <setreg> -      <!-- 1 bit, enable clear user --> -      <name>CONFIG</name> -      <address>130</address> -    </setreg> -    <!-- DUC block registers --> -    <setreg> -      <name>INTERP_WORD</name> <!--Includes the half-bands and the CIC--> -      <address>131</address> -    </setreg> -    <setreg> -      <name>DDS_FREQ</name> -      <address>132</address> -    </setreg> -    <setreg> -      <name>SCALE_IQ</name> -      <address>133</address> -    </setreg> -  </registers> -  <!-- Args --> -  <args> -    <arg> -      <name>freq</name> -      <type>double</type> -      <value>0.0</value> -      <port>0</port> -      <!--<action>--> -          <!--SR_WRITE("CORDIC_FREQ", $cordic_freq)--> -      <!--</action>--> -      <!--FIXME Calculate this properly--> -    </arg> -    <arg> -      <name>input_rate</name> -      <type>double</type> -      <value>1.0</value> -      <port>0</port> -      <check>GE($input_rate, 0.0)</check> -      <check_message>The input rate must be a positive value (in Hz).</check_message> -    </arg> -    <arg> -      <name>output_rate</name> -      <type>double</type> -      <value>1.0</value> -      <port>0</port> -      <check>GE($output_rate, 0.0)</check> -      <check_message>The output rate must be a positive value (in Hz).</check_message> -    </arg> -    <arg> -      <name>fullscale</name> -      <type>double</type> -      <value>1.0</value> -      <port>0</port> -      <check>GE($fullscale, 0.0)</check> -      <check_message>The output rate must be a positive value (in Hz).</check_message> -      <!--FIXME Calculate this properly--> -    </arg> -    <arg> -      <name>scalar_correction</name> -      <type>double</type> -      <value>1.0</value> -      <port>0</port> -    </arg> -</args> -  <!--All the connections to the outside world are listed in 'ports':--> -  <ports> -    <sink> -      <name>in</name> -      <type>sc16</type> -    </sink> -    <source> -      <name>out</name> -      <type>sc16</type> -    </source> -  </ports> -</nocblock> - diff --git a/host/include/uhd/rfnoc/blocks/fft.xml b/host/include/uhd/rfnoc/blocks/fft.xml deleted file mode 100644 index af51d0ddb..000000000 --- a/host/include/uhd/rfnoc/blocks/fft.xml +++ /dev/null @@ -1,147 +0,0 @@ -<!--This defines one NoC-Block.--> -<nocblock> -  <name>FFT</name> -  <blockname>FFT</blockname> -  <!--There can be several of these:--> -  <ids> -    <id revision="0">FF70</id> -  </ids> -  <!-- Registers --> -  <registers> -    <!--Note: AXI config bus uses 129 & 130--> -    <setreg> -      <name>FFT_RESET</name> -      <address>131</address> -    </setreg> -    <setreg> -      <name>FFT_SIZE_LOG2</name> -      <address>132</address> -    </setreg> -    <setreg> -      <name>MAGNITUDE_OUT</name> -      <address>133</address> -    </setreg> -    <setreg> -      <name>FFT_DIRECTION</name> -      <address>134</address> -    </setreg> -    <setreg> -      <name>FFT_SCALING</name> -      <address>135</address> -    </setreg> -    <setreg> -      <name>FFT_SHIFT_CONFIG</name> -      <address>136</address> -    </setreg> -    <readback> -      <name>RB_FFT_RESET</name> -      <address>0</address> -    </readback> -    <readback> -      <name>RB_MAGNITUDE_OUT</name> -      <address>1</address> -    </readback> -    <readback> -      <name>RB_FFT_SIZE_LOG2</name> -      <address>2</address> -    </readback> -    <readback> -      <name>RB_FFT_DIRECTION</name> -      <address>3</address> -    </readback> -    <readback> -      <name>RB_FFT_SCALING</name> -      <address>4</address> -    </readback> -    <readback> -      <name>RB_FFT_SHIFT_CONFIG</name> -      <address>5</address> -    </readback> -  </registers> -  <!-- Args --> -  <args> -    <arg> -      <name>spp</name> -      <type>int</type> -      <value>256</value> -      <check>GE($spp, 16) AND LE($spp, 4096) AND IS_PWR_OF_2($spp)</check> -      <check_message>FFT size must be in [16, 4096] and a power of two.</check_message> -      <action>SR_WRITE("FFT_SIZE_LOG2", LOG2($spp))</action> -    </arg> -    <arg> -      <name>shift</name> -      <type>string</type> -      <value>normal</value> -      <check>EQUAL($shift, "normal") OR EQUAL($shift, "reverse") OR EQUAL($shift, "natural")</check> -      <check_message>FFT direction must be either "normal", "reverse", or "natural".</check_message> -      <action> -          IF(EQUAL($shift, "normal"),  SR_WRITE("FFT_SHIFT_CONFIG", 0)) OR -          IF(EQUAL($shift, "reverse"), SR_WRITE("FFT_SHIFT_CONFIG", 1)) OR -          IF(EQUAL($shift, "natural"), SR_WRITE("FFT_SHIFT_CONFIG", 2)) -      </action> -    </arg> -    <arg> -      <name>direction</name> -      <type>string</type> -      <value>forward</value> -      <check>EQUAL($direction, "forward") OR EQUAL($direction, "reverse")</check> -      <check_message>FFT direction must be either "forward" or "reverse".</check_message> -      <action> -          IF(EQUAL($direction, "forward"),  SR_WRITE("FFT_DIRECTION", 1)) OR -          IF(EQUAL($direction, "reverse"), SR_WRITE("FFT_DIRECTION", 0)) -      </action> -    </arg> -    <arg> -      <name>scaling</name> -      <type>int</type> -      <!--scaling per radix-4 butterfly--> -      <value>1706</value> -      <action>SR_WRITE("FFT_SCALING", $scaling)</action> -    </arg> -    <arg> -      <name>otype</name> -      <type>string</type> -      <value>sc16</value> -      <check>EQUAL($otype, "sc16")</check> -      <check_message>Output data type must be sc16.</check_message> -      <!--TODO: Check against mag-out value (requires GET() function) --> -    </arg> -    <arg> -      <name>reset</name> -      <type>int</type> -      <value>1</value> -      <action> -          IF(NOT(EQUAL($reset, 0)), SR_WRITE("FFT_RESET", 1) AND SR_WRITE("FFT_RESET", 0)) -      </action> -      <!--TODO: Set to zero after setting, add publisher--> -    </arg> -    <arg> -      <name>magnitude_out</name> -      <type>string</type> -      <value>COMPLEX</value> -      <check>EQUAL($magnitude_out, "COMPLEX") OR EQUAL($magnitude_out, "MAGNITUDE") OR EQUAL($magnitude_out, "MAGNITUDE_SQUARED")</check> -      <check_message>Output format must be one of: COMPLEX, MAGNITUDE, MAGNITUDE_SQUARED.</check_message> -      <action> -          IF(EQUAL($magnitude_out, "COMPLEX"),           SR_WRITE("MAGNITUDE_OUT", 0)) OR -          IF(EQUAL($magnitude_out, "MAGNITUDE"),         SR_WRITE("MAGNITUDE_OUT", 1)) OR -          IF(EQUAL($magnitude_out, "MAGNITUDE_SQUARED"), SR_WRITE("MAGNITUDE_OUT", 2)) -      </action> -      <!--TODO: add publisher--> -    </arg> -  </args> -  <!--All the connections to the outside world are listed in 'ports':--> -  <ports> -    <sink> -      <name>in</name> -      <type>sc16</type> -      <vlen>$spp</vlen> -      <pkt_size>%vlen</pkt_size> -    </sink> -    <source> -      <name>out</name> -      <type>$otype</type> <!--TODO make this dependent on the output type --> -      <vlen>$spp</vlen> -      <pkt_size>%vlen</pkt_size> -    </source> -  </ports> -</nocblock> diff --git a/host/include/uhd/rfnoc/blocks/fifo.xml b/host/include/uhd/rfnoc/blocks/fifo.xml deleted file mode 100644 index 07b01c6ea..000000000 --- a/host/include/uhd/rfnoc/blocks/fifo.xml +++ /dev/null @@ -1,36 +0,0 @@ -<!--This defines one NoC-Block.--> -<nocblock> -  <name>FIFO</name> -  <blockname>FIFO</blockname> -  <!--Use default block controller--> -  <key>Block</key> -  <!--There can be several of these:--> -  <ids> -    <id revision="0">F1F00000</id> -  </ids> -  <ports> -    <sink> -      <name>in0</name> -    </sink> -    <source> -      <name>out0</name> -    </source> -  </ports> -  <!--<components>--> -    <!--<component>--> -      <!--<key revision="1">nocshell</key>--> -    <!--</component>--> -    <!--<component srbase="0">--> -      <!--[>Will look for a component with this key:<]--> -      <!--<key revision="1">componentname</key>--> -    <!--</component>--> -  <!--</components>--> -  <!--<connection>--> -    <!--<source port="0">nocshell</source>--> -    <!--<sink port="0">componentname</sink>--> -  <!--</connection>--> -  <!--<connection>--> -    <!--<source port="0">componentname</source>--> -    <!--<sink port="0">nocshell</sink>--> -  <!--</connection>--> -</nocblock> diff --git a/host/include/uhd/rfnoc/blocks/fir.xml b/host/include/uhd/rfnoc/blocks/fir.xml deleted file mode 100644 index 9a97e3a84..000000000 --- a/host/include/uhd/rfnoc/blocks/fir.xml +++ /dev/null @@ -1,19 +0,0 @@ -<!--This defines one NoC-Block.--> -<nocblock> -  <name>FIR Filter</name> -  <blockname>FIR</blockname> -  <!--There can be several of these:--> -  <ids> -    <id revision="0">F112</id> -  </ids> -  <ports> -    <sink> -      <name>in</name> -      <type>sc16</type> -    </sink> -    <source> -      <name>out</name> -      <type>sc16</type> -    </source> -  </ports> -</nocblock> diff --git a/host/include/uhd/rfnoc/blocks/fosphor.xml b/host/include/uhd/rfnoc/blocks/fosphor.xml deleted file mode 100644 index b1db73192..000000000 --- a/host/include/uhd/rfnoc/blocks/fosphor.xml +++ /dev/null @@ -1,201 +0,0 @@ -<!--This defines one NoC-Block.--> -<nocblock> -  <name>fosphor</name> -  <blockname>fosphor</blockname> -  <!--There can be several of these:--> -  <ids> -    <id revision="0">666F</id> -  </ids> -  <!-- Registers --> -  <registers> -    <setreg> -      <name>ENABLE</name> -      <address>160</address> -    </setreg> -    <setreg> -      <name>CLEAR</name> -      <address>161</address> -    </setreg> -    <setreg> -      <name>RANDOM</name> -      <address>162</address> -    </setreg> -    <setreg> -      <name>DECIM</name> -      <address>168</address> -    </setreg> -    <setreg> -      <name>OFFSET</name> -      <address>170</address> -    </setreg> -    <setreg> -      <name>SCALE</name> -      <address>171</address> -    </setreg> -    <setreg> -      <name>TRISE</name> -      <address>172</address> -    </setreg> -    <setreg> -      <name>TDECAY</name> -      <address>173</address> -    </setreg> -    <setreg> -      <name>ALPHA</name> -      <address>174</address> -    </setreg> -    <setreg> -      <name>EPSILON</name> -      <address>175</address> -    </setreg> -    <setreg> -      <name>WF_CTRL</name> -      <address>176</address> -    </setreg> -    <setreg> -      <name>WF_DECIM</name> -      <address>177</address> -    </setreg> -  </registers> -  <!-- Args --> -  <args> -    <arg> -      <name>spp</name> -      <type>int</type> -      <value>1024</value> -    </arg> -    <arg> -      <name>enable</name> -      <type>int</type> -      <value>3</value> -      <check>GE($enable, 0) AND LE($enable, 3)</check> -      <check_message>"fosphor enable value must be within [0, 3]"</check_message> -      <action>SR_WRITE("ENABLE", $enable)</action> -    </arg> -    <arg> -      <name>clear</name> -      <type>int</type> -      <action>IF(NOT(EQUAL($clear, 0)), SR_WRITE("CLEAR", $clear))</action> -    </arg> -    <arg> -      <name>random</name> -      <type>int</type> -      <value>3</value> -      <check>GE($random, 0) AND LE($random, 3)</check> -      <check_message>"fosphor random mode value must be within [0, 3]"</check_message> -      <action>SR_WRITE("RANDOM", $random)</action> -    </arg> -    <arg> -      <name>decim</name> -      <type>int</type> -      <value>2</value> -      <check>GE($decim, 2) AND LE($decim, 1024)</check> -      <check_message>fosphor decim constant must be within [2, 1024]</check_message> -      <action>SR_WRITE("DECIM", ADD($decim, -2))</action> -    </arg> -    <arg> -      <name>offset</name> -      <type>int</type> -      <value>0</value> -      <check>GE($offset, 0) AND LE($offset, 65536)</check> -      <check_message>"fosphor offset value must be within [0, 65535]"</check_message> -      <action>SR_WRITE("OFFSET", $offset)</action> -    </arg> -    <arg> -      <name>scale</name> -      <type>int</type> -      <value>256</value> -      <check>GE($scale, 0) AND LE($scale, 65536)</check> -      <check_message>"fosphor scale value must be within [0, 65535]"</check_message> -      <action>SR_WRITE("SCALE", $scale)</action> -    </arg> -    <arg> -      <name>trise</name> -      <type>int</type> -      <value>4096</value> -      <check>GE($trise, 0) AND LE($trise, 65536)</check> -      <check_message>"fosphor trise value must be within [0, 65535]"</check_message> -      <action>SR_WRITE("TRISE", $trise)</action> -    </arg> -    <arg> -      <name>tdecay</name> -      <type>int</type> -      <value>16384</value> -      <check>GE($tdecay, 0) AND LE($tdecay, 65536)</check> -      <check_message>"fosphor tdecay value must be within [0, 65535]"</check_message> -      <action>SR_WRITE("TDECAY", $tdecay)</action> -    </arg> -    <arg> -      <name>alpha</name> -      <type>int</type> -      <value>65280</value> -      <check>GE($alpha, 0) AND LE($alpha, 65536)</check> -      <check_message>"fosphor alpha value must be within [0, 65535]"</check_message> -      <action>SR_WRITE("ALPHA", $alpha)</action> -    </arg> -    <arg> -      <name>epsilon</name> -      <type>int</type> -      <value>1</value> -      <check>GE($epsilon, 0) AND LE($epsilon, 65536)</check> -      <check_message>"fosphor epsilon value must be within [0, 65535]"</check_message> -      <action>SR_WRITE("EPSILON", $epsilon)</action> -    </arg> -    <arg> -      <name>wf_ctrl</name> -      <type>int</type> -      <value>0</value> -      <check>GE($wf_ctrl, 0) AND LE($enable, 255)</check> -      <check_message>"fosphor wf_ctrl value must be within [0, 255]"</check_message> -      <action>SR_WRITE("WF_CTRL", $wf_ctrl)</action> -    </arg> -    <arg> -      <name>wf_decim</name> -      <type>int</type> -      <value>8</value> -      <check>GE($wf_decim, 2) AND LE($wf_decim, 256)</check> -      <check_message>fosphor wf_decim constant must be within [2, 256]</check_message> -      <action>SR_WRITE("WF_DECIM", ADD($wf_decim, -2))</action> -    </arg> -  </args> -  <!--All the connections to the outside world are listed in 'ports':--> -  <ports> -    <sink> -      <name>in</name> -      <type>sc16</type> -      <vlen>$spp</vlen> -      <pkt_size>%vlen</pkt_size> -    </sink> -    <source> -      <name>out_hist</name> -      <type>u8</type> -      <vlen>$spp</vlen> -      <pkt_size>%vlen</pkt_size> -      <port>0</port> -    </source> -    <source> -      <name>out_wf</name> -      <type>u8</type> -      <vlen>$spp</vlen> -      <pkt_size>%vlen</pkt_size> -      <port>1</port> -    </source> -  </ports> -  <!--<components>--> -    <!--<component>--> -      <!--<key revision="1">nocshell</key>--> -    <!--</component>--> -    <!--<component srbase="0">--> -      <!--[>Will look for a component with this key:<]--> -      <!--<key revision="1">componentname</key>--> -    <!--</component>--> -  <!--</components>--> -  <!--<connection>--> -    <!--<source port="0">nocshell</source>--> -    <!--<sink port="0">componentname</sink>--> -  <!--</connection>--> -  <!--<connection>--> -    <!--<source port="0">componentname</source>--> -    <!--<sink port="0">nocshell</sink>--> -  <!--</connection>--> -</nocblock> diff --git a/host/include/uhd/rfnoc/blocks/keep_one_in_n.xml b/host/include/uhd/rfnoc/blocks/keep_one_in_n.xml deleted file mode 100644 index 5a99685de..000000000 --- a/host/include/uhd/rfnoc/blocks/keep_one_in_n.xml +++ /dev/null @@ -1,55 +0,0 @@ -<!--This defines one NoC-Block.--> -<nocblock> -  <name>Keep One in N</name> -  <blockname>KeepOneInN</blockname> -  <doc> -    Block controller for the Keep One in N RFNoC block. - -    For every N packets received, this block will output a single packet. -    - One input / output block port -    - N up to 65535 -  </doc> -  <!--There can be several of these:--> -  <ids> -    <id revision="0">0246</id> -  </ids> -  <registers> -    <setreg> -      <name>SR_N</name> -      <address>129</address> -    </setreg> -  </registers> -  <args> -    <arg> -      <name>n</name> -      <type>int</type> -      <value>256</value> -      <action>SR_WRITE("SR_N", $n)</action> -    </arg> -  </args> -  <ports> -    <sink> -      <name>in</name> -    </sink> -    <source> -      <name>out</name> -    </source> -  </ports> -  <!--<components>--> -    <!--<component>--> -      <!--<key revision="1">nocshell</key>--> -    <!--</component>--> -    <!--<component srbase="0">--> -      <!--[>Will look for a component with this key:<]--> -      <!--<key revision="1">componentname</key>--> -    <!--</component>--> -  <!--</components>--> -  <!--<connection>--> -    <!--<source port="0">nocshell</source>--> -    <!--<sink port="0">componentname</sink>--> -  <!--</connection>--> -  <!--<connection>--> -    <!--<source port="0">componentname</source>--> -    <!--<sink port="0">nocshell</sink>--> -  <!--</connection>--> -</nocblock> diff --git a/host/include/uhd/rfnoc/blocks/logpwr.xml b/host/include/uhd/rfnoc/blocks/logpwr.xml deleted file mode 100644 index 9307446e3..000000000 --- a/host/include/uhd/rfnoc/blocks/logpwr.xml +++ /dev/null @@ -1,49 +0,0 @@ -<!--This defines one NoC-Block.--> -<nocblock> -  <name>Log Power</name> -  <blockname>LogPwr</blockname> -  <!--There can be several of these:--> -  <ids> -    <id revision="0">4C50</id> -  </ids> -  <!-- Args --> -  <args> -    <arg> -      <name>spp</name> -      <type>int</type> -      <value>256</value> -    </arg> -  </args> -  <!--All the connections to the outside world are listed in 'ports':--> -  <ports> -    <sink> -      <name>in</name> -      <type>sc16</type> -      <vlen>$spp</vlen> -      <pkt_size>%vlen</pkt_size> -    </sink> -    <source> -      <name>out</name> -      <type>sc16</type> -      <vlen>$spp</vlen> -      <pkt_size>%vlen</pkt_size> -    </source> -  </ports> -  <!--<components>--> -    <!--<component>--> -      <!--<key revision="1">nocshell</key>--> -    <!--</component>--> -    <!--<component srbase="0">--> -      <!--[>Will look for a component with this key:<]--> -      <!--<key revision="1">componentname</key>--> -    <!--</component>--> -  <!--</components>--> -  <!--<connection>--> -    <!--<source port="0">nocshell</source>--> -    <!--<sink port="0">componentname</sink>--> -  <!--</connection>--> -  <!--<connection>--> -    <!--<source port="0">componentname</source>--> -    <!--<sink port="0">nocshell</sink>--> -  <!--</connection>--> -</nocblock> diff --git a/host/include/uhd/rfnoc/blocks/moving_avg.xml b/host/include/uhd/rfnoc/blocks/moving_avg.xml deleted file mode 100644 index 943c83261..000000000 --- a/host/include/uhd/rfnoc/blocks/moving_avg.xml +++ /dev/null @@ -1,50 +0,0 @@ -<!--This defines one NoC-Block.--> -<nocblock> -  <name>Moving Average</name> -  <blockname>MovingAverage</blockname> -  <ids> -    <id revision="0">AAD2</id> -  </ids> -  <!-- Registers --> -  <registers> -    <setreg> -      <name>SUM_LEN</name> -      <address>192</address> -    </setreg> -    <setreg> -      <name>DIVISOR</name> -      <address>193</address> -    </setreg> -    <readback> -      <name>RB_SUM_LEN</name> -      <address>0</address> -    </readback> -    <readback> -      <name>RB_DIVISOR</name> -      <address>1</address> -    </readback> -  </registers> -  <!-- Args --> -  <args> -    <arg> -      <name>length</name> -      <type>int</type> -      <value>10</value> -      <check>GE($length, 1) AND LE($length, 255)</check> -      <check_message>Average length must be in [1, 255].</check_message> -      <action>SR_WRITE("SUM_LEN", $length) AND SR_WRITE("DIVISOR", $length)</action> -    </arg> -  </args> -  <!-- Ports --> -  <ports> -    <sink> -      <name>in</name> -      <type>sc16</type> -      <port>0</port> -    </sink> -    <source> -      <name>avg</name> -      <type>sc16</type> -    </source> -  </ports> -</nocblock> diff --git a/host/include/uhd/erfnoc/blocks/null_src_sink.yml b/host/include/uhd/rfnoc/blocks/null_src_sink.yml index 1636ea046..1636ea046 100644 --- a/host/include/uhd/erfnoc/blocks/null_src_sink.yml +++ b/host/include/uhd/rfnoc/blocks/null_src_sink.yml diff --git a/host/include/uhd/rfnoc/blocks/nullblock.xml b/host/include/uhd/rfnoc/blocks/nullblock.xml deleted file mode 100644 index f1ed3bbd2..000000000 --- a/host/include/uhd/rfnoc/blocks/nullblock.xml +++ /dev/null @@ -1,30 +0,0 @@ -<nocblock> -  <name>Null Source/Sink</name> -  <blockname>NullSrcSink</blockname> -  <!--There can be several of these:--> -  <ids> -    <id revision="0">0000000000000000</id> -  </ids> -  <!-- Args --> -  <args> -    <arg> -      <name>line_rate</name> -      <type>int</type> -      <value>65535</value> -    </arg> -    <arg> -      <name>bpp</name> -      <type>int</type> -      <value>256</value> -    </arg> -  </args> -  <!-- Ports --> -  <ports> -    <sink> -      <name>dump</name> -    </sink> -    <source> -      <name>src</name> -    </source> -  </ports> -</nocblock> diff --git a/host/include/uhd/rfnoc/blocks/ofdmeq.xml b/host/include/uhd/rfnoc/blocks/ofdmeq.xml deleted file mode 100644 index 50218e976..000000000 --- a/host/include/uhd/rfnoc/blocks/ofdmeq.xml +++ /dev/null @@ -1,31 +0,0 @@ -<!--This defines one NoC-Block.--> -<nocblock> -  <name>OFDM Equalizer</name> -  <blockname>OFDMEq</blockname> -  <!--There can be several of these:--> -  <ids> -    <id revision="0">FF42</id> -  </ids> -  <!-- Args --> -  <args> -    <arg> -      <name>fftsize</name> -      <type>int</type> -      <value>64</value> -    </arg> -  </args> -  <ports> -    <sink> -      <name>in</name> -      <type>sc16</type> -      <vlen>$fftsize</vlen> -      <pkt_size>%vlen</pkt_size> -    </sink> -    <source> -      <name>out</name> -      <type>sc16</type> -      <vlen>$fftsize</vlen> -      <pkt_size>%vlen</pkt_size> -    </source> -  </ports> -</nocblock> diff --git a/host/include/uhd/rfnoc/blocks/packetresizer.xml b/host/include/uhd/rfnoc/blocks/packetresizer.xml deleted file mode 100644 index 306218318..000000000 --- a/host/include/uhd/rfnoc/blocks/packetresizer.xml +++ /dev/null @@ -1,55 +0,0 @@ -<!--This defines one NoC-Block.--> -<nocblock> -  <name>Packet Resizer</name> -  <blockname>PacketResizer</blockname> -  <doc> -    Block controller for the Packet Resizer RFNoC block. - -    The Packet Resizer RFNoC block changes the packet length of a stream. It can break large -    packets into smaller packets or combine small packets into a single larger packet. -  </doc> -  <ids> -    <id revision="0">12E5</id> -  </ids> -  <registers> -    <setreg> -      <name>SR_PKT_SIZE</name> -      <address>129</address> -    </setreg> -  </registers> -  <args> -    <arg> -      <name>pkt_size</name> -      <type>int</type> -      <value>32</value> -      <check>GT($pkt_size, 0)</check> -      <check_message>Packet size must be positive, non-zero.</check_message> -      <action>SR_WRITE("SR_PKT_SIZE", $pkt_size)</action> -    </arg> -  </args> -  <ports> -    <sink> -      <name>in</name> -    </sink> -    <source> -      <name>out</name> -    </source> -  </ports> -  <!--<components>--> -    <!--<component>--> -      <!--<key revision="1">nocshell</key>--> -    <!--</component>--> -    <!--<component srbase="0">--> -      <!--[>Will look for a component with this key:<]--> -      <!--<key revision="1">componentname</key>--> -    <!--</component>--> -  <!--</components>--> -  <!--<connection>--> -    <!--<source port="0">nocshell</source>--> -    <!--<sink port="0">componentname</sink>--> -  <!--</connection>--> -  <!--<connection>--> -    <!--<source port="0">componentname</source>--> -    <!--<sink port="0">nocshell</sink>--> -  <!--</connection>--> -</nocblock> diff --git a/host/include/uhd/erfnoc/blocks/radio_1x64.yml b/host/include/uhd/rfnoc/blocks/radio_1x64.yml index 7fc9b7890..7fc9b7890 100644 --- a/host/include/uhd/erfnoc/blocks/radio_1x64.yml +++ b/host/include/uhd/rfnoc/blocks/radio_1x64.yml diff --git a/host/include/uhd/erfnoc/blocks/radio_2x64.yml b/host/include/uhd/rfnoc/blocks/radio_2x64.yml index 4e7838392..4e7838392 100644 --- a/host/include/uhd/erfnoc/blocks/radio_2x64.yml +++ b/host/include/uhd/rfnoc/blocks/radio_2x64.yml diff --git a/host/include/uhd/rfnoc/blocks/radio_e31x.xml b/host/include/uhd/rfnoc/blocks/radio_e31x.xml deleted file mode 100644 index 0635e397c..000000000 --- a/host/include/uhd/rfnoc/blocks/radio_e31x.xml +++ /dev/null @@ -1,59 +0,0 @@ -<!--This defines one NoC-Block.--> -<nocblock> -  <name>Radio (E31X)</name> -  <blockname>Radio</blockname> -  <key>E31XRadio</key> -  <!--There can be several of these:--> -  <ids> -    <id revision="0">12AD100000003310</id> -  </ids> -  <!-- Registers --> -  <registers> -    <!--<setreg>--> -      <!--<name>FFT_RESET</name>--> -      <!--<address>131</address>--> -    <!--</setreg>--> -    <!--<readback>--> -      <!--<name>RB_MAGNITUDE_OUT</name>--> -      <!--<address>1</address>--> -    <!--</readback>--> -  </registers> -  <!-- Args --> -  <args> -    <arg> -      <name>spp</name> -      <type>int</type> -      <value>508</value> -      <!--<value>256</value>--> -      <!--<check>GE($spp, 16) AND LE($spp, 4096) AND IS_PWR_OF_2($spp)</check>--> -      <!--<check_message>FFT size must be in [16, 4096] and a power of two.</check_message>--> -      <!--<action>SR_WRITE("FFT_SIZE_LOG2", LOG2($spp)) AND SR_WRITE("AXIS_CONFIG_BUS", ADD(873472, LOG2($spp)))</action>--> -    </arg> -  </args> -  <ports> -    <sink> -      <name>in0</name> -      <type>sc16</type> -      <!--<vlen>$spp</vlen>--> -      <!--<pkt_size>%vlen</pkt_size>--> -    </sink> -    <sink> -      <name>in1</name> -      <type>sc16</type> -      <!--<vlen>$spp</vlen>--> -      <!--<pkt_size>%vlen</pkt_size>--> -    </sink> -    <source> -      <name>out0</name> -      <type>sc16</type> -      <!--<vlen>$spp</vlen>--> -      <!--<pkt_size>%vlen</pkt_size>--> -    </source> -    <source> -      <name>out1</name> -      <type>sc16</type> -      <!--<vlen>$spp</vlen>--> -      <!--<pkt_size>%vlen</pkt_size>--> -    </source> -  </ports> -</nocblock> diff --git a/host/include/uhd/rfnoc/blocks/radio_e320.xml b/host/include/uhd/rfnoc/blocks/radio_e320.xml deleted file mode 100644 index 01f286324..000000000 --- a/host/include/uhd/rfnoc/blocks/radio_e320.xml +++ /dev/null @@ -1,53 +0,0 @@ -<!--This defines one NoC-Block.--> -<nocblock> -  <name>Radio (Neon)</name> -  <blockname>Radio</blockname> -  <key>NeonRadio</key> -  <!--There can be several of these:--> -  <ids> -    <id revision="0">12AD100000003320</id> -  </ids> -  <!-- Registers --> -  <registers> -    <!--<setreg>--> -      <!--<name>FFT_RESET</name>--> -      <!--<address>131</address>--> -    <!--</setreg>--> -    <!--<readback>--> -      <!--<name>RB_MAGNITUDE_OUT</name>--> -      <!--<address>1</address>--> -    <!--</readback>--> -  </registers> -  <!-- Args --> -  <args> -    <arg> -      <name>spp</name> -      <type>int</type> -      <value>364</value> -    </arg> -    <arg> -      <name>gain_mode</name> -      <type>string</type> -      <value>auto</value> -    </arg> -  </args> -  <ports> -    <sink> -      <name>in0</name> -      <type>sc16</type> -    </sink> -    <source> -      <name>out0</name> -      <type>sc16</type> -    </source> -    <sink> -      <name>in1</name> -      <type>sc16</type> -    </sink> -    <source> -      <name>out1</name> -      <type>sc16</type> -    </source> -  </ports> -</nocblock> - diff --git a/host/include/uhd/rfnoc/blocks/radio_eiscat.xml b/host/include/uhd/rfnoc/blocks/radio_eiscat.xml deleted file mode 100644 index cc6fb7f3b..000000000 --- a/host/include/uhd/rfnoc/blocks/radio_eiscat.xml +++ /dev/null @@ -1,267 +0,0 @@ -<nocblock> -  <name>Radio (EISCAT)</name> -  <blockname>Radio</blockname> -  <key>EISCATRadio</key> -  <!--There can be several of these:--> -  <ids> -    <id revision="0">E15CA70000000000</id> -  </ids> -  <!-- Registers --> -  <registers> -    <setreg> -      <!--1-Bit register. Enable Beam Stream Channels. There are 10, so this is a 10 bit value. --> -      <name>SR_RX_STREAM_ENABLE</name> -      <address>159</address> -    </setreg> -    <setreg> -     <!--4-Bit register.  -       [0] Are we sending the upper or lower 5 beam contirbutions?  -       [1] = 1, beams_to_here goes directly to output (bypass neighbour contributions, single USRP) -       [2] = 1, input to rx_receive direct from jesd_core (bypassing beamforming) -       [3] = 1, if bypassing beamforming, instead output counter 00-FF -       to output counter [3:0] = 0d10. -       to output jesd streams directly [3:0] = 6 --> -      <name>SR_BEAMS_TO_NEIGHBOR</name> -      <address>202</address> -      <value>14</value> -    </setreg> -    <setreg> -      <!--1-Bit register. Are we expecting previous contributions? 1==yes we are --> -      <name>SR_PREV_OR_NULL</name> -      <address>203</address> -    </setreg> -    <setreg> -      <name>SR_FIR_COMMANDS_RELOAD</name> -      <address>198</address> -    </setreg> -    <setreg> -      <name>SR_FIR_COMMANDS_CTRL_TIME_HI</name> -      <address>199</address> -    </setreg> -    <setreg> -      <name>SR_FIR_COMMANDS_CTRL_TIME_LO</name> -      <address>200</address> -    </setreg> -    <setreg> -      <!-- Use this to actually update taps in RAM --> -      <name>SR_FIR_BRAM_WRITE_TAPS</name> -      <address>201</address> -    </setreg> -    <setreg> -      <name>SR_SYSREF</name> -      <address>221</address> -    </setreg> -    <setreg> -      <name>SR_CHANNEL_GAIN_0</name> -      <address>204</address> -    </setreg> -    <readback> -      <name>RB_NUM_TAPS</name> -      <address>6</address> -    </readback> -    <readback> -      <name>RB_NUM_CHANNELS</name> -      <address>7</address> -    </readback> -    <readback> -      <name>RB_NUM_BEAMS</name> -      <address>8</address> -    </readback> -    <readback> -      <name>RB_NUM_FILTERS</name> -      <address>9</address> -    </readback> -    <readback> -      <name>RB_STREAM_ENABLED</name> -      <address>10</address> -    </readback> -  </registers> -  <!-- Args --> -  <args> -  <!--Gets applied to all channels--> -    <arg> -      <name>spp</name> -      <type>int</type> -      <value>3968</value> -    </arg> -    <arg> -      <name>taps</name> -      <type>int</type> -    </arg> -    <arg> -      <name>use_prev</name> -      <type>int</type> -      <value>0</value> -      <check>EQUAL($use_prev, 0) OR EQUAL($use_prev, 1)</check> -      <check_message>use_prev must be 0 or 1.</check_message> -      <action>SR_WRITE("SR_PREV_OR_NULL", $use_prev)</action> -    </arg> -    <!--Direct access to the beams register--> -    <arg> -      <name>configure_beams</name> -      <type>int</type> -    </arg> -    <!--Bit 0: 0: Upper 1: Lower Bit 1: 0: Use neighbours 1: no neighbours--> -    <arg> -      <name>choose_beams</name> -      <type>int</type> -      <value>2</value> -    </arg> -    <arg> -      <name>enable_firs</name> -      <type>int</type> -      <value>1</value> -    </arg> -    <arg> -      <name>enable_counter</name> -      <type>int</type> -      <value>0</value> -    </arg> -    <arg> -      <name>channel_enable</name> -      <type>int</type> -      <value>1</value> -      <action>SR_WRITE("SR_RX_STREAM_ENABLE", $channel_enable)</action> -    </arg> -    <arg> -      <name>gain</name> -      <type>double</type> -      <value>1.0</value> -      <action>SR_WRITE("SR_CHANNEL_GAIN_0", 131071)</action> -      <port>0</port> -    </arg> -    <arg> -      <name>gain</name> -      <type>double</type> -      <value>1.0</value> -      <port>1</port> -    </arg> -    <arg> -      <name>gain</name> -      <type>double</type> -      <value>1.0</value> -      <port>2</port> -    </arg> -    <arg> -      <name>gain</name> -      <type>double</type> -      <value>1.0</value> -      <port>3</port> -    </arg> -    <arg> -      <name>gain</name> -      <type>double</type> -      <value>1.0</value> -      <port>4</port> -    </arg> -    <arg> -      <name>gain</name> -      <type>double</type> -      <value>1.0</value> -      <port>5</port> -    </arg> -    <arg> -      <name>gain</name> -      <type>double</type> -      <value>1.0</value> -      <port>6</port> -    </arg> -    <arg> -      <name>gain</name> -      <type>double</type> -      <value>1.0</value> -      <port>7</port> -    </arg> -    <arg> -      <name>gain</name> -      <type>double</type> -      <value>1.0</value> -      <port>8</port> -    </arg> -    <arg> -      <name>gain</name> -      <type>double</type> -      <value>1.0</value> -      <port>9</port> -    </arg> -    <arg> -      <name>gain</name> -      <type>double</type> -      <value>1.0</value> -      <port>10</port> -    </arg> -    <arg> -      <name>gain</name> -      <type>double</type> -      <value>1.0</value> -      <port>11</port> -    </arg> -    <arg> -      <name>gain</name> -      <type>double</type> -      <value>1.0</value> -      <port>12</port> -    </arg> -    <arg> -      <name>gain</name> -      <type>double</type> -      <value>1.0</value> -      <port>13</port> -    </arg> -    <arg> -      <name>gain</name> -      <type>double</type> -      <value>1.0</value> -      <port>14</port> -    </arg> -    <arg> -      <name>gain</name> -      <type>double</type> -      <value>1.0</value> -      <port>15</port> -    </arg> -  </args> -  <ports> -    <source> -      <name>out0</name> -      <type>s16</type> -    </source> -    <source> -      <name>out1</name> -      <type>s16</type> -    </source> -    <source> -      <name>out2</name> -      <type>s16</type> -    </source> -    <source> -      <name>out3</name> -      <type>s16</type> -    </source> -    <source> -      <name>out4</name> -      <type>s16</type> -    </source> -    <sink> -      <name>in0</name> -      <type>s16</type> -    </sink> -    <sink> -      <name>in1</name> -      <type>s16</type> -    </sink> -    <sink> -      <name>in2</name> -      <type>s16</type> -    </sink> -    <sink> -      <name>in3</name> -      <type>s16</type> -    </sink> -    <sink> -      <name>in4</name> -      <type>s16</type> -    </sink> -  </ports> -</nocblock> - diff --git a/host/include/uhd/rfnoc/blocks/radio_magnesium.xml b/host/include/uhd/rfnoc/blocks/radio_magnesium.xml deleted file mode 100644 index b9b32f369..000000000 --- a/host/include/uhd/rfnoc/blocks/radio_magnesium.xml +++ /dev/null @@ -1,53 +0,0 @@ -<!--This defines one NoC-Block.--> -<nocblock> -  <name>Radio (Magnesium)</name> -  <blockname>Radio</blockname> -  <key>MagnesiumRadio</key> -  <!--There can be several of these:--> -  <ids> -    <id revision="0">12AD100000011312</id> -  </ids> -  <!-- Registers --> -  <registers> -    <!--<setreg>--> -      <!--<name>FFT_RESET</name>--> -      <!--<address>131</address>--> -    <!--</setreg>--> -    <!--<readback>--> -      <!--<name>RB_MAGNITUDE_OUT</name>--> -      <!--<address>1</address>--> -    <!--</readback>--> -  </registers> -  <!-- Args --> -  <args> -    <arg> -      <name>spp</name> -      <type>int</type> -      <value>364</value> -    </arg> -    <arg> -      <name>gain_mode</name> -      <type>string</type> -      <value>auto</value> -    </arg> -  </args> -  <ports> -    <sink> -      <name>in0</name> -      <type>sc16</type> -    </sink> -    <source> -      <name>out0</name> -      <type>sc16</type> -    </source> -    <sink> -      <name>in1</name> -      <type>sc16</type> -    </sink> -    <source> -      <name>out1</name> -      <type>sc16</type> -    </source> -  </ports> -</nocblock> - diff --git a/host/include/uhd/rfnoc/blocks/radio_rhodium.xml b/host/include/uhd/rfnoc/blocks/radio_rhodium.xml deleted file mode 100644 index 7bbe3c904..000000000 --- a/host/include/uhd/rfnoc/blocks/radio_rhodium.xml +++ /dev/null @@ -1,47 +0,0 @@ -<!--This defines the Radio (Rhodium) NoC-Block.--> -<nocblock> -  <name>Radio (Rhodium)</name> -  <blockname>Radio</blockname> -  <key>RhodiumRadio</key> -  <!--There can be several of these:--> -  <ids> -    <id revision="0">12AD100000000320</id> -  </ids> -  <!-- Registers --> -  <registers> -  </registers> -  <!-- Args --> -  <args> -    <arg> -      <name>spp</name> -      <type>int</type> -      <value>364</value> -    </arg> -    <arg> -      <name>spur_dodging</name> -      <type>string</type> -      <value>disabled</value> -    </arg> -    <arg> -      <name>spur_dodging_threshold</name> -      <type>double</type> -      <value>2e6</value> -    </arg> -    <arg> -      <name>highband_spur_reduction</name> -      <type>string</type> -      <value>disabled</value> -    </arg> -  </args> -  <ports> -    <sink> -      <name>in0</name> -      <type>sc16</type> -    </sink> -    <source> -      <name>out0</name> -      <type>sc16</type> -    </source> -  </ports> -</nocblock> - diff --git a/host/include/uhd/rfnoc/blocks/radio_x300.xml b/host/include/uhd/rfnoc/blocks/radio_x300.xml deleted file mode 100644 index 8621ac40f..000000000 --- a/host/include/uhd/rfnoc/blocks/radio_x300.xml +++ /dev/null @@ -1,55 +0,0 @@ -<!--This defines one NoC-Block.--> -<nocblock> -  <name>Radio (X300)</name> -  <blockname>Radio</blockname> -  <key>X300Radio</key> -  <!--There can be several of these:--> -  <ids> -    <id revision="0">12AD100000000001</id> -  </ids> -  <!-- Registers --> -  <registers> -    <!--<setreg>--> -      <!--<name>FFT_RESET</name>--> -      <!--<address>131</address>--> -    <!--</setreg>--> -    <!--<readback>--> -      <!--<name>RB_MAGNITUDE_OUT</name>--> -      <!--<address>1</address>--> -    <!--</readback>--> -  </registers> -  <!-- Args --> -  <args> -    <arg> -      <name>spp</name> -      <type>int</type> -      <value>364</value> -      <!--<value>256</value>--> -      <!--<check>GE($spp, 16) AND LE($spp, 4096) AND IS_PWR_OF_2($spp)</check>--> -      <!--<check_message>FFT size must be in [16, 4096] and a power of two.</check_message>--> -      <!--<action>SR_WRITE("FFT_SIZE_LOG2", LOG2($spp)) AND SR_WRITE("AXIS_CONFIG_BUS", ADD(873472, LOG2($spp)))</action>--> -    </arg> -  </args> -  <ports> -    <sink> -      <name>in</name> -      <type>sc16</type> -      <!--<vlen>$spp</vlen>--> -      <!--<pkt_size>%vlen</pkt_size>--> -    </sink> - -    <source> -      <name>out0</name> -      <type>sc16</type> -      <!--<vlen>$spp</vlen>--> -      <!--<pkt_size>%vlen</pkt_size>--> -    </source> -    <source> -      <name>out1</name> -      <type>sc16</type> -      <!--<vlen>$spp</vlen>--> -      <!--<pkt_size>%vlen</pkt_size>--> -    </source> -  </ports> -</nocblock> - diff --git a/host/include/uhd/rfnoc/blocks/replay.xml b/host/include/uhd/rfnoc/blocks/replay.xml deleted file mode 100644 index 3ffc5c01a..000000000 --- a/host/include/uhd/rfnoc/blocks/replay.xml +++ /dev/null @@ -1,64 +0,0 @@ -<!--This defines one NoC-Block.--> -<nocblock> -  <name>Replay</name> -  <blockname>Replay</blockname> -  <key>Replay</key> -  <!--There can be several of these:--> -  <ids> -    <id revision="0">4E91A00000000000</id> -  </ids> -  <!-- Registers --> -  <registers> -    <setreg> -      <name>REC_BASE_ADDR</name> -      <address>128</address> -    </setreg> -    <setreg> -      <name>REC_BUFFER_SIZE</name> -      <address>129</address> -    </setreg> -    <setreg> -      <name>REC_RESTART</name> -      <address>130</address> -    </setreg> -    <readback> -      <name>REC_FULLNESS</name> -      <address>131</address> -    </readback> -    <setreg> -      <name>PLAY_BASE_ADDR</name> -      <address>132</address> -    </setreg> -    <setreg> -      <name>PLAY_BUFFER_SIZE</name> -      <address>133</address> -    </setreg> -    <setreg> -      <name>RX_CTRL_COMMAND</name> -      <address>152</address> -    </setreg> -    <setreg> -      <name>RX_CTRL_HALT</name> -      <address>155</address> -    </setreg> -    <setreg> -      <name>RX_CTRL_MAXLEN</name> -      <address>156</address> -    </setreg> -  </registers> -  <!-- Args --> -  <args> -  </args> -  <!--All the connections to the outside world are listed in 'ports':--> -  <ports> -    <sink> -      <name>in0</name> -      <type>sc16</type> -    </sink> -    <source> -      <name>out0</name> -      <type>sc16</type> -    </source> -  </ports> -</nocblock> - diff --git a/host/include/uhd/rfnoc/blocks/replay_x2.xml b/host/include/uhd/rfnoc/blocks/replay_x2.xml deleted file mode 100644 index a267a85de..000000000 --- a/host/include/uhd/rfnoc/blocks/replay_x2.xml +++ /dev/null @@ -1,72 +0,0 @@ -<!--This defines one NoC-Block.--> -<nocblock> -  <name>Replay</name> -  <blockname>Replay</blockname> -  <key>Replay</key> -  <!--There can be several of these:--> -  <ids> -    <id revision="0">4E91A00000000002</id> -  </ids> -  <!-- Registers --> -  <registers> -    <setreg> -      <name>REC_BASE_ADDR</name> -      <address>128</address> -    </setreg> -    <setreg> -      <name>REC_BUFFER_SIZE</name> -      <address>129</address> -    </setreg> -    <setreg> -      <name>REC_RESTART</name> -      <address>130</address> -    </setreg> -    <readback> -      <name>REC_FULLNESS</name> -      <address>131</address> -    </readback> -    <setreg> -      <name>PLAY_BASE_ADDR</name> -      <address>132</address> -    </setreg> -    <setreg> -      <name>PLAY_BUFFER_SIZE</name> -      <address>133</address> -    </setreg> -    <setreg> -      <name>RX_CTRL_COMMAND</name> -      <address>152</address> -    </setreg> -    <setreg> -      <name>RX_CTRL_HALT</name> -      <address>155</address> -    </setreg> -    <setreg> -      <name>RX_CTRL_MAXLEN</name> -      <address>156</address> -    </setreg> -  </registers> -  <!-- Args --> -  <args> -  </args> -  <!--All the connections to the outside world are listed in 'ports':--> -  <ports> -    <sink> -      <name>in0</name> -      <type>sc16</type> -    </sink> -    <sink> -      <name>in1</name> -      <type>sc16</type> -    </sink> -    <source> -      <name>out0</name> -      <type>sc16</type> -    </source> -    <source> -      <name>out1</name> -      <type>sc16</type> -    </source> -  </ports> -</nocblock> - diff --git a/host/include/uhd/rfnoc/blocks/replay_x4.xml b/host/include/uhd/rfnoc/blocks/replay_x4.xml deleted file mode 100644 index e12b5f0df..000000000 --- a/host/include/uhd/rfnoc/blocks/replay_x4.xml +++ /dev/null @@ -1,87 +0,0 @@ -<!--This defines one NoC-Block.--> -<nocblock> -  <name>Replay</name> -  <blockname>Replay</blockname> -  <key>Replay</key> -  <!--There can be several of these:--> -  <ids> -    <id revision="0">4E91A00000000004</id> -  </ids> -  <!-- Registers --> -  <registers> -    <setreg> -      <name>REC_BASE_ADDR</name> -      <address>128</address> -    </setreg> -    <setreg> -      <name>REC_BUFFER_SIZE</name> -      <address>129</address> -    </setreg> -    <setreg> -      <name>REC_RESTART</name> -      <address>130</address> -    </setreg> -    <readback> -      <name>REC_FULLNESS</name> -      <address>131</address> -    </readback> -    <setreg> -      <name>PLAY_BASE_ADDR</name> -      <address>132</address> -    </setreg> -    <setreg> -      <name>PLAY_BUFFER_SIZE</name> -      <address>133</address> -    </setreg> -    <setreg> -      <name>RX_CTRL_COMMAND</name> -      <address>152</address> -    </setreg> -    <setreg> -      <name>RX_CTRL_HALT</name> -      <address>155</address> -    </setreg> -    <setreg> -      <name>RX_CTRL_MAXLEN</name> -      <address>156</address> -    </setreg> -  </registers> -  <!-- Args --> -  <args> -  </args> -  <!--All the connections to the outside world are listed in 'ports':--> -  <ports> -    <sink> -      <name>in0</name> -      <type>sc16</type> -    </sink> -    <sink> -      <name>in1</name> -      <type>sc16</type> -    </sink> -    <sink> -      <name>in2</name> -      <type>sc16</type> -    </sink> -    <sink> -      <name>in3</name> -      <type>sc16</type> -    </sink> -    <source> -      <name>out0</name> -      <type>sc16</type> -    </source> -    <source> -      <name>out1</name> -      <type>sc16</type> -    </source> -    <source> -      <name>out2</name> -      <type>sc16</type> -    </source> -    <source> -      <name>out3</name> -      <type>sc16</type> -    </source>  </ports> -</nocblock> - diff --git a/host/include/uhd/rfnoc/blocks/schmidlcox.xml b/host/include/uhd/rfnoc/blocks/schmidlcox.xml deleted file mode 100644 index 917b54ba3..000000000 --- a/host/include/uhd/rfnoc/blocks/schmidlcox.xml +++ /dev/null @@ -1,101 +0,0 @@ -<!--This defines one NoC-Block.--> -<nocblock> -  <name>Schmidl & Cox</name> -  <blockname>SchmidlCox</blockname> -  <!--There can be several of these:--> -  <ids> -    <id revision="0">5CC0</id> -  </ids> -  <!-- Registers --> -  <registers> -    <setreg> -      <name>FRAME_LENGTH</name> -      <address>129</address> -    </setreg> -    <setreg> -      <name>CP_LENGTH</name> -      <address>130</address> -    </setreg> -    <setreg> -      <name>DELAY</name> -      <address>131</address> -    </setreg> -    <setreg> -      <name>NUM_SYMBOLS_MAX</name> -      <address>132</address> -    </setreg> -    <setreg> -      <name>THRESHOLD</name> -      <address>134</address> -    </setreg> -    <setreg> -      <name>AGC_REF_LEVEL</name> -      <address>135</address> -    </setreg> -  </registers> -  <!-- Args --> -  <args> -    <arg> -      <name>fftsize</name> -      <type>int</type> -      <value>64</value> -      <!--TODO: Make publisher, when setting this value, check if equal to GET()--> -    </arg> -    <arg> -      <name>frame_len</name> -      <type>int</type> -      <value>64</value> -      <action>SR_WRITE("FRAME_LENGTH", $frame_len)</action> -    </arg> -    <arg> -      <name>cp_len</name> -      <type>int</type> -      <value>16</value> -      <action>SR_WRITE("CP_LENGTH", $cp_len)</action> -    </arg> -    <arg> -      <name>threshold</name> -      <type>double</type> -      <value>0.8</value> -      <check>GE($threshold, 0.0) AND LE($threshold, 1.0)</check> -      <check_message>Detection threshold must be in [0, 1].</check_message> -      <action>SR_WRITE("THRESHOLD", IROUND(MULT(16384.0, $threshold)))</action> -    </arg> -    <arg> -      <name>delay</name> -      <type>int</type> -      <value>146</value> -      <check>GE($delay, 0) AND LE($delay, 32767)</check> -      <check_message>Invalid delay.</check_message> -      <action>SR_WRITE("DELAY", $delay)</action> -    </arg> -    <arg> -      <name>max_num_symbols</name> -      <type>int</type> -      <value>12</value> -      <check>GE($max_num_symbols, 0) AND LE($max_num_symbols, 1000)</check> -      <check_message>Invalid number of max symbols.</check_message> -      <action>SR_WRITE("NUM_SYMBOLS_MAX", $max_num_symbols)</action> -    </arg> -    <arg> -      <name>agc_ref_level</name> -      <type>double</type> -      <value>0.125</value> -      <check>GE($agc_ref_level, 0.0) AND LE($agc_ref_level, 1.0)</check> -      <check_message>AGC reference level must be in [0, 1].</check_message> -      <action>SR_WRITE("AGC_REF_LEVEL", IROUND(MULT(32768.0, $agc_ref_level)))</action> -    </arg> -  </args> -  <ports> -    <sink> -      <name>in</name> -      <type>sc16</type> -    </sink> -    <source> -      <name>out</name> -      <type>sc16</type> -      <vlen>$fftsize</vlen> -      <pkt_size>%vlen</pkt_size> -    </source> -  </ports> -</nocblock> diff --git a/host/include/uhd/rfnoc/blocks/serialdemod.xml b/host/include/uhd/rfnoc/blocks/serialdemod.xml deleted file mode 100644 index 37f3357c1..000000000 --- a/host/include/uhd/rfnoc/blocks/serialdemod.xml +++ /dev/null @@ -1,109 +0,0 @@ -<!--This defines one NoC-Block.--> -<nocblock> -  <name>OFDM Constellation Demod</name> -  <blockname>OFDMDemap</blockname> -  <!--There can be several of these:--> -  <ids> -    <id revision="0">0FCD</id> -  </ids> -  <!-- Registers --> -  <registers> -    <setreg> -      <name>MOD_ORDER</name> -      <address>129</address> -    </setreg> -    <setreg> -      <name>SCALING</name> -      <address>130</address> -    </setreg> -    <setreg> -      <name>OUTPUT_SYMBOLS</name> -      <address>131</address> -    </setreg> -    <setreg> -      <name>PKT_LEN</name> -      <address>132</address> -    </setreg> -    <setreg> -      <name>SET_EOB</name> -      <address>133</address> -    </setreg> -  </registers> -  <!-- Args --> -  <args> -    <arg> -      <name>fftsize</name> -      <type>int</type> -      <value>64</value> -    </arg> -    <arg> -      <name>mod_order</name> -      <type>int</type> -      <value>4</value> -      <check>GE($mod_order, 2) AND LE($mod_order, 64) AND IS_PWR_OF_2($mod_order)</check> -      <check_message>Modulation order must be in (2, 4, 16, 64).</check_message> -      <action>SR_WRITE("MOD_ORDER", LOG2($mod_order))</action> -    </arg> -    <arg> -      <name>scaling</name> -      <type>double</type> -      <value>1.4142135623730951</value> -      <check>GE($scaling, 0.1) AND LT($scaling, 4.0)</check> -      <check_message>Invalid scaling.</check_message> -      <action>SR_WRITE("SCALING", IROUND(MULT(16384.0, $scaling)))</action> -    </arg> -    <arg> -      <name>output_symbols</name> -      <type>int</type> -      <value>1</value> -      <check>EQUAL($output_symbols, 0) OR EQUAL($output_symbols, 1)</check> -      <check_message>Output symbols can only be true (1) or false (0)</check_message> -      <action>SR_WRITE("OUTPUT_SYMBOLS", $output_symbols)</action> -    </arg> -    <!-- Packet length in bytes --> -    <arg> -      <name>pkt_len</name> -      <type>int</type> -      <value>64</value> -      <check>GE($pkt_len, 4) AND LE($pkt_len, 4096)</check> -      <check_message>Packet length must be greater than or equal to 4 and less than or equal to 4096 bytes</check_message> -      <action>SR_WRITE("PKT_LEN", $pkt_len)</action> -    </arg> -    <arg> -      <name>set_eob</name> -      <type>int</type> -      <value>1</value> -      <check>EQUAL($set_eob, 0) OR EQUAL($set_eob, 1)</check> -      <check_message>Set end of burst can only be true (1) or false (0)</check_message> -      <action>SR_WRITE("SET_EOB", $set_eob)</action> -    </arg> -  </args> -  <ports> -    <sink> -      <name>in</name> -      <type>sc16</type> -      <vlen>$fftsize</vlen> -    </sink> -    <source> -      <name>out</name> -      <type>u8</type> -    </source> -  </ports> -  <!--<components>--> -    <!--<component>--> -      <!--<key revision="1">nocshell</key>--> -    <!--</component>--> -    <!--<component srbase="0">--> -      <!--[>Will look for a component with this key:<]--> -      <!--<key revision="1">componentname</key>--> -    <!--</component>--> -  <!--</components>--> -  <!--<connection>--> -    <!--<source port="0">nocshell</source>--> -    <!--<sink port="0">componentname</sink>--> -  <!--</connection>--> -  <!--<connection>--> -    <!--<source port="0">componentname</source>--> -    <!--<sink port="0">nocshell</sink>--> -  <!--</connection>--> -</nocblock> diff --git a/host/include/uhd/rfnoc/blocks/siggen.xml b/host/include/uhd/rfnoc/blocks/siggen.xml deleted file mode 100644 index 2850e6804..000000000 --- a/host/include/uhd/rfnoc/blocks/siggen.xml +++ /dev/null @@ -1,116 +0,0 @@ -<nocblock> -  <name>Signal Generator</name> -  <blockname>SigGen</blockname> -  <!--There can be several of these:--> -  <ids> -    <id revision="0">5166311000000000</id> -  </ids> -  <!-- Registers --> -  <registers> -    <!-- Reg 128 used for FREQ --> -    <setreg> -      <name>FREQ</name> -      <address>129</address> -    </setreg> -    <setreg> -      <name>CARTESIAN</name> -      <address>130</address> -    </setreg> -    <setreg> -      <name>ENABLE</name> -      <address>132</address> -    </setreg> -    <setreg> -      <name>CONSTANT</name> -      <address>138</address> -    </setreg> -    <setreg> -      <name>GAIN</name> -      <address>139</address> -    </setreg> -    <setreg> -      <name>PKT_SIZE</name> -      <address>140</address> -    </setreg> -    <setreg> -      <name>WAVEFORM</name> -      <address>142</address> -    </setreg> -  </registers> -  <!-- Args --> -  <args> -    <arg> -      <name>enable</name> -      <type>int</type> -      <value>0</value> -      <check>EQUAL($enable, 0) OR EQUAL($enable, 1)</check> -      <check_message>Enable is either 0 or 1.</check_message> -      <action>SR_WRITE("ENABLE", $enable)</action> -    </arg> -    <arg> -      <name>spp</name> -      <type>int</type> -      <value>256</value> -      <action>SR_WRITE("PKT_SIZE", $spp)</action> -    </arg> -    <!-- Overall Gain --> -    <arg> -      <name>gain</name> -      <type>double</type> -      <value>1.0</value> -      <check>GE($gain, 0.0) AND LE($gain, 1.0)</check> -      <check_message>Invalid gain.</check_message> -      <action> -        SR_WRITE("GAIN", IROUND(MULT(32767.0,$gain))) -      </action> -    </arg> -    <!-- Sine Wave, Constant I / Q --> -    <arg> -      <name>amplitude_i</name> -      <type>double</type> -      <value>1.0</value> -      <check>GE($amplitude_i, -1.0) AND LE($amplitude_i, 1.0)</check> -      <check_message>Invalid amplitude.</check_message> -    </arg> -    <arg> -      <name>amplitude_q</name> -      <type>double</type> -      <value>1.0</value> -      <check>GE($amplitude_q, -1.0) AND LE($amplitude_q, 1.0)</check> -      <check_message>Invalid amplitude.</check_message> -      <action> -          SR_WRITE("CONSTANT", ADD(MULT(65536,IROUND(MULT(32767.0, $amplitude_i))),IROUND(MULT(32767.0, $amplitude_q)))) -      </action> -    </arg> -    <arg> -      <name>frequency</name> -      <type>double</type> -      <value>0.1</value> -      <check>GE($frequency, -1.0) AND LE($frequency, 1.0)</check> -      <check_message>Invalid frequency.</check_message> -      <action>SR_WRITE("FREQ", IROUND(MULT(-8192.0, $frequency)))</action> -    </arg> -    <arg> -      <name>waveform</name> -      <type>string</type> -      <value>CONSTANT</value> -      <check>EQUAL($waveform, "CONSTANT") OR EQUAL($waveform, "SINE_WAVE") OR EQUAL($waveform, "NOISE")</check> -      <check_message>Waveform type should be one of: CONSTANT, SINE WAVE, NOISE.</check_message> -      <action> -          IF(EQUAL($waveform, "CONSTANT"),  SR_WRITE("WAVEFORM", 0) AND SR_WRITE("CONSTANT",  ADD(MULT(65536,IROUND(MULT(32767.0, $amplitude_i))),IROUND(MULT(32767.0, $amplitude_q))))) OR -          IF(EQUAL($waveform, "SINE_WAVE"), SR_WRITE("WAVEFORM", 1) AND SR_WRITE("CARTESIAN", MULT(65536,28000))) OR -          IF(EQUAL($waveform, "NOISE"),     SR_WRITE("WAVEFORM", 2)) -      </action> -    </arg> -  </args> -  <!-- Ports --> -  <ports> -    <sink> -      <name>dump</name> -    </sink> -    <source> -      <name>src</name> -      <type>sc16</type> -    </source> -  </ports> -</nocblock> diff --git a/host/include/uhd/rfnoc/blocks/splitstream.xml b/host/include/uhd/rfnoc/blocks/splitstream.xml deleted file mode 100644 index 08cbd0457..000000000 --- a/host/include/uhd/rfnoc/blocks/splitstream.xml +++ /dev/null @@ -1,38 +0,0 @@ -<!--This defines one NoC-Block.--> -<nocblock> -  <name>Split Stream</name> -  <blockname>SplitStream</blockname> -  <!--There can be several of these:--> -  <ids> -    <id revision="0">5757</id> -  </ids> -  <!-- This block takes any type, hence we skip the <type> tag: --> -  <ports> -    <sink> -      <name>in</name> -    </sink> -    <source> -      <name>out0</name> -    </source> -    <source> -      <name>out1</name> -    </source> -  </ports> -  <!--<components>--> -    <!--<component>--> -      <!--<key revision="1">nocshell</key>--> -    <!--</component>--> -    <!--<component srbase="0">--> -      <!--[>Will look for a component with this key:<]--> -      <!--<key revision="1">componentname</key>--> -    <!--</component>--> -  <!--</components>--> -  <!--<connection>--> -    <!--<source port="0">nocshell</source>--> -    <!--<sink port="0">componentname</sink>--> -  <!--</connection>--> -  <!--<connection>--> -    <!--<source port="0">componentname</source>--> -    <!--<sink port="0">nocshell</sink>--> -  <!--</connection>--> -</nocblock> diff --git a/host/include/uhd/rfnoc/blocks/vector_iir.xml b/host/include/uhd/rfnoc/blocks/vector_iir.xml deleted file mode 100644 index 98b46e757..000000000 --- a/host/include/uhd/rfnoc/blocks/vector_iir.xml +++ /dev/null @@ -1,84 +0,0 @@ -<!--This defines one NoC-Block.--> -<nocblock> -  <name>Vector IIR</name> -  <blockname>VectorIIR</blockname> -  <!--There can be several of these:--> -  <ids> -    <id revision="0">1112</id> -  </ids> -  <!-- Registers --> -  <registers> -    <setreg> -      <name>VECTOR_LEN</name> -      <address>129</address> -    </setreg> -    <setreg> -      <name>ALPHA</name> -      <address>130</address> -    </setreg> -    <setreg> -      <name>BETA</name> -      <address>131</address> -    </setreg> -  </registers> -  <!-- Args --> -  <args> -    <arg> -      <name>spp</name> -      <type>int</type> -      <value>256</value> -      <check>GE($spp, 1) AND LE($spp, 4096)</check> -      <check_message>Vector length must be in [1, 4096].</check_message> -      <action>SR_WRITE("VECTOR_LEN", $spp)</action> -    </arg> -    <arg> -      <name>alpha</name> -      <type>double</type> -      <value>0.9</value> -      <check>GT($alpha, 0.0) AND LT($alpha, 1.0)</check> -      <check_message>Alpha must be in (0.0, 1.0).</check_message> -      <!--We set the register value to alpha * 2^31 (Q1.31 format)--> -      <action>SR_WRITE("ALPHA", IROUND(MULT($alpha, 2147483648.0)))</action> -    </arg> -    <arg> -      <name>beta</name> -      <type>double</type> -      <value>0.1</value> -      <check>GT($beta, 0.0) AND LT($beta, 1.0)</check> -      <check_message>Beta must be in (0.0, 1.0).</check_message> -      <!--We set the register value to alpha * 2^31 (Q1.31 format)--> -      <action>SR_WRITE("BETA", IROUND(MULT($beta, 2147483648.0)))</action> -    </arg> -  </args> -  <ports> -    <sink> -      <name>in</name> -      <type>sc16</type> -      <vlen>$spp</vlen> -      <pkt_size>%vlen</pkt_size> -    </sink> -    <source> -      <name>out</name> -      <type>sc16</type> -      <vlen>$spp</vlen> -      <pkt_size>%vlen</pkt_size> -    </source> -  </ports> -  <!--<components>--> -    <!--<component>--> -      <!--<key revision="1">nocshell</key>--> -    <!--</component>--> -    <!--<component srbase="0">--> -      <!--[>Will look for a component with this key:<]--> -      <!--<key revision="1">componentname</key>--> -    <!--</component>--> -  <!--</components>--> -  <!--<connection>--> -    <!--<source port="0">nocshell</source>--> -    <!--<sink port="0">componentname</sink>--> -  <!--</connection>--> -  <!--<connection>--> -    <!--<source port="0">componentname</source>--> -    <!--<sink port="0">nocshell</sink>--> -  <!--</connection>--> -</nocblock> diff --git a/host/include/uhd/rfnoc/blocks/window.xml b/host/include/uhd/rfnoc/blocks/window.xml deleted file mode 100644 index df36f4b4f..000000000 --- a/host/include/uhd/rfnoc/blocks/window.xml +++ /dev/null @@ -1,47 +0,0 @@ -<!--This defines one NoC-Block.--> -<nocblock> -  <name>Window</name> -  <blockname>Window</blockname> -  <!--There can be several of these:--> -  <ids> -    <id revision="0">D053</id> -  </ids> -  <args> -    <arg> -      <name>spp</name> -      <type>int</type> -      <value>256</value> -    </arg> -  </args> -  <ports> -    <sink> -      <name>in</name> -      <type>sc16</type> -      <vlen>$spp</vlen> -      <pkt_size>%vlen</pkt_size> -    </sink> -    <source> -      <name>out</name> -      <type>sc16</type> -      <vlen>$spp</vlen> -      <pkt_size>%vlen</pkt_size> -    </source> -  </ports> -  <!--<components>--> -    <!--<component>--> -      <!--<key revision="1">nocshell</key>--> -    <!--</component>--> -    <!--<component srbase="0">--> -      <!--[>Will look for a component with this key:<]--> -      <!--<key revision="1">componentname</key>--> -    <!--</component>--> -  <!--</components>--> -  <!--<connection>--> -    <!--<source port="0">nocshell</source>--> -    <!--<sink port="0">componentname</sink>--> -  <!--</connection>--> -  <!--<connection>--> -    <!--<source port="0">componentname</source>--> -    <!--<sink port="0">nocshell</sink>--> -  <!--</connection>--> -</nocblock> diff --git a/host/include/uhd/rfnoc/constants.hpp b/host/include/uhd/rfnoc/constants.hpp index 1a992378c..6aeef1522 100644 --- a/host/include/uhd/rfnoc/constants.hpp +++ b/host/include/uhd/rfnoc/constants.hpp @@ -16,13 +16,6 @@  namespace uhd { namespace rfnoc { -// All these configure the XML reader -//! Where the RFNoC block/component definition files lie, relative to UHD_PKG_DIR -static const std::string XML_DEFAULT_PATH = "share/uhd/rfnoc"; -//! The name of the environment variable storing the bath to the block definition files -static const std::string XML_PATH_ENV = "UHD_RFNOC_DIR"; - -static const uint64_t DEFAULT_NOC_ID_64     = 0xFFFFFFFFFFFFFFFF;  static const size_t NOC_SHELL_COMPAT_MAJOR  = 5;  static const size_t NOC_SHELL_COMPAT_MINOR  = 1; diff --git a/host/include/uhd/erfnoc/blocks/CMakeLists.txt b/host/include/uhd/rfnoc/core/CMakeLists.txt index c4b8e678d..2027c208b 100644 --- a/host/include/uhd/erfnoc/blocks/CMakeLists.txt +++ b/host/include/uhd/rfnoc/core/CMakeLists.txt @@ -1,14 +1,15 @@  # -# Copyright 2019 Ettus Research, a National Instruments Company +# Copyright 2019 Ettus Research, a National Instruments Brand  #  # SPDX-License-Identifier: GPL-3.0-or-later  #  file(GLOB yml_files "*.yml") +file(GLOB json_files "*.json")  # We always need this, even when RFNoC is 'disabled'  UHD_INSTALL( -    FILES ${yml_files} -    DESTINATION ${PKG_DATA_DIR}/erfnoc/blocks +    FILES ${yml_files} ${json_files} +    DESTINATION ${PKG_DATA_DIR}/rfnoc/core      COMPONENT headers # TODO: Different component -)
\ No newline at end of file +) diff --git a/host/include/uhd/erfnoc/blocks/e310_bsp.yml b/host/include/uhd/rfnoc/core/e310_bsp.yml index 8fabbb55a..8fabbb55a 100644 --- a/host/include/uhd/erfnoc/blocks/e310_bsp.yml +++ b/host/include/uhd/rfnoc/core/e310_bsp.yml diff --git a/host/include/uhd/erfnoc/core/e320_bsp.yml b/host/include/uhd/rfnoc/core/e320_bsp.yml index c8d5b7de0..c8d5b7de0 100644 --- a/host/include/uhd/erfnoc/core/e320_bsp.yml +++ b/host/include/uhd/rfnoc/core/e320_bsp.yml diff --git a/host/include/uhd/erfnoc/core/io_signatures.yml b/host/include/uhd/rfnoc/core/io_signatures.yml index ba7721e3e..ba7721e3e 100644 --- a/host/include/uhd/erfnoc/core/io_signatures.yml +++ b/host/include/uhd/rfnoc/core/io_signatures.yml diff --git a/host/include/uhd/erfnoc/core/n300_bsp.yml b/host/include/uhd/rfnoc/core/n300_bsp.yml index f0c75df4e..f0c75df4e 100644 --- a/host/include/uhd/erfnoc/core/n300_bsp.yml +++ b/host/include/uhd/rfnoc/core/n300_bsp.yml diff --git a/host/include/uhd/erfnoc/core/n310_bsp.yml b/host/include/uhd/rfnoc/core/n310_bsp.yml index 08690ed5a..08690ed5a 100644 --- a/host/include/uhd/erfnoc/core/n310_bsp.yml +++ b/host/include/uhd/rfnoc/core/n310_bsp.yml diff --git a/host/include/uhd/erfnoc/core/n320_bsp.yml b/host/include/uhd/rfnoc/core/n320_bsp.yml index 5d31da947..5d31da947 100644 --- a/host/include/uhd/erfnoc/core/n320_bsp.yml +++ b/host/include/uhd/rfnoc/core/n320_bsp.yml diff --git a/host/include/uhd/erfnoc/core/rfnoc_imagebuilder_args.json b/host/include/uhd/rfnoc/core/rfnoc_imagebuilder_args.json index 65ef2dd76..65ef2dd76 100644 --- a/host/include/uhd/erfnoc/core/rfnoc_imagebuilder_args.json +++ b/host/include/uhd/rfnoc/core/rfnoc_imagebuilder_args.json diff --git a/host/include/uhd/erfnoc/core/x300_bsp.yml b/host/include/uhd/rfnoc/core/x300_bsp.yml index 20a78958f..20a78958f 100644 --- a/host/include/uhd/erfnoc/core/x300_bsp.yml +++ b/host/include/uhd/rfnoc/core/x300_bsp.yml diff --git a/host/include/uhd/erfnoc/core/x310_bsp.yml b/host/include/uhd/rfnoc/core/x310_bsp.yml index 20a78958f..20a78958f 100644 --- a/host/include/uhd/erfnoc/core/x310_bsp.yml +++ b/host/include/uhd/rfnoc/core/x310_bsp.yml diff --git a/host/include/uhd/rfnoc/ddc_block_ctrl.hpp b/host/include/uhd/rfnoc/ddc_block_ctrl.hpp deleted file mode 100644 index 2a261db00..000000000 --- a/host/include/uhd/rfnoc/ddc_block_ctrl.hpp +++ /dev/null @@ -1,38 +0,0 @@ -// -// Copyright 2016 Ettus Research -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#ifndef INCLUDED_LIBUHD_RFNOC_DDC_BLOCK_CTRL_HPP -#define INCLUDED_LIBUHD_RFNOC_DDC_BLOCK_CTRL_HPP - -#include <uhd/rfnoc/rate_node_ctrl.hpp> -#include <uhd/rfnoc/scalar_node_ctrl.hpp> -#include <uhd/rfnoc/sink_block_ctrl_base.hpp> -#include <uhd/rfnoc/source_block_ctrl_base.hpp> - -namespace uhd { namespace rfnoc { - -/*! \brief DDC block controller - * - * This block provides DSP for Rx operations. - * Its main component is a DDC chain, which can decimate over a wide range - * of decimation rates (using a CIC and halfband filters). - * - * It also includes a CORDIC component to shift signals in frequency. - */ -class UHD_RFNOC_API ddc_block_ctrl : public source_block_ctrl_base, -                                     public sink_block_ctrl_base, -                                     public rate_node_ctrl, -                                     public scalar_node_ctrl -{ -public: -    UHD_RFNOC_BLOCK_OBJECT(ddc_block_ctrl) - -}; /* class ddc_block_ctrl*/ - -}} /* namespace uhd::rfnoc */ - -#endif /* INCLUDED_LIBUHD_RFNOC_DDC_BLOCK_CTRL_HPP */ diff --git a/host/include/uhd/rfnoc/dma_fifo_block_ctrl.hpp b/host/include/uhd/rfnoc/dma_fifo_block_ctrl.hpp deleted file mode 100644 index 093e2ef91..000000000 --- a/host/include/uhd/rfnoc/dma_fifo_block_ctrl.hpp +++ /dev/null @@ -1,46 +0,0 @@ -// -// Copyright 2016 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#ifndef INCLUDED_LIBUHD_RFNOC_DMA_FIFO_BLOCK_HPP -#define INCLUDED_LIBUHD_RFNOC_DMA_FIFO_BLOCK_HPP - -#include <uhd/rfnoc/sink_block_ctrl_base.hpp> -#include <uhd/rfnoc/source_block_ctrl_base.hpp> - -namespace uhd { namespace rfnoc { - -/*! \brief Block controller for a DMA FIFO block. - * - * The DMA FIFO block has the following features: - * - One input- and output-port (type agnostic) - * - Configurable base address and FIFO depth - * - The base storage for the FIFO can be device - *   specific. Usually it will be an off-chip SDRAM - *   bank. - * - */ -class UHD_RFNOC_API dma_fifo_block_ctrl : public source_block_ctrl_base, -                                          public sink_block_ctrl_base -{ -public: -    UHD_RFNOC_BLOCK_OBJECT(dma_fifo_block_ctrl) - -    //! Configure the base address and depth of the FIFO (in bytes). -    virtual void resize( -        const uint32_t base_addr, const uint32_t depth, const size_t chan) = 0; - -    //! Returns the base address of the FIFO (in bytes). -    uint32_t get_base_addr(const size_t chan) const; - -    //! Returns the depth of the FIFO (in bytes). -    uint32_t get_depth(const size_t chan) const; - -}; /* class dma_fifo_block_ctrl*/ - -}} /* namespace uhd::rfnoc */ - -#endif /* INCLUDED_LIBUHD_RFNOC_DMA_FIFO_BLOCK_HPP */ diff --git a/host/include/uhd/rfnoc/duc_block_ctrl.hpp b/host/include/uhd/rfnoc/duc_block_ctrl.hpp deleted file mode 100644 index b24f7af26..000000000 --- a/host/include/uhd/rfnoc/duc_block_ctrl.hpp +++ /dev/null @@ -1,38 +0,0 @@ -// -// Copyright 2016 Ettus Research -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#ifndef INCLUDED_LIBUHD_RFNOC_DUC_BLOCK_CTRL_HPP -#define INCLUDED_LIBUHD_RFNOC_DUC_BLOCK_CTRL_HPP - -#include <uhd/rfnoc/rate_node_ctrl.hpp> -#include <uhd/rfnoc/scalar_node_ctrl.hpp> -#include <uhd/rfnoc/sink_block_ctrl_base.hpp> -#include <uhd/rfnoc/source_block_ctrl_base.hpp> - -namespace uhd { namespace rfnoc { - -/*! \brief DUC block controller - * - * This block provides DSP for Tx operations. - * Its main component is a DUC chain, which can interpolate over a wide range - * of interpolation rates (using a CIC and halfband filters). - * - * It also includes a CORDIC component to shift signals in frequency. - */ -class UHD_RFNOC_API duc_block_ctrl : public source_block_ctrl_base, -                                     public sink_block_ctrl_base, -                                     public rate_node_ctrl, -                                     public scalar_node_ctrl -{ -public: -    UHD_RFNOC_BLOCK_OBJECT(duc_block_ctrl) - -}; /* class duc_block_ctrl*/ - -}} /* namespace uhd::rfnoc */ - -#endif /* INCLUDED_LIBUHD_RFNOC_DUC_BLOCK_CTRL_HPP */ diff --git a/host/include/uhd/rfnoc/fir_block_ctrl.hpp b/host/include/uhd/rfnoc/fir_block_ctrl.hpp deleted file mode 100644 index 67a6a958b..000000000 --- a/host/include/uhd/rfnoc/fir_block_ctrl.hpp +++ /dev/null @@ -1,45 +0,0 @@ -// -// Copyright 2014-2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#ifndef INCLUDED_LIBUHD_RFNOC_fir_block_ctrl_HPP -#define INCLUDED_LIBUHD_RFNOC_fir_block_ctrl_HPP - -#include <uhd/rfnoc/sink_block_ctrl_base.hpp> -#include <uhd/rfnoc/source_block_ctrl_base.hpp> - -namespace uhd { namespace rfnoc { - -/*! \brief Block controller for the standard FIR RFNoC block. - * - * The standard FIR has the following features: - * - One input- and output-port - * - Configurable taps, but fixed number of taps - * - Supports data type sc16 (16-Bit fix-point complex samples) - * - * This block requires packets to be the same size as the FFT length. - * It will perform one FFT operation per incoming packet, treating it - * as a vector of samples. - */ -class UHD_RFNOC_API fir_block_ctrl : public source_block_ctrl_base, -                                     public sink_block_ctrl_base -{ -public: -    UHD_RFNOC_BLOCK_OBJECT(fir_block_ctrl) - -    //! Configure the filter taps. -    // -    // The length of \p taps must correspond the number of taps -    // in this block. If it's shorter, zeros will be padded. -    // If it's longer, throws a uhd::value_error. -    virtual void set_taps(const std::vector<int>& taps) = 0; - -    //! Returns the number of filter taps in this block. -    virtual size_t get_n_taps() const = 0; -}; /* class fir_block_ctrl*/ - -}} /* namespace uhd::rfnoc */ - -#endif /* INCLUDED_LIBUHD_RFNOC_fir_block_ctrl_HPP */ diff --git a/host/include/uhd/rfnoc/graph.hpp b/host/include/uhd/rfnoc/graph.hpp deleted file mode 100644 index bdd104620..000000000 --- a/host/include/uhd/rfnoc/graph.hpp +++ /dev/null @@ -1,76 +0,0 @@ -// -// Copyright 2016 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#ifndef INCLUDED_LIBUHD_RFNOC_GRAPH_HPP -#define INCLUDED_LIBUHD_RFNOC_GRAPH_HPP - -#include <uhd/rfnoc/block_id.hpp> -#include <uhd/types/sid.hpp> -#include <uhd/utils/noncopyable.hpp> - -namespace uhd { namespace rfnoc { - -class graph : uhd::noncopyable -{ -public: -    typedef boost::shared_ptr<uhd::rfnoc::graph> sptr; - -    /*! Connect a RFNOC block with block ID \p src_block to another with block ID \p -     * dst_block. -     * -     * This will: -     * - Check if this connection is valid (IO signatures, see if types match) -     * - Configure the flow control for the blocks -     * - Configure SID for the upstream block -     * - Register the upstream block in the downstream block -     */ -    virtual void connect(const block_id_t& src_block, -        size_t src_block_port, -        const block_id_t& dst_block, -        size_t dst_block_port, -        const size_t pkt_size = 0) = 0; - -    /*! Shorthand for connect(). -     * -     * Using default ports for both source and destination. -     */ -    virtual void connect(const block_id_t& src_block, const block_id_t& dst_block) = 0; - -    /*! Anonymous connection. -     * -     * Danger, danger. You use this, you know what you're doing. -     * -     * \param src_block Source block ID -     * \param src_block_port Source block port -     * \param dst_sid SID to route traffic to -     * \param buf_size_dst_bytes Destination window buffer in bytes -     * \param pkt_size Hint what the packet size over this link will be -     */ -    virtual void connect_src(const block_id_t& src_block, -        const size_t src_block_port, -        const uhd::sid_t dst_sid, -        const size_t buf_size_dst_bytes, -        const size_t pkt_size) = 0; - -    /*! Anonymous connection -     * -     * Danger, danger. You use this, you know what you're doing. -     * -     * \param sink_block Sink block ID -     * \param dst_block_port Destination (sink) block port -     * \param bytes_per_ack Flow control frequency in bytes -     */ -    virtual void connect_sink(const block_id_t& sink_block, -        const size_t dst_block_port, -        const size_t bytes_per_ack) = 0; - -    virtual std::string get_name() const = 0; -}; - -}}; // namespace uhd::rfnoc - -#endif /* INCLUDED_LIBUHD_RFNOC_GRAPH_HPP */ diff --git a/host/include/uhd/rfnoc/node_ctrl_base.hpp b/host/include/uhd/rfnoc/node_ctrl_base.hpp deleted file mode 100644 index c94507173..000000000 --- a/host/include/uhd/rfnoc/node_ctrl_base.hpp +++ /dev/null @@ -1,309 +0,0 @@ -// -// Copyright 2014-2016 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// Copyright 2019 Ettus Research, a National Instruments Brand -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#ifndef INCLUDED_LIBUHD_NODE_CTRL_BASE_HPP -#define INCLUDED_LIBUHD_NODE_CTRL_BASE_HPP - -#include <uhd/rfnoc/constants.hpp> -#include <uhd/types/device_addr.hpp> -#include <uhd/utils/log.hpp> -#include <uhd/utils/noncopyable.hpp> -#include <stdint.h> -#include <boost/enable_shared_from_this.hpp> -#include <boost/function.hpp> -#include <boost/shared_ptr.hpp> -#include <boost/utility.hpp> -#include <map> -#include <set> - -namespace uhd { namespace usrp { -// Forward declaration for friend clause -class device3_impl; -}} // namespace uhd::usrp - -namespace uhd { namespace rfnoc { - -#define UHD_RFNOC_BLOCK_TRACE() UHD_LOGGER_TRACE("RFNOC") - -/*! \brief Abstract base class for streaming nodes. - * - */ -class UHD_RFNOC_API node_ctrl_base; -class node_ctrl_base : uhd::noncopyable, -                       public boost::enable_shared_from_this<node_ctrl_base> -{ -public: -    /*********************************************************************** -     * Types -     **********************************************************************/ -    typedef boost::shared_ptr<node_ctrl_base> sptr; -    typedef boost::weak_ptr<node_ctrl_base> wptr; -    typedef std::map<size_t, wptr> node_map_t; -    typedef std::pair<size_t, wptr> node_map_pair_t; -    typedef boost::function<void(void)> graph_update_cb_t; - -    /*********************************************************************** -     * Node control -     **********************************************************************/ -    //! Returns a unique string that identifies this block. -    virtual std::string unique_id() const; - -    /*********************************************************************** -     * Connections -     **********************************************************************/ -    /*! Clears the list of connected nodes. -     */ -    virtual void clear(); - -    node_map_t list_downstream_nodes() -    { -        return _downstream_nodes; -    }; -    node_map_t list_upstream_nodes() -    { -        return _upstream_nodes; -    }; - -    /*! Disconnect this node from all neighbouring nodes. -     */ -    void disconnect(); - -    /*! Identify \p output_port as unconnected -     */ -    void disconnect_output_port(const size_t output_port); - -    /*! Identify \p input_port as unconnected -     */ -    void disconnect_input_port(const size_t input_port); - -    // TODO we need a more atomic connect procedure, this is too error-prone. - -    /*! For an existing connection, store the remote port number. -     * -     * \throws uhd::value_error if \p this_port is not connected. -     */ -    void set_downstream_port(const size_t this_port, const size_t remote_port); - -    /*! Return the remote port of a connection on a given port. -     * -     * \throws uhd::value_error if \p this_port is not connected. -     */ -    size_t get_downstream_port(const size_t this_port); - -    /*! For an existing connection, store the remote port number. -     * -     * \throws uhd::value_error if \p this_port is not connected. -     */ -    void set_upstream_port(const size_t this_port, const size_t remote_port); - -    /*! Return the remote port of a connection on a given port. -     * -     * \throws uhd::value_error if \p this_port is not connected. -     */ -    size_t get_upstream_port(const size_t this_port); - -    /*! Find nodes downstream that match a predicate. -     * -     * Uses a non-recursive breadth-first search algorithm. -     * On every branch, the search stops if a block matches. -     * See this example: -     * <pre> -     * A -> B -> C -> C -     * </pre> -     * Say node A searches for nodes of type C. It will only find the -     * first 'C' block, not the second. -     * -     * Returns blocks that are of type T. -     * -     * Search only goes downstream. -     */ -    template <typename T> -    UHD_INLINE std::vector<boost::shared_ptr<T> > find_downstream_node( -        bool active_only = false) -    { -        return _find_child_node<T, true>(active_only); -    } - -    /*! Same as find_downstream_node(), but only search upstream. -     */ -    template <typename T> -    UHD_INLINE std::vector<boost::shared_ptr<T> > find_upstream_node( -        bool active_only = false) -    { -        return _find_child_node<T, false>(active_only); -    } - -    /*! Checks if downstream nodes share a common, unique property. -     * -     * This will use find_downstream_node() to find all nodes downstream of -     * this that are of type T. Then it will use \p get_property to return a -     * property from all of them. If all these properties are identical, it will -     * return that property. Otherwise, it will throw a uhd::runtime_error. -     * -     * \p get_property A functor to return the property from a node -     * \p null_value If \p get_property returns this value, that node is skipped. -     * \p explored_nodes A list of nodes to exclude from the search. This is typically -     *                   to avoid recursion loops. -     */ -    template <typename T, typename value_type> -    UHD_INLINE value_type find_downstream_unique_property( -        boost::function<value_type(boost::shared_ptr<T> node, size_t port)> get_property, -        value_type null_value, -        const std::set<boost::shared_ptr<T> >& exclude_nodes = -            std::set<boost::shared_ptr<T> >()) -    { -        return _find_unique_property<T, value_type, true>( -            get_property, null_value, exclude_nodes); -    } - -    /*! Like find_downstream_unique_property(), but searches upstream. -     */ -    template <typename T, typename value_type> -    UHD_INLINE value_type find_upstream_unique_property( -        boost::function<value_type(boost::shared_ptr<T> node, size_t port)> get_property, -        value_type null_value, -        const std::set<boost::shared_ptr<T> >& exclude_nodes = -            std::set<boost::shared_ptr<T> >()) -    { -        return _find_unique_property<T, value_type, false>( -            get_property, null_value, exclude_nodes); -    } - -protected: -    /*********************************************************************** -     * Structors -     **********************************************************************/ -    node_ctrl_base(void) : _num_input_ports(0), _num_output_ports(0) {} -    virtual ~node_ctrl_base() -    { -        disconnect(); -    } - -    /*********************************************************************** -     * Protected members -     **********************************************************************/ - -    //! Stores default arguments -    uhd::device_addr_t _args; - -    // TODO make these private - -    //! List of upstream nodes -    node_map_t _upstream_nodes; - -    //! List of downstream nodes -    node_map_t _downstream_nodes; - -    /*! Number of input ports -     */ -    size_t _num_input_ports; - -    /*! Number of output ports -     */ -    size_t _num_output_ports; - -    /*! For every output port, store rx streamer activity. -     * -     * If _rx_streamer_active[0] == true, this means that an active rx -     * streamer is operating on port 0. If it is false, or if the entry -     * does not exist, there is no streamer. -     * Values are toggled by set_rx_streamer(). -     */ -    std::map<size_t, bool> _rx_streamer_active; - -    /*! For every input port, store tx streamer activity. -     * -     * If _tx_streamer_active[0] == true, this means that an active tx -     * streamer is operating on port 0. If it is false, or if the entry -     * does not exist, there is no streamer. -     * Values are toggled by set_tx_streamer(). -     */ -    std::map<size_t, bool> _tx_streamer_active; - -    /*********************************************************************** -     * Connections -     **********************************************************************/ -    /*! Registers another node as downstream of this node, connected to a given port. -     * -     * This implies that this node is a source node, and the downstream node is -     * a sink node. -     * See also uhd::rfnoc::source_node_ctrl::_register_downstream_node(). -     */ -    virtual void _register_downstream_node( -        node_ctrl_base::sptr downstream_node, size_t port); - -    /*! Registers another node as upstream of this node, connected to a given port. -     * -     * This implies that this node is a sink node, and the upstream node is -     * a source node. -     * See also uhd::rfnoc::sink_node_ctrl::_register_upstream_node(). -     */ -    virtual void _register_upstream_node(node_ctrl_base::sptr upstream_node, size_t port); - -    /*! Initiate the update graph callback -     * -     * Call this from your block when you've changed one of these: -     * - sampling rate -     * - scaling -     * - tick rate -     */ -    void update_graph() -    { -        _graph_update_cb(); -    } - -private: -    friend class uhd::usrp::device3_impl; - -    /*! Implements the search algorithm for find_downstream_node() and -     * find_upstream_node(). -     * -     * Depending on \p downstream, "child nodes" are either defined as -     * nodes connected downstream or upstream. -     * -     * \param downstream Set to true if search goes downstream, false for upstream. -     */ -    template <typename T, bool downstream> -    std::vector<boost::shared_ptr<T> > _find_child_node(bool active_only = false); - -    /*! Implements the search algorithm for find_downstream_unique_property() and -     * find_upstream_unique_property(). -     * -     * Depending on \p downstream, "child nodes" are either defined as -     * nodes connected downstream or upstream. -     * -     * \param downstream Set to true if search goes downstream, false for upstream. -     */ -    template <typename T, typename value_type, bool downstream> -    value_type _find_unique_property( -        boost::function<value_type(boost::shared_ptr<T>, size_t)> get_property, -        value_type NULL_VALUE, -        const std::set<boost::shared_ptr<T> >& exclude_nodes); - -    void set_graph_update_cb(graph_update_cb_t graph_update_cb) -    { -        _graph_update_cb = graph_update_cb; -    } - -    /*! Stores the remote port number of a downstream connection. -     */ -    std::map<size_t, size_t> _upstream_ports; - -    /*! Stores the remote port number of a downstream connection. -     */ -    std::map<size_t, size_t> _downstream_ports; - -    graph_update_cb_t _graph_update_cb; - -}; /* class node_ctrl_base */ - -}} /* namespace uhd::rfnoc */ - -#include <uhd/rfnoc/node_ctrl_base.ipp> - -#endif /* INCLUDED_LIBUHD_NODE_CTRL_BASE_HPP */ diff --git a/host/include/uhd/rfnoc/node_ctrl_base.ipp b/host/include/uhd/rfnoc/node_ctrl_base.ipp deleted file mode 100644 index 80dadfcf9..000000000 --- a/host/include/uhd/rfnoc/node_ctrl_base.ipp +++ /dev/null @@ -1,156 +0,0 @@ -// -// Copyright 2014 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -// Implements templated functions from node_ctrl_base.hpp - -#ifndef INCLUDED_LIBUHD_NODE_CTRL_BASE_IPP -#define INCLUDED_LIBUHD_NODE_CTRL_BASE_IPP - -#include <uhd/exception.hpp> - -#include <boost/shared_ptr.hpp> -#include <vector> - -namespace uhd { -    namespace rfnoc { - -    template <typename T, bool downstream> -    std::vector< boost::shared_ptr<T> > node_ctrl_base::_find_child_node(bool active_only) -    { -        typedef boost::shared_ptr<T> T_sptr; -        static const size_t MAX_ITER = 20; -        size_t iters = 0; -        // List of return values: -        std::set< T_sptr > results_s; -        // To avoid cycles: -        std::set < sptr > explored; -        // Initialize our search queue with ourself: -        std::set < node_map_pair_t > search_q; -        // FIXME:  Port is initialized to ANY_PORT, but it should really be -        // passed in by the caller. -        search_q.insert(node_map_pair_t(ANY_PORT, shared_from_this())); -        std::set < node_map_pair_t > next_q; - -        while (iters++ < MAX_ITER) { -            next_q.clear(); -            BOOST_FOREACH(const node_map_pair_t node_pair, search_q) { -                sptr node = node_pair.second.lock(); -                if (not node) -                { -                    continue; -                } -                size_t our_port = node_pair.first; -                // Add this node to the list of explored nodes -                explored.insert(node); -                // Create set of all child nodes of this_node that are not in explored: -                std::set< node_map_pair_t > next_nodes; -                { -                    node_map_t all_next_nodes = downstream ? -                        node->list_downstream_nodes() : -                        node->list_upstream_nodes(); -                    for ( -                        node_map_t::iterator it = all_next_nodes.begin(); -                        it != all_next_nodes.end(); -                        ++it -                    ) { -                        size_t connected_port = it->first; -                        // If port is given, limit traversal to only that port. -                        if (our_port != ANY_PORT and our_port != connected_port) -                        { -                            continue; -                        } -                        if (active_only -                            and not (downstream ? -                                _tx_streamer_active[connected_port] : -                                _rx_streamer_active[connected_port] )) { -                            continue; -                        } -                        sptr one_next_node = it->second.lock(); -                        if (not one_next_node or explored.count(one_next_node)) { -                            continue; -                        } -                        T_sptr next_node_sptr = boost::dynamic_pointer_cast<T>(one_next_node); -                        if (next_node_sptr) { -                            results_s.insert(next_node_sptr); -                        } else { -                            size_t next_port = ANY_PORT; -                            // FIXME:  Need proper mapping from input port -                            // to output port. -                            // The code below assumes that blocks with the same -                            // number of connected upstream and downstream nodes -                            // map each input port directly to the same output -                            // port.  This limits the graph traversal to prevent -                            // finding nodes that are not part of this chain. -                            if (one_next_node->_num_input_ports -                                and (one_next_node->_num_input_ports == -                                one_next_node->_num_output_ports)) -                            { -                                next_port = (downstream ? -                                    node->get_downstream_port(connected_port) : -                                    node->get_upstream_port(connected_port)); -                            } -                            next_nodes.insert(node_map_pair_t(next_port, it->second)); -                        } -                    } -                } -                // Add all of these nodes to the next search queue -                next_q.insert(next_nodes.begin(), next_nodes.end()); -            } -            // If next_q is empty, we've exhausted our graph -            if (next_q.empty()) { -                break; -            } -            // Re-init the search queue -            search_q = next_q; -        } - -        std::vector< T_sptr > results(results_s.begin(), results_s.end()); -        return results; -    } - -    template <typename T, typename value_type, bool downstream> -    value_type node_ctrl_base::_find_unique_property( -            boost::function<value_type(boost::shared_ptr<T>, size_t)> get_property, -            value_type NULL_VALUE, -            const std::set< boost::shared_ptr<T> > &exclude_nodes -    ) { -        std::vector< boost::shared_ptr<T> > descendant_rate_nodes = _find_child_node<T, downstream>(); -        value_type ret_val = NULL_VALUE; -        std::string first_node_id; -        BOOST_FOREACH(const boost::shared_ptr<T> &node, descendant_rate_nodes) { -            if (exclude_nodes.count(node)) { -                continue; -            } -            // FIXME we need to know the port!!! -            size_t port = ANY_PORT; // NOOO! this is wrong!!!! FIXME -            value_type this_property = get_property(node, port); -            if (this_property == NULL_VALUE) { -                continue; -            } -            // We use the first property we find as reference -            if (ret_val == NULL_VALUE) { -                ret_val = this_property; -                first_node_id = node->unique_id(); -                continue; -            } -            // In all subsequent finds, we make sure the property is equal to the reference -            if (this_property != ret_val) { -                throw uhd::runtime_error( -                    str( -                        boost::format("Node %1% specifies %2%, node %3% specifies %4%") -                            % first_node_id % ret_val % node->unique_id() % this_property -                    ) -                ); -            } -        } -        return ret_val; -    } - -}} /* namespace uhd::rfnoc */ - -#endif /* INCLUDED_LIBUHD_NODE_CTRL_BASE_IPP */ -// vim: sw=4 et: diff --git a/host/include/uhd/rfnoc/null_block_ctrl.hpp b/host/include/uhd/rfnoc/null_block_ctrl.hpp deleted file mode 100644 index 1406fd219..000000000 --- a/host/include/uhd/rfnoc/null_block_ctrl.hpp +++ /dev/null @@ -1,68 +0,0 @@ -// -// Copyright 2014-2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#ifndef INCLUDED_LIBUHD_RFNOC_NULL_BLOCK_CTRL_HPP -#define INCLUDED_LIBUHD_RFNOC_NULL_BLOCK_CTRL_HPP - -#include <uhd/rfnoc/sink_block_ctrl_base.hpp> -#include <uhd/rfnoc/source_block_ctrl_base.hpp> - -namespace uhd { namespace rfnoc { - -/*! \brief Provide access to a 'null block'. - * - * A 'null block' is a specific block, which comes with a couple - * of features useful for testing: - * - It can produce data at a given line rate, with a configurable - *   packet size. - * - It can be used to dump packets ("null sink", "bit bucket") - * - * This block also serves as an example of how to create your own - * C++ classes to control your block. - * - * As a true source, it understands the following stream commands: - * - STREAM_MODE_START_CONTINUOUS - * - STREAM_MODE_STOP_CONTINUOUS - * - * Other stream commands are not understood and issue_stream_cmd() - * will throw if it receives them. - */ -class null_block_ctrl : public source_block_ctrl_base, public sink_block_ctrl_base -{ -public: -    // This macro must always be at the top of the public section in an RFNoC block class -    UHD_RFNOC_BLOCK_OBJECT(null_block_ctrl) - -    //! Set this register to number of lines per packet -    static const uint32_t SR_LINES_PER_PACKET = 129; -    //! Set this register to number of cycles between producing a line -    static const uint32_t SR_LINE_RATE = 130; -    //! Set this register to non-zero to start producing data -    static const uint32_t SR_ENABLE_STREAM = 131; - -    static const size_t DEFAULT_LINES_PER_PACKET = 32; -    static const size_t BYTES_PER_LINE           = 8; - -    //! Custom function to set the rate at which data is produced. -    // Note: This is 'cycles per line', so the bit rate is actually -    // 64 times this value (byte/s is 8*rate etc.) -    // -    // Equivalent to writing to line_rate/value in the property tree. -    // -    // \param The rate you want to set this to -    // \param The clock rate of this block's clock domain -    // \returns the actual line rate (will find closest possible). -    virtual double set_line_rate(double rate, double clock_rate = 166.6e6) = 0; - -    //! Return the current line rate. Equivalent to reading line_rate/value -    // from the property tree. -    virtual double get_line_rate(double clock_rate = 166.6e6) const = 0; - -}; /* class null_block_ctrl*/ - -}} /* namespace uhd::rfnoc */ - -#endif /* INCLUDED_LIBUHD_RFNOC_NULL_BLOCK_CTRL_HPP */ diff --git a/host/include/uhd/rfnoc/radio_ctrl.hpp b/host/include/uhd/rfnoc/radio_ctrl.hpp deleted file mode 100644 index 4f8f3bb1d..000000000 --- a/host/include/uhd/rfnoc/radio_ctrl.hpp +++ /dev/null @@ -1,521 +0,0 @@ -// -// Copyright 2015-2016 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#ifndef INCLUDED_LIBUHD_RFNOC_RADIO_CTRL_HPP -#define INCLUDED_LIBUHD_RFNOC_RADIO_CTRL_HPP - -#include <uhd/rfnoc/rate_node_ctrl.hpp> -#include <uhd/rfnoc/scalar_node_ctrl.hpp> -#include <uhd/rfnoc/sink_block_ctrl_base.hpp> -#include <uhd/rfnoc/source_block_ctrl_base.hpp> -#include <uhd/rfnoc/terminator_node_ctrl.hpp> -#include <uhd/rfnoc/tick_node_ctrl.hpp> -#include <uhd/types/direction.hpp> -#include <uhd/types/ranges.hpp> - -namespace uhd { namespace rfnoc { - -/*! \brief Block controller for all RFNoC-based radio blocks - */ -class UHD_RFNOC_API radio_ctrl : public source_block_ctrl_base, -                                 public sink_block_ctrl_base, -                                 public rate_node_ctrl, -                                 public tick_node_ctrl, -                                 public terminator_node_ctrl -{ -public: -    UHD_RFNOC_BLOCK_OBJECT(radio_ctrl) - -    virtual ~radio_ctrl() {} - - -    //! A wildcard channel index -    static const size_t ALL_CHANS = size_t(~0); - -    //! A wildcard gain element name -    static const std::string ALL_GAINS; - -    //! A wildcard local oscillator element name -    static const std::string ALL_LOS; - -    /************************************************************************ -     * API calls -     ***********************************************************************/ -    /*! Return the tick rate on all channels (rx and tx). -     * -     * \return The tick rate. -     */ -    virtual double get_rate() const = 0; - -    /*! Set the tick/sample rate on all channels (rx and tx). -     * -     * Will coerce to the nearest possible rate and return the actual value. -     */ -    virtual double set_rate(double rate) = 0; - -    /*! Return the selected TX antenna for channel \p chan. -     * -     * \return The selected antenna. -     */ -    virtual std::string get_tx_antenna(const size_t chan) /* const */ = 0; - -    /*! Select RX antenna \p for channel \p chan. -     * -     * \throws uhd::value_error if \p ant is not a valid value. -     */ -    virtual void set_tx_antenna(const std::string& ant, const size_t chan) = 0; - -    /*! Return the selected RX antenna for channel \p chan. -     * -     * \return The selected antenna. -     */ -    virtual std::string get_rx_antenna(const size_t chan) /* const */ = 0; - -    /*! Select RX antenna \p for channel \p chan. -     * -     * \throws uhd::value_error if \p ant is not a valid value. -     */ -    virtual void set_rx_antenna(const std::string& ant, const size_t chan) = 0; - -    /*! Return the current transmit LO frequency on channel \p chan. -     * -     * Note that the AD9361 only has one LO for all TX channels, and the -     * \p chan parameter is thus only for API compatibility. -     * -     * \return The current LO frequency. -     */ -    virtual double get_tx_frequency(const size_t chan) /* const */ = 0; - -    /*! Tune the TX LO for channel \p chan. -     * -     * This function will attempt to tune as close as possible, and return a -     * coerced value of the actual tuning result. -     * -     * \param freq Frequency in Hz -     * \param chan Channel to tune -     * -     * \return The actual LO frequency. -     */ -    virtual double set_tx_frequency(const double freq, size_t chan) = 0; - -    /*! Return the current receive LO frequency on channel \p chan. -     * -     * \return The current LO frequency. -     */ -    virtual double get_rx_frequency(const size_t chan) /* const */ = 0; - -    /*! Tune the RX LO for channel \p chan. -     * -     * This function will attempt to tune as close as possible, and return a -     * coerced value of the actual tuning result. -     * -     * \param freq Requested LO frequency -     * \param chan Channel number. -     * \return The actual LO frequency. -     */ -    virtual double set_rx_frequency(const double freq, const size_t chan) = 0; - -    /*! Return the transmit gain on channel \p chan -     * -     * \return The actual gain value -     */ -    virtual double get_tx_gain(const size_t chan) = 0; - -    /*! Set the transmit gain on channel \p chan -     * -     * This function will attempt to set the gain as close as possible, -     * and return a coerced value of the actual gain value. -     * -     * \return The actual gain value -     */ -    virtual double set_tx_gain(const double gain, const size_t chan) = 0; - -    /*! Return the transmit gain on channel \p chan -     * -     * \return The actual gain value -     */ -    virtual double get_rx_gain(const size_t chan) = 0; - -    /*! Set the transmit gain on channel \p chan -     * -     * This function will attempt to set the gain as close as possible, -     * and return a coerced value of the actual gain value. -     * -     * \return The actual gain value -     */ -    virtual double set_rx_gain(const double gain, const size_t chan) = 0; - -    /*! Return the analog filter bandwidth channel \p chan -     * -     * \return The actual bandwidth value -     */ -    virtual double get_tx_bandwidth(const size_t chan) = 0; - -    /*! Set the analog filter bandwidth channel \p chan -     * -     * This function will attempt to set the analog bandwidth. -     * -     * \return The actual bandwidth value -     */ -    virtual double set_tx_bandwidth(const double bandwidth, const size_t chan) = 0; - -    /*! Return the analog filter bandwidth channel \p chan -     * -     * \return The actual bandwidth value -     */ -    virtual double get_rx_bandwidth(const size_t chan) = 0; - -    /*! Set the analog filter bandwidth channel \p chan -     * -     * This function will attempt to set the analog bandwidth. -     * -     * \return The actual bandwidth value -     */ -    virtual double set_rx_bandwidth(const double bandwidth, const size_t chan) = 0; - -    /*! Sets the time in the radio's timekeeper to the given value. -     * -     * Note that there is a non-deterministic delay between calling this -     * function and the valung written to the register. For setting the -     * time in alignment with a certain reference time, use -     * set_time_next_pps(). -     */ -    virtual void set_time_now(const time_spec_t& time_spec) = 0; - -    /*! Set the time registers at the next pps tick. -     * -     * The values will not be latched in until the pulse occurs. -     * It is recommended that the user sleep(1) after calling to ensure -     * that the time registers will be in a known state prior to use. -     * -     * Note: Because this call sets the time on the "next" pps, -     * the seconds in the time spec should be current seconds + 1. -     * -     * \param time_spec the time to latch into the timekeeper -     */ -    virtual void set_time_next_pps(const time_spec_t& time_spec) = 0; - -    /*! Get the current time in the timekeeper registers. -     * -     * Note that there is a non-deterministic delay between the time the -     * register is read and the time the function value is returned. -     * To get the time with respect to a tick edge, use get_time_last_pps(). -     * -     * \return A timespec representing current radio time -     */ -    virtual time_spec_t get_time_now() = 0; - -    /*! Get the time when the last PPS pulse occurred. -     * -     * \return A timespec representing the last PPS -     */ -    virtual time_spec_t get_time_last_pps() = 0; - -    /*! Returns the list of GPIO banks that are associated with this radio. -     * -     * \returns list of GPIO bank names -     */ -    virtual std::vector<std::string> get_gpio_banks() const = 0; - -    /*! -     * Set a GPIO attribute on a particular GPIO bank. -     * Possible attribute names: -     *  - CTRL - 1 for ATR mode 0 for GPIO mode -     *  - DDR - 1 for output 0 for input -     *  - OUT - GPIO output level (not ATR mode) -     *  - ATR_0X - ATR idle state -     *  - ATR_RX - ATR receive only state -     *  - ATR_TX - ATR transmit only state -     *  - ATR_XX - ATR full duplex state -     * \param bank the name of a GPIO bank (e.g., FP0) -     * \param attr the name of a GPIO attribute (e.g., CTRL) -     * \param value the new value for this GPIO bank -     * \param mask the bit mask to effect which pins are changed -     */ -    virtual void set_gpio_attr(const std::string& bank, -        const std::string& attr, -        const uint32_t value, -        const uint32_t mask) = 0; - -    /*! -     * Get a GPIO attribute on a particular GPIO bank. -     * Possible attribute names: -     *  - CTRL - 1 for ATR mode 0 for GPIO mode -     *  - DDR - 1 for output 0 for input -     *  - OUT - GPIO output level (not ATR mode) -     *  - ATR_0X - ATR idle state -     *  - ATR_RX - ATR receive only state -     *  - ATR_TX - ATR transmit only state -     *  - ATR_XX - ATR full duplex state -     *  - READBACK - readback input GPIOs -     * \param bank the name of a GPIO bank -     * \param attr the name of a GPIO attribute -     * \return the value set for this attribute -     */ -    virtual uint32_t get_gpio_attr(const std::string& bank, const std::string& attr) = 0; - -    /************************************************************************** -     * LO Controls -     *************************************************************************/ -    /*! Get a list of possible LO stage names -     * -     * \param chan the channel index 0 to N-1 -     * \return a vector of strings for possible LO names -     */ -    virtual std::vector<std::string> get_rx_lo_names(const size_t chan) = 0; - -    /*! Get a list of possible LO sources. -     * -     * Channels which do not have controllable LO sources -     * will return "internal". -     * \param name the name of the LO stage to query -     * \param chan the channel index 0 to N-1 -     * \return a vector of strings for possible settings -     */ -    virtual std::vector<std::string> get_rx_lo_sources( -        const std::string& name, const size_t chan) = 0; - -    /*! -     * Get the LO frequency range of the RX LO. -     * If the channel does not have independently configurable LOs -     * the rf frequency range will be returned. -     * \param name the name of the LO stage to query -     * \param chan the channel index 0 to N-1 -     * \return a frequency range object -     */ -    virtual freq_range_t get_rx_lo_freq_range( -        const std::string& name, const size_t chan) = 0; - -    /*! -     * Set the LO source for a channel. -     * For usrps that support selectable LOs, this function -     * allows switching between them. -     * Typical options for source: internal, external. -     * \param src a string representing the LO source -     * \param name the name of the LO stage to update -     * \param chan the channel index 0 to N-1 -     */ -    virtual void set_rx_lo_source( -        const std::string& src, const std::string& name, const size_t chan) = 0; - -    /*! -     * Get the currently set LO source. -     * Channels without controllable LO sources will return -     * "internal" -     * \param name the name of the LO stage to query -     * \param chan the channel index 0 to N-1 -     * \return the configured LO source -     */ -    virtual const std::string get_rx_lo_source( -        const std::string& name, const size_t chan) = 0; - -    /*! -     * Set whether the LO used by the usrp device is exported -     * For usrps that support exportable LOs, this function -     * configures if the LO used by chan is exported or not. -     * \param enabled if true then export the LO -     * \param name the name of the LO stage to update -     * \param chan the channel index 0 to N-1 for the source channel -     */ -    virtual void set_rx_lo_export_enabled( -        bool enabled, const std::string& name, const size_t chan) = 0; - -    /*! -     * Returns true if the currently selected LO is being exported. -     * \param name the name of the LO stage to query -     * \param chan the channel index 0 to N-1 -     */ -    virtual bool get_rx_lo_export_enabled(const std::string& name, const size_t chan) = 0; - -    /*! -     * Set the RX LO frequency (Advanced). -     * \param freq the frequency to set the LO to -     * \param name the name of the LO stage to update -     * \param chan the channel index 0 to N-1 -     * \return a coerced LO frequency -     */ -    virtual double set_rx_lo_freq( -        double freq, const std::string& name, const size_t chan) = 0; - -    /*! -     * Get the current RX LO frequency (Advanced). -     * If the channel does not have independently configurable LOs -     * the current rf frequency will be returned. -     * \param name the name of the LO stage to query -     * \param chan the channel index 0 to N-1 -     * \return the configured LO frequency -     */ -    virtual double get_rx_lo_freq(const std::string& name, const size_t chan) = 0; - -    /*! Get a list of possible LO stage names -     * -     * \param chan the channel index 0 to N-1 -     * \return a vector of strings for possible LO names -     */ -    virtual std::vector<std::string> get_tx_lo_names(const size_t chan) = 0; - -    /*! Get a list of possible LO sources. -     * -     * Channels which do not have controllable LO sources -     * will return "internal". -     * \param name the name of the LO stage to query -     * \param chan the channel index 0 to N-1 -     * \return a vector of strings for possible settings -     */ -    virtual std::vector<std::string> get_tx_lo_sources( -        const std::string& name, const size_t chan) = 0; - -    /*! -     * Get the LO frequency range of the tx LO. -     * If the channel does not have independently configurable LOs -     * the rf frequency range will be returned. -     * \param name the name of the LO stage to query -     * \param chan the channel index 0 to N-1 -     * \return a frequency range object -     */ -    virtual freq_range_t get_tx_lo_freq_range( -        const std::string& name, const size_t chan) = 0; - -    /*! -     * Set the LO source for a channel. -     * For usrps that support selectable LOs, this function -     * allows switching between them. -     * Typical options for source: internal, external. -     * \param src a string representing the LO source -     * \param name the name of the LO stage to update -     * \param chan the channel index 0 to N-1 -     */ -    virtual void set_tx_lo_source( -        const std::string& src, const std::string& name, const size_t chan) = 0; - -    /*! -     * Get the currently set LO source. -     * Channels without controllable LO sources will return -     * "internal" -     * \param name the name of the LO stage to query -     * \param chan the channel index 0 to N-1 -     * \return the configured LO source -     */ -    virtual const std::string get_tx_lo_source( -        const std::string& name, const size_t chan) = 0; - -    /*! -     * Set whether the LO used by the usrp device is exported -     * For usrps that support exportable LOs, this function -     * configures if the LO used by chan is exported or not. -     * \param enabled if true then export the LO -     * \param name the name of the LO stage to update -     * \param chan the channel index 0 to N-1 for the source channel -     */ -    virtual void set_tx_lo_export_enabled( -        const bool enabled, const std::string& name, const size_t chan) = 0; - -    /*! -     * Returns true if the currently selected LO is being exported. -     * \param name the name of the LO stage to query -     * \param chan the channel index 0 to N-1 -     */ -    virtual bool get_tx_lo_export_enabled(const std::string& name, const size_t chan) = 0; - -    /*!  Set the tx LO frequency (Advanced). -     * -     * See also multi_usrp::set_tx_lo_freq(). -     * -     * \param freq the frequency to set the LO to -     * \param name the name of the LO stage to update -     * \param chan the channel index 0 to N-1 -     * \return a coerced LO frequency -     */ -    virtual double set_tx_lo_freq( -        const double freq, const std::string& name, const size_t chan) = 0; - -    /*!  Get the current TX LO frequency (Advanced). -     * -     * See also multi_usrp::get_tx_lo_freq() -     * -     * If the channel does not have independently configurable LOs -     * the current RF frequency will be returned. -     * -     * \param name the name of the LO stage to query -     * \param chan the channel index 0 to N-1 -     * \return the configured LO frequency -     */ -    virtual double get_tx_lo_freq(const std::string& name, const size_t chan) = 0; - -    /************************************************************************** -     * Time and clock control -     *************************************************************************/ - -    /*! -     * Set the time source for this radio. -     * -     * May affect other radio blocks. -     * -     * \param source A string representing the time source -     * \throws uhd::value_error if the value can't be applied -     */ -    virtual void set_time_source(const std::string& source) = 0; - -    /*! -     * Get the currently set time source. -     * -     * \return the string representing the time source -     */ -    virtual std::string get_time_source() = 0; - -    /*! -     * Get a list of possible time sources. -     * -     * \return a vector of strings for possible settings -     */ -    virtual std::vector<std::string> get_time_sources() = 0; - -    /*! -     * Set the clock source for the usrp device (for reference clock). -     * -     * Typical options for source: internal, external. -     * -     * \param source a string representing the clock source -     */ -    virtual void set_clock_source(const std::string& source) = 0; - -    /*! -     * Get the currently set clock source. -     * -     * \return the string representing the clock source -     */ -    virtual std::string get_clock_source() = 0; - -    /*! -     * Get a list of possible clock sources. -     * -     * \return a vector of strings for possible settings -     */ -    virtual std::vector<std::string> get_clock_sources() = 0; - -    /*! Given a frontend name, return the channel mapping. -     * -     * E.g.: For a TwinRX board, there's two frontends, '0' and '1', which -     * map to channels 0 and 1 respectively. A BasicRX boards has alphabetical -     * frontends (A, B) which map to channels differently. -     */ -    virtual size_t get_chan_from_dboard_fe( -        const std::string& fe, const uhd::direction_t dir) = 0; - -    /*! The inverse function to get_chan_from_dboard_fe() -     */ -    virtual std::string get_dboard_fe_from_chan( -        const size_t chan, const uhd::direction_t dir) = 0; - -    /*! Enable or disable the setting of timestamps on Rx. -     */ -    virtual void enable_rx_timestamps(const bool enable, const size_t chan) = 0; -}; /* class radio_ctrl */ - -}} /* namespace uhd::rfnoc */ - -#endif /* INCLUDED_LIBUHD_RFNOC_RADIO_CTRL_HPP */ diff --git a/host/include/uhd/rfnoc/rate_node_ctrl.hpp b/host/include/uhd/rfnoc/rate_node_ctrl.hpp deleted file mode 100644 index f04af11f4..000000000 --- a/host/include/uhd/rfnoc/rate_node_ctrl.hpp +++ /dev/null @@ -1,54 +0,0 @@ -// -// Copyright 2014 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#ifndef INCLUDED_LIBUHD_RATE_NODE_CTRL_BASE_HPP -#define INCLUDED_LIBUHD_RATE_NODE_CTRL_BASE_HPP - -#include <uhd/rfnoc/constants.hpp> -#include <uhd/rfnoc/node_ctrl_base.hpp> - -namespace uhd { namespace rfnoc { - -/*! \brief Sampling-rate-aware node control - * - * A "rate" node is a streaming node is a point in the flow graph - * that is aware of sampling rates. Such nodes include: - * - Radio Controls (these actually set a sampling rate) - * - Decimating FIR filters (their output rates depend on both - *   incoming rates and their own settings, i.e. the decimation) - * - Streaming terminators (these need to know the sampling rates - *   to configure the connected streamers) - */ -class UHD_RFNOC_API rate_node_ctrl; -class rate_node_ctrl : virtual public node_ctrl_base -{ -public: -    /*********************************************************************** -     * Types -     **********************************************************************/ -    typedef boost::shared_ptr<rate_node_ctrl> sptr; -    //! This value is used by rate nodes that don't actually set a rate themselves -    static const double RATE_UNDEFINED; - -    /*********************************************************************** -     * Rate controls -     **********************************************************************/ -    /*! Returns the sampling rate this block expects at its input. -     * -     * A radio will simply return the sampling rate it is set to. -     * A decimating FIR filter will ask downstream for the input sampling rate -     * and then return that value multiplied by the decimation factor. -     * -     */ -    virtual double get_input_samp_rate(size_t port = ANY_PORT); -    virtual double get_output_samp_rate(size_t port = ANY_PORT); - -}; /* class rate_node_ctrl */ - -}} /* namespace uhd::rfnoc */ - -#endif /* INCLUDED_LIBUHD_RATE_NODE_CTRL_BASE_HPP */ diff --git a/host/include/uhd/rfnoc/replay_block_ctrl.hpp b/host/include/uhd/rfnoc/replay_block_ctrl.hpp deleted file mode 100644 index 639d31595..000000000 --- a/host/include/uhd/rfnoc/replay_block_ctrl.hpp +++ /dev/null @@ -1,72 +0,0 @@ -// -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#ifndef INCLUDED_LIBUHD_RFNOC_REPLAY_BLOCK_HPP -#define INCLUDED_LIBUHD_RFNOC_REPLAY_BLOCK_HPP - -#include <uhd/rfnoc/sink_block_ctrl_base.hpp> -#include <uhd/rfnoc/source_block_ctrl_base.hpp> - -namespace uhd { namespace rfnoc { - -/*! \brief Replay block controller - * - * The replay block has the following features: - * - One input and one output - * - The ability to record and playback data - * - Configurable base addresses and buffer sizes - * - Independent record and playback controls - * - Radio-like playback interface - * - The storage for the replay data can be any - *   memory, usually an off-chip DRAM. - * - */ -class UHD_RFNOC_API replay_block_ctrl : public source_block_ctrl_base, -                                        public sink_block_ctrl_base -{ -public: -    UHD_RFNOC_BLOCK_OBJECT(replay_block_ctrl) - -    //! Configure the base address and size of the record buffer region (in bytes). -    virtual void config_record( -        const uint32_t base_addr, const uint32_t size, const size_t chan) = 0; - -    //! Configure the base address and size of the playback buffer region (in bytes). -    virtual void config_play( -        const uint32_t base_addr, const uint32_t size, const size_t chan) = 0; - -    //! Restarts recording at the beginning of the record buffer -    virtual void record_restart(const size_t chan) = 0; - -    //! Returns the base address of the record buffer (in bytes). -    virtual uint32_t get_record_addr(const size_t chan) = 0; - -    //! Returns the base address of the playback buffer (in bytes). -    virtual uint32_t get_play_addr(const size_t chan) = 0; - -    //! Returns the size of the record buffer (in bytes). -    virtual uint32_t get_record_size(const size_t chan) = 0; - -    //! Returns the current fullness of the record buffer (in bytes). -    virtual uint32_t get_record_fullness(const size_t chan) = 0; - -    //! Returns the size of the playback buffer (in bytes). -    virtual uint32_t get_play_size(const size_t chan) = 0; - -    //! Sets the size of the packets played by the Replay block (in 64-bit words) -    virtual void set_words_per_packet(const uint32_t num_words, const size_t chan) = 0; - -    //! Returns the size of the packets played by the Replay block (in 64-bit words) -    virtual uint32_t get_words_per_packet(const size_t chan) = 0; - -    //! Halts playback and clears the playback command FIFO -    virtual void play_halt(const size_t chan) = 0; - -}; /* class replay_block_ctrl*/ - -}} /* namespace uhd::rfnoc */ - -#endif /* INCLUDED_LIBUHD_RFNOC_REPLAY_BLOCK_HPP */ diff --git a/host/include/uhd/rfnoc/scalar_node_ctrl.hpp b/host/include/uhd/rfnoc/scalar_node_ctrl.hpp deleted file mode 100644 index 910a94b0c..000000000 --- a/host/include/uhd/rfnoc/scalar_node_ctrl.hpp +++ /dev/null @@ -1,62 +0,0 @@ -// -// Copyright 2014 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#ifndef INCLUDED_LIBUHD_SCALAR_NODE_CTRL_BASE_HPP -#define INCLUDED_LIBUHD_SCALAR_NODE_CTRL_BASE_HPP - -#include <uhd/rfnoc/constants.hpp> -#include <uhd/rfnoc/node_ctrl_base.hpp> - -namespace uhd { namespace rfnoc { - -/*! \brief Scaling node control - * - * A "scalar" node is a streaming node in which a scaling takes - * place, usually for the conversion between fixed point and floating - * point (the latter usually being normalized between -1 and 1). - * - * Such blocks include: - * - Radio Controls - * - Potentially FFTs or FIRs, if they affect scaling - */ -class UHD_RFNOC_API scalar_node_ctrl; -class scalar_node_ctrl : virtual public node_ctrl_base -{ -public: -    /*********************************************************************** -     * Types -     **********************************************************************/ -    typedef boost::shared_ptr<scalar_node_ctrl> sptr; -    //! Undefined scaling -    static const double SCALE_UNDEFINED; - -    /*********************************************************************** -     * Scaling controls -     **********************************************************************/ -    /*! Returns the scaling factor for this block on input. -     * -     * A DUC block will return the scaling factor as determined by the duc -     * stage. -     * -     * \param port Port Number -     */ -    virtual double get_input_scale_factor(size_t port = ANY_PORT); - -    /*! Returns the scaling factor for this block on output. -     * -     * A DDC block will return the scaling factor as determined by the ddc -     * stage. -     * -     * \param port Port Number -     */ -    virtual double get_output_scale_factor(size_t port = ANY_PORT); - -}; /* class scalar_node_ctrl */ - -}} /* namespace uhd::rfnoc */ - -#endif /* INCLUDED_LIBUHD_SCALAR_NODE_CTRL_BASE_HPP */ diff --git a/host/include/uhd/rfnoc/siggen_block_ctrl.hpp b/host/include/uhd/rfnoc/siggen_block_ctrl.hpp deleted file mode 100644 index c58d3490d..000000000 --- a/host/include/uhd/rfnoc/siggen_block_ctrl.hpp +++ /dev/null @@ -1,25 +0,0 @@ -// -// Copyright 2014-2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#ifndef INCLUDED_LIBUHD_RFNOC_SIGGEN_BLOCK_CTRL_HPP -#define INCLUDED_LIBUHD_RFNOC_SIGGEN_BLOCK_CTRL_HPP - -#include <uhd/rfnoc/sink_block_ctrl_base.hpp> -#include <uhd/rfnoc/source_block_ctrl_base.hpp> - -namespace uhd { namespace rfnoc { - -class UHD_RFNOC_API siggen_block_ctrl : public source_block_ctrl_base, -                                        public sink_block_ctrl_base -{ -public: -    UHD_RFNOC_BLOCK_OBJECT(siggen_block_ctrl) - -}; /* class siggen_block_ctrl*/ - -}} /* namespace uhd::rfnoc */ - -#endif /* INCLUDED_LIBUHD_RFNOC_SIGGEN_BLOCK_CTRL_HPP */ diff --git a/host/include/uhd/rfnoc/sink_block_ctrl_base.hpp b/host/include/uhd/rfnoc/sink_block_ctrl_base.hpp deleted file mode 100644 index 5267612e6..000000000 --- a/host/include/uhd/rfnoc/sink_block_ctrl_base.hpp +++ /dev/null @@ -1,118 +0,0 @@ -// -// Copyright 2014 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#ifndef INCLUDED_LIBUHD_TX_BLOCK_CTRL_BASE_HPP -#define INCLUDED_LIBUHD_TX_BLOCK_CTRL_BASE_HPP - -#include <uhd/rfnoc/block_ctrl_base.hpp> -#include <uhd/rfnoc/sink_node_ctrl.hpp> - -namespace uhd { namespace rfnoc { - -/*! \brief Extends block_ctrl_base with input capabilities. - * - * A sink block is an RFNoC block that can receive data at an input. - * We can use this block to transmit data (In RFNoC nomenclature, a - * transmit operation means streaming data to the device from the host). - * - * Every input is defined by a port definition (port_t). - */ -class UHD_RFNOC_API sink_block_ctrl_base; -class sink_block_ctrl_base : virtual public block_ctrl_base, virtual public sink_node_ctrl -{ -public: -    typedef boost::shared_ptr<sink_block_ctrl_base> sptr; - -    /*********************************************************************** -     * Stream signatures -     **********************************************************************/ -    /*! Return the input stream signature for a given block port. -     * -     * The actual signature is determined by the current configuration -     * and the block definition file. The value returned here is calculated -     * on-the-fly and is only valid as long as the configuration does not -     * change. -     * -     * \returns The stream signature for port \p block_port -     * \throws uhd::runtime_error if \p block_port is not a valid port -     */ -    stream_sig_t get_input_signature(size_t block_port = 0) const; - -    /*! Return a list of valid input ports. -     */ -    std::vector<size_t> get_input_ports() const; - -    /*********************************************************************** -     * FPGA Configuration -     **********************************************************************/ -    /*! Return the size of input buffer on a given block port. -     * -     * This is necessary for setting up flow control, among other things. -     * Note: This does not query the block's settings register. The FIFO size -     * is queried once during construction and cached. -     * -     * If the block port is not defined, it will return 0, and not throw. -     * -     * \param block_port The block port (0 through 15). -     * -     * Returns the size of the buffer in bytes. -     */ -    size_t get_fifo_size(size_t block_port = 0) const; - -    /*! Return the MTU size on a given block port. -     * -     * This is necessary for setting up transports, among other things. -     * -     * If the block port is not defined, it will return 0, and not throw. -     * -     * \param block_port The block port (0 through 15). -     * -     * Returns the MTU in bytes. -     */ -    size_t get_mtu(size_t block_port = 0) const; - -    /*! Configure flow control for incoming streams. -     * -     * If flow control is enabled for incoming streams, this block will periodically -     * send out ACKs, telling the upstream block which packets have been consumed, -     * so the upstream block can increase his flow control credit. -     * -     * In the default implementation, this just sets register SR_FLOW_CTRL_PKTS_PER_ACK -     * accordingly. -     * -     * Override this function if your block has port-specific flow control settings. -     * -     * \param bytes Send an ACK after this many bytes have been consumed. -     *              Setting this to zero disables flow control acknowledgement. -     * \param block_port Set up flow control for a stream coming in on this particular -     * block port. -     */ -    virtual void configure_flow_control_in( -        const size_t bytes, const size_t block_port = 0); - -    /*! Configure the behaviour for errors on incoming packets -     *  (e.g. sequence errors). -     * -     * -     */ -    virtual void set_error_policy(const std::string& policy); - -protected: -    /*********************************************************************** -     * Hooks -     **********************************************************************/ -    /*! Like sink_node_ctrl::_request_input_port(), but also checks -     * the port has an input signature. -     */ -    virtual size_t _request_input_port( -        const size_t suggested_port, const uhd::device_addr_t& args) const; - -}; /* class sink_block_ctrl_base */ - -}} /* namespace uhd::rfnoc */ - -#endif /* INCLUDED_LIBUHD_TX_BLOCK_CTRL_BASE_HPP */ diff --git a/host/include/uhd/rfnoc/sink_node_ctrl.hpp b/host/include/uhd/rfnoc/sink_node_ctrl.hpp deleted file mode 100644 index 22100f4c5..000000000 --- a/host/include/uhd/rfnoc/sink_node_ctrl.hpp +++ /dev/null @@ -1,117 +0,0 @@ -// -// Copyright 2014-2016 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#ifndef INCLUDED_LIBUHD_SINK_NODE_CTRL_BASE_HPP -#define INCLUDED_LIBUHD_SINK_NODE_CTRL_BASE_HPP - -#include <uhd/rfnoc/constants.hpp> -#include <uhd/rfnoc/node_ctrl_base.hpp> -#include <uhd/rfnoc/sink_node_ctrl.hpp> -#include <boost/thread.hpp> - -namespace uhd { namespace rfnoc { - -/*! \brief Abstract class for sink nodes. - * - * Sink nodes can have upstream blocks. - */ -class UHD_RFNOC_API sink_node_ctrl; -class sink_node_ctrl : virtual public node_ctrl_base -{ -public: -    /*********************************************************************** -     * Types -     **********************************************************************/ -    typedef boost::shared_ptr<sink_node_ctrl> sptr; -    typedef std::map<size_t, boost::weak_ptr<sink_node_ctrl> > node_map_t; -    typedef std::pair<size_t, boost::weak_ptr<sink_node_ctrl> > node_map_pair_t; - -    /*********************************************************************** -     * Sink block controls -     **********************************************************************/ -    /*! Connect another node upstream of this node. -     * -     * *Note:* If additional settings are required to make this connection work, -     * e.g. configure flow control, these need to be done separately. -     * -     * If the requested connection is not possible, this function will throw. -     * -     * \p upstream_node Pointer to the node class to connect -     * \p port Suggested port number on this block to connect the upstream -     *         block to. -     * \p args Any arguments that can be useful for determining the port number. -     * -     * \returns The actual port number used. -     */ -    size_t connect_upstream(node_ctrl_base::sptr upstream_node, -        size_t port                    = ANY_PORT, -        const uhd::device_addr_t& args = uhd::device_addr_t()); - -    /*! Call this function to notify a node about its streamer activity. -     * -     * When \p active is set to true, this means this block is now part of -     * an active tx streamer chain. Conversely, when set to false, this means -     * the node has been removed from an tx streamer chain. -     */ -    virtual void set_tx_streamer(bool active, const size_t port); - - -protected: -    /*! Ask for a port number to connect an upstream block to. -     * -     * Typically, this will be overridden for custom behaviour. -     * The default is to return the suggested port, disregarding -     * \p args, unless \p port == ANY_PORT, in which case the first -     * unused input port is returned. -     * -     * When deriving this function for custom behaviour, consider: -     * - The result is used to call register_upstream_node(), which -     *   has its own checks in place. -     * - This function may throw if the arguments can't be resolved. -     *   The exception will propagate to the user space. -     * - Alternatively, the function may return ANY_PORT to signify -     *   failure. -     * - \p args and \p suggested_port should be treated as strong -     *   suggestions, but there's no reason to just return any valid -     *   port. -     * -     * *Note:* For reasons of thread safety, it is recommended to -     * never, ever call this function directly. It will be used by -     * connect_upstream() which will handle the connection process -     * in a thread-safe manner. -     * -     * \param suggested_port Try and connect here. -     * \param args When deciding on a port number, these arguments may be used. -     * -     * \returns A valid input port, or ANY_PORT on failure. -     */ -    virtual size_t _request_input_port( -        const size_t suggested_port, const uhd::device_addr_t& args) const; - -private: -    /*! Makes connecting something to the input thread-safe. -     */ -    boost::mutex _input_mutex; - -    /*! Register a node upstream of this one (i.e., a node that can send data to this -     * node). -     * -     * By definition, the upstream node must of type source_node_ctrl. -     * -     * This saves a *weak pointer* to the upstream node and checks the port is -     * available. Will throw otherwise. -     * -     * \param upstream_node A pointer to the node instantiation -     * \param port Port number the upstream node is connected to -     */ -    void _register_upstream_node(node_ctrl_base::sptr upstream_node, size_t port); - -}; /* class sink_node_ctrl */ - -}} /* namespace uhd::rfnoc */ - -#endif /* INCLUDED_LIBUHD_SINK_NODE_CTRL_BASE_HPP */ diff --git a/host/include/uhd/rfnoc/source_block_ctrl_base.hpp b/host/include/uhd/rfnoc/source_block_ctrl_base.hpp deleted file mode 100644 index e79b7ef69..000000000 --- a/host/include/uhd/rfnoc/source_block_ctrl_base.hpp +++ /dev/null @@ -1,148 +0,0 @@ -// -// Copyright 2014 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#ifndef INCLUDED_LIBUHD_RX_BLOCK_CTRL_BASE_HPP -#define INCLUDED_LIBUHD_RX_BLOCK_CTRL_BASE_HPP - -#include <uhd/rfnoc/block_ctrl_base.hpp> -#include <uhd/rfnoc/source_node_ctrl.hpp> - -namespace uhd { namespace rfnoc { - -/*! \brief Extends block_ctrl_base with receive capabilities. - * - * In RFNoC nomenclature, a receive operation means streaming - * data from the device (the crossbar) to the host. - * If a block has receive capabilities, this means we can receive - * data *from* this block. - */ -class UHD_RFNOC_API source_block_ctrl_base; -class source_block_ctrl_base : virtual public block_ctrl_base, -                               virtual public source_node_ctrl -{ -public: -    typedef boost::shared_ptr<source_block_ctrl_base> sptr; - -    /*********************************************************************** -     * Streaming operations -     **********************************************************************/ -    /*! Issue a stream command for this block. -     * -     * There is no guaranteed action for this command. The default implementation -     * is to send this command to the next upstream block, or issue a warning if -     * there is no upstream block registered. -     * -     * However, implementations of block_ctrl_base might choose to do whatever seems -     * appropriate, including throwing exceptions. This may also be true for some -     * stream commands and not for others (i.e. STREAM_MODE_START_CONTINUOUS may be -     * implemented, and STREAM_MODE_NUM_SAMPS_AND_DONE may be not). -     * -     * This function does not check for infinite loops. Example: Say you have two blocks, -     * which are both registered as upstream from one another. If they both use -     * block_ctrl_base::issue_stream_cmd(), then the stream command will be passed from -     * one block to another indefinitely. This will not happen if one the block's -     * controller classes overrides this function and actually handles it. -     * -     * See also register_upstream_block(). -     * -     * \param stream_cmd The stream command. -     * \param chan Channel for which this command is meant (data shall be produced on this -     * channel). -     */ -    virtual void issue_stream_cmd( -        const uhd::stream_cmd_t& stream_cmd, const size_t chan = 0); - -    /*********************************************************************** -     * Stream signatures -     **********************************************************************/ -    /*! Return the output stream signature for a given block port. -     * -     * The actual signature is determined by the current configuration -     * and the block definition file. The value returned here is calculated -     * on-the-fly and is only valid as long as the configuration does not -     * change. -     * -     * \returns The stream signature for port \p block_port -     * \throws uhd::runtime_error if \p block_port is not a valid port -     */ -    stream_sig_t get_output_signature(size_t block_port = 0) const; - -    /*! Return a list of valid output ports. -     */ -    std::vector<size_t> get_output_ports() const; - -    /*********************************************************************** -     * FPGA Configuration -     **********************************************************************/ -    /*! Configures data flowing from port \p output_block_port to go to \p next_address -     * -     * \param next_address Address of the downstream block -     * \param output_block_port Port for which this is valid -     * -     * In the default implementation, this will write the value in \p next_address -     * to register SR_NEXT_DST of this blocks settings bus. The value will also -     * have bit 16 set to 1, since some blocks require this to respect this value. -     */ -    virtual void set_destination(uint32_t next_address, size_t output_block_port = 0); - -    /*! Configure flow control for outgoing streams. -     * -     * In the default implementation, this just sets registers SR_FLOW_CTRL_BUF_SIZE -     * and SR_FLOW_CTRL_ENABLE accordingly; \b block_port and \p sid are ignored. -     * -     * Override this function if your block has port-specific flow control settings. -     * -     * \param enable_output Enable flow control module's output. If disabled, no packets -     * will be output regardless of flow control state. \param buf_size_bytes The size of -     * the downstream block's input FIFO size in number of bytes. Setting this to zero -     * disables byte based flow control. If both byte based flow control and the packet -     * limit are set to zero, the block will then produce data as fast as it can. \b -     * Warning: This can cause head-of-line blocking, and potentially lock up your device! -     * \param lossless_link The link for the connection is lossless.  Periodic sync -     * packets will be disabled. \param pkt_limit Limit the maximum number of packets in -     * flight. Setting this to zero disables packet limiting. Usually kept disabled except -     * for special case connections (such as DMA) that support only a finite number of -     * packets in flight. \param block_port Specify on which outgoing port this setting is -     * valid. \param sid The SID for which this is valid. This is meant for cases where -     * the outgoing block port is not sufficient to set the flow control, and as such is -     * rarely used. -     */ -    virtual void configure_flow_control_out(const bool enable_output, -        const bool lossless_link, -        const size_t buf_size_bytes, -        const size_t pkt_limit  = 0, -        const size_t block_port = 0, -        const uhd::sid_t& sid   = uhd::sid_t()); - -    /*! Return the MTU size on a given block port. -     * -     * This is necessary for setting up transports, among other things. -     * -     * If the block port is not defined, it will return 0, and not throw. -     * -     * \param block_port The block port (0 through 15). -     * -     * Returns the MTU in bytes. -     */ -    size_t get_mtu(size_t block_port = 0) const; - - -protected: -    /*********************************************************************** -     * Hooks -     **********************************************************************/ -    /*! Like source_node_ctrl::_request_output_port(), but also checks if -     * the port has an output signature. -     */ -    virtual size_t _request_output_port( -        const size_t suggested_port, const uhd::device_addr_t& args) const; - -}; /* class source_block_ctrl_base */ - -}} /* namespace uhd::rfnoc */ - -#endif /* INCLUDED_LIBUHD_RX_BLOCK_CTRL_BASE_HPP */ diff --git a/host/include/uhd/rfnoc/source_node_ctrl.hpp b/host/include/uhd/rfnoc/source_node_ctrl.hpp deleted file mode 100644 index 1dcc1ecfb..000000000 --- a/host/include/uhd/rfnoc/source_node_ctrl.hpp +++ /dev/null @@ -1,106 +0,0 @@ -// -// Copyright 2014 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#ifndef INCLUDED_LIBUHD_SOURCE_NODE_CTRL_BASE_HPP -#define INCLUDED_LIBUHD_SOURCE_NODE_CTRL_BASE_HPP - -#include <uhd/rfnoc/constants.hpp> -#include <uhd/rfnoc/node_ctrl_base.hpp> -#include <uhd/types/stream_cmd.hpp> -#include <boost/thread.hpp> - -namespace uhd { namespace rfnoc { - -/*! \brief Abstract class for source nodes. - * - * Source nodes can have downstream blocks. - */ -class UHD_RFNOC_API source_node_ctrl; -class source_node_ctrl : virtual public node_ctrl_base -{ -public: -    /*********************************************************************** -     * Types -     **********************************************************************/ -    typedef boost::shared_ptr<source_node_ctrl> sptr; -    typedef std::map<size_t, boost::weak_ptr<source_node_ctrl> > node_map_t; -    typedef std::pair<size_t, boost::weak_ptr<source_node_ctrl> > node_map_pair_t; - -    /*********************************************************************** -     * Source block controls -     **********************************************************************/ -    /*! Issue a stream command for this block. -     * \param stream_cmd The stream command. -     * \param chan Channel Index -     */ -    virtual void issue_stream_cmd( -        const uhd::stream_cmd_t& stream_cmd, const size_t chan = 0) = 0; - -    /*! Connect another node downstream of this node. -     * -     * *Note:* If additional settings are required to make this connection work, -     * e.g. configure flow control, these need to be done separately. -     * -     * If the requested connection is not possible, this function will throw. -     * -     * \p downstream_node Pointer to the node class to connect -     * \p port Suggested port number on this block to connect the downstream -     *         block to. -     * \p args Any arguments that can be useful for determining the port number. -     * -     * \returns The actual port number used. -     */ -    size_t connect_downstream(node_ctrl_base::sptr downstream_node, -        size_t port                    = ANY_PORT, -        const uhd::device_addr_t& args = uhd::device_addr_t()); - -    /*! Call this function to notify a node about its streamer activity. -     * -     * When \p active is set to true, this means this block is now part of -     * an active rx streamer chain. Conversely, when set to false, this means -     * the node has been removed from an rx streamer chain. -     */ -    virtual void set_rx_streamer(bool active, const size_t port); - -protected: -    /*! Ask for a port number to connect a downstream block to. -     * -     * See sink_node_ctrl::_request_input_port(). This is the same -     * for output. -     * -     * \param suggested_port Try and connect here. -     * \param args When deciding on a port number, these arguments may be used. -     * -     * \returns A valid input port, or ANY_PORT on failure. -     */ -    virtual size_t _request_output_port( -        const size_t suggested_port, const uhd::device_addr_t& args) const; - - -private: -    /*! Makes connecting something to the output thread-safe. -     */ -    boost::mutex _output_mutex; - -    /*! Register a node downstream of this one (i.e., a node that receives data from this -     * node). -     * -     * By definition, the upstream node must of type sink_node_ctrl. -     * -     * This saves a *weak pointer* to the downstream node and checks -     * the port is available. Will throw otherwise. -     * -     * \param downstream_node A pointer to the node instantiation -     * \param port Port number the downstream node is connected to -     */ -    void _register_downstream_node(node_ctrl_base::sptr downstream_node, size_t port); - -}; /* class source_node_ctrl */ - -}} /* namespace uhd::rfnoc */ - -#endif /* INCLUDED_LIBUHD_SOURCE_NODE_CTRL_BASE_HPP */ diff --git a/host/include/uhd/rfnoc/stream_sig.hpp b/host/include/uhd/rfnoc/stream_sig.hpp deleted file mode 100644 index 3b8482781..000000000 --- a/host/include/uhd/rfnoc/stream_sig.hpp +++ /dev/null @@ -1,80 +0,0 @@ -// -// Copyright 2014-2015 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#ifndef INCLUDED_LIBUHD_RFNOC_STREAMSIG_HPP -#define INCLUDED_LIBUHD_RFNOC_STREAMSIG_HPP - -#include <uhd/config.hpp> -#include <iostream> - -namespace uhd { namespace rfnoc { - -/*! Describes a stream signature for data going to or coming from - * RFNoC ports. - * - * The stream signature may depend on a block's configuration. Even - * so, some attributes may be left undefined (e.g., a FIFO block - * works for any item type, so it doesn't need to set it). - */ -class UHD_RFNOC_API stream_sig_t -{ -public: -    /*********************************************************************** -     * Structors -     ***********************************************************************/ -    stream_sig_t(); - -    /*********************************************************************** -     * The stream signature attributes -     ***********************************************************************/ -    //! The data type of the individual items (e.g. 'sc16'). If undefined, set -    // to empty. -    std::string item_type; - -    //! The vector length in multiples of items. If undefined, set to zero. -    size_t vlen; - -    //! Packet size in bytes. If undefined, set to zero. -    size_t packet_size; - -    bool is_bursty; - -    /*********************************************************************** -     * Helpers -     ***********************************************************************/ -    //! Compact string representation -    std::string to_string(); -    //! Pretty-print string representation -    std::string to_pp_string(); - -    //! Returns the number of bytes necessary to store one item. -    // Note: The vector length is *not* considered here. -    // -    // \returns Number of bytes per item or 0 if the item type is -    //          undefined. -    // \throws uhd::key_error if the item type is invalid. -    size_t get_bytes_per_item() const; - -    /*! Check if an output with signature \p output_sig could -     * stream to an input signature \p input_sig. -     * -     * \return true if streams are compatible -     */ -    static bool is_compatible( -        const stream_sig_t& output_sig, const stream_sig_t& input_sig); -}; - -//! Shortcut for << stream_sig.to_string() -UHD_INLINE std::ostream& operator<<(std::ostream& out, stream_sig_t stream_sig) -{ -    out << stream_sig.to_string().c_str(); -    return out; -} - -}} /* namespace uhd::rfnoc */ - -#endif /* INCLUDED_LIBUHD_RFNOC_STREAMSIG_HPP */ diff --git a/host/include/uhd/rfnoc/terminator_node_ctrl.hpp b/host/include/uhd/rfnoc/terminator_node_ctrl.hpp deleted file mode 100644 index 5909a6367..000000000 --- a/host/include/uhd/rfnoc/terminator_node_ctrl.hpp +++ /dev/null @@ -1,41 +0,0 @@ -// -// Copyright 2015 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#ifndef INCLUDED_LIBUHD_TERMINATOR_NODE_CTRL_BASE_HPP -#define INCLUDED_LIBUHD_TERMINATOR_NODE_CTRL_BASE_HPP - -#include <uhd/rfnoc/node_ctrl_base.hpp> - -namespace uhd { namespace rfnoc { - -/*! \brief Abstract class for terminator nodes (i.e. nodes that terminate - *         the flow graph). - * - * Terminator nodes have the following properties: - * - Data flowing into such a node is not propagated to any other node, and - *   data coming out of this node originates in this node. - * - Chain commands are not propagated past this node. - * - * A block may be a terminator node, but have both upstream and downstream - * nodes. An example is the radio block, which can be used for Rx and Tx. - * Even if it's used for both, the data going into the radio block is not - * the data coming out. - */ -class UHD_RFNOC_API terminator_node_ctrl; -class terminator_node_ctrl : virtual public node_ctrl_base -{ -public: -    /*********************************************************************** -     * Types -     **********************************************************************/ -    typedef boost::shared_ptr<terminator_node_ctrl> sptr; - -}; /* class terminator_node_ctrl */ - -}} /* namespace uhd::rfnoc */ - -#endif /* INCLUDED_LIBUHD_TERMINATOR_NODE_CTRL_BASE_HPP */ diff --git a/host/include/uhd/rfnoc/tick_node_ctrl.hpp b/host/include/uhd/rfnoc/tick_node_ctrl.hpp deleted file mode 100644 index da75a209f..000000000 --- a/host/include/uhd/rfnoc/tick_node_ctrl.hpp +++ /dev/null @@ -1,60 +0,0 @@ -// -// Copyright 2014 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#ifndef INCLUDED_LIBUHD_TICK_NODE_CTRL_BASE_HPP -#define INCLUDED_LIBUHD_TICK_NODE_CTRL_BASE_HPP - -#include <uhd/rfnoc/constants.hpp> -#include <uhd/rfnoc/node_ctrl_base.hpp> - -namespace uhd { namespace rfnoc { - -/*! \brief Tick-rate-aware node control - * - * A "rate" node is a streaming node is a point in the flow graph - * that is aware of tick rates (time base). Such nodes include: - * - Radio Controls - * - Data generating blocks that add time stamps - */ -class UHD_RFNOC_API tick_node_ctrl; -class tick_node_ctrl : virtual public node_ctrl_base -{ -public: -    /*********************************************************************** -     * Types -     **********************************************************************/ -    typedef boost::shared_ptr<tick_node_ctrl> sptr; - -    /*********************************************************************** -     * Constants -     **********************************************************************/ -    //! This value is used by rate nodes that don't actually set a rate themselves -    static const double RATE_UNDEFINED; - -    /*********************************************************************** -     * Rate controls -     **********************************************************************/ -    /*! Return a tick rate. -     * -     * This might be either a tick rate defined by this block (see also _get_tick_rate()) -     * or it's a tick rate defined by an adjacent block. -     * In that case, performs a graph search to figure out the tick rate. -     */ -    double get_tick_rate(const std::set<node_ctrl_base::sptr>& _explored_nodes = -                             std::set<node_ctrl_base::sptr>()); - -protected: -    virtual double _get_tick_rate() -    { -        return RATE_UNDEFINED; -    }; - -}; /* class tick_node_ctrl */ - -}} /* namespace uhd::rfnoc */ - -#endif /* INCLUDED_LIBUHD_TICK_NODE_CTRL_BASE_HPP */ diff --git a/host/include/uhd/rfnoc/window_block_ctrl.hpp b/host/include/uhd/rfnoc/window_block_ctrl.hpp deleted file mode 100644 index ee5439b40..000000000 --- a/host/include/uhd/rfnoc/window_block_ctrl.hpp +++ /dev/null @@ -1,54 +0,0 @@ -// -// Copyright 2014-2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#ifndef INCLUDED_LIBUHD_RFNOC_WINDOW_BLOCK_CTRL_HPP -#define INCLUDED_LIBUHD_RFNOC_WINDOW_BLOCK_CTRL_HPP - -#include <uhd/rfnoc/sink_block_ctrl_base.hpp> -#include <uhd/rfnoc/source_block_ctrl_base.hpp> - -namespace uhd { namespace rfnoc { - -/*! \brief Block controller for the standard windowing RFNoC block. - * - * The standard windowing block has the following features: - * - One input- and output-port - * - Configurable window length and coefficients - * - Supports data type sc16 (16-Bit fix-point complex samples) - * - * This block requires packets to be the same size as the downstream FFT length. - * It will perform one window operation per incoming packet, treating it - * as a vector of samples. - */ -class UHD_RFNOC_API window_block_ctrl : public source_block_ctrl_base, -                                        public sink_block_ctrl_base -{ -public: -    UHD_RFNOC_BLOCK_OBJECT(window_block_ctrl) - -    static const size_t MAX_COEFF_VAL       = 32767; -    static const uint32_t SR_WINDOW_LEN     = 131; // Note: AXI config bus uses 129 & 130 -    static const uint32_t RB_MAX_WINDOW_LEN = 0; -    static const uint32_t AXIS_WINDOW_LOAD  = AXIS_CONFIG_BUS + 0; // 2*0+0 -    static const uint32_t AXIS_WINDOW_LOAD_TLAST = AXIS_CONFIG_BUS + 1; // 2*0+1 - -    //! Configure the window coefficients -    // -    // \p coeffs size determines the window length. If it longer than -    // the maximum window length, throws a uhd::value_error. -    virtual void set_window(const std::vector<int>& coeffs) = 0; - -    //! Returns the maximum window length. -    virtual size_t get_max_len() const = 0; - -    //! Returns the current window length. -    virtual size_t get_window_len() const = 0; - -}; /* class window_block_ctrl*/ - -}} /* namespace uhd::rfnoc */ - -#endif /* INCLUDED_LIBUHD_RFNOC_WINDOW_BLOCK_CTRL_HPP */ diff --git a/host/include/uhd/transport/CMakeLists.txt b/host/include/uhd/transport/CMakeLists.txt index 400b3db0b..a74f025bf 100644 --- a/host/include/uhd/transport/CMakeLists.txt +++ b/host/include/uhd/transport/CMakeLists.txt @@ -6,6 +6,7 @@  #  UHD_INSTALL(FILES +    adapter_id.hpp      bounded_buffer.hpp      bounded_buffer.ipp      buffer_pool.hpp diff --git a/host/include/uhd/transport/zero_copy.hpp b/host/include/uhd/transport/zero_copy.hpp index 09b39f454..c59213e92 100644 --- a/host/include/uhd/transport/zero_copy.hpp +++ b/host/include/uhd/transport/zero_copy.hpp @@ -23,11 +23,6 @@ class UHD_API managed_buffer  public:      managed_buffer(void) : _ref_count(0), _buffer(NULL), _length(0)      { -#ifdef UHD_TXRX_DEBUG_PRINTS -        _mb_num = s_buffer_count; -        // From Boost website: atomic_count seems only to have precrement operator. -        ++s_buffer_count; -#endif      }      virtual ~managed_buffer(void) {} @@ -83,24 +78,11 @@ public:          return (int)_ref_count;      } -#ifdef UHD_TXRX_DEBUG_PRINTS -    int num() const -    { -        return _mb_num; -    } -#endif -  protected:      void* _buffer;      size_t _length; -#ifdef UHD_TXRX_DEBUG_PRINTS -    int _mb_num; -#endif  private: -#ifdef UHD_TXRX_DEBUG_PRINTS -    static boost::detail::atomic_count s_buffer_count; -#endif  };  UHD_INLINE void intrusive_ptr_add_ref(managed_buffer* p) diff --git a/host/include/uhd/transport/zero_copy_recv_offload.hpp b/host/include/uhd/transport/zero_copy_recv_offload.hpp deleted file mode 100644 index 04878f72d..000000000 --- a/host/include/uhd/transport/zero_copy_recv_offload.hpp +++ /dev/null @@ -1,40 +0,0 @@ -// -// Copyright 2016 Ettus Research -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#ifndef INCLUDED_UHD_ZERO_COPY_RECV_OFFLOAD_HPP -#define INCLUDED_UHD_ZERO_COPY_RECV_OFFLOAD_HPP - -#include <uhd/config.hpp> -#include <uhd/transport/zero_copy.hpp> -#include <boost/shared_ptr.hpp> - -namespace uhd { namespace transport { - -/*! - * A threaded transport offload that is meant to relieve the main thread of - * the responsibility of making receive calls. - */ -class UHD_API zero_copy_recv_offload : public virtual zero_copy_if -{ -public: -    typedef boost::shared_ptr<zero_copy_recv_offload> sptr; - -    /*! -     * This transport offload adds a receive thread in order to -     * communicate with the underlying transport. It is meant to be -     * used in cases where the main thread needs to be relieved of the burden -     * of the underlying transport receive calls. -     * -     * \param transport a shared pointer to the transport interface -     * \param timeout a general timeout for pushing and pulling on the bounded buffer -     */ -    static sptr make(zero_copy_if::sptr transport, const double timeout); -}; - -}} // namespace uhd::transport - -#endif /* INCLUDED_ZERO_COPY_OFFLOAD_HPP */ diff --git a/host/include/uhd/types/CMakeLists.txt b/host/include/uhd/types/CMakeLists.txt index a0eccc3f0..47f68315d 100644 --- a/host/include/uhd/types/CMakeLists.txt +++ b/host/include/uhd/types/CMakeLists.txt @@ -1,17 +1,18 @@  #  # Copyright 2010-2011,2015-2016 Ettus Research LLC  # Copyright 2018 Ettus Research, a National Instruments Company +# Copyright 2019 Ettus Research, a National Instruments Brand  #  # SPDX-License-Identifier: GPL-3.0-or-later  # -  UHD_INSTALL(FILES      byte_vector.hpp      device_addr.hpp      dict.ipp      dict.hpp      direction.hpp +    eeprom.hpp      endianness.hpp      io_type.hpp      mac_addr.hpp @@ -20,7 +21,6 @@ UHD_INSTALL(FILES      ref_vector.hpp      sensors.hpp      serial.hpp -    sid.hpp      stream_cmd.hpp      time_spec.hpp      tune_request.hpp diff --git a/host/include/uhd/types/sid.hpp b/host/include/uhd/types/sid.hpp deleted file mode 100644 index c552bdeb3..000000000 --- a/host/include/uhd/types/sid.hpp +++ /dev/null @@ -1,268 +0,0 @@ -// -// Copyright 2014-2016 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#ifndef INCLUDED_UHD_TYPES_SID_HPP -#define INCLUDED_UHD_TYPES_SID_HPP - -#include <uhd/config.hpp> -#include <stdint.h> -#include <iostream> - -namespace uhd { -/*! - * \brief Represents a stream ID (SID). - * - * A stream ID (SID) is an identifier for data. - * It is a 32-Bit value which consists of 16 Bits - * for the source address and 16 Bits for the destination - * address. - * Every address is split into two parts: The _address_, which - * identifies the device used, and the _endpoint_, which identifies - * a specific object inside the given device (e.g., a block). - * *Note:* In the case where there are several crossbars on a single - * device, each crossbar gets its own address. - * Both address and endpoint are 8 bits in length. If a 16-bit address - * is required, we use the combination of the 8-bit address and the 8-bit - * endpoint. - * - * <pre> - * +-------------+--------------+-------------+--------------+ - * | SRC address | SRC endpoint | DST address | DST endpoint | - * +-------------+--------------+-------------+--------------+ - * </pre> - * - * \section sid_str_repr String Representation (pretty printing) - * - * The string representation of a SID is of the form - * - *     2.3>0.6 - * - * The '>' symbol shows the direction, so in this case, - * data is flowing from address 2.3 to 0.6. - * - * As a convention, ':' is used instead of '.' when giving the - * SID in hexadecimal numbers, and two characters are used for each - * address part. As an example, the following two SIDs are identical: - * - *     2.3>0.16 (decimal) - *     02:03>00:10 (hexadecimal) - * - * The format is: - *     SRC_ADDRESS.SRC_ENDPOINT>DST_ADDRESS.DST_ENDPOINT - * - * - * \section sid_block_ports Block Ports - * - * In the special case where a block on a crossbar is addressed, the - * endpoint is further split up into two parts of four bits each: The - * first four bits specify the port number on the crossbar, whereas the - * lower four bits represent the *block port*. As an example, consider - * the following SID, given in hexadecimal: - * - *    00:10>02:A1 - * - * In this example, assume data is flowing from the host computer to an - * X300. The crossbar address is 02. The endpoint is A1, which means we - * are accessing a block on crossbar port A (the tenth port), and are addressing - * block port 1. - * - */ -class UHD_API sid_t -{ -public: -    //! Create an unset SID -    sid_t(); -    //! Create a sid_t object from a 32-Bit SID value -    sid_t(uint32_t sid); -    //! Create a sid_t object from its four components -    sid_t(uint8_t src_addr, uint8_t src_ep, uint8_t dst_addr, uint8_t dst_ep); -    //! Convert a string representation of a SID into its numerical representation -    sid_t(const std::string&); - -    //! Copy a sid -    sid_t(const sid_t& sid) { -        set_sid(sid.get_sid()); -    } - -    //! Return a decimal string representation of the SID. -    std::string to_pp_string() const; -    //! Return a hexadecimal string representation of the SID. -    std::string to_pp_string_hex() const; - -    //! Returns true if this actually holds a valid SID -    bool is_set() const -    { -        return _set; -    }; - -    // Getters -    // -    //! Alias for get_sid() -    inline uint32_t get() const -    { -        return get_sid(); -    }; -    //! Returns a 32-Bit representation of the SID if set, or zero otherwise. -    inline uint32_t get_sid() const -    { -        return _set ? _sid : 0; -    }; -    //! Return the 16-bit source address of this SID -    inline uint32_t get_src() const -    { -        return (_sid >> 16) & 0xFFFF; -    } -    //! Return the 16-bit destination address of this SID -    inline uint32_t get_dst() const -    { -        return _sid & 0xFFFF; -    } -    //! Return 8-bit address of the source -    inline uint32_t get_src_addr() const -    { -        return (get_src() >> 8) & 0xFF; -    } -    //! Return endpoint of the source -    inline uint32_t get_src_endpoint() const -    { -        return get_src() & 0xFF; -    } -    //! Return crossbar port of the source -    inline uint32_t get_src_xbarport() const -    { -        return (get_src_endpoint() >> 4) & 0xF; -    } -    //! Return block port of the source -    inline uint32_t get_src_blockport() const -    { -        return (get_src_endpoint()) & 0xF; -    } -    //! Return 8-bit address of the destination -    inline uint32_t get_dst_addr() const -    { -        return (get_dst() >> 8) & 0xFF; -    } -    //! Return endpoint of the destination -    inline uint32_t get_dst_endpoint() const -    { -        return get_dst() & 0xFF; -    } -    //! Return crossbar port of the source -    inline uint32_t get_dst_xbarport() const -    { -        return (get_dst_endpoint() >> 4) & 0xF; -    } -    //! Return block port of the source -    inline uint32_t get_dst_blockport() const -    { -        return (get_dst_endpoint()) & 0xF; -    } - -    // Setters - -    //! Alias for set_sid() -    void set(uint32_t new_sid) -    { -        set_sid(new_sid); -    }; -    //! Convert a string representation of a SID into a numerical one -    // Throws uhd::value_error if the string is not a valid SID -    // representation. -    void set_from_str(const std::string&); -    void set_sid(uint32_t new_sid); -    //! Set the source address of this SID -    //  (the first 16 Bits) -    void set_src(uint32_t new_addr); -    //! Set the destination address of this SID -    //  (the last 16 Bits) -    void set_dst(uint32_t new_addr); -    void set_src_addr(uint32_t new_addr); -    void set_src_endpoint(uint32_t new_addr); -    void set_dst_addr(uint32_t new_addr); -    void set_dst_endpoint(uint32_t new_addr); -    void set_dst_xbarport(uint32_t new_xbarport); -    void set_dst_blockport(uint32_t new_blockport); - -    // Manipulators - -    //! Swaps dst and src address and returns the new SID. -    sid_t reversed() const; - -    //! Swaps dst and src in-place. This modifies the current SID. -    void reverse(); - -    // Overloaded operators - -    sid_t operator=(const uint32_t new_sid) -    { -        set_sid(new_sid); -        return *this; -    } - -    sid_t operator=(const sid_t& sid) -    { -        set_sid(sid.get_sid()); -        return *this; -    } - -    sid_t operator=(const std::string& sid_str) -    { -        set_from_str(sid_str); -        return *this; -    } - -    bool operator==(const sid_t& sid) const -    { -        return (not _set and not sid.is_set()) or (_sid == sid.get_sid()); -    } - -    bool operator==(uint32_t sid) const -    { -        return _set and _sid == sid; -    } - -    bool operator==(const std::string& sid_str) const -    { -        sid_t rhs(sid_str); -        return *this == rhs; -    } - -    // overloaded type casts are tricky, but for now we'll need them -    // for backward compatibility. consider them deprecated. - -    //! If the SID is not set, always returns zero. -    //  Use is_set() to check if the return value is valid. -    operator uint32_t() const -    { -        return get(); -    } - -    operator bool() const -    { -        return _set; -    } - -private: -    uint32_t _sid; -    bool _set; -}; - -//! Stream output operator. Honors std::ios::hex. -inline std::ostream& operator<<(std::ostream& out, const sid_t& sid) -{ -    std::ios_base::fmtflags ff = out.flags(); -    if (ff & std::ios::hex) { -        out << sid.to_pp_string_hex(); -    } else { -        out << sid.to_pp_string(); -    } -    return out; -} - -} // namespace uhd - -#endif /* INCLUDED_UHD_TYPES_SID_HPP */ diff --git a/host/include/uhd/utils/CMakeLists.txt b/host/include/uhd/utils/CMakeLists.txt index 767e56c44..bf367f63d 100644 --- a/host/include/uhd/utils/CMakeLists.txt +++ b/host/include/uhd/utils/CMakeLists.txt @@ -13,6 +13,7 @@ UHD_INSTALL(FILES      byteswap.ipp      cast.hpp      csv.hpp +    dirty_tracked.hpp      fp_compare_delta.ipp      fp_compare_epsilon.ipp      gain_group.hpp diff --git a/host/lib/CMakeLists.txt b/host/lib/CMakeLists.txt index d15c8b264..4e2cf9022 100644 --- a/host/lib/CMakeLists.txt +++ b/host/lib/CMakeLists.txt @@ -116,7 +116,6 @@ configure_file(  LIBUHD_APPEND_SOURCES(      ${CMAKE_CURRENT_BINARY_DIR}/build_info.cpp      ${CMAKE_CURRENT_SOURCE_DIR}/device.cpp -    ${CMAKE_CURRENT_SOURCE_DIR}/device3.cpp      ${CMAKE_CURRENT_SOURCE_DIR}/image_loader.cpp      ${CMAKE_CURRENT_SOURCE_DIR}/stream.cpp      ${CMAKE_CURRENT_SOURCE_DIR}/exception.cpp diff --git a/host/lib/device3.cpp b/host/lib/device3.cpp deleted file mode 100644 index 90fb1c7fe..000000000 --- a/host/lib/device3.cpp +++ /dev/null @@ -1,67 +0,0 @@ -// -// Copyright 2014 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#include <uhd/device3.hpp> -#include <uhd/utils/log.hpp> -#include <boost/format.hpp> -#include <boost/thread/lock_guard.hpp> - -using namespace uhd; -using namespace uhd::rfnoc; - -device3::sptr device3::make(const device_addr_t &hint, const size_t which) -{ -    device3::sptr device3_sptr = -        boost::dynamic_pointer_cast< device3 >(device::make(hint, device::USRP, which)); -    if (not device3_sptr) { -        throw uhd::key_error(str( -            boost::format("No gen-3 devices found for ----->\n%s") % hint.to_pp_string() -        )); -    } - -    return device3_sptr; -} - -bool device3::has_block(const rfnoc::block_id_t &block_id) const -{ -    for (size_t i = 0; i < _rfnoc_block_ctrl.size(); i++) { -        if (_rfnoc_block_ctrl[i]->get_block_id() == block_id) { -            return true; -        } -    } -    return false; -} - -block_ctrl_base::sptr device3::get_block_ctrl(const block_id_t &block_id) const -{ -    for (size_t i = 0; i < _rfnoc_block_ctrl.size(); i++) { -        if (_rfnoc_block_ctrl[i]->get_block_id() == block_id) { -            return _rfnoc_block_ctrl[i]; -        } -    } -    throw uhd::lookup_error(str(boost::format("This device does not have a block with ID: %s") % block_id.to_string())); -} - -std::vector<rfnoc::block_id_t> device3::find_blocks(const std::string &block_id_hint) const -{ -    std::vector<rfnoc::block_id_t> block_ids; -    for (size_t i = 0; i < _rfnoc_block_ctrl.size(); i++) { -        if (_rfnoc_block_ctrl[i]->get_block_id().match(block_id_hint)) { -            block_ids.push_back(_rfnoc_block_ctrl[i]->get_block_id()); -        } -    } -    return block_ids; -} - -void device3::clear() -{ -    boost::lock_guard<boost::mutex> lock(_block_ctrl_mutex); -    for(const block_ctrl_base::sptr &block:  _rfnoc_block_ctrl) { -        block->clear(); -    } -} -// vim: sw=4 et: diff --git a/host/lib/include/uhdlib/rfnoc/async_msg_handler.hpp b/host/lib/include/uhdlib/rfnoc/async_msg_handler.hpp deleted file mode 100644 index cd1aed37d..000000000 --- a/host/lib/include/uhdlib/rfnoc/async_msg_handler.hpp +++ /dev/null @@ -1,85 +0,0 @@ -// -// Copyright 2016 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#ifndef INCLUDED_LIBUHD_RFNOC_AYNC_MSG_HANDLER_HPP -#define INCLUDED_LIBUHD_RFNOC_AYNC_MSG_HANDLER_HPP - -#include <uhd/rfnoc/graph.hpp> -#include <uhd/transport/zero_copy.hpp> -#include <uhd/types/sid.hpp> -#include <uhd/types/endianness.hpp> -#include <uhdlib/rfnoc/async_msg.hpp> -#include <uhd/utils/noncopyable.hpp> -#include <functional> - -namespace uhd { namespace rfnoc { - -/*! Async message handler for a uhd::rfnoc::graph - * - */ -class async_msg_handler : uhd::noncopyable -{ -public: -    typedef boost::shared_ptr<async_msg_handler> sptr; -    typedef std::function<void(const async_msg_t&)> async_handler_type; - -    /*! -     * \param recv A transport on which async messages are received -     * \param send A transport on which to send response messages -     * \param sid The source part of this is taken as the local address of the -     *            transports. The remote part is ignored. -     */ -    static sptr make( -        uhd::transport::zero_copy_if::sptr recv, -        uhd::transport::zero_copy_if::sptr send, -        uhd::sid_t sid, -        uhd::endianness_t endianness -    ); - -    /*! Register an event handler. -     * -     * When any message is received with the given event code, -     * \p handler is called with the async message data as an argument. -     * -     * Note that \p handler is called if a message includes a certain event -     * code, but it does not have to be exclusive. Example: If there are two -     * event handlers registered, one for EVENT_CODE_OVERRUN and one for -     * EVENT_CODE_BAD_PACKET, and a message includes both those event codes, -     * then both event handlers are called. -     * -     * Multiple handlers per event code may be registered. The order they are -     * called in is non-deterministic. -     * -     * \returns The number of event handlers registered for this event code. -     *          Should never return anything less than 1. -     */ -    virtual int register_event_handler( -            const async_msg_t::event_code_t event_code, -            async_handler_type handler -    ) = 0; - -    /*! Post async messages into this message handler. -     * -     * This is the entry point for all async messages. When a message -     * is posted here, the following actions take place: -     * - If applicable, an event handler is called with \p metadata as the -     *   argument -     * - Some messages print error codes (e.g. O, U, L, S) -     */ -    virtual void post_async_msg( -            const async_msg_t &metadata -    ) = 0; - -    /*! Return the 16-bit address of this async message -    */ -    virtual uint32_t get_local_addr() const = 0; -}; - - -}}; /* namespace uhd::rfnoc */ - -#endif /* INCLUDED_LIBUHD_RFNOC_AYNC_MSG_HANDLER_HPP */ diff --git a/host/lib/include/uhdlib/rfnoc/ctrl_iface.hpp b/host/lib/include/uhdlib/rfnoc/ctrl_iface.hpp deleted file mode 100644 index 29b2e73c0..000000000 --- a/host/lib/include/uhdlib/rfnoc/ctrl_iface.hpp +++ /dev/null @@ -1,77 +0,0 @@ -// -// Copyright 2012-2016 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#ifndef INCLUDED_LIBUHD_RFNOC_CTRL_IFACE_HPP -#define INCLUDED_LIBUHD_RFNOC_CTRL_IFACE_HPP - -#include "xports.hpp" -#include <boost/shared_ptr.hpp> -#include <string> - -namespace uhd { namespace rfnoc { - -/*! - * Provide read/write access to registers on an RFNoC block via Noc-Shell. - */ -class ctrl_iface -{ -public: -    typedef boost::shared_ptr<ctrl_iface> sptr; -    virtual ~ctrl_iface(void) {} - -    /*! Make a new control object -     * -     * \param xports Bidirectional transport object to the RFNoC block port. -     * \param name Optional name for better identification in error messages. -     */ -    static sptr make( -        const both_xports_t &xports, -        const std::string &name="0" -    ); - -    /*! Send a command packet. -     * -     * \param addr Register address. This is the value that gets put into the -     *             command packet, its interpretation is defined on the FPGA. -     * \param data Register value to write. -     * \param readback If true, assume the command packet is for a readback, -     *                 and wait for a response packet to return. The return -     *                 value will then be the 64-bit payload of that response -     *                 packet. If false, the return value is the payload of -     *                 any outstanding ACK packet. -     * \param timestamp Optional timestamp. The command packet will include this -     *                  timestamp. Depending on the block configuration, this -     *                  can trigger timed commands. -     *                  A value of zero indicates that no timestamp will be -     *                  applied. It is not possible to request anything to -     *                  happen at time zero. -     * -     * \throws uhd::io_error if the response is malformed; uhd::runtime_error if -     *         no packet could be sent. -     */ -    virtual uint64_t send_cmd_pkt( -            const size_t addr, -            const size_t data, -            const bool readback=false, -            const uint64_t timestamp=0 -    ) = 0; - -    /*! Set the depth of the command FIFO size -     * -     * Note: This is not safe to call during operations. Call this during -     * initialization. -     * -     * \param num_lines The number of lines of depth in the command FIFO. The -     *                  function will calculate the number of packets that will -     *                  fit into the command FIFO. -     */ -    virtual void set_cmd_fifo_size(const size_t num_lines) = 0; -}; - -}} /* namespace uhd::rfnoc */ - -#endif /* INCLUDED_LIBUHD_RFNOC_CTRL_IFACE_HPP */ diff --git a/host/lib/include/uhdlib/rfnoc/graph_impl.hpp b/host/lib/include/uhdlib/rfnoc/graph_impl.hpp deleted file mode 100644 index 4147acedf..000000000 --- a/host/lib/include/uhdlib/rfnoc/graph_impl.hpp +++ /dev/null @@ -1,87 +0,0 @@ -// -// Copyright 2016 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#ifndef INCLUDED_LIBUHD_RFNOC_GRAPH_IMPL_HPP -#define INCLUDED_LIBUHD_RFNOC_GRAPH_IMPL_HPP - -#include "async_msg_handler.hpp" -#include <uhd/device3.hpp> -#include <uhd/rfnoc/graph.hpp> - -namespace uhd { namespace rfnoc { - -class graph_impl : public graph -{ -public: -    /************************************************************************ -     * Structors -     ***********************************************************************/ -    /*! -     * \param name An optional name to describe this graph -     * \param device_ptr Weak pointer to the originating device3 -     * \param msg_handler Pointer to the async message handler -     */ -    graph_impl(const std::string& name, -        boost::weak_ptr<uhd::device3> device_ptr, -        async_msg_handler::sptr msg_handler); -    virtual ~graph_impl() {} - -    /************************************************************************ -     * Connection API -     ***********************************************************************/ -    void connect(const block_id_t& src_block, -        size_t src_block_port, -        const block_id_t& dst_block, -        size_t dst_block_port, -        const size_t pkt_size = 0); - -    void connect(const block_id_t& src_block, const block_id_t& dst_block); - -    void connect_src(const block_id_t& src_block, -        const size_t src_block_port, -        const uhd::sid_t dst_sid, -        const size_t buf_size_dst_bytes, -        const size_t pkt_size_); - -    void connect_sink(const block_id_t& sink_block, -        const size_t dst_block_port, -        const size_t bytes_per_ack); - -    /************************************************************************ -     * Utilities -     ***********************************************************************/ -    std::string get_name() const -    { -        return _name; -    } - - -private: -    void handle_overruns(const async_msg_t& async_msg); - -    //! Maps 16-bit addresses to block IDs -    std::map<uint32_t, block_id_t> _block_id_map; - -    //! For any given block, look up the MIMO group -    std::map<uint32_t, size_t> _mimo_group_map; - -    //! For any MIMO group, store the list of blocks in that group -    std::map<size_t, std::set<block_id_t>> _mimo_groups; - -    //! Optional: A string to describe this graph -    const std::string _name; - -    //! Reference to the generating device object -    const boost::weak_ptr<uhd::device3> _device_ptr; - -    //! Reference to the async message handler -    async_msg_handler::sptr _msg_handler; -}; - -}} /* namespace uhd::rfnoc */ - -#endif /* INCLUDED_LIBUHD_RFNOC_GRAPH_IMPL_HPP */ diff --git a/host/lib/include/uhdlib/rfnoc/legacy_compat.hpp b/host/lib/include/uhdlib/rfnoc/legacy_compat.hpp deleted file mode 100644 index 185b89f82..000000000 --- a/host/lib/include/uhdlib/rfnoc/legacy_compat.hpp +++ /dev/null @@ -1,49 +0,0 @@ -// -// Copyright 2016 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#ifndef INCLUDED_RFNOC_LEGACY_COMPAT_HPP -#define INCLUDED_RFNOC_LEGACY_COMPAT_HPP - -#include <uhd/device3.hpp> -#include <uhd/stream.hpp> - -namespace uhd { namespace rfnoc { - -    /*! Legacy compatibility layer class. -     */ -    class legacy_compat -    { -    public: -        typedef boost::shared_ptr<legacy_compat> sptr; - -        virtual uhd::fs_path rx_dsp_root(const size_t mboard_idx, const size_t chan) = 0; - -        virtual uhd::fs_path tx_dsp_root(const size_t mboard_idx, const size_t chan) = 0; - -        virtual uhd::fs_path rx_fe_root(const size_t mboard_idx, const size_t chan) = 0; - -        virtual uhd::fs_path tx_fe_root(const size_t mboard_idx, const size_t chan) = 0; - -        virtual void issue_stream_cmd(const uhd::stream_cmd_t &stream_cmd, size_t mboard, size_t chan) = 0; - -        virtual uhd::rx_streamer::sptr get_rx_stream(const uhd::stream_args_t &args) = 0; - -        virtual uhd::tx_streamer::sptr get_tx_stream(const uhd::stream_args_t &args) = 0; - -        virtual void set_rx_rate(const double rate, const size_t chan) = 0; - -        virtual void set_tx_rate(const double rate, const size_t chan) = 0; - -        static sptr make( -                uhd::device3::sptr device, -                const uhd::device_addr_t &args -        ); -    }; - -}} /* namespace uhd::rfnoc */ - -#endif /* INCLUDED_RFNOC_LEGACY_COMPAT_HPP */ diff --git a/host/lib/include/uhdlib/rfnoc/radio_ctrl_impl.hpp b/host/lib/include/uhdlib/rfnoc/radio_ctrl_impl.hpp deleted file mode 100644 index af4168d8b..000000000 --- a/host/lib/include/uhdlib/rfnoc/radio_ctrl_impl.hpp +++ /dev/null @@ -1,249 +0,0 @@ -// -// Copyright 2014-2016 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#ifndef INCLUDED_LIBUHD_RFNOC_RADIO_CTRL_IMPL_HPP -#define INCLUDED_LIBUHD_RFNOC_RADIO_CTRL_IMPL_HPP - -#include <uhd/rfnoc/radio_ctrl.hpp> -#include <uhd/types/direction.hpp> -#include <uhdlib/usrp/cores/rx_vita_core_3000.hpp> -#include <uhdlib/usrp/cores/tx_vita_core_3000.hpp> -#include <uhdlib/usrp/cores/time_core_3000.hpp> -#include <uhdlib/usrp/cores/gpio_atr_3000.hpp> -#include <boost/thread.hpp> -#include <mutex> - -//! Shorthand for radio block constructor -#define UHD_RFNOC_RADIO_BLOCK_CONSTRUCTOR_DECL(CLASS_NAME) \ -    CLASS_NAME##_impl(const make_args_t &make_args); - -#define UHD_RFNOC_RADIO_BLOCK_CONSTRUCTOR(CLASS_NAME) \ -    CLASS_NAME##_impl::CLASS_NAME##_impl( \ -        const make_args_t &make_args \ -    ) : block_ctrl_base(make_args), radio_ctrl_impl() - -namespace uhd { -    namespace rfnoc { - -/*! \brief Provide access to a radio. - * - */ -class radio_ctrl_impl : public radio_ctrl -{ -public: -    /************************************************************************ -     * Structors -     ***********************************************************************/ -    radio_ctrl_impl(); -    virtual ~radio_ctrl_impl() {}; - -    /************************************************************************ -     * Public Radio API calls -     ***********************************************************************/ -    virtual double set_rate(double rate); -    virtual void set_tx_antenna(const std::string &ant, const size_t chan); -    virtual void set_rx_antenna(const std::string &ant, const size_t chan); -    virtual double set_tx_frequency(const double freq, const size_t chan); -    virtual double set_rx_frequency(const double freq, const size_t chan); -    virtual double set_tx_gain(const double gain, const size_t chan); -    virtual double set_rx_gain(const double gain, const size_t chan); -    virtual double set_tx_bandwidth(const double bandwidth, const size_t chan); -    virtual double set_rx_bandwidth(const double bandwidth, const size_t chan); - -    virtual double get_rate() const; -    virtual std::string get_tx_antenna(const size_t chan) /* const */; -    virtual std::string get_rx_antenna(const size_t chan) /* const */; -    virtual double get_tx_frequency(const size_t) /* const */; -    virtual double get_rx_frequency(const size_t) /* const */; -    virtual double get_tx_gain(const size_t) /* const */; -    virtual double get_rx_gain(const size_t) /* const */; -    virtual double get_tx_bandwidth(const size_t) /* const */; -    virtual double get_rx_bandwidth(const size_t) /* const */; - -    virtual std::vector<std::string> get_rx_lo_names(const size_t chan); -    virtual std::vector<std::string> get_rx_lo_sources(const std::string &name, const size_t chan); -    virtual freq_range_t get_rx_lo_freq_range(const std::string &name, const size_t chan); - -    virtual void set_rx_lo_source(const std::string &src, const std::string &name, const size_t chan); -    virtual const std::string get_rx_lo_source(const std::string &name, const size_t chan); - -    virtual void set_rx_lo_export_enabled(bool enabled, const std::string &name, const size_t chan); -    virtual bool get_rx_lo_export_enabled(const std::string &name, const size_t chan); - -    virtual double set_rx_lo_freq(const double freq, const std::string &name, const size_t chan); -    virtual double get_rx_lo_freq(const std::string &name, const size_t chan); - -    virtual std::vector<std::string> get_tx_lo_names(const size_t chan); -    virtual std::vector<std::string> get_tx_lo_sources(const std::string &name, const size_t chan); -    virtual freq_range_t get_tx_lo_freq_range(const std::string &name, const size_t chan); - -    virtual void set_tx_lo_source(const std::string &src, const std::string &name, const size_t chan); -    virtual const std::string get_tx_lo_source(const std::string &name, const size_t chan); - -    virtual void set_tx_lo_export_enabled(const bool enabled, const std::string &name, const size_t chan); -    virtual bool get_tx_lo_export_enabled(const std::string &name, const size_t chan); - -    virtual double set_tx_lo_freq(const double freq, const std::string &name, const size_t chan); -    virtual double get_tx_lo_freq(const std::string &name, const size_t chan); - -    void set_time_now(const time_spec_t &time_spec); -    void set_time_next_pps(const time_spec_t &time_spec); -    void set_time_sync(const uhd::time_spec_t &time); -    time_spec_t get_time_now(); -    time_spec_t get_time_last_pps(); -    virtual void set_time_source(const std::string &source); -    virtual std::string get_time_source(); -    virtual std::vector<std::string> get_time_sources(); -    virtual void set_clock_source(const std::string &source); -    virtual std::string get_clock_source(); -    virtual std::vector<std::string> get_clock_sources(); - -    virtual std::vector<std::string> get_gpio_banks() const; -    virtual void set_gpio_attr( -            const std::string &bank, -            const std::string &attr, -            const uint32_t value, -            const uint32_t mask -    ); -    virtual uint32_t get_gpio_attr(const std::string &bank, const std::string &attr); -    void enable_rx_timestamps(const bool, const size_t); - -    /*********************************************************************** -     * Block control API calls -     **********************************************************************/ -    void set_rx_streamer(bool active, const size_t port); -    void set_tx_streamer(bool active, const size_t port); - -    void issue_stream_cmd(const uhd::stream_cmd_t &stream_cmd, const size_t port); - -    virtual double get_input_samp_rate(size_t /* port */) { return get_rate(); } -    virtual double get_output_samp_rate(size_t /* port */) { return get_rate(); } -    double _get_tick_rate() { return get_rate(); } - -    std::vector<size_t> get_active_rx_ports(); -    bool in_continuous_streaming_mode(const size_t chan) { return _continuous_streaming.at(chan); } -    void rx_ctrl_clear_cmds(const size_t port) { sr_write(regs::RX_CTRL_CLEAR_CMDS, 0, port); } - -protected: // TODO see what's protected and what's private -    void _register_loopback_self_test(size_t chan); - -    /*********************************************************************** -     * Registers -     **********************************************************************/ -    struct regs { -        static inline uint32_t sr_addr(const uint32_t offset) { return offset * 4; } -        static inline uint32_t rb_addr(const uint32_t offset) { return offset * 8; } - -        static const uint32_t BASE       = 128; - -        // defined in radio_core_regs.vh -        static const uint32_t TIME                 = 128; // time hi - 128, time lo - 129, ctrl - 130 -        static const uint32_t CLEAR_CMDS           = 131; // Any write to this reg clears the command FIFO -        static const uint32_t LOOPBACK             = 132; -        static const uint32_t TEST                 = 133; -        static const uint32_t CODEC_IDLE           = 134; -        static const uint32_t TX_CTRL_ERROR_POLICY = 144; -        static const uint32_t RX_CTRL_CMD          = 152; -        static const uint32_t RX_CTRL_TIME_HI      = 153; -        static const uint32_t RX_CTRL_TIME_LO      = 154; -        static const uint32_t RX_CTRL_HALT         = 155; -        static const uint32_t RX_CTRL_MAXLEN       = 156; -        static const uint32_t RX_CTRL_CLEAR_CMDS   = 157; -        static const uint32_t RX_CTRL_OUTPUT_FORMAT= 158; -        static const uint32_t MISC_OUTS            = 160; -        static const uint32_t DACSYNC              = 161; -        static const uint32_t SPI                  = 168; -        static const uint32_t LEDS                 = 176; -        static const uint32_t FP_GPIO              = 184; -        static const uint32_t GPIO                 = 192; -        // NOTE: Upper 32 registers (224-255) are reserved for the output settings bus for use with -        //       device specific front end control - -        // frontend control: needs rethinking TODO -        //static const uint32_t TX_FRONT             = BASE + 96; -        //static const uint32_t RX_FRONT             = BASE + 112; -        //static const uint32_t READBACK             = BASE + 127; - -        static const uint32_t RB_TIME_NOW        = 0; -        static const uint32_t RB_TIME_PPS        = 1; -        static const uint32_t RB_TEST            = 2; -        static const uint32_t RB_CODEC_READBACK  = 3; -        static const uint32_t RB_RADIO_NUM       = 4; -        static const uint32_t RB_MISC_IO         = 16; -        static const uint32_t RB_SPI             = 17; -        static const uint32_t RB_LEDS            = 18; -        static const uint32_t RB_DB_GPIO         = 19; -        static const uint32_t RB_FP_GPIO         = 20; -    }; - -    /*********************************************************************** -     * Block control API calls -     **********************************************************************/ -    void _update_spp(int spp); - -    inline size_t _get_num_radios() const { -       return  std::max(_num_rx_channels, _num_tx_channels); -    } - -    inline timed_wb_iface::sptr _get_ctrl(size_t radio_num) const { -        return _perifs.at(radio_num).ctrl; -    } - -    inline bool _is_streamer_active(uhd::direction_t dir, const size_t chan) const { -        switch (dir) { -        case uhd::TX_DIRECTION: -            return _tx_streamer_active.count(chan) ? _tx_streamer_active.at(chan) : false; -        case uhd::RX_DIRECTION: -            return _rx_streamer_active.count(chan) ? _rx_streamer_active.at(chan) : false; -        case uhd::DX_DIRECTION: -            return (_tx_streamer_active.count(chan) and _rx_streamer_active.count(chan)) ? -                _rx_streamer_active.at(chan) and _tx_streamer_active.at(chan) : false; -        default: -            return false; -        } -    } - -    virtual bool check_radio_config() { return true; }; - -    //! There is always only one time core per radio -    time_core_3000::sptr         _time64; - -    std::mutex _mutex; - -    size_t _num_tx_channels; -    size_t _num_rx_channels; -    std::vector<bool> _continuous_streaming; - -private: -    /************************************************************************ -     * Peripherals -     ***********************************************************************/ -    //! Stores pointers to all streaming-related radio cores -    struct radio_perifs_t -    { -        timed_wb_iface::sptr     ctrl; -    }; -    std::map<size_t, radio_perifs_t> _perifs; - - - -    // Cached values -    double _tick_rate; -    std::map<size_t, std::string> _tx_antenna; -    std::map<size_t, std::string> _rx_antenna; -    std::map<size_t, double> _tx_freq; -    std::map<size_t, double> _rx_freq; -    std::map<size_t, double> _tx_gain; -    std::map<size_t, double> _rx_gain; -    std::map<size_t, double> _tx_bandwidth; -    std::map<size_t, double> _rx_bandwidth; - -}; /* class radio_ctrl_impl */ - -}} /* namespace uhd::rfnoc */ - -#endif /* INCLUDED_LIBUHD_RFNOC_RADIO_CTRL_IMPL_HPP */ diff --git a/host/lib/include/uhdlib/rfnoc/rx_stream_terminator.hpp b/host/lib/include/uhdlib/rfnoc/rx_stream_terminator.hpp deleted file mode 100644 index 2ac65bb25..000000000 --- a/host/lib/include/uhdlib/rfnoc/rx_stream_terminator.hpp +++ /dev/null @@ -1,78 +0,0 @@ -// -// Copyright 2014 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#ifndef INCLUDED_LIBUHD_RFNOC_TERMINATOR_RECV_HPP -#define INCLUDED_LIBUHD_RFNOC_TERMINATOR_RECV_HPP - -#include <uhd/rfnoc/sink_node_ctrl.hpp> -#include <uhd/rfnoc/rate_node_ctrl.hpp> -#include <uhd/rfnoc/tick_node_ctrl.hpp> -#include <uhd/rfnoc/scalar_node_ctrl.hpp> -#include <uhd/rfnoc/terminator_node_ctrl.hpp> -#include <uhd/rfnoc/block_ctrl_base.hpp> // For the block macros -#include <mutex> - -namespace uhd { -    namespace rfnoc { - -/*! \brief Terminator node for Rx streamers. - * - * This node is only used by rx_streamers. It terminates the flow graph - * inside the streamer and does not have a counterpart on the FPGA. - */ -class rx_stream_terminator : -    public sink_node_ctrl, -    public rate_node_ctrl, -    public tick_node_ctrl, -    public scalar_node_ctrl, -    public terminator_node_ctrl -{ -public: -    UHD_RFNOC_BLOCK_OBJECT(rx_stream_terminator) - -    static sptr make() -    { -        return sptr(new rx_stream_terminator); -    } - -    // If this is called, then by a send terminator at the other end -    // of a flow graph. -    double get_input_samp_rate(size_t) { return _samp_rate; }; - -    // Same for the scaling factor -    double get_input_scale_factor(size_t) { return scalar_node_ctrl::SCALE_UNDEFINED; }; - -    std::string unique_id() const; - -    void set_rx_streamer(bool active, const size_t port); - -    void set_tx_streamer(bool active, const size_t port); - -    virtual ~rx_stream_terminator(); - -    void handle_overrun(boost::weak_ptr<uhd::rx_streamer>, const size_t); - -protected: -    rx_stream_terminator(); - -    virtual double _get_tick_rate() { return _tick_rate; }; - -private: -    //! Every terminator has a unique index -    const size_t _term_index; -    static size_t _count; - -    double _samp_rate; -    double _tick_rate; - -    std::mutex _overrun_handler_mutex; - -}; /* class rx_stream_terminator */ - -}} /* namespace uhd::rfnoc */ - -#endif /* INCLUDED_LIBUHD_RFNOC_TERMINATOR_RECV_HPP */ diff --git a/host/lib/include/uhdlib/rfnoc/tx_stream_terminator.hpp b/host/lib/include/uhdlib/rfnoc/tx_stream_terminator.hpp deleted file mode 100644 index e4d509dc5..000000000 --- a/host/lib/include/uhdlib/rfnoc/tx_stream_terminator.hpp +++ /dev/null @@ -1,79 +0,0 @@ -// -// Copyright 2014 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#ifndef INCLUDED_LIBUHD_RFNOC_TERMINATOR_SEND_HPP -#define INCLUDED_LIBUHD_RFNOC_TERMINATOR_SEND_HPP - -#include <uhd/rfnoc/source_node_ctrl.hpp> -#include <uhd/rfnoc/rate_node_ctrl.hpp> -#include <uhd/rfnoc/tick_node_ctrl.hpp> -#include <uhd/rfnoc/scalar_node_ctrl.hpp> -#include <uhd/rfnoc/terminator_node_ctrl.hpp> -#include <uhd/rfnoc/block_ctrl_base.hpp> // For the block macros -#include <uhd/utils/log.hpp> - -namespace uhd { -    namespace rfnoc { - -/*! \brief Terminator node for Tx streamers. - * - * This node is only used by tx_streamers. It terminates the flow graph - * inside the streamer and does not have a counterpart on the FPGA. - */ -class tx_stream_terminator : -    public source_node_ctrl, -    public rate_node_ctrl, -    public tick_node_ctrl, -    public scalar_node_ctrl, -    public terminator_node_ctrl -{ -public: -    UHD_RFNOC_BLOCK_OBJECT(tx_stream_terminator) - -    static sptr make() -    { -        return sptr(new tx_stream_terminator); -    } - -    void issue_stream_cmd(const uhd::stream_cmd_t &, const size_t) -    { -        UHD_RFNOC_BLOCK_TRACE() << "tx_stream_terminator::issue_stream_cmd()" ; -    } - -    // If this is called, then by a send terminator at the other end -    // of a flow graph. -    double get_output_samp_rate(size_t) { return _samp_rate; }; - -    // Same for the scaling factor -    double get_output_scale_factor(size_t) { return scalar_node_ctrl::SCALE_UNDEFINED; }; - -    std::string unique_id() const; - -    void set_rx_streamer(bool active, const size_t port); - -    void set_tx_streamer(bool active, const size_t port); - -    virtual ~tx_stream_terminator(); - -protected: -    tx_stream_terminator(); - -    virtual double _get_tick_rate() { return _tick_rate; }; - -private: -    //! Every terminator has a unique index -    const size_t _term_index; -    static size_t _count; - -    double _samp_rate; -    double _tick_rate; - -}; /* class tx_stream_terminator */ - -}} /* namespace uhd::rfnoc */ - -#endif /* INCLUDED_LIBUHD_RFNOC_TERMINATOR_SEND_HPP */ diff --git a/host/lib/include/uhdlib/rfnoc/utils.hpp b/host/lib/include/uhdlib/rfnoc/utils.hpp deleted file mode 100644 index 7c3c1bb5f..000000000 --- a/host/lib/include/uhdlib/rfnoc/utils.hpp +++ /dev/null @@ -1,66 +0,0 @@ -// -// Copyright 2014 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#ifndef INCLUDED_LIBUHD_RFNOC_UTILS_HPP -#define INCLUDED_LIBUHD_RFNOC_UTILS_HPP - -#include <uhd/rfnoc/node_ctrl_base.hpp> -#include <boost/lexical_cast.hpp> -#include <set> - -namespace uhd { namespace rfnoc { namespace utils { - -    /*! If \p suggested_port equals ANY_PORT, return the first available -     * port number on \p nodes. Otherwise, return \p suggested_port. -     * -     * If \p allowed_ports is given, another condition is that the port -     * number must be listed in here. -     * If \p allowed_ports is not specified or empty, the assumption is -     * that all ports are valid. -     * -     * On failure, ANY_PORT is returned. -     */ -    static size_t node_map_find_first_free( -            node_ctrl_base::node_map_t nodes, -            const size_t suggested_port, -            const std::set<size_t> allowed_ports=std::set<size_t>() -    ) { -        size_t port = suggested_port; -        if (port == ANY_PORT) { -            if (allowed_ports.empty()) { -                port = 0; -                while (nodes.count(port) and (port != ANY_PORT)) { -                    port++; -                } -            } else { -                for(const size_t allowed_port:  allowed_ports) { -                    if (not nodes.count(port)) { -                        return allowed_port; -                    } -                    return ANY_PORT; -                } -            } -        } else { -            if (not (allowed_ports.empty() or allowed_ports.count(port))) { -                return ANY_PORT; -            } -        } -        return port; -    } - -    template <typename T> -    static std::set<T> str_list_to_set(const std::vector<std::string> &list) { -        std::set<T> return_set; -        for(const std::string &S:  list) { -            return_set.insert(boost::lexical_cast<T>(S)); -        } -        return return_set; -    } - -}}}; /* namespace uhd::rfnoc::utils */ - -#endif /* INCLUDED_LIBUHD_RFNOC_UTILS_HPP */ diff --git a/host/lib/include/uhdlib/rfnoc/wb_iface_adapter.hpp b/host/lib/include/uhdlib/rfnoc/wb_iface_adapter.hpp deleted file mode 100644 index 1ed8cf69b..000000000 --- a/host/lib/include/uhdlib/rfnoc/wb_iface_adapter.hpp +++ /dev/null @@ -1,57 +0,0 @@ -// -// Copyright 2016 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#ifndef INCLUDED_RFNOC_WB_IFACE_ADAPTER_HPP -#define INCLUDED_RFNOC_WB_IFACE_ADAPTER_HPP - -#include <uhd/config.hpp> -#include "ctrl_iface.hpp" -#include <uhd/types/wb_iface.hpp> -#include <boost/function.hpp> - -namespace uhd { -    namespace rfnoc { - -/*! wb_iface control into RFNoC block registers. - * - * This is specifically for mimicking a wb_iface that talks to an RFNoC block. - * It assumes an underlying ctrl_iface is talking to an RFNoC block. - */ -class UHD_API wb_iface_adapter : public uhd::timed_wb_iface -{ -public: -    typedef boost::function<double()> gettickrate_type; -    typedef boost::function<uhd::time_spec_t()> gettime_type; -    typedef boost::function<void(const uhd::time_spec_t &)> settime_type; - -    wb_iface_adapter( -        ctrl_iface::sptr iface, -        const gettickrate_type &, -        const settime_type &, -        const gettime_type & -    ); - -    virtual ~wb_iface_adapter(void) {} - -    void poke32(const wb_addr_type addr, const uint32_t data); -    uint32_t peek32(const wb_addr_type addr); -    uint64_t peek64(const wb_addr_type addr); -    time_spec_t get_time() { return gettime_functor(); } -    void set_time(const uhd::time_spec_t& t) { settime_functor(t); } - -private: -    ctrl_iface::sptr       _iface; -    const gettickrate_type gettickrate_functor; -    const settime_type     settime_functor; -    const gettime_type     gettime_functor; - -    inline uint64_t get_timestamp() { return gettime_functor().to_ticks(gettickrate_functor()); } -}; - -}} // namespace uhd::rfnoc - -#endif /* INCLUDED_RFNOC_WB_IFACE_ADAPTER_HPP */ diff --git a/host/lib/include/uhdlib/rfnoc/xports.hpp b/host/lib/include/uhdlib/rfnoc/xports.hpp deleted file mode 100644 index 6b30fe5b1..000000000 --- a/host/lib/include/uhdlib/rfnoc/xports.hpp +++ /dev/null @@ -1,35 +0,0 @@ -// -// Copyright 2016 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#ifndef INCLUDED_LIBUHD_XPORTS_HPP -#define INCLUDED_LIBUHD_XPORTS_HPP - -#include <uhd/types/sid.hpp> -#include <uhd/types/endianness.hpp> -#include <uhd/transport/zero_copy.hpp> - -namespace uhd { - -    /*! Holds all necessary items for a bidirectional link -     */ -    struct both_xports_t -    { -        both_xports_t(): recv_buff_size(0), send_buff_size(0), lossless(false) -            {} -        uhd::transport::zero_copy_if::sptr recv; -        uhd::transport::zero_copy_if::sptr send; -        size_t recv_buff_size; -        size_t send_buff_size; -        uhd::sid_t send_sid; -        uhd::sid_t recv_sid; -        uhd::endianness_t endianness; -        bool lossless; -    }; - -}; - -#endif /* INCLUDED_LIBUHD_XPORTS_HPP */ diff --git a/host/lib/rfnoc/CMakeLists.txt b/host/lib/rfnoc/CMakeLists.txt index 2892e0d6d..5f5838a29 100644 --- a/host/lib/rfnoc/CMakeLists.txt +++ b/host/lib/rfnoc/CMakeLists.txt @@ -13,12 +13,7 @@  LIBUHD_APPEND_SOURCES(      # Infrastructure:      ${CMAKE_CURRENT_SOURCE_DIR}/actions.cpp -    ${CMAKE_CURRENT_SOURCE_DIR}/async_msg_handler.cpp      ${CMAKE_CURRENT_SOURCE_DIR}/block_container.cpp -    ${CMAKE_CURRENT_SOURCE_DIR}/block_ctrl_base.cpp -    ${CMAKE_CURRENT_SOURCE_DIR}/block_ctrl_base_factory.cpp -    ${CMAKE_CURRENT_SOURCE_DIR}/block_ctrl_impl.cpp -    ${CMAKE_CURRENT_SOURCE_DIR}/blockdef_xml_impl.cpp      ${CMAKE_CURRENT_SOURCE_DIR}/block_id.cpp      ${CMAKE_CURRENT_SOURCE_DIR}/chdr_types.cpp      ${CMAKE_CURRENT_SOURCE_DIR}/chdr_packet.cpp @@ -26,35 +21,20 @@ LIBUHD_APPEND_SOURCES(      ${CMAKE_CURRENT_SOURCE_DIR}/chdr_rx_data_xport.cpp      ${CMAKE_CURRENT_SOURCE_DIR}/chdr_tx_data_xport.cpp      ${CMAKE_CURRENT_SOURCE_DIR}/client_zero.cpp -    ${CMAKE_CURRENT_SOURCE_DIR}/ctrl_iface.cpp      ${CMAKE_CURRENT_SOURCE_DIR}/device_id.cpp      ${CMAKE_CURRENT_SOURCE_DIR}/epid_allocator.cpp -    ${CMAKE_CURRENT_SOURCE_DIR}/graph_impl.cpp      ${CMAKE_CURRENT_SOURCE_DIR}/graph.cpp -    ${CMAKE_CURRENT_SOURCE_DIR}/legacy_compat.cpp      ${CMAKE_CURRENT_SOURCE_DIR}/link_stream_manager.cpp      ${CMAKE_CURRENT_SOURCE_DIR}/graph_stream_manager.cpp      ${CMAKE_CURRENT_SOURCE_DIR}/mb_controller.cpp      ${CMAKE_CURRENT_SOURCE_DIR}/noc_block_base.cpp -    ${CMAKE_CURRENT_SOURCE_DIR}/node_ctrl_base.cpp      ${CMAKE_CURRENT_SOURCE_DIR}/node.cpp -    ${CMAKE_CURRENT_SOURCE_DIR}/rate_node_ctrl.cpp      ${CMAKE_CURRENT_SOURCE_DIR}/register_iface_holder.cpp      ${CMAKE_CURRENT_SOURCE_DIR}/ctrlport_endpoint.cpp      ${CMAKE_CURRENT_SOURCE_DIR}/chdr_ctrl_endpoint.cpp      ${CMAKE_CURRENT_SOURCE_DIR}/registry_factory.cpp      ${CMAKE_CURRENT_SOURCE_DIR}/rfnoc_graph.cpp -    ${CMAKE_CURRENT_SOURCE_DIR}/rx_stream_terminator.cpp -    ${CMAKE_CURRENT_SOURCE_DIR}/scalar_node_ctrl.cpp -    ${CMAKE_CURRENT_SOURCE_DIR}/sink_block_ctrl_base.cpp -    ${CMAKE_CURRENT_SOURCE_DIR}/sink_node_ctrl.cpp -    ${CMAKE_CURRENT_SOURCE_DIR}/source_block_ctrl_base.cpp -    ${CMAKE_CURRENT_SOURCE_DIR}/source_node_ctrl.cpp      ${CMAKE_CURRENT_SOURCE_DIR}/mgmt_portal.cpp -    ${CMAKE_CURRENT_SOURCE_DIR}/stream_sig.cpp -    ${CMAKE_CURRENT_SOURCE_DIR}/tick_node_ctrl.cpp -    ${CMAKE_CURRENT_SOURCE_DIR}/tx_stream_terminator.cpp -    ${CMAKE_CURRENT_SOURCE_DIR}/wb_iface_adapter.cpp      ${CMAKE_CURRENT_SOURCE_DIR}/rfnoc_rx_streamer.cpp      ${CMAKE_CURRENT_SOURCE_DIR}/rfnoc_tx_streamer.cpp      ${CMAKE_CURRENT_SOURCE_DIR}/tx_async_msg_queue.cpp @@ -62,17 +42,7 @@ LIBUHD_APPEND_SOURCES(      ${CMAKE_CURRENT_SOURCE_DIR}/block_control.cpp      ${CMAKE_CURRENT_SOURCE_DIR}/ddc_block_control.cpp      ${CMAKE_CURRENT_SOURCE_DIR}/duc_block_control.cpp -    ${CMAKE_CURRENT_SOURCE_DIR}/ddc_block_ctrl_impl.cpp -    ${CMAKE_CURRENT_SOURCE_DIR}/duc_block_ctrl_impl.cpp -    ${CMAKE_CURRENT_SOURCE_DIR}/fir_block_ctrl_impl.cpp -    ${CMAKE_CURRENT_SOURCE_DIR}/null_block_ctrl_impl.cpp      ${CMAKE_CURRENT_SOURCE_DIR}/null_block_control.cpp -    ${CMAKE_CURRENT_SOURCE_DIR}/window_block_ctrl_impl.cpp -    ${CMAKE_CURRENT_SOURCE_DIR}/radio_ctrl_impl.cpp      ${CMAKE_CURRENT_SOURCE_DIR}/radio_control_impl.cpp -    ${CMAKE_CURRENT_SOURCE_DIR}/siggen_block_ctrl_impl.cpp -    ${CMAKE_CURRENT_SOURCE_DIR}/dma_fifo_block_ctrl_impl.cpp -    ${CMAKE_CURRENT_SOURCE_DIR}/replay_block_ctrl_impl.cpp  ) -INCLUDE_SUBDIRECTORY(nocscript) diff --git a/host/lib/rfnoc/async_msg_handler.cpp b/host/lib/rfnoc/async_msg_handler.cpp deleted file mode 100644 index 6b7d7d057..000000000 --- a/host/lib/rfnoc/async_msg_handler.cpp +++ /dev/null @@ -1,174 +0,0 @@ -// -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#include <uhd/exception.hpp> -#include <uhd/transport/bounded_buffer.hpp> -#include <uhd/transport/chdr.hpp> -#include <uhd/transport/zero_copy.hpp> -#include <uhd/utils/byteswap.hpp> -#include <uhd/utils/log.hpp> -#include <uhd/utils/tasks.hpp> -#include <uhdlib/rfnoc/async_msg_handler.hpp> -#include <boost/make_shared.hpp> -#include <mutex> - -using namespace uhd; -using namespace uhd::rfnoc; - -template <endianness_t _endianness> -class async_msg_handler_impl : public async_msg_handler -{ -public: -    /************************************************************************ -     * Types -     ***********************************************************************/ -    typedef uhd::transport::bounded_buffer<async_msg_t> async_md_type; - -    /************************************************************************ -     * Structors -     ***********************************************************************/ -    async_msg_handler_impl(uhd::transport::zero_copy_if::sptr recv, -        uhd::transport::zero_copy_if::sptr send, -        uhd::sid_t sid) -        : _rx_xport(recv), _tx_xport(send), _sid(sid) -    { -        // Launch receive thread -        _recv_msg_task = task::make([=]() { this->handle_async_msgs(); }); -    } - -    ~async_msg_handler_impl() {} - -    /************************************************************************ -     * API calls -     ***********************************************************************/ -    int register_event_handler( -        const async_msg_t::event_code_t event_code, async_handler_type handler) -    { -        _event_handlers.insert(std::pair<async_msg_t::event_code_t, async_handler_type>( -            event_code, handler)); -        return _event_handlers.count(event_code); -    } - -    void post_async_msg(const async_msg_t& metadata) -    { -        std::lock_guard<std::mutex> lock(_mutex); - -        for (auto const event_handler : _event_handlers) { -            // If the event code in the message matches the event code used at -            // registration time, call the event handler -            if ((metadata.event_code & event_handler.first) == event_handler.first) { -                event_handler.second(metadata); -            } -        } - -        // Print -        if (metadata.event_code & async_msg_t::EVENT_CODE_UNDERFLOW) { -            UHD_LOG_FASTPATH("U") -        } else if (metadata.event_code -                   & (async_msg_t::EVENT_CODE_SEQ_ERROR -                         | async_msg_t::EVENT_CODE_SEQ_ERROR_IN_BURST)) { -            UHD_LOG_FASTPATH("S") -        } else if (metadata.event_code -                   & (async_msg_t::EVENT_CODE_LATE_CMD_ERROR -                         | async_msg_t::EVENT_CODE_LATE_DATA_ERROR)) { -            UHD_LOG_FASTPATH("L") -        } else if (metadata.event_code & async_msg_t::EVENT_CODE_OVERRUN) { -            UHD_LOG_FASTPATH("O") -        } -    } - -private: // methods -    /************************************************************************ -     * Internals -     ***********************************************************************/ -    /*! Packet receiver thread call. -     */ -    void handle_async_msgs() -    { -        using namespace uhd::transport; -        managed_recv_buffer::sptr buff = _rx_xport->get_recv_buff(); -        if (not buff) -            return; - -        // Get packet info -        vrt::if_packet_info_t if_packet_info; -        if_packet_info.num_packet_words32 = buff->size() / sizeof(uint32_t); -        const uint32_t* packet_buff       = buff->cast<const uint32_t*>(); - -        // unpacking can fail -        uint32_t (*endian_conv)(uint32_t) = uhd::ntohx; -        try { -            if (_endianness == ENDIANNESS_BIG) { -                vrt::chdr::if_hdr_unpack_be(packet_buff, if_packet_info); -                endian_conv = uhd::ntohx; -            } else { -                vrt::chdr::if_hdr_unpack_le(packet_buff, if_packet_info); -                endian_conv = uhd::wtohx; -            } -        } catch (const uhd::value_error& ex) { -            UHD_LOGGER_ERROR("RFNOC") -                << "[async message handler] Error parsing async message packet: " -                << ex.what() << std::endl; -            return; -        } - -        // We discard anything that's not actually a command or response packet. -        if (not(if_packet_info.packet_type & vrt::if_packet_info_t::PACKET_TYPE_CMD) -            or if_packet_info.num_packet_words32 == 0) { -            return; -        } - -        const uint32_t* payload = packet_buff + if_packet_info.num_header_words32; -        async_msg_t metadata(if_packet_info.num_payload_words32 - 1); -        metadata.has_time_spec = if_packet_info.has_tsf; -        // FIXME: not hardcoding tick rate -        metadata.time_spec  = time_spec_t::from_ticks(if_packet_info.tsf, 1); -        metadata.event_code = async_msg_t::event_code_t(endian_conv(payload[0]) & 0xFFFF); -        metadata.sid        = if_packet_info.sid; - -        // load user payload -        for (size_t i = 1; i < if_packet_info.num_payload_words32; i++) { -            metadata.payload[i - 1] = endian_conv(payload[i]); -        } - -        this->post_async_msg(metadata); -    } - -    uint32_t get_local_addr() const -    { -        return _sid.get_src(); -    } - -private: // members -    std::mutex _mutex; -    //! Store event handlers -    std::multimap<async_msg_t::event_code_t, async_handler_type> _event_handlers; -    //! port that receive messge -    uhd::transport::zero_copy_if::sptr _rx_xport; - -    //! port that send out respond -    uhd::transport::zero_copy_if::sptr _tx_xport; - -    //! The source part of \p _sid is the address of this async message handler. -    uhd::sid_t _sid; - -    //! Stores the task that polls the Rx queue -    task::sptr _recv_msg_task; -}; - -async_msg_handler::sptr async_msg_handler::make(uhd::transport::zero_copy_if::sptr recv, -    uhd::transport::zero_copy_if::sptr send, -    uhd::sid_t sid, -    endianness_t endianness) -{ -    if (endianness == ENDIANNESS_BIG) { -        return boost::make_shared<async_msg_handler_impl<ENDIANNESS_BIG>>( -            recv, send, sid); -    } else { -        return boost::make_shared<async_msg_handler_impl<ENDIANNESS_LITTLE>>( -            recv, send, sid); -    } -} diff --git a/host/lib/rfnoc/block_ctrl_base.cpp b/host/lib/rfnoc/block_ctrl_base.cpp deleted file mode 100644 index d186910b9..000000000 --- a/host/lib/rfnoc/block_ctrl_base.cpp +++ /dev/null @@ -1,678 +0,0 @@ -// -// Copyright 2014-2016 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -// This file contains the block control functions for block controller classes. -// See block_ctrl_base_factory.cpp for discovery and factory functions. - -#include "nocscript/block_iface.hpp" -#include <uhd/convert.hpp> -#include <uhd/rfnoc/block_ctrl_base.hpp> -#include <uhd/rfnoc/constants.hpp> -#include <uhd/utils/log.hpp> -#include <uhd/utils/safe_call.hpp> -#include <uhdlib/rfnoc/ctrl_iface.hpp> -#include <uhdlib/rfnoc/wb_iface_adapter.hpp> -#include <uhdlib/utils/compat_check.hpp> -#include <boost/bind.hpp> -#include <boost/format.hpp> -#include <chrono> -#include <thread> - -using namespace uhd; -using namespace uhd::rfnoc; -using std::string; - -/*********************************************************************** - * Structors - **********************************************************************/ -block_ctrl_base::block_ctrl_base(const make_args_t& make_args) -    : _tree(make_args.tree) -    , _ctrl_ifaces(make_args.ctrl_ifaces) -    , _base_address(make_args.base_address & 0xFFF0) -    , _noc_id(sr_read64(SR_READBACK_REG_ID)) -    , _compat_num(sr_read64(SR_READBACK_COMPAT)) -{ -    /*** Identify this block (NoC-ID, block-ID, and block definition) *******/ -    // Read NoC-ID (name is passed in through make_args): -    _block_def = blockdef::make_from_noc_id(_noc_id); -    if (not _block_def) { -        UHD_LOG_DEBUG("RFNOC", -            "No block definition found, using default block configuration " -            "for block with NOC ID: " -                + str(boost::format("0x%08X") % _noc_id)); -        _block_def = blockdef::make_from_noc_id(DEFAULT_NOC_ID_64); -    } -    UHD_ASSERT_THROW(_block_def); -    // For the block ID, we start with block count 0 and increase until -    // we get a block ID that's not already registered: -    _block_id.set(make_args.device_index, make_args.block_name, 0); -    while (_tree->exists("xbar/" + _block_id.get_local())) { -        _block_id++; -    } -    UHD_LOG_INFO(unique_id(), -        str(boost::format("Initializing block control (NOC ID: 0x%016X)") % _noc_id)); - -    /*** Check compat number ************************************************/ -    assert_fpga_compat(NOC_SHELL_COMPAT_MAJOR, -        NOC_SHELL_COMPAT_MINOR, -        _compat_num, -        "noc_shell", -        unique_id(), -        false /* fail_on_minor_behind */ -    ); - -    /*** Initialize property tree *******************************************/ -    _root_path = "xbar/" + _block_id.get_local(); -    _tree->create<uint64_t>(_root_path / "noc_id").set(_noc_id); - -    /*** Reset block state *******************************************/ -    // We don't know the state of the data-path of this block before -    // we initialize. If everything tore down properly, the data-path -    // should be disconnected and thus idle. Reconfiguration of parameters -    // like SIDs is safe to do in that scenario. -    // However, if data is still streaming, block configuration -    // can potentially lock up noc_shell. So we flush the data-path here. - -    // Flush is a block-level operation that can be triggered -    // from any block port. -    // Do it once before clearing... -    if (get_ctrl_ports().size() > 0) { -        _flush(get_ctrl_ports().front()); -    } -    // Clear flow control and misc state -    clear(); - -    /*** Configure ports ****************************************************/ -    size_t n_valid_input_buffers = 0; -    for (const size_t ctrl_port : get_ctrl_ports()) { -        // Set command times to sensible defaults -        set_command_tick_rate(1.0, ctrl_port); -        set_command_time(time_spec_t(0.0), ctrl_port); -        // Set source addresses: -        sr_write(SR_BLOCK_SID, get_address(ctrl_port), ctrl_port); -        // Set sink buffer sizes: -        const uint64_t fifo_size_reg = sr_read64(SR_READBACK_REG_FIFOSIZE, ctrl_port); -        const size_t buf_size_bytes  = size_t(fifo_size_reg & 0xFFFFFFFF); -        if (buf_size_bytes > 0) { -            n_valid_input_buffers++; -        } -        _tree->create<size_t>(_root_path / "input_buffer_size" / ctrl_port) -            .set(buf_size_bytes); -        // Set MTU size and convert to bytes: -        settingsbus_reg_t reg_mtu = SR_READBACK_REG_MTU; -        size_t mtu                = 8 * (1 << size_t(sr_read64(reg_mtu, ctrl_port))); -        _tree->create<size_t>(_root_path / "mtu" / ctrl_port).set(mtu); -        // Set command FIFO size -        const uint32_t cmd_fifo_size = (fifo_size_reg >> 32) & 0xFFFFFFFF; -        _ctrl_ifaces[ctrl_port]->set_cmd_fifo_size(cmd_fifo_size); -        // Set default destination SIDs -        // Otherwise, the default is someone else's SID, which we don't want -        sr_write(SR_RESP_IN_DST_SID, 0xFFFF, ctrl_port); -        sr_write(SR_RESP_OUT_DST_SID, 0xFFFF, ctrl_port); -    } - -    /*** Register names *****************************************************/ -    blockdef::registers_t sregs = _block_def->get_settings_registers(); -    for (const std::string& reg_name : sregs.keys()) { -        if (DEFAULT_NAMED_SR.has_key(reg_name)) { -            throw uhd::runtime_error( -                str(boost::format("Register name %s is already defined!") % reg_name)); -        } -        _tree->create<size_t>(_root_path / "registers" / "sr" / reg_name) -            .set(sregs.get(reg_name)); -    } -    blockdef::registers_t rbacks = _block_def->get_readback_registers(); -    for (const std::string& reg_name : rbacks.keys()) { -        _tree->create<size_t>(_root_path / "registers" / "rb" / reg_name) -            .set(rbacks.get(reg_name)); -    } - -    /*** Init I/O port definitions ******************************************/ -    _init_port_defs("in", _block_def->get_input_ports()); -    _init_port_defs("out", _block_def->get_output_ports()); -    _num_input_ports = _block_def->get_input_ports().size(); -    _num_output_ports = _block_def->get_output_ports().size(); -    // FIXME this warning always fails until the input buffer code above is fixed -    // if (_tree->list(_root_path / "ports/in").size() != n_valid_input_buffers) { -    //    UHD_LOGGER_WARNING(unique_id()) << -    //        boost::format("[%s] defines %d input buffer sizes, but %d input ports") -    //        % get_block_id().get() -    //        % n_valid_input_buffers -    //        % _tree->list(_root_path / "ports/in").size() -    //    ; -    //} - -    /*** Init default block args ********************************************/ -    _nocscript_iface = nocscript::block_iface::make(this); -    _init_block_args(); -} - -block_ctrl_base::~block_ctrl_base() -{ -    UHD_SAFE_CALL(if (get_ctrl_ports().size() > 0) { -        // Notify the data-path gatekeeper in noc_shell that we are done -        // with this block. This operation disconnects the noc_block -        // data-path from noc_shell which dumps all input and output -        // packets that are in flight, for now and until the setting is -        // disabled. This prevents long-running blocks without a tear-down -        // mechanism to gracefully flush. -        _start_drain(get_ctrl_ports().front()); -    } _tree->remove(_root_path);) -} - -void block_ctrl_base::_init_port_defs( -    const std::string& direction, blockdef::ports_t ports, const size_t first_port_index) -{ -    size_t port_index = first_port_index; -    for (const blockdef::port_t& port_def : ports) { -        fs_path port_path = _root_path / "ports" / direction / port_index; -        if (not _tree->exists(port_path)) { -            _tree->create<blockdef::port_t>(port_path); -        } -        UHD_LOGGER_TRACE(unique_id()) -            << "Adding port definition at " << port_path -            << boost::format(": type = '%s' pkt_size = '%s' vlen = '%s'") -                   % port_def["type"] % port_def["pkt_size"] % port_def["vlen"]; -        _tree->access<blockdef::port_t>(port_path).set(port_def); -        port_index++; -    } -} - -void block_ctrl_base::_init_block_args() -{ -    blockdef::args_t args = _block_def->get_args(); -    fs_path arg_path      = _root_path / "args"; -    for (const size_t port : get_ctrl_ports()) { -        _tree->create<std::string>(arg_path / port); -    } - -    // First, create all nodes. -    for (const auto& arg : args) { -        fs_path arg_type_path = arg_path / arg["port"] / arg["name"] / "type"; -        _tree->create<std::string>(arg_type_path).set(arg["type"]); -        fs_path arg_val_path = arg_path / arg["port"] / arg["name"] / "value"; -        if (arg["type"] == "int_vector") { -            throw uhd::runtime_error("not yet implemented: int_vector"); -        } else if (arg["type"] == "int") { -            _tree->create<int>(arg_val_path); -        } else if (arg["type"] == "double") { -            _tree->create<double>(arg_val_path); -        } else if (arg["type"] == "string") { -            _tree->create<string>(arg_val_path); -        } else { -            UHD_THROW_INVALID_CODE_PATH(); -        } -    } -    // Next: Create all the subscribers and coercers. -    // TODO: Add coercer -#define _SUBSCRIBE_CHECK_AND_RUN(type, arg_tag, error_message)                        \ -    _tree->access<type>(arg_val_path)                                                 \ -        .add_coerced_subscriber(boost::bind((&nocscript::block_iface::run_and_check), \ -            _nocscript_iface,                                                         \ -            arg[#arg_tag],                                                            \ -            error_message)) -    for (const auto& arg : args) { -        fs_path arg_val_path = arg_path / arg["port"] / arg["name"] / "value"; -        if (not arg["check"].empty()) { -            if (arg["type"] == "string") { -                _SUBSCRIBE_CHECK_AND_RUN(string, check, arg["check_message"]); -            } else if (arg["type"] == "int") { -                _SUBSCRIBE_CHECK_AND_RUN(int, check, arg["check_message"]); -            } else if (arg["type"] == "double") { -                _SUBSCRIBE_CHECK_AND_RUN(double, check, arg["check_message"]); -            } else if (arg["type"] == "int_vector") { -                throw uhd::runtime_error("not yet implemented: int_vector"); -            } else { -                UHD_THROW_INVALID_CODE_PATH(); -            } -        } -        if (not arg["action"].empty()) { -            if (arg["type"] == "string") { -                _SUBSCRIBE_CHECK_AND_RUN(string, action, ""); -            } else if (arg["type"] == "int") { -                _SUBSCRIBE_CHECK_AND_RUN(int, action, ""); -            } else if (arg["type"] == "double") { -                _SUBSCRIBE_CHECK_AND_RUN(double, action, ""); -            } else if (arg["type"] == "int_vector") { -                throw uhd::runtime_error("not yet implemented: int_vector"); -            } else { -                UHD_THROW_INVALID_CODE_PATH(); -            } -        } -    } - -    // Finally: Set the values. This will call subscribers, if we have any. -    for (const auto& arg : args) { -        fs_path arg_val_path = arg_path / arg["port"] / arg["name"] / "value"; -        if (not arg["value"].empty()) { -            if (arg["type"] == "int_vector") { -                throw uhd::runtime_error("not yet implemented: int_vector"); -            } else if (arg["type"] == "int") { -                _tree->access<int>(arg_val_path).set(std::stoi(arg["value"])); -            } else if (arg["type"] == "double") { -                _tree->access<double>(arg_val_path).set(std::stod(arg["value"])); -            } else if (arg["type"] == "string") { -                _tree->access<string>(arg_val_path).set(arg["value"]); -            } else { -                UHD_THROW_INVALID_CODE_PATH(); -            } -        } -    } -} - -/*********************************************************************** - * FPGA control & communication - **********************************************************************/ -timed_wb_iface::sptr block_ctrl_base::get_ctrl_iface(const size_t block_port) -{ -    return boost::make_shared<wb_iface_adapter>(_ctrl_ifaces[block_port], -        boost::bind(&block_ctrl_base::get_command_tick_rate, this, block_port), -        boost::bind(&block_ctrl_base::set_command_time, this, _1, block_port), -        boost::bind(&block_ctrl_base::get_command_time, this, block_port)); -} - -std::vector<size_t> block_ctrl_base::get_ctrl_ports() const -{ -    std::vector<size_t> ctrl_ports; -    ctrl_ports.reserve(_ctrl_ifaces.size()); -    std::pair<size_t, ctrl_iface::sptr> it; -    for (auto it : _ctrl_ifaces) { -        ctrl_ports.push_back(it.first); -    } -    return ctrl_ports; -} - -void block_ctrl_base::sr_write(const uint32_t reg, const uint32_t data, const size_t port) -{ -    if (not _ctrl_ifaces.count(port)) { -        throw uhd::key_error(str(boost::format("[%s] sr_write(): No such port: %d") -                                 % get_block_id().get() % port)); -    } -    try { -        _ctrl_ifaces[port]->send_cmd_pkt( -            reg, data, false, _cmd_timespecs[port].to_ticks(_cmd_tickrates[port])); -    } catch (const std::exception& ex) { -        throw uhd::io_error(str(boost::format("[%s] sr_write() failed: %s") -                                % get_block_id().get() % ex.what())); -    } -} - -void block_ctrl_base::sr_write( -    const std::string& reg, const uint32_t data, const size_t port) -{ -    uint32_t reg_addr = 255; -    if (DEFAULT_NAMED_SR.has_key(reg)) { -        reg_addr = DEFAULT_NAMED_SR[reg]; -    } else { -        if (not _tree->exists(_root_path / "registers" / "sr" / reg)) { -            throw uhd::key_error( -                str(boost::format("Unknown settings register name: %s") % reg)); -        } -        reg_addr = -            uint32_t(_tree->access<size_t>(_root_path / "registers" / "sr" / reg).get()); -    } -    return sr_write(reg_addr, data, port); -} - -uint64_t block_ctrl_base::sr_read64(const settingsbus_reg_t reg, const size_t port) -{ -    if (not _ctrl_ifaces.count(port)) { -        throw uhd::key_error(str(boost::format("[%s] sr_read64(): No such port: %d") -                                 % get_block_id().get() % port)); -    } -    try { -        return _ctrl_ifaces[port]->send_cmd_pkt( -            SR_READBACK, reg, true, _cmd_timespecs[port].to_ticks(_cmd_tickrates[port])); -    } catch (const std::exception& ex) { -        throw uhd::io_error(str(boost::format("[%s] sr_read64() failed: %s") -                                % get_block_id().get() % ex.what())); -    } -} - -uint32_t block_ctrl_base::sr_read32(const settingsbus_reg_t reg, const size_t port) -{ -    if (not _ctrl_ifaces.count(port)) { -        throw uhd::key_error(str(boost::format("[%s] sr_read32(): No such port: %d") -                                 % get_block_id().get() % port)); -    } -    try { -        return uint32_t(_ctrl_ifaces[port]->send_cmd_pkt( -            SR_READBACK, reg, true, _cmd_timespecs[port].to_ticks(_cmd_tickrates[port]))); -    } catch (const std::exception& ex) { -        throw uhd::io_error(str(boost::format("[%s] sr_read32() failed: %s") -                                % get_block_id().get() % ex.what())); -    } -} - -uint64_t block_ctrl_base::user_reg_read64(const uint32_t addr, const size_t port) -{ -    try { -        // TODO: When timed readbacks are used, time the second, but not the first -        // Set readback register address -        sr_write(SR_READBACK_ADDR, addr, port); -        // Read readback register via RFNoC -        return sr_read64(SR_READBACK_REG_USER, port); -    } catch (const std::exception& ex) { -        throw uhd::io_error(str(boost::format("%s user_reg_read64() failed: %s") -                                % get_block_id().get() % ex.what())); -    } -} - -uint64_t block_ctrl_base::user_reg_read64(const std::string& reg, const size_t port) -{ -    if (not _tree->exists(_root_path / "registers" / "rb" / reg)) { -        throw uhd::key_error( -            str(boost::format("Invalid readback register name: %s") % reg)); -    } -    return user_reg_read64( -        uint32_t(_tree->access<size_t>(_root_path / "registers" / "rb" / reg).get()), -        port); -} - -uint32_t block_ctrl_base::user_reg_read32(const uint32_t addr, const size_t port) -{ -    try { -        // Set readback register address -        sr_write(SR_READBACK_ADDR, addr, port); -        // Read readback register via RFNoC -        return sr_read32(SR_READBACK_REG_USER, port); -    } catch (const std::exception& ex) { -        throw uhd::io_error(str(boost::format("[%s] user_reg_read32() failed: %s") -                                % get_block_id().get() % ex.what())); -    } -} - -uint32_t block_ctrl_base::user_reg_read32(const std::string& reg, const size_t port) -{ -    if (not _tree->exists(_root_path / "registers" / "rb" / reg)) { -        throw uhd::key_error( -            str(boost::format("Invalid readback register name: %s") % reg)); -    } -    return user_reg_read32( -        uint32_t(_tree->access<size_t>(_root_path / "registers" / "rb" / reg).get()), -        port); -} - -void block_ctrl_base::set_command_time(const time_spec_t& time_spec, const size_t port) -{ -    if (port == ANY_PORT) { -        for (const size_t specific_port : get_ctrl_ports()) { -            set_command_time(time_spec, specific_port); -        } -        return; -    } - -    _cmd_timespecs[port] = time_spec; -    _set_command_time(time_spec, port); -} - -time_spec_t block_ctrl_base::get_command_time(const size_t port) -{ -    return _cmd_timespecs[port]; -} - -void block_ctrl_base::set_command_tick_rate(const double tick_rate, const size_t port) -{ -    if (port == ANY_PORT) { -        for (const size_t specific_port : get_ctrl_ports()) { -            set_command_tick_rate(tick_rate, specific_port); -        } -        return; -    } - -    _cmd_tickrates[port] = tick_rate; -} - -double block_ctrl_base::get_command_tick_rate(const size_t port) -{ -    return _cmd_tickrates[port]; -} - -void block_ctrl_base::clear_command_time(const size_t port) -{ -    _cmd_timespecs[port] = time_spec_t(0.0); -} - -void block_ctrl_base::clear() -{ -    UHD_LOG_TRACE(unique_id(), "block_ctrl_base::clear()"); -    // Call parent... -    node_ctrl_base::clear(); -    // ...then child -    for (const size_t port_index : get_ctrl_ports()) { -        _clear(port_index); -    } -} - -uint32_t block_ctrl_base::get_address(size_t block_port) -{ -    UHD_ASSERT_THROW(block_port < 16); -    return (_base_address & 0xFFF0) | (block_port & 0xF); -} - -/*********************************************************************** - * Argument handling - **********************************************************************/ -void block_ctrl_base::set_args(const uhd::device_addr_t& args, const size_t port) -{ -    for (const std::string& key : args.keys()) { -        if (_tree->exists(get_arg_path(key, port))) { -            set_arg(key, args.get(key), port); -        } -    } -} - -void block_ctrl_base::set_arg( -    const std::string& key, const std::string& val, const size_t port) -{ -    fs_path arg_path = get_arg_path(key, port); -    if (not _tree->exists(arg_path / "value")) { -        throw uhd::runtime_error(str( -            boost::format("Attempting to set uninitialized argument '%s' on block '%s'") -            % key % unique_id())); -    } - -    std::string type     = _tree->access<std::string>(arg_path / "type").get(); -    fs_path arg_val_path = arg_path / "value"; -    try { -        if (type == "string") { -            _tree->access<std::string>(arg_val_path).set(val); -        } else if (type == "int") { -            _tree->access<int>(arg_val_path).set(std::stoi(val)); -        } else if (type == "double") { -            _tree->access<double>(arg_val_path).set(std::stod(val)); -        } else if (type == "int_vector") { -            throw uhd::runtime_error("not yet implemented: int_vector"); -        } -    } catch (const boost::bad_lexical_cast&) { -        throw uhd::value_error( -            str(boost::format("Error trying to cast value %s == '%s' to type '%s'") % key -                % val % type)); -    } -} - -device_addr_t block_ctrl_base::get_args(const size_t port) const -{ -    device_addr_t args; -    for (const std::string& key : _tree->list(_root_path / "args" / port)) { -        args[key] = get_arg(key); -    } -    return args; -} - -std::string block_ctrl_base::get_arg(const std::string& key, const size_t port) const -{ -    fs_path arg_path = get_arg_path(key, port); -    if (not _tree->exists(arg_path / "value")) { -        throw uhd::runtime_error(str( -            boost::format("Attempting to get uninitialized argument '%s' on block '%s'") -            % key % unique_id())); -    } - -    std::string type     = _tree->access<std::string>(arg_path / "type").get(); -    fs_path arg_val_path = arg_path / "value"; -    if (type == "string") { -        return _tree->access<std::string>(arg_val_path).get(); -    } else if (type == "int") { -        return std::to_string(_tree->access<int>(arg_val_path).get()); -    } else if (type == "double") { -        return std::to_string(_tree->access<double>(arg_val_path).get()); -    } else if (type == "int_vector") { -        throw uhd::runtime_error("not yet implemented: int_vector"); -    } - -    UHD_THROW_INVALID_CODE_PATH(); -} - -std::string block_ctrl_base::get_arg_type(const std::string& key, const size_t port) const -{ -    fs_path arg_type_path = _root_path / "args" / port / key / "type"; -    return _tree->access<std::string>(arg_type_path).get(); -} - -stream_sig_t block_ctrl_base::_resolve_port_def(const blockdef::port_t& port_def) const -{ -    if (not port_def.is_valid()) { -        throw uhd::runtime_error( -            str(boost::format("Invalid port definition: %s") % port_def.to_string())); -    } - -    // TODO this entire section is pretty dumb at this point. Needs better -    // checks. -    stream_sig_t stream_sig; -    // Item Type -    if (port_def.is_variable("type")) { -        std::string var_name = port_def["type"].substr(1); -        // TODO check this is even a string -        stream_sig.item_type = get_arg(var_name); -    } else if (port_def.is_keyword("type")) { -        throw uhd::runtime_error("keywords resolution for type not yet implemented"); -    } else { -        stream_sig.item_type = port_def["type"]; -    } - -    // Vector length -    if (port_def.is_variable("vlen")) { -        std::string var_name = port_def["vlen"].substr(1); -        stream_sig.vlen      = boost::lexical_cast<size_t>(get_arg(var_name)); -    } else if (port_def.is_keyword("vlen")) { -        throw uhd::runtime_error("keywords resolution for vlen not yet implemented"); -    } else { -        stream_sig.vlen = boost::lexical_cast<size_t>(port_def["vlen"]); -    } - -    // Packet size -    if (port_def.is_variable("pkt_size")) { -        std::string var_name   = port_def["pkt_size"].substr(1); -        stream_sig.packet_size = boost::lexical_cast<size_t>(get_arg(var_name)); -    } else if (port_def.is_keyword("pkt_size")) { -        if (port_def["pkt_size"] != "%vlen") { -            throw uhd::runtime_error( -                "generic keywords resolution for pkt_size not yet implemented"); -        } -        if (stream_sig.vlen == 0) { -            stream_sig.packet_size = 0; -        } else { -            if (stream_sig.item_type.empty()) { -                throw uhd::runtime_error( -                    "cannot resolve pkt_size if item type is not given"); -            } -            size_t bpi = uhd::convert::get_bytes_per_item(stream_sig.item_type); -            stream_sig.packet_size = stream_sig.vlen * bpi; -        } -    } else { -        stream_sig.packet_size = boost::lexical_cast<size_t>(port_def["pkt_size"]); -    } - -    return stream_sig; -} - -void block_ctrl_base::_start_drain(const size_t port) -{ -    // Begin flushing data out of the block by writing to the flushing -    // registers, then disabling flow control. We do this because we don't know -    // what state the flow-control module was left in in the previous run -    sr_write(SR_CLEAR_TX_FC, 0x2, port); -    sr_write(SR_CLEAR_RX_FC, 0x2, port); -    sr_write(SR_FLOW_CTRL_EN, 0, port); -} - -bool block_ctrl_base::_flush(const size_t port) -{ -    UHD_LOG_TRACE(unique_id(), "block_ctrl_base::_flush (port=" << port << ")"); - -    auto is_data_streaming = [this](int time_ms) -> bool { -        // noc_shell has 2 16-bit counters (one for TX and one for RX) in the top -        // 32 bits of the SR_READBACK_REG_GLOBAL_PARAMS. For all the checks below -        // we want to make sure that the counts are not changing i.e. no data is -        // streaming. So we just look at the two counters together as a single -        // 32-bit quantity. -        auto old_cnts = -            static_cast<uint32_t>(this->sr_read64(SR_READBACK_REG_GLOBAL_PARAMS) >> 32); -        std::this_thread::sleep_for(std::chrono::milliseconds(time_ms)); -        auto new_cnts = -            static_cast<uint32_t>(this->sr_read64(SR_READBACK_REG_GLOBAL_PARAMS) >> 32); -        return (new_cnts != old_cnts); -    }; - -    // We always want to try flushing out data. This is done by starting to -    // drain the data out of the block, then checking if counts have changed. -    // If a change is detected, this is most likely because the last -    // session terminated abnormally or if logic in a noc_block is -    // misbehaving. This is a situation that we may not be able to -    // recover from because we are in a partially initialized state. -    // We will try to at least not lock up the FPGA. - -    // Disconnect the RX and TX data paths and let them flush. -    // A timeout of 2s is chosen to be conservative. It needs to account for: -    // - Upstream blocks that weren't terminated to run out of FC credits -    // - This block which might be finishing up with its data output -    constexpr int FLUSH_TIMEOUT_MS = 2000; // This is approximate -    bool success                   = false; -    _start_drain(port); -    for (int i = 0; i < FLUSH_TIMEOUT_MS / 10; i++) { -        if (not is_data_streaming(10)) { -            success = true; -            break; -        } -    } -    // Stop flushing -    sr_write(SR_CLEAR_TX_FC, 0x0, port); // Enable TX data-path -    sr_write(SR_CLEAR_RX_FC, 0x0, port); // Enable RX data-path - -    if (not success) { -        // Print a warning only if data was still flushing -        // after the timeout elapsed -        UHD_LOGGER_WARNING(unique_id()) -            << "This block seems to be busy most likely due to the abnormal termination " -               "of a previous " -               "session. Attempted recovery but it may not have worked depending on the " -               "behavior of " -               "other blocks in the design. Please restart the application."; -    } -    return success; -} - - -/*********************************************************************** - * Hooks & Derivables - **********************************************************************/ -void block_ctrl_base::_clear(const size_t port) -{ -    UHD_LOG_TRACE(unique_id(), "block_ctrl_base::_clear()"); -    sr_write(SR_CLEAR_TX_FC, 0x1, port); // Write 1 to trigger a single cycle clear event -    sr_write(SR_CLEAR_TX_FC, 0x0, port); // Write 0 to reset the clear flag -    sr_write(SR_CLEAR_RX_FC, 0x1, port); // Write 1 to trigger a single cycle clear event -    sr_write(SR_CLEAR_RX_FC, 0x0, port); // Write 0 to reset the clear flag -} - -void block_ctrl_base::_set_command_time( -    const time_spec_t& /*time_spec*/, const size_t /*port*/) -{ -    UHD_LOG_TRACE(unique_id(), "block_ctrl_base::_set_command_time()"); -} -// vim: sw=4 et: diff --git a/host/lib/rfnoc/block_ctrl_base_factory.cpp b/host/lib/rfnoc/block_ctrl_base_factory.cpp deleted file mode 100644 index 6f3e9d9f7..000000000 --- a/host/lib/rfnoc/block_ctrl_base_factory.cpp +++ /dev/null @@ -1,87 +0,0 @@ -// -// Copyright 2014 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#include <uhd/rfnoc/block_ctrl_base.hpp> -#include <uhd/rfnoc/blockdef.hpp> -#include <uhd/utils/log.hpp> -#include <boost/format.hpp> - -using namespace uhd; -using namespace uhd::rfnoc; - -typedef uhd::dict<std::string, block_ctrl_base::make_t> block_fcn_reg_t; -// Instantiate the block function registry container -UHD_SINGLETON_FCN(block_fcn_reg_t, get_block_fcn_regs); - -void block_ctrl_base::register_block(const make_t& make, const std::string& key) -{ -    if (get_block_fcn_regs().has_key(key)) { -        throw uhd::runtime_error(str( -            boost::format( -                "Attempting to register an RFNoC block with key %s for the second time.") -            % key)); -    } - -    get_block_fcn_regs().set(key, make); -} - -/*! Look up names for blocks in XML files using NoC ID. - */ -static void lookup_block_key(uint64_t noc_id, make_args_t& make_args) -{ -    try { -        blockdef::sptr bd = blockdef::make_from_noc_id(noc_id); -        if (not bd) { -            make_args.block_key  = DEFAULT_BLOCK_NAME; -            make_args.block_name = DEFAULT_BLOCK_NAME; -            return; -        } -        UHD_ASSERT_THROW(bd->is_block()); -        make_args.block_key  = bd->get_key(); -        make_args.block_name = bd->get_name(); -        return; -    } catch (std::exception& e) { -        UHD_LOGGER_WARNING("RFNOC") -            << str(boost::format("Error while looking up name for NoC-ID %016X.\n%s") -                   % noc_id % e.what()); -    } - -    make_args.block_key  = DEFAULT_BLOCK_NAME; -    make_args.block_name = DEFAULT_BLOCK_NAME; -} - - -block_ctrl_base::sptr block_ctrl_base::make( -    const make_args_t& make_args_, uint64_t noc_id) -{ -    UHD_LOGGER_TRACE("RFNOC") << "[RFNoC Factory] block_ctrl_base::make()"; -    make_args_t make_args = make_args_; - -    // Check if a block key was specified, in this case, we *must* either -    // create a specialized block controller class or throw -    if (make_args.block_key.empty()) { -        lookup_block_key(noc_id, make_args); -    } else if (not get_block_fcn_regs().has_key(make_args.block_key)) { -        throw uhd::runtime_error( -            str(boost::format("No block controller class registered for key '%s'.") -                % make_args.block_key)); -    } -    if (not get_block_fcn_regs().has_key(make_args.block_key)) { -        UHD_LOG_WARNING("RFNOC", -            "Can't find a block controller for key " -                << make_args.block_key << ", using default block controller!"); -        make_args.block_key = DEFAULT_BLOCK_NAME; -    } -    if (make_args.block_name.empty()) { -        make_args.block_name = make_args.block_key; -    } - -    UHD_LOGGER_TRACE("RFNOC") << "[RFNoC Factory] Using controller key '" -                              << make_args.block_key << "' and block name '" -                              << make_args.block_name << "'"; -    return get_block_fcn_regs()[make_args.block_key](make_args); -} diff --git a/host/lib/rfnoc/block_ctrl_impl.cpp b/host/lib/rfnoc/block_ctrl_impl.cpp deleted file mode 100644 index 030cd77de..000000000 --- a/host/lib/rfnoc/block_ctrl_impl.cpp +++ /dev/null @@ -1,23 +0,0 @@ -// -// Copyright 2014 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#include <uhd/rfnoc/block_ctrl.hpp> - -using namespace uhd::rfnoc; - -class block_ctrl_impl : public block_ctrl -{ -public: -    UHD_RFNOC_BLOCK_CONSTRUCTOR(block_ctrl) -    { -        // nop -    } - -    // Very empty class, this one -}; - -UHD_RFNOC_BLOCK_REGISTER(block_ctrl, DEFAULT_BLOCK_NAME); diff --git a/host/lib/rfnoc/blockdef_xml_impl.cpp b/host/lib/rfnoc/blockdef_xml_impl.cpp deleted file mode 100644 index 2326043ca..000000000 --- a/host/lib/rfnoc/blockdef_xml_impl.cpp +++ /dev/null @@ -1,438 +0,0 @@ -// -// Copyright 2014-2015 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#include <uhd/exception.hpp> -#include <uhd/rfnoc/blockdef.hpp> -#include <uhd/rfnoc/constants.hpp> -#include <uhd/utils/log.hpp> -#include <uhd/utils/paths.hpp> -#include <boost/algorithm/string.hpp> -#include <boost/filesystem/operations.hpp> -#include <boost/format.hpp> -#include <boost/lexical_cast.hpp> -#include <boost/property_tree/ptree.hpp> -#include <boost/property_tree/xml_parser.hpp> -#include <cstdlib> - -using namespace uhd; -using namespace uhd::rfnoc; -namespace fs = boost::filesystem; -namespace pt = boost::property_tree; - -static const fs::path XML_BLOCKS_SUBDIR("blocks"); -static const fs::path XML_COMPONENTS_SUBDIR("components"); -static const fs::path XML_EXTENSION(".xml"); - - -/**************************************************************************** - * port_t stuff - ****************************************************************************/ -const device_addr_t blockdef::port_t::PORT_ARGS("name," -                                                "type," -                                                "vlen=0," -                                                "pkt_size=0," -                                                "optional=0," -                                                "bursty=0," -                                                "port,"); - -blockdef::port_t::port_t() -{ -    // This guarantees that we can access these keys -    // even if they were never initialized: -    for (const std::string& key : PORT_ARGS.keys()) { -        set(key, PORT_ARGS[key]); -    } -} - -bool blockdef::port_t::is_variable(const std::string& key) const -{ -    const std::string& val = get(key); -    return (val[0] == '$'); -} - -bool blockdef::port_t::is_keyword(const std::string& key) const -{ -    const std::string& val = get(key); -    return (val[0] == '%'); -} - -bool blockdef::port_t::is_valid() const -{ -    // Check we have all the keys: -    for (const std::string& key : PORT_ARGS.keys()) { -        if (not has_key(key)) { -            return false; -        } -    } - -    // Twelve of the clock, all seems well -    return true; -} - -std::string blockdef::port_t::to_string() const -{ -    std::string result; -    for (const std::string& key : PORT_ARGS.keys()) { -        if (has_key(key)) { -            result += str(boost::format("%s=%s,") % key % get(key)); -        } -    } - -    return result; -} - -/**************************************************************************** - * arg_t stuff - ****************************************************************************/ -const device_addr_t blockdef::arg_t::ARG_ARGS( -    // List all tags/args an <arg> can have here: -    "name," -    "type," -    "value," -    "check," -    "check_message," -    "action," -    "port=0,"); - -const std::set<std::string> blockdef::arg_t::VALID_TYPES = { -    // List all tags/args a <type> can have here: -    "string", -    "int", -    "int_vector", -    "double"}; - -blockdef::arg_t::arg_t() -{ -    // This guarantees that we can access these keys -    // even if they were never initialized: -    for (const std::string& key : ARG_ARGS.keys()) { -        set(key, ARG_ARGS[key]); -    } -} - -bool blockdef::arg_t::is_valid() const -{ -    // 1. Check we have all the keys: -    for (const std::string& key : ARG_ARGS.keys()) { -        if (not has_key(key)) { -            return false; -        } -    } - -    // 2. Check arg type is valid -    if (not get("type").empty() and not VALID_TYPES.count(get("type"))) { -        return false; -    } - -    // Twelve of the clock, all seems well -    return true; -} - -std::string blockdef::arg_t::to_string() const -{ -    std::string result; -    for (const std::string& key : ARG_ARGS.keys()) { -        if (has_key(key)) { -            result += str(boost::format("%s=%s,") % key % get(key)); -        } -    } - -    return result; -} - -/**************************************************************************** - * blockdef_impl stuff - ****************************************************************************/ -class blockdef_xml_impl : public blockdef -{ -public: -    enum xml_repr_t { DESCRIBES_BLOCK, DESCRIBES_COMPONENT }; - -    //! Returns a list of base paths for the XML files. -    // It is assumed that block definitions are in a subdir with name -    // XML_BLOCKS_SUBDIR and component definitions in a subdir with name -    // XML_COMPONENTS_SUBDIR -    static std::vector<boost::filesystem::path> get_xml_paths() -    { -        std::vector<boost::filesystem::path> paths; - -        // Path from environment variable -        if (std::getenv(XML_PATH_ENV.c_str()) != NULL) { -            paths.push_back(boost::filesystem::path(std::getenv(XML_PATH_ENV.c_str()))); -        } - -        // Finally, the default path -        const boost::filesystem::path pkg_path = uhd::get_pkg_path(); -        paths.push_back(pkg_path / XML_DEFAULT_PATH); - -        return paths; -    } - -    //! Matches a NoC ID through substring matching -    static bool match_noc_id(const std::string& lhs_, uint64_t rhs_) -    { -        // Sanitize input: Make both values strings with all uppercase -        // characters and no leading 0x. Check inputs are valid. -        std::string lhs = boost::to_upper_copy(lhs_); -        std::string rhs = str(boost::format("%016X") % rhs_); -        if (lhs.size() > 2 and lhs[0] == '0' and lhs[1] == 'X') { -            lhs = lhs.substr(2); -        } -        UHD_ASSERT_THROW(rhs.size() == 16); -        if (lhs.size() < 4 or lhs.size() > 16) { -            throw uhd::value_error( -                str(boost::format("%s is not a valid NoC ID (must be hexadecimal, min 4 " -                                  "and max 16 characters)") -                    % lhs_)); -        } - -        // OK, all good now. Next, we try and match the substring lhs in rhs: -        return (rhs.find(lhs) == 0); -    } - -    //! Open the file at filename and see if it's a block definition for the given NoC ID -    static bool has_noc_id(uint64_t noc_id, const fs::path& filename) -    { -        pt::ptree propt; -        try { -            read_xml(filename.string(), propt); -            for (pt::ptree::value_type& v : propt.get_child("nocblock.ids")) { -                if (v.first == "id" and match_noc_id(v.second.data(), noc_id)) { -                    return true; -                } -            } -        } catch (std::exception& e) { -            UHD_LOGGER_WARNING("RFNOC") << "has_noc_id(): caught exception " << e.what() -                                        << " while parsing file: " << filename.string(); -            return false; -        } -        return false; -    } - -    blockdef_xml_impl( -        const fs::path& filename, uint64_t noc_id, xml_repr_t type = DESCRIBES_BLOCK) -        : _type(type), _noc_id(noc_id) -    { -        UHD_LOGGER_DEBUG("RFNOC") -            << boost::format("Reading XML file %s for NOC ID 0x%08X") -                   % filename.string().c_str() % noc_id; -        read_xml(filename.string(), _pt); -        try { -            // Check key is valid -            get_key(); -            // Check name is valid -            get_name(); -            // Check there's at least one port -            ports_t in  = get_input_ports(); -            ports_t out = get_output_ports(); -            if (in.empty() and out.empty()) { -                throw uhd::runtime_error("Block does not define inputs or outputs."); -            } -            // Check args are valid -            get_args(); -            // TODO any more checks? -        } catch (const std::exception& e) { -            throw uhd::runtime_error( -                str(boost::format("Invalid block definition in %s: %s") -                    % filename.string() % e.what())); -        } -    } - -    virtual ~blockdef_xml_impl() {} - -    bool is_block() const -    { -        return _type == DESCRIBES_BLOCK; -    } - -    bool is_component() const -    { -        return _type == DESCRIBES_COMPONENT; -    } - -    std::string get_key() const -    { -        try { -            return _pt.get<std::string>("nocblock.key"); -        } catch (const pt::ptree_bad_path&) { -            return _pt.get<std::string>("nocblock.blockname"); -        } -    } - -    std::string get_name() const -    { -        return _pt.get<std::string>("nocblock.blockname"); -    } - -    uint64_t noc_id() const -    { -        return _noc_id; -    } - -    ports_t get_input_ports() -    { -        return _get_ports("sink"); -    } - -    ports_t get_output_ports() -    { -        return _get_ports("source"); -    } - -    ports_t _get_ports(const std::string& port_type) -    { -        std::set<size_t> port_numbers; -        size_t n_ports = 0; -        ports_t ports; -        for (pt::ptree::value_type& v : _pt.get_child("nocblock.ports")) { -            if (v.first != port_type) -                continue; -            // Now we have the correct sink or source node: -            port_t port; -            for (const std::string& key : port_t::PORT_ARGS.keys()) { -                port[key] = v.second.get(key, port_t::PORT_ARGS[key]); -            } -            // We have to be extra-careful with the port numbers: -            if (port["port"].empty()) { -                port["port"] = std::to_string(n_ports); -            } -            size_t new_port_number; -            try { -                new_port_number = boost::lexical_cast<size_t>(port["port"]); -            } catch (const boost::bad_lexical_cast& e) { -                throw uhd::value_error( -                    str(boost::format("Invalid port number '%s' on port '%s'") -                        % port["port"] % port["name"])); -            } -            if (port_numbers.count(new_port_number) or new_port_number > MAX_NUM_PORTS) { -                throw uhd::value_error( -                    str(boost::format("Port '%s' has invalid port number %d!") -                        % port["name"] % new_port_number)); -            } -            port_numbers.insert(new_port_number); -            n_ports++; -            ports.push_back(port); -        } -        return ports; -    } - -    std::vector<size_t> get_all_port_numbers() -    { -        std::set<size_t> set_ports; -        for (const port_t& port : get_input_ports()) { -            set_ports.insert(boost::lexical_cast<size_t>(port["port"])); -        } -        for (const port_t& port : get_output_ports()) { -            set_ports.insert(boost::lexical_cast<size_t>(port["port"])); -        } -        return std::vector<size_t>(set_ports.begin(), set_ports.end()); -    } - - -    blockdef::args_t get_args() -    { -        args_t args; -        bool is_valid = true; -        pt::ptree def; -        for (pt::ptree::value_type& v : _pt.get_child("nocblock.args", def)) { -            arg_t arg; -            if (v.first != "arg") -                continue; -            for (const std::string& key : arg_t::ARG_ARGS.keys()) { -                arg[key] = v.second.get(key, arg_t::ARG_ARGS[key]); -            } -            if (arg["type"].empty()) { -                arg["type"] = "string"; -            } -            if (not arg.is_valid()) { -                UHD_LOGGER_WARNING("RFNOC") -                    << "Found invalid argument: " << arg.to_string(); -                is_valid = false; -            } -            args.push_back(arg); -        } -        if (not is_valid) { -            throw uhd::runtime_error( -                str(boost::format("Found invalid arguments for block %s.") % get_name())); -        } -        return args; -    } - -    registers_t get_settings_registers() -    { -        return _get_regs("setreg"); -    } - -    registers_t get_readback_registers() -    { -        return _get_regs("readback"); -    } - -    registers_t _get_regs(const std::string& reg_type) -    { -        registers_t registers; -        pt::ptree def; -        for (pt::ptree::value_type& v : _pt.get_child("nocblock.registers", def)) { -            if (v.first != reg_type) -                continue; -            registers[v.second.get<std::string>("name")] = -                boost::lexical_cast<size_t>(v.second.get<size_t>("address")); -        } -        return registers; -    } - - -private: -    //! Tells us if is this for a NoC block, or a component. -    const xml_repr_t _type; -    //! The NoC-ID as reported (there may be several valid NoC IDs, this is the one used) -    const uint64_t _noc_id; - -    //! This is a boost property tree, not the same as -    // our property tree. -    pt::ptree _pt; -}; - -blockdef::sptr blockdef::make_from_noc_id(uint64_t noc_id) -{ -    std::vector<fs::path> paths = blockdef_xml_impl::get_xml_paths(); -    std::vector<fs::path> valid; - -    // Check if any of the paths exist -    for (const auto& base_path : paths) { -        fs::path this_path = base_path / XML_BLOCKS_SUBDIR; -        if (fs::exists(this_path) and fs::is_directory(this_path)) { -            valid.push_back(this_path); -        } -    } - -    if (valid.empty()) { -        throw uhd::assertion_error("Failed to find a valid XML path for RFNoC blocks.\n" -                                   "Try setting the enviroment variable UHD_RFNOC_DIR " -                                   "to the correct location"); -    } - -    // Iterate over all paths -    for (const auto& path : valid) { -        // Iterate over all .xml files -        fs::directory_iterator end_itr; -        for (fs::directory_iterator i(path); i != end_itr; ++i) { -            if (not fs::exists(*i) or fs::is_directory(*i) or fs::is_empty(*i)) { -                continue; -            } -            if (i->path().filename().extension() != XML_EXTENSION) { -                continue; -            } -            if (blockdef_xml_impl::has_noc_id(noc_id, i->path())) { -                return blockdef::sptr(new blockdef_xml_impl(i->path(), noc_id)); -            } -        } -    } - -    return blockdef::sptr(); -} -// vim: sw=4 et: diff --git a/host/lib/rfnoc/ctrl_iface.cpp b/host/lib/rfnoc/ctrl_iface.cpp deleted file mode 100644 index ee2a78df3..000000000 --- a/host/lib/rfnoc/ctrl_iface.cpp +++ /dev/null @@ -1,240 +0,0 @@ -// -// Copyright 2012-2016 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#include <uhd/exception.hpp> -#include <uhd/rfnoc/constants.hpp> -#include <uhd/transport/bounded_buffer.hpp> -#include <uhd/transport/chdr.hpp> -#include <uhd/types/endianness.hpp> -#include <uhd/types/sid.hpp> -#include <uhd/utils/byteswap.hpp> -#include <uhd/utils/safe_call.hpp> -#include <uhdlib/rfnoc/ctrl_iface.hpp> -#include <boost/bind.hpp> -#include <boost/format.hpp> -#include <boost/make_shared.hpp> -#include <boost/thread/mutex.hpp> -#include <boost/thread/thread.hpp> -#include <queue> - -using namespace uhd; -using namespace uhd::rfnoc; -using namespace uhd::transport; - -static const double ACK_TIMEOUT     = 2.0; // supposed to be worst case practical timeout -static const double MASSIVE_TIMEOUT = 10.0; // for when we wait on a timed command - -template <uhd::endianness_t _endianness> class ctrl_iface_impl : public ctrl_iface -{ -public: -    ctrl_iface_impl(const both_xports_t& xports, const std::string& name) -        : _xports(xports) -        , _name(name) -        , _seq_out(0) -        , _max_outstanding_acks(xports.recv->get_num_recv_frames()) -    { - -        UHD_ASSERT_THROW(bool(_xports.send)); -        UHD_ASSERT_THROW(bool(_xports.recv)); -        // Flush the response transport in case we have something over: -        while (_xports.recv->get_recv_buff(0.0)) { -        } -    } - -    virtual ~ctrl_iface_impl(void) -    { -        UHD_SAFE_CALL( -            // dummy peek with the purpose of ack'ing all packets -            this->send_cmd_pkt(0, 0, true);) -    } - -    /******************************************************************* -     * Get and set register implementation -     ******************************************************************/ -    uint64_t send_cmd_pkt(const size_t addr, -        const size_t data, -        const bool readback, -        const uint64_t timestamp = 0) -    { -        boost::mutex::scoped_lock lock(_mutex); -        this->send_pkt(addr, data, timestamp); -        return this->wait_for_ack( -            readback, bool(timestamp != 0) ? MASSIVE_TIMEOUT : ACK_TIMEOUT); -    } - -    void set_cmd_fifo_size(const size_t num_lines) -    { -        _max_outstanding_acks = -            std::min(num_lines / 3, _xports.recv->get_num_recv_frames()); -        UHD_LOG_TRACE("RFNOC", -            "[ctrl_iface " << _name << "] Changed cmd FIFO size to " -                           << _max_outstanding_acks); -    } - -private: -    // This is the buffer type for response messages -    struct resp_buff_type -    { -        uint32_t data[8]; -    }; - -    /******************************************************************* -     * Primary control and interaction private methods -     ******************************************************************/ -    inline void send_pkt( -        const uint32_t addr, const uint32_t data, const uint64_t timestamp) -    { -        managed_send_buffer::sptr buff = _xports.send->get_send_buff(0.0); -        if (not buff) { -            throw uhd::runtime_error("fifo ctrl timed out getting a send buffer"); -        } -        uint32_t* pkt = buff->cast<uint32_t*>(); - -        // load packet info -        vrt::if_packet_info_t packet_info; -        packet_info.link_type           = vrt::if_packet_info_t::LINK_TYPE_CHDR; -        packet_info.packet_type         = vrt::if_packet_info_t::PACKET_TYPE_CMD; -        packet_info.num_payload_words32 = 2; -        packet_info.num_payload_bytes = -            packet_info.num_payload_words32 * sizeof(uint32_t); -        packet_info.packet_count = _seq_out; -        packet_info.tsf          = timestamp; -        packet_info.sob          = false; -        packet_info.eob          = false; -        packet_info.fc_ack       = false; -        packet_info.sid          = _xports.send_sid; -        packet_info.has_sid      = true; -        packet_info.has_cid      = false; -        packet_info.has_tsi      = false; -        packet_info.has_tsf      = bool(timestamp); -        packet_info.has_tlr      = false; - -        // Unpack header and load payload -        if (_endianness == uhd::ENDIANNESS_BIG) { // This if statement gets compiled out -            vrt::if_hdr_pack_be(pkt, packet_info); -            pkt[packet_info.num_header_words32 + 0] = uhd::htonx(addr); -            pkt[packet_info.num_header_words32 + 1] = uhd::htonx(data); -        } else { -            vrt::if_hdr_pack_le(pkt, packet_info); -            pkt[packet_info.num_header_words32 + 0] = uhd::htowx(addr); -            pkt[packet_info.num_header_words32 + 1] = uhd::htowx(data); -        } - -        // UHD_LOGGER_TRACE("RFNOC") << boost::format("0x%08x, 0x%08x\n") % addr % data; -        // send the buffer over the interface -        _outstanding_seqs.push(_seq_out); -        buff->commit(sizeof(uint32_t) * (packet_info.num_packet_words32)); - -        _seq_out++; // inc seq for next call -    } - -    inline uint64_t wait_for_ack(const bool readback, const double timeout) -    { -        while (readback or (_outstanding_seqs.size() >= _max_outstanding_acks)) { -            // get seq to ack from outstanding packets list -            UHD_ASSERT_THROW(not _outstanding_seqs.empty()); -            const size_t seq_to_ack = _outstanding_seqs.front(); - -            // parse the packet -            vrt::if_packet_info_t packet_info; -            resp_buff_type resp_buff; -            memset(&resp_buff, 0x00, sizeof(resp_buff)); -            uint32_t const* pkt = NULL; -            managed_recv_buffer::sptr buff; - -            buff = _xports.recv->get_recv_buff(timeout); -            try { -                UHD_ASSERT_THROW(bool(buff)); -                UHD_ASSERT_THROW(buff->size() > 0); -                _outstanding_seqs.pop(); -            } catch (const std::exception& ex) { -                throw uhd::io_error( -                    str(boost::format("Block ctrl (%s) no response packet - %s") % _name -                        % ex.what())); -            } -            pkt                            = buff->cast<const uint32_t*>(); -            packet_info.num_packet_words32 = buff->size() / sizeof(uint32_t); - -            // parse the buffer -            try { -                if (_endianness == uhd::ENDIANNESS_BIG) { -                    vrt::chdr::if_hdr_unpack_be(pkt, packet_info); -                } else { -                    vrt::chdr::if_hdr_unpack_le(pkt, packet_info); -                } -            } catch (const std::exception& ex) { -                UHD_LOGGER_ERROR("RFNOC") -                    << "[" << _name << "] Block ctrl bad VITA packet: " << ex.what(); -                if (buff) { -                    UHD_LOGGER_INFO("RFNOC") << boost::format("%08X") % pkt[0]; -                    UHD_LOGGER_INFO("RFNOC") << boost::format("%08X") % pkt[1]; -                    UHD_LOGGER_INFO("RFNOC") << boost::format("%08X") % pkt[2]; -                    UHD_LOGGER_INFO("RFNOC") << boost::format("%08X") % pkt[3]; -                } else { -                    UHD_LOGGER_INFO("RFNOC") << "buff is NULL"; -                } -            } - -            // check the buffer -            try { -                UHD_ASSERT_THROW(packet_info.has_sid); -                if (packet_info.sid != _xports.recv_sid.get()) { -                    throw uhd::io_error( -                        str(boost::format("Expected SID: %s  Received SID: %s") -                            % _xports.recv_sid.to_pp_string_hex() -                            % uhd::sid_t(packet_info.sid).to_pp_string_hex())); -                } - -                if (packet_info.packet_count != (seq_to_ack & 0xfff)) { -                    throw uhd::io_error( -                        str(boost::format("Expected packet index: %d " -                                          "Received index: %d") -                            % (seq_to_ack & 0xfff) % packet_info.packet_count)); -                } - -                UHD_ASSERT_THROW(packet_info.num_payload_words32 == 2); -            } catch (const std::exception& ex) { -                throw uhd::io_error( -                    str(boost::format("Block ctrl (%s) packet parse error - %s") % _name -                        % ex.what())); -            } - -            // return the readback value -            if (readback and _outstanding_seqs.empty()) { -                const uint64_t hi = -                    (_endianness == uhd::ENDIANNESS_BIG) -                        ? uhd::ntohx(pkt[packet_info.num_header_words32 + 0]) -                        : uhd::wtohx(pkt[packet_info.num_header_words32 + 0]); -                const uint64_t lo = -                    (_endianness == uhd::ENDIANNESS_BIG) -                        ? uhd::ntohx(pkt[packet_info.num_header_words32 + 1]) -                        : uhd::wtohx(pkt[packet_info.num_header_words32 + 1]); -                return ((hi << 32) | lo); -            } -        } - -        return 0; -    } - - -    const uhd::both_xports_t _xports; -    const std::string _name; -    size_t _seq_out; -    std::queue<size_t> _outstanding_seqs; -    size_t _max_outstanding_acks; - -    boost::mutex _mutex; -}; - -ctrl_iface::sptr ctrl_iface::make(const both_xports_t& xports, const std::string& name) -{ -    if (xports.endianness == uhd::ENDIANNESS_BIG) { -        return boost::make_shared<ctrl_iface_impl<uhd::ENDIANNESS_BIG>>(xports, name); -    } else { -        return boost::make_shared<ctrl_iface_impl<uhd::ENDIANNESS_LITTLE>>(xports, name); -    } -} diff --git a/host/lib/rfnoc/ddc_block_ctrl_impl.cpp b/host/lib/rfnoc/ddc_block_ctrl_impl.cpp deleted file mode 100644 index 13bf43072..000000000 --- a/host/lib/rfnoc/ddc_block_ctrl_impl.cpp +++ /dev/null @@ -1,347 +0,0 @@ -// -// Copyright 2016-2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#include <uhd/convert.hpp> -#include <uhd/rfnoc/ddc_block_ctrl.hpp> -#include <uhd/types/ranges.hpp> -#include <uhd/utils/log.hpp> -#include <uhdlib/usrp/cores/dsp_core_utils.hpp> -#include <uhdlib/utils/compat_check.hpp> -#include <uhdlib/utils/math.hpp> -#include <uhdlib/utils/narrow.hpp> -#include <boost/math/special_functions/round.hpp> -#include <cmath> - -using namespace uhd::rfnoc; - -class ddc_block_ctrl_impl : public ddc_block_ctrl -{ -public: -    UHD_RFNOC_BLOCK_CONSTRUCTOR(ddc_block_ctrl) -    , _fpga_compat(user_reg_read64(RB_REG_COMPAT_NUM)), -        _num_halfbands(uhd::narrow_cast<size_t>(user_reg_read64(RB_REG_NUM_HALFBANDS))), -        _cic_max_decim(uhd::narrow_cast<size_t>(user_reg_read64(RB_REG_CIC_MAX_DECIM))) -    { -        UHD_LOG_DEBUG(unique_id(), -            "Loading DDC with " << get_num_halfbands() -                                << " halfbands and " -                                   "max CIC decimation " -                                << get_cic_max_decim()); -        uhd::assert_fpga_compat(MAJOR_COMP, -            MINOR_COMP, -            _fpga_compat, -            "DDC", -            "DDC", -            false /* Let it slide if minors mismatch */ -        ); - -        // Argument/prop tree hooks -        for (size_t chan = 0; chan < get_input_ports().size(); chan++) { -            const double default_freq = get_arg<double>("freq", chan); -            _tree->access<double>(get_arg_path("freq/value", chan)) -                .set_coercer([this, chan](const double value) { -                    return this->set_freq(value, chan); -                }) -                .set(default_freq); -            ; -            const double default_output_rate = get_arg<double>("output_rate", chan); -            _tree->access<double>(get_arg_path("output_rate/value", chan)) -                .set_coercer([this, chan](const double value) { -                    return this->set_output_rate(value, chan); -                }) -                .set(default_output_rate) -                .add_coerced_subscriber([this](const double) { update_graph(); }); -            _tree->access<double>(get_arg_path("input_rate/value", chan)) -                .add_coerced_subscriber( -                    [this, chan](const double rate) { this->set_input_rate(rate, chan); }) -                .add_coerced_subscriber([this](const double) { update_graph(); }); - -            // Legacy properties (for backward compat w/ multi_usrp) -            const uhd::fs_path dsp_base_path = _root_path / "legacy_api" / chan; -            // Legacy properties simply forward to the block args properties -            _tree->create<double>(dsp_base_path / "rate/value") -                .set_coercer([this, chan](const double value) { -                    return this->_tree -                        ->access<double>(this->get_arg_path("output_rate/value", chan)) -                        .set(value) -                        .get(); -                }) -                .set_publisher([this, chan]() { -                    return this->_tree -                        ->access<double>(this->get_arg_path("output_rate/value", chan)) -                        .get(); -                }); -            _tree->create<uhd::meta_range_t>(dsp_base_path / "rate/range") -                .set_publisher([this]() { return get_output_rates(); }); -            _tree->create<double>(dsp_base_path / "freq/value") -                .set_coercer([this, chan](const double value) { -                    return this->_tree -                        ->access<double>(this->get_arg_path("freq/value", chan)) -                        .set(value) -                        .get(); -                }) -                .set_publisher([this, chan]() { -                    return this->_tree -                        ->access<double>(this->get_arg_path("freq/value", chan)) -                        .get(); -                }); -            _tree->create<uhd::meta_range_t>(dsp_base_path / "freq/range") -                .set_publisher([this]() { return get_freq_range(); }); -            _tree->access<uhd::time_spec_t>("time/cmd") -                .add_coerced_subscriber([this, chan](const uhd::time_spec_t time_spec) { -                    this->set_command_time(time_spec, chan); -                }); -            if (_tree->exists("tick_rate")) { -                const double tick_rate = _tree->access<double>("tick_rate").get(); -                set_command_tick_rate(tick_rate, chan); -                _tree->access<double>("tick_rate") -                    .add_coerced_subscriber([this, chan](const double rate) { -                        this->set_command_tick_rate(rate, chan); -                    }); -            } - -            // Rate 1:1 by default -            sr_write("N", 1, chan); -            sr_write("M", 1, chan); -            sr_write("CONFIG", 1, chan); // Enable clear EOB -        } -    } // end ctor - -    virtual ~ddc_block_ctrl_impl() {} - -    double get_output_scale_factor(size_t port = ANY_PORT) -    { -        port = port == ANY_PORT ? 0 : port; -        if (not(_rx_streamer_active.count(port) and _rx_streamer_active.at(port))) { -            return SCALE_UNDEFINED; -        } -        return get_arg<double>("scalar_correction", port); -    } - -    double get_input_samp_rate(size_t port = ANY_PORT) -    { -        port = port == ANY_PORT ? 0 : port; -        if (not(_tx_streamer_active.count(port) and _tx_streamer_active.at(port))) { -            return RATE_UNDEFINED; -        } -        return get_arg<double>("input_rate", port); -    } - -    double get_output_samp_rate(size_t port = ANY_PORT) -    { -        if (port == ANY_PORT) { -            port = 0; -            for (size_t i = 0; i < get_input_ports().size(); i++) { -                if (_rx_streamer_active.count(i) and _rx_streamer_active.at(i)) { -                    port = i; -                    break; -                } -            } -        } - -        // Wait, what? If this seems out of place to you, you're right. However, -        // we need a function call that is called when the graph is complete, -        // but streaming is not yet set up. -        if (_tree->exists("tick_rate")) { -            const double tick_rate = _tree->access<double>("tick_rate").get(); -            set_command_tick_rate(tick_rate, port); -        } - -        if (not(_rx_streamer_active.count(port) and _rx_streamer_active.at(port))) { -            return RATE_UNDEFINED; -        } -        return get_arg<double>("output_rate", port); -    } - - -    void issue_stream_cmd(const uhd::stream_cmd_t& stream_cmd_, const size_t chan) -    { -        UHD_RFNOC_BLOCK_TRACE() << "ddc_block_ctrl_base::issue_stream_cmd()"; - -        if (list_upstream_nodes().count(chan) == 0) { -            UHD_LOGGER_INFO("RFNOC") << "No upstream blocks."; -            return; -        } - -        uhd::stream_cmd_t stream_cmd = stream_cmd_; -        if (stream_cmd.stream_mode == uhd::stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_DONE -            or stream_cmd.stream_mode -                   == uhd::stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_MORE) { -            const size_t decimation = -                static_cast<size_t>(get_arg<double>("input_rate", chan) -                                    / get_arg<double>("output_rate", chan)); -            stream_cmd.num_samps *= decimation; -        } - -        source_block_ctrl_base::issue_stream_cmd(stream_cmd, chan); -    } - -private: -    static constexpr size_t MAJOR_COMP           = 2; -    static constexpr size_t MINOR_COMP           = 0; -    static constexpr size_t RB_REG_COMPAT_NUM    = 0; -    static constexpr size_t RB_REG_NUM_HALFBANDS = 1; -    static constexpr size_t RB_REG_CIC_MAX_DECIM = 2; - -    const uint64_t _fpga_compat; -    const size_t _num_halfbands; -    const size_t _cic_max_decim; - -    //! Set the DDS frequency shift the signal to \p requested_freq -    double set_freq(const double requested_freq, const size_t chan) -    { -        const double input_rate = get_arg<double>("input_rate"); -        double actual_freq; -        int32_t freq_word; -        get_freq_and_freq_word(requested_freq, input_rate, actual_freq, freq_word); -        sr_write("DDS_FREQ", uint32_t(freq_word), chan); -        return actual_freq; -    } - -    //! Return a range of valid frequencies the DDS can tune to -    uhd::meta_range_t get_freq_range(void) -    { -        const double input_rate = get_arg<double>("input_rate"); -        return uhd::meta_range_t( -            -input_rate / 2, +input_rate / 2, input_rate / std::pow(2.0, 32)); -    } - -    uhd::meta_range_t get_output_rates(void) -    { -        uhd::meta_range_t range; -        const double input_rate = get_arg<double>("input_rate"); -        for (int hb = _num_halfbands; hb >= 0; hb--) { -            const size_t decim_offset = _cic_max_decim << (hb - 1); -            for (size_t decim = _cic_max_decim; decim > 0; decim--) { -                const size_t hb_cic_decim = decim * (1 << hb); -                if (hb == 0 || hb_cic_decim > decim_offset) { -                    range.push_back(uhd::range_t(input_rate / hb_cic_decim)); -                } -            } -        } -        return range; -    } - -    double set_output_rate(const double requested_rate, const size_t chan) -    { -        const double input_rate = get_arg<double>("input_rate"); -        const double tick_rate  = _tree->exists("tick_rate") -                                     ? _tree->access<double>("tick_rate").get() -                                     : input_rate; -        const size_t m          = size_t(tick_rate / input_rate); -        const size_t decim_rate = boost::math::iround( -            input_rate / this->get_output_rates().clip(requested_rate, true)); -        size_t decim = decim_rate; -        // The FPGA knows which halfbands to enable for any given value of hb_enable. -        uint32_t hb_enable = 0; -        while ((decim % 2 == 0) and hb_enable < _num_halfbands) { -            hb_enable++; -            decim /= 2; -        } -        UHD_ASSERT_THROW(hb_enable <= _num_halfbands); -        UHD_ASSERT_THROW(decim > 0 and decim <= _cic_max_decim); -        // What we can't cover with halfbands, we do with the CIC -        sr_write("DECIM_WORD", (hb_enable << 8) | (decim & 0xff), chan); - -        // Rate change = M/N -        sr_write("N", m * std::pow(2.0, double(hb_enable)) * (decim & 0xff), chan); -        const auto noc_id = _tree->access<uint64_t>(_root_path / "noc_id").get(); -        // FIXME this should be a rb reg in the FPGA, not based on a hard-coded -        // Noc-ID -        if (noc_id == 0xDDC5E15CA7000000) { -            UHD_LOG_DEBUG("DDC", "EISCAT DDC! Assuming real inputs."); -            sr_write("M", 2, chan); -        } else { -            sr_write("M", m, chan); -        } - -        if (decim > 1 and hb_enable == 0) { -            UHD_LOGGER_WARNING("RFNOC") -                << boost::format( -                       "The requested decimation is odd; the user should expect passband " -                       "CIC rolloff.\n" -                       "Select an even decimation to ensure that a halfband filter is " -                       "enabled.\n" -                       "Decimations factorable by 4 will enable 2 halfbands, those " -                       "factorable by 8 will enable 3 halfbands.\n" -                       "decimation = dsp_rate/samp_rate -> %d = (%f MHz)/(%f MHz)\n") -                       % decim_rate % (input_rate / 1e6) % (requested_rate / 1e6); -        } - -        // Calculate algorithmic gain of CIC for a given decimation. -        // For Ettus CIC R=decim, M=1, N=4. Gain = (R * M) ^ N -        const double rate_pow = std::pow(double(decim & 0xff), 4); -        // Calculate compensation gain values for algorithmic gain of DDS and CIC taking -        // into account gain compensation blocks already hardcoded in place in DDC (that -        // provide simple 1/2^n gain compensation). -        static const double DDS_GAIN = 2.0; -        // -        // The polar rotation of [I,Q] = [1,1] by Pi/8 also yields max magnitude of -        // SQRT(2) (~1.4142) however input to the DDS thats outside the unit circle can -        // only be sourced from a saturated RF frontend. To provide additional dynamic -        // range head room accordingly using scale factor applied at egress from DDC would -        // cost us small signal performance, thus we do no provide compensation gain for a -        // saturated front end and allow the signal to clip in the H/W as needed. If we -        // wished to avoid the signal clipping in these circumstances then adjust code to -        // read: -        const double scaling_adjustment = -            std::pow(2, uhd::math::ceil_log2(rate_pow)) / (DDS_GAIN * rate_pow); -        update_scalar(scaling_adjustment, chan); -        return input_rate / decim_rate; -    } - -    //! Set frequency and decimation again -    void set_input_rate(const double /* rate */, const size_t chan) -    { -        const double desired_freq = -            _tree->access<double>(get_arg_path("freq", chan) / "value").get_desired(); -        set_arg<double>("freq", desired_freq, chan); -        const double desired_output_rate = -            _tree->access<double>(get_arg_path("output_rate", chan) / "value") -                .get_desired(); -        set_arg<double>("output_rate", desired_output_rate, chan); -    } - -    // Calculate compensation gain values for algorithmic gain of DDS and CIC taking into -    // account gain compensation blocks already hardcoded in place in DDC (that provide -    // simple 1/2^n gain compensation). Further more factor in OTW format which adds -    // further gain factor to weight output samples correctly. -    void update_scalar(const double scalar, const size_t chan) -    { -        const double target_scalar  = (1 << 15) * scalar; -        const int32_t actual_scalar = boost::math::iround(target_scalar); -        // Calculate the error introduced by using integer representation for the scalar, -        // can be corrected in host later. -        const double scalar_correction = -            target_scalar / actual_scalar -            / double(1 << 15) // Rounding error, normalized to 1.0 -            * get_arg<double>("fullscale"); // Scaling requested by host -        set_arg<double>("scalar_correction", scalar_correction, chan); -        // Write DDC with scaling correction for CIC and DDS that maximizes dynamic range -        // in 32/16/12/8bits. -        sr_write("SCALE_IQ", actual_scalar, chan); -    } - -    //! Get cached value of FPGA compat number -    uint64_t get_fpga_compat() const -    { -        return _fpga_compat; -    } - -    //! Get cached value of _num_halfbands -    size_t get_num_halfbands() const -    { -        return _num_halfbands; -    } - -    //! Get cached value of _cic_max_decim readback -    size_t get_cic_max_decim() const -    { -        return _cic_max_decim; -    } -}; - -UHD_RFNOC_BLOCK_REGISTER(ddc_block_ctrl, "DDC"); diff --git a/host/lib/rfnoc/dma_fifo_block_ctrl_impl.cpp b/host/lib/rfnoc/dma_fifo_block_ctrl_impl.cpp deleted file mode 100644 index a80e2ef53..000000000 --- a/host/lib/rfnoc/dma_fifo_block_ctrl_impl.cpp +++ /dev/null @@ -1,106 +0,0 @@ -// -// Copyright 2016 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#include <uhd/convert.hpp> -#include <uhd/rfnoc/dma_fifo_block_ctrl.hpp> -#include <uhd/types/wb_iface.hpp> -#include <uhd/utils/log.hpp> -#include <uhdlib/rfnoc/wb_iface_adapter.hpp> -#include <uhdlib/usrp/cores/dma_fifo_core_3000.hpp> -#include <boost/format.hpp> -#include <boost/make_shared.hpp> -#include <boost/thread/mutex.hpp> - -using namespace uhd; -using namespace uhd::rfnoc; - -class dma_fifo_block_ctrl_impl : public dma_fifo_block_ctrl -{ -public: -    static const uint32_t DEFAULT_SIZE = 32 * 1024 * 1024; - -    UHD_RFNOC_BLOCK_CONSTRUCTOR(dma_fifo_block_ctrl) -    { -        _perifs.resize(get_input_ports().size()); -        for (size_t i = 0; i < _perifs.size(); i++) { -            _perifs[i].ctrl                    = this->get_ctrl_iface(i); -            static const uint32_t USER_SR_BASE = 128 * 4; -            static const uint32_t USER_RB_BASE = 0; // Don't care -            _perifs[i].base_addr               = DEFAULT_SIZE * i; -            _perifs[i].depth                   = DEFAULT_SIZE; -            _perifs[i].core = -                dma_fifo_core_3000::make(_perifs[i].ctrl, USER_SR_BASE, USER_RB_BASE); -            _perifs[i].core->resize(_perifs[i].base_addr, _perifs[i].depth); -            UHD_LOG_DEBUG(unique_id(), "Running BIST for FIFO " << i); -            if (_perifs[i].core->ext_bist_supported()) { -                uint32_t bisterr = _perifs[i].core->run_bist(); -                if (bisterr != 0) { -                    throw uhd::runtime_error( -                        str(boost::format("BIST failed! (code: %d)\n") % bisterr)); -                } else { -                    double throughput = _perifs[i].core->get_bist_throughput(); -                    UHD_LOGGER_INFO(unique_id()) -                        << (boost::format("BIST passed (Throughput: %.0f MB/s)") -                               % (throughput / 1e6)); -                } -            } else { -                if (_perifs[i].core->run_bist() == 0) { -                    UHD_LOGGER_INFO(unique_id()) << "BIST passed"; -                } else { -                    UHD_LOGGER_ERROR(unique_id()) << "BIST failed!"; -                    throw uhd::runtime_error("BIST failed!"); -                } -            } -            _tree->access<int>(get_arg_path("base_addr/value", i)) -                .add_coerced_subscriber(boost::bind(&dma_fifo_block_ctrl_impl::resize, -                    this, -                    _1, -                    boost::ref(_perifs[i].depth), -                    i)) -                .set(_perifs[i].base_addr); -            _tree->access<int>(get_arg_path("depth/value", i)) -                .add_coerced_subscriber(boost::bind(&dma_fifo_block_ctrl_impl::resize, -                    this, -                    boost::ref(_perifs[i].base_addr), -                    _1, -                    i)) -                .set(_perifs[i].depth); -        } -    } - -    void resize(const uint32_t base_addr, const uint32_t depth, const size_t chan) -    { -        boost::lock_guard<boost::mutex> lock(_config_mutex); -        _perifs[chan].base_addr = base_addr; -        _perifs[chan].depth     = depth; -        _perifs[chan].core->resize(base_addr, depth); -    } - -    uint32_t get_base_addr(const size_t chan) const -    { -        return _perifs[chan].base_addr; -    } - -    uint32_t get_depth(const size_t chan) const -    { -        return _perifs[chan].depth; -    } - -private: -    struct fifo_perifs_t -    { -        wb_iface::sptr ctrl; -        dma_fifo_core_3000::sptr core; -        uint32_t base_addr; -        uint32_t depth; -    }; -    std::vector<fifo_perifs_t> _perifs; - -    boost::mutex _config_mutex; -}; - -UHD_RFNOC_BLOCK_REGISTER(dma_fifo_block_ctrl, "DmaFIFO"); diff --git a/host/lib/rfnoc/duc_block_ctrl_impl.cpp b/host/lib/rfnoc/duc_block_ctrl_impl.cpp deleted file mode 100644 index 18f6c9fb5..000000000 --- a/host/lib/rfnoc/duc_block_ctrl_impl.cpp +++ /dev/null @@ -1,313 +0,0 @@ -// -// Copyright 2016-2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#include <uhd/convert.hpp> -#include <uhd/rfnoc/duc_block_ctrl.hpp> -#include <uhd/types/ranges.hpp> -#include <uhd/utils/log.hpp> -#include <uhdlib/usrp/cores/dsp_core_utils.hpp> -#include <uhdlib/utils/compat_check.hpp> -#include <uhdlib/utils/math.hpp> -#include <uhdlib/utils/narrow.hpp> -#include <boost/math/special_functions/round.hpp> -#include <cmath> - -using namespace uhd::rfnoc; - -class duc_block_ctrl_impl : public duc_block_ctrl -{ -public: -    UHD_RFNOC_BLOCK_CONSTRUCTOR(duc_block_ctrl) -    , _fpga_compat(user_reg_read64(RB_REG_COMPAT_NUM)), -        _num_halfbands(uhd::narrow_cast<size_t>(user_reg_read64(RB_REG_NUM_HALFBANDS))), -        _cic_max_interp(uhd::narrow_cast<size_t>(user_reg_read64(RB_REG_CIC_MAX_INTERP))) -    { -        UHD_LOG_DEBUG(unique_id(), -            "Loading DUC with " << get_num_halfbands() -                                << " halfbands and " -                                   "max CIC interpolation " -                                << get_cic_max_interp()); -        uhd::assert_fpga_compat(MAJOR_COMP, -            MINOR_COMP, -            _fpga_compat, -            "DUC", -            "DUC", -            false /* Let it slide if minors mismatch */ -        ); - -        // Argument/prop tree hooks -        for (size_t chan = 0; chan < get_input_ports().size(); chan++) { -            const double default_freq = get_arg<double>("freq", chan); -            _tree->access<double>(get_arg_path("freq/value", chan)) -                .set_coercer([this, chan](const double value) { -                    return this->set_freq(value, chan); -                }) -                .set(default_freq); -            ; - -            const double default_input_rate = get_arg<double>("input_rate", chan); -            _tree->access<double>(get_arg_path("input_rate/value", chan)) -                .set_coercer([this, chan](const double value) { -                    return this->set_input_rate(value, chan); -                }) -                .set(default_input_rate) -                .add_coerced_subscriber([this](const double) { update_graph(); }); -            _tree->access<double>(get_arg_path("output_rate/value", chan)) -                .add_coerced_subscriber([this, chan](const double rate) { -                    this->set_output_rate(rate, chan); -                }) -                .add_coerced_subscriber([this](const double) { update_graph(); }); - -            // Legacy properties (for backward compat w/ multi_usrp) -            const uhd::fs_path dsp_base_path = _root_path / "legacy_api" / chan; -            // Legacy properties -            _tree->create<double>(dsp_base_path / "rate/value") -                .set_coercer([this, chan](const double value) { -                    return this->_tree -                        ->access<double>(this->get_arg_path("input_rate/value", chan)) -                        .set(value) -                        .get(); -                }) -                .set_publisher([this, chan]() { -                    return this->_tree -                        ->access<double>(this->get_arg_path("input_rate/value", chan)) -                        .get(); -                }); -            _tree->create<uhd::meta_range_t>(dsp_base_path / "rate/range") -                .set_publisher([this]() { return get_input_rates(); }); -            _tree->create<double>(dsp_base_path / "freq/value") -                .set_coercer([this, chan](const double value) { -                    return this->_tree -                        ->access<double>(this->get_arg_path("freq/value", chan)) -                        .set(value) -                        .get(); -                }) -                .set_publisher([this, chan]() { -                    return this->_tree -                        ->access<double>(this->get_arg_path("freq/value", chan)) -                        .get(); -                }); -            _tree->create<uhd::meta_range_t>(dsp_base_path / "freq/range") -                .set_publisher([this]() { return get_freq_range(); }); -            _tree->access<uhd::time_spec_t>("time/cmd") -                .add_coerced_subscriber([this, chan](const uhd::time_spec_t time_spec) { -                    this->set_command_time(time_spec, chan); -                }); -            if (_tree->exists("tick_rate")) { -                const double tick_rate = _tree->access<double>("tick_rate").get(); -                set_command_tick_rate(tick_rate, chan); -                _tree->access<double>("tick_rate") -                    .add_coerced_subscriber([this, chan](const double rate) { -                        this->set_command_tick_rate(rate, chan); -                    }); -            } - -            // Rate 1:1 by default -            sr_write("N", 1, chan); -            sr_write("M", 1, chan); -            sr_write("CONFIG", 1, chan); // Enable clear EOB -        } -    } // end ctor - -    virtual ~duc_block_ctrl_impl() {} - -    double get_input_scale_factor(size_t port = ANY_PORT) -    { -        port = (port == ANY_PORT) ? 0 : port; -        if (not(_tx_streamer_active.count(port) and _tx_streamer_active.at(port))) { -            return SCALE_UNDEFINED; -        } -        return get_arg<double>("scalar_correction", port); -    } - -    double get_input_samp_rate(size_t port = ANY_PORT) -    { -        port = (port == ANY_PORT) ? 0 : port; - -        // Wait, what? If this seems out of place to you, you're right. However, -        // we need a function call that is called when the graph is complete, -        // but streaming is not yet set up. -        if (_tree->exists("tick_rate")) { -            const double tick_rate = _tree->access<double>("tick_rate").get(); -            set_command_tick_rate(tick_rate, port); -        } - -        if (not(_tx_streamer_active.count(port) and _tx_streamer_active.at(port))) { -            return RATE_UNDEFINED; -        } -        return get_arg<double>("input_rate", port); -    } - -    double get_output_samp_rate(size_t port = ANY_PORT) -    { -        port = (port == ANY_PORT) ? 0 : port; -        if (not(_tx_streamer_active.count(port) and _tx_streamer_active.at(port))) { -            return RATE_UNDEFINED; -        } -        return get_arg<double>("output_rate", port == ANY_PORT ? 0 : port); -    } - -    void issue_stream_cmd(const uhd::stream_cmd_t& stream_cmd_, const size_t chan) -    { -        UHD_RFNOC_BLOCK_TRACE() << "duc_block_ctrl_base::issue_stream_cmd()"; - -        uhd::stream_cmd_t stream_cmd = stream_cmd_; -        if (stream_cmd.stream_mode == uhd::stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_DONE -            or stream_cmd.stream_mode -                   == uhd::stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_MORE) { -            size_t interpolation = get_arg<double>("output_rate", chan) -                                   / get_arg<double>("input_rate", chan); -            stream_cmd.num_samps *= interpolation; -        } - -        source_block_ctrl_base::issue_stream_cmd(stream_cmd, chan); -    } - -private: -    static constexpr size_t MAJOR_COMP            = 2; -    static constexpr size_t MINOR_COMP            = 0; -    static constexpr size_t RB_REG_COMPAT_NUM     = 0; -    static constexpr size_t RB_REG_NUM_HALFBANDS  = 1; -    static constexpr size_t RB_REG_CIC_MAX_INTERP = 2; - -    const uint64_t _fpga_compat; -    const size_t _num_halfbands; -    const size_t _cic_max_interp; - -    //! Set the DDS frequency shift the signal to \p requested_freq -    double set_freq(const double requested_freq, const size_t chan) -    { -        const double output_rate = get_arg<double>("output_rate"); -        double actual_freq; -        int32_t freq_word; -        get_freq_and_freq_word(requested_freq, output_rate, actual_freq, freq_word); -        sr_write("DDS_FREQ", uint32_t(freq_word), chan); -        return actual_freq; -    } - -    //! Return a range of valid frequencies the DDS can tune to -    uhd::meta_range_t get_freq_range(void) -    { -        const double output_rate = get_arg<double>("output_rate"); -        return uhd::meta_range_t( -            -output_rate / 2, +output_rate / 2, output_rate / std::pow(2.0, 32)); -    } - -    uhd::meta_range_t get_input_rates(void) -    { -        uhd::meta_range_t range; -        const double output_rate = get_arg<double>("output_rate"); -        for (int hb = _num_halfbands; hb >= 0; hb--) { -            const size_t interp_offset = _cic_max_interp << (hb - 1); -            for (size_t interp = _cic_max_interp; interp > 0; interp--) { -                const size_t hb_cic_interp = interp * (1 << hb); -                if (hb == 0 || hb_cic_interp > interp_offset) { -                    range.push_back(uhd::range_t(output_rate / hb_cic_interp)); -                } -            } -        } -        return range; -    } - -    double set_input_rate(const double requested_rate, const size_t chan) -    { -        const double output_rate = get_arg<double>("output_rate", chan); -        const double tick_rate   = _tree->exists("tick_rate") -                                     ? _tree->access<double>("tick_rate").get() -                                     : output_rate; -        const size_t n           = size_t(tick_rate / output_rate); -        const size_t interp_rate = boost::math::iround( -            output_rate / get_input_rates().clip(requested_rate, true)); -        size_t interp = interp_rate; - -        uint32_t hb_enable = 0; -        while ((interp % 2 == 0) and hb_enable < _num_halfbands) { -            hb_enable++; -            interp /= 2; -        } -        UHD_ASSERT_THROW(hb_enable <= _num_halfbands); -        UHD_ASSERT_THROW(interp > 0 and interp <= _cic_max_interp); -        // What we can't cover with halfbands, we do with the CIC -        sr_write("INTERP_WORD", (hb_enable << 8) | (interp & 0xff), chan); - -        // Rate change = M/N -        sr_write("N", n, chan); -        sr_write("M", n * std::pow(2.0, double(hb_enable)) * (interp & 0xff), chan); - -        if (interp > 1 and hb_enable == 0) { -            UHD_LOGGER_WARNING("RFNOC") -                << boost::format( -                       "The requested interpolation is odd; the user should expect " -                       "passband CIC rolloff.\n" -                       "Select an even interpolation to ensure that a halfband filter is " -                       "enabled.\n" -                       "interpolation = dsp_rate/samp_rate -> %d = (%f MHz)/(%f MHz)\n") -                       % interp_rate % (output_rate / 1e6) % (requested_rate / 1e6); -        } - -        // Calculate algorithmic gain of CIC for a given interpolation -        // For Ettus CIC R=interp, M=1, N=4. Gain = (R * M) ^ (N - 1) -        const int CIC_N            = 4; -        const double rate_pow      = std::pow(double(interp & 0xff), CIC_N - 1); -        const double CONSTANT_GAIN = 1.0; - -        const double scaling_adjustment = -            std::pow(2, uhd::math::ceil_log2(rate_pow)) / (CONSTANT_GAIN * rate_pow); -        update_scalar(scaling_adjustment, chan); -        return output_rate / interp_rate; -    } - -    //! Set frequency and interpolation again -    void set_output_rate(const double /* rate */, const size_t chan) -    { -        const double desired_freq = -            _tree->access<double>(get_arg_path("freq", chan) / "value").get_desired(); -        set_arg<double>("freq", desired_freq, chan); -        const double desired_input_rate = -            _tree->access<double>(get_arg_path("input_rate", chan) / "value") -                .get_desired(); -        set_arg<double>("input_rate", desired_input_rate, chan); -    } - -    // Calculate compensation gain values for algorithmic gain of DDS and CIC taking into -    // account gain compensation blocks already hardcoded in place in DUC (that provide -    // simple 1/2^n gain compensation). Further more factor in OTW format which adds -    // further gain factor to weight output samples correctly. -    void update_scalar(const double scalar, const size_t chan) -    { -        const double target_scalar  = (1 << 15) * scalar; -        const int32_t actual_scalar = boost::math::iround(target_scalar); -        // Calculate the error introduced by using integer representation for the scalar -        const double scalar_correction = -            actual_scalar / target_scalar -            * (double(1 << 15) - 1.0) // Rounding error, normalized to 1.0 -            * get_arg<double>("fullscale"); // Scaling requested by host -        set_arg<double>("scalar_correction", scalar_correction, chan); -        // Write DUC with scaling correction for CIC and CORDIC that maximizes dynamic -        // range in 32/16/12/8bits. -        sr_write("SCALE_IQ", actual_scalar, chan); -    } - -    //! Get cached value of FPGA compat number -    uint64_t get_fpga_compat() const -    { -        return _fpga_compat; -    } - -    // Get cached value of _num_halfbands -    size_t get_num_halfbands() const -    { -        return _num_halfbands; -    } - -    // Get cached value of _cic_max_decim readback -    size_t get_cic_max_interp() const -    { -        return _cic_max_interp; -    } -}; - -UHD_RFNOC_BLOCK_REGISTER(duc_block_ctrl, "DUC"); diff --git a/host/lib/rfnoc/fir_block_ctrl_impl.cpp b/host/lib/rfnoc/fir_block_ctrl_impl.cpp deleted file mode 100644 index a4106111e..000000000 --- a/host/lib/rfnoc/fir_block_ctrl_impl.cpp +++ /dev/null @@ -1,78 +0,0 @@ -// -// Copyright 2014-2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#include <uhd/convert.hpp> -#include <uhd/rfnoc/fir_block_ctrl.hpp> -#include <uhd/utils/log.hpp> - -using namespace uhd::rfnoc; - -class fir_block_ctrl_impl : public fir_block_ctrl -{ -public: -    static const uint32_t RB_NUM_TAPS     = 0; -    static const uint32_t SR_RELOAD       = 128; -    static const uint32_t SR_RELOAD_TLAST = 129; -    static const uint32_t SR_CONFIG       = 130; - -    UHD_RFNOC_BLOCK_CONSTRUCTOR(fir_block_ctrl), -        _item_type("sc16") // We only support sc16 in this block -    { -        _n_taps = uint32_t(user_reg_read64(RB_NUM_TAPS)); -        UHD_LOGGER_DEBUG(unique_id()) -            << "fir_block::fir_block() n_taps ==" << _n_taps << std::endl; -        UHD_ASSERT_THROW(_n_taps); - -        // Default to Dirac impulse -        std::vector<int> default_taps(1, 20000); -        set_taps(default_taps); -    } - -    void set_taps(const std::vector<int>& taps_) -    { -        UHD_LOGGER_TRACE(unique_id()) << "fir_block::set_taps()" << std::endl; -        if (taps_.size() > _n_taps) { -            throw uhd::value_error( -                str(boost::format("FIR block: Too many filter coefficients! Provided %d, " -                                  "FIR allows %d.\n") -                    % taps_.size() % _n_taps)); -        } -        for (size_t i = 0; i < taps_.size(); i++) { -            if (taps_[i] > 32767 || taps_[i] < -32768) { -                throw uhd::value_error( -                    str(boost::format("FIR block: Coefficient %d out of range! Value %d, " -                                      "Allowed range [-32768,32767].\n") -                        % i % taps_[i])); -            } -        } -        std::vector<int> taps = taps_; -        if (taps.size() < _n_taps) { -            taps.resize(_n_taps, 0); -        } - -        // Write taps via the reload bus -        for (size_t i = 0; i < taps.size() - 1; i++) { -            sr_write(SR_RELOAD, uint32_t(taps[i])); -        } -        // Assert tlast when sending the spinal tap (haha, it's actually the final tap). -        sr_write(SR_RELOAD_TLAST, uint32_t(taps.back())); -        // Send the configuration word to replace the existing coefficients with the new -        // ones. Note: This configuration bus does not require tlast -        sr_write(SR_CONFIG, 0); -    } - -    //! Returns the number of filter taps in this block. -    size_t get_n_taps() const -    { -        return _n_taps; -    } - -private: -    const std::string _item_type; -    size_t _n_taps; -}; - -UHD_RFNOC_BLOCK_REGISTER(fir_block_ctrl, "FIR"); diff --git a/host/lib/rfnoc/graph_impl.cpp b/host/lib/rfnoc/graph_impl.cpp deleted file mode 100644 index 4c04a0c1e..000000000 --- a/host/lib/rfnoc/graph_impl.cpp +++ /dev/null @@ -1,219 +0,0 @@ -// -// Copyright 2016 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#include <uhd/rfnoc/sink_block_ctrl_base.hpp> -#include <uhd/rfnoc/source_block_ctrl_base.hpp> -#include <uhd/utils/log.hpp> -#include <uhdlib/rfnoc/graph_impl.hpp> - -using namespace uhd::rfnoc; - -/**************************************************************************** - * Structors - ***************************************************************************/ -graph_impl::graph_impl(const std::string& name, -    boost::weak_ptr<uhd::device3> device_ptr, -    async_msg_handler::sptr msg_handler) -    : _name(name), _device_ptr(device_ptr), _msg_handler(msg_handler) -{ -    UHD_LOG_TRACE("RFNOC", "Instantiating RFNoC graph " << _name); -} - -/**************************************************************************** - * Connection API - ***************************************************************************/ -void graph_impl::connect(const block_id_t& src_block, -    size_t src_block_port, -    const block_id_t& dst_block, -    size_t dst_block_port, -    const size_t pkt_size_) -{ -    device3::sptr device_ptr = _device_ptr.lock(); -    if (not device_ptr) { -        throw uhd::runtime_error("Invalid device"); -    } - -    uhd::rfnoc::source_block_ctrl_base::sptr src = -        device_ptr->get_block_ctrl<rfnoc::source_block_ctrl_base>(src_block); -    uhd::rfnoc::sink_block_ctrl_base::sptr dst = -        device_ptr->get_block_ctrl<rfnoc::sink_block_ctrl_base>(dst_block); -    UHD_LOGGER_TRACE("RFNOC") << "[" << _name << "] Attempting to connect " << src_block -                              << ":" << src_block_port << " --> " << dst_block << ":" -                              << dst_block_port; - -    /******************************************************************** -     * 1. Draw the edges (logically connect the nodes) -     ********************************************************************/ -    size_t actual_src_block_port = src->connect_downstream( -        boost::dynamic_pointer_cast<uhd::rfnoc::node_ctrl_base>(dst), src_block_port); -    if (src_block_port == uhd::rfnoc::ANY_PORT) { -        src_block_port = actual_src_block_port; -    } else if (src_block_port != actual_src_block_port) { -        throw uhd::runtime_error( -            str(boost::format("Can't connect to port %d on block %s.") % src_block_port -                % src->unique_id())); -    } -    size_t actual_dst_block_port = dst->connect_upstream( -        boost::dynamic_pointer_cast<uhd::rfnoc::node_ctrl_base>(src), dst_block_port); -    if (dst_block_port == uhd::rfnoc::ANY_PORT) { -        dst_block_port = actual_dst_block_port; -    } else if (dst_block_port != actual_dst_block_port) { -        throw uhd::runtime_error( -            str(boost::format("Can't connect to port %d on block %s.") % dst_block_port -                % dst->unique_id())); -    } -    src->set_downstream_port(actual_src_block_port, actual_dst_block_port); -    dst->set_upstream_port(actual_dst_block_port, actual_src_block_port); -    // At this point, ports are locked and no one else can simply connect -    // into them. -    UHD_LOGGER_TRACE("RFNOC") << "[" << _name << "] Connecting " << src_block << ":" -                              << actual_src_block_port << " --> " << dst_block << ":" -                              << actual_dst_block_port; - -    /******************************************************************** -     * 2. Check IO signatures match -     ********************************************************************/ -    if (not rfnoc::stream_sig_t::is_compatible( -            src->get_output_signature(actual_src_block_port), -            dst->get_input_signature(actual_dst_block_port))) { -        throw uhd::runtime_error( -            str(boost::format("Can't connect block %s to %s: IO signature mismatch\n(%s " -                              "is incompatible with %s).") -                % src->get_block_id().get() % dst->get_block_id().get() -                % src->get_output_signature(actual_src_block_port) -                % dst->get_input_signature(actual_dst_block_port))); -    } -    UHD_LOG_TRACE("RFNOC", "IO signatures match."); - -    /******************************************************************** -     * 3. Configure the source block's destination -     ********************************************************************/ -    // Calculate SID -    sid_t sid = dst->get_address(dst_block_port); -    sid.set_src(src->get_address(src_block_port)); - -    // Set SID on source block -    src->set_destination(sid.get(), src_block_port); - -    /******************************************************************** -     * 4. Configure flow control -     ********************************************************************/ -    size_t pkt_size = (pkt_size_ != 0) -                          ? pkt_size_ -                          : src->get_output_signature(src_block_port).packet_size; -    if (pkt_size == 0) { // Unspecified packet rate. Assume max packet size. -        UHD_LOGGER_WARNING("RFNOC") -            << "Assuming max packet size for " << src->get_block_id(); -        pkt_size = uhd::rfnoc::MAX_PACKET_SIZE; -    } -    // FC window (in bytes) depends on FIFO size. -    size_t buf_size_bytes = dst->get_fifo_size(dst_block_port); -    if (buf_size_bytes < pkt_size) { -        throw uhd::runtime_error( -            str(boost::format("Input FIFO for block %s is too small (%d kiB) for packets " -                              "of size %d kiB\n" -                              "coming from block %s.") -                % dst->get_block_id().get() % (dst->get_fifo_size(dst_block_port) / 1024) -                % (pkt_size / 1024) % src->get_block_id().get())); -    } -    const bool same_xbar = sid.get_src_addr() == sid.get_dst_addr(); -    src->configure_flow_control_out(true, /* enable output */ -        false, // Keep packets from jamming the crossbar -        buf_size_bytes, -        0, /* no packet limit. We need to revisit this at some point. */ -        src_block_port); -    // On the same crossbar, use lots of FC packets -    // Over the network, use less or we'd flood the transport -    const size_t bytes_per_response = -        same_xbar ? buf_size_bytes / uhd::rfnoc::DEFAULT_FC_XBAR_RESPONSE_FREQ -                  : buf_size_bytes / uhd::rfnoc::DEFAULT_FC_TX_RESPONSE_FREQ; -    UHD_ASSERT_THROW(bytes_per_response != 0); -    dst->configure_flow_control_in(bytes_per_response, dst_block_port); - -    /******************************************************************** -     * 5. Configure error policy -     ********************************************************************/ -    dst->set_error_policy("next_burst"); - -    /******************************************************************** -     * 6. Set async message handling -     ********************************************************************/ -    src->sr_write( -        uhd::rfnoc::SR_RESP_OUT_DST_SID, _msg_handler->get_local_addr(), src_block_port); -    dst->sr_write( -        uhd::rfnoc::SR_RESP_IN_DST_SID, _msg_handler->get_local_addr(), dst_block_port); -} - -void graph_impl::connect(const block_id_t& src_block, const block_id_t& dst_block) -{ -    connect(src_block, ANY_PORT, dst_block, ANY_PORT); -} - -void graph_impl::connect_src(const block_id_t& src_block, -    const size_t src_block_port, -    const uhd::sid_t dst_sid, -    const size_t buf_size_dst_bytes, -    const size_t pkt_size_) -{ -    device3::sptr device_ptr = _device_ptr.lock(); -    if (not device_ptr) { -        throw uhd::runtime_error("Invalid device"); -    } - -    UHD_LOGGER_DEBUG("RFNOC") << "[" << _name << "] Connecting " << src_block << ":" -                              << src_block_port << " --> " << dst_sid.to_pp_string_hex(); - -    uhd::rfnoc::source_block_ctrl_base::sptr src = -        device_ptr->get_block_ctrl<rfnoc::source_block_ctrl_base>(src_block); - -    src->set_destination(dst_sid.get(), src_block_port); - -    size_t pkt_size = (pkt_size_ != 0) -                          ? pkt_size_ -                          : src->get_output_signature(src_block_port).packet_size; -    if (pkt_size == 0) { // Unspecified packet rate. Assume max packet size. -        UHD_LOGGER_WARNING("RFNOC") -            << "Assuming max packet size for " << src->get_block_id(); -        pkt_size = uhd::rfnoc::MAX_PACKET_SIZE; -    } -    size_t buf_size_pkts = buf_size_dst_bytes / pkt_size; -    if (buf_size_pkts == 0) { -        throw uhd::runtime_error( -            str(boost::format("Input FIFO for unknown destination is too small " -                              "(%d kiB) for packets of size %d kiB\n coming from " -                              "block %s.") -                % (buf_size_dst_bytes / 1024) % (pkt_size / 1024) -                % src->get_block_id().get())); -    } - -    src->configure_flow_control_out(true, /* enable output */ -        (dst_sid.get_src_addr() == dst_sid.get_dst_addr()), -        buf_size_dst_bytes, -        0, /* no packet limit. We need to revisit this at some point. */ -        src_block_port); -} - -void graph_impl::connect_sink( -    const block_id_t& sink_block, const size_t dst_block_port, const size_t bytes_per_ack) -{ -    device3::sptr device_ptr = _device_ptr.lock(); -    if (not device_ptr) { -        throw uhd::runtime_error("Invalid device"); -    } - -    UHD_LOGGER_DEBUG("RFNOC") << "[" << _name << "] Connecting unknown source to" -                              << sink_block << ":" << dst_block_port; - -    uhd::rfnoc::sink_block_ctrl_base::sptr dst = -        device_ptr->get_block_ctrl<rfnoc::sink_block_ctrl_base>(sink_block); -    dst->configure_flow_control_in(bytes_per_ack, dst_block_port); - -    /******************************************************************** -     * 5. Configure error policy -     ********************************************************************/ -    dst->set_error_policy("next_burst"); -} 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; -} diff --git a/host/lib/rfnoc/nocscript/CMakeLists.txt b/host/lib/rfnoc/nocscript/CMakeLists.txt deleted file mode 100644 index 2eeb984bf..000000000 --- a/host/lib/rfnoc/nocscript/CMakeLists.txt +++ /dev/null @@ -1,27 +0,0 @@ -# -# Copyright 2015 Ettus Research LLC -# Copyright 2018 Ettus Research, a National Instruments Company -# -# SPDX-License-Identifier: GPL-3.0-or-later -# - -include_directories(${CMAKE_CURRENT_SOURCE_DIR}) -include_directories(${CMAKE_CURRENT_BINARY_DIR}) -LIBUHD_PYTHON_GEN_SOURCE( -    ${CMAKE_CURRENT_SOURCE_DIR}/gen_basic_funcs.py -    ${CMAKE_CURRENT_BINARY_DIR}/basic_functions.hpp -) - -if(ENABLE_MANUAL) -    LIBUHD_PYTHON_GEN_SOURCE( -        ${CMAKE_CURRENT_SOURCE_DIR}/gen_basic_funcs.py -        ${CMAKE_BINARY_DIR}/docs/nocscript_functions.dox -    ) -endif(ENABLE_MANUAL) - -LIBUHD_APPEND_SOURCES( -    ${CMAKE_CURRENT_SOURCE_DIR}/expression.cpp -    ${CMAKE_CURRENT_SOURCE_DIR}/function_table.cpp -    ${CMAKE_CURRENT_SOURCE_DIR}/parser.cpp -    ${CMAKE_CURRENT_SOURCE_DIR}/block_iface.cpp -) diff --git a/host/lib/rfnoc/nocscript/block_iface.cpp b/host/lib/rfnoc/nocscript/block_iface.cpp deleted file mode 100644 index f029c3324..000000000 --- a/host/lib/rfnoc/nocscript/block_iface.cpp +++ /dev/null @@ -1,236 +0,0 @@ -// -// Copyright 2015 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#include "block_iface.hpp" -#include "function_table.hpp" -#include <uhd/exception.hpp> -#include <uhd/utils/log.hpp> -#include <boost/assign.hpp> -#include <boost/bind.hpp> -#include <boost/format.hpp> - -#define UHD_NOCSCRIPT_LOG() UHD_LOGGER_TRACE("RFNOC") - -using namespace uhd::rfnoc; -using namespace uhd::rfnoc::nocscript; - -block_iface::block_iface(block_ctrl_base* block_ptr) : _block_ptr(block_ptr) -{ -    function_table::sptr ft = function_table::make(); - -    // Add the SR_WRITE() function -    expression_function::argtype_list_type sr_write_args_wo_port = -        boost::assign::list_of(expression::TYPE_STRING)(expression::TYPE_INT); -    expression_function::argtype_list_type sr_write_args_w_port = boost::assign::list_of( -        expression::TYPE_STRING)(expression::TYPE_INT)(expression::TYPE_INT); -    ft->register_function("SR_WRITE", -        boost::bind(&block_iface::_nocscript__sr_write, this, _1), -        expression::TYPE_BOOL, -        sr_write_args_wo_port); -    ft->register_function("SR_WRITE", -        boost::bind(&block_iface::_nocscript__sr_write, this, _1), -        expression::TYPE_BOOL, -        sr_write_args_w_port); - -    // Add read access to arguments ($foo) -    expression_function::argtype_list_type arg_set_args_wo_port = -        boost::assign::list_of(expression::TYPE_STRING)(expression::TYPE_INT); -    expression_function::argtype_list_type arg_set_args_w_port = boost::assign::list_of( -        expression::TYPE_STRING)(expression::TYPE_INT)(expression::TYPE_INT); -#define REGISTER_ARG_SETTER(noctype, setter_func)         \ -    arg_set_args_wo_port[1] = expression::noctype;        \ -    arg_set_args_w_port[1]  = expression::noctype;        \ -    ft->register_function("SET_ARG",                      \ -        boost::bind(&block_iface::setter_func, this, _1), \ -        expression::TYPE_BOOL,                            \ -        arg_set_args_wo_port);                            \ -    ft->register_function("SET_ARG",                      \ -        boost::bind(&block_iface::setter_func, this, _1), \ -        expression::TYPE_BOOL,                            \ -        arg_set_args_w_port); -    REGISTER_ARG_SETTER(TYPE_INT, _nocscript__arg_set_int); -    REGISTER_ARG_SETTER(TYPE_STRING, _nocscript__arg_set_string); -    REGISTER_ARG_SETTER(TYPE_DOUBLE, _nocscript__arg_set_double); -    REGISTER_ARG_SETTER(TYPE_INT_VECTOR, _nocscript__arg_set_intvec); - - -    // Add read/write access to local variables -    expression_function::argtype_list_type set_var_args = -        boost::assign::list_of(expression::TYPE_STRING)(expression::TYPE_INT); -    const expression_function::argtype_list_type get_var_args = -        boost::assign::list_of(expression::TYPE_STRING); -#define REGISTER_VAR_ACCESS(noctype, typestr)                     \ -    set_var_args[1] = expression::noctype;                        \ -    ft->register_function("SET_VAR",                              \ -        boost::bind(&block_iface::_nocscript__var_set, this, _1), \ -        expression::TYPE_BOOL,                                    \ -        set_var_args);                                            \ -    ft->register_function("GET_" #typestr,                        \ -        boost::bind(&block_iface::_nocscript__var_get, this, _1), \ -        expression::noctype,                                      \ -        get_var_args); -    REGISTER_VAR_ACCESS(TYPE_INT, INT); -    REGISTER_VAR_ACCESS(TYPE_STRING, STRING); -    REGISTER_VAR_ACCESS(TYPE_DOUBLE, DOUBLE); -    REGISTER_VAR_ACCESS(TYPE_INT_VECTOR, INT_VECTOR); - -    // Create the parser -    _parser = parser::make(ft, -        boost::bind(&block_iface::_nocscript__arg_get_type, this, _1), -        boost::bind(&block_iface::_nocscript__arg_get_val, this, _1)); -} - - -void block_iface::run_and_check(const std::string& code, const std::string& error_message) -{ -    boost::mutex::scoped_lock local_interpreter_lock(_lil_mutex); - -    UHD_NOCSCRIPT_LOG() << "[NocScript] Executing and asserting code: " << code; -    expression::sptr e        = _parser->create_expr_tree(code); -    expression_literal result = e->eval(); -    if (not result.to_bool()) { -        if (error_message.empty()) { -            throw uhd::runtime_error( -                str(boost::format("[NocScript] Code returned false: %s") % code)); -        } else { -            throw uhd::runtime_error( -                str(boost::format("[NocScript] Error: %s") % error_message)); -        } -    } - -    _vars.clear(); // We go out of scope, and so do NocScript variables -} - - -expression_literal block_iface::_nocscript__sr_write( -    expression_container::expr_list_type args) -{ -    const std::string reg_name = args[0]->eval().get_string(); -    const uint32_t reg_val     = uint32_t(args[1]->eval().get_int()); -    size_t port                = 0; -    if (args.size() == 3) { -        port = size_t(args[2]->eval().get_int()); -    } - -    bool result = true; -    try { -        UHD_NOCSCRIPT_LOG() << "[NocScript] Executing SR_WRITE() "; -        _block_ptr->sr_write(reg_name, reg_val, port); -    } catch (const uhd::exception& e) { -        UHD_LOGGER_ERROR("RFNOC") -            << boost::format("[NocScript] Error while executing SR_WRITE(%s, 0x%X):\n%s") -                   % reg_name % reg_val % e.what(); -        result = false; -    } - -    return expression_literal(result); -} - -expression::type_t block_iface::_nocscript__arg_get_type(const std::string& varname) -{ -    const std::string var_type = _block_ptr->get_arg_type(varname); -    if (var_type == "int") { -        return expression::TYPE_INT; -    } else if (var_type == "string") { -        return expression::TYPE_STRING; -    } else if (var_type == "double") { -        return expression::TYPE_DOUBLE; -    } else if (var_type == "int_vector") { -        UHD_THROW_INVALID_CODE_PATH(); // TODO -    } else { -        UHD_THROW_INVALID_CODE_PATH(); -    } -} - -expression_literal block_iface::_nocscript__arg_get_val(const std::string& varname) -{ -    const std::string var_type = _block_ptr->get_arg_type(varname); -    if (var_type == "int") { -        return expression_literal(_block_ptr->get_arg<int>(varname)); -    } else if (var_type == "string") { -        return expression_literal(_block_ptr->get_arg<std::string>(varname)); -    } else if (var_type == "double") { -        return expression_literal(_block_ptr->get_arg<double>(varname)); -    } else if (var_type == "int_vector") { -        UHD_THROW_INVALID_CODE_PATH(); // TODO -    } else { -        UHD_THROW_INVALID_CODE_PATH(); -    } -} - -expression_literal block_iface::_nocscript__arg_set_int( -    const expression_container::expr_list_type& args) -{ -    const std::string var_name = args[0]->eval().get_string(); -    const int val              = args[1]->eval().get_int(); -    size_t port                = 0; -    if (args.size() == 3) { -        port = size_t(args[2]->eval().get_int()); -    } -    UHD_NOCSCRIPT_LOG() << "[NocScript] Setting $" << var_name; -    _block_ptr->set_arg<int>(var_name, val, port); -    return expression_literal(true); -} - -expression_literal block_iface::_nocscript__arg_set_string( -    const expression_container::expr_list_type& args) -{ -    const std::string var_name = args[0]->eval().get_string(); -    const std::string val      = args[1]->eval().get_string(); -    size_t port                = 0; -    if (args.size() == 3) { -        port = size_t(args[2]->eval().get_int()); -    } -    UHD_NOCSCRIPT_LOG() << "[NocScript] Setting $" << var_name; -    _block_ptr->set_arg<std::string>(var_name, val, port); -    return expression_literal(true); -} - -expression_literal block_iface::_nocscript__arg_set_double( -    const expression_container::expr_list_type& args) -{ -    const std::string var_name = args[0]->eval().get_string(); -    const double val           = args[1]->eval().get_double(); -    size_t port                = 0; -    if (args.size() == 3) { -        port = size_t(args[2]->eval().get_int()); -    } -    UHD_NOCSCRIPT_LOG() << "[NocScript] Setting $" << var_name; -    _block_ptr->set_arg<double>(var_name, val, port); -    return expression_literal(true); -} - -expression_literal block_iface::_nocscript__arg_set_intvec( -    const expression_container::expr_list_type&) -{ -    UHD_THROW_INVALID_CODE_PATH(); -} - -block_iface::sptr block_iface::make(uhd::rfnoc::block_ctrl_base* block_ptr) -{ -    return sptr(new block_iface(block_ptr)); -} - -expression_literal block_iface::_nocscript__var_get( -    const expression_container::expr_list_type& args) -{ -    expression_literal expr = _vars[args[0]->eval().get_string()]; -    // std::cout << "[NocScript] Getting var " << args[0]->eval().get_string() << " == " -    // << expr ; std::cout << "[NocScript] Type " << expr.infer_type() ; return -    // _vars[args[0]->eval().get_string()]; -    return expr; -} - -expression_literal block_iface::_nocscript__var_set( -    const expression_container::expr_list_type& args) -{ -    _vars[args[0]->eval().get_string()] = args[1]->eval(); -    // std::cout << "[NocScript] Set var " << args[0]->eval().get_string() << " to " << -    // _vars[args[0]->eval().get_string()] ; std::cout << "[NocScript] Type " << -    // _vars[args[0]->eval().get_string()].infer_type() ; -    return expression_literal(true); -} diff --git a/host/lib/rfnoc/nocscript/block_iface.hpp b/host/lib/rfnoc/nocscript/block_iface.hpp deleted file mode 100644 index 9d13fd4ab..000000000 --- a/host/lib/rfnoc/nocscript/block_iface.hpp +++ /dev/null @@ -1,87 +0,0 @@ -// -// Copyright 2015 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#include "expression.hpp" -#include "parser.hpp" -#include <uhd/rfnoc/block_ctrl_base.hpp> -#include <boost/thread/mutex.hpp> - -#ifndef INCLUDED_LIBUHD_NOCSCRIPT_BLOCK_IFACE_HPP -#    define INCLUDED_LIBUHD_NOCSCRIPT_BLOCK_IFACE_HPP - -namespace uhd { namespace rfnoc { namespace nocscript { - -/*! NocScript / Block interface class. - * - * This class only exists as a member of an rfnoc::block_ctrl_base class. - * It should never be instantiated anywhere else. It is used to execute - * NocScript function calls that require access to the original block - * controller class. - */ -class block_iface -{ -public: -    typedef boost::shared_ptr<block_iface> sptr; - -    static sptr make(uhd::rfnoc::block_ctrl_base* block_ptr); - -    block_iface(uhd::rfnoc::block_ctrl_base* block_ptr); - -    /*! Execute \p code and make sure it returns 'true'. -     * -     * \param code Must be a valid NocScript expression that returns a boolean value. -     *             If it returns false, this is interpreted as failure. -     * \param error_message If the expression fails, this error message is printed. -     * \throws uhd::runtime_error if the expression returns false. -     * \throws uhd::syntax_error if the expression is invalid. -     */ -    void run_and_check(const std::string& code, const std::string& error_message = ""); - -private: -    //! For the local interpreter lock (lil) -    boost::mutex _lil_mutex; - -    //! Wrapper for block_ctrl_base::sr_write, so we can call it from within NocScript -    expression_literal _nocscript__sr_write(expression_container::expr_list_type); - -    //! Argument type getter that can be used within NocScript -    expression::type_t _nocscript__arg_get_type(const std::string& argname); - -    //! Argument value getter that can be used within NocScript -    expression_literal _nocscript__arg_get_val(const std::string& argname); - -    //! Argument value setters: -    expression_literal _nocscript__arg_set_int( -        const expression_container::expr_list_type&); -    expression_literal _nocscript__arg_set_string( -        const expression_container::expr_list_type&); -    expression_literal _nocscript__arg_set_double( -        const expression_container::expr_list_type&); -    expression_literal _nocscript__arg_set_intvec( -        const expression_container::expr_list_type&); - -    //! Variable value getter -    expression_literal _nocscript__var_get(const expression_container::expr_list_type&); - -    //! Variable value setter -    expression_literal _nocscript__var_set(const expression_container::expr_list_type&); - -    //! Raw pointer to the block class. Note that since block_iface may -    // only live as a member of a block_ctrl_base, we don't really need -    // the reference counting. -    uhd::rfnoc::block_ctrl_base* _block_ptr; - -    //! Pointer to the parser object -    parser::sptr _parser; - -    //! Container for scoped variables -    std::map<std::string, expression_literal> _vars; -}; - -}}} /* namespace uhd::rfnoc::nocscript */ - -#endif /* INCLUDED_LIBUHD_NOCSCRIPT_BLOCK_IFACE_HPP */ diff --git a/host/lib/rfnoc/nocscript/expression.cpp b/host/lib/rfnoc/nocscript/expression.cpp deleted file mode 100644 index 5e03485be..000000000 --- a/host/lib/rfnoc/nocscript/expression.cpp +++ /dev/null @@ -1,380 +0,0 @@ -// -// Copyright 2015 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#include "expression.hpp" -#include "function_table.hpp" -#include <uhd/utils/cast.hpp> -#include <boost/algorithm/string.hpp> -#include <boost/format.hpp> - -using namespace uhd::rfnoc::nocscript; - -std::map<expression::type_t, std::string> expression::type_repr{{TYPE_INT, "INT"}, -    {TYPE_DOUBLE, "DOUBLE"}, -    {TYPE_STRING, "STRING"}, -    {TYPE_BOOL, "BOOL"}, -    {TYPE_INT_VECTOR, "INT_VECTOR"}}; - -/******************************************************************** - * Literal expressions (constants) - *******************************************************************/ -expression_literal::expression_literal( -    const std::string token_val, expression::type_t type) -    : _bool_val(false), _int_val(0), _double_val(0.0), _val(token_val), _type(type) -{ -    switch (_type) { -        case expression::TYPE_STRING: -            // Remove the leading and trailing quotes: -            _val = _val.substr(1, _val.size() - 2); -            break; - -        case expression::TYPE_INT: -            if (_val.substr(0, 2) == "0x") { -                _int_val = uhd::cast::hexstr_cast<int>(_val); -            } else { -                _int_val = std::stoi(_val); -            } -            break; - -        case expression::TYPE_DOUBLE: -            _double_val = std::stod(_val); -            break; - -        case expression::TYPE_BOOL: -            if (boost::to_upper_copy(_val) == "TRUE") { -                _bool_val = true; -            } else { -                // lexical cast to bool is too picky -                _bool_val = (std::stoi(_val) != 0); -            } -            break; - -        case expression::TYPE_INT_VECTOR: { -            std::string str_vec = _val.substr(1, _val.size() - 2); -            std::vector<std::string> subtoken_list; -            boost::split( -                subtoken_list, str_vec, boost::is_any_of(", "), boost::token_compress_on); -            for (const std::string& t : subtoken_list) { -                _int_vector_val.push_back(std::stoi(t)); -            } -            break; -        } - -        default: -            UHD_THROW_INVALID_CODE_PATH(); -    } -} - -expression_literal::expression_literal(bool b) -    : _bool_val(b), _int_val(0), _double_val(0.0), _val(""), _type(expression::TYPE_BOOL) -{ -    // nop -} - -expression_literal::expression_literal(int i) -    : _bool_val(false) -    , _int_val(i) -    , _double_val(0.0) -    , _val("") -    , _type(expression::TYPE_INT) -{ -    // nop -} - -expression_literal::expression_literal(double d) -    : _bool_val(false) -    , _int_val(0) -    , _double_val(d) -    , _val("") -    , _type(expression::TYPE_DOUBLE) -{ -    // nop -} - -expression_literal::expression_literal(const std::string& s) -    : _bool_val(false) -    , _int_val(0) -    , _double_val(0.0) -    , _val(s) -    , _type(expression::TYPE_STRING) -{ -    // nop -} - -expression_literal::expression_literal(const std::vector<int> v) -    : _bool_val(false) -    , _int_val(0) -    , _double_val(0.0) -    , _int_vector_val(v) -    , _val("") -    , _type(expression::TYPE_INT_VECTOR) -{ -    // nop -} - -bool expression_literal::to_bool() const -{ -    switch (_type) { -        case TYPE_INT: -            return bool(std::stoi(_val)); -        case TYPE_STRING: -            return not _val.empty(); -        case TYPE_DOUBLE: -            return bool(std::stod(_val)); -        case TYPE_BOOL: -            return _bool_val; -        case TYPE_INT_VECTOR: -            return not _int_vector_val.empty(); -        default: -            UHD_THROW_INVALID_CODE_PATH(); -    } -} - -int expression_literal::get_int() const -{ -    if (_type != TYPE_INT) { -        throw uhd::type_error("Cannot call get_int() on non-int value."); -    } - -    return _int_val; -} - -double expression_literal::get_double() const -{ -    if (_type != TYPE_DOUBLE) { -        throw uhd::type_error("Cannot call get_double() on non-double value."); -    } - -    return _double_val; -} - -std::string expression_literal::get_string() const -{ -    if (_type != TYPE_STRING) { -        throw uhd::type_error("Cannot call get_string() on non-string value."); -    } - -    return _val; -} - -bool expression_literal::get_bool() const -{ -    if (_type != TYPE_BOOL) { -        throw uhd::type_error("Cannot call get_bool() on non-boolean value."); -    } - -    return _bool_val; -} - -std::vector<int> expression_literal::get_int_vector() const -{ -    if (_type != TYPE_INT_VECTOR) { -        throw uhd::type_error("Cannot call get_bool() on non-boolean value."); -    } - -    return _int_vector_val; -} - -std::string expression_literal::repr() const -{ -    switch (_type) { -        case TYPE_INT: -            return std::to_string(_int_val); -        case TYPE_STRING: -            return _val; -        case TYPE_DOUBLE: -            return std::to_string(_double_val); -        case TYPE_BOOL: -            return _bool_val ? "TRUE" : "FALSE"; -        case TYPE_INT_VECTOR: { -            std::stringstream sstr; -            sstr << "["; -            for (size_t i = 0; i < _int_vector_val.size(); i++) { -                if (i > 0) { -                    sstr << ", "; -                } -                sstr << _int_vector_val[i]; -            } -            sstr << "]"; -            return sstr.str(); -        } -        default: -            UHD_THROW_INVALID_CODE_PATH(); -    } -} - -bool expression_literal::operator==(const expression_literal& rhs) const -{ -    if (rhs.infer_type() != _type) { -        return false; -    } - -    switch (_type) { -        case TYPE_INT: -            return get_int() == rhs.get_int(); -        case TYPE_STRING: -            return get_string() == rhs.get_string(); -        case TYPE_DOUBLE: -            return get_double() == rhs.get_double(); -        case TYPE_BOOL: -            return get_bool() == rhs.get_bool(); -        default: -            UHD_THROW_INVALID_CODE_PATH(); -    } -} - -/******************************************************************** - * Containers - *******************************************************************/ -expression_container::sptr expression_container::make() -{ -    return sptr(new expression_container); -} - -expression::type_t expression_container::infer_type() const -{ -    if (_combiner == COMBINE_OR or _combiner == COMBINE_AND) { -        return TYPE_BOOL; -    } - -    if (_sub_exprs.empty()) { -        return TYPE_BOOL; -    } - -    return _sub_exprs.back()->infer_type(); -} - -void expression_container::add(expression::sptr new_expr) -{ -    _sub_exprs.push_back(new_expr); -} - -bool expression_container::empty() const -{ -    return _sub_exprs.empty(); -} - -void expression_container::set_combiner_safe(const combiner_type c) -{ -    if (_combiner == COMBINE_NOTSET) { -        _combiner = c; -        return; -    } - -    throw uhd::syntax_error("Attempting to override combiner type"); -} - -expression_literal expression_container::eval() -{ -    if (_sub_exprs.empty()) { -        return expression_literal(true); -    } - -    expression_literal ret_val; -    for (const expression::sptr& sub_expr : _sub_exprs) { -        ret_val = sub_expr->eval(); -        if (_combiner == COMBINE_AND and ret_val.to_bool() == false) { -            return ret_val; -        } -        if (_combiner == COMBINE_OR and ret_val.to_bool() == true) { -            return ret_val; -        } -        // For ALL, we return the last one, so just overwrite it -    } -    return ret_val; -} - -/******************************************************************** - * Functions - *******************************************************************/ -std::string expression_function::to_string( -    const std::string& name, const argtype_list_type& types) -{ -    std::string s = name; -    int arg_count = 0; -    for (const expression::type_t type : types) { -        if (arg_count == 0) { -            s += "("; -        } else { -            s += ", "; -        } -        s += type_repr[type]; -        arg_count++; -    } -    s += ")"; - -    return s; -} - -expression_function::expression_function( -    const std::string& name, const function_table::sptr func_table) -    : _name(name), _func_table(func_table) -{ -    _combiner = COMBINE_ALL; -    if (not _func_table->function_exists(_name)) { -        throw uhd::syntax_error(str(boost::format("Unknown function: %s") % _name)); -    } -} - -void expression_function::add(expression::sptr new_expr) -{ -    expression_container::add(new_expr); -    _arg_types.push_back(new_expr->infer_type()); -} - -expression::type_t expression_function::infer_type() const -{ -    return _func_table->get_type(_name, _arg_types); -} - -expression_literal expression_function::eval() -{ -    return _func_table->eval(_name, _arg_types, _sub_exprs); -} - - -std::string expression_function::repr() const -{ -    return to_string(_name, _arg_types); -} - -expression_function::sptr expression_function::make( -    const std::string& name, const function_table::sptr func_table) -{ -    return sptr(new expression_function(name, func_table)); -} - -/******************************************************************** - * Variables - *******************************************************************/ -expression_variable::expression_variable(const std::string& token_val, -    type_getter_type type_getter, -    value_getter_type value_getter) -    : _type_getter(type_getter), _value_getter(value_getter) -{ -    // We can assume this is true because otherwise, it's not a valid token: -    UHD_ASSERT_THROW(not token_val.empty() and token_val[0] == '$'); - -    _varname = token_val.substr(1); -} - -expression::type_t expression_variable::infer_type() const -{ -    return _type_getter(_varname); -} - -expression_literal expression_variable::eval() -{ -    return _value_getter(_varname); -} - -expression_variable::sptr expression_variable::make(const std::string& token_val, -    type_getter_type type_getter, -    value_getter_type value_getter) -{ -    return sptr(new expression_variable(token_val, type_getter, value_getter)); -} diff --git a/host/lib/rfnoc/nocscript/expression.hpp b/host/lib/rfnoc/nocscript/expression.hpp deleted file mode 100644 index 309741295..000000000 --- a/host/lib/rfnoc/nocscript/expression.hpp +++ /dev/null @@ -1,360 +0,0 @@ -// -// Copyright 2015 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#include <uhd/exception.hpp> -#include <boost/function.hpp> -#include <boost/make_shared.hpp> -#include <boost/shared_ptr.hpp> -#include <map> -#include <vector> - -#ifndef INCLUDED_LIBUHD_RFNOC_NOCSCRIPT_EXPR_HPP -#    define INCLUDED_LIBUHD_RFNOC_NOCSCRIPT_EXPR_HPP - -namespace uhd { namespace rfnoc { namespace nocscript { - -// Forward declaration for expression::eval() -class expression_literal; - -/*! Virtual base class for Noc-Script expressions. - */ -class expression -{ -public: -    typedef boost::shared_ptr<expression> sptr; - -    //! All the possible return types for expressions within Noc-Script -    enum type_t { TYPE_INT, TYPE_DOUBLE, TYPE_STRING, TYPE_BOOL, TYPE_INT_VECTOR }; - -    // TODO make this a const and fix the [] usage -    static std::map<type_t, std::string> type_repr; - -    //! Returns the type of this expression without evaluating it -    virtual type_t infer_type() const = 0; - -    //! Evaluate current expression and return its return value -    virtual expression_literal eval() = 0; -}; - -/*! Literal (constant) expression class - * - * A literal is any value that is literally given in the NoC-Script - * source code, such as '5', '"FOO"', or '2.3'. - */ -class expression_literal : public expression -{ -public: -    typedef boost::shared_ptr<expression_literal> sptr; - -    template <typename expr_type> static sptr make(expr_type x) -    { -        return boost::make_shared<expression_literal>(x); -    }; - -    /*! Generate the literal expression from its token string representation. -     * This includes markup, e.g. a string would still have the quotes, and -     * a hex value would still have leading 0x. -     */ -    expression_literal(const std::string token_val, expression::type_t type); - -    //! Create a boolean literal expression from a C++ bool. -    expression_literal(bool b = false); -    //! Create an integer literal expression from a C++ int. -    expression_literal(int i); -    //! Create a double literal expression from a C++ double. -    expression_literal(double d); -    //! Create a string literal expression from a C++ string. -    expression_literal(const std::string& s); -    //! Create an int vector literal expression from a C++ vector<int>. -    expression_literal(std::vector<int> v); - -    virtual ~expression_literal() {} - -    expression::type_t infer_type() const -    { -        return _type; -    } - -    //! Literals aren't evaluated as such, so the evaluation -    //  simply returns a copy of itself. -    expression_literal eval() -    { -        return *this; // TODO make sure this is copy -    } - -    /*! A 'type cast' to bool. Cast rules are similar to most -     * scripting languages: -     * - Integers and doubles are false if zero, true otherwise -     * - Strings are false if empty, true otherwise -     * - Vectors are false if empty, true otherwise -     */ -    bool to_bool() const; - -    /*! Convenience function to typecast to C++ int -     * -     * Note that the current type must be TYPE_INT. -     * -     * \return C++ int representation of current literal -     * \throws uhd::type_error if type didn't match -     */ -    int get_int() const; - -    /*! Convenience function to typecast to C++ double -     * -     * Note that the current type must be TYPE_DOUBLE. -     * -     * \return C++ double representation of current literal -     * \throws uhd::type_error if type didn't match -     */ -    double get_double() const; - -    /*! Convenience function to typecast to C++ std::string. -     * -     * Note that the current type must be TYPE_STRING. -     * -     * \return String representation of current literal. -     * \throws uhd::type_error if type didn't match. -     */ -    std::string get_string() const; - -    /*! Convenience function to typecast to C++ int vector. -     * -     * Note that the current type must be TYPE_INT_VECTOR. -     * -     * \return String representation of current literal. -     * \throws uhd::type_error if type didn't match. -     */ -    std::vector<int> get_int_vector() const; - -    /*! Convenience function to typecast to C++ bool. -     * -     * Note that the current type must be TYPE_BOOL. -     * See also expression_literal::to_bool() for a type-cast -     * style function. -     * -     * \return bool representation of current literal. -     * \throws uhd::type_error if type didn't match. -     */ -    bool get_bool() const; - -    //! String representation -    std::string repr() const; - -    bool operator==(const expression_literal& rhs) const; - -private: -    //! For TYPE_BOOL -    bool _bool_val; - -    //! For TYPE_INT -    int _int_val; - -    //! For TYPE_DOUBLE -    double _double_val; - -    //! For TYPE_INT_VECTOR -    std::vector<int> _int_vector_val; - -    //! Store the token value -    std::string _val; - -    //! Current expression type -    expression::type_t _type; -}; - -UHD_INLINE std::ostream& operator<<(std::ostream& out, const expression_literal& l) -{ -    out << l.repr(); -    return out; -} - -UHD_INLINE std::ostream& operator<<(std::ostream& out, const expression_literal::sptr& l) -{ -    out << l->repr(); -    return out; -} - -/*! Contains multiple (sub-)expressions. - */ -class expression_container : public expression -{ -public: -    typedef boost::shared_ptr<expression_container> sptr; -    typedef std::vector<expression::sptr> expr_list_type; - -    //! Return an sptr to an empty container -    static sptr make(); - -    //! List of valid combination types (see expression_container::eval()). -    enum combiner_type { COMBINE_ALL, COMBINE_AND, COMBINE_OR, COMBINE_NOTSET }; - -    //! Create an empty container -    expression_container() : _combiner(COMBINE_NOTSET){}; -    virtual ~expression_container() {} - -    /*! Type-deduction rules for containers are: -     * - If the combination type is COMBINE_ALL or COMBINE_AND, -     *   return value must be TYPE_BOOL -     * - In all other cases, we return the last expression return -     *   value, and hence its type is relevant -     */ -    expression::type_t infer_type() const; - -    /*! Add another expression container to this container. -     */ -    virtual void add(expression::sptr new_expr); - -    virtual bool empty() const; - -    void set_combiner_safe(const combiner_type c); - -    void set_combiner(const combiner_type c) -    { -        _combiner = c; -    }; - -    combiner_type get_combiner() const -    { -        return _combiner; -    }; - -    /*! Evaluate a container by evaluating its sub-expressions. -     * -     * If a container contains multiple sub-expressions, the rules -     * for evaluating them depend on the combiner_type: -     * - COMBINE_ALL: Run all the sub-expressions and return the last -     *   expression's return value -     * - COMBINE_AND: Run sub-expressions, in order, until one of them -     *   returns false. Following expressions are not evaluated (like -     *   most C++ compilers). -     * - COMBINE_OR: Run sub-expressions, in order, until one of them -     *   returns true. Following expressions are not evaluated. -     * -     * In the special case where no sub-expressions are contained, always -     * returns true. -     */ -    virtual expression_literal eval(); - -protected: -    //! Store all the sub-expressions, in order -    expr_list_type _sub_exprs; -    combiner_type _combiner; -}; - -// Forward declaration: -class function_table; -/*! A function call is a special type of container. - * - * All arguments are sub-expressions. The combiner type is - * always COMBINE_ALL in this case (changing the combiner type - * does not affect anything). - * - * The actual function maps to a C++ function available through - * a uhd::rfnoc::nocscript::function_table object. - * - * The recommended to use this is: - * 1. Create a function object giving its name (e.g. ADD) - * 2. Use the add() method to add all the function arguments - *    in the right order (left to right). - * 3. Once step 2 is complete, the function object can be used. - *    Call infer_type() to get the return value, if required. - * 4. Calling eval() will call into the function table. The - *    argument expressions are evaluated, if so required, inside - *    the function (lazy evalulation). Functions do not need - *    to evaluate arguments. - */ -class expression_function : public expression_container -{ -public: -    typedef boost::shared_ptr<expression_function> sptr; -    typedef std::vector<expression::type_t> argtype_list_type; - -    //! Return an sptr to a function object without args -    static sptr make( -        const std::string& name, const boost::shared_ptr<function_table> func_table); - -    static std::string to_string(const std::string& name, const argtype_list_type& types); - -    expression_function( -        const std::string& name, const boost::shared_ptr<function_table> func_table); -    ~expression_function() {} - -    //! Add an argument expression -    virtual void add(expression::sptr new_expr); - -    /*! Looks up the function type in the function table. -     * -     * Note that this will only work after all arguments have been -     * added, as they are also used to look up a function's type in the -     * function table. -     */ -    expression::type_t infer_type() const; - -    /*! Evaluate all arguments, then the function itself. -     */ -    expression_literal eval(); - -    //! String representation -    std::string repr() const; - -private: -    std::string _name; -    const boost::shared_ptr<function_table> _func_table; -    std::vector<expression::type_t> _arg_types; -}; - - -/*! Variable expression - * - * Variables are like literals, only their type and value aren't known - * at parse-time. Instead, we provide a function object to look up - * variable's types and value. - */ -class expression_variable : public expression -{ -public: -    typedef boost::shared_ptr<expression_variable> sptr; -    typedef boost::function<expression::type_t(const std::string&)> type_getter_type; -    typedef boost::function<expression_literal(const std::string&)> value_getter_type; - -    static sptr make(const std::string& token_val, -        type_getter_type type_getter, -        value_getter_type value_getter); - -    /*! Create a variable object from its token value -     *  (e.g. '$spp', i.e. including the '$' symbol). The variable -     *  does not have to exist at this point. -     */ -    expression_variable(const std::string& token_val, -        type_getter_type type_getter, -        value_getter_type value_getter); - -    virtual ~expression_variable() {} - -    /*! Looks up the variable type in the variable table. -     * -     * \throws Depending on \p type_getter, this may throw when the variable does not -     * exist. Recommended behaviour is to throw uhd::syntax_error. -     */ -    expression::type_t infer_type() const; - -    /*! Look up a variable's value in the variable table. -     * -     * \throws Depending on \p value_getter, this may throw when the variable does not -     * exist. Recommended behaviour is to throw uhd::syntax_error. -     */ -    expression_literal eval(); - -private: -    std::string _varname; -    type_getter_type _type_getter; -    value_getter_type _value_getter; -}; - -}}} /* namespace uhd::rfnoc::nocscript */ - -#endif /* INCLUDED_LIBUHD_RFNOC_NOCSCRIPT_EXPR_HPP */ diff --git a/host/lib/rfnoc/nocscript/function_table.cpp b/host/lib/rfnoc/nocscript/function_table.cpp deleted file mode 100644 index 57e32363d..000000000 --- a/host/lib/rfnoc/nocscript/function_table.cpp +++ /dev/null @@ -1,100 +0,0 @@ -// -// Copyright 2015 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#include "function_table.hpp" -#include "basic_functions.hpp" -#include <boost/bind.hpp> -#include <boost/format.hpp> -#include <map> - -using namespace uhd::rfnoc::nocscript; - -class function_table_impl : public function_table -{ -public: -    struct function_info -    { -        expression::type_t return_type; -        function_ptr function; - -        function_info() : return_type(expression::TYPE_INT){}; -        function_info( -            const expression::type_t return_type_, const function_ptr& function_) -            : return_type(return_type_), function(function_){}; -    }; -    // Should be an unordered_map... sigh, we'll get to C++11 someday. -    typedef std::map<std::string, -        std::map<expression_function::argtype_list_type, function_info>> -        table_type; - -    /************************************************************************ -     * Structors -     ***********************************************************************/ -    function_table_impl() -    { -        _REGISTER_ALL_FUNCS(); -    } - -    ~function_table_impl(){}; - - -    /************************************************************************ -     * Interface implementation -     ***********************************************************************/ -    bool function_exists(const std::string& name) const -    { -        return bool(_table.count(name)); -    } - -    bool function_exists(const std::string& name, -        const expression_function::argtype_list_type& arg_types) const -    { -        table_type::const_iterator it = _table.find(name); -        return (it != _table.end()) and bool(it->second.count(arg_types)); -    } - -    expression::type_t get_type(const std::string& name, -        const expression_function::argtype_list_type& arg_types) const -    { -        table_type::const_iterator it = _table.find(name); -        if (it == _table.end() or (it->second.find(arg_types) == it->second.end())) { -            throw uhd::syntax_error( -                str(boost::format("Unable to retrieve return value for function %s") -                    % expression_function::to_string(name, arg_types))); -        } -        return it->second.find(arg_types)->second.return_type; -    } - -    expression_literal eval(const std::string& name, -        const expression_function::argtype_list_type& arg_types, -        expression_container::expr_list_type& arguments) -    { -        if (not function_exists(name, arg_types)) { -            throw uhd::syntax_error( -                str(boost::format("Cannot eval() function %s, not a known signature") -                    % expression_function::to_string(name, arg_types))); -        } - -        return _table[name][arg_types].function(arguments); -    } - -    void register_function(const std::string& name, -        const function_table::function_ptr& ptr, -        const expression::type_t return_type, -        const expression_function::argtype_list_type& sig) -    { -        _table[name][sig] = function_info(return_type, ptr); -    } - -private: -    table_type _table; -}; - -function_table::sptr function_table::make() -{ -    return sptr(new function_table_impl()); -} diff --git a/host/lib/rfnoc/nocscript/function_table.hpp b/host/lib/rfnoc/nocscript/function_table.hpp deleted file mode 100644 index 63125ab1b..000000000 --- a/host/lib/rfnoc/nocscript/function_table.hpp +++ /dev/null @@ -1,75 +0,0 @@ -// -// Copyright 2015 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#include "expression.hpp" -#include <boost/function.hpp> -#include <boost/shared_ptr.hpp> -#include <vector> - -#ifndef INCLUDED_LIBUHD_RFNOC_NOCSCRIPT_FUNCTABLE_HPP -#    define INCLUDED_LIBUHD_RFNOC_NOCSCRIPT_FUNCTABLE_HPP - -namespace uhd { namespace rfnoc { namespace nocscript { - -class function_table -{ -public: -    typedef boost::shared_ptr<function_table> sptr; -    typedef boost::function<expression_literal(expression_container::expr_list_type&)> -        function_ptr; - -    static sptr make(); -    virtual ~function_table(){}; - -    /*! Check if any function with a given name exists -     * -     * \returns True, if any function with name \p name is registered. -     */ -    virtual bool function_exists(const std::string& name) const = 0; - -    /*! Check if a function with a given name and list of argument types exists -     * -     * \returns True, if such a function is registered. -     */ -    virtual bool function_exists(const std::string& name, -        const expression_function::argtype_list_type& arg_types) const = 0; - -    /*! Get the return type of a function with given name and argument type list -     * -     * \returns The function's return type -     * \throws uhd::syntax_error if no such function is registered -     */ -    virtual expression::type_t get_type(const std::string& name, -        const expression_function::argtype_list_type& arg_types) const = 0; - -    /*! Calls the function \p name with the argument list \p arguments -     * -     * \param arg_types A list of types for each argument -     * \param arguments An expression list of the arguments -     * \returns The return value of the called function -     * \throws uhd::syntax_error if no such function is found -     */ -    virtual expression_literal eval(const std::string& name, -        const expression_function::argtype_list_type& arg_types, -        expression_container::expr_list_type& arguments) = 0; - -    /*! Register a new function -     * -     * \param name Name of the function (e.g. 'ADD') -     * \param ptr Function object -     * \param return_type The function's return value -     * \param sig The function signature (list of argument types) -     */ -    virtual void register_function(const std::string& name, -        const function_ptr& ptr, -        const expression::type_t return_type, -        const expression_function::argtype_list_type& sig) = 0; -}; - -}}} /* namespace uhd::rfnoc::nocscript */ - -#endif /* INCLUDED_LIBUHD_RFNOC_NOCSCRIPT_FUNCTABLE_HPP */ diff --git a/host/lib/rfnoc/nocscript/gen_basic_funcs.py b/host/lib/rfnoc/nocscript/gen_basic_funcs.py deleted file mode 100755 index fec6b04ad..000000000 --- a/host/lib/rfnoc/nocscript/gen_basic_funcs.py +++ /dev/null @@ -1,465 +0,0 @@ -#!/usr/bin/env python -""" -Generate the function list for the basic NocScript functions -""" - -import re -import os -import sys -from mako.template import Template - -############################################################################# -# This is the interesting part: Add new functions in here -# -# Notes: -# - Lines starting with # are considered comments, and will be removed from -#   the output -# - C++ comments will be copied onto the generated file if inside functions -# - Docstrings start with //! and are required -# - Function signature is RETURN_TYPE NAME(ARG_TYPE1, ARG_TYPE2, ...) -# - Function body is valid C++ -# - If your function requires special includes, put them in INCLUDE_LIST -# - End of functions is delimited by s/^}/, so take care with the indents! -# - Use these substitutions: -#   - ${RETURN}(...): Create a valid return value -#   - ${args[n]}: Access the n-th argument -# -INCLUDE_LIST = """ -#include <boost/math/special_functions/round.hpp> -#include <chrono> -#include <thread> -""" -FUNCTION_LIST = """ -CATEGORY: Math Functions -//! Returns x + y -INT ADD(INT, INT) -{ -    ${RETURN}(${args[0]} + ${args[1]}); -} - -//! Returns x + y -DOUBLE ADD(DOUBLE, DOUBLE) -{ -    ${RETURN}(${args[0]} + ${args[1]}); -} - -//! Returns x * y -DOUBLE MULT(DOUBLE, DOUBLE) -{ -    ${RETURN}(${args[0]} * ${args[1]}); -} - -//! Returns x * y -INT MULT(INT, INT) -{ -    ${RETURN}(${args[0]} * ${args[1]}); -} - -//! Returns x / y -DOUBLE DIV(DOUBLE, DOUBLE) -{ -    ${RETURN}(${args[0]} / ${args[1]}); -} - -//! Returns true if x <= y (Less or Equal) -BOOL LE(INT, INT) -{ -    ${RETURN}(bool(${args[0]} <= ${args[1]})); -} - -//! Returns true if x <= y (Less or Equal) -BOOL LE(DOUBLE, DOUBLE) -{ -    ${RETURN}(bool(${args[0]} <= ${args[1]})); -} - -//! Returns true if x >= y (Greater or Equal) -BOOL GE(INT, INT) -{ -    ${RETURN}(bool(${args[0]} >= ${args[1]})); -} - -//! Returns true if x >= y (Greater or Equal) -BOOL GE(DOUBLE, DOUBLE) -{ -    ${RETURN}(bool(${args[0]} >= ${args[1]})); -} - -//! Returns true if x < y (Less Than) -BOOL LT(INT, INT) -{ -    ${RETURN}(bool(${args[0]} < ${args[1]})); -} - -//! Returns true if x > y (Greater Than) -BOOL GT(INT, INT) -{ -    ${RETURN}(bool(${args[0]} > ${args[1]})); -} - -//! Returns true if x < y (Less Than) -BOOL LT(DOUBLE, DOUBLE) -{ -    ${RETURN}(bool(${args[0]} < ${args[1]})); -} - -//! Returns true if x > y (Greater Than) -BOOL GT(DOUBLE, DOUBLE) -{ -    ${RETURN}(bool(${args[0]} > ${args[1]})); -} - -//! Round x and return it as an integer -INT IROUND(DOUBLE) -{ -    ${RETURN}(int(boost::math::iround(${args[0]}))); -} - -//! Returns true if x is a power of 2 -BOOL IS_PWR_OF_2(INT) -{ -    if (${args[0]} < 0) return ${FALSE}; -    int i = ${args[0]}; -    while ( (i & 1) == 0 and (i > 1) ) { -        i >>= 1; -    } -    ${RETURN}(bool(i == 1)); -} - -//! Returns floor(log2(x)). -INT LOG2(INT) -{ -    if (${args[0]} < 0) { -        throw uhd::runtime_error(str( -            boost::format("In NocScript function ${func_name}: Cannot calculate log2() of negative number.") -        )); -    } - -    int power_value = ${args[0]}; -    int log2_value = 0; -    while ( (power_value & 1) == 0 and (power_value > 1) ) { -        power_value >>= 1; -        log2_value++; -    } -    ${RETURN}(log2_value); -} - -//! Returns x % y -INT MODULO(INT, INT) -{ -    ${RETURN}(${args[0]} % ${args[1]}); -} - -//! Returns true if x == y -BOOL EQUAL(INT, INT) -{ -    ${RETURN}(bool(${args[0]} == ${args[1]})); -} - -//! Returns true if x == y -BOOL EQUAL(DOUBLE, DOUBLE) -{ -    ${RETURN}(bool(${args[0]} == ${args[1]})); -} - -//! Returns true if x == y -BOOL EQUAL(STRING, STRING) -{ -    ${RETURN}(bool(${args[0]} == ${args[1]})); -} - -CATEGORY: Bitwise Operations -//! Returns x >> y -INT SHIFT_RIGHT(INT, INT) -{ -    ${RETURN}(${args[0]} >> ${args[1]}); -} - -//! Returns x << y -INT SHIFT_LEFT(INT, INT) -{ -    ${RETURN}(${args[0]} << ${args[1]}); -} - -//! Returns x & y -INT BITWISE_AND(INT, INT) -{ -    ${RETURN}(${args[0]} & ${args[1]}); -} - -//! Returns x | y -INT BITWISE_OR(INT, INT) -{ -    ${RETURN}(${args[0]} | ${args[1]}); -} - -//! Returns x ^ y -INT BITWISE_XOR(INT, INT) -{ -    ${RETURN}(${args[0]} ^ ${args[1]}); -} - -CATEGORY: Boolean Logic -//! Returns x xor y. -BOOL XOR(BOOL, BOOL) -{ -    ${RETURN}(${args[0]} xor ${args[1]}); -} - -//! Returns !x -BOOL NOT(BOOL) -{ -    ${RETURN}(not ${args[0]}); -} - -//! Always returns true -BOOL TRUE() -{ -    return ${TRUE}; -} - -//! Always returns false -BOOL FALSE() -{ -    return ${FALSE}; -} - -CATEGORY: Conditional Execution -//! Executes x, if true, execute y. Returns true if x is true. -BOOL IF(BOOL, BOOL) -{ -    if (${args[0]}) { -        ${args[1]}; -        ${RETURN}(true); -    } -    ${RETURN}(false); -} - -//! Executes x, if true, execute y, otherwise, execute z. Returns true if x is true. -BOOL IF_ELSE(BOOL, BOOL, BOOL) -{ -    if (${args[0]}) { -        ${args[1]}; -        ${RETURN}(true); -    } else { -        ${args[2]}; -    } -    ${RETURN}(false); -} - -CATEGORY: Execution Control -//! Sleep for x seconds. Fractions are allowed. Millisecond accuracy. -BOOL SLEEP(DOUBLE) -{ -    int ms = ${args[0]} / 1000; -    std::this_thread::sleep_for(std::chrono::milliseconds(ms)); -    ${RETURN}(true); -} -""" -# End of interesting part. The rest will take this and turn into a C++ -# header file. -############################################################################# - -HEADER = """<% import time %>// -/////////////////////////////////////////////////////////////////////// -// This file was generated by ${file} on ${time.strftime("%c")} -/////////////////////////////////////////////////////////////////////// -// Copyright 2015 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -/**************************************************************************** - * This file is autogenerated! Any manual changes in here will be - * overwritten by calling nocscript_gen_basic_funcs.py! - ***************************************************************************/ - -#include "expression.hpp" -#include "function_table.hpp" -#include <uhd/exception.hpp> -#include <boost/format.hpp> -#include <boost/assign/list_of.hpp> -${INCLUDE_LIST} - -#ifndef INCLUDED_LIBUHD_RFNOC_NOCSCRIPT_BASICFUNCS_HPP -#define INCLUDED_LIBUHD_RFNOC_NOCSCRIPT_BASICFUNCS_HPP - -namespace uhd { namespace rfnoc { namespace nocscript { -""" - -# Not a Mako template: -FOOTER=""" -}}} /* namespace uhd::rfnoc::nocscript */ - -#endif /* INCLUDED_LIBUHD_RFNOC_NOCSCRIPT_BASICFUNCS_HPP */ -""" - -# Not a Mako template: -FUNC_TEMPLATE = """ -expression_literal {NAME}(expression_container::expr_list_type &{ARGS}) -{BODY} -""" - -REGISTER_MACRO_TEMPLATE = """#define _REGISTER_ALL_FUNCS()${registry} -""" - -REGISTER_COMMANDS_TEMPLATE = """ -    % if len(arglist): -    expression_function::argtype_list_type ${func_name}_args = boost::assign::list_of -    % for this_type in arglist: -        (expression::TYPE_${this_type}) -    % endfor -    ; -    % else: -    expression_function::argtype_list_type ${func_name}_args; -    % endif -    register_function( -            "${name}", -            boost::bind(&${func_name}, _1), -            expression::TYPE_${retval}, -            ${func_name}_args -    );""" - -DOXY_TEMPLATE = """/*! \page page_nocscript_funcs NocScript Function Reference -% for cat, func_by_name in func_list_tree.items(): -- ${cat} -%   for func_name, func_info_list in func_by_name.items(): -  - ${func_name}: ${func_info_list[0]['docstring']} -%     for func_info in func_info_list: -    - ${func_info['arglist']} -> ${func_info['retval']} -%     endfor -%   endfor -% endfor - -*/ -""" - -def parse_tmpl(_tmpl_text, **kwargs): -    return Template(_tmpl_text).render(**kwargs) - -def make_cxx_func_name(func_dict): -    """ -    Creates a unique C++ function name from a function description -    """ -    return "{name}__{retval}__{arglist}".format( -        name=func_dict['name'], -        retval=func_dict['retval'], -        arglist="_".join(func_dict['arglist']) -    ) - -def make_cxx_func_body(func_dict): -    """ -    Formats the function body properly -    """ -    type_lookup_methods = { -            'INT': 'get_int', -            'DOUBLE': 'get_double', -            'BOOL': 'get_bool', -            'STRING': 'get_string', -    } -    args_lookup = [] -    for idx, arg_type in enumerate(func_dict['arglist']): -        args_lookup.append("args[{idx}]->eval().{getter}()".format(idx=idx, getter=type_lookup_methods[arg_type])) -    return parse_tmpl( -        func_dict['body'], -        args=args_lookup, -        FALSE='expression_literal(false)', -        TRUE='expression_literal(true)', -        RETURN='return expression_literal', -        **func_dict -    ) - -def prep_function_list(): -    """ -    - Remove all comments -    - Split the function list into individual functions -    - Split the functions into return value, name, argument list and body -    """ -    comment_remove_re = re.compile(r'^\s*#.*$', flags=re.MULTILINE) -    func_list_wo_comments = comment_remove_re.sub('', FUNCTION_LIST) -    func_splitter_re = re.compile(r'(?<=^})\s*$', flags=re.MULTILINE) -    func_list_split = func_splitter_re.split(func_list_wo_comments) -    func_list_split = [x.strip() for x in func_list_split if len(x.strip())] -    func_list = [] -    last_category = '' -    for func in func_list_split: -        split_regex = r'(^CATEGORY: (?P<cat>[^\n]*)\s*)?' \ -                      r'//!(?P<docstring>[^\n]*)\s*' + \ -                      r'(?P<retval>[A-Z][A-Z0-9_]*)\s+' + \ -                      r'(?P<funcname>[A-Z][A-Z0-9_]*)\s*\((?P<arglist>[^\)]*)\)\s*' + \ -                      r'(?P<funcbody>^{.*)' -        split_re = re.compile(split_regex, flags=re.MULTILINE|re.DOTALL) -        mo = split_re.match(func) -        if mo.group('cat'): -            last_category = mo.group('cat').strip() -        func_dict = { -            'docstring': mo.group('docstring').strip(), -            'name': mo.group('funcname'), -            'retval': mo.group('retval'), -            'arglist': [x.strip() for x in mo.group('arglist').split(',') if len(x.strip())], -            'body': mo.group('funcbody'), -            'category': last_category, -        } -        func_dict['func_name'] = make_cxx_func_name(func_dict) -        func_list.append(func_dict) -    return func_list - -def write_function_header(output_filename): -    """ -    Create the .hpp file that defines all the NocScript functions in C++. -    """ -    func_list = prep_function_list() -    # Step 1: Write the prototypes -    func_prototypes = '' -    registry_commands = '' -    for func in func_list: -        func_prototypes += FUNC_TEMPLATE.format( -            NAME=func['func_name'], -            BODY=make_cxx_func_body(func), -            ARGS="args" if len(func['arglist']) else "" -        ) -        registry_commands += parse_tmpl( -                REGISTER_COMMANDS_TEMPLATE, -                **func -        ) -    # Step 2: Write the registry process -    register_func = parse_tmpl(REGISTER_MACRO_TEMPLATE, registry=registry_commands) -    register_func = register_func.replace('\n', ' \\\n') - -    # Final step: Join parts and write to file -    full_file = "\n".join(( -            parse_tmpl(HEADER, file = os.path.basename(__file__), INCLUDE_LIST=INCLUDE_LIST), -            func_prototypes, -            register_func, -            FOOTER, -    )) -    open(output_filename, 'w').write(full_file) - -def write_manual_file(output_filename): -    """ -    Write the Doxygen file for the NocScript functions. -    """ -    func_list = prep_function_list() -    func_list_tree = {} -    for func in func_list: -        if func['category'] not in func_list_tree: -            func_list_tree[func['category']] = {} -        if func['name'] not in func_list_tree[func['category']]: -            func_list_tree[func['category']][func['name']] = [] -        func_list_tree[func['category']][func['name']].append(func) -    open(output_filename, 'w').write(parse_tmpl(DOXY_TEMPLATE, func_list_tree=func_list_tree)) - - -def main(): -    if len(sys.argv) < 2: -        print("No output file specified!") -        exit(1) -    outfile = sys.argv[1] -    if os.path.splitext(outfile)[1] == '.dox': -        write_manual_file(outfile) -    else: -        write_function_header(outfile) - -if __name__ == "__main__": -    main() diff --git a/host/lib/rfnoc/nocscript/parser.cpp b/host/lib/rfnoc/nocscript/parser.cpp deleted file mode 100644 index 8ef1b7f44..000000000 --- a/host/lib/rfnoc/nocscript/parser.cpp +++ /dev/null @@ -1,357 +0,0 @@ -// -// Copyright 2015 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#include "parser.hpp" -#include <uhd/utils/cast.hpp> -#include <boost/assign.hpp> -#include <boost/bind.hpp> -#include <boost/format.hpp> -#include <boost/make_shared.hpp> -#include <boost/spirit/include/lex_lexertl.hpp> -#include <sstream> -#include <stack> - -using namespace uhd::rfnoc::nocscript; -namespace lex = boost::spirit::lex; - -class parser_impl : public parser -{ -public: -    /****************************************************************** -     * Structors TODO make them protected -     *****************************************************************/ -    parser_impl(function_table::sptr ftable, -        expression_variable::type_getter_type var_type_getter, -        expression_variable::value_getter_type var_value_getter) -        : _ftable(ftable) -        , _var_type_getter(var_type_getter) -        , _var_value_getter(var_value_getter) -    { -        // nop -    } - -    virtual ~parser_impl() {} - - -    /****************************************************************** -     * Parsing -     *****************************************************************/ -    //! List of parser tokens -    enum token_ids { -        ID_WHITESPACE = lex::min_token_id + 42, -        ID_KEYWORD, -        ID_ARG_SEP, -        ID_PARENS_OPEN, -        ID_PARENS_CLOSE, -        ID_VARIABLE, -        ID_LITERAL_DOUBLE, -        ID_LITERAL_INT, -        ID_LITERAL_HEX, -        ID_LITERAL_STR, -        ID_LITERAL_VECTOR_INT -    }; - -    //! The Lexer object used for NocScript -    template <typename Lexer> struct ns_lexer : lex::lexer<Lexer> -    { -        ns_lexer() -        { -            this->self.add("\\s+", ID_WHITESPACE)(",", ID_ARG_SEP)( -                "[A-Z][A-Z0-9_]*", ID_KEYWORD)("\\(", ID_PARENS_OPEN)( -                "\\)", ID_PARENS_CLOSE)("\\$[a-z][a-z0-9_]*", ID_VARIABLE)( -                "-?\\d+\\.\\d+", ID_LITERAL_DOUBLE)("-?\\d+", ID_LITERAL_INT)( -                "0x[0-9A-F]+", ID_LITERAL_HEX)("\\\"[^\\\"]*\\\"", ID_LITERAL_STR)( -                "'[^']*'", ID_LITERAL_STR) // both work -                ("\\[[0-9]\\]", ID_LITERAL_VECTOR_INT); -        } -    }; - -private: -    struct grammar_props -    { -        function_table::sptr ftable; -        expression_variable::type_getter_type var_type_getter; -        expression_variable::value_getter_type var_value_getter; - -        //! Store the last keyword -        std::string function_name; -        std::string error; -        std::stack<expression_container::sptr> expr_stack; - -        grammar_props(function_table::sptr ftable_, -            expression_variable::type_getter_type var_type_getter_, -            expression_variable::value_getter_type var_value_getter_) -            : ftable(ftable_) -            , var_type_getter(var_type_getter_) -            , var_value_getter(var_value_getter_) -            , function_name("") -        { -            UHD_ASSERT_THROW(expr_stack.empty()); -            // Push an empty container to the stack to hold the result -            expr_stack.push(expression_container::make()); -        } - -        expression::sptr get_result() -        { -            UHD_ASSERT_THROW(expr_stack.size() == 1); -            return expr_stack.top(); -        } -    }; - -    //! This isn't strictly a grammar, as it also includes semantic -    //  actions etc. I'm not going to spend ages thinking of a better -    //  name at this point. -    struct grammar -    { -        // Implementation detail specific to boost::bind (see Boost::Spirit -        // examples) -        typedef bool result_type; - -        static const int VALID_COMMA        = 0x1; -        static const int VALID_PARENS_OPEN  = 0x2; -        static const int VALID_PARENS_CLOSE = 0x4; -        static const int VALID_EXPRESSION   = 0x8 + 0x02; -        static const int VALID_OPERATOR     = 0x10; - -        // !This function operator gets called for each of the matched tokens. -        template <typename Token> -        bool operator()(Token const& t, grammar_props& P, int& next_valid_state) const -        { -            //! This is totally not how Boost::Spirit is meant to be used, -            // as there's token types etc. But for now let's just convert -            // every token to a string, and then handle it as such. -            std::stringstream sstr; -            sstr << t.value(); -            std::string val = sstr.str(); -            // std::cout << "VAL: " << val << std::endl; -            // std::cout << "Next valid states:\n" -            //<< boost::format("VALID_COMMA        [%s]\n") % ((next_valid_state & 0x1) ? -            //"x" : " ") -            //<< boost::format("VALID_PARENS_OPEN  [%s]\n") % ((next_valid_state & 0x2) ? -            //"x" : " ") -            //<< boost::format("VALID_PARENS_CLOSE [%s]\n") % ((next_valid_state & 0x4) ? -            //"x" : " ") -            //<< boost::format("VALID_EXPRESSION   [%s]\n") % ((next_valid_state & (0x8 + -            //0x02)) ? "x" : " ") -            //<< boost::format("VALID_OPERATOR      [%s]\n") % ((next_valid_state & 0x10) -            //? "x" : " ") -            //<< std::endl; - -            switch (t.id()) { -                case ID_WHITESPACE: -                    // Ignore -                    break; - -                case ID_KEYWORD: -                    // Ambiguous, could be an operator (AND, OR) or a function name (ADD, -                    // MULT...). So first, check which it is: -                    if (val == "AND" or val == "OR") { -                        if (not(next_valid_state & VALID_OPERATOR)) { -                            P.error = str(boost::format("Unexpected operator: %s") % val); -                            return false; -                        } -                        next_valid_state = VALID_EXPRESSION; -                        try { -                            if (val == "AND") { -                                P.expr_stack.top()->set_combiner_safe( -                                    expression_container::COMBINE_AND); -                            } else if (val == "OR") { -                                P.expr_stack.top()->set_combiner_safe( -                                    expression_container::COMBINE_OR); -                            } -                        } catch (const uhd::syntax_error&) { -                            P.error = str(boost::format("Operator %s is mixing operator " -                                                        "types within this container.") -                                          % val); -                        } -                        // Right now, we can't have multiple operator types within a -                        // container. We might be able to change that, if there's enough -                        // demand. Either we keep track of multiple operators, or we open -                        // a new container. In the latter case, we'd need a way of keeping -                        // track of those containers, so it's a bit tricky. -                        break; -                    } -                    // If it's not a keyword, it has to be a function, so check the -                    // function table: -                    if (not(next_valid_state & VALID_EXPRESSION)) { -                        P.error = str(boost::format("Unexpected expression: %s") % val); -                        return false; -                    } -                    if (not P.ftable->function_exists(val)) { -                        P.error = str(boost::format("Unknown function: %s") % val); -                        return false; -                    } -                    P.function_name  = val; -                    next_valid_state = VALID_PARENS_OPEN; -                    break; - -                // Every () creates a new container, either a raw container or -                // a function. -                case ID_PARENS_OPEN: -                    if (not(next_valid_state & VALID_PARENS_OPEN)) { -                        P.error = str(boost::format("Unexpected parentheses.")); -                        return false; -                    } -                    if (not P.function_name.empty()) { -                        // We've already checked the function name exists -                        P.expr_stack.push( -                            expression_function::make(P.function_name, P.ftable)); -                        P.function_name.clear(); -                    } else { -                        P.expr_stack.push(expression_container::make()); -                    } -                    // Push another empty container to hold the first element/argument -                    // in this container: -                    P.expr_stack.push(expression_container::make()); -                    next_valid_state = VALID_EXPRESSION | VALID_PARENS_CLOSE; -                    break; - -                case ID_PARENS_CLOSE: { -                    if (not(next_valid_state & VALID_PARENS_CLOSE)) { -                        P.error = str(boost::format("Unexpected parentheses.")); -                        return false; -                    } -                    if (P.expr_stack.size() < 2) { -                        P.error = str(boost::format("Unbalanced closing parentheses.")); -                        return false; -                    } -                    // First pop the last expression inside the parentheses, -                    // if it's not empty, add it to the top container (this also avoids -                    // adding arguments to functions if none were provided): -                    expression_container::sptr c = P.expr_stack.top(); -                    P.expr_stack.pop(); -                    if (not c->empty()) { -                        P.expr_stack.top()->add(c); -                    } -                    // At the end of (), either a function or container is complete, -                    // so pop that and add it to its top container: -                    expression_container::sptr c2 = P.expr_stack.top(); -                    P.expr_stack.pop(); -                    P.expr_stack.top()->add(c2); -                    next_valid_state = VALID_OPERATOR | VALID_COMMA | VALID_PARENS_CLOSE; -                } break; - -                case ID_ARG_SEP: { -                    if (not(next_valid_state & VALID_COMMA)) { -                        P.error = str(boost::format("Unexpected comma.")); -                        return false; -                    } -                    next_valid_state = VALID_EXPRESSION; -                    // If stack size is 1, we're on the base container, which means we -                    // simply string stuff. -                    if (P.expr_stack.size() == 1) { -                        break; -                    } -                    // Otherwise, a ',' always means we add the previous expression to -                    // the current container: -                    expression_container::sptr c = P.expr_stack.top(); -                    P.expr_stack.pop(); -                    P.expr_stack.top()->add(c); -                    // It also means another expression is following, so create another -                    // empty container for that: -                    P.expr_stack.push(expression_container::make()); -                } break; - -                    // All the atomic expressions just get added to the current container: - -                case ID_VARIABLE: { -                    if (not(next_valid_state & VALID_EXPRESSION)) { -                        P.error = str(boost::format("Unexpected expression.")); -                        return false; -                    } -                    expression_variable::sptr v = expression_variable::make( -                        val, P.var_type_getter, P.var_value_getter); -                    P.expr_stack.top()->add(v); -                    next_valid_state = VALID_OPERATOR | VALID_COMMA | VALID_PARENS_CLOSE; -                } break; - -                default: -                    // If we get here, we assume it's a literal expression -                    { -                        if (not(next_valid_state & VALID_EXPRESSION)) { -                            P.error = str(boost::format("Unexpected expression.")); -                            return false; -                        } -                        expression::type_t token_type; -                        switch (t.id()) { // A map lookup would be more elegant, but we'd -                                          // need a nicer C++ for that -                            case ID_LITERAL_DOUBLE: -                                token_type = expression::TYPE_DOUBLE; -                                break; -                            case ID_LITERAL_INT: -                                token_type = expression::TYPE_INT; -                                break; -                            case ID_LITERAL_HEX: -                                token_type = expression::TYPE_INT; -                                break; -                            case ID_LITERAL_STR: -                                token_type = expression::TYPE_STRING; -                                break; -                            case ID_LITERAL_VECTOR_INT: -                                token_type = expression::TYPE_INT_VECTOR; -                                break; -                            default: -                                UHD_THROW_INVALID_CODE_PATH(); -                        } -                        P.expr_stack.top()->add( -                            boost::make_shared<expression_literal>(val, token_type)); -                        next_valid_state = VALID_OPERATOR | VALID_COMMA -                                           | VALID_PARENS_CLOSE; -                        break; -                    } - -            } // end switch -            return true; -        } -    }; - -public: -    expression::sptr create_expr_tree(const std::string& code) -    { -        // Create empty stack and keyword states -        grammar_props P(_ftable, _var_type_getter, _var_value_getter); -        int next_valid_state = grammar::VALID_EXPRESSION; - -        // Create a lexer instance -        ns_lexer<lex::lexertl::lexer<>> lexer_functor; - -        // Tokenize the string -        char const* first = code.c_str(); -        char const* last  = &first[code.size()]; -        bool r            = lex::tokenize(first, -            last, // Iterators -            lexer_functor, // Lexer -            boost::bind(grammar(), -                _1, -                boost::ref(P), -                boost::ref(next_valid_state)) // Function object -        ); - -        // Check the parsing worked: -        if (not r or P.expr_stack.size() != 1) { -            std::string rest(first, last); -            throw uhd::syntax_error( -                str(boost::format("Parsing stopped at: %s\nError message: %s") % rest -                    % P.error)); -        } - -        // Clear stack and return result -        return P.get_result(); -    } - -private: -    function_table::sptr _ftable; -    expression_variable::type_getter_type _var_type_getter; -    expression_variable::value_getter_type _var_value_getter; -}; - -parser::sptr parser::make(function_table::sptr ftable, -    expression_variable::type_getter_type var_type_getter, -    expression_variable::value_getter_type var_value_getter) -{ -    return sptr(new parser_impl(ftable, var_type_getter, var_value_getter)); -} diff --git a/host/lib/rfnoc/nocscript/parser.hpp b/host/lib/rfnoc/nocscript/parser.hpp deleted file mode 100644 index e9d9f0820..000000000 --- a/host/lib/rfnoc/nocscript/parser.hpp +++ /dev/null @@ -1,37 +0,0 @@ -// -// Copyright 2015 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#include "expression.hpp" -#include "function_table.hpp" -#include <boost/shared_ptr.hpp> - -#ifndef INCLUDED_LIBUHD_RFNOC_NOCSCRIPT_PARSER_HPP -#    define INCLUDED_LIBUHD_RFNOC_NOCSCRIPT_PARSER_HPP - -namespace uhd { namespace rfnoc { namespace nocscript { - -class parser -{ -public: -    typedef boost::shared_ptr<parser> sptr; - -    static sptr make(function_table::sptr ftable, -        expression_variable::type_getter_type var_type_getter, -        expression_variable::value_getter_type var_value_getter); - -    /*! The main parsing call: Turn a string of code into an expression tree. -     * -     * Evaluating the returned object will execute the code. -     * -     * \throws uhd::syntax_error if \p code contains syntax errors -     */ -    virtual expression::sptr create_expr_tree(const std::string& code) = 0; -}; - -}}} /* namespace uhd::rfnoc::nocscript */ - -#endif /* INCLUDED_LIBUHD_RFNOC_NOCSCRIPT_PARSER_HPP */ diff --git a/host/lib/rfnoc/node_ctrl_base.cpp b/host/lib/rfnoc/node_ctrl_base.cpp deleted file mode 100644 index a6ee80f8b..000000000 --- a/host/lib/rfnoc/node_ctrl_base.cpp +++ /dev/null @@ -1,138 +0,0 @@ -// -// Copyright 2014-2016 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#include <uhd/rfnoc/node_ctrl_base.hpp> -#include <uhd/utils/log.hpp> -#include <boost/range/adaptor/map.hpp> - -using namespace uhd::rfnoc; - -std::string node_ctrl_base::unique_id() const -{ -    // Most instantiations will override this, so we don't need anything -    // more elegant here. -    return str(boost::format("%08X") % size_t(this)); -} - -void node_ctrl_base::clear() -{ -    UHD_LOG_TRACE(unique_id(), "node_ctrl_base::clear()"); -    // Reset connections: -    _upstream_nodes.clear(); -    _downstream_nodes.clear(); -} - -void node_ctrl_base::_register_downstream_node(node_ctrl_base::sptr, size_t) -{ -    throw uhd::runtime_error( -        "Attempting to register a downstream block on a non-source node."); -} - -void node_ctrl_base::_register_upstream_node(node_ctrl_base::sptr, size_t) -{ -    throw uhd::runtime_error( -        "Attempting to register an upstream block on a non-sink node."); -} - -void node_ctrl_base::set_downstream_port(const size_t this_port, const size_t remote_port) -{ -    if (not _downstream_nodes.count(this_port) and remote_port != ANY_PORT) { -        throw uhd::value_error( -            str(boost::format( -                    "[%s] Cannot set remote downstream port: Port %d not connected.") -                % unique_id() % this_port)); -    } -    _downstream_ports[this_port] = remote_port; -} - -size_t node_ctrl_base::get_downstream_port(const size_t this_port) -{ -    if (not _downstream_ports.count(this_port) or not _downstream_nodes.count(this_port) -        or _downstream_ports[this_port] == ANY_PORT) { -        throw uhd::value_error( -            str(boost::format( -                    "[%s] Cannot retrieve remote downstream port: Port %d not connected.") -                % unique_id() % this_port)); -    } -    return _downstream_ports[this_port]; -} - -void node_ctrl_base::set_upstream_port(const size_t this_port, const size_t remote_port) -{ -    if (not _upstream_nodes.count(this_port) and remote_port != ANY_PORT) { -        throw uhd::value_error(str( -            boost::format("[%s] Cannot set remote upstream port: Port %d not connected.") -            % unique_id() % this_port)); -    } -    _upstream_ports[this_port] = remote_port; -} - -size_t node_ctrl_base::get_upstream_port(const size_t this_port) -{ -    if (not _upstream_ports.count(this_port) or not _upstream_nodes.count(this_port) -        or _upstream_ports[this_port] == ANY_PORT) { -        throw uhd::value_error( -            str(boost::format( -                    "[%s] Cannot retrieve remote upstream port: Port %d not connected.") -                % unique_id() % this_port)); -    } -    return _upstream_ports[this_port]; -} - -void node_ctrl_base::disconnect() -{ -    // Notify neighbours: -    for (node_map_t::iterator i = _downstream_nodes.begin(); i != _downstream_nodes.end(); -         ++i) { -        sptr downstream_node = i->second.lock(); -        if (not downstream_node) { -            // Actually this is not OK -            continue; -        } -        downstream_node->disconnect_input_port(_downstream_ports[i->first]); -    } -    for (node_map_t::iterator i = _upstream_nodes.begin(); i != _upstream_nodes.end(); -         ++i) { -        sptr upstream_node = i->second.lock(); -        if (not upstream_node) { -            // Actually this is not OK -            continue; -        } -        upstream_node->disconnect_output_port(_upstream_ports[i->first]); -    } -    // Clear own maps: -    _downstream_nodes.clear(); -    _downstream_ports.clear(); -    _upstream_nodes.clear(); -    _upstream_ports.clear(); -} - -void node_ctrl_base::disconnect_output_port(const size_t output_port) -{ -    if (_downstream_nodes.count(output_port) == 0 -        or _downstream_ports.count(output_port) == 0) { -        throw uhd::assertion_error( -            str(boost::format("[%s] Attempting to disconnect output port %u, which is " -                              "not registered as connected!") -                % unique_id() % output_port)); -    } -    _downstream_nodes.erase(output_port); -    _downstream_ports.erase(output_port); -} - -void node_ctrl_base::disconnect_input_port(const size_t input_port) -{ -    if (_upstream_nodes.count(input_port) == 0 -        or _upstream_ports.count(input_port) == 0) { -        throw uhd::assertion_error( -            str(boost::format("[%s] Attempting to disconnect input port %u, which is not " -                              "registered as connected!") -                % unique_id() % input_port)); -    } -    _upstream_nodes.erase(input_port); -    _upstream_ports.erase(input_port); -} diff --git a/host/lib/rfnoc/null_block_ctrl_impl.cpp b/host/lib/rfnoc/null_block_ctrl_impl.cpp deleted file mode 100644 index 1de41d256..000000000 --- a/host/lib/rfnoc/null_block_ctrl_impl.cpp +++ /dev/null @@ -1,120 +0,0 @@ -// -// Copyright 2014-2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#include <uhd/rfnoc/null_block_ctrl.hpp> -#include <uhd/rfnoc/traffic_counter.hpp> -#include <uhd/types/ranges.hpp> -#include <uhd/utils/log.hpp> -#include <boost/format.hpp> - -using namespace uhd::rfnoc; - -class null_block_ctrl_impl : public null_block_ctrl -{ -public: -    UHD_RFNOC_BLOCK_CONSTRUCTOR(null_block_ctrl) -    { -        // Register hooks for line_rate: -        _tree->access<int>(_root_path / "args" / 0 / "line_rate" / "value") -            .add_coerced_subscriber( -                [this](const int delay) { this->set_line_delay_cycles(delay); }) -            .update(); -        // Register hooks for bpp: -        _tree->access<int>(_root_path / "args" / 0 / "bpp" / "value") -            .add_coerced_subscriber( -                [this](const int bpp) { this->set_bytes_per_packet(bpp); }) -            .update(); - -        traffic_counter::write_reg_fn_t write = [this](const uint32_t addr, -                                                    const uint32_t data) { -            const uint64_t traffic_counter_sr_base = 192; -            sr_write(addr + traffic_counter_sr_base, data); -        }; - -        traffic_counter::read_reg_fn_t read = [this](const uint32_t addr) { -            const uint64_t traffic_counter_rb_base = 64; -            return user_reg_read64(addr + traffic_counter_rb_base); -        }; - -        _traffic_counter = -            std::make_shared<traffic_counter>(_tree, _root_path, write, read); -    } - -    void set_line_delay_cycles(int cycles) -    { -        sr_write(SR_LINE_RATE, uint32_t(cycles)); -    } - -    void set_bytes_per_packet(int bpp) -    { -        sr_write(SR_LINES_PER_PACKET, uint32_t(bpp / BYTES_PER_LINE)); -    } - -    double set_line_rate(double rate, double clock_rate) -    { -        int cycs_between_lines = clock_rate / rate - 1; -        if (cycs_between_lines > 0xFFFF) { -            cycs_between_lines = 0xFFFF; -            UHD_LOGGER_WARNING(unique_id()) -                << str(boost::format("Requested rate %f is larger than possible " -                                     "with the current clock rate (%.2f MHz).") -                       % rate % (clock_rate / 1e6)) -                << std::endl; -        } -        cycs_between_lines = std::max(0, cycs_between_lines); -        set_arg<int>("line_rate", cycs_between_lines); -        return _line_rate_from_reg_val(cycs_between_lines, clock_rate); -    } - -    double get_line_rate(double clock_rate) const -    { -        return _line_rate_from_reg_val(get_arg<int>("line_rate"), clock_rate); -    } - -    double _line_rate_from_reg_val(uint32_t reg_val, double clock_rate) const -    { -        return clock_rate / (reg_val + 1); -    } - -    void issue_stream_cmd(const uhd::stream_cmd_t& stream_cmd, const size_t) -    { -        if (not stream_cmd.stream_now) { -            throw uhd::not_implemented_error( -                "null_block does not support timed commands."); -        } -        switch (stream_cmd.stream_mode) { -            case uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS: -                sr_write(SR_ENABLE_STREAM, true); -                break; - -            case uhd::stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS: -                sr_write(SR_ENABLE_STREAM, false); -                break; - -            case uhd::stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_DONE: -            case uhd::stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_MORE: -                throw uhd::not_implemented_error( -                    "null_block does not support streaming modes other than CONTINUOUS"); - -            default: -                UHD_THROW_INVALID_CODE_PATH(); -        } -    } - -    void set_destination(uint32_t next_address, size_t output_block_port) -    { -        uhd::sid_t sid(next_address); -        if (sid.get_src() == 0) { -            sid.set_src(get_address()); -        } -        sr_write(SR_NEXT_DST_SID, sid.get(), output_block_port); -    } - -private: -    traffic_counter::sptr _traffic_counter; -}; - -UHD_RFNOC_BLOCK_REGISTER(null_block_ctrl, "NullSrcSink"); diff --git a/host/lib/rfnoc/radio_ctrl_impl.cpp b/host/lib/rfnoc/radio_ctrl_impl.cpp deleted file mode 100644 index 94c3e6ae0..000000000 --- a/host/lib/rfnoc/radio_ctrl_impl.cpp +++ /dev/null @@ -1,533 +0,0 @@ -// -// Copyright 2014-2016 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#include "../../transport/super_recv_packet_handler.hpp" -#include <uhd/convert.hpp> -#include <uhd/types/direction.hpp> -#include <uhd/types/ranges.hpp> -#include <uhd/utils/log.hpp> -#include <uhdlib/rfnoc/radio_ctrl_impl.hpp> -#include <uhdlib/rfnoc/wb_iface_adapter.hpp> -#include <boost/format.hpp> -#include <tuple> - -using namespace uhd; -using namespace uhd::rfnoc; - -static const size_t BYTES_PER_SAMPLE  = 4; -const std::string radio_ctrl::ALL_LOS = "all"; - -/**************************************************************************** - * Structors and init - ***************************************************************************/ -// Note: block_ctrl_base must be called before this, but has to be called by -// the derived class because of virtual inheritance -radio_ctrl_impl::radio_ctrl_impl() : _tick_rate(rfnoc::rate_node_ctrl::RATE_UNDEFINED) -{ -    _num_rx_channels      = get_output_ports().size(); -    _num_tx_channels      = get_input_ports().size(); -    _continuous_streaming = std::vector<bool>(2, false); - -    for (size_t i = 0; i < _num_rx_channels; i++) { -        _rx_streamer_active[i] = false; -    } -    for (size_t i = 0; i < _num_tx_channels; i++) { -        _tx_streamer_active[i] = false; -    } - -    ///////////////////////////////////////////////////////////////////////// -    // Setup peripherals -    ///////////////////////////////////////////////////////////////////////// -    for (size_t i = 0; i < _get_num_radios(); i++) { -        _register_loopback_self_test(i); -        _perifs[i].ctrl = this->get_ctrl_iface(i); -        // FIXME there's currently no way to set the underflow policy - -        if (i == 0) { -            time_core_3000::readback_bases_type time64_rb_bases; -            time64_rb_bases.rb_now = regs::rb_addr(regs::RB_TIME_NOW); -            time64_rb_bases.rb_pps = regs::rb_addr(regs::RB_TIME_PPS); -            _time64                = time_core_3000::make( -                _perifs[i].ctrl, regs::sr_addr(regs::TIME), time64_rb_bases); -            this->set_time_now(0.0); -        } - -        // Reset the RX control engine -        sr_write(regs::RX_CTRL_HALT, 1, i); -    } - -    //////////////////////////////////////////////////////////////////// -    // Register the time keeper -    //////////////////////////////////////////////////////////////////// -    if (not _tree->exists(fs_path("time") / "now")) { -        _tree->create<time_spec_t>(fs_path("time") / "now").set_publisher([this]() { -            return this->get_time_now(); -        }); -    } -    if (not _tree->exists(fs_path("time") / "pps")) { -        _tree->create<time_spec_t>(fs_path("time") / "pps").set_publisher([this]() { -            return this->get_time_last_pps(); -        }); -    } -    if (not _tree->exists(fs_path("time") / "cmd")) { -        _tree->create<time_spec_t>(fs_path("time") / "cmd"); -    } -    _tree->access<time_spec_t>(fs_path("time") / "now") -        .add_coerced_subscriber( -            [this](const time_spec_t& time_spec) { this->set_time_now(time_spec); }); -    _tree->access<time_spec_t>(fs_path("time") / "pps") -        .add_coerced_subscriber( -            [this](const time_spec_t& time_spec) { this->set_time_next_pps(time_spec); }); -    for (size_t i = 0; i < _get_num_radios(); i++) { -        _tree->access<time_spec_t>("time/cmd") -            .add_coerced_subscriber([this, i](const time_spec_t& time_spec) { -                this->set_command_tick_rate(this->_tick_rate, i); -                this->set_command_time(time_spec, i); -            }); -    } -    // spp gets created in the XML file -    _tree->access<int>(get_arg_path("spp") / "value") -        .add_coerced_subscriber([this](const int spp) { this->_update_spp(spp); }) -        .update(); -} - -void radio_ctrl_impl::_register_loopback_self_test(size_t chan) -{ -    size_t hash = size_t(time(NULL)); -    for (size_t i = 0; i < 100; i++) { -        boost::hash_combine(hash, i); -        sr_write(regs::TEST, uint32_t(hash), chan); -        uint32_t result = user_reg_read32(regs::RB_TEST, chan); -        if (result != uint32_t(hash)) { -            UHD_LOGGER_ERROR("RFNOC RADIO") << "Register loopback test failed"; -            UHD_LOGGER_ERROR("RFNOC RADIO") -                << boost::format("expected: %x result: %x") % uint32_t(hash) % result; -            return; // exit on any failure -        } -    } -    UHD_LOG_DEBUG(unique_id(), "Register loopback test passed"); -} - - -/**************************************************************************** - * API calls - ***************************************************************************/ -double radio_ctrl_impl::set_rate(double rate) -{ -    std::lock_guard<std::mutex> lock(_mutex); -    _tick_rate = rate; -    _time64->set_tick_rate(_tick_rate); -    _time64->self_test(); -    set_command_tick_rate(rate); -    return _tick_rate; -} - -void radio_ctrl_impl::set_tx_antenna(const std::string& ant, const size_t chan) -{ -    _tx_antenna[chan] = ant; -} - -void radio_ctrl_impl::set_rx_antenna(const std::string& ant, const size_t chan) -{ -    _rx_antenna[chan] = ant; -} - -double radio_ctrl_impl::set_tx_frequency(const double freq, const size_t chan) -{ -    return _tx_freq[chan] = freq; -} - -double radio_ctrl_impl::set_rx_frequency(const double freq, const size_t chan) -{ -    return _rx_freq[chan] = freq; -} - -double radio_ctrl_impl::set_tx_gain(const double gain, const size_t chan) -{ -    return _tx_gain[chan] = gain; -} - -double radio_ctrl_impl::set_rx_gain(const double gain, const size_t chan) -{ -    return _rx_gain[chan] = gain; -} - -double radio_ctrl_impl::set_tx_bandwidth(const double bandwidth, const size_t chan) -{ -    return _tx_bandwidth[chan] = bandwidth; -} - -double radio_ctrl_impl::set_rx_bandwidth(const double bandwidth, const size_t chan) -{ -    return _rx_bandwidth[chan] = bandwidth; -} - -void radio_ctrl_impl::set_time_sync(const uhd::time_spec_t& time) -{ -    _time64->set_time_sync(time); -} - -double radio_ctrl_impl::get_rate() const -{ -    return _tick_rate; -} - -std::string radio_ctrl_impl::get_tx_antenna(const size_t chan) /* const */ -{ -    return _tx_antenna.at(chan); -} - -std::string radio_ctrl_impl::get_rx_antenna(const size_t chan) /* const */ -{ -    return _rx_antenna.at(chan); -} - -double radio_ctrl_impl::get_tx_frequency(const size_t chan) /* const */ -{ -    return _tx_freq.at(chan); -} - -double radio_ctrl_impl::get_rx_frequency(const size_t chan) /* const */ -{ -    return _rx_freq.at(chan); -} - -double radio_ctrl_impl::get_tx_gain(const size_t chan) /* const */ -{ -    return _tx_gain.at(chan); -} - -double radio_ctrl_impl::get_rx_gain(const size_t chan) /* const */ -{ -    return _rx_gain.at(chan); -} - -double radio_ctrl_impl::get_tx_bandwidth(const size_t chan) /* const */ -{ -    return _tx_bandwidth.at(chan); -} - -double radio_ctrl_impl::get_rx_bandwidth(const size_t chan) /* const */ -{ -    return _rx_bandwidth.at(chan); -} - -/****************************************************************************** - * LO controls - *****************************************************************************/ -std::vector<std::string> radio_ctrl_impl::get_rx_lo_names(const size_t /* chan */) -{ -    return std::vector<std::string>(); -} - -std::vector<std::string> radio_ctrl_impl::get_rx_lo_sources( -    const std::string& /* name */, const size_t /* chan */) -{ -    return std::vector<std::string>(); -} - -freq_range_t radio_ctrl_impl::get_rx_lo_freq_range( -    const std::string& /* name */, const size_t /* chan */) -{ -    return freq_range_t(); -} - -void radio_ctrl_impl::set_rx_lo_source( -    const std::string& /* src */, const std::string& /* name */, const size_t /* chan */) -{ -    throw uhd::not_implemented_error("set_rx_lo_source is not supported on this radio"); -} - -const std::string radio_ctrl_impl::get_rx_lo_source( -    const std::string& /* name */, const size_t /* chan */) -{ -    return "internal"; -} - -void radio_ctrl_impl::set_rx_lo_export_enabled( -    bool /* enabled */, const std::string& /* name */, const size_t /* chan */) -{ -    throw uhd::not_implemented_error( -        "set_rx_lo_export_enabled is not supported on this radio"); -} - -bool radio_ctrl_impl::get_rx_lo_export_enabled( -    const std::string& /* name */, const size_t /* chan */) -{ -    return false; // Not exporting non-existant LOs -} - -double radio_ctrl_impl::set_rx_lo_freq( -    double /* freq */, const std::string& /* name */, const size_t /* chan */) -{ -    throw uhd::not_implemented_error("set_rx_lo_freq is not supported on this radio"); -} - -double radio_ctrl_impl::get_rx_lo_freq( -    const std::string& /* name */, const size_t /* chan */) -{ -    return 0; -} - -std::vector<std::string> radio_ctrl_impl::get_tx_lo_names(const size_t /* chan */ -) -{ -    return std::vector<std::string>(); -} - -std::vector<std::string> radio_ctrl_impl::get_tx_lo_sources( -    const std::string& /* name */, const size_t /* chan */ -) -{ -    return std::vector<std::string>(); -} - -freq_range_t radio_ctrl_impl::get_tx_lo_freq_range( -    const std::string& /* name */, const size_t /* chan */ -) -{ -    return freq_range_t(); -} - -void radio_ctrl_impl::set_tx_lo_source( -    const std::string& /* src */, const std::string& /* name */, const size_t /* chan */ -) -{ -    throw uhd::not_implemented_error("set_tx_lo_source is not supported on this radio"); -} - -const std::string radio_ctrl_impl::get_tx_lo_source( -    const std::string& /* name */, const size_t /* chan */ -) -{ -    return "internal"; -} - -void radio_ctrl_impl::set_tx_lo_export_enabled( -    const bool /* enabled */, const std::string& /* name */, const size_t /* chan */ -) -{ -    throw uhd::not_implemented_error( -        "set_tx_lo_export_enabled is not supported on this radio"); -} - -bool radio_ctrl_impl::get_tx_lo_export_enabled( -    const std::string& /* name */, const size_t /* chan */ -) -{ -    return false; // Not exporting non-existant LOs -} - -double radio_ctrl_impl::set_tx_lo_freq( -    const double /* freq */, const std::string& /* name */, const size_t /* chan */ -) -{ -    throw uhd::not_implemented_error("set_tx_lo_freq is not supported on this radio"); -} - -double radio_ctrl_impl::get_tx_lo_freq(const std::string& /* name */, const size_t chan) -{ -    return get_tx_frequency(chan); -} - -void radio_ctrl_impl::enable_rx_timestamps(const bool enable, const size_t chan) -{ -    const uint32_t output_format = 0 | (enable ? 0x01 : 0x00); -    sr_write(regs::RX_CTRL_OUTPUT_FORMAT, output_format, chan); -} - -/*********************************************************************** - * RX Streamer-related methods (from source_block_ctrl_base) - **********************************************************************/ -//! Pass stream commands to the radio -void radio_ctrl_impl::issue_stream_cmd( -    const uhd::stream_cmd_t& stream_cmd, const size_t chan) -{ -    std::lock_guard<std::mutex> lock(_mutex); -    UHD_RFNOC_BLOCK_TRACE() << "radio_ctrl_impl::issue_stream_cmd() " << chan << " " -                            << char(stream_cmd.stream_mode); -    if (not _is_streamer_active(uhd::RX_DIRECTION, chan)) { -        UHD_RFNOC_BLOCK_TRACE() -            << "radio_ctrl_impl::issue_stream_cmd() called on inactive " -               "channel. Skipping."; -        return; -    } -    constexpr size_t max_num_samps = 0x0fffffff; -    if (stream_cmd.num_samps > max_num_samps) { -        UHD_LOG_ERROR("RFNOC RADIO", -            "Requesting too many samples in a single burst! " -            "Requested " -                + std::to_string(stream_cmd.num_samps) -                + ", maximum " -                  "is " -                + std::to_string(max_num_samps) + "."); -        UHD_LOG_INFO("RFNOC RADIO", -            "Note that a decimation block will increase the number of samples " -            "per burst by the decimation factor. Your application may have " -            "requested fewer samples."); -        throw uhd::value_error("Requested too many samples in a single burst."); -    } -    _continuous_streaming[chan] = -        (stream_cmd.stream_mode == stream_cmd_t::STREAM_MODE_START_CONTINUOUS); - -    // setup the mode to instruction flags -    typedef std::tuple<bool, bool, bool, bool> inst_t; -    static const std::map<stream_cmd_t::stream_mode_t, inst_t> mode_to_inst{ -        // reload, chain, samps, stop -        {stream_cmd_t::STREAM_MODE_START_CONTINUOUS, inst_t(true, true, false, false)}, -        {stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS, inst_t(false, false, false, true)}, -        {stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_DONE, inst_t(false, false, true, false)}, -        {stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_MORE, inst_t(false, true, true, false)}}; - -    // setup the instruction flag values -    bool inst_reload, inst_chain, inst_samps, inst_stop; -    std::tie(inst_reload, inst_chain, inst_samps, inst_stop) = -        mode_to_inst.at(stream_cmd.stream_mode); - -    // calculate the word from flags and length -    const uint32_t cmd_word = -        0 | (uint32_t((stream_cmd.stream_now) ? 1 : 0) << 31) -        | (uint32_t((inst_chain) ? 1 : 0) << 30) | (uint32_t((inst_reload) ? 1 : 0) << 29) -        | (uint32_t((inst_stop) ? 1 : 0) << 28) -        | ((inst_samps) ? stream_cmd.num_samps : ((inst_stop) ? 0 : 1)); - -    // issue the stream command -    const uint64_t ticks = -        (stream_cmd.stream_now) ? 0 : stream_cmd.time_spec.to_ticks(get_rate()); -    sr_write(regs::RX_CTRL_CMD, cmd_word, chan); -    sr_write(regs::RX_CTRL_TIME_HI, uint32_t(ticks >> 32), chan); -    sr_write(regs::RX_CTRL_TIME_LO, uint32_t(ticks >> 0), chan); // latches the command -} - -std::vector<size_t> radio_ctrl_impl::get_active_rx_ports() -{ -    std::vector<size_t> active_rx_ports; -    typedef std::map<size_t, bool> map_t; -    for (map_t::value_type& m : _rx_streamer_active) { -        if (m.second) { -            active_rx_ports.push_back(m.first); -        } -    } -    return active_rx_ports; -} - -/*********************************************************************** - * Radio controls (radio_ctrl specific) - **********************************************************************/ -void radio_ctrl_impl::set_rx_streamer(bool active, const size_t port) -{ -    UHD_RFNOC_BLOCK_TRACE() << "radio_ctrl_impl::set_rx_streamer() " << port << " -> " -                            << active; -    if (port > _num_rx_channels) { -        throw uhd::value_error(str( -            boost::format("[%s] Can't (un)register RX streamer on port %d (invalid port)") -            % unique_id() % port)); -    } -    _rx_streamer_active[port] = active; -    if (not check_radio_config()) { -        throw std::runtime_error( -            str(boost::format("[%s]: Invalid radio configuration.") % unique_id())); -    } -} - -void radio_ctrl_impl::set_tx_streamer(bool active, const size_t port) -{ -    UHD_RFNOC_BLOCK_TRACE() << "radio_ctrl_impl::set_tx_streamer() " << port << " -> " -                            << active; -    if (port > _num_tx_channels) { -        throw uhd::value_error(str( -            boost::format("[%s] Can't (un)register TX streamer on port %d (invalid port)") -            % unique_id() % port)); -    } -    _tx_streamer_active[port] = active; -    if (not check_radio_config()) { -        throw std::runtime_error( -            str(boost::format("[%s]: Invalid radio configuration.") % unique_id())); -    } -} - -// Subscribers to block args: -// TODO move to nocscript -void radio_ctrl_impl::_update_spp(int spp) -{ -    std::lock_guard<std::mutex> lock(_mutex); -    UHD_RFNOC_BLOCK_TRACE() << "radio_ctrl_impl::_update_spp(): Requested spp: " << spp; -    if (spp == 0) { -        spp = DEFAULT_PACKET_SIZE / BYTES_PER_SAMPLE; -    } -    UHD_RFNOC_BLOCK_TRACE() << "radio_ctrl_impl::_update_spp(): Setting spp to: " << spp; -    for (size_t i = 0; i < _num_rx_channels; i++) { -        sr_write(regs::RX_CTRL_MAXLEN, uint32_t(spp), i); -    } -} - -void radio_ctrl_impl::set_time_now(const time_spec_t& time_spec) -{ -    _time64->set_time_now(time_spec); -} - -void radio_ctrl_impl::set_time_next_pps(const time_spec_t& time_spec) -{ -    _time64->set_time_next_pps(time_spec); -} - -time_spec_t radio_ctrl_impl::get_time_now() -{ -    return _time64->get_time_now(); -} - -time_spec_t radio_ctrl_impl::get_time_last_pps() -{ -    return _time64->get_time_last_pps(); -} - -void radio_ctrl_impl::set_time_source(const std::string& source) -{ -    _tree->access<std::string>("time_source/value").set(source); -} - -std::string radio_ctrl_impl::get_time_source() -{ -    return _tree->access<std::string>("time_source/value").get(); -} - -std::vector<std::string> radio_ctrl_impl::get_time_sources() -{ -    return _tree->access<std::vector<std::string>>("time_source/options").get(); -} - -void radio_ctrl_impl::set_clock_source(const std::string& source) -{ -    _tree->access<std::string>("clock_source/value").set(source); -} - -std::string radio_ctrl_impl::get_clock_source() -{ -    return _tree->access<std::string>("clock_source/value").get(); -} - -std::vector<std::string> radio_ctrl_impl::get_clock_sources() -{ -    return _tree->access<std::vector<std::string>>("clock_source/options").get(); -} - - -std::vector<std::string> radio_ctrl_impl::get_gpio_banks() const -{ -    return std::vector<std::string>(); -} - -void radio_ctrl_impl::set_gpio_attr( -    const std::string&, const std::string&, const uint32_t, const uint32_t) -{ -    throw uhd::not_implemented_error("set_gpio_attr was not defined for this radio"); -} - -uint32_t radio_ctrl_impl::get_gpio_attr(const std::string&, const std::string&) -{ -    throw uhd::not_implemented_error("get_gpio_attr was not defined for this radio"); -} diff --git a/host/lib/rfnoc/rate_node_ctrl.cpp b/host/lib/rfnoc/rate_node_ctrl.cpp deleted file mode 100644 index 08abf4f78..000000000 --- a/host/lib/rfnoc/rate_node_ctrl.cpp +++ /dev/null @@ -1,51 +0,0 @@ -// -// Copyright 2014-2015 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#include <uhd/rfnoc/rate_node_ctrl.hpp> -#include <boost/bind.hpp> - -using namespace uhd::rfnoc; - -const double rate_node_ctrl::RATE_UNDEFINED = -1.0; - -static double _get_input_samp_rate(rate_node_ctrl::sptr node, size_t port) -{ -    return node->get_input_samp_rate(port); -} - -static double _get_output_samp_rate(rate_node_ctrl::sptr node, size_t port) -{ -    return node->get_output_samp_rate(port); -} - - -// FIXME add recursion limiters (i.e. list of explored nodes) -double rate_node_ctrl::get_input_samp_rate(size_t /* port */ -) -{ -    try { -        return find_downstream_unique_property<rate_node_ctrl, double>( -            boost::bind(_get_input_samp_rate, _1, _2), RATE_UNDEFINED); -    } catch (const uhd::runtime_error& ex) { -        throw uhd::runtime_error( -            str(boost::format("Multiple sampling rates downstream of %s: %s.") -                % unique_id() % ex.what())); -    } -} - -double rate_node_ctrl::get_output_samp_rate(size_t /* port */ -) -{ -    try { -        return find_upstream_unique_property<rate_node_ctrl, double>( -            boost::bind(_get_output_samp_rate, _1, _2), RATE_UNDEFINED); -    } catch (const uhd::runtime_error& ex) { -        throw uhd::runtime_error( -            str(boost::format("Multiple sampling rates upstream of %s: %s.") % unique_id() -                % ex.what())); -    } -} diff --git a/host/lib/rfnoc/rx_stream_terminator.cpp b/host/lib/rfnoc/rx_stream_terminator.cpp deleted file mode 100644 index 18ecb4974..000000000 --- a/host/lib/rfnoc/rx_stream_terminator.cpp +++ /dev/null @@ -1,134 +0,0 @@ -// -// Copyright 2014 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#include "../transport/super_recv_packet_handler.hpp" -#include <uhd/rfnoc/source_node_ctrl.hpp> -#include <uhd/utils/log.hpp> -#include <uhdlib/rfnoc/radio_ctrl_impl.hpp> -#include <uhdlib/rfnoc/rx_stream_terminator.hpp> -#include <boost/format.hpp> - -using namespace uhd::rfnoc; - -size_t rx_stream_terminator::_count = 0; - -rx_stream_terminator::rx_stream_terminator() -    : _term_index(_count) -    , _samp_rate(rate_node_ctrl::RATE_UNDEFINED) -    , _tick_rate(tick_node_ctrl::RATE_UNDEFINED) -{ -    _count++; -} - -std::string rx_stream_terminator::unique_id() const -{ -    return str(boost::format("RX Terminator %d") % _term_index); -} - -void rx_stream_terminator::set_tx_streamer(bool, const size_t) -{ -    /* nop */ -} - -void rx_stream_terminator::set_rx_streamer(bool active, const size_t) -{ -    // TODO this is identical to source_node_ctrl::set_rx_streamer() -> factor out -    UHD_RFNOC_BLOCK_TRACE() << "rx_stream_terminator::set_rx_streamer() " << active; -    for (const node_ctrl_base::node_map_pair_t upstream_node : _upstream_nodes) { -        source_node_ctrl::sptr curr_upstream_block_ctrl = -            boost::dynamic_pointer_cast<source_node_ctrl>(upstream_node.second.lock()); -        if (curr_upstream_block_ctrl) { -            curr_upstream_block_ctrl->set_rx_streamer( -                active, get_upstream_port(upstream_node.first)); -        } -        _rx_streamer_active[upstream_node.first] = active; -    } -} - -void rx_stream_terminator::handle_overrun( -    boost::weak_ptr<uhd::rx_streamer> streamer, const size_t) -{ -    std::unique_lock<std::mutex> l(_overrun_handler_mutex, std::defer_lock); -    if (!l.try_lock()) { -        // We're already handling overruns, so just stop right there -        return; -    } - -    std::vector<boost::shared_ptr<uhd::rfnoc::radio_ctrl_impl>> upstream_radio_nodes = -        find_upstream_node<uhd::rfnoc::radio_ctrl_impl>(); -    const size_t n_radios = upstream_radio_nodes.size(); -    if (n_radios == 0) { -        return; -    } - -    UHD_RFNOC_BLOCK_TRACE() << "rx_stream_terminator::handle_overrun()"; -    boost::shared_ptr<uhd::transport::sph::recv_packet_streamer> my_streamer = -        boost::dynamic_pointer_cast<uhd::transport::sph::recv_packet_streamer>( -            streamer.lock()); -    if (not my_streamer) -        return; // If the rx_streamer has expired then overflow handling makes no sense. - -    bool in_continuous_streaming_mode = true; -    int num_channels                  = 0; -    for (const boost::shared_ptr<uhd::rfnoc::radio_ctrl_impl>& node : -        upstream_radio_nodes) { -        num_channels += node->get_active_rx_ports().size(); -        for (const size_t port : node->get_active_rx_ports()) { -            in_continuous_streaming_mode = in_continuous_streaming_mode -                                           && node->in_continuous_streaming_mode(port); -        } -    } -    if (num_channels == 0) { -        return; -    } - -    if (num_channels == 1 and in_continuous_streaming_mode) { -        std::vector<size_t> active_rx_ports = -            upstream_radio_nodes[0]->get_active_rx_ports(); -        if (active_rx_ports.empty()) { -            return; -        } -        const size_t port = active_rx_ports[0]; -        upstream_radio_nodes[0]->issue_stream_cmd( -            stream_cmd_t::STREAM_MODE_START_CONTINUOUS, port); -        return; -    } - -    ///////////////////////////////////////////////////////////// -    // MIMO overflow recovery time -    ///////////////////////////////////////////////////////////// -    for (const boost::shared_ptr<uhd::rfnoc::radio_ctrl_impl>& node : -        upstream_radio_nodes) { -        for (const size_t port : node->get_active_rx_ports()) { -            // check all the ports on all the radios -            node->rx_ctrl_clear_cmds(port); -            node->issue_stream_cmd(stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS, port); -        } -    } -    // flush transports -    my_streamer->flush_all(0.001); // TODO flushing will probably have to go away. -    // restart streaming on all channels -    if (in_continuous_streaming_mode) { -        stream_cmd_t stream_cmd(stream_cmd_t::STREAM_MODE_START_CONTINUOUS); -        stream_cmd.stream_now = false; -        stream_cmd.time_spec = -            upstream_radio_nodes[0]->get_time_now() + time_spec_t(0.05); - -        for (const boost::shared_ptr<uhd::rfnoc::radio_ctrl_impl>& node : -            upstream_radio_nodes) { -            for (const size_t port : node->get_active_rx_ports()) { -                node->issue_stream_cmd(stream_cmd, port); -            } -        } -    } -} - -rx_stream_terminator::~rx_stream_terminator() -{ -    UHD_RFNOC_BLOCK_TRACE() << "rx_stream_terminator::~rx_stream_terminator() "; -    set_rx_streamer(false, 0); -} diff --git a/host/lib/rfnoc/scalar_node_ctrl.cpp b/host/lib/rfnoc/scalar_node_ctrl.cpp deleted file mode 100644 index f197da0b5..000000000 --- a/host/lib/rfnoc/scalar_node_ctrl.cpp +++ /dev/null @@ -1,50 +0,0 @@ -// -// Copyright 2014-2015 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#include <uhd/rfnoc/scalar_node_ctrl.hpp> -#include <boost/bind.hpp> - -using namespace uhd::rfnoc; - -const double scalar_node_ctrl::SCALE_UNDEFINED = -1.0; - -static double _get_input_factor(scalar_node_ctrl::sptr node, size_t port) -{ -    return node->get_input_scale_factor(port); -} - -static double _get_output_factor(scalar_node_ctrl::sptr node, size_t port) -{ -    return node->get_output_scale_factor(port); -} - -// FIXME add recursion limiters (i.e. list of explored nodes) -double scalar_node_ctrl::get_input_scale_factor(size_t /* port */ -) -{ -    try { -        return find_downstream_unique_property<scalar_node_ctrl, double>( -            boost::bind(_get_input_factor, _1, _2), SCALE_UNDEFINED); -    } catch (const uhd::runtime_error& ex) { -        throw uhd::runtime_error( -            str(boost::format("Multiple scaling factors rates downstream of %s: %s.") -                % unique_id() % ex.what())); -    } -} - -double scalar_node_ctrl::get_output_scale_factor(size_t /* port */ -) -{ -    try { -        return find_upstream_unique_property<scalar_node_ctrl, double>( -            boost::bind(_get_output_factor, _1, _2), SCALE_UNDEFINED); -    } catch (const uhd::runtime_error& ex) { -        throw uhd::runtime_error( -            str(boost::format("Multiple scaling factors rates upstream of %s: %s.") -                % unique_id() % ex.what())); -    } -} diff --git a/host/lib/rfnoc/siggen_block_ctrl_impl.cpp b/host/lib/rfnoc/siggen_block_ctrl_impl.cpp deleted file mode 100644 index dc4035962..000000000 --- a/host/lib/rfnoc/siggen_block_ctrl_impl.cpp +++ /dev/null @@ -1,48 +0,0 @@ -// -// Copyright 2016-2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#include <uhd/rfnoc/siggen_block_ctrl.hpp> -#include <uhd/utils/log.hpp> -#include <boost/format.hpp> - -using namespace uhd::rfnoc; - -class siggen_block_ctrl_impl : public siggen_block_ctrl -{ -public: -    UHD_RFNOC_BLOCK_CONSTRUCTOR(siggen_block_ctrl) -    { -        // nop -    } - -    void issue_stream_cmd(const uhd::stream_cmd_t& stream_cmd, const size_t) -    { -        UHD_LOGGER_TRACE(unique_id()) << "issue_stream_cmd()" << std::endl; -        if (not stream_cmd.stream_now) { -            throw uhd::not_implemented_error( -                "siggen_block does not support timed commands."); -        } -        switch (stream_cmd.stream_mode) { -            case uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS: -                sr_write("ENABLE", true); -                break; - -            case uhd::stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS: -                sr_write("ENABLE", false); -                break; - -            case uhd::stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_DONE: -            case uhd::stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_MORE: -                throw uhd::not_implemented_error("siggen_block does not support " -                                                 "streaming modes other than CONTINUOUS"); - -            default: -                UHD_THROW_INVALID_CODE_PATH(); -        } -    } -}; - -UHD_RFNOC_BLOCK_REGISTER(siggen_block_ctrl, "SigGen"); diff --git a/host/lib/rfnoc/sink_block_ctrl_base.cpp b/host/lib/rfnoc/sink_block_ctrl_base.cpp deleted file mode 100644 index f1d65350a..000000000 --- a/host/lib/rfnoc/sink_block_ctrl_base.cpp +++ /dev/null @@ -1,105 +0,0 @@ -// -// Copyright 2014 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#include <uhd/rfnoc/constants.hpp> -#include <uhd/rfnoc/sink_block_ctrl_base.hpp> -#include <uhd/utils/log.hpp> -#include <uhdlib/rfnoc/utils.hpp> - -using namespace uhd; -using namespace uhd::rfnoc; - - -/*********************************************************************** - * Stream signatures - **********************************************************************/ -stream_sig_t sink_block_ctrl_base::get_input_signature(size_t block_port) const -{ -    if (not _tree->exists(_root_path / "ports" / "in" / block_port)) { -        throw uhd::runtime_error(str(boost::format("Invalid port number %d for block %s") -                                     % block_port % unique_id())); -    } - -    return _resolve_port_def( -        _tree->access<blockdef::port_t>(_root_path / "ports" / "in" / block_port).get()); -} - -std::vector<size_t> sink_block_ctrl_base::get_input_ports() const -{ -    std::vector<size_t> input_ports; -    input_ports.reserve(_tree->list(_root_path / "ports" / "in").size()); -    for (const std::string port : _tree->list(_root_path / "ports" / "in")) { -        input_ports.push_back(boost::lexical_cast<size_t>(port)); -    } -    return input_ports; -} - -/*********************************************************************** - * FPGA Configuration - **********************************************************************/ -size_t sink_block_ctrl_base::get_fifo_size(size_t block_port) const -{ -    if (_tree->exists(_root_path / "input_buffer_size" / std::to_string(block_port))) { -        return _tree -            ->access<size_t>( -                _root_path / "input_buffer_size" / std::to_string(block_port)) -            .get(); -    } -    return 0; -} - -size_t sink_block_ctrl_base::get_mtu(size_t block_port) const -{ -    if (_tree->exists(_root_path / "mtu" / std::to_string(block_port))) { -        return _tree->access<size_t>(_root_path / "mtu" / std::to_string(block_port)) -            .get(); -    } -    return 0; -} - -void sink_block_ctrl_base::configure_flow_control_in( -    const size_t bytes, const size_t block_port) -{ -    UHD_RFNOC_BLOCK_TRACE() -        << boost::format("sink_block_ctrl_base::configure_flow_control_in(bytes=%d)") -               % bytes; - -    uint32_t bytes_word = 0; -    if (bytes) { -        // Bit 32 enables flow control -        bytes_word = (1 << 31) | bytes; -    } -    sr_write(SR_FLOW_CTRL_BYTES_PER_ACK, bytes_word, block_port); -} - -void sink_block_ctrl_base::set_error_policy(const std::string& policy) -{ -    if (policy == "next_packet") { -        sr_write(SR_ERROR_POLICY, (1 << 2) | 1); -    } else if (policy == "next_burst") { -        sr_write(SR_ERROR_POLICY, (1 << 3) | 1); -    } else if (policy == "continue") { -        sr_write(SR_ERROR_POLICY, (1 << 1) | 1); -    } else if (policy == "wait") { -        sr_write(SR_ERROR_POLICY, 1); -    } else -        throw uhd::value_error( -            "Block input cannot handle requested error policy: " + policy); -} - -/*********************************************************************** - * Hooks - **********************************************************************/ -size_t sink_block_ctrl_base::_request_input_port( -    const size_t suggested_port, const uhd::device_addr_t&) const -{ -    const std::set<size_t> valid_input_ports = -        utils::str_list_to_set<size_t>(_tree->list(_root_path / "ports" / "in")); -    return utils::node_map_find_first_free( -        _upstream_nodes, suggested_port, valid_input_ports); -} -// vim: sw=4 et: diff --git a/host/lib/rfnoc/sink_node_ctrl.cpp b/host/lib/rfnoc/sink_node_ctrl.cpp deleted file mode 100644 index 53a26d7ed..000000000 --- a/host/lib/rfnoc/sink_node_ctrl.cpp +++ /dev/null @@ -1,80 +0,0 @@ -// -// Copyright 2014 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#include <uhd/rfnoc/sink_node_ctrl.hpp> -#include <uhd/rfnoc/source_node_ctrl.hpp> -#include <uhd/utils/log.hpp> -#include <uhdlib/rfnoc/utils.hpp> - -using namespace uhd::rfnoc; - -size_t sink_node_ctrl::connect_upstream( -    node_ctrl_base::sptr upstream_node, size_t port, const uhd::device_addr_t& args) -{ -    boost::mutex::scoped_lock lock(_input_mutex); -    port = _request_input_port(port, args); -    _register_upstream_node(upstream_node, port); -    return port; -} - -void sink_node_ctrl::set_tx_streamer(bool active, const size_t port) -{ -    UHD_RFNOC_BLOCK_TRACE() << "sink_node_ctrl::set_tx_streamer() " << active << " " -                            << port; - -    /* Enable all downstream connections: -    for(const node_ctrl_base::node_map_pair_t downstream_node:  list_downstream_nodes()) { -        sptr curr_downstream_block_ctrl = -            boost::dynamic_pointer_cast<sink_node_ctrl>(downstream_node.second.lock()); -        if (curr_downstream_block_ctrl) { -            curr_downstream_block_ctrl->set_tx_streamer( -                    active, -                    get_downstream_port(downstream_node.first) -            ); -        } -    } -    */ - -    // Only enable 1:1 -    if (list_downstream_nodes().count(port)) { -        sink_node_ctrl::sptr this_downstream_block_ctrl = -            boost::dynamic_pointer_cast<sink_node_ctrl>( -                list_downstream_nodes().at(port).lock()); -        if (this_downstream_block_ctrl) { -            this_downstream_block_ctrl->set_tx_streamer( -                active, get_downstream_port(port)); -        } -    } - -    _tx_streamer_active[port] = active; -} - -size_t sink_node_ctrl::_request_input_port( -    const size_t suggested_port, const uhd::device_addr_t&) const -{ -    return utils::node_map_find_first_free(_upstream_nodes, suggested_port); -} - -void sink_node_ctrl::_register_upstream_node( -    node_ctrl_base::sptr upstream_node, size_t port) -{ -    // Do all the checks: -    if (port == ANY_PORT) { -        throw uhd::type_error("Invalid input port number."); -    } -    if (_upstream_nodes.count(port) and not _upstream_nodes[port].expired()) { -        throw uhd::runtime_error( -            str(boost::format("On node %s, input port %d is already connected.") -                % unique_id() % port)); -    } -    if (not boost::dynamic_pointer_cast<source_node_ctrl>(upstream_node)) { -        throw uhd::type_error("Attempting to register a non-source block as upstream."); -    } -    // Alles klar, Herr Kommissar :) - -    _upstream_nodes[port] = boost::weak_ptr<node_ctrl_base>(upstream_node); -} diff --git a/host/lib/rfnoc/source_block_ctrl_base.cpp b/host/lib/rfnoc/source_block_ctrl_base.cpp deleted file mode 100644 index 2ddb455a1..000000000 --- a/host/lib/rfnoc/source_block_ctrl_base.cpp +++ /dev/null @@ -1,148 +0,0 @@ -// -// Copyright 2014 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#include <uhd/rfnoc/constants.hpp> -#include <uhd/rfnoc/source_block_ctrl_base.hpp> -#include <uhd/utils/log.hpp> -#include <uhdlib/rfnoc/utils.hpp> -#include <chrono> -#include <thread> - -using namespace uhd; -using namespace uhd::rfnoc; - -/*********************************************************************** - * Streaming operations - **********************************************************************/ -void source_block_ctrl_base::issue_stream_cmd( -    const uhd::stream_cmd_t& stream_cmd, const size_t chan) -{ -    UHD_RFNOC_BLOCK_TRACE() << "source_block_ctrl_base::issue_stream_cmd()"; -    if (_upstream_nodes.empty()) { -        UHD_LOGGER_WARNING("RFNOC") -            << "issue_stream_cmd() not implemented for " << get_block_id(); -        return; -    } - -    for (const node_ctrl_base::node_map_pair_t upstream_node : _upstream_nodes) { -        // FIXME:  Need proper mapping from input port to output port -        // The code below assumes the input port and output port are the same -        // if the number of upstream and downstream ports are the same. -        // The stream command is limited to only that port to prevent issuing -        // it on the wrong block and port. -        if (_num_input_ports == _num_output_ports -            and upstream_node.first != chan) { -            continue; -        } -        source_node_ctrl::sptr this_upstream_block_ctrl = -            boost::dynamic_pointer_cast<source_node_ctrl>(upstream_node.second.lock()); -        if (this_upstream_block_ctrl) { -            this_upstream_block_ctrl->issue_stream_cmd( -                stream_cmd, get_upstream_port(upstream_node.first)); -        } -    } -} - -/*********************************************************************** - * Stream signatures - **********************************************************************/ -stream_sig_t source_block_ctrl_base::get_output_signature(size_t block_port) const -{ -    if (not _tree->exists(_root_path / "ports" / "out" / block_port)) { -        throw uhd::runtime_error(str(boost::format("Invalid port number %d for block %s") -                                     % block_port % unique_id())); -    } - -    return _resolve_port_def( -        _tree->access<blockdef::port_t>(_root_path / "ports" / "out" / block_port).get()); -} - -std::vector<size_t> source_block_ctrl_base::get_output_ports() const -{ -    std::vector<size_t> output_ports; -    output_ports.reserve(_tree->list(_root_path / "ports" / "out").size()); -    for (const std::string port : _tree->list(_root_path / "ports" / "out")) { -        output_ports.push_back(boost::lexical_cast<size_t>(port)); -    } -    return output_ports; -} - -/*********************************************************************** - * FPGA Configuration - **********************************************************************/ -void source_block_ctrl_base::set_destination( -    uint32_t next_address, size_t output_block_port) -{ -    UHD_RFNOC_BLOCK_TRACE() << "source_block_ctrl_base::set_destination() " -                            << uhd::sid_t(next_address); -    sid_t new_sid(next_address); -    new_sid.set_src(get_address(output_block_port)); -    UHD_RFNOC_BLOCK_TRACE() << "  Setting SID: " << new_sid << "  "; -    sr_write(SR_NEXT_DST_SID, (1 << 16) | next_address, output_block_port); -} - -void source_block_ctrl_base::configure_flow_control_out(const bool enable_fc_output, -    const bool lossless_link, -    const size_t buf_size_bytes, -    const size_t pkt_limit, -    const size_t block_port, -    UHD_UNUSED(const uhd::sid_t& sid)) -{ -    UHD_RFNOC_BLOCK_TRACE() -        << "source_block_ctrl_base::configure_flow_control_out() buf_size_bytes==" -        << buf_size_bytes; -    if (buf_size_bytes == 0) { -        throw uhd::runtime_error( -            str(boost::format( -                    "Invalid window size %d for block %s. Window size cannot be 0 bytes.") -                % buf_size_bytes % unique_id())); -    } - -    // Enable source flow control module and conditionally enable byte based and/or packet -    // count based flow control -    const bool enable_byte_fc    = (buf_size_bytes != 0); -    const bool enable_pkt_cnt_fc = (pkt_limit != 0); -    const uint32_t config = (enable_fc_output ? 1 : 0) | ((enable_byte_fc ? 1 : 0) << 1) -                            | ((enable_pkt_cnt_fc ? 1 : 0) << 2) -                            | ((lossless_link ? 1 : 0) << 3); - -    // Resize the FC window. -    // Precondition: No data can be buffered upstream. -    if (enable_byte_fc) { -        sr_write(SR_FLOW_CTRL_WINDOW_SIZE, buf_size_bytes, block_port); -    } -    if (enable_pkt_cnt_fc) { -        sr_write(SR_FLOW_CTRL_PKT_LIMIT, pkt_limit, block_port); -    } - -    // Enable the FC window. -    // Precondition: The window size and/or packet limit must be set. -    sr_write(SR_FLOW_CTRL_EN, config, block_port); -} - -size_t source_block_ctrl_base::get_mtu(size_t block_port) const -{ -    if (_tree->exists(_root_path / "mtu" / std::to_string(block_port))) { -        return _tree->access<size_t>(_root_path / "mtu" / std::to_string(block_port)) -            .get(); -    } -    return 0; -} - - -/*********************************************************************** - * Hooks - **********************************************************************/ -size_t source_block_ctrl_base::_request_output_port( -    const size_t suggested_port, const uhd::device_addr_t&) const -{ -    const std::set<size_t> valid_output_ports = -        utils::str_list_to_set<size_t>(_tree->list(_root_path / "ports" / "out")); -    return utils::node_map_find_first_free( -        _downstream_nodes, suggested_port, valid_output_ports); -} -// vim: sw=4 et: diff --git a/host/lib/rfnoc/source_node_ctrl.cpp b/host/lib/rfnoc/source_node_ctrl.cpp deleted file mode 100644 index 23a17a463..000000000 --- a/host/lib/rfnoc/source_node_ctrl.cpp +++ /dev/null @@ -1,80 +0,0 @@ -// -// Copyright 2014 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#include <uhd/rfnoc/sink_node_ctrl.hpp> -#include <uhd/rfnoc/source_node_ctrl.hpp> -#include <uhd/utils/log.hpp> -#include <uhdlib/rfnoc/utils.hpp> - -using namespace uhd::rfnoc; - -size_t source_node_ctrl::connect_downstream( -    node_ctrl_base::sptr downstream_node, size_t port, const uhd::device_addr_t& args) -{ -    boost::mutex::scoped_lock lock(_output_mutex); -    port = _request_output_port(port, args); -    _register_downstream_node(downstream_node, port); -    return port; -} - -void source_node_ctrl::set_rx_streamer(bool active, const size_t port) -{ -    UHD_RFNOC_BLOCK_TRACE() << "source_node_ctrl::set_rx_streamer() " << port << " -> " -                            << active; - -    /* This will enable all upstream blocks: -    for(const node_ctrl_base::node_map_pair_t upstream_node:  list_upstream_nodes()) { -        sptr curr_upstream_block_ctrl = -            boost::dynamic_pointer_cast<source_node_ctrl>(upstream_node.second.lock()); -        if (curr_upstream_block_ctrl) { -            curr_upstream_block_ctrl->set_rx_streamer( -                    active, -                    get_upstream_port(upstream_node.first) -            ); -        } -    } -    */ - -    // This only enables 1:1 (if output 1 is enabled, enable what's connected to input 1) -    if (list_upstream_nodes().count(port)) { -        source_node_ctrl::sptr this_upstream_block_ctrl = -            boost::dynamic_pointer_cast<source_node_ctrl>( -                list_upstream_nodes().at(port).lock()); -        if (this_upstream_block_ctrl) { -            this_upstream_block_ctrl->set_rx_streamer(active, get_upstream_port(port)); -        } -    } - -    _rx_streamer_active[port] = active; -} - -size_t source_node_ctrl::_request_output_port( -    const size_t suggested_port, const uhd::device_addr_t&) const -{ -    return utils::node_map_find_first_free(_downstream_nodes, suggested_port); -} - -void source_node_ctrl::_register_downstream_node( -    node_ctrl_base::sptr downstream_node, size_t port) -{ -    // Do all the checks: -    if (port == ANY_PORT) { -        throw uhd::type_error( -            str(boost::format("[%s] Invalid output port number (ANY).") % unique_id())); -    } -    if (_downstream_nodes.count(port) and not _downstream_nodes[port].expired()) { -        throw uhd::runtime_error( -            str(boost::format("On node %s, output port %d is already connected.") -                % unique_id() % port)); -    } -    if (not boost::dynamic_pointer_cast<sink_node_ctrl>(downstream_node)) { -        throw uhd::type_error("Attempting to register a non-sink block as downstream."); -    } -    // Alles klar, Herr Kommissar :) - -    _downstream_nodes[port] = boost::weak_ptr<node_ctrl_base>(downstream_node); -} diff --git a/host/lib/rfnoc/stream_sig.cpp b/host/lib/rfnoc/stream_sig.cpp deleted file mode 100644 index 55d1cb005..000000000 --- a/host/lib/rfnoc/stream_sig.cpp +++ /dev/null @@ -1,66 +0,0 @@ -// -// Copyright 2014 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#include <uhd/convert.hpp> -#include <uhd/rfnoc/stream_sig.hpp> -#include <boost/format.hpp> - -using namespace uhd::rfnoc; - -stream_sig_t::stream_sig_t() : item_type(""), vlen(0), packet_size(0), is_bursty(false) -{ -    // nop -} - -std::string stream_sig_t::to_string() -{ -    return str( -        boost::format("%s,vlen=%d,packet_size=%d") % item_type % vlen % packet_size); -} - -std::string stream_sig_t::to_pp_string() -{ -    return str(boost::format("Data type: %s  | Vector Length: %d | Packet size: %d") -               % item_type % vlen % packet_size); -} - -size_t stream_sig_t::get_bytes_per_item() const -{ -    if (item_type == "") { -        return 0; -    } - -    return uhd::convert::get_bytes_per_item(item_type); -} - -bool stream_sig_t::is_compatible( -    const stream_sig_t& output_sig, const stream_sig_t& input_sig) -{ -    /// Item types: -    if (not(input_sig.item_type.empty() or output_sig.item_type.empty()) -        and input_sig.item_type != output_sig.item_type) { -        return false; -    } - -    /// Vector lengths -    if (output_sig.vlen and input_sig.vlen) { -        if (input_sig.vlen != output_sig.vlen) { -            return false; -        } -    } - -    /// Packet sizes -    if (output_sig.packet_size and input_sig.packet_size) { -        if (input_sig.packet_size != output_sig.packet_size) { -            return false; -        } -    } - -    // You may pass -    return true; -} -// vim: sw=4 et: diff --git a/host/lib/rfnoc/tick_node_ctrl.cpp b/host/lib/rfnoc/tick_node_ctrl.cpp deleted file mode 100644 index 40131e72f..000000000 --- a/host/lib/rfnoc/tick_node_ctrl.cpp +++ /dev/null @@ -1,65 +0,0 @@ -// -// Copyright 2014-2015 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#include <uhd/rfnoc/tick_node_ctrl.hpp> - -using namespace uhd::rfnoc; - -const double tick_node_ctrl::RATE_UNDEFINED = 0; - -double tick_node_ctrl::get_tick_rate( -    const std::set<node_ctrl_base::sptr>& _explored_nodes) -{ -    // First, see if we've implemented _get_tick_rate() -    { -        double my_tick_rate = _get_tick_rate(); -        if (my_tick_rate != RATE_UNDEFINED) { -            return my_tick_rate; -        } -    } - -    // If not, we ask all our neighbours for the tick rate. -    // This will fail if we get different values. -    std::set<node_ctrl_base::sptr> explored_nodes(_explored_nodes); -    explored_nodes.insert(shared_from_this()); -    // Here, we need all up- and downstream nodes. Note that we have the rule -    // that there can only be one tick rate in all of the nodes, that means we -    // don't only search active neighbouring nodes. -    std::vector<sptr> neighbouring_tick_nodes = -        find_downstream_node<tick_node_ctrl>(false); -    { -        std::vector<sptr> upstream_neighbouring_tick_nodes = -            find_upstream_node<tick_node_ctrl>(false); -        neighbouring_tick_nodes.insert(neighbouring_tick_nodes.end(), -            upstream_neighbouring_tick_nodes.begin(), -            upstream_neighbouring_tick_nodes.end()); -    } // neighbouring_tick_nodes is now initialized -    double ret_val = RATE_UNDEFINED; -    for (const sptr& node : neighbouring_tick_nodes) { -        if (_explored_nodes.count(node)) { -            continue; -        } -        double tick_rate = node->get_tick_rate(explored_nodes); -        if (tick_rate == RATE_UNDEFINED) { -            continue; -        } -        if (ret_val == RATE_UNDEFINED) { -            ret_val = tick_rate; -            // TODO: Remember name of this node so we can make the throw message more -            // descriptive. -            continue; -        } -        if (tick_rate != ret_val) { -            throw uhd::runtime_error(str( -                // TODO add node names -                boost::format("Conflicting tick rates: One neighbouring block specifies " -                              "%d MHz, another %d MHz.") -                % tick_rate % ret_val)); -        } -    } -    return ret_val; -} diff --git a/host/lib/rfnoc/tx_stream_terminator.cpp b/host/lib/rfnoc/tx_stream_terminator.cpp deleted file mode 100644 index fa4148fbb..000000000 --- a/host/lib/rfnoc/tx_stream_terminator.cpp +++ /dev/null @@ -1,53 +0,0 @@ -// -// Copyright 2014-2015 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#include <uhd/rfnoc/sink_node_ctrl.hpp> -#include <uhdlib/rfnoc/tx_stream_terminator.hpp> -#include <boost/format.hpp> - -using namespace uhd::rfnoc; - -size_t tx_stream_terminator::_count = 0; - -tx_stream_terminator::tx_stream_terminator() -    : _term_index(_count) -    , _samp_rate(rate_node_ctrl::RATE_UNDEFINED) -    , _tick_rate(tick_node_ctrl::RATE_UNDEFINED) -{ -    _count++; -} - -std::string tx_stream_terminator::unique_id() const -{ -    return str(boost::format("TX Terminator %d") % _term_index); -} - -void tx_stream_terminator::set_rx_streamer(bool, const size_t) -{ -    /* nop */ -} - -void tx_stream_terminator::set_tx_streamer(bool active, const size_t /* port */) -{ -    // TODO this is identical to sink_node_ctrl::set_tx_streamer() -> factor out -    UHD_RFNOC_BLOCK_TRACE() << "tx_stream_terminator::set_tx_streamer() " << active; -    for (const node_ctrl_base::node_map_pair_t downstream_node : _downstream_nodes) { -        sink_node_ctrl::sptr curr_downstream_block_ctrl = -            boost::dynamic_pointer_cast<sink_node_ctrl>(downstream_node.second.lock()); -        if (curr_downstream_block_ctrl) { -            curr_downstream_block_ctrl->set_tx_streamer( -                active, get_downstream_port(downstream_node.first)); -        } -        _tx_streamer_active[downstream_node.first] = active; -    } -} - -tx_stream_terminator::~tx_stream_terminator() -{ -    UHD_RFNOC_BLOCK_TRACE() << "tx_stream_terminator::~tx_stream_terminator() "; -    set_tx_streamer(false, 0); -} diff --git a/host/lib/rfnoc/wb_iface_adapter.cpp b/host/lib/rfnoc/wb_iface_adapter.cpp deleted file mode 100644 index d035ce881..000000000 --- a/host/lib/rfnoc/wb_iface_adapter.cpp +++ /dev/null @@ -1,44 +0,0 @@ -// -// Copyright 2016 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#include <uhd/rfnoc/constants.hpp> -#include <uhdlib/rfnoc/wb_iface_adapter.hpp> - -using namespace uhd::rfnoc; - -wb_iface_adapter::wb_iface_adapter(ctrl_iface::sptr iface, -    const gettickrate_type& gettickrate_functor_, -    const settime_type& settime_functor_, -    const gettime_type& gettime_functor_) -    : _iface(iface) -    , gettickrate_functor(gettickrate_functor_) -    , settime_functor(settime_functor_) -    , gettime_functor(gettime_functor_) -{ -    // nop -} - -void wb_iface_adapter::poke32(const wb_addr_type addr, const uint32_t data) -{ -    const uint64_t timestamp = gettime_functor().to_ticks(gettickrate_functor()); -    _iface->send_cmd_pkt(addr / 4, data, false, timestamp); -} - -uint32_t wb_iface_adapter::peek32(const wb_addr_type addr) -{ -    const uint64_t reg_value = peek64(addr); -    return ((addr / 4) & 0x1) ? uint32_t(reg_value >> 32) -                              : uint32_t(reg_value & 0xffffffff); -} - -uint64_t wb_iface_adapter::peek64(const wb_addr_type addr) -{ -    const uint64_t timestamp = gettime_functor().to_ticks(gettickrate_functor()); -    // TODO: Figure out if we should have a timestamp here -    _iface->send_cmd_pkt(SR_READBACK_ADDR, addr / 8, false, timestamp); -    return _iface->send_cmd_pkt(SR_READBACK, SR_READBACK_REG_USER, true, timestamp); -} diff --git a/host/lib/rfnoc/window_block_ctrl_impl.cpp b/host/lib/rfnoc/window_block_ctrl_impl.cpp deleted file mode 100644 index c1a814706..000000000 --- a/host/lib/rfnoc/window_block_ctrl_impl.cpp +++ /dev/null @@ -1,95 +0,0 @@ -// -// Copyright 2014-2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#include <uhd/convert.hpp> -#include <uhd/rfnoc/window_block_ctrl.hpp> -#include <uhd/utils/log.hpp> - -using namespace uhd::rfnoc; - -class window_block_ctrl_impl : public window_block_ctrl -{ -public: -    UHD_RFNOC_BLOCK_CONSTRUCTOR(window_block_ctrl), -        _item_type("sc16"), // We only support sc16 in this block -        _bpi(uhd::convert::get_bytes_per_item("sc16")) -    { -        _max_len = uint32_t(user_reg_read64(RB_MAX_WINDOW_LEN)); -        UHD_LOGGER_DEBUG(unique_id()) -            << "window_block::window_block() max_len ==" << _max_len << std::endl; -        UHD_ASSERT_THROW(_max_len); - -        // TODO we need a coercer to check that spp on the prop tree doesn't get set to -        // anything invalid -        _set_default_window(std::min<size_t>(get_arg<int>("spp"), _max_len)); -    } - -    //! Set window coefficients and length -    void set_window(const std::vector<int>& coeffs) -    { -        UHD_LOGGER_TRACE(unique_id()) << "window_block::set_window()" << std::endl; -        if (coeffs.size() > _max_len) { -            throw uhd::value_error( -                str(boost::format("window_block::set_window(): Too many window " -                                  "coefficients! Provided %d, window allows up to %d.\n") -                    % coeffs.size() % _max_len)); -        } - -        size_t window_len = coeffs.size(); - -        // Window block can take complex coefficients in sc16 format, but typical usage is -        // to have real(coeffs) == imag(coeffs) -        std::vector<uint32_t> coeffs_; -        for (size_t i = 0; i < window_len - 1; i++) { -            if (coeffs[i] > 32767 || coeffs[i] < -32768) { -                throw uhd::value_error( -                    str(boost::format( -                            "window_block::set_window(): Coefficient %d " -                            "(index %d) outside coefficient range [-32768,32767].\n") -                        % coeffs[i] % i)); -            } -            coeffs_.push_back(coeffs[i]); -        } - -        // Write coefficients via the load bus -        for (size_t i = 0; i < window_len - 1; i++) { -            sr_write(AXIS_WINDOW_LOAD, coeffs_[i]); -        } -        // Assert tlast when sending the final coefficient (sorry, no joke here) -        sr_write(AXIS_WINDOW_LOAD_TLAST, coeffs_.back()); -        // Set the window length -        sr_write(SR_WINDOW_LEN, window_len); - -        // This block requires spp to match the window length: -        set_arg<int>("spp", int(window_len)); -    } - -    //! Returns the maximum window length of this block. -    size_t get_max_len() const -    { -        return _max_len; -    } - -    size_t get_window_len() const -    { -        return size_t(get_arg<int>("spp")); -    } - - -private: -    const std::string _item_type; -    const size_t _bpi; -    size_t _max_len; - -    //! Default is a rectangular window -    void _set_default_window(size_t window_len) -    { -        std::vector<int> default_coeffs(window_len, (1 << 15) - 1); -        set_window(default_coeffs); -    } -}; - -UHD_RFNOC_BLOCK_REGISTER(window_block_ctrl, "Window"); diff --git a/host/lib/transport/CMakeLists.txt b/host/lib/transport/CMakeLists.txt index e899cfba0..d21644f01 100644 --- a/host/lib/transport/CMakeLists.txt +++ b/host/lib/transport/CMakeLists.txt @@ -115,7 +115,6 @@ LIBUHD_PYTHON_GEN_SOURCE(  LIBUHD_APPEND_SOURCES(      ${CMAKE_CURRENT_SOURCE_DIR}/zero_copy_flow_ctrl.cpp -    ${CMAKE_CURRENT_SOURCE_DIR}/zero_copy_recv_offload.cpp      ${CMAKE_CURRENT_SOURCE_DIR}/tcp_zero_copy.cpp      ${CMAKE_CURRENT_SOURCE_DIR}/buffer_pool.cpp      ${CMAKE_CURRENT_SOURCE_DIR}/if_addrs.cpp @@ -130,7 +129,6 @@ LIBUHD_APPEND_SOURCES(  if(ENABLE_X300)      LIBUHD_APPEND_SOURCES(          ${CMAKE_CURRENT_SOURCE_DIR}/nirio_link.cpp -        ${CMAKE_CURRENT_SOURCE_DIR}/nirio_zero_copy.cpp      )  endif(ENABLE_X300) @@ -150,11 +148,3 @@ if(ENABLE_DPDK)      )  endif(ENABLE_DPDK) -# Verbose Debug output for send/recv -set( UHD_TXRX_DEBUG_PRINTS OFF CACHE BOOL "Use verbose debug output for send/recv" ) -option( UHD_TXRX_DEBUG_PRINTS "Use verbose debug output for send/recv" "" ) -if(UHD_TXRX_DEBUG_PRINTS) -	message(STATUS "Using verbose debug output for send/recv") -	add_definitions(-DUHD_TXRX_DEBUG_PRINTS) -endif() - diff --git a/host/lib/transport/buffer_pool.cpp b/host/lib/transport/buffer_pool.cpp index c481b9d02..0dd4a8d7f 100644 --- a/host/lib/transport/buffer_pool.cpp +++ b/host/lib/transport/buffer_pool.cpp @@ -12,15 +12,6 @@  using namespace uhd::transport; -#ifdef UHD_TXRX_DEBUG_PRINTS -/* - * This is the implementation for the static variable 's_buffer_count' - * located in uhd/transport/zero_copy.hpp. - * It is used in the managed_buffer class. - */ -boost::detail::atomic_count managed_buffer::s_buffer_count(0); -#endif // UHD_TXRX_DEBUG_PRINTS -  //! pad the byte count to a multiple of alignment  static size_t pad_to_boundary(const size_t bytes, const size_t alignment)  { diff --git a/host/lib/transport/libusb1_zero_copy.cpp b/host/lib/transport/libusb1_zero_copy.cpp index f5693b198..9a1b74fb2 100644 --- a/host/lib/transport/libusb1_zero_copy.cpp +++ b/host/lib/transport/libusb1_zero_copy.cpp @@ -21,12 +21,6 @@  #include <boost/thread/mutex.hpp>  #include <list> -#ifdef UHD_TXRX_DEBUG_PRINTS -#    include <boost/format.hpp> -#    include <fstream> -#    include <vector> -#endif -  using namespace uhd;  using namespace uhd::transport; diff --git a/host/lib/transport/super_recv_packet_handler.hpp b/host/lib/transport/super_recv_packet_handler.hpp index 85d00bad1..950da4c8a 100644 --- a/host/lib/transport/super_recv_packet_handler.hpp +++ b/host/lib/transport/super_recv_packet_handler.hpp @@ -18,7 +18,6 @@  #include <uhd/utils/byteswap.hpp>  #include <uhd/utils/log.hpp>  #include <uhd/utils/tasks.hpp> -#include <uhdlib/rfnoc/rx_stream_terminator.hpp>  #include <boost/dynamic_bitset.hpp>  #include <boost/format.hpp>  #include <boost/function.hpp> @@ -26,13 +25,6 @@  #include <iostream>  #include <vector> -// Included for debugging -#ifdef UHD_TXRX_DEBUG_PRINTS -#    include "boost/date_time/posix_time/posix_time.hpp" -#    include <boost/format.hpp> -#    include <boost/thread/thread.hpp> -#endif -  namespace uhd { namespace transport { namespace sph {  UHD_INLINE uint32_t get_context_code( @@ -250,10 +242,6 @@ public:              recv_one_packet(buffs, nsamps_per_buff, metadata, timeout);          if (one_packet or metadata.end_of_burst) { -#ifdef UHD_TXRX_DEBUG_PRINTS -            dbg_gather_data( -                nsamps_per_buff, accum_num_samps, metadata, timeout, one_packet); -#endif              return accum_num_samps;          } @@ -285,9 +273,6 @@ public:                  break;              }          } -#ifdef UHD_TXRX_DEBUG_PRINTS -        dbg_gather_data(nsamps_per_buff, accum_num_samps, metadata, timeout, one_packet); -#endif          return accum_num_samps;      } @@ -813,84 +798,6 @@ private:      size_t _convert_buffer_offset_bytes;      size_t _convert_bytes_to_copy; -    /* -     * This last section is only for debugging purposes. -     * It causes a lot of prints to stderr which can be piped to a file. -     * Gathered data can be used to post process it with external tools. -     */ -#ifdef UHD_TXRX_DEBUG_PRINTS -    struct dbg_recv_stat_t -    { -        dbg_recv_stat_t(long wc, -            size_t nspb, -            size_t nsr, -            uhd::rx_metadata_t md, -            double to, -            bool op, -            double rate) -            : wallclock(wc) -            , nsamps_per_buff(nspb) -            , nsamps_recv(nsr) -            , metadata(md) -            , timeout(to) -            , one_packet(op) -            , samp_rate(rate) -        { -        } -        long wallclock; -        size_t nsamps_per_buff; -        size_t nsamps_recv; -        uhd::rx_metadata_t metadata; -        double timeout; -        bool one_packet; -        double samp_rate; -        // Create a formatted print line for all the info gathered in this struct. -        std::string print_line() -        { -            boost::format fmt("recv,%ld,%f,%i,%i,%s,%i,%s,%s,%s,%i,%s,%ld"); -            fmt % wallclock; -            fmt % timeout % (int)nsamps_per_buff % (int)nsamps_recv; -            fmt % (one_packet ? "true" : "false"); -            fmt % metadata.error_code; -            fmt % (metadata.start_of_burst ? "true" : "false") -                % (metadata.end_of_burst ? "true" : "false"); -            fmt % (metadata.more_fragments ? "true" : "false") -                % (int)metadata.fragment_offset; -            fmt % (metadata.has_time_spec ? "true" : "false") -                % metadata.time_spec.to_ticks(samp_rate); -            return fmt.str(); -        } -    }; - -    void dbg_gather_data(const size_t nsamps_per_buff, -        const size_t nsamps_recv, -        uhd::rx_metadata_t& metadata, -        const double timeout, -        const bool one_packet, -        bool dbg_print_directly = true) -    { -        // Initialize a struct with all available data. It can return a formatted string -        // with all infos if wanted. -        dbg_recv_stat_t data(boost::get_system_time().time_of_day().total_microseconds(), -            nsamps_per_buff, -            nsamps_recv, -            metadata, -            timeout, -            one_packet, -            _samp_rate); -        if (dbg_print_directly) { -            dbg_print_err(data.print_line()); -        } -    } - - -    void dbg_print_err(std::string msg) -    { -        std::string dbg_prefix("super_recv_packet_handler,"); -        msg = dbg_prefix + msg; -        fprintf(stderr, "%s\n", msg.c_str()); -    } -#endif  };  class recv_packet_streamer : public recv_packet_handler, public rx_streamer diff --git a/host/lib/transport/super_send_packet_handler.hpp b/host/lib/transport/super_send_packet_handler.hpp index af6ecaa5e..cd707cb89 100644 --- a/host/lib/transport/super_send_packet_handler.hpp +++ b/host/lib/transport/super_send_packet_handler.hpp @@ -18,22 +18,12 @@  #include <uhd/utils/byteswap.hpp>  #include <uhd/utils/tasks.hpp>  #include <uhd/utils/thread.hpp> -#include <uhdlib/rfnoc/tx_stream_terminator.hpp>  #include <boost/function.hpp>  #include <chrono>  #include <iostream>  #include <thread>  #include <vector> -#ifdef UHD_TXRX_DEBUG_PRINTS -// Included for debugging -#    include "boost/date_time/posix_time/posix_time.hpp" -#    include <boost/format.hpp> -#    include <boost/thread/thread.hpp> -#    include <fstream> -#    include <map> -#endif -  namespace uhd { namespace transport { namespace sph {  /*********************************************************************** @@ -240,9 +230,6 @@ public:              size_t nsamps_sent =                  send_one_packet(buffs, nsamps_per_buff, if_packet_info, timeout); -#ifdef UHD_TXRX_DEBUG_PRINTS -            dbg_print_send(nsamps_per_buff, nsamps_sent, metadata, timeout); -#endif              return nsamps_sent;          }          size_t total_num_samps_sent = 0; @@ -281,10 +268,6 @@ public:                                     if_packet_info,                                     timeout,                                     total_num_samps_sent * _bytes_per_cpu_item); -#ifdef UHD_TXRX_DEBUG_PRINTS -        dbg_print_send(nsamps_per_buff, nsamps_sent, metadata, timeout); - -#endif          return nsamps_sent;      } @@ -314,67 +297,6 @@ private:      bool _cached_metadata;      uhd::tx_metadata_t _metadata_cache; -#ifdef UHD_TXRX_DEBUG_PRINTS -    struct dbg_send_stat_t -    { -        dbg_send_stat_t(long wc, -            size_t nspb, -            size_t nss, -            uhd::tx_metadata_t md, -            double to, -            double rate) -            : wallclock(wc) -            , nsamps_per_buff(nspb) -            , nsamps_sent(nss) -            , metadata(md) -            , timeout(to) -            , samp_rate(rate) -        { -        } -        long wallclock; -        size_t nsamps_per_buff; -        size_t nsamps_sent; -        uhd::tx_metadata_t metadata; -        double timeout; -        double samp_rate; -        // Create a formatted print line for all the info gathered in this struct. -        std::string print_line() -        { -            boost::format fmt("send,%ld,%f,%i,%i,%s,%s,%s,%ld"); -            fmt % wallclock; -            fmt % timeout % (int)nsamps_per_buff % (int)nsamps_sent; -            fmt % (metadata.start_of_burst ? "true" : "false") -                % (metadata.end_of_burst ? "true" : "false"); -            fmt % (metadata.has_time_spec ? "true" : "false") -                % metadata.time_spec.to_ticks(samp_rate); -            return fmt.str(); -        } -    }; - -    void dbg_print_send(size_t nsamps_per_buff, -        size_t nsamps_sent, -        const uhd::tx_metadata_t& metadata, -        const double timeout, -        bool dbg_print_directly = true) -    { -        dbg_send_stat_t data(boost::get_system_time().time_of_day().total_microseconds(), -            nsamps_per_buff, -            nsamps_sent, -            metadata, -            timeout, -            _samp_rate); -        if (dbg_print_directly) { -            dbg_print_err(data.print_line()); -        } -    } -    void dbg_print_err(std::string msg) -    { -        msg = "super_send_packet_handler," + msg; -        fprintf(stderr, "%s\n", msg.c_str()); -    } - - -#endif      /*******************************************************************       * Send a single packet: diff --git a/host/lib/transport/xport_benchmarker.cpp b/host/lib/transport/xport_benchmarker.cpp deleted file mode 100644 index 67582ff2c..000000000 --- a/host/lib/transport/xport_benchmarker.cpp +++ /dev/null @@ -1,158 +0,0 @@ -// -// Copyright 2010-2013 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#include "xport_benchmarker.hpp" -#include <chrono> -#include <thread> - -namespace uhd { namespace transport { - -const device_addr_t& xport_benchmarker::benchmark_throughput_chdr( -    zero_copy_if::sptr tx_transport, -    zero_copy_if::sptr rx_transport, -    uint32_t sid, -    bool big_endian, -    uint32_t duration_ms) -{ -    vrt::if_packet_info_t pkt_info; -    _initialize_chdr(tx_transport, rx_transport, sid, pkt_info); -    _reset_counters(); -    boost::posix_time::ptime start_time(boost::posix_time::microsec_clock::local_time()); - -    _tx_thread.reset(new boost::thread(boost::bind(&xport_benchmarker::_stream_tx, -        this, -        tx_transport.get(), -        &pkt_info, -        big_endian))); -    _rx_thread.reset(new boost::thread(boost::bind(&xport_benchmarker::_stream_rx, -        this, -        rx_transport.get(), -        &pkt_info, -        big_endian))); - -    std::this_thread::sleep_for(std::chrono::milliseconds(duration_ms)); - -    _tx_thread->interrupt(); -    _rx_thread->interrupt(); -    _tx_thread->join(); -    _rx_thread->join(); - -    boost::posix_time::ptime stop_time(boost::posix_time::microsec_clock::local_time()); -    double duration_s = ((double)(stop_time - start_time).total_microseconds()) / 1e6; - -    uint64_t tx_bytes = pkt_info.num_payload_words32 * sizeof(uint32_t) * _num_tx_packets; -    uint64_t rx_bytes = pkt_info.num_payload_words32 * sizeof(uint32_t) * _num_rx_packets; -    double tx_rate    = (((double)tx_bytes) / duration_s); -    double rx_rate    = (((double)rx_bytes) / duration_s); - -    _results["TX-Bytes"] = (boost::format("%.2fMB") % (tx_bytes / (1024 * 1024))).str(); -    _results["RX-Bytes"] = (boost::format("%.2fMB") % (rx_bytes / (1024 * 1024))).str(); -    _results["TX-Throughput"] = -        (boost::format("%.2fMB/s") % (tx_rate / (1024 * 1024))).str(); -    _results["RX-Throughput"] = -        (boost::format("%.2fMB/s") % (rx_rate / (1024 * 1024))).str(); -    _results["TX-Timeouts"] = std::to_string(_num_tx_timeouts); -    _results["RX-Timeouts"] = std::to_string(_num_rx_timeouts); -    _results["Data-Errors"] = std::to_string(_num_data_errors); - -    return _results; -} - -void xport_benchmarker::_stream_tx( -    zero_copy_if* transport, vrt::if_packet_info_t* pkt_info, bool big_endian) -{ -    while (not boost::this_thread::interruption_requested()) { -        managed_send_buffer::sptr buff = transport->get_send_buff(_tx_timeout); -        if (buff) { -            uint32_t* packet_buff = buff->cast<uint32_t*>(); -            // Populate packet -            if (big_endian) { -                vrt::if_hdr_pack_be(packet_buff, *pkt_info); -            } else { -                vrt::if_hdr_pack_le(packet_buff, *pkt_info); -            } -            // send the buffer over the interface -            buff->commit(sizeof(uint32_t) * (pkt_info->num_packet_words32)); -            _num_tx_packets++; -        } else { -            _num_tx_timeouts++; -        } -    } -} - -void xport_benchmarker::_stream_rx( -    zero_copy_if* transport, const vrt::if_packet_info_t* exp_pkt_info, bool big_endian) -{ -    while (not boost::this_thread::interruption_requested()) { -        managed_recv_buffer::sptr buff = transport->get_recv_buff(_rx_timeout); -        if (buff) { -            // Extract packet info -            vrt::if_packet_info_t pkt_info; -            pkt_info.link_type          = exp_pkt_info->link_type; -            pkt_info.num_packet_words32 = buff->size() / sizeof(uint32_t); -            const uint32_t* packet_buff = buff->cast<const uint32_t*>(); - -            _num_rx_packets++; - -            // unpacking can fail -            try { -                if (big_endian) { -                    vrt::if_hdr_unpack_be(packet_buff, pkt_info); -                } else { -                    vrt::if_hdr_unpack_le(packet_buff, pkt_info); -                } - -                if (exp_pkt_info->packet_type != pkt_info.packet_type -                    || exp_pkt_info->num_payload_bytes != pkt_info.num_payload_bytes) { -                    _num_data_errors++; -                } -            } catch (const std::exception& ex) { -                _num_data_errors++; -            } -        } else { -            _num_rx_timeouts++; -        } -    } -} - -void xport_benchmarker::_reset_counters(void) -{ -    _num_tx_packets  = 0; -    _num_rx_packets  = 0; -    _num_tx_timeouts = 0; -    _num_rx_timeouts = 0; -    _num_data_errors = 0; -} - -void xport_benchmarker::_initialize_chdr(zero_copy_if::sptr tx_transport, -    zero_copy_if::sptr rx_transport, -    uint32_t sid, -    vrt::if_packet_info_t& pkt_info) -{ -    _tx_timeout = 0.5; -    _rx_timeout = 0.5; - -    size_t frame_size = std::min( -        tx_transport->get_send_frame_size(), rx_transport->get_recv_frame_size()); - -    pkt_info.link_type           = vrt::if_packet_info_t::LINK_TYPE_CHDR; -    pkt_info.packet_type         = vrt::if_packet_info_t::PACKET_TYPE_DATA; -    pkt_info.num_packet_words32  = (frame_size / sizeof(uint32_t)); -    pkt_info.num_payload_words32 = pkt_info.num_packet_words32 - 2; -    pkt_info.num_payload_bytes   = pkt_info.num_payload_words32 * sizeof(uint32_t); -    pkt_info.packet_count        = 0; -    pkt_info.sob                 = false; -    pkt_info.eob                 = false; -    pkt_info.sid                 = sid; -    pkt_info.has_sid             = true; -    pkt_info.has_cid             = false; -    pkt_info.has_tsi             = false; -    pkt_info.has_tsf             = false; -    pkt_info.has_tlr             = false; -} - -}} // namespace uhd::transport diff --git a/host/lib/transport/xport_benchmarker.hpp b/host/lib/transport/xport_benchmarker.hpp deleted file mode 100644 index 3843540e0..000000000 --- a/host/lib/transport/xport_benchmarker.hpp +++ /dev/null @@ -1,63 +0,0 @@ -// -// Copyright 2010-2013 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#ifndef INCLUDED_LIBUHD_XPORT_BENCHMARKER_HPP -#define INCLUDED_LIBUHD_XPORT_BENCHMARKER_HPP - -#include <uhd/transport/vrt_if_packet.hpp> -#include <uhd/transport/zero_copy.hpp> -#include <uhd/types/device_addr.hpp> -#include <uhd/utils/log.hpp> -#include <boost/shared_ptr.hpp> -#include <boost/thread/thread.hpp> - -namespace uhd { namespace transport { - -// Test class to benchmark a low-level transport object with a VITA/C-VITA data stream -class xport_benchmarker : uhd::noncopyable -{ -public: -    const device_addr_t& benchmark_throughput_chdr(zero_copy_if::sptr tx_transport, -        zero_copy_if::sptr rx_transport, -        uint32_t sid, -        bool big_endian, -        uint32_t duration_ms); - -private: -    void _stream_tx( -        zero_copy_if* transport, vrt::if_packet_info_t* pkt_info, bool big_endian); - -    void _stream_rx(zero_copy_if* transport, -        const vrt::if_packet_info_t* exp_pkt_info, -        bool big_endian); - -    void _initialize_chdr(zero_copy_if::sptr tx_transport, -        zero_copy_if::sptr rx_transport, -        uint32_t sid, -        vrt::if_packet_info_t& pkt_info); - -    void _reset_counters(void); - -    boost::shared_ptr<boost::thread> _tx_thread; -    boost::shared_ptr<boost::thread> _rx_thread; - -    uint64_t _num_tx_packets; -    uint64_t _num_rx_packets; -    uint64_t _num_tx_timeouts; -    uint64_t _num_rx_timeouts; -    uint64_t _num_data_errors; - -    double _tx_timeout; -    double _rx_timeout; - -    device_addr_t _results; -}; - - -}} // namespace uhd::transport - -#endif /* INCLUDED_LIBUHD_XPORT_BENCHMARKER_HPP */ diff --git a/host/lib/transport/zero_copy_recv_offload.cpp b/host/lib/transport/zero_copy_recv_offload.cpp deleted file mode 100644 index 7329dbdf3..000000000 --- a/host/lib/transport/zero_copy_recv_offload.cpp +++ /dev/null @@ -1,146 +0,0 @@ -// -// Copyright 2016 Ettus Research -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#include <uhd/transport/bounded_buffer.hpp> -#include <uhd/transport/buffer_pool.hpp> -#include <uhd/transport/zero_copy_recv_offload.hpp> -#include <uhd/utils/log.hpp> -#include <uhd/utils/safe_call.hpp> -#include <uhd/utils/thread.hpp> -#include <boost/bind.hpp> -#include <boost/format.hpp> -#include <boost/make_shared.hpp> -#include <boost/thread/mutex.hpp> -#include <boost/thread/thread.hpp> - -using namespace uhd; -using namespace uhd::transport; - -typedef bounded_buffer<managed_recv_buffer::sptr> bounded_buffer_t; - -/*********************************************************************** - * Zero copy offload transport: - * An intermediate transport that utilizes threading to free - * the main thread from any receive work. - **********************************************************************/ -class zero_copy_recv_offload_impl : public zero_copy_recv_offload -{ -public: -    typedef boost::shared_ptr<zero_copy_recv_offload_impl> sptr; - -    zero_copy_recv_offload_impl(zero_copy_if::sptr transport, const double timeout) -        : _transport(transport) -        , _timeout(timeout) -        , _inbox(transport->get_num_recv_frames()) -        , _recv_done(false) -    { -        UHD_LOGGER_TRACE("XPORT") << "Created threaded transport"; - -        // Create the receive and send threads to offload -        // the system calls onto other threads -        _recv_thread = -            boost::thread(boost::bind(&zero_copy_recv_offload_impl::enqueue_recv, this)); -        set_thread_name(&_recv_thread, "zero_copy_recv"); -    } - -    // Receive thread flags -    void set_recv_done() -    { -        boost::lock_guard<boost::mutex> guard(_recv_mutex); -        _recv_done = true; -    } - -    bool is_recv_done() -    { -        boost::lock_guard<boost::mutex> guard(_recv_mutex); -        return _recv_done; -    } - -    ~zero_copy_recv_offload_impl() -    { -        // Signal the threads we're finished -        set_recv_done(); - -        // Wait for them to join -        UHD_SAFE_CALL(_recv_thread.join();) -    } - -    // The receive thread function is responsible for -    // pulling pointers to managed receiver buffers quickly -    void enqueue_recv() -    { -        while (not is_recv_done()) { -            managed_recv_buffer::sptr buff = _transport->get_recv_buff(_timeout); -            if (not buff) -                continue; -            _inbox.push_with_timed_wait(buff, _timeout); -        } -    } - -    /******************************************************************* -     * Receive implementation: -     * Pop the receive buffer pointer from the underlying transport -     ******************************************************************/ -    managed_recv_buffer::sptr get_recv_buff(double timeout) -    { -        managed_recv_buffer::sptr ptr; -        _inbox.pop_with_timed_wait(ptr, timeout); -        return ptr; -    } - -    size_t get_num_recv_frames() const -    { -        return _transport->get_num_recv_frames(); -    } - -    size_t get_recv_frame_size() const -    { -        return _transport->get_recv_frame_size(); -    } - -    /******************************************************************* -     * Send implementation: -     * Pass the send buffer pointer from the underlying transport -     ******************************************************************/ -    managed_send_buffer::sptr get_send_buff(double timeout) -    { -        return _transport->get_send_buff(timeout); -    } - -    size_t get_num_send_frames() const -    { -        return _transport->get_num_send_frames(); -    } - -    size_t get_send_frame_size() const -    { -        return _transport->get_send_frame_size(); -    } - -private: -    // The linked transport -    zero_copy_if::sptr _transport; - -    const double _timeout; - -    // Shared buffers -    bounded_buffer_t _inbox; - -    // Threading -    bool _recv_done; -    boost::thread _recv_thread; -    boost::mutex _recv_mutex; -}; - -zero_copy_recv_offload::sptr zero_copy_recv_offload::make( -    zero_copy_if::sptr transport, const double timeout) -{ -    zero_copy_recv_offload_impl::sptr zero_copy_recv_offload( -        new zero_copy_recv_offload_impl(transport, timeout)); - -    return zero_copy_recv_offload; -} diff --git a/host/lib/types/CMakeLists.txt b/host/lib/types/CMakeLists.txt index 3265c654f..f731adf20 100644 --- a/host/lib/types/CMakeLists.txt +++ b/host/lib/types/CMakeLists.txt @@ -1,6 +1,7 @@  #  # Copyright 2011-2013,2015 Ettus Research LLC  # Copyright 2018 Ettus Research, a National Instruments Company +# Copyright 2019 Ettus Research, a National Instruments Brand  #  # SPDX-License-Identifier: GPL-3.0-or-later  # @@ -15,7 +16,6 @@ LIBUHD_APPEND_SOURCES(      ${CMAKE_CURRENT_SOURCE_DIR}/ranges.cpp      ${CMAKE_CURRENT_SOURCE_DIR}/sensors.cpp      ${CMAKE_CURRENT_SOURCE_DIR}/serial.cpp -    ${CMAKE_CURRENT_SOURCE_DIR}/sid.cpp      ${CMAKE_CURRENT_SOURCE_DIR}/time_spec.cpp      ${CMAKE_CURRENT_SOURCE_DIR}/tune.cpp      ${CMAKE_CURRENT_SOURCE_DIR}/types.cpp diff --git a/host/lib/types/sid.cpp b/host/lib/types/sid.cpp deleted file mode 100644 index 1f7aa0227..000000000 --- a/host/lib/types/sid.cpp +++ /dev/null @@ -1,143 +0,0 @@ -// -// Copyright 2014-2016 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#include <uhd/types/sid.hpp> -#include <uhd/exception.hpp> -#include <uhd/utils/cast.hpp> -#include <boost/format.hpp> -#include <boost/regex.hpp> -#include <boost/lexical_cast.hpp> - -using namespace uhd; - -sid_t::sid_t() -    : _sid(0x0000), _set(false) -{ -} - -sid_t::sid_t(uint32_t sid) -    : _sid(sid), _set(true) -{ -} - -sid_t::sid_t(uint8_t src_addr, uint8_t src_ep, uint8_t dst_addr, uint8_t dst_ep) -    :  _sid(0x0000), _set(true) -{ -    set_src_addr(src_addr); -    set_src_endpoint(src_ep); -    set_dst_addr(dst_addr); -    set_dst_endpoint(dst_ep); -} - -sid_t::sid_t(const std::string &sid_str) -    : _sid(0x0000), _set(false) -{ -    set_from_str(sid_str); -} - -std::string sid_t::to_pp_string() const -{ -    if (not _set) { -        return "x.x>x.x"; -    } -    return str(boost::format("%d.%d>%d.%d") -        % get_src_addr() -        % get_src_endpoint() -        % get_dst_addr() -        % get_dst_endpoint() -    ); -} - -std::string sid_t::to_pp_string_hex() const -{ -    if (not _set) { -        return "xx:xx>xx:xx"; -    } -    return str(boost::format("%02x:%02x>%02x:%02x") -        % get_src_addr() -        % get_src_endpoint() -        % get_dst_addr() -        % get_dst_endpoint() -    ); -} - - -void sid_t::set_sid(uint32_t new_sid) -{ -    _set = true; -    _sid = new_sid; -} - -void sid_t::set_from_str(const std::string &sid_str) -{ -    const std::string dec_regex = "(\\d{1,3})\\.(\\d{1,3})[.:/><](\\d{1,3})\\.(\\d{1,3})"; -    const std::string hex_regex = "([[:xdigit:]]{2}):([[:xdigit:]]{2})[.:/><]([[:xdigit:]]{2}):([[:xdigit:]]{2})"; - -    boost::cmatch matches; -    if (boost::regex_match(sid_str.c_str(), matches, boost::regex(dec_regex))) { -        set_src_addr(boost::lexical_cast<size_t>(matches[1])); -        set_src_endpoint(boost::lexical_cast<size_t>(matches[2])); -        set_dst_addr(boost::lexical_cast<size_t>(matches[3])); -        set_dst_endpoint(boost::lexical_cast<size_t>(matches[4])); -        return; -    } - -    if (boost::regex_match(sid_str.c_str(), matches, boost::regex(hex_regex))) { -        set_src_addr(uhd::cast::hexstr_cast<size_t>(matches[1])); -        set_src_endpoint(uhd::cast::hexstr_cast<size_t>(matches[2])); -        set_dst_addr(uhd::cast::hexstr_cast<size_t>(matches[3])); -        set_dst_endpoint(uhd::cast::hexstr_cast<size_t>(matches[4])); -        return; -    } - -    throw uhd::value_error(str(boost::format("Invalid SID representation: %s") % sid_str)); -} - -void sid_t::set_src(uint32_t new_addr) { -    set_sid((_sid & 0x0000FFFF) | ((new_addr & 0xFFFF) << 16)); -} - -void sid_t::set_dst(uint32_t new_addr) { -    set_sid((_sid & 0xFFFF0000) | (new_addr & 0xFFFF)); -} - -void sid_t::set_src_addr(uint32_t new_addr) { -    set_sid((_sid & 0x00FFFFFF) | ((new_addr & 0xFF) << 24)); -} - -void sid_t::set_src_endpoint(uint32_t new_addr) { -    set_sid((_sid & 0xFF00FFFF) | ((new_addr & 0xFF) << 16)); -} - -void sid_t::set_dst_addr(uint32_t new_addr) { -    set_sid((_sid & 0xFFFF00FF) | ((new_addr & 0xFF) << 8)); -} - -void sid_t::set_dst_endpoint(uint32_t new_addr) { -    set_sid((_sid & 0xFFFFFF00) | ((new_addr & 0xFF) << 0)); -} - -void sid_t::set_dst_xbarport(uint32_t new_xbarport) -{ -    set_sid((_sid & 0xFFFFFF0F) | ((new_xbarport & 0xF) << 4)); -} - -void sid_t::set_dst_blockport(uint32_t new_blockport) -{ -    set_sid((_sid & 0xFFFFFFF0) | ((new_blockport & 0xF) << 0)); -} - -sid_t sid_t::reversed() const -{ -    return sid_t((get_dst() << 16) | get_src()); -} - -void sid_t::reverse() -{ -    set_sid((get_dst() << 16) | get_src()); -} - diff --git a/host/lib/usrp/CMakeLists.txt b/host/lib/usrp/CMakeLists.txt index 0b839a835..f15324608 100644 --- a/host/lib/usrp/CMakeLists.txt +++ b/host/lib/usrp/CMakeLists.txt @@ -35,7 +35,6 @@ endif(ENABLE_C_API)  INCLUDE_SUBDIRECTORY(cores)  INCLUDE_SUBDIRECTORY(dboard)  INCLUDE_SUBDIRECTORY(common) -INCLUDE_SUBDIRECTORY(device3)  INCLUDE_SUBDIRECTORY(mpmd)  INCLUDE_SUBDIRECTORY(usrp1)  INCLUDE_SUBDIRECTORY(usrp2) diff --git a/host/lib/usrp/dboard/CMakeLists.txt b/host/lib/usrp/dboard/CMakeLists.txt index 8ee79103f..2dd4e7e26 100644 --- a/host/lib/usrp/dboard/CMakeLists.txt +++ b/host/lib/usrp/dboard/CMakeLists.txt @@ -49,6 +49,3 @@ endif(ENABLE_N300)  if(ENABLE_N320)      INCLUDE_SUBDIRECTORY(rhodium)  endif(ENABLE_N320) -if(ENABLE_MPMD AND ENABLE_EISCAT) -    INCLUDE_SUBDIRECTORY(eiscat) -endif(ENABLE_MPMD AND ENABLE_EISCAT) diff --git a/host/lib/usrp/dboard/e3xx/e3xx_radio_control_impl.cpp b/host/lib/usrp/dboard/e3xx/e3xx_radio_control_impl.cpp index 29381a53c..bc9ed9169 100644 --- a/host/lib/usrp/dboard/e3xx/e3xx_radio_control_impl.cpp +++ b/host/lib/usrp/dboard/e3xx/e3xx_radio_control_impl.cpp @@ -7,7 +7,6 @@  #include "e3xx_radio_control_impl.hpp"  #include "e3xx_constants.hpp" -#include <uhd/transport/chdr.hpp>  #include <uhd/types/direction.hpp>  #include <uhd/types/eeprom.hpp>  #include <uhd/utils/algorithm.hpp> diff --git a/host/lib/usrp/dboard/e3xx/e3xx_radio_control_init.cpp b/host/lib/usrp/dboard/e3xx/e3xx_radio_control_init.cpp index f97feeb68..6ecf4ff2a 100644 --- a/host/lib/usrp/dboard/e3xx/e3xx_radio_control_init.cpp +++ b/host/lib/usrp/dboard/e3xx/e3xx_radio_control_init.cpp @@ -6,7 +6,6 @@  #include "e3xx_constants.hpp"  #include "e3xx_radio_control_impl.hpp" -#include <uhd/transport/chdr.hpp>  #include <uhd/types/sensors.hpp>  #include <uhd/utils/log.hpp>  #include <uhdlib/rfnoc/reg_iface_adapter.hpp> diff --git a/host/lib/usrp/dboard/eiscat/CMakeLists.txt b/host/lib/usrp/dboard/eiscat/CMakeLists.txt deleted file mode 100644 index 076d26916..000000000 --- a/host/lib/usrp/dboard/eiscat/CMakeLists.txt +++ /dev/null @@ -1,14 +0,0 @@ -# -# Copyright 2017 Ettus Research, a National Instruments Company -# -# SPDX-License-Identifier: GPL-3.0-or-later -# - -# This file is conditionally included if ENABLE_MPMD and ENABLE_EISCAT are -# set to true. - -list(APPEND EISCAT_SOURCES -    ${CMAKE_CURRENT_SOURCE_DIR}/eiscat_radio_ctrl_impl.cpp -) -LIBUHD_APPEND_SOURCES(${EISCAT_SOURCES}) - diff --git a/host/lib/usrp/dboard/eiscat/eiscat_radio_ctrl_impl.cpp b/host/lib/usrp/dboard/eiscat/eiscat_radio_ctrl_impl.cpp deleted file mode 100644 index 73851656b..000000000 --- a/host/lib/usrp/dboard/eiscat/eiscat_radio_ctrl_impl.cpp +++ /dev/null @@ -1,950 +0,0 @@ -// -// Copyright 2017 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#include "eiscat_radio_ctrl_impl.hpp" - -#include <uhd/utils/log.hpp> -#include <uhd/utils/math.hpp> -#include <uhd/rfnoc/node_ctrl_base.hpp> -#include <uhd/types/ranges.hpp> -#include <boost/algorithm/string.hpp> -#include <boost/make_shared.hpp> -#include <boost/date_time/posix_time/posix_time_io.hpp> -#include <boost/format.hpp> - -using namespace uhd; -using namespace uhd::usrp; -using namespace uhd::rfnoc; - -namespace { -    const size_t SR_ANTENNA_GAIN_BASE     = 204; -    const size_t SR_ANTENNA_SELECT_BASE   = 192; // Note: On other dboards, 192 is DB_GPIO address space -    const size_t RB_CHOOSE_BEAMS          = 11; - -    const double EISCAT_TICK_RATE         = 208e6; // Hz -    const double EISCAT_RADIO_RATE        = 104e6; // Hz -    const double EISCAT_CENTER_FREQ       = 208e6; // Hz -    const double EISCAT_DEFAULT_NULL_GAIN = 0.0; // dB. This is not the digital antenna gain, this a fake stub value. -    const double EISCAT_DEFAULT_BANDWIDTH = 104e6; // Hz -    const char*  EISCAT_DEFAULT_ANTENNA   = "BF"; -    const size_t EISCAT_NUM_ANTENNAS      = 16; -    const size_t EISCAT_NUM_BEAMS         = 10; -    const size_t EISCAT_NUM_PORTS         = 5; -    const size_t EISCAT_MAX_GAIN_RANGE    = 18; // Bits, *signed*. -    const size_t EISCAT_UNIT_GAIN_RANGE   = 14; // Bits, *signed*. -    const int32_t EISCAT_MAX_GAIN         = (1<<(EISCAT_MAX_GAIN_RANGE-1))-1; -    const int32_t EISCAT_UNIT_GAIN        = (1<<(EISCAT_UNIT_GAIN_RANGE-1))-1; -    const int32_t EISCAT_MIN_GAIN         = -(1<<(EISCAT_MAX_GAIN_RANGE-1)); -    const double EISCAT_DEFAULT_NORM_GAIN = 1.0; // Normalized. This is the actual digital gain value. -    const size_t EISCAT_BITS_PER_TAP      = 18; -    const eiscat_radio_ctrl_impl::fir_tap_t EISCAT_MAX_TAP_VALUE  = (1<<(EISCAT_BITS_PER_TAP-1))-1; -    const eiscat_radio_ctrl_impl::fir_tap_t EISCAT_MIN_TAP_VALUE  = -(1<<(EISCAT_BITS_PER_TAP-1)); -    const size_t EISCAT_NUM_FIR_TAPS      = 10; -    const size_t EISCAT_NUM_FIR_SETS      = 1024; // BRAM must be at least EISCAT_NUM_FIR_TAPS * EISCAT_NUM_FIR_SETS -    const size_t EISCAT_FIR_INDEX_IMPULSE = 1002; -    const size_t EISCAT_FIR_INDEX_ZEROS   = 1003; - -    const uint32_t EISCAT_CONTRIB_LOWER   = 0<<0; -    const uint32_t EISCAT_CONTRIB_UPPER   = 1<<0; -    const uint32_t EISCAT_SKIP_NEIGHBOURS = 1<<1; -    const uint32_t EISCAT_BYPASS_MATRIX   = 1<<2; -    const uint32_t EISCAT_OUTPUT_COUNTER  = 1<<3; -}; - - -UHD_RFNOC_RADIO_BLOCK_CONSTRUCTOR(eiscat_radio_ctrl) -{ -    UHD_LOG_TRACE("EISCAT", "eiscat_radio_ctrl_impl::ctor() "); -    _num_ports = get_output_ports().size(); -    UHD_LOG_TRACE("EISCAT", "Number of channels: " << _num_ports); -    UHD_LOG_TRACE("EISCAT", -        "Tick rate is " << EISCAT_TICK_RATE/1e6 << " MHz" -    ); - -    /**** Configure the radio_ctrl itself ***********************************/ -    // This also sets the command tick rate: -    radio_ctrl_impl::set_rate(EISCAT_TICK_RATE); -    for (size_t chan = 0; chan < _num_ports; chan++) { -        radio_ctrl_impl::set_rx_frequency(EISCAT_CENTER_FREQ, chan); -        radio_ctrl_impl::set_rx_gain(EISCAT_DEFAULT_NULL_GAIN, chan); -        radio_ctrl_impl::set_rx_antenna(EISCAT_DEFAULT_ANTENNA, chan); -        radio_ctrl_impl::set_rx_bandwidth(EISCAT_DEFAULT_BANDWIDTH, chan); -        // We might get tx async messages from upstream radios, we send them to the -        // nevernever by default or they interfere with our streamers or ctrl_iface -        // objects. The assumption is that FF:FF is never a valid SID. -        this->sr_write(uhd::rfnoc::SR_RESP_IN_DST_SID, 0xFFFF, chan); -    } - -    /**** Set up arg-based control API **************************************/ -    // None of these properties are defined in the XML file. Some of them have -    // non-Noc-Script-compatible types. -    _tree->create<bool>(get_arg_path("sysref", 0) / "value") -        .set(true) -        .add_coerced_subscriber([this](bool){ -            try { -                this->send_sysref(); -            } catch (const uhd::exception &ex) { -                UHD_LOGGER_WARNING("EISCAT") -                    << "Failed to send SYSREF: " << ex.what(); -                throw uhd::runtime_error(str( -                    boost::format("Failed to send SYSREF: %s") -                    % ex.what() -                )); -            } -        }) -        .set_publisher([](){ return true; }) -    ; -    _tree->create<bool>(get_arg_path("assert_adcs_deframers", 0) / "value") -        .set(true) -        .set_publisher([this](){ return this->assert_adcs_deframers(); }) -    ; -    _tree->create<bool>(get_arg_path("assert_deframer_status", 0) / "value") -        .set(true) -        .set_publisher([this](){ return this->assert_adcs_deframers(); }) -    ; -    _tree->create<time_spec_t>(get_arg_path("fir_ctrl_time", 0) / "value") -        .add_coerced_subscriber([this](time_spec_t switch_time){ -            this->set_fir_ctrl_time(switch_time); -        }) -        .set(time_spec_t(0.0)) -    ; -    for (size_t beam = 0; beam < EISCAT_NUM_BEAMS; beam++) { -        for (size_t ant = 0; ant < EISCAT_NUM_ANTENNAS; ant++) { -            const size_t fir_index = beam * EISCAT_NUM_ANTENNAS + ant; -            // These are not in the XML file -            _tree->create<int>(get_arg_path("fir_select", fir_index) / "value") -                .add_coerced_subscriber([beam, ant, this](const size_t ram_idx){ -                    UHD_ASSERT_THROW(ram_idx < EISCAT_NUM_FIR_SETS); -                    this->select_filter( -                        beam, -                        ant, -                        ram_idx, -                        this->get_arg<time_spec_t>("fir_ctrl_time", 0), -                        false -                    ); -                }) -            ; -        } -    } -    for (size_t fir_set = 0; fir_set < EISCAT_NUM_FIR_SETS; fir_set++) { -        _tree->create<std::vector<fir_tap_t>>( -                                get_arg_path("fir_taps", fir_set) / "value") -            .add_coerced_subscriber( -                [this, fir_set](const std::vector<fir_tap_t> &taps){ -                    this->write_fir_taps(fir_set, taps); -                } -            ) -        ; -    } - - -    /**** Add subscribers for our special properties ************************/ -    // The difference between this block and the previous that these *are* -    // defined in the XML file, and can have defaults set there. -    _tree->access<int>(get_arg_path("choose_beams", 0) / "value") -        .add_coerced_subscriber([this](int choose_beams){ -            this->set_beam_selection(choose_beams); -        }) -        .update() -    ; -    _tree->access<bool>(get_arg_path("enable_firs", 0) / "value") -        .add_coerced_subscriber([this](int enable){ -            this->enable_firs(bool(enable)); -        }) -        .update() -    ; -    _tree->access<bool>(get_arg_path("enable_counter", 0) / "value") -        .add_coerced_subscriber([this](int enable){ -            this->enable_counter(bool(enable)); -        }) -        .update() -    ; -    _tree->access<int>(get_arg_path("configure_beams", 0) / "value") -        .add_coerced_subscriber([this](int reg_value){ -            this->configure_beams(uint32_t(reg_value)); -        }) // No update! This would override the previous settings. -        .set_publisher([this](){ -            return this->user_reg_read32(RB_CHOOSE_BEAMS); -        }) -    ; - -    /**** Configure the digital gain controls *******************************/ -    for (size_t i = 0; i < EISCAT_NUM_ANTENNAS; i++) { -        _tree->access<double>(get_arg_path("gain", i) / "value") -            .set_coercer([](double gain){ -                return std::max(-16.0, std::min(16.0, gain)); -            }) -            .add_coerced_subscriber([this, i](double gain){ -                this->set_antenna_gain(i, gain); -            }) -            .update() -        ; -    } - -    /**** Set up legacy compatible properties *******************************/ -    // For use with multi_usrp APIs etc. -    // For legacy prop tree init: -    fs_path fe_path = fs_path("dboards") / "A" / "rx_frontends"; - -    // The EISCAT dboards have 16 frontends total, but they map to 10 beams -    // each through a matrix of FIR filters and summations, and then only 5 of -    // those channels go out through the Noc-Shell. -    // UHD will thus get much less confused if we create 5 fake frontends (i.e., -    // number of Noc-Block-ports). Since we have no control over the frontends, -    // nothing is lost here. -    for (size_t fe_idx = 0; fe_idx < _num_ports; fe_idx++) { -        _tree->create<std::string>(fe_path / fe_idx / "name") -            .set(str(boost::format("EISCAT Beam Contributions %d") % fe_idx)) -        ; -        _tree->create<std::string>(fe_path / fe_idx / "connection") -            .set("I") -        ; -        _tree->create<double>(fe_path / fe_idx / "freq" / "value") -            .set_coercer([this](const double freq){ -                return this->set_rx_frequency(freq, 0); -            }) -            .set_publisher([this](){ -                return this->get_rx_frequency(0); -            }) -        ; -        _tree->create<meta_range_t>(fe_path / fe_idx / "freq" / "range") -            .set(meta_range_t(EISCAT_CENTER_FREQ, EISCAT_CENTER_FREQ)) -        ; -        _tree->create<double>(fe_path / fe_idx / "gains" / "null" / "value") -            .set_coercer([this](const double gain){ -                return this->set_rx_gain(gain, 0); -            }) -            .set_publisher([this](){ -                return this->get_rx_gain(0); -            }) -        ; -        _tree->create<meta_range_t>(fe_path / fe_idx / "gains" / "null" / "range") -            .set(meta_range_t(EISCAT_DEFAULT_NULL_GAIN, EISCAT_DEFAULT_NULL_GAIN)) -        ; -        _tree->create<double>(fe_path / fe_idx / "bandwidth" / "value") -            .set_coercer([this](const double bw){ -                return this->set_rx_bandwidth(bw, 0); -            }) -            .set_publisher([this](){ -                return this->get_rx_bandwidth(0); -            }) -        ; -        _tree->create<meta_range_t>(fe_path / fe_idx / "bandwidth" / "range") -            .set(meta_range_t(EISCAT_DEFAULT_BANDWIDTH, EISCAT_DEFAULT_BANDWIDTH)) -        ; -        _tree->create<bool>(fe_path / fe_idx / "use_lo_offset") -            .set(false) -        ; -    } - -    auto antenna_options = std::vector<std::string>{"BF"}; -    for (size_t i = 0; i < EISCAT_NUM_ANTENNAS; i++) { -        antenna_options.push_back(str(boost::format("Rx%d") % i)); -        antenna_options.push_back(str(boost::format("BF%d") % i)); -    } -    antenna_options.push_back("FI0"); -    antenna_options.push_back("FI250"); -    antenna_options.push_back("FI500"); -    antenna_options.push_back("FI750"); -    for (size_t beam_idx = 0; beam_idx < _num_ports; beam_idx++) { -        _tree->create<std::string>(fe_path / beam_idx / "antenna" / "value") -            .set(EISCAT_DEFAULT_ANTENNA) -            .add_coerced_subscriber([this, beam_idx](const std::string &name){ -                this->set_rx_antenna(name, beam_idx); -            }) -            .set_publisher([this, beam_idx](){ -                return this->get_rx_antenna(beam_idx); -            }) -        ; -        _tree->create<std::vector<std::string>>( -                fe_path / beam_idx / "antenna" / "options") -            .set(antenna_options) -        ; -    } - -    // We can actually stream data to an EISCAT board, so it needs some tx -    // frontends too: -    fe_path = fs_path("dboards") / "A" / "tx_frontends"; -    for (size_t fe_idx = 0; fe_idx < _num_ports; fe_idx++) { -        _tree->create<std::string>(fe_path / fe_idx / "name") -            .set(str(boost::format("EISCAT Uplink %d") % fe_idx)) -        ; -    } - -    for (size_t i = 0; i < EISCAT_NUM_PORTS; i++) { -        _tree->create<uhd::time_spec_t>(get_arg_path("pseudo_stream_cmd", i) / "value") -            .add_coerced_subscriber([this, i](uhd::time_spec_t stream_time){ -                if (stream_time != uhd::time_spec_t(0.0)) { -                    uhd::stream_cmd_t cmd(uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS); -                    cmd.stream_now = false; -                    cmd.time_spec = stream_time; -                    this->issue_stream_cmd(cmd, i); -                } else { -                    this->issue_stream_cmd( -                        uhd::stream_cmd_t(uhd::stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS), -                        i -                    ); -                } -            }) -        ; -    } -    //FIXME elaborate this more, but for now it works. -    _tree->create<int>("rx_codecs/A/gains"); -    _tree->create<std::string>("rx_codecs/A/name").set("ADS54J66"); - - -    // There is only ever one EISCAT radio per mboard, so this should be unset -    // when we reach this line: -    UHD_ASSERT_THROW(not _tree->exists("tick_rate")); -    _tree->create<double>("tick_rate") -        .set(EISCAT_TICK_RATE) -        .set_coercer(boost::bind(&eiscat_radio_ctrl_impl::set_rate, this, _1)) -    ; -} - -eiscat_radio_ctrl_impl::~eiscat_radio_ctrl_impl() -{ -    UHD_LOG_TRACE("EISCAT", "eiscat_radio_ctrl_impl::dtor() "); -} - - -/**************************************************************************** - * Public API calls - ***************************************************************************/ -void eiscat_radio_ctrl_impl::set_tx_antenna(const std::string &, const size_t) -{ -    throw uhd::runtime_error("Cannot set Tx antenna on EISCAT daughterboard"); -} - -void eiscat_radio_ctrl_impl::set_rx_antenna( -        const std::string &ant, -        const size_t port -) { -    UHD_ASSERT_THROW(port < EISCAT_NUM_BEAMS); -    if (ant == "BF") { -        UHD_LOG_TRACE("EISCAT", "Setting antenna to 'BF' (which is a no-op)"); -        return; -    } -    if (ant.size() < 3) { -        throw uhd::value_error(str( -            boost::format("EISCAT: Invalid antenna selection: %s") -            % ant -        )); -    } - -    const std::string ant_mode = ant.substr(0, 2); -    const size_t antenna_idx = [&ant](){ -        try { -            return boost::lexical_cast<size_t>(ant.substr(2)); -        } catch (const boost::bad_lexical_cast&) { -            throw uhd::value_error(str( -                boost::format("EISCAT: Invalid antenna selection: %s") -                % ant -            )); -        } -    }(); - -    if (ant_mode == "BF") { -        int new_choose_beams = -            get_arg<int>("choose_beams") | EISCAT_SKIP_NEIGHBOURS; -        set_arg<int>("choose_beams", new_choose_beams); -        size_t beam_select_offset = -                (get_arg<int>("choose_beams") & EISCAT_CONTRIB_UPPER) ? -                EISCAT_NUM_PORTS : 0; -        const size_t beam_index = port + beam_select_offset; -        uhd::time_spec_t send_now(0.0); -        UHD_LOG_TRACE("EISCAT", str( -            boost::format("Setting block port %d to only receive from beam %d " -                          "connected to antenna %d via FIR matrix") -            % port -            % beam_index -            % antenna_idx -        )); -        for (size_t i = 0; i < EISCAT_NUM_ANTENNAS; i++) { -            select_filter( -                beam_index, -                i, -                (i == antenna_idx) ? -                    EISCAT_FIR_INDEX_IMPULSE : EISCAT_FIR_INDEX_ZEROS, -                send_now -            ); -        } -        enable_firs(true); -    } else if (ant_mode == "RX" or ant_mode == "Rx") { -        int new_choose_beams = -            get_arg<int>("choose_beams") | EISCAT_SKIP_NEIGHBOURS; -        set_arg<int>("choose_beams", new_choose_beams); -        UHD_LOG_TRACE("EISCAT", str( -            boost::format("Setting port %d to only receive on antenna %d " -                          "directly, bypassing neighbours and FIR matrix") -            % port % antenna_idx -        )); -        sr_write(SR_ANTENNA_SELECT_BASE + port, antenna_idx); -        enable_firs(false); -    } else if (ant_mode == "FI") { -        size_t beam_index = port % EISCAT_NUM_PORTS; -        UHD_LOG_TRACE("EISCAT", str( -            boost::format("Setting port %d to filter index %d on all antennas " -                          "using beam indices %d and %d.") -            % port -            % antenna_idx -            % beam_index % (beam_index + EISCAT_NUM_PORTS) -        )); -        // Note: antenna_idx is not indexing a physical antenna in this scenario. -        uhd::time_spec_t send_now(0.0); -        for (size_t i = 0; i < EISCAT_NUM_ANTENNAS; i++) { -            select_filter( -                beam_index, -                i, -                antenna_idx, -                send_now -            ); -            select_filter( -                beam_index + EISCAT_NUM_PORTS, -                i, -                antenna_idx, -                send_now -            ); -        } -        enable_firs(true); -    } else if (ant_mode == "CN") { -        const size_t beam_index = port % EISCAT_NUM_PORTS; -        UHD_LOG_TRACE("EISCAT", str( -            boost::format("Setting port %d to filter index %d on all antennas " -                          "using beam indices %d and %d.") -            % port -            % antenna_idx -            % beam_index % (beam_index + EISCAT_NUM_PORTS) -        )); -        // Note: antenna_idx is not indexing a physical antenna in this scenario. -        uhd::time_spec_t send_now(0.0); -        for (size_t i = 0; i < EISCAT_NUM_ANTENNAS; i+=2) { -            select_filter( -                beam_index, -                i, -                0, -                send_now -            ); -            select_filter( -                beam_index + EISCAT_NUM_PORTS, -                i, -                0, -                send_now -            ); -            select_filter( -                beam_index, -                i+1, -                antenna_idx, -                send_now -            ); -            select_filter( -                beam_index + EISCAT_NUM_PORTS, -                i+1, -                antenna_idx, -                send_now -            ); -        } -        enable_firs(true); -    } else { -        throw uhd::value_error(str( -            boost::format("EISCAT: Invalid antenna selection: %s") -            % ant -        )); -    } -} - -double eiscat_radio_ctrl_impl::get_tx_frequency(const size_t /* chan */) -{ -    UHD_LOG_WARNING("EISCAT", "Ignoring attempt to read Tx frequency"); -    return 0.0; -} - -double eiscat_radio_ctrl_impl::set_tx_frequency(const double /* freq */, const size_t /* chan */) -{ -    throw uhd::runtime_error("Cannot set Tx frequency on EISCAT daughterboard"); -} - -double eiscat_radio_ctrl_impl::set_rx_frequency(const double freq, const size_t chan) -{ -    if (freq != get_rx_frequency(chan)) { -        UHD_LOG_WARNING("EISCAT", "Ignoring attempt to set Rx frequency"); -    } -    return get_rx_frequency(chan); -} - -double eiscat_radio_ctrl_impl::set_rx_bandwidth(const double bandwidth, const size_t chan) -{ -    if (bandwidth != get_rx_bandwidth(chan)) { -        UHD_LOG_WARNING("EISCAT", "Ignoring attempt to set Rx bandwidth"); -    } -    return get_rx_bandwidth(chan); -} - - -double eiscat_radio_ctrl_impl::set_tx_gain(const double /* gain */, const size_t /* chan */) -{ -    throw uhd::runtime_error("Cannot set Tx gain on EISCAT daughterboard"); -} - -double eiscat_radio_ctrl_impl::set_rx_gain(const double gain, const size_t chan) -{ -    // TODO: Add ability to set digital gain or make it explicit this function is not supported. -    if (gain != get_rx_gain(chan)) { -        UHD_LOG_WARNING("EISCAT", "Ignoring attempt to set Rx gain."); -    } -    return get_rx_gain(chan); -} - -double eiscat_radio_ctrl_impl::set_rate(double rate) -{ -    if (rate != get_rate()) { -        UHD_LOG_WARNING("EISCAT", "Attempting to set sampling rate to invalid value " << rate); -    } -    return get_rate(); -} - -size_t eiscat_radio_ctrl_impl::get_chan_from_dboard_fe( -        const std::string &fe, -        const uhd::direction_t /* dir */ -) { -    return boost::lexical_cast<size_t>(fe); -} - -std::string eiscat_radio_ctrl_impl::get_dboard_fe_from_chan( -        const size_t chan, -        const uhd::direction_t /* dir */ -) { -    return std::to_string(chan); -} - -double eiscat_radio_ctrl_impl::get_output_samp_rate(size_t /* port */) -{ -    return EISCAT_RADIO_RATE; -} - -void eiscat_radio_ctrl_impl::set_rx_streamer(bool active, const size_t port) -{ -    UHD_RFNOC_BLOCK_TRACE() << "radio_ctrl_impl::set_rx_streamer() " << port << " -> " << active ; -    if (port > EISCAT_NUM_PORTS) { -        throw uhd::value_error(str( -            boost::format("[%s] Can't (un)register RX streamer on port %d (invalid port)") -            % unique_id() % port -        )); -    } -    _rx_streamer_active[port] = active; -    if (not check_radio_config()) { -        throw std::runtime_error(str( -            boost::format("[%s]: Invalid radio configuration.") -            % unique_id() -        )); -    } - -    if (list_upstream_nodes().empty() or not bool(get_arg<int>("use_prev"))) { -        UHD_LOG_DEBUG(unique_id(), "No prevs found, or prevs disabled, not passing on set_rx_streamer"); -    } else { -        UHD_LOG_DEBUG(unique_id(), "set_rx_streamer(): We have prevs, so passing on set_rx_streamer"); -        source_node_ctrl::sptr this_upstream_block_ctrl = -                boost::dynamic_pointer_cast<source_node_ctrl>(list_upstream_nodes().at(0).lock()); -        if (this_upstream_block_ctrl) { -            this_upstream_block_ctrl->set_rx_streamer(active, port); -        } else { -            UHD_LOG_WARNING(unique_id(), "Oh noes, couldn't lock sptr!"); -        } -    } -} - -void eiscat_radio_ctrl_impl::issue_stream_cmd(const uhd::stream_cmd_t &stream_cmd, const size_t chan) -{ -    std::lock_guard<std::mutex> lock(_mutex); - -    // Turn on/off top ones -    if (list_upstream_nodes().empty() or not bool(get_arg<int>("use_prev"))) { -        UHD_LOG_DEBUG(unique_id(), "No prevs found, or prevs disabled, not passing on stream cmd"); -    } else { -        UHD_LOG_DEBUG(unique_id(), "issue_stream_cmd(): We have prevs, so passing on stream command"); -        source_node_ctrl::sptr this_upstream_block_ctrl = -                boost::dynamic_pointer_cast<source_node_ctrl>(list_upstream_nodes().at(0).lock()); -        if (this_upstream_block_ctrl) { -            this_upstream_block_ctrl->issue_stream_cmd( -                    stream_cmd, -                    chan -            ); -        } else { -            UHD_LOG_WARNING(unique_id(), "Oh noes, couldn't lock sptr!"); -        } -    } - -    // Turn on/off this one -    UHD_LOGGER_DEBUG(unique_id()) << "eiscat_radio_ctrl_impl::issue_stream_cmd() " << chan << " " << char(stream_cmd.stream_mode); -    if (not _is_streamer_active(uhd::RX_DIRECTION, chan)) { -        UHD_RFNOC_BLOCK_TRACE() << "radio_ctrl_impl::issue_stream_cmd() called on inactive channel. Skipping." ; -        return; -    } -    UHD_ASSERT_THROW(stream_cmd.num_samps <= 0x0fffffff); -    _continuous_streaming[chan] = (stream_cmd.stream_mode == stream_cmd_t::STREAM_MODE_START_CONTINUOUS); - -    if (stream_cmd.stream_mode == stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS && -            stream_cmd.stream_now == false) { -        UHD_LOG_TRACE("EISCAT", "Stop cmd timed, setting cmd time!"); -        set_command_time(stream_cmd.time_spec, chan); -    } - -    //setup the mode to instruction flags -    typedef boost::tuple<bool, bool, bool, bool> inst_t; -    static const uhd::dict<stream_cmd_t::stream_mode_t, inst_t> mode_to_inst = boost::assign::map_list_of -                                                            //reload, chain, samps, stop -        (stream_cmd_t::STREAM_MODE_START_CONTINUOUS,   inst_t(true,  true,  false, false)) -        (stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS,    inst_t(false, false, false, true)) -        (stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_DONE, inst_t(false, false, true,  false)) -        (stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_MORE, inst_t(false, true,  true,  false)) -    ; - -    //setup the instruction flag values -    bool inst_reload, inst_chain, inst_samps, inst_stop; -    boost::tie(inst_reload, inst_chain, inst_samps, inst_stop) = mode_to_inst[stream_cmd.stream_mode]; - -    //calculate the word from flags and length -    uint32_t cmd_word = 0; -    cmd_word |= uint32_t((stream_cmd.stream_now)? 1 : 0) << 31; -    cmd_word |= uint32_t((inst_chain)?            1 : 0) << 30; -    cmd_word |= uint32_t((inst_reload)?           1 : 0) << 29; -    cmd_word |= uint32_t((inst_stop)?             1 : 0) << 28; -    cmd_word |= (inst_samps)? stream_cmd.num_samps : ((inst_stop)? 0 : 1); - -    //issue the stream command -    const uint64_t ticks = (stream_cmd.stream_now)? 0 : stream_cmd.time_spec.to_ticks(get_rate()); -    sr_write(regs::RX_CTRL_CMD, cmd_word, chan); -    sr_write(regs::RX_CTRL_TIME_HI, uint32_t(ticks >> 32), chan); -    sr_write(regs::RX_CTRL_TIME_LO, uint32_t(ticks >> 0),  chan); //latches the command -    UHD_LOG_INFO(unique_id(), "issued stream command."); -    if (stream_cmd.stream_mode == stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS && -            stream_cmd.stream_now == false) { -        UHD_LOG_TRACE("EISCAT", "Stop cmd timed, setting cmd time!"); -        set_command_time(uhd::time_spec_t(0.0), chan); -    } - -} - -bool eiscat_radio_ctrl_impl::check_radio_config() -{ -    const uint32_t config_beams = get_arg<int>("configure_beams"); -    bool skipping_neighbours = config_beams & EISCAT_SKIP_NEIGHBOURS; -    bool upper_contrib = config_beams & EISCAT_CONTRIB_UPPER; -    const fs_path rx_fe_path = fs_path("dboards/A/rx_frontends"); -    uint32_t chan_enables = 0; -    for (const auto &enb: _rx_streamer_active) { -        if (enb.second) { -            chan_enables |= (1<<enb.first); -        } -    } -    if (not skipping_neighbours) { -        chan_enables = chan_enables | (chan_enables << EISCAT_NUM_PORTS); -    } else if (upper_contrib) { -        chan_enables <<= EISCAT_NUM_PORTS; -    } -    UHD_LOG_TRACE("EISCAT", str( -        boost::format("check_radio_config(): Setting channel enables to 0x%02X" -                      " Using %s beams, %saccepting neighbour contributions") -        % chan_enables -        % (upper_contrib ? "upper" : "lower") -        % (skipping_neighbours ? "not " : "") -    )); -    sr_write("SR_RX_STREAM_ENABLE", chan_enables); - -    return true; -} - -void eiscat_radio_ctrl_impl::set_rpc_client( -    uhd::rpc_client::sptr rpcc, -    const uhd::device_addr_t &block_args -) { -    _rpcc = rpcc; -    _block_args = block_args; -    auto dboard_info = -        _rpcc->request<std::vector<std::map<std::string, std::string>>>( -                "get_dboard_info" -        ); -    _num_dboards = dboard_info.size(); -    UHD_LOG_DEBUG("EISCAT", "Using " << _num_dboards << " daughterboards."); -    if (_num_dboards == 1) { -        UHD_LOG_WARNING("EISCAT", -            "Found 1 dboard, expected 2 for optimal operation." -        ); -    } else if (_num_dboards > 2) { -        UHD_LOG_ERROR("EISCAT", "Detected too many dboards: " << _num_dboards); -        throw uhd::runtime_error("Too many dboards detected."); -    } - -    UHD_LOG_INFO( -        "EISCAT", -        "Finalizing dboard initialization; initializing JESD cores and ADCs." -    ); - -    /* Start of the ADC synchronization operation. -     * These steps must be repeated if any ADC fails its deframer check -     * Changing the sync line from SyncbAB to SyncnCD usually resolves the error -     */ -    const size_t possible_sync_combinations = 16; // 2 sync lines ^ (2 ADCs * 2 Daughtercards) -    for (size_t iteration = 0; iteration < possible_sync_combinations; iteration++) { -        UHD_LOG_INFO( -            "EISCAT", -            "looping to initialize JESD cores and ADCs." -        ); -        if (not assert_jesd_cores_initialized()) { -            throw uhd::runtime_error("Failed to initialize JESD cores and reset ADCs!"); -        } -        send_sysref(); - -        if (not assert_adcs_deframers()) { -            throw uhd::runtime_error("Failed to initialize ADCs and JESD deframers!"); -        } -        send_sysref(); -        std::this_thread::sleep_for(std::chrono::milliseconds(500)); - -        if (assert_deframer_status()) { -            return; -        } -    } - -    // Unable to find a sync line combination which works -    throw uhd::runtime_error("Failed to finalize JESD core setup!"); -} - -/**************************************************************************** - * Internal methods - ***************************************************************************/ -void eiscat_radio_ctrl_impl::write_fir_taps( -    const size_t fir_idx, -    const std::vector<eiscat_radio_ctrl_impl::fir_tap_t> &taps -) { -    if (taps.size() > EISCAT_NUM_FIR_TAPS) { -        throw uhd::value_error(str( -            boost::format("Too many FIR taps for EISCAT filters (%d)") -            % taps.size() -        )); -    } -    for (const auto &tap: taps) { -        if (tap > EISCAT_MAX_TAP_VALUE or tap < EISCAT_MIN_TAP_VALUE) { -            throw uhd::value_error(str( -                boost::format("Filter tap for filter_idx %d exceeds dynamic range (%d bits are allowed)") -                % fir_idx % EISCAT_BITS_PER_TAP -            )); -        } -    } - -    UHD_LOG_TRACE("EISCAT", str( -        boost::format("Writing %d filter taps for filter index %d") -        % taps.size() % fir_idx -    )); -    for (size_t i = 0; i < EISCAT_NUM_FIR_TAPS; i++) { -        // Payload: -        // - bottom 14 bits address, fir_idx * 16 + tap_index -        // - top 18 bits are value -        uint32_t reg_value = (fir_idx * 16) + i;; -        if (taps.size() > i) { -            reg_value |= (taps[i] & 0x3FFFF) << 14; -        } -        sr_write("SR_FIR_BRAM_WRITE_TAPS", reg_value); -    } -} - -void eiscat_radio_ctrl_impl::select_filter( -        const size_t beam_index, -        const size_t antenna_index, -        const size_t fir_index, -        const uhd::time_spec_t &time_spec, -        const bool write_time -) { -    if (antenna_index >= EISCAT_NUM_ANTENNAS) { -        throw uhd::value_error(str( -            boost::format("Antenna index %d out of range. There are %d antennas in EISCAT.") -            % antenna_index % EISCAT_NUM_ANTENNAS -        )); -    } -    if (beam_index >= EISCAT_NUM_BEAMS) { -        throw uhd::value_error(str( -            boost::format("Beam index %d out of range. " -                          "There are %d beam channels in EISCAT.") -            % beam_index -            % EISCAT_NUM_BEAMS -        )); -    } - -    UHD_LOGGER_TRACE("EISCAT") -        << "Selecting filter " << fir_index -        << " for beam " << beam_index -        << " and antenna " << antenna_index -    ; -    bool send_now = (time_spec == uhd::time_spec_t(0.0)); -    uint32_t reg_value = 0 -        | (fir_index * 16) -        | (antenna_index & 0xF) << 14 -        | (beam_index & 0xF) << 18 -        | send_now << 22 -    ; -    if (not send_now) { -        UHD_LOG_TRACE("EISCAT", str( -            boost::format("Filter selection will be applied at " -                          "time %f (0x%016X == %u). %s") -            % time_spec.get_full_secs() -            % time_spec.to_ticks(EISCAT_TICK_RATE) -            % time_spec.to_ticks(EISCAT_TICK_RATE) -            % (write_time ? "Writing time regs now." -                          : "Assuming time regs already up-to-date.") -        )); -        if (write_time) { -            set_fir_ctrl_time(time_spec); -        } -    } -    sr_write("SR_FIR_COMMANDS_RELOAD", reg_value); -} - -void eiscat_radio_ctrl_impl::set_fir_ctrl_time( -    const uhd::time_spec_t &time_spec -) { -    const uint64_t cmd_time_ticks = time_spec.to_ticks(EISCAT_TICK_RATE); -    sr_write( -        "SR_FIR_COMMANDS_CTRL_TIME_LO", -        uint32_t(cmd_time_ticks & 0xFFFFFFFF) -    ); -    sr_write( -        "SR_FIR_COMMANDS_CTRL_TIME_HI", -        uint32_t((cmd_time_ticks >> 32) & 0xFFFFFFFF) -    ); -} - -void eiscat_radio_ctrl_impl::set_antenna_gain( -    const size_t antenna_idx, -    const double normalized_gain -) { -    if (normalized_gain < -16.0 or normalized_gain > 16.0) { -        throw uhd::value_error(str( -            boost::format("Invalid digital gain value for antenna %d: %f") -            % antenna_idx % normalized_gain -        )); -    } - -    const auto fixpoint_gain = std::max<int32_t>( -        EISCAT_MIN_GAIN, -        std::min( -            EISCAT_MAX_GAIN, -            int32_t(normalized_gain * EISCAT_UNIT_GAIN) -        ) -    ); - -    UHD_LOG_TRACE("EISCAT", str( -        boost::format("Setting digital gain value for antenna %d to %f (%d)") -        % antenna_idx % normalized_gain % fixpoint_gain -    )); -    sr_write(SR_ANTENNA_GAIN_BASE + antenna_idx, fixpoint_gain); -} - -void eiscat_radio_ctrl_impl::configure_beams(uint32_t reg_value) -{ -    UHD_LOGGER_TRACE("EISCAT") -        << "Selecting " << -        ((reg_value & EISCAT_CONTRIB_UPPER) ? "upper" : "lower") << " beams."; -    UHD_LOGGER_TRACE("EISCAT") -        << ((reg_value & EISCAT_SKIP_NEIGHBOURS) ? "Disabling" : "Enabling") -        << " neighbour contributions."; -    UHD_LOGGER_TRACE("EISCAT") -        << ((reg_value & EISCAT_BYPASS_MATRIX) ? "Disabling" : "Enabling") -        << " FIR matrix."; -    UHD_LOGGER_TRACE("EISCAT") -        << ((reg_value & EISCAT_OUTPUT_COUNTER) ? "Enabling" : "Disabling") -        << " counter."; -    UHD_LOG_TRACE("EISCAT", str( -        boost::format("Setting SR_BEAMS_TO_NEIGHBOR to 0x%08X.") -        % reg_value -    )); -    sr_write("SR_BEAMS_TO_NEIGHBOR", reg_value); -} - -void eiscat_radio_ctrl_impl::set_beam_selection(int beam_selection) -{ -    UHD_ASSERT_THROW(beam_selection < 4 and beam_selection >= 0); -    const uint32_t old_value = user_reg_read32(RB_CHOOSE_BEAMS); -    const uint32_t new_value = -        (old_value & (~uint32_t(EISCAT_CONTRIB_UPPER|EISCAT_SKIP_NEIGHBOURS))) -        | (uint32_t(beam_selection) -                & uint32_t(EISCAT_CONTRIB_UPPER|EISCAT_SKIP_NEIGHBOURS)) -    ; -    configure_beams(new_value); -} - -void eiscat_radio_ctrl_impl::enable_firs(bool enable) -{ -    const uint32_t old_value = user_reg_read32(RB_CHOOSE_BEAMS); -    const uint32_t new_value = enable ? -        (old_value & ~EISCAT_BYPASS_MATRIX) -        : old_value | EISCAT_BYPASS_MATRIX -    ; -    configure_beams(new_value); -} - -void eiscat_radio_ctrl_impl::send_sysref() -{ -    if (_block_args.has_key("use_mpm_sysref")) { -        _rpcc->notify_with_token("db_0_send_sysref"); -    } else { -        // This value needs to be big enough that we actually hit it between -        // reading back the time, and applying the command: -        const int CMD_DELAY_MS = 100; -        auto sysref_time = get_time_now() -                + uhd::time_spec_t(double(CMD_DELAY_MS * 1000)); -        uint64_t sysref_time_ticks = sysref_time.to_ticks(EISCAT_TICK_RATE); -        // The tick value must be even, or we'd still have the 180 degree phase -        // ambiguity! The actual value doesn't matter. -        sysref_time_ticks += sysref_time_ticks % 2; -        set_command_time(uhd::time_spec_t::from_ticks( -            sysref_time_ticks, EISCAT_TICK_RATE -        )); -        this->sr_write("SR_SYSREF", 1); -        std::this_thread::sleep_for(std::chrono::milliseconds(CMD_DELAY_MS)); -    } -} - -void eiscat_radio_ctrl_impl::enable_counter(bool enable) -{ -    const uint32_t old_value = user_reg_read32(RB_CHOOSE_BEAMS); -    const uint32_t new_value = enable ? -        old_value | EISCAT_OUTPUT_COUNTER -        : (old_value & ~EISCAT_OUTPUT_COUNTER) -    ; -    configure_beams(new_value); -} - -bool eiscat_radio_ctrl_impl::assert_jesd_cores_initialized() -{ -    if (_num_dboards == 1) { -        return _rpcc->request_with_token<bool>("db_0_init_jesd_core_reset_adcs"); -    } -    return _rpcc->request_with_token<bool>("db_0_init_jesd_core_reset_adcs") -        and _rpcc->request_with_token<bool>("db_1_init_jesd_core_reset_adcs"); -} - -bool eiscat_radio_ctrl_impl::assert_adcs_deframers() -{ -    if (_num_dboards == 1) { -        return _rpcc->request_with_token<bool>("db_0_init_adcs_and_deframers"); -    } -    return _rpcc->request_with_token<bool>("db_0_init_adcs_and_deframers") -        and _rpcc->request_with_token<bool>("db_1_init_adcs_and_deframers"); -} - -bool eiscat_radio_ctrl_impl::assert_deframer_status() -{ -    if (_num_dboards == 1) { -        return _rpcc->request_with_token<bool>("db_0_check_deframer_status"); -    } -    return _rpcc->request_with_token<bool>("db_0_check_deframer_status") -        and _rpcc->request_with_token<bool>("db_1_check_deframer_status"); -} - -/**************************************************************************** - * Registry - ***************************************************************************/ -UHD_RFNOC_BLOCK_REGISTER(eiscat_radio_ctrl, "EISCATRadio"); diff --git a/host/lib/usrp/dboard/eiscat/eiscat_radio_ctrl_impl.hpp b/host/lib/usrp/dboard/eiscat/eiscat_radio_ctrl_impl.hpp deleted file mode 100644 index 3ce0b48fd..000000000 --- a/host/lib/usrp/dboard/eiscat/eiscat_radio_ctrl_impl.hpp +++ /dev/null @@ -1,295 +0,0 @@ -// -// Copyright 2017 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#ifndef INCLUDED_LIBUHD_RFNOC_EISCAT_RADIO_CTRL_IMPL_HPP -#define INCLUDED_LIBUHD_RFNOC_EISCAT_RADIO_CTRL_IMPL_HPP - -#include <uhd/types/direction.hpp> -#include <uhdlib/rfnoc/rpc_block_ctrl.hpp> -#include <uhdlib/rfnoc/radio_ctrl_impl.hpp> - -namespace uhd { -    namespace rfnoc { - -/*! \brief Provide access to an EISCAT radio, including beamformer. - * - * Note: This will control both daughterboards. Since we have a single RFNoC - * block, we only have one of these per motherboard. - * - * EISCAT radios have a whole bunch of features which don't have APIs provided - * by radio_ctrl. This means the most interesting features are controlled by - * set_arg() and get_arg(). Notable exception is set_rx_antenna(), which is - * heavily abused for all sorts of things. - * - * List of relevant args: - * - sysref (bool): Write to this to trigger a SYSREF pulse to *both* - *                  daughterboards. Will honor command time. Will always return - *                  true when read. - * - gain (double): Set the gain for antenna X, where X is the set_arg() `port` - *                  value. The gain is normalized in [0,1]. Can be read to get - *                  the current value. Example: `set_arg("gain", 0.5, 5)` will - *                  set the digital gain for antenna 5 to mid-point. - * - fir_ctrl_time (time_spec_t): This time will be used for following - *                                fir_select writes. Will return the last value - *                                that was written. - * - fir_select (int): Will queue a filter for manipulating a specific - *                     contribution. The value is the filter index in the BRAM. - *                     The port parameter specifies which filter; filters are - *                     indexed 0...159 using the equation beam_index * 16 + - *                     antenna_idx. Example: `set_arg("fir_select", 357, 16)` - *                     will apply filter number 357 to the zeroth antenna for - *                     beam number 1 (i.e. the second beam). Returns the last - *                     value that was written. May be incorrect before written - *                     for the first time. - * - fir_taps (vector<int32_t>): Updates FIR tap values in the BRAM. Port is - *                               the filter index. Will always return an impulse - *                               response, not the actual filter value. - * - assert_adcs_deframers (bool): Writing this does nothing. Reading it back - *                                 will run the initialization of ADCs and - *                                 deframers. Return value is success. - * - assert_deframer_status (bool): Writing this does nothing. Reading it will - *                                  run the final step of the JESD deframer - *                                  initialization routine. Returns success. - * - choose_beams (int): Configures beam selection (upper, lower, are neighbour - *                       contributions included). See set_beam_selection() for - *                       details. - * - enable_firs (int): Can be used to disable fir FIR matrix. This routes the - *                      JESD output directly to the noc_shell. - * - enable_counter (int): If the feature is available in the given FPGA image, - *                         setting this to true will disable the JESD core - *                         output and will input a counter signal (ramp) - *                         instead. - * - configure_beams (int): Danger, danger: Directly writes the - *                          SR_BEAMS_TO_NEIGHBOR register. Writing this can put - *                          some of the other properties out of sync, because - *                          writing to those will also write to this, but not - *                          vice versa. - * - * - * ## Time-aligned synchronization sequence: - * - * 0. Make sure all devices are getting the same ref clock and PPS! - * 1. Call set_command_time() with the same time on all blocks (make it far - *    enough in the future) - * 2. Call set_arg<bool>("sysref") on all blocks. This should SYSREF all dboards - *    synchronously. - * 3. On all blocks, call get_arg<bool>("assert_adcs_deframers") and verify it - *    returns true. - * 4. Repeat steps 1 and 2 with, obviously, another time that's in the future. - * 5. On all blocks, call get_arg<bool>("assert_deframer_status") and make sure - *    it returned true. - */ -class eiscat_radio_ctrl_impl : public radio_ctrl_impl, public rpc_block_ctrl -{ -public: -    using sptr = boost::shared_ptr<eiscat_radio_ctrl_impl>; -    using fir_tap_t = int32_t; // See also EISCAT_BITS_PER_TAP - -    /************************************************************************ -     * Structors -     ***********************************************************************/ -    UHD_RFNOC_RADIO_BLOCK_CONSTRUCTOR_DECL(eiscat_radio_ctrl) -    virtual ~eiscat_radio_ctrl_impl(); - -    /************************************************************************ -     * API calls -     * Note: Tx calls are here mostly to throw errors. -     ***********************************************************************/ -    //! Returns the actual tick rate. Will display a warning if rate is not that -    // value. -    double set_rate(double rate); - -    //! \throws uhd::runtime_error -    void set_tx_antenna(const std::string &ant, const size_t chan); - -    /*! Configures FPGA switching for antenna selection -     * -     * Valid antenna values: -     * - BF: This is the default. Will apply the beamforming matrix in whatever -     *   state it currently is. -     * - RX0...RX15: Will mux the antenna signal 0...15 straight to this -     *   channel. Note that this will disable the FIR matrix entirely, and will -     *   also disable contributions from other USRPs globally. -     * - BF0...BF15: Will configure the FIR filter matrix such that only the -     *   contributions from antenna 0...15 are passed to this channel. This -     *   should produce the same signal as RX0..RX15, reduced by 12 dB (because -     *   the FIR matri needs to account for bit growth from adding 16 channels). -     *   Will also disable contributions from other channels globally. -     * - FI$idx: Here, $idx is a number (the filter index, hence the name). -     *   This will apply filter index $idx to all input channels. Useful for -     *   testing actual beamforming applications, when the same signal is -     *   applied to all inputs. -     * -     * Note that this is very useful for testing and debugging. For actual -     * beamforming operations, this API call won't be enough. Rather, set this -     * to 'BF' (or don't do anything) and use the block properties -     * -     * \throws uhd::value_error if the antenna value was not valid -     */ -    void set_rx_antenna(const std::string &ant, const size_t chan); - -    //! \throws uhd::runtime_error -    double set_tx_frequency(const double freq, const size_t chan); -    //! \returns Some value in the EISCAT passband -    double set_rx_frequency(const double freq, const size_t chan); -    //! \returns Width of the EISCAT analog frontend filters -    double set_rx_bandwidth(const double bandwidth, const size_t chan); -    //! \throws uhd::runtime_error -    double get_tx_frequency(const size_t chan); - -    //! \throws uhd::runtime_error -    double set_tx_gain(const double gain, const size_t chan); -    //! \returns zero -    double set_rx_gain(const double gain, const size_t chan); - -    size_t get_chan_from_dboard_fe(const std::string &fe, const uhd::direction_t dir); -    std::string get_dboard_fe_from_chan(const size_t chan, const uhd::direction_t dir); - -    //! \returns The EISCAT sampling rate -    double get_output_samp_rate(size_t port); - -    void set_rx_streamer(bool active, const size_t port); -    void issue_stream_cmd(const uhd::stream_cmd_t &stream_cmd, const size_t port); - -protected: -    virtual bool check_radio_config(); - -    /*! Finalize initialization sequence (ADCs, deframers) etc. -     */ -    void set_rpc_client( -        uhd::rpc_client::sptr rpcc, -        const uhd::device_addr_t &block_args -    ); - -private: -    /************************************************************************* -     * Private methods -     * To control the dboard (and execute these), take a look at the block -     * properties. -     ************************************************************************/ -    /*! Write filter taps for a specific FIR filter. -     * -     * Note: If the number of taps is smaller than the number of available -     * filter taps, it is padded with zero (i.e., all taps are always written -     * and this can't be use to partially update filters). -     * -     * \param fir_idx The index of the FIR filter we are reprogramming -     * \param taps A list of FIR filter taps for this filter. -     * -     * \throws uhd::value_error if the number of taps is longer than the number -     *                          of taps that the filter can handle, or if any -     *                          tap has more bits than allowed. -     */ -    void write_fir_taps( -        const size_t fir_idx, -        const std::vector<fir_tap_t> &taps -    ); - -    /*! Choose a filter to be applied between an output beam and antenna input -     * -     * \param beam_index Beam index -     * \param antenna_index Antenna index -     * \param fir_index The index of the FIR filter taps that get applied -     * \param time_spec If non-zero, the taps get applied at this time. -     *                  Otherwise, they get sent out now. -     * \param write_time If false, time will never get written *even if* it is -     *                   non-zero. The assumption is that someone else wrote -     *                   the value previously -     *                   \param write_time If false, time will never get written *even if* it is -     *                                     non-zero. The assumption is that someone else wrote -     *                                     the value previously  -     */ -    void select_filter( -        const size_t beam_index, -        const size_t antenna_index, -        const size_t fir_index, -        const uhd::time_spec_t &time_spec, -        const bool write_time=true -    ); - - -    /*! Sets the command time for the next call to select_filter() -     * -     * \param time_spec This value gets written to the FPGA and is applied to -     *                  *all* subsequent filter selections. To request -     *                  immediate application of filters, set this to zero. -     */ -    void set_fir_ctrl_time(const uhd::time_spec_t &time_spec); - -    /*! Sets the digital gain on a specific antenna -     * -     * \param antenna_idx Antenna for which this gain setting applies -     * \param normalized_gain A value in [0, 1] which gets converted to a -     *                        digital gain value -     */ -    void set_antenna_gain( -        const size_t antenna_idx, -        const double normalized_gain -    ); - -    /*! Directly writes a value to the beam configuration register. -     */ -    void configure_beams(uint32_t reg_value); - -    /*! Controls selection of beams coming from the FIR matrix. -     * -     * The following values are allowed: -     * - 0: We stream the lower 5 beams, plus the neighbours contribution -     * - 1: We stream the upper 5 beams, plus the neighbours contribution -     * - 2: We stream the lower 5 beams, without the neighbours contribution -     * - 3: We stream the upper 5 beams, without the neighbours contribution -     */ -    void set_beam_selection(int beam_selection); - -    /*! Controls if we're using the FIR matrix -     * -     * If this is false, the beam selection is irrelevant. -     */ -    void enable_firs(bool enable); - -    /*! Enables counter instead of JESD core output -     */ -    void enable_counter(bool enable); - -    //! Sends a SYSREF pulse. Device arg use_mpm_sysref can be used to send it -    // via MPM. Default is to send it via CHDR, in which case calling this -    // function *will modify the command time!*, but it will ensure that the -    // sysref is sent on an even time -    void send_sysref(); - -    //! Run initialization of JESD cores, put ADCs into reset -    bool assert_jesd_cores_initialized(); - -    //! Run initialization of ADCs and deframers; returns success status -    bool assert_adcs_deframers(); - -    //! Run final step of JESD core setup; returns success status -    bool assert_deframer_status(); - -    /*! The number of channels this block outputs -     * -     * This is *not* the number of antennas, but the number of streams a single -     * block outputs to the crossbar. -     */ -    size_t _num_ports; - -    //! Running with 1 dboard is theoretically possible; thus, store the -    // number of active dboards. -    size_t _num_dboards = 0; - -    //! Additional block args; gets set during set_rpc_client() -    uhd::device_addr_t _block_args; - -    /*! Reference to the RPC client -     */ -    uhd::rpc_client::sptr _rpcc; - -}; /* class radio_ctrl_impl */ - -}} /* namespace uhd::rfnoc */ - -#endif /* INCLUDED_LIBUHD_RFNOC_EISCAT_RADIO_CTRL_IMPL_HPP */ - diff --git a/host/lib/usrp/dboard/magnesium/magnesium_radio_control.cpp b/host/lib/usrp/dboard/magnesium/magnesium_radio_control.cpp index dc78cee7d..13186e146 100644 --- a/host/lib/usrp/dboard/magnesium/magnesium_radio_control.cpp +++ b/host/lib/usrp/dboard/magnesium/magnesium_radio_control.cpp @@ -1,5 +1,6 @@  //  // Copyright 2017 Ettus Research, a National Instruments Company +// Copyright 2019 Ettus Research, a National Instruments Brand  //  // SPDX-License-Identifier: GPL-3.0-or-later  // @@ -8,9 +9,7 @@  #include "magnesium_constants.hpp"  #include "magnesium_gain_table.hpp"  #include <uhd/exception.hpp> -#include <uhd/rfnoc/node_ctrl_base.hpp>  #include <uhd/rfnoc/registry.hpp> -#include <uhd/transport/chdr.hpp>  #include <uhd/types/direction.hpp>  #include <uhd/types/eeprom.hpp>  #include <uhd/utils/algorithm.hpp> diff --git a/host/lib/usrp/dboard/magnesium/magnesium_radio_control_init.cpp b/host/lib/usrp/dboard/magnesium/magnesium_radio_control_init.cpp index db2ec9494..d8a1ccba8 100644 --- a/host/lib/usrp/dboard/magnesium/magnesium_radio_control_init.cpp +++ b/host/lib/usrp/dboard/magnesium/magnesium_radio_control_init.cpp @@ -6,7 +6,6 @@  #include "magnesium_constants.hpp"  #include "magnesium_radio_control.hpp" -#include <uhd/transport/chdr.hpp>  #include <uhd/types/eeprom.hpp>  #include <uhd/types/sensors.hpp>  #include <uhd/utils/log.hpp> diff --git a/host/lib/usrp/dboard/rhodium/rhodium_radio_control.cpp b/host/lib/usrp/dboard/rhodium/rhodium_radio_control.cpp index a3b072e74..df2c3aadd 100644 --- a/host/lib/usrp/dboard/rhodium/rhodium_radio_control.cpp +++ b/host/lib/usrp/dboard/rhodium/rhodium_radio_control.cpp @@ -9,7 +9,6 @@  #include "rhodium_constants.hpp"  #include <uhd/exception.hpp>  #include <uhd/rfnoc/registry.hpp> -#include <uhd/transport/chdr.hpp>  #include <uhd/types/direction.hpp>  #include <uhd/types/eeprom.hpp>  #include <uhd/utils/algorithm.hpp> diff --git a/host/lib/usrp/dboard/rhodium/rhodium_radio_control_init.cpp b/host/lib/usrp/dboard/rhodium/rhodium_radio_control_init.cpp index d6b7afd09..850e5aff3 100644 --- a/host/lib/usrp/dboard/rhodium/rhodium_radio_control_init.cpp +++ b/host/lib/usrp/dboard/rhodium/rhodium_radio_control_init.cpp @@ -7,7 +7,6 @@  #include "rhodium_constants.hpp"  #include "rhodium_radio_control.hpp" -#include <uhd/transport/chdr.hpp>  #include <uhd/types/eeprom.hpp>  #include <uhd/types/sensors.hpp>  #include <uhd/utils/algorithm.hpp> diff --git a/host/lib/usrp/device3/CMakeLists.txt b/host/lib/usrp/device3/CMakeLists.txt deleted file mode 100644 index 979225c2c..000000000 --- a/host/lib/usrp/device3/CMakeLists.txt +++ /dev/null @@ -1,15 +0,0 @@ -# -# Copyright 2014 Ettus Research LLC -# Copyright 2018 Ettus Research, a National Instruments Company -# -# SPDX-License-Identifier: GPL-3.0-or-later -# - -######################################################################## -# This file included, use CMake directory variables -######################################################################## - -LIBUHD_APPEND_SOURCES( -    ${CMAKE_CURRENT_SOURCE_DIR}/device3_impl.cpp -    ${CMAKE_CURRENT_SOURCE_DIR}/device3_io_impl.cpp -) diff --git a/host/lib/usrp/device3/device3_flow_ctrl.hpp b/host/lib/usrp/device3/device3_flow_ctrl.hpp deleted file mode 100644 index fd445effd..000000000 --- a/host/lib/usrp/device3/device3_flow_ctrl.hpp +++ /dev/null @@ -1,306 +0,0 @@ -// -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#ifndef INCLUDED_DEVICE3_FLOW_CTRL_HPP -#define INCLUDED_DEVICE3_FLOW_CTRL_HPP - -#include "device3_impl.hpp" -#include <uhd/transport/vrt_if_packet.hpp> -#include <uhd/transport/zero_copy.hpp> -#include <uhd/types/sid.hpp> -#include <uhd/utils/log.hpp> -#include <boost/shared_ptr.hpp> - -namespace uhd { namespace usrp { - -//! Stores the state of RX flow control -struct rx_fc_cache_t -{ -    rx_fc_cache_t() -        : interval(0) -        , last_byte_count(0) -        , total_bytes_consumed(0) -        , total_packets_consumed(0) -        , seq_num(0) -    { -    } - -    //! Flow control interval in bytes -    size_t interval; -    //! Byte count at last flow control packet -    uint32_t last_byte_count; -    //! This will wrap around, but that's OK, because math. -    uint32_t total_bytes_consumed; -    //! This will wrap around, but that's OK, because math. -    uint32_t total_packets_consumed; -    //! Sequence number of next flow control packet -    uint64_t seq_num; -    uhd::sid_t sid; -    uhd::transport::zero_copy_if::sptr xport; -    std::function<uint32_t(uint32_t)> to_host; -    std::function<uint32_t(uint32_t)> from_host; -    std::function<void( -        const uint32_t* packet_buff, uhd::transport::vrt::if_packet_info_t&)> -        unpack; -    std::function<void(uint32_t* packet_buff, uhd::transport::vrt::if_packet_info_t&)> -        pack; -}; - -/*! Send out RX flow control packets. - * - * This function handles updating the counters for the consumed - * bytes and packets, determines if a flow control message is - * is necessary, and sends one if it is.  Passing a nullptr for - * the buff parameter will skip the counter update. - * - * \param fc_cache RX flow control state information - * \param buff Receive buffer.  Setting to nullptr will - *             skip the counter update. - */ -inline bool rx_flow_ctrl( -    boost::shared_ptr<rx_fc_cache_t> fc_cache, uhd::transport::managed_buffer::sptr buff) -{ -    // If the caller supplied a buffer -    if (buff) { -        // Unpack the header -        uhd::transport::vrt::if_packet_info_t packet_info; -        packet_info.num_packet_words32 = buff->size() / sizeof(uint32_t); -        const uint32_t* pkt            = buff->cast<const uint32_t*>(); -        try { -            fc_cache->unpack(pkt, packet_info); -        } catch (const std::exception& ex) { -            // Log and ignore -            UHD_LOGGER_ERROR("RX FLOW CTRL") -                << "Error unpacking packet: " << ex.what() << std::endl; -            return true; -        } - -        // Update counters assuming the buffer is a consumed packet -        if (not packet_info.error) { -            const size_t bytes = 4 * (packet_info.num_header_words32 + packet_info.num_payload_words32); -            fc_cache->total_bytes_consumed += bytes; -            fc_cache->total_packets_consumed++; -        } -    } - -    // Just return if there is no need to send a flow control packet -    if (fc_cache->total_bytes_consumed - fc_cache->last_byte_count < fc_cache->interval) { -        return true; -    } - -    // Time to send a flow control packet -    // Get a send buffer -    uhd::transport::managed_send_buffer::sptr fc_buff = -        fc_cache->xport->get_send_buff(0.0); -    if (not fc_buff) { -        throw uhd::runtime_error("rx_flowctrl timed out getting a send buffer"); -    } -    uint32_t* pkt = fc_buff->cast<uint32_t*>(); - -    // load packet info -    uhd::transport::vrt::if_packet_info_t packet_info; -    packet_info.packet_type = uhd::transport::vrt::if_packet_info_t::PACKET_TYPE_FC; -    packet_info.num_payload_words32 = uhd::usrp::DEVICE3_FC_PACKET_LEN_IN_WORDS32; -    packet_info.num_payload_bytes   = packet_info.num_payload_words32 * sizeof(uint32_t); -    packet_info.packet_count        = fc_cache->seq_num++; -    packet_info.sob                 = false; -    packet_info.eob                 = false; -    packet_info.error               = false; -    packet_info.fc_ack              = false; -    packet_info.sid                 = fc_cache->sid.get(); -    packet_info.has_sid             = true; -    packet_info.has_cid             = false; -    packet_info.has_tsi             = false; -    packet_info.has_tsf             = false; -    packet_info.has_tlr             = false; - -    // Load Header: -    fc_cache->pack(pkt, packet_info); -    // Load Payload: Packet count, and byte count -    pkt[packet_info.num_header_words32 + uhd::usrp::DEVICE3_FC_PACKET_COUNT_OFFSET] = -        fc_cache->from_host(fc_cache->total_packets_consumed); -    pkt[packet_info.num_header_words32 + uhd::usrp::DEVICE3_FC_BYTE_COUNT_OFFSET] = -        fc_cache->from_host(fc_cache->total_bytes_consumed); - -    // send the buffer over the interface -    fc_buff->commit(sizeof(uint32_t) * (packet_info.num_packet_words32)); - -    // update byte count -    fc_cache->last_byte_count = fc_cache->total_bytes_consumed; - -    return true; -} - -/*! Handle RX flow control ACK packets. - * - */ -inline void handle_rx_flowctrl_ack( -    boost::shared_ptr<rx_fc_cache_t> fc_cache, const uint32_t* payload) -{ -    const uint32_t pkt_count  = fc_cache->to_host(payload[0]); -    const uint32_t byte_count = fc_cache->to_host(payload[1]); -    if (fc_cache->total_bytes_consumed != byte_count) { -        UHD_LOGGER_DEBUG("device3") -            << "oh noes: byte_count==" << byte_count -            << "  total_bytes_consumed==" << fc_cache->total_bytes_consumed << std::hex -            << " sid==" << fc_cache->sid << std::dec << std::endl; -    } -    fc_cache->total_bytes_consumed   = byte_count; -    fc_cache->total_packets_consumed = pkt_count; // guess we need a pkt offset too? - -    // This will send a flow control packet if there is a significant discrepancy -    rx_flow_ctrl(fc_cache, nullptr); -} - -//! Stores the state of TX flow control -struct tx_fc_cache_t -{ -    tx_fc_cache_t(uint32_t capacity) -        : last_byte_ack(0) -        , last_seq_ack(0) -        , byte_count(0) -        , pkt_count(0) -        , window_size(capacity) -        , fc_ack_seqnum(0) -        , fc_received(false) -    { -    } - -    uint32_t last_byte_ack; -    uint32_t last_seq_ack; -    uint32_t byte_count; -    uint32_t pkt_count; -    uint32_t window_size; -    uint32_t fc_ack_seqnum; -    bool fc_received; -    std::function<uint32_t(uint32_t)> to_host; -    std::function<uint32_t(uint32_t)> from_host; -    std::function<void( -        const uint32_t* packet_buff, uhd::transport::vrt::if_packet_info_t&)> -        unpack; -    std::function<void(uint32_t* packet_buff, uhd::transport::vrt::if_packet_info_t&)> -        pack; -}; - -inline bool tx_flow_ctrl(boost::shared_ptr<tx_fc_cache_t> fc_cache, -    uhd::transport::zero_copy_if::sptr xport, -    uhd::transport::managed_buffer::sptr buff) -{ -    while (true) { -        // If there is space -        if (fc_cache->window_size - (fc_cache->byte_count - fc_cache->last_byte_ack) -            >= buff->size()) { -            // All is good - packet will be sent -            fc_cache->byte_count += buff->size(); -            // Round up to nearest word -            if (fc_cache->byte_count % uhd::usrp::DEVICE3_LINE_SIZE) { -                fc_cache->byte_count += -                    uhd::usrp::DEVICE3_LINE_SIZE -                    - (fc_cache->byte_count % uhd::usrp::DEVICE3_LINE_SIZE); -            } -            fc_cache->pkt_count++; -            return true; -        } - -        // Look for a flow control message to update the space available in the buffer. -        uhd::transport::managed_recv_buffer::sptr buff = xport->get_recv_buff(0.1); -        if (buff) { -            uhd::transport::vrt::if_packet_info_t if_packet_info; -            if_packet_info.num_packet_words32 = buff->size() / sizeof(uint32_t); -            const uint32_t* packet_buff       = buff->cast<const uint32_t*>(); -            try { -                fc_cache->unpack(packet_buff, if_packet_info); -            } catch (const std::exception& ex) { -                UHD_LOGGER_ERROR("TX FLOW CTRL") -                    << "Error unpacking flow control packet: " << ex.what() << std::endl; -                continue; -            } - -            if (if_packet_info.packet_type -                != uhd::transport::vrt::if_packet_info_t::PACKET_TYPE_FC) { -                UHD_LOGGER_ERROR("TX FLOW CTRL") -                    << "Unexpected packet received by flow control handler: " -                    << if_packet_info.packet_type << std::endl; -                continue; -            } - -            const uint32_t* payload   = &packet_buff[if_packet_info.num_header_words32]; -            const uint32_t pkt_count  = fc_cache->to_host(payload[0]); -            const uint32_t byte_count = fc_cache->to_host(payload[1]); - -            // update the amount of space -            fc_cache->last_byte_ack = byte_count; -            fc_cache->last_seq_ack  = pkt_count; - -            fc_cache->fc_received = true; -        } -    } -    return false; -} - -inline void tx_flow_ctrl_ack(boost::shared_ptr<tx_fc_cache_t> fc_cache, -    uhd::transport::zero_copy_if::sptr send_xport, -    uhd::sid_t send_sid) -{ -    if (not fc_cache->fc_received) { -        return; -    } - -    // Time to send a flow control ACK packet -    // Get a send buffer -    uhd::transport::managed_send_buffer::sptr fc_buff = send_xport->get_send_buff(0.0); -    if (not fc_buff) { -        UHD_LOGGER_ERROR("tx_flow_ctrl_ack") << "timed out getting a send buffer"; -        return; -    } -    uint32_t* pkt = fc_buff->cast<uint32_t*>(); - -    // Load packet info -    uhd::transport::vrt::if_packet_info_t packet_info; -    packet_info.packet_type = uhd::transport::vrt::if_packet_info_t::PACKET_TYPE_ACK; -    packet_info.num_payload_words32 = uhd::usrp::DEVICE3_FC_PACKET_LEN_IN_WORDS32; -    packet_info.num_payload_bytes   = packet_info.num_payload_words32 * sizeof(uint32_t); -    packet_info.packet_count        = fc_cache->fc_ack_seqnum++; -    packet_info.sob                 = false; -    packet_info.eob                 = true; -    packet_info.error               = false; -    packet_info.fc_ack              = false; -    packet_info.sid                 = send_sid.get(); -    packet_info.has_sid             = true; -    packet_info.has_cid             = false; -    packet_info.has_tsi             = false; -    packet_info.has_tsf             = false; -    packet_info.has_tlr             = false; - -    // Load Header: -    fc_cache->pack(pkt, packet_info); - -    // Update counters to include this packet -    size_t fc_ack_pkt_size = sizeof(uint32_t) * (packet_info.num_packet_words32); -    fc_cache->byte_count += fc_ack_pkt_size; -    // Round up to nearest word -    if (fc_cache->byte_count % uhd::usrp::DEVICE3_LINE_SIZE) { -        fc_cache->byte_count += uhd::usrp::DEVICE3_LINE_SIZE -                                - (fc_cache->byte_count % uhd::usrp::DEVICE3_LINE_SIZE); -    } -    fc_cache->pkt_count++; - -    // Load Payload: Packet count, and byte count -    pkt[packet_info.num_header_words32 + uhd::usrp::DEVICE3_FC_PACKET_COUNT_OFFSET] = -        fc_cache->from_host(fc_cache->pkt_count); -    pkt[packet_info.num_header_words32 + uhd::usrp::DEVICE3_FC_BYTE_COUNT_OFFSET] = -        fc_cache->from_host(fc_cache->byte_count); - -    // Send the buffer over the interface -    fc_buff->commit(fc_ack_pkt_size); - -    // Reset for next FC -    fc_cache->fc_received = false; -} - -}}; // namespace uhd::usrp - -#endif /* INCLUDED_DEVICE3_FLOW_CTRL_HPP */ diff --git a/host/lib/usrp/device3/device3_impl.cpp b/host/lib/usrp/device3/device3_impl.cpp deleted file mode 100644 index bc1cf9002..000000000 --- a/host/lib/usrp/device3/device3_impl.cpp +++ /dev/null @@ -1,206 +0,0 @@ -// -// Copyright 2014-2016 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#include "device3_impl.hpp" -#include <uhd/rfnoc/block_ctrl_base.hpp> -#include <uhd/utils/log.hpp> -#include <uhdlib/rfnoc/ctrl_iface.hpp> -#include <uhdlib/rfnoc/graph_impl.hpp> -#include <boost/make_shared.hpp> -#include <algorithm> - -using namespace uhd::usrp; - -device3_impl::device3_impl() -{ -    _type = uhd::device::USRP; -    _async_md.reset(new async_md_type(1000 /*messages deep*/)); -    _tree = uhd::property_tree::make(); -}; - -//! Returns true if the integer value stored in lhs is smaller than that in rhs -bool _compare_string_indexes(const std::string& lhs, const std::string& rhs) -{ -    return boost::lexical_cast<size_t>(lhs) < boost::lexical_cast<size_t>(rhs); -} - -void device3_impl::merge_channel_defs(const std::vector<uhd::rfnoc::block_id_t>& chan_ids, -    const std::vector<uhd::device_addr_t>& chan_args, -    const uhd::direction_t dir) -{ -    UHD_ASSERT_THROW(chan_ids.size() == chan_args.size()); -    if (dir == uhd::DX_DIRECTION) { -        merge_channel_defs(chan_ids, chan_args, RX_DIRECTION); -        merge_channel_defs(chan_ids, chan_args, TX_DIRECTION); -        return; -    } - -    uhd::fs_path chans_root = -        uhd::fs_path("/channels/") / (dir == RX_DIRECTION ? "rx" : "tx"); -    // Store the new positions of the channels: -    std::vector<size_t> chan_idxs; - -    // 1. Get sorted list of currently defined channels -    std::vector<std::string> curr_channels; -    if (_tree->exists(chans_root)) { -        curr_channels = _tree->list(chans_root); -        std::sort(curr_channels.begin(), curr_channels.end(), _compare_string_indexes); -    } - -    // 2. Cycle through existing channels to find out where to merge -    //    the new channels. Rules are: -    //    - The order of chan_ids must be preserved -    //    - All block indices that are in chan_ids may be overwritten in the channel -    //    definition -    //    - If the channels in chan_ids are not yet in the property tree channel list, -    //      they are appended. -    for (const std::string& chan_idx : curr_channels) { -        if (_tree->exists(chans_root / chan_idx)) { -            rfnoc::block_id_t chan_block_id = -                _tree->access<rfnoc::block_id_t>(chans_root / chan_idx).get(); -            if (std::find(chan_ids.begin(), chan_ids.end(), chan_block_id) -                != chan_ids.end()) { -                chan_idxs.push_back(boost::lexical_cast<size_t>(chan_idx)); -            } -        } -    } -    size_t last_chan_idx = curr_channels.empty() -                               ? 0 -                               : (boost::lexical_cast<size_t>(curr_channels.back()) + 1); -    while (chan_idxs.size() < chan_ids.size()) { -        chan_idxs.push_back(last_chan_idx); -        last_chan_idx++; -    } - -    // 3. Write the new channels -    for (size_t i = 0; i < chan_ids.size(); i++) { -        if (not _tree->exists(chans_root / chan_idxs[i])) { -            _tree->create<rfnoc::block_id_t>(chans_root / chan_idxs[i]); -        } -        _tree->access<rfnoc::block_id_t>(chans_root / chan_idxs[i]).set(chan_ids[i]); -        if (not _tree->exists(chans_root / chan_idxs[i] / "args")) { -            _tree->create<uhd::device_addr_t>(chans_root / chan_idxs[i] / "args"); -        } -        _tree->access<uhd::device_addr_t>(chans_root / chan_idxs[i] / "args") -            .set(chan_args[i]); -    } -} - -/*********************************************************************** - * RFNoC-Specific - **********************************************************************/ -void device3_impl::enumerate_rfnoc_blocks(size_t device_index, -    size_t n_blocks, -    size_t base_port, -    const uhd::sid_t& base_sid, -    uhd::device_addr_t transport_args) -{ -    // entries that are already connected to this block -    uhd::sid_t ctrl_sid = base_sid; -    uhd::property_tree::sptr subtree = -        _tree->subtree(uhd::fs_path("/mboards") / device_index); -    // 1) Clean property tree entries -    // TODO put this back once radios are actual rfnoc blocks!!!!!! -    // if (subtree->exists("xbar")) { -    // subtree->remove("xbar"); -    //} -    // 2) Destroy existing block controllers -    // TODO: Clear out all the old block control classes -    // 3) Create new block controllers -    for (size_t i = 0; i < n_blocks; i++) { -        // First, make a transport for port number zero, because we always need that: -        ctrl_sid.set_dst_xbarport(base_port + i); -        ctrl_sid.set_dst_blockport(0); -        both_xports_t xport = this->make_transport(ctrl_sid, CTRL, transport_args); -        UHD_LOG_TRACE("DEVICE3", -            str(boost::format("Setting up NoC-Shell Control for port #0 (SID: %s)...") -                % xport.send_sid.to_pp_string_hex())); -        uhd::rfnoc::ctrl_iface::sptr ctrl = uhd::rfnoc::ctrl_iface::make(xport, -            str(boost::format("CE_%02d_Port_%02X") % i % ctrl_sid.get_dst_endpoint())); -        uint64_t noc_id                   = ctrl->send_cmd_pkt( -            uhd::rfnoc::SR_READBACK, uhd::rfnoc::SR_READBACK_REG_ID, true); -        UHD_LOG_DEBUG("DEVICE3", -            str(boost::format("Port 0x%02X: Found NoC-Block with ID %016X.") -                % int(ctrl_sid.get_dst_endpoint()) % noc_id)); -        uhd::rfnoc::make_args_t make_args; -        uhd::rfnoc::blockdef::sptr block_def = -            uhd::rfnoc::blockdef::make_from_noc_id(noc_id); -        if (not block_def) { -            UHD_LOG_WARNING("DEVICE3", -                "No block definition found, using default block configuration " -                "for block with NOC ID: " -                    + str(boost::format("0x%08X") % noc_id)); -            block_def = -                uhd::rfnoc::blockdef::make_from_noc_id(uhd::rfnoc::DEFAULT_NOC_ID_64); -        } -        UHD_ASSERT_THROW(block_def); -        make_args.ctrl_ifaces[0] = ctrl; -        for (const size_t port_number : block_def->get_all_port_numbers()) { -            if (port_number == 0) { // We've already set this up -                continue; -            } -            ctrl_sid.set_dst_blockport(port_number); -            both_xports_t xport1 = this->make_transport(ctrl_sid, CTRL, transport_args); -            UHD_LOG_TRACE("DEVICE3", -                str(boost::format("Setting up NoC-Shell Control for port #%d " -                                  "(SID: %s)...") -                    % port_number % xport1.send_sid.to_pp_string_hex())); -            uhd::rfnoc::ctrl_iface::sptr ctrl1 = uhd::rfnoc::ctrl_iface::make(xport1, -                str(boost::format("CE_%02d_Port_%02X") % i -                    % ctrl_sid.get_dst_endpoint())); -            make_args.ctrl_ifaces[port_number] = ctrl1; -        } -        UHD_LOG_TRACE("DEVICE3", -            "All control transports successfully created for block with ID " -                << str(boost::format("0x%08X") % noc_id)); - -        make_args.base_address = xport.send_sid.get_dst(); -        make_args.device_index = device_index; -        make_args.tree         = subtree; -        { // Critical section for block_ctrl vector access -            boost::lock_guard<boost::mutex> lock(_block_ctrl_mutex); -            _rfnoc_block_ctrl.push_back( -                uhd::rfnoc::block_ctrl_base::make(make_args, noc_id)); -            _rfnoc_block_ctrl.back()->set_graph_update_cb([this]() { -                update_rx_streamers(); -                update_tx_streamers(); -            }); -        } -    } -} - - -uhd::rfnoc::graph::sptr device3_impl::create_graph(const std::string& name) -{ -    // Create an async message handler -    UHD_LOGGER_TRACE("DEVICE3") -        << "Creating async message handler for graph `" << name << "'..."; -    // FIXME: right now this only can only handle source sid of 0 and xbar local addr -    // of 2. This is ok for now because that most of our device has xbard local addr -    // hardcode to 2. -    sid_t async_sid(0); -    async_sid.set_dst_addr(2); -    both_xports_t async_xports = make_transport(async_sid, -        ASYNC_MSG, -        // FIXME: only get rx_hints from mb index of 0 -        get_rx_hints(0)); -    UHD_LOGGER_TRACE("DEVICE3") << " Async transport ready." << std::endl; -    uhd::rfnoc::async_msg_handler::sptr async_msg_handler = -        uhd::rfnoc::async_msg_handler::make(async_xports.recv, -            async_xports.send, -            async_xports.send_sid, -            async_xports.endianness); -    UHD_LOGGER_TRACE("DEVICE3") -        << "Async message has address " << async_xports.send_sid << std::endl; - -    // Create the graph -    UHD_LOGGER_TRACE("DEVICE3") << "Creating graph `" << name << "'..." << std::endl; -    uhd::rfnoc::graph::sptr graph = boost::make_shared<uhd::rfnoc::graph_impl>( -        name, shared_from_this(), async_msg_handler); - -    return graph; -} diff --git a/host/lib/usrp/device3/device3_impl.hpp b/host/lib/usrp/device3/device3_impl.hpp deleted file mode 100644 index 17f6a3f6f..000000000 --- a/host/lib/usrp/device3/device3_impl.hpp +++ /dev/null @@ -1,264 +0,0 @@ -// -// Copyright 2014-2015 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -// Declares the device3_impl class which is a layer between device3 and -// the different 3-rd gen device impls (e.g. x300_impl) - -#ifndef INCLUDED_DEVICE3_IMPL_HPP -#define INCLUDED_DEVICE3_IMPL_HPP - -#include "../../transport/super_recv_packet_handler.hpp" -#include "../../transport/super_send_packet_handler.hpp" -#include <uhd/device3.hpp> -#include <uhd/transport/bounded_buffer.hpp> -#include <uhd/transport/chdr.hpp> -#include <uhd/transport/vrt_if_packet.hpp> -#include <uhd/transport/zero_copy.hpp> -#include <uhd/types/direction.hpp> -#include <uhd/types/endianness.hpp> -#include <uhd/types/metadata.hpp> -#include <uhd/types/sid.hpp> -#include <uhd/utils/tasks.hpp> -#include <uhdlib/rfnoc/rx_stream_terminator.hpp> -#include <uhdlib/rfnoc/tx_stream_terminator.hpp> -#include <uhdlib/rfnoc/xports.hpp> - -namespace uhd { namespace usrp { - -/*********************************************************************** - * Default settings (any device3 may override these) - **********************************************************************/ -static const size_t DEVICE3_RX_FC_REQUEST_FREQ       = 32; // per flow-control window -static const size_t DEVICE3_TX_FC_RESPONSE_FREQ      = 8; -static const size_t DEVICE3_FC_PACKET_LEN_IN_WORDS32 = 2; -static const size_t DEVICE3_FC_PACKET_COUNT_OFFSET   = 0; -static const size_t DEVICE3_FC_BYTE_COUNT_OFFSET     = 1; -static const size_t DEVICE3_LINE_SIZE                = 8; - -static const size_t DEVICE3_TX_MAX_HDR_LEN = -    uhd::transport::vrt::chdr::max_if_hdr_words64 * sizeof(uint64_t); // Bytes -static const size_t DEVICE3_RX_MAX_HDR_LEN = -    uhd::transport::vrt::chdr::max_if_hdr_words64 * sizeof(uint64_t); // Bytes - -// This class manages the lifetime of the TX async message handler task, transports, and -// terminator -class device3_send_packet_streamer : public uhd::transport::sph::send_packet_streamer -{ -public: -    device3_send_packet_streamer(const size_t max_num_samps, -        const uhd::rfnoc::tx_stream_terminator::sptr terminator, -        const both_xports_t data_xport, -        const both_xports_t async_msg_xport) -        : uhd::transport::sph::send_packet_streamer(max_num_samps) -        , _terminator(terminator) -        , _data_xport(data_xport) -        , _async_msg_xport(async_msg_xport) -    { -    } - -    ~device3_send_packet_streamer() -    { -        // Make sure the async task is destroyed before the transports -        _tx_async_msg_tasks.clear(); -    } - -    uhd::rfnoc::tx_stream_terminator::sptr get_terminator() -    { -        return _terminator; -    } - -    void add_async_msg_task(task::sptr task) -    { -        _tx_async_msg_tasks.push_back(task); -    } - -private: -    uhd::rfnoc::tx_stream_terminator::sptr _terminator; -    both_xports_t _data_xport; -    both_xports_t _async_msg_xport; -    std::vector<task::sptr> _tx_async_msg_tasks; -}; - -// This class manages the lifetime of the RX transports and terminator and provides access -// to both -class device3_recv_packet_streamer : public uhd::transport::sph::recv_packet_streamer -{ -public: -    device3_recv_packet_streamer(const size_t max_num_samps, -        const uhd::rfnoc::rx_stream_terminator::sptr terminator, -        const both_xports_t xport) -        : uhd::transport::sph::recv_packet_streamer(max_num_samps) -        , _terminator(terminator) -        , _xport(xport) -    { -    } - -    ~device3_recv_packet_streamer() {} - -    both_xports_t get_xport() -    { -        return _xport; -    } - -    uhd::rfnoc::rx_stream_terminator::sptr get_terminator() -    { -        return _terminator; -    } - -private: -    uhd::rfnoc::rx_stream_terminator::sptr _terminator; -    both_xports_t _xport; -}; - -class device3_impl : public uhd::device3, -                     public boost::enable_shared_from_this<device3_impl> -{ -public: -    /*********************************************************************** -     * device3-specific Types -     **********************************************************************/ -    typedef uhd::transport::bounded_buffer<uhd::async_metadata_t> async_md_type; - -    //! The purpose of a transport -    enum xport_type_t { CTRL = 0, ASYNC_MSG, TX_DATA, RX_DATA }; - -    enum xport_t { AXI, ETH, PCIE }; - -    //! Stores all streaming-related options -    struct stream_options_t -    { -        //! Max size of the header in bytes for TX -        size_t tx_max_len_hdr; -        //! Max size of the header in bytes for RX -        size_t rx_max_len_hdr; -        //! How often we send ACKs to the upstream block per one full FC window -        size_t rx_fc_request_freq; -        //! How often the downstream block should send ACKs per one full FC window -        size_t tx_fc_response_freq; -        stream_options_t(void) -            : tx_max_len_hdr(DEVICE3_TX_MAX_HDR_LEN) -            , rx_max_len_hdr(DEVICE3_RX_MAX_HDR_LEN) -            , rx_fc_request_freq(DEVICE3_RX_FC_REQUEST_FREQ) -            , tx_fc_response_freq(DEVICE3_TX_FC_RESPONSE_FREQ) -        { -        } -    }; - -    /*********************************************************************** -     * I/O Interface -     **********************************************************************/ -    uhd::tx_streamer::sptr get_tx_stream(const uhd::stream_args_t&); -    uhd::rx_streamer::sptr get_rx_stream(const uhd::stream_args_t&); -    bool recv_async_msg(uhd::async_metadata_t& async_metadata, double timeout); - -    /*********************************************************************** -     * Other public APIs -     **********************************************************************/ -    rfnoc::graph::sptr create_graph(const std::string& name = ""); - -protected: -    /*********************************************************************** -     * Structors -     **********************************************************************/ -    device3_impl(); -    virtual ~device3_impl() {} - -    /*********************************************************************** -     * Streaming-related -     **********************************************************************/ -public: // TODO make these protected again -    /*! Update tick rate, samp rate, and scaling on the streamers by querying -     * the graph. -     */ -    void update_rx_streamers(); -    /*! Update tick rate, samp rate, and scaling on the streamers by querying -     * the graph. -     */ -    void update_tx_streamers(); - -protected: -    /*********************************************************************** -     * Transport-related -     **********************************************************************/ -    stream_options_t stream_options; - -    /*! \brief Create a transport to a given endpoint. -     * -     * \param address The endpoint address of the block we're creating a transport to. -     *                The source address in this value is not considered, only the -     *                destination address. -     * \param xport_type Specify which kind of transport this is. -     * \param args Additional arguments for the transport generation. See \ref -     * page_transport for valid arguments. -     */ -    virtual uhd::both_xports_t make_transport(const uhd::sid_t& address, -        const xport_type_t xport_type, -        const uhd::device_addr_t& args) = 0; - -    virtual uhd::device_addr_t get_tx_hints(size_t) -    { -        return uhd::device_addr_t(); -    } -    virtual uhd::device_addr_t get_rx_hints(size_t) -    { -        return uhd::device_addr_t(); -    } - -    //! Is called after a streamer is generated -    virtual void post_streamer_hooks(uhd::direction_t) {} - -    //! get mtu -    virtual size_t get_mtu(const size_t, const uhd::direction_t) = 0; - -    /*********************************************************************** -     * Channel-related -     **********************************************************************/ -    /*! Merge a list of channels into the existing channel definition. -     * -     * Intelligently merge the channels described in \p chan_ids -     * into the current channel definition. If none of the channels in -     * \p chan_ids is in the current definition, they simply get appended. -     * Otherwise, they get overwritten in the order of \p chan_ids. -     * -     * \param chan_ids List of block IDs for the channels. -     * \param chan_args New channel args. Must have same length as chan_ids. -     * -     */ -    void merge_channel_defs(const std::vector<rfnoc::block_id_t>& chan_ids, -        const std::vector<uhd::device_addr_t>& chan_args, -        const uhd::direction_t dir); - -    /*********************************************************************** -     * RFNoC-Specific -     **********************************************************************/ -    void enumerate_rfnoc_blocks(size_t device_index, -        size_t n_blocks, -        size_t base_port, -        const uhd::sid_t& base_sid, -        uhd::device_addr_t transport_args); - -    /*********************************************************************** -     * Members -     **********************************************************************/ -    // TODO: Maybe move these to private -    uhd::dict<std::string, boost::weak_ptr<uhd::rx_streamer>> _rx_streamers; -    uhd::dict<std::string, boost::weak_ptr<uhd::tx_streamer>> _tx_streamers; - -private: -    /*********************************************************************** -     * Private Members -     **********************************************************************/ -    //! Buffer for async metadata -    boost::shared_ptr<async_md_type> _async_md; - -    //! This mutex locks the get_xx_stream() functions. -    boost::mutex _transport_setup_mutex; -}; - -}} /* namespace uhd::usrp */ - -#endif /* INCLUDED_DEVICE3_IMPL_HPP */ diff --git a/host/lib/usrp/device3/device3_io_impl.cpp b/host/lib/usrp/device3/device3_io_impl.cpp deleted file mode 100644 index 800d2f5a8..000000000 --- a/host/lib/usrp/device3/device3_io_impl.cpp +++ /dev/null @@ -1,827 +0,0 @@ -// -// Copyright 2014-2016 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -// Provides streaming-related functions which are used by device3 objects. - -#include "device3_flow_ctrl.hpp" -#include "device3_impl.hpp" -#include <uhd/rfnoc/constants.hpp> -#include <uhd/rfnoc/radio_ctrl.hpp> -#include <uhd/rfnoc/rate_node_ctrl.hpp> -#include <uhd/rfnoc/sink_block_ctrl_base.hpp> -#include <uhd/rfnoc/source_block_ctrl_base.hpp> -#include <uhd/transport/zero_copy_flow_ctrl.hpp> -#include <uhd/utils/byteswap.hpp> -#include <uhd/utils/log.hpp> -#include <uhdlib/rfnoc/rx_stream_terminator.hpp> -#include <uhdlib/rfnoc/tx_stream_terminator.hpp> -#include <uhdlib/usrp/common/async_packet_handler.hpp> -#include <boost/atomic.hpp> - -#define UHD_TX_STREAMER_LOG() UHD_LOGGER_TRACE("STREAMER") -#define UHD_RX_STREAMER_LOG() UHD_LOGGER_TRACE("STREAMER") - -using namespace uhd; -using namespace uhd::usrp; -using namespace uhd::transport; - -/*********************************************************************** - * Helper functions for get_?x_stream() - **********************************************************************/ -static uhd::stream_args_t sanitize_stream_args(const uhd::stream_args_t& args_) -{ -    uhd::stream_args_t args = args_; -    if (args.channels.empty()) { -        args.channels = std::vector<size_t>(1, 0); -    } - -    return args; -} - -static void check_stream_sig_compatible( -    const rfnoc::stream_sig_t& stream_sig, stream_args_t& args, const std::string& tx_rx) -{ -    if (args.otw_format.empty()) { -        if (stream_sig.item_type.empty()) { -            throw uhd::runtime_error( -                str(boost::format("[%s Streamer] No otw_format defined!") % tx_rx)); -        } else { -            args.otw_format = stream_sig.item_type; -        } -    } else if (not stream_sig.item_type.empty() -               and stream_sig.item_type != args.otw_format) { -        throw uhd::runtime_error( -            str(boost::format("[%s Streamer] Conflicting OTW types defined: " -                              "args.otw_format = '%s' <=> stream_sig.item_type = '%s'") -                % tx_rx % args.otw_format % stream_sig.item_type)); -    } -    const size_t bpi = convert::get_bytes_per_item(args.otw_format); // bytes per item -    if (stream_sig.packet_size) { -        if (args.args.has_key("spp")) { -            size_t args_spp = args.args.cast<size_t>("spp", 0); -            if (args_spp * bpi != stream_sig.packet_size) { -                throw uhd::runtime_error( -                    str(boost::format( -                            "[%s Streamer] Conflicting packet sizes defined: args yields " -                            "%d bytes but stream_sig.packet_size is %d bytes") -                        % tx_rx % (args_spp * bpi) % stream_sig.packet_size)); -            } -        } else { -            args.args["spp"] = str(boost::format("%d") % (stream_sig.packet_size / bpi)); -        } -    } -} - -/*! \brief Returns a list of rx or tx channels for a streamer. - * - * If the given stream args contain instructions to set up channels, - * those are used. Otherwise, the current device's channel definition - * is consulted. - * - * \param args_ Stream args. - * \param[out] chan_list The list of channels in the correct order. - * \param[out] chan_args Channel args for every channel. `chan_args.size() == - * chan_list.size()` - */ -void generate_channel_list(const uhd::stream_args_t& args_, -    std::vector<uhd::rfnoc::block_id_t>& chan_list, -    std::vector<device_addr_t>& chan_args) -{ -    uhd::stream_args_t args = args_; -    std::vector<uhd::rfnoc::block_id_t> chan_list_(args.channels.size()); -    std::vector<device_addr_t> chan_args_(args.channels.size()); - -    for (size_t i = 0; i < args.channels.size(); i++) { -        // Extract block ID -        size_t chan_idx = args.channels[i]; -        std::string key = str(boost::format("block_id%d") % chan_idx); -        if (args.args.has_key(key)) { -            chan_list_[i] = args.args.pop(key); -        } else if (args.args.has_key("block_id")) { -            chan_list_[i] = args.args["block_id"]; -        } else { -            throw uhd::runtime_error( -                str(boost::format( -                        "Cannot create streamers: No block_id specified for channel %d.") -                    % chan_idx)); -        } - -        // Split off known channel specific args -        key = str(boost::format("block_port%d") % chan_idx); -        if (args.args.has_key(key)) { -            chan_args_[i]["block_port"] = args.args.pop(key); -        } -        key = str(boost::format("radio_id%d") % chan_idx); -        if (args.args.has_key(key)) { -            chan_args_[i]["radio_id"] = args.args.pop(key); -        } -        key = str(boost::format("radio_port%d") % chan_idx); -        if (args.args.has_key(key)) { -            chan_args_[i]["radio_port"] = args.args.pop(key); -        } -    } - -    // Add all remaining args to all channel args -    for (device_addr_t& chan_arg : chan_args_) { -        chan_arg = chan_arg.to_string() + "," + args.args.to_string(); -    } - -    chan_list = chan_list_; -    chan_args = chan_args_; -} - - -/*********************************************************************** - * RX Flow Control Functions - **********************************************************************/ -/*! Determine the size of the flow control window in number of packets. - * - * This value depends on three things: - * - The packet size (in bytes), P - * - The size of the software buffer (in bytes), B - * - The desired buffer fullness, F - * - * The FC window size is thus X = floor(B*F/P). - * - * \param pkt_size The maximum packet size in bytes - * \param sw_buff_size Software buffer size in bytes - * \param rx_args If this has a key 'recv_buff_fullness', this value will - *                be used for said fullness. Must be between 0.01 and 1. - * - *  \returns The size of the flow control window in number of packets - */ -static size_t get_rx_flow_control_window( -    size_t pkt_size, size_t sw_buff_size, const device_addr_t& rx_args) -{ -    double fullness_factor = rx_args.cast<double>( -        "recv_buff_fullness", uhd::rfnoc::DEFAULT_FC_RX_SW_BUFF_FULL_FACTOR); - -    if (fullness_factor < 0.01 || fullness_factor > 1) { -        throw uhd::value_error( -            "recv_buff_fullness must be in [0.01, 1] inclusive (1% to 100%)"); -    } - -    size_t window_in_bytes = (static_cast<size_t>(fullness_factor * sw_buff_size)); -    if (rx_args.has_key("max_recv_window")) { -        window_in_bytes = std::min( -            window_in_bytes, -            pkt_size * rx_args.cast<size_t>("max_recv_window", 1) -        ); -    } -    if (window_in_bytes < pkt_size) { -        throw uhd::value_error("recv_buff_size must be larger than the recv_frame_size."); -    } -    UHD_ASSERT_THROW(size_t(sw_buff_size * fullness_factor) >= window_in_bytes); -    return window_in_bytes; -} - - -/*********************************************************************** - * TX Async Message Functions - **********************************************************************/ -#define DEVICE3_ASYNC_EVENT_CODE_FLOW_CTRL 0 - -struct async_tx_info_t -{ -    size_t stream_channel; -    size_t device_channel; -    boost::shared_ptr<device3_impl::async_md_type> async_queue; -    boost::shared_ptr<device3_impl::async_md_type> old_async_queue; -}; - -/*! Handle incoming messages. - *  Send them to the async message queue for the user to poll. - * - * This is run inside a uhd::task as long as this streamer lives. - */ -static void handle_tx_async_msgs(boost::shared_ptr<async_tx_info_t> async_info, -    zero_copy_if::sptr xport, -    uint32_t (*to_host)(uint32_t), -    void (*unpack)(const uint32_t* packet_buff, vrt::if_packet_info_t&), -    boost::function<double(void)> get_tick_rate) -{ -    managed_recv_buffer::sptr buff = xport->get_recv_buff(); -    if (not buff) { -        return; -    } - -    // extract packet info -    vrt::if_packet_info_t if_packet_info; -    if_packet_info.num_packet_words32 = buff->size() / sizeof(uint32_t); -    const uint32_t* packet_buff       = buff->cast<const uint32_t*>(); - -    // unpacking can fail -    try { -        unpack(packet_buff, if_packet_info); -    } catch (const std::exception& ex) { -        UHD_LOGGER_ERROR("STREAMER") -            << "Error parsing async message packet: " << ex.what(); -        return; -    } - -    double tick_rate = get_tick_rate(); -    if (tick_rate == rfnoc::tick_node_ctrl::RATE_UNDEFINED) { -        tick_rate = 1; -    } - -    // fill in the async metadata -    async_metadata_t metadata; -    load_metadata_from_buff(to_host, -        metadata, -        if_packet_info, -        packet_buff, -        tick_rate, -        async_info->stream_channel); - -    // Filter out any flow control messages and cache the rest -    if (metadata.event_code == DEVICE3_ASYNC_EVENT_CODE_FLOW_CTRL) { -        UHD_LOGGER_ERROR("TX ASYNC MSG") -            << "Unexpected flow control message found in async message handling" -            << std::endl; -    } else { -        async_info->async_queue->push_with_pop_on_full(metadata); -        metadata.channel = async_info->device_channel; -        async_info->old_async_queue->push_with_pop_on_full(metadata); -        standard_async_msg_prints(metadata); -    } -} - -bool device3_impl::recv_async_msg(async_metadata_t& async_metadata, double timeout) -{ -    return _async_md->pop_with_timed_wait(async_metadata, timeout); -} - -/*********************************************************************** - * Receive streamer - **********************************************************************/ -void device3_impl::update_rx_streamers() -{ -    for (const std::string& block_id : _rx_streamers.keys()) { -        UHD_RX_STREAMER_LOG() << "updating RX streamer to " << block_id; -        boost::shared_ptr<device3_recv_packet_streamer> my_streamer = -            boost::dynamic_pointer_cast<device3_recv_packet_streamer>( -                _rx_streamers[block_id].lock()); -        if (my_streamer) { -            double tick_rate = my_streamer->get_terminator()->get_tick_rate(); -            if (tick_rate == rfnoc::tick_node_ctrl::RATE_UNDEFINED) { -                tick_rate = 1.0; -            } -            double samp_rate = my_streamer->get_terminator()->get_output_samp_rate(); -            if (samp_rate == rfnoc::rate_node_ctrl::RATE_UNDEFINED) { -                samp_rate = 1.0; -            } -            double scaling = my_streamer->get_terminator()->get_output_scale_factor(); -            if (scaling == rfnoc::scalar_node_ctrl::SCALE_UNDEFINED) { -                scaling = 1 / 32767.; -            } -            UHD_RX_STREAMER_LOG() -                << "  New tick_rate == " << tick_rate -                << "  New samp_rate == " << samp_rate << " New scaling == " << scaling; - -            my_streamer->set_tick_rate(tick_rate); -            my_streamer->set_samp_rate(samp_rate); -            my_streamer->set_scale_factor(scaling); -        } -    } -} - -rx_streamer::sptr device3_impl::get_rx_stream(const stream_args_t& args_) -{ -    boost::mutex::scoped_lock lock(_transport_setup_mutex); -    stream_args_t args = sanitize_stream_args(args_); - -    // I. Generate the channel list -    std::vector<uhd::rfnoc::block_id_t> chan_list; -    std::vector<device_addr_t> chan_args; -    generate_channel_list(args, chan_list, chan_args); -    // Note: All 'args.args' are merged into chan_args now. - -    // II. Iterate over all channels -    boost::shared_ptr<device3_recv_packet_streamer> my_streamer; -    // The terminator's lifetime is coupled to the streamer. -    // There is only one terminator. If the streamer has multiple channels, -    // it will be connected to each upstream block. -    rfnoc::rx_stream_terminator::sptr recv_terminator = -        rfnoc::rx_stream_terminator::make(); -    for (size_t stream_i = 0; stream_i < chan_list.size(); stream_i++) { -        // First, configure blocks and create transport - -        // Get block ID and mb index -        uhd::rfnoc::block_id_t block_id = chan_list[stream_i]; -        UHD_RX_STREAMER_LOG() << "chan " << stream_i << " connecting to " << block_id; -        // Update args so args.args is always valid for this particular channel: -        args.args       = chan_args[stream_i]; -        size_t mb_index = block_id.get_device_no(); -        size_t suggested_block_port = -            args.args.cast<size_t>("block_port", rfnoc::ANY_PORT); - -        // Access to this channel's block control -        uhd::rfnoc::source_block_ctrl_base::sptr blk_ctrl = -            boost::dynamic_pointer_cast<uhd::rfnoc::source_block_ctrl_base>( -                get_block_ctrl(block_id)); - -        // Connect the terminator with this channel's block. -        size_t block_port = blk_ctrl->connect_downstream( -            recv_terminator, suggested_block_port, args.args); -        const size_t terminator_port = recv_terminator->connect_upstream(blk_ctrl); -        blk_ctrl->set_downstream_port(block_port, terminator_port); -        recv_terminator->set_upstream_port(terminator_port, block_port); - -        // Check if the block connection is compatible (spp and item type) -        check_stream_sig_compatible( -            blk_ctrl->get_output_signature(block_port), args, "RX"); - -        // Setup the DSP transport hints -        device_addr_t rx_hints = get_rx_hints(mb_index); - -        // Search the device and all nodes for lowest MTU -        size_t mtu = std::min( -            get_mtu(mb_index, uhd::direction_t::RX_DIRECTION), -            blk_ctrl->get_mtu(block_port)); -        UHD_RX_STREAMER_LOG() << "Maximum MTU supported by " -                              <<  blk_ctrl->unique_id() -                              << ": " << blk_ctrl->get_mtu(block_port); -        std::vector<boost::shared_ptr<uhd::rfnoc::source_block_ctrl_base>> -            upstream_source_nodes = -                blk_ctrl->find_upstream_node<uhd::rfnoc::source_block_ctrl_base>(); -        for (const boost::shared_ptr<uhd::rfnoc::source_block_ctrl_base>& node : -            upstream_source_nodes) { -            // Get MTU from Port 0 of the upstream nodes. This is okay for now as -            // currently we use port 0 of a block in case of channel 1. -            UHD_RX_STREAMER_LOG() << "Maximum MTU supported by " << node->unique_id() -                                  << ": " << node->get_mtu(0); -            mtu = std::min(mtu, node->get_mtu(0)); -        } -        rx_hints["mtu"] = std::to_string(mtu); - -        // Make sure user supplied recv_frame_size is less than the MTU -        if (rx_hints.cast<size_t>("recv_frame_size", mtu) > mtu) { -            UHD_LOGGER_WARNING("STREAMER") -                << "Requested recv_frame_size of " -                << rx_hints["recv_frame_size"] -                << " exceeds the maximum possible on this stream. Using " -                << mtu; -            rx_hints["recv_frame_size"] = std::to_string(mtu); -        } - -        // allocate sid and create transport -        uhd::sid_t stream_address = blk_ctrl->get_address(block_port); -        UHD_RX_STREAMER_LOG() << "creating rx stream " << rx_hints.to_string(); -        both_xports_t xport = make_transport(stream_address, RX_DATA, rx_hints); -        UHD_RX_STREAMER_LOG() << std::hex << "data_sid = " << xport.send_sid << std::dec -                              << " actual recv_buff_size = " << xport.recv_buff_size; - -        // Configure the block -        // Flow control setup -        const size_t pkt_size = xport.recv->get_recv_frame_size(); -        // Leave one pkt_size space for overrun packets - TODO make this obsolete -        const size_t fc_window = -            get_rx_flow_control_window(pkt_size, xport.recv_buff_size, rx_hints) -            - pkt_size; -        const size_t fc_handle_window = -            std::max<size_t>(pkt_size, fc_window / stream_options.rx_fc_request_freq); -        UHD_RX_STREAMER_LOG() << "Flow Control Window = " << (fc_window) -                              << ", Flow Control Handler Window = " << fc_handle_window; -        blk_ctrl->configure_flow_control_out(true, -            xport.lossless, -            fc_window, -            rx_hints.cast<size_t>("recv_pkt_limit", -                0), // On rfnoc-devel, update e300_impl::get_rx_hints() to set this to 32 -            block_port); - -        // Add flow control transport -        boost::shared_ptr<rx_fc_cache_t> fc_cache(new rx_fc_cache_t()); -        fc_cache->sid      = xport.send_sid; -        fc_cache->xport    = xport.send; -        fc_cache->interval = fc_handle_window; -        if (xport.endianness == ENDIANNESS_BIG) { -            fc_cache->to_host   = uhd::ntohx<uint32_t>; -            fc_cache->from_host = uhd::htonx<uint32_t>; -            fc_cache->pack      = vrt::chdr::if_hdr_pack_be; -            fc_cache->unpack    = vrt::chdr::if_hdr_unpack_be; -        } else { -            fc_cache->to_host   = uhd::wtohx<uint32_t>; -            fc_cache->from_host = uhd::htowx<uint32_t>; -            fc_cache->pack      = vrt::chdr::if_hdr_pack_le; -            fc_cache->unpack    = vrt::chdr::if_hdr_unpack_le; -        } -        xport.recv = zero_copy_flow_ctrl::make( -            xport.recv, 0, [fc_cache](managed_buffer::sptr buff) { -                return rx_flow_ctrl(fc_cache, buff); -            }); - -        // Configure the block -        // Note: We need to set_destination() after writing to SR_CLEAR_TX_FC. -        // See noc_shell.v, in the section called Stream Source for details. -        // Setting SR_CLEAR_TX_FC will actually also clear the destination and -        // other settings. -        blk_ctrl->sr_write(uhd::rfnoc::SR_CLEAR_TX_FC, 0x1, block_port); -        blk_ctrl->sr_write(uhd::rfnoc::SR_CLEAR_TX_FC, 0x0, block_port); -        // Configure routing for data -        blk_ctrl->set_destination(xport.send_sid.get_src(), block_port); - -        // Configure routing for responses -        blk_ctrl->sr_write( -            uhd::rfnoc::SR_RESP_OUT_DST_SID, xport.send_sid.get_src(), block_port); -        UHD_RX_STREAMER_LOG() << "resp_out_dst_sid == " << xport.send_sid.get_src(); - -        // Find all upstream radio nodes and set their response in SID to the host -        std::vector<boost::shared_ptr<uhd::rfnoc::radio_ctrl>> upstream_radio_nodes = -            blk_ctrl->find_upstream_node<uhd::rfnoc::radio_ctrl>(); -        UHD_RX_STREAMER_LOG() << "Number of upstream radio nodes: " -                              << upstream_radio_nodes.size(); -        for (const boost::shared_ptr<uhd::rfnoc::radio_ctrl>& node : -            upstream_radio_nodes) { -            node->sr_write( -                uhd::rfnoc::SR_RESP_OUT_DST_SID, xport.send_sid.get_src(), block_port); -        } - -        // Second, configure the streamer - -        // make the new streamer given the samples per packet -        if (not my_streamer) { -            // To calculate the max number of samples per packet, we assume the maximum -            // header length to avoid fragmentation should the entire header be used. -            const size_t bpp = -                pkt_size - stream_options.rx_max_len_hdr; // bytes per packet -            const size_t bpi = -                convert::get_bytes_per_item(args.otw_format); // bytes per item -            const size_t spp = std::min(args.args.cast<size_t>("spp", bpp / bpi), -                bpp / bpi); // samples per packet -            UHD_RX_STREAMER_LOG() << "bpp == " << bpp << ", bpi == " << bpi << ", spp == " << spp; - -            my_streamer = boost::make_shared<device3_recv_packet_streamer>( -                spp, recv_terminator, xport); -            my_streamer->resize(chan_list.size()); -        } - -        // init some streamer stuff -        std::string conv_endianness; -        if (xport.endianness == ENDIANNESS_BIG) { -            my_streamer->set_vrt_unpacker(&vrt::chdr::if_hdr_unpack_be); -            conv_endianness = "be"; -        } else { -            my_streamer->set_vrt_unpacker(&vrt::chdr::if_hdr_unpack_le); -            conv_endianness = "le"; -        } - -        // set the converter -        uhd::convert::id_type id; -        id.input_format  = args.otw_format + "_item32_" + conv_endianness; -        id.num_inputs    = 1; -        id.output_format = args.cpu_format; -        id.num_outputs   = 1; -        my_streamer->set_converter(id); - -        // Give the streamer a functor to handle flow control ACK messages -        my_streamer->set_xport_handle_flowctrl_ack( -            stream_i, [fc_cache](const uint32_t* payload) { -                handle_rx_flowctrl_ack(fc_cache, payload); -            }); - -        // Give the streamer a functor to get the recv_buffer -        my_streamer->set_xport_chan_get_buff(stream_i, -            [xport](double timeout) { return xport.recv->get_recv_buff(timeout); }, -            true /*flush*/ -        ); - -        // Give the streamer a functor to handle overruns -        // bind requires a weak_ptr to break the a streamer->streamer circular dependency -        // Using "this" is OK because we know that this device3_impl will outlive the -        // streamer -        boost::weak_ptr<uhd::rx_streamer> weak_ptr(my_streamer); -        my_streamer->set_overflow_handler( -            stream_i, [recv_terminator, weak_ptr, stream_i]() { -                recv_terminator->handle_overrun(weak_ptr, stream_i); -            }); - -        // Give the streamer a functor issue stream cmd -        my_streamer->set_issue_stream_cmd( -            stream_i, [blk_ctrl, block_port](const stream_cmd_t& stream_cmd) { -                blk_ctrl->issue_stream_cmd(stream_cmd, block_port); -            }); -    } - -    // Notify all blocks in this chain that they are connected to an active streamer -    recv_terminator->set_rx_streamer(true, 0); - -    // Store a weak pointer to prevent a streamer->device3_impl->streamer circular -    // dependency. Note that we store the streamer only once, and use its terminator's ID -    // to do so. -    _rx_streamers[recv_terminator->unique_id()] = -        boost::weak_ptr<uhd::rx_streamer>(my_streamer); - -    // Sets tick rate, samp rate and scaling on this streamer. -    // A registered terminator is required to do this. -    update_rx_streamers(); - -    post_streamer_hooks(RX_DIRECTION); -    return my_streamer; -} - -/*********************************************************************** - * Transmit streamer - **********************************************************************/ -void device3_impl::update_tx_streamers() -{ -    for (const std::string& block_id : _tx_streamers.keys()) { -        UHD_TX_STREAMER_LOG() << "updating TX streamer: " << block_id; -        boost::shared_ptr<device3_send_packet_streamer> my_streamer = -            boost::dynamic_pointer_cast<device3_send_packet_streamer>( -                _tx_streamers[block_id].lock()); -        if (my_streamer) { -            double tick_rate = my_streamer->get_terminator()->get_tick_rate(); -            if (tick_rate == rfnoc::tick_node_ctrl::RATE_UNDEFINED) { -                tick_rate = 1.0; -            } -            double samp_rate = my_streamer->get_terminator()->get_input_samp_rate(); -            if (samp_rate == rfnoc::rate_node_ctrl::RATE_UNDEFINED) { -                samp_rate = 1.0; -            } -            double scaling = my_streamer->get_terminator()->get_input_scale_factor(); -            if (scaling == rfnoc::scalar_node_ctrl::SCALE_UNDEFINED) { -                scaling = 32767.; -            } -            UHD_TX_STREAMER_LOG() -                << "New tick_rate == " << tick_rate << "  New samp_rate == " << samp_rate -                << " New scaling == " << scaling; -            my_streamer->set_tick_rate(tick_rate); -            my_streamer->set_samp_rate(samp_rate); -            my_streamer->set_scale_factor(scaling); -        } -    } -} - -tx_streamer::sptr device3_impl::get_tx_stream(const uhd::stream_args_t& args_) -{ -    boost::mutex::scoped_lock lock(_transport_setup_mutex); -    stream_args_t args = sanitize_stream_args(args_); - -    // I. Generate the channel list -    std::vector<uhd::rfnoc::block_id_t> chan_list; -    std::vector<device_addr_t> chan_args; -    generate_channel_list(args, chan_list, chan_args); -    // Note: All 'args.args' are merged into chan_args now. - -    // shared async queue for all channels in streamer -    boost::shared_ptr<async_md_type> async_md(new async_md_type(1000 /*messages deep*/)); - -    // II. Iterate over all channels -    boost::shared_ptr<device3_send_packet_streamer> my_streamer; -    // The terminator's lifetime is coupled to the streamer. -    // There is only one terminator. If the streamer has multiple channels, -    // it will be connected to each downstream block. -    rfnoc::tx_stream_terminator::sptr send_terminator = -        rfnoc::tx_stream_terminator::make(); -    for (size_t stream_i = 0; stream_i < chan_list.size(); stream_i++) { -        // First, configure the downstream blocks and create the transports - -        // Get block ID and mb index -        uhd::rfnoc::block_id_t block_id = chan_list[stream_i]; -        // Update args so args.args is always valid for this particular channel: -        args.args       = chan_args[stream_i]; -        size_t mb_index = block_id.get_device_no(); -        size_t suggested_block_port = -            args.args.cast<size_t>("block_port", rfnoc::ANY_PORT); - -        // Access to this channel's block control -        uhd::rfnoc::sink_block_ctrl_base::sptr blk_ctrl = -            boost::dynamic_pointer_cast<uhd::rfnoc::sink_block_ctrl_base>( -                get_block_ctrl(block_id)); - -        // Connect the terminator with this channel's block. -        // This will throw if the connection is not possible. -        size_t block_port = -            blk_ctrl->connect_upstream(send_terminator, suggested_block_port, args.args); -        const size_t terminator_port = send_terminator->connect_downstream(blk_ctrl); -        blk_ctrl->set_upstream_port(block_port, terminator_port); -        send_terminator->set_downstream_port(terminator_port, block_port); - -        // Check if the block connection is compatible (spp and item type) -        check_stream_sig_compatible( -            blk_ctrl->get_input_signature(block_port), args, "TX"); - -        // Setup the dsp transport hints -        device_addr_t tx_hints = get_tx_hints(mb_index); - -        // Search the device and all nodes for lowest MTU -        size_t mtu = std::min( -            get_mtu(mb_index, uhd::direction_t::TX_DIRECTION), -            blk_ctrl->get_mtu(block_port)); -        UHD_TX_STREAMER_LOG() << "Maximum MTU supported by " -                              <<  blk_ctrl->unique_id() << ": " -                              << blk_ctrl->get_mtu(block_port); -        std::vector<boost::shared_ptr<uhd::rfnoc::sink_block_ctrl_base>> -            downstream_sink_nodes = -                blk_ctrl->find_downstream_node<uhd::rfnoc::sink_block_ctrl_base>(); -        for (const boost::shared_ptr<uhd::rfnoc::sink_block_ctrl_base>& node : -            downstream_sink_nodes) { -            // Get MTU from Port 0 of the downstream nodes. This is okay for now as -            // currently we use port 0 of a block in case of channel 1. -            UHD_TX_STREAMER_LOG() << "Maximum MTU supported by " -                                  <<  node->unique_id() << ": " -                                  << node->get_mtu(0); -            mtu = std::min(mtu, node->get_mtu(0)); -        } -        tx_hints["mtu"] = std::to_string(mtu); - -        // Make sure user supplied send_frame_size is less than the MTU -        if (tx_hints.cast<size_t>("send_frame_size", mtu) > mtu) { -            UHD_LOGGER_WARNING("STREAMER") -                << "Requested send_frame_size of " -                << tx_hints["send_frame_size"] -                << " exceeds the maximum possible on this stream. Using " -                << mtu; -            tx_hints["send_frame_size"] = std::to_string(mtu); -        } - -        const size_t fifo_size = blk_ctrl->get_fifo_size(block_port); -        // Allocate sid and create transport -        uhd::sid_t stream_address = blk_ctrl->get_address(block_port); -        UHD_TX_STREAMER_LOG() << "creating tx stream " << tx_hints.to_string(); -        both_xports_t xport = make_transport(stream_address, TX_DATA, tx_hints); -        both_xports_t async_xport = -            make_transport(stream_address, ASYNC_MSG, device_addr_t("")); -        UHD_TX_STREAMER_LOG() << std::hex << "data_sid = " << xport.send_sid << std::dec; - -        // Configure flow control -        // This disables the FC module's output, do this before configuring flow control -        blk_ctrl->sr_write(uhd::rfnoc::SR_CLEAR_RX_FC, 0x1, block_port); -        blk_ctrl->sr_write(uhd::rfnoc::SR_CLEAR_RX_FC, 0x0, block_port); -        // Configure flow control on downstream block -        const size_t pkt_size = xport.send->get_send_frame_size(); -        const size_t fc_window = -            std::min(tx_hints.cast<size_t>("send_buff_size", fifo_size), fifo_size); -        const size_t fc_handle_window = -            std::max<size_t>(pkt_size, fc_window / stream_options.tx_fc_response_freq); -        UHD_TX_STREAMER_LOG() << "Flow Control Window = " << fc_window -                              << ", Flow Control Handler Window = " << fc_handle_window -                              << ", FIFO size = " << fifo_size; -        blk_ctrl->configure_flow_control_in(fc_handle_window, /*bytes*/ -            block_port); -        // Add flow control transport -        boost::shared_ptr<tx_fc_cache_t> fc_cache(new tx_fc_cache_t(fc_window)); -        if (xport.endianness == ENDIANNESS_BIG) { -            fc_cache->to_host   = uhd::ntohx<uint32_t>; -            fc_cache->from_host = uhd::htonx<uint32_t>; -            fc_cache->pack      = vrt::chdr::if_hdr_pack_be; -            fc_cache->unpack    = vrt::chdr::if_hdr_unpack_be; -        } else { -            fc_cache->to_host   = uhd::wtohx<uint32_t>; -            fc_cache->from_host = uhd::htowx<uint32_t>; -            fc_cache->pack      = vrt::chdr::if_hdr_pack_le; -            fc_cache->unpack    = vrt::chdr::if_hdr_unpack_le; -        } -        xport.send = zero_copy_flow_ctrl::make(xport.send, -            [fc_cache, xport](managed_buffer::sptr buff) { -                return tx_flow_ctrl(fc_cache, xport.recv, buff); -            }, -            0); - -        // Configure return path for async messages -        blk_ctrl->sr_write( -            uhd::rfnoc::SR_RESP_IN_DST_SID, async_xport.recv_sid.get_dst(), block_port); -        UHD_TX_STREAMER_LOG() << "resp_in_dst_sid == " -                              << boost::format("0x%04X") % xport.recv_sid.get_dst(); - -        // FIXME: Once there is a better way to map the radio block and port -        // to the channel or another way to receive asynchronous messages that -        // is not in-band, this should be removed. -        if (args.args.has_key("radio_id") and args.args.has_key("radio_port")) { -            // Find downstream radio node and set the response SID to the host -            uhd::rfnoc::block_id_t radio_id(args.args["radio_id"]); -            size_t radio_port = args.args.cast<size_t>("radio_port", 0); -            std::vector<boost::shared_ptr<uhd::rfnoc::radio_ctrl>> -                downstream_radio_nodes = -                    blk_ctrl->find_downstream_node<uhd::rfnoc::radio_ctrl>(); -            UHD_TX_STREAMER_LOG() -                << "Number of downstream radio nodes: " << downstream_radio_nodes.size(); -            for (const boost::shared_ptr<uhd::rfnoc::radio_ctrl>& node : -                downstream_radio_nodes) { -                if (node->get_block_id() == radio_id) { -                    node->sr_write(uhd::rfnoc::SR_RESP_IN_DST_SID, -                        async_xport.recv_sid.get_dst(), -                        radio_port); -                } -            } -        } else { -            // FIXME:  This block is preserved for legacy behavior where the -            // radio_id and radio_port are not provided.  It fails if more -            // than one radio is visible downstream or the port on the radio -            // is not the same as the block_port.  It should be removed as -            // soon as possible. -            // Find all downstream radio nodes and set their response SID to the host -            std::vector<boost::shared_ptr<uhd::rfnoc::radio_ctrl>> -                downstream_radio_nodes = -                    blk_ctrl->find_downstream_node<uhd::rfnoc::radio_ctrl>(); -            UHD_TX_STREAMER_LOG() -                << "Number of downstream radio nodes: " << downstream_radio_nodes.size(); -            for (const boost::shared_ptr<uhd::rfnoc::radio_ctrl>& node : -                downstream_radio_nodes) { -                node->sr_write(uhd::rfnoc::SR_RESP_IN_DST_SID, -                    async_xport.recv_sid.get_dst(), -                    block_port); -            } -        } - -        // Second, configure the streamer now that the blocks and transports are -        // configured - -        // make the new streamer given the samples per packet -        if (not my_streamer) { -            // To calculate the max number of samples per packet, we assume the maximum -            // header length to avoid fragmentation should the entire header be used. -            const size_t bpp = -                tx_hints.cast<size_t>("bpp", pkt_size) - -                stream_options.tx_max_len_hdr; -            const size_t bpi = -                convert::get_bytes_per_item(args.otw_format); // bytes per item -            const size_t spp = std::min(args.args.cast<size_t>("spp", bpp / bpi), -                bpp / bpi); // samples per packet -            UHD_TX_STREAMER_LOG() -                << "bpp == " << bpp -                << ", bpi == " << bpi -                << ", spp == " << spp; - -            my_streamer = boost::make_shared<device3_send_packet_streamer>( -                spp, send_terminator, xport, async_xport); -            my_streamer->resize(chan_list.size()); -        } - -        // init some streamer stuff -        std::string conv_endianness; -        if (xport.endianness == ENDIANNESS_BIG) { -            my_streamer->set_vrt_packer(&vrt::chdr::if_hdr_pack_be); -            conv_endianness = "be"; -        } else { -            my_streamer->set_vrt_packer(&vrt::chdr::if_hdr_pack_le); -            conv_endianness = "le"; -        } - -        // set the converter -        uhd::convert::id_type id; -        id.input_format  = args.cpu_format; -        id.num_inputs    = 1; -        id.output_format = args.otw_format + "_item32_" + conv_endianness; -        id.num_outputs   = 1; -        my_streamer->set_converter(id); - -        boost::shared_ptr<async_tx_info_t> async_tx_info(new async_tx_info_t()); -        async_tx_info->stream_channel  = args.channels[stream_i]; -        async_tx_info->device_channel  = mb_index; -        async_tx_info->async_queue     = async_md; -        async_tx_info->old_async_queue = _async_md; - -        task::sptr async_task = -            task::make([async_tx_info, async_xport, xport, send_terminator]() { -                handle_tx_async_msgs(async_tx_info, -                    async_xport.recv, -                    xport.endianness == ENDIANNESS_BIG ? uhd::ntohx<uint32_t> -                                                       : uhd::wtohx<uint32_t>, -                    xport.endianness == ENDIANNESS_BIG ? vrt::chdr::if_hdr_unpack_be -                                                       : vrt::chdr::if_hdr_unpack_le, -                    [send_terminator]() { return send_terminator->get_tick_rate(); }); -            }); -        my_streamer->add_async_msg_task(async_task); - -        // Give the streamer a functor to get the send buffer -        my_streamer->set_xport_chan_get_buff(stream_i, -            [xport](const double timeout) { return xport.send->get_send_buff(timeout); }); -        // Give the streamer a functor handled received async messages -        my_streamer->set_async_receiver( -            [async_md](uhd::async_metadata_t& md, const double timeout) { -                return async_md->pop_with_timed_wait(md, timeout); -            }); -        my_streamer->set_xport_chan_sid(stream_i, true, xport.send_sid); -        // CHDR does not support trailers -        my_streamer->set_enable_trailer(false); - -        // Avoid sending FC ACKs if the transport is lossless or the user -        // has explictly requested not to send them -        if (not(xport.lossless or tx_hints.has_key("send_no_fc_acks"))) { -            my_streamer->set_xport_chan_post_send_cb(stream_i, [fc_cache, xport]() { -                tx_flow_ctrl_ack(fc_cache, xport.send, xport.send_sid); -            }); -        } -    } - -    // Notify all blocks in this chain that they are connected to an active streamer -    send_terminator->set_tx_streamer(true, 0); - -    // Store a weak pointer to prevent a streamer->device3_impl->streamer circular -    // dependency. Note that we store the streamer only once, and use its terminator's ID -    // to do so. -    _tx_streamers[send_terminator->unique_id()] = -        boost::weak_ptr<uhd::tx_streamer>(my_streamer); - -    // Sets tick rate, samp rate and scaling on this streamer -    // A registered terminator is required to do this. -    update_tx_streamers(); - -    post_streamer_hooks(TX_DIRECTION); -    return my_streamer; -} diff --git a/host/lib/usrp/mpmd/mpmd_impl.cpp b/host/lib/usrp/mpmd/mpmd_impl.cpp index 30a3c5804..69f990807 100644 --- a/host/lib/usrp/mpmd/mpmd_impl.cpp +++ b/host/lib/usrp/mpmd/mpmd_impl.cpp @@ -7,15 +7,9 @@  #include "mpmd_impl.hpp"  #include <uhd/exception.hpp>  #include <uhd/types/component_file.hpp> -#include <uhd/types/eeprom.hpp> -#include <uhd/types/sensors.hpp> -#include <uhd/usrp/mboard_eeprom.hpp>  #include <uhd/utils/static.hpp>  #include <uhd/utils/tasks.hpp> -#include <uhdlib/rfnoc/radio_ctrl_impl.hpp> -#include <uhdlib/rfnoc/rpc_block_ctrl.hpp>  #include <boost/algorithm/string.hpp> -#include <boost/asio.hpp>  #include <boost/make_shared.hpp>  #include <boost/thread.hpp>  #include <chrono> diff --git a/host/lib/usrp/mpmd/mpmd_link_if_ctrl_dpdk_udp.cpp b/host/lib/usrp/mpmd/mpmd_link_if_ctrl_dpdk_udp.cpp index baf0dde3e..2a3a48b62 100644 --- a/host/lib/usrp/mpmd/mpmd_link_if_ctrl_dpdk_udp.cpp +++ b/host/lib/usrp/mpmd/mpmd_link_if_ctrl_dpdk_udp.cpp @@ -192,77 +192,79 @@ mpmd_link_if_ctrl_dpdk_udp::mpmd_link_if_ctrl_dpdk_udp(      }  } -uhd::both_xports_t -mpmd_link_if_ctrl_dpdk_udp::make_transport( -        mpmd_link_if_mgr::xport_info_t &xport_info, -        const usrp::device3_impl::xport_type_t xport_type, -        const uhd::device_addr_t& xport_args -) { +// uhd::both_xports_t +// mpmd_link_if_ctrl_dpdk_udp::make_transport( +// mpmd_link_if_mgr::xport_info_t &xport_info, +// const uhd::transport::link_type_t xport_type, +// const uhd::device_addr_t& xport_args +//) { -    // Constrain by this transport's MTU and the MTU in the xport_args -    const size_t send_mtu = std::min(get_mtu(uhd::TX_DIRECTION), -        xport_args.cast<size_t>("mtu", get_mtu(uhd::TX_DIRECTION))); -    const size_t recv_mtu = std::min(get_mtu(uhd::RX_DIRECTION), -        xport_args.cast<size_t>("mtu", get_mtu(uhd::RX_DIRECTION))); +//// Constrain by this transport's MTU and the MTU in the xport_args +// const size_t send_mtu = std::min(get_mtu(uhd::TX_DIRECTION), +// xport_args.cast<size_t>("mtu", get_mtu(uhd::TX_DIRECTION))); +// const size_t recv_mtu = std::min(get_mtu(uhd::RX_DIRECTION), +// xport_args.cast<size_t>("mtu", get_mtu(uhd::RX_DIRECTION))); -    // Create actual UHD-DPDK UDP transport -    transport::zero_copy_xport_params default_buff_args; -    default_buff_args.num_recv_frames = MPMD_ETH_NUM_CTRL_FRAMES; -    default_buff_args.num_send_frames = MPMD_ETH_NUM_CTRL_FRAMES; -    default_buff_args.recv_frame_size = MPMD_10GE_MSG_FRAME_DEFAULT_SIZE; -    default_buff_args.send_frame_size = MPMD_10GE_MSG_FRAME_DEFAULT_SIZE; +//// Create actual UHD-DPDK UDP transport +// transport::zero_copy_xport_params default_buff_args; +// default_buff_args.num_recv_frames = MPMD_ETH_NUM_CTRL_FRAMES; +// default_buff_args.num_send_frames = MPMD_ETH_NUM_CTRL_FRAMES; +// default_buff_args.recv_frame_size = MPMD_10GE_MSG_FRAME_DEFAULT_SIZE; +// default_buff_args.send_frame_size = MPMD_10GE_MSG_FRAME_DEFAULT_SIZE; -    if (xport_type == usrp::device3_impl::RX_DATA) { -        default_buff_args.num_recv_frames = -            xport_args.cast<size_t>("num_recv_frames", MPMD_ETH_NUM_RECV_FRAMES); -        default_buff_args.recv_frame_size = std::min( -            xport_args.cast<size_t>("recv_frame_size", -                MPMD_10GE_DATA_FRAME_DEFAULT_SIZE), -            recv_mtu); -    } else if (xport_type == usrp::device3_impl::TX_DATA) { -        default_buff_args.num_send_frames = -            xport_args.cast<size_t>("num_send_frames", MPMD_ETH_NUM_SEND_FRAMES); -        default_buff_args.send_frame_size = std::min( -            xport_args.cast<size_t>("send_frame_size", -                MPMD_10GE_DATA_FRAME_DEFAULT_SIZE), -            send_mtu); -    } +// if (xport_type == uhd::transport::link_type_t::RX_DATA) { +// default_buff_args.num_recv_frames = +// xport_args.cast<size_t>("num_recv_frames", MPMD_ETH_NUM_RECV_FRAMES); +// default_buff_args.recv_frame_size = std::min( +// xport_args.cast<size_t>("recv_frame_size", +// MPMD_10GE_DATA_FRAME_DEFAULT_SIZE), +// recv_mtu); +//} else if (xport_type == uhd::transport::link_type_t::TX_DATA) { +// default_buff_args.num_send_frames = +// xport_args.cast<size_t>("num_send_frames", MPMD_ETH_NUM_SEND_FRAMES); +// default_buff_args.send_frame_size = std::min( +// xport_args.cast<size_t>("send_frame_size", +// MPMD_10GE_DATA_FRAME_DEFAULT_SIZE), +// send_mtu); +//} -    UHD_LOG_TRACE("BUFF", "num_recv_frames=" << default_buff_args.num_recv_frames -                     << ", num_send_frames=" << default_buff_args.num_send_frames -                     << ", recv_frame_size=" << default_buff_args.recv_frame_size -                     << ", send_frame_size=" << default_buff_args.send_frame_size); +// UHD_LOG_TRACE("BUFF", "num_recv_frames=" << default_buff_args.num_recv_frames +//<< ", num_send_frames=" << default_buff_args.num_send_frames +//<< ", recv_frame_size=" << default_buff_args.recv_frame_size +//<< ", send_frame_size=" << default_buff_args.send_frame_size); -    int dpdk_port_id = _ctx.get_route(xport_info["ipv4"]); -    if (dpdk_port_id < 0) { -        throw uhd::runtime_error("Could not find a DPDK port with route to " + -            xport_info["ipv4"]); -    } -    auto recv = transport::dpdk_zero_copy::make( -        _ctx, -        (const unsigned int) dpdk_port_id, -        xport_info["ipv4"], -        xport_info["port"], -        "0", -        default_buff_args, -        uhd::device_addr_t() -    ); -    const uint16_t port = recv->get_local_port(); -    const std::string src_ip_addr = recv->get_local_addr(); -    xport_info["src_port"] = std::to_string(port); -    xport_info["src_ipv4"] = src_ip_addr; +// int dpdk_port_id = _ctx.get_route(xport_info["ipv4"]); +// if (dpdk_port_id < 0) { +// throw uhd::runtime_error("Could not find a DPDK port with route to " + +// xport_info["ipv4"]); +//} +// auto recv = transport::dpdk_zero_copy::make( +//_ctx, +//(const unsigned int) dpdk_port_id, +// xport_info["ipv4"], +// xport_info["port"], +//"0", +// default_buff_args, +// uhd::device_addr_t() +//); +// const uint16_t port = recv->get_local_port(); +// const std::string src_ip_addr = recv->get_local_addr(); +// xport_info["src_port"] = std::to_string(port); +// xport_info["src_ipv4"] = src_ip_addr; -    // Create both_xports_t object and finish: -    both_xports_t xports; -    xports.endianness = uhd::ENDIANNESS_BIG; -    xports.send_sid = sid_t(xport_info["send_sid"]); -    xports.recv_sid = xports.send_sid.reversed(); -    xports.recv_buff_size = (default_buff_args.recv_frame_size-MPMD_UDP_RESERVED_FRAME_SIZE)*default_buff_args.num_recv_frames; -    xports.send_buff_size = (default_buff_args.send_frame_size-MPMD_UDP_RESERVED_FRAME_SIZE)*default_buff_args.num_send_frames; -    xports.recv = recv; // Note: This is a type cast! -    xports.send = recv; // This too -    return xports; -} +//// Create both_xports_t object and finish: +// both_xports_t xports; +// xports.endianness = uhd::ENDIANNESS_BIG; +// xports.send_sid = sid_t(xport_info["send_sid"]); +// xports.recv_sid = xports.send_sid.reversed(); +// xports.recv_buff_size = +// (default_buff_args.recv_frame_size-MPMD_UDP_RESERVED_FRAME_SIZE)*default_buff_args.num_recv_frames; +// xports.send_buff_size = +// (default_buff_args.send_frame_size-MPMD_UDP_RESERVED_FRAME_SIZE)*default_buff_args.num_send_frames; +// xports.recv = recv; // Note: This is a type cast! +// xports.send = recv; // This too +// return xports; +//}  bool mpmd_link_if_ctrl_dpdk_udp::is_valid(      const mpmd_link_if_mgr::xport_info_t& xport_info diff --git a/host/lib/usrp/mpmd/mpmd_link_if_ctrl_dpdk_udp.hpp b/host/lib/usrp/mpmd/mpmd_link_if_ctrl_dpdk_udp.hpp index 4423b4340..8f4f1c7d1 100644 --- a/host/lib/usrp/mpmd/mpmd_link_if_ctrl_dpdk_udp.hpp +++ b/host/lib/usrp/mpmd/mpmd_link_if_ctrl_dpdk_udp.hpp @@ -10,7 +10,6 @@  #include "mpmd_link_if_ctrl_base.hpp"  #include <uhd/types/device_addr.hpp>  #include <uhdlib/transport/dpdk_zero_copy.hpp> -#include "../device3/device3_impl.hpp"  namespace uhd { namespace mpmd { namespace xport { @@ -25,12 +24,6 @@ public:          const uhd::device_addr_t& mb_args      ); -    both_xports_t make_transport( -        mpmd_link_if_mgr::xport_info_t& xport_info, -        const usrp::device3_impl::xport_type_t xport_type, -        const uhd::device_addr_t& xport_args -    ); -      bool is_valid(          const mpmd_link_if_mgr::xport_info_t& xport_info      ) const; diff --git a/host/lib/usrp/mpmd/mpmd_link_if_mgr.hpp b/host/lib/usrp/mpmd/mpmd_link_if_mgr.hpp index 4b0ba4212..a1d11bad7 100644 --- a/host/lib/usrp/mpmd/mpmd_link_if_mgr.hpp +++ b/host/lib/usrp/mpmd/mpmd_link_if_mgr.hpp @@ -130,10 +130,10 @@ public:       *          The latter needs to get sent back to MPM to complete the       *          transport handshake.       */ -    //virtual both_xports_t make_transport(const xport_info_list_t& xport_info_list, -        //const usrp::device3_impl::xport_type_t xport_type, -        //const uhd::device_addr_t& xport_args, -        //xport_info_t& xport_info_out) = 0; +    // virtual both_xports_t make_transport(const xport_info_list_t& xport_info_list, +    // const uhd::transport::link_type_t::xport_type_t xport_type, +    // const uhd::device_addr_t& xport_args, +    // xport_info_t& xport_info_out) = 0;      /*! Return the path MTU for whatever this manager lets us do       */ diff --git a/host/lib/usrp/multi_usrp.cpp b/host/lib/usrp/multi_usrp.cpp index 227ba4212..6f8b794ce 100644 --- a/host/lib/usrp/multi_usrp.cpp +++ b/host/lib/usrp/multi_usrp.cpp @@ -20,7 +20,6 @@  #include <uhd/convert.hpp>  #include <uhd/utils/soft_register.hpp>  #include <uhdlib/usrp/gpio_defs.hpp> -#include <uhdlib/rfnoc/legacy_compat.hpp>  #include <uhdlib/rfnoc/rfnoc_device.hpp>  #include <boost/assign/list_of.hpp>  #include <boost/format.hpp> @@ -397,8 +396,7 @@ static double derive_freq_from_xx_subdev_and_dsp(   **********************************************************************/  class multi_usrp_impl : public multi_usrp{  public: -    multi_usrp_impl(device::sptr dev, const device_addr_t& addr) -        : _dev(dev) +    multi_usrp_impl(device::sptr dev) : _dev(dev)      {          _tree = _dev->get_tree();      } @@ -2259,7 +2257,6 @@ public:  private:      device::sptr _dev;      property_tree::sptr _tree; -    uhd::rfnoc::legacy_compat::sptr _legacy_compat;      struct mboard_chan_pair{          size_t mboard, chan; @@ -2517,5 +2514,5 @@ multi_usrp::sptr multi_usrp::make(const device_addr_t& dev_addr)      if (rfnoc_dev) {          return rfnoc::detail::make_rfnoc_device(rfnoc_dev, dev_addr);      } -    return boost::make_shared<multi_usrp_impl>(dev, dev_addr); +    return boost::make_shared<multi_usrp_impl>(dev);  } diff --git a/host/lib/usrp/x300/x300_eth_mgr.cpp b/host/lib/usrp/x300/x300_eth_mgr.cpp index b1d9f40ee..8ff63b050 100644 --- a/host/lib/usrp/x300/x300_eth_mgr.cpp +++ b/host/lib/usrp/x300/x300_eth_mgr.cpp @@ -239,46 +239,46 @@ both_links_t eth_manager::get_links(link_type_t link_type,  //#ifdef HAVE_DPDK          // auto& dpdk_ctx = uhd::transport::uhd_dpdk_ctx::get(); -        // default_buff_args.num_recv_frames = ETH_MSG_NUM_FRAMES; -        // default_buff_args.num_send_frames = ETH_MSG_NUM_FRAMES; -        // if (link_type == link_type_t::CTRL) { -        //// Increasing number of recv frames here because ctrl_iface uses it -        //// to determine how many control packets can be in flight before it -        //// must wait for an ACK -        // default_buff_args.num_recv_frames = -        // uhd::rfnoc::CMD_FIFO_SIZE / uhd::rfnoc::MAX_CMD_PKT_SIZE; -        //} else if (xport_type == uhd::usrp::device3_impl::TX_DATA) { -        // size_t default_frame_size = conn.link_rate == MAX_RATE_1GIGE -        //? GE_DATA_FRAME_SEND_SIZE -        //: XGE_DATA_FRAME_SEND_SIZE; -        // default_buff_args.send_frame_size = args.cast<size_t>( -        //"send_frame_size", std::min(default_frame_size, send_mtu)); -        // default_buff_args.num_send_frames = -        // args.cast<size_t>("num_send_frames", default_buff_args.num_send_frames); -        // default_buff_args.send_buff_size = args.cast<size_t>("send_buff_size", 0); -        //} else if (xport_type == uhd::usrp::device3_impl::RX_DATA) { -        // size_t default_frame_size = conn.link_rate == MAX_RATE_1GIGE -        //? GE_DATA_FRAME_RECV_SIZE -        //: XGE_DATA_FRAME_RECV_SIZE; -        // default_buff_args.recv_frame_size = args.cast<size_t>( -        //"recv_frame_size", std::min(default_frame_size, recv_mtu)); -        // default_buff_args.num_recv_frames = -        // args.cast<size_t>("num_recv_frames", default_buff_args.num_recv_frames); -        // default_buff_args.recv_buff_size = args.cast<size_t>("recv_buff_size", 0); -        //} - -        // int dpdk_port_id = dpdk_ctx.get_route(conn.addr); -        // if (dpdk_port_id < 0) { -        // throw uhd::runtime_error( -        //"Could not find a DPDK port with route to " + conn.addr); -        //} -        // auto recv = transport::dpdk_zero_copy::make(dpdk_ctx, -        //(const unsigned int)dpdk_port_id, -        // conn.addr, -        // BOOST_STRINGIZE(X300_VITA_UDP_PORT), -        //"0", -        // default_buff_args, -        // uhd::device_addr_t()); +// default_buff_args.num_recv_frames = ETH_MSG_NUM_FRAMES; +// default_buff_args.num_send_frames = ETH_MSG_NUM_FRAMES; +// if (link_type == link_type_t::CTRL) { +//// Increasing number of recv frames here because ctrl_iface uses it +//// to determine how many control packets can be in flight before it +//// must wait for an ACK +// default_buff_args.num_recv_frames = +// uhd::rfnoc::CMD_FIFO_SIZE / uhd::rfnoc::MAX_CMD_PKT_SIZE; +//} else if (xport_type == uhd::transport::link_type_t::TX_DATA) { +// size_t default_frame_size = conn.link_rate == MAX_RATE_1GIGE +//? GE_DATA_FRAME_SEND_SIZE +//: XGE_DATA_FRAME_SEND_SIZE; +// default_buff_args.send_frame_size = args.cast<size_t>( +//"send_frame_size", std::min(default_frame_size, send_mtu)); +// default_buff_args.num_send_frames = +// args.cast<size_t>("num_send_frames", default_buff_args.num_send_frames); +// default_buff_args.send_buff_size = args.cast<size_t>("send_buff_size", 0); +//} else if (xport_type == uhd::transport::link_type_t::RX_DATA) { +// size_t default_frame_size = conn.link_rate == MAX_RATE_1GIGE +//? GE_DATA_FRAME_RECV_SIZE +//: XGE_DATA_FRAME_RECV_SIZE; +// default_buff_args.recv_frame_size = args.cast<size_t>( +//"recv_frame_size", std::min(default_frame_size, recv_mtu)); +// default_buff_args.num_recv_frames = +// args.cast<size_t>("num_recv_frames", default_buff_args.num_recv_frames); +// default_buff_args.recv_buff_size = args.cast<size_t>("recv_buff_size", 0); +//} + +// int dpdk_port_id = dpdk_ctx.get_route(conn.addr); +// if (dpdk_port_id < 0) { +// throw uhd::runtime_error( +//"Could not find a DPDK port with route to " + conn.addr); +//} +// auto recv = transport::dpdk_zero_copy::make(dpdk_ctx, +//(const unsigned int)dpdk_port_id, +// conn.addr, +// BOOST_STRINGIZE(X300_VITA_UDP_PORT), +//"0", +// default_buff_args, +// uhd::device_addr_t());  //#else          UHD_LOG_WARNING("X300", "Cannot create DPDK transport, falling back to UDP"); diff --git a/host/lib/usrp/x300/x300_pcie_mgr.cpp b/host/lib/usrp/x300/x300_pcie_mgr.cpp index 220a96530..6560f2770 100644 --- a/host/lib/usrp/x300/x300_pcie_mgr.cpp +++ b/host/lib/usrp/x300/x300_pcie_mgr.cpp @@ -275,13 +275,13 @@ uint32_t pcie_manager::allocate_pcie_dma_chan(      const rfnoc::sep_id_t& /*remote_epid*/, const link_type_t /*link_type*/)  {      throw uhd::not_implemented_error("allocate_pcie_dma_chan()"); -    //constexpr uint32_t CTRL_CHANNEL       = 0; -    //constexpr uint32_t ASYNC_MSG_CHANNEL  = 1; -    //constexpr uint32_t FIRST_DATA_CHANNEL = 2; -    //if (link_type == uhd::usrp::device3_impl::CTRL) { -        //return CTRL_CHANNEL; -    //} else if (link_type == uhd::usrp::device3_impl::ASYNC_MSG) { -        //return ASYNC_MSG_CHANNEL; +    // constexpr uint32_t CTRL_CHANNEL       = 0; +    // constexpr uint32_t ASYNC_MSG_CHANNEL  = 1; +    // constexpr uint32_t FIRST_DATA_CHANNEL = 2; +    // if (link_type == uhd::transport::link_type_t::CTRL) { +    // return CTRL_CHANNEL; +    //} else if (link_type == uhd::transport::link_type_t::ASYNC_MSG) { +    // return ASYNC_MSG_CHANNEL;      //} else {          //// sid_t has no comparison defined, so we need to convert it uint32_t          //uint32_t raw_sid = tx_sid.get(); @@ -330,50 +330,50 @@ both_links_t pcie_manager::get_links(link_type_t /*link_type*/,              + std::to_string(local_device_id)              + ", no such device associated with this motherboard!");      } -    //zero_copy_xport_params default_buff_args; -    //xports.endianness              = ENDIANNESS_LITTLE; -    //xports.lossless                = true; -    //const uint32_t dma_channel_num = allocate_pcie_dma_chan(xports.send_sid, xport_type); -    //if (xport_type == uhd::usrp::device3_impl::CTRL) { -        //// Transport for control stream -        //if (not _ctrl_dma_xport) { -            //// One underlying DMA channel will handle -            //// all control traffic -            //_ctrl_dma_xport = -                //make_muxed_pcie_msg_xport(dma_channel_num, PCIE_MAX_MUXED_CTRL_XPORTS); -        //} -        //// Create a virtual control transport -        //xports.recv = _ctrl_dma_xport->make_stream(xports.recv_sid.get_dst()); -    //} else if (xport_type == uhd::usrp::device3_impl::ASYNC_MSG) { -        //// Transport for async message stream -        //if (not _async_msg_dma_xport) { -            //// One underlying DMA channel will handle -            //// all async message traffic -            //_async_msg_dma_xport = -                //make_muxed_pcie_msg_xport(dma_channel_num, PCIE_MAX_MUXED_ASYNC_XPORTS); -        //} -        //// Create a virtual async message transport -        //xports.recv = _async_msg_dma_xport->make_stream(xports.recv_sid.get_dst()); -    //} else if (xport_type == uhd::usrp::device3_impl::TX_DATA) { -        //default_buff_args.send_frame_size = args.cast<size_t>( -            //"send_frame_size", std::min(send_mtu, PCIE_TX_DATA_FRAME_SIZE)); -        //default_buff_args.num_send_frames = -            //args.cast<size_t>("num_send_frames", PCIE_TX_DATA_NUM_FRAMES); -        //default_buff_args.send_buff_size  = args.cast<size_t>("send_buff_size", 0); -        //default_buff_args.recv_frame_size = PCIE_MSG_FRAME_SIZE; -        //default_buff_args.num_recv_frames = PCIE_MSG_NUM_FRAMES; -        //xports.recv                       = nirio_zero_copy::make( -            //_rio_fpga_interface, dma_channel_num, default_buff_args); -    //} else if (xport_type == uhd::usrp::device3_impl::RX_DATA) { -        //default_buff_args.send_frame_size = PCIE_MSG_FRAME_SIZE; -        //default_buff_args.num_send_frames = PCIE_MSG_NUM_FRAMES; -        //default_buff_args.recv_frame_size = args.cast<size_t>( -            //"recv_frame_size", std::min(recv_mtu, PCIE_RX_DATA_FRAME_SIZE)); -        //default_buff_args.num_recv_frames = -            //args.cast<size_t>("num_recv_frames", PCIE_RX_DATA_NUM_FRAMES); -        //default_buff_args.recv_buff_size = args.cast<size_t>("recv_buff_size", 0); -        //xports.recv                      = nirio_zero_copy::make( -            //_rio_fpga_interface, dma_channel_num, default_buff_args); +    // zero_copy_xport_params default_buff_args; +    // xports.endianness              = ENDIANNESS_LITTLE; +    // xports.lossless                = true; +    // const uint32_t dma_channel_num = allocate_pcie_dma_chan(xports.send_sid, +    // xport_type); if (xport_type == uhd::transport::link_type_t::CTRL) { +    //// Transport for control stream +    // if (not _ctrl_dma_xport) { +    //// One underlying DMA channel will handle +    //// all control traffic +    //_ctrl_dma_xport = +    // make_muxed_pcie_msg_xport(dma_channel_num, PCIE_MAX_MUXED_CTRL_XPORTS); +    //} +    //// Create a virtual control transport +    // xports.recv = _ctrl_dma_xport->make_stream(xports.recv_sid.get_dst()); +    //} else if (xport_type == uhd::transport::link_type_t::ASYNC_MSG) { +    //// Transport for async message stream +    // if (not _async_msg_dma_xport) { +    //// One underlying DMA channel will handle +    //// all async message traffic +    //_async_msg_dma_xport = +    // make_muxed_pcie_msg_xport(dma_channel_num, PCIE_MAX_MUXED_ASYNC_XPORTS); +    //} +    //// Create a virtual async message transport +    // xports.recv = _async_msg_dma_xport->make_stream(xports.recv_sid.get_dst()); +    //} else if (xport_type == uhd::transport::link_type_t::TX_DATA) { +    // default_buff_args.send_frame_size = args.cast<size_t>( +    //"send_frame_size", std::min(send_mtu, PCIE_TX_DATA_FRAME_SIZE)); +    // default_buff_args.num_send_frames = +    // args.cast<size_t>("num_send_frames", PCIE_TX_DATA_NUM_FRAMES); +    // default_buff_args.send_buff_size  = args.cast<size_t>("send_buff_size", 0); +    // default_buff_args.recv_frame_size = PCIE_MSG_FRAME_SIZE; +    // default_buff_args.num_recv_frames = PCIE_MSG_NUM_FRAMES; +    // xports.recv                       = nirio_zero_copy::make( +    //_rio_fpga_interface, dma_channel_num, default_buff_args); +    //} else if (xport_type == uhd::transport::link_type_t::RX_DATA) { +    // default_buff_args.send_frame_size = PCIE_MSG_FRAME_SIZE; +    // default_buff_args.num_send_frames = PCIE_MSG_NUM_FRAMES; +    // default_buff_args.recv_frame_size = args.cast<size_t>( +    //"recv_frame_size", std::min(recv_mtu, PCIE_RX_DATA_FRAME_SIZE)); +    // default_buff_args.num_recv_frames = +    // args.cast<size_t>("num_recv_frames", PCIE_RX_DATA_NUM_FRAMES); +    // default_buff_args.recv_buff_size = args.cast<size_t>("recv_buff_size", 0); +    // xports.recv                      = nirio_zero_copy::make( +    //_rio_fpga_interface, dma_channel_num, default_buff_args);      //}      //xports.send = xports.recv; diff --git a/host/lib/usrp/x300/x300_radio_ctrl_impl.cpp b/host/lib/usrp/x300/x300_radio_ctrl_impl.cpp deleted file mode 100644 index c280f77c5..000000000 --- a/host/lib/usrp/x300/x300_radio_ctrl_impl.cpp +++ /dev/null @@ -1,1577 +0,0 @@ -// -// Copyright 2015-2017 Ettus Research, A National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#include "x300_radio_ctrl_impl.hpp" -#include "x300_dboard_iface.hpp" -#include <uhd/rfnoc/node_ctrl_base.hpp> -#include <uhd/transport/chdr.hpp> -#include <uhd/usrp/dboard_eeprom.hpp> -#include <uhd/usrp/dboard_iface.hpp> -#include <uhd/utils/log.hpp> -#include <uhd/utils/math.hpp> -#include <uhd/utils/safe_call.hpp> -#include <uhdlib/rfnoc/wb_iface_adapter.hpp> -#include <uhdlib/usrp/common/apply_corrections.hpp> -#include <uhdlib/usrp/cores/gpio_atr_3000.hpp> -#include <boost/algorithm/string.hpp> -#include <boost/date_time/posix_time/posix_time_io.hpp> -#include <boost/make_shared.hpp> -#include <chrono> -#include <thread> -#include <bitset> - -using namespace uhd; -using namespace uhd::usrp; -using namespace uhd::rfnoc; -using namespace uhd::usrp::x300; - -static const size_t IO_MASTER_RADIO = 0; - -namespace { - -gain_fcns_t make_gain_fcns_from_subtree(property_tree::sptr subtree) -{ -    gain_fcns_t gain_fcns; -    gain_fcns.get_range = [subtree]() { -        return subtree->access<meta_range_t>("range").get(); -    }; -    gain_fcns.get_value = [subtree]() { return subtree->access<double>("value").get(); }; -    gain_fcns.set_value = [subtree](const double gain) { -        subtree->access<double>("value").set(gain); -    }; -    return gain_fcns; -} - -} // namespace - -/**************************************************************************** - * Structors - ***************************************************************************/ -UHD_RFNOC_RADIO_BLOCK_CONSTRUCTOR(x300_radio_ctrl) -, _ignore_cal_file(false) -{ -    UHD_RFNOC_BLOCK_TRACE() << "x300_radio_ctrl_impl::ctor() "; - -    //////////////////////////////////////////////////////////////////// -    // Set up basic info -    //////////////////////////////////////////////////////////////////// -    _radio_type     = (get_block_id().get_block_count() == 0) ? PRIMARY : SECONDARY; -    _radio_slot     = (get_block_id().get_block_count() == 0) ? "A" : "B"; -    _radio_clk_rate = _tree->access<double>("master_clock_rate").get(); - -    //////////////////////////////////////////////////////////////////// -    // Set up peripherals -    //////////////////////////////////////////////////////////////////// -    wb_iface::sptr ctrl = _get_ctrl(IO_MASTER_RADIO); -    _regs = boost::make_shared<radio_regmap_t>(_radio_type == PRIMARY ? 0 : 1); -    _regs->initialize(*ctrl, true); - -    // Only Radio0 has the ADC/DAC reset bits. Those bits are reserved for Radio1 -    if (_radio_type == PRIMARY) { -        _regs->misc_outs_reg.set(radio_regmap_t::misc_outs_reg_t::ADC_RESET, 1); -        _regs->misc_outs_reg.set(radio_regmap_t::misc_outs_reg_t::DAC_RESET_N, 0); -        _regs->misc_outs_reg.flush(); -        _regs->misc_outs_reg.set(radio_regmap_t::misc_outs_reg_t::ADC_RESET, 0); -        _regs->misc_outs_reg.set(radio_regmap_t::misc_outs_reg_t::DAC_RESET_N, 1); -        _regs->misc_outs_reg.flush(); -    } -    _regs->misc_outs_reg.write(radio_regmap_t::misc_outs_reg_t::DAC_ENABLED, 1); - -    //////////////////////////////////////////////////////////////// -    // Setup peripherals -    //////////////////////////////////////////////////////////////// -    _spi = spi_core_3000::make(ctrl, -        regs::sr_addr(radio_ctrl_impl::regs::SPI), -        regs::rb_addr(radio_ctrl_impl::regs::RB_SPI)); -    _adc = x300_adc_ctrl::make(_spi, DB_ADC_SEN); -    _dac = x300_dac_ctrl::make(_spi, DB_DAC_SEN, _radio_clk_rate); - -    if (_radio_type == PRIMARY) { -        _fp_gpio = gpio_atr::gpio_atr_3000::make( -            ctrl, regs::sr_addr(regs::FP_GPIO), regs::rb_addr(regs::RB_FP_GPIO)); -        for (const gpio_atr::gpio_attr_map_t::value_type attr : gpio_atr::gpio_attr_map) { -            switch (attr.first) { -                case usrp::gpio_atr::GPIO_SRC: -                    _tree -                        ->create<std::vector<std::string>>( -                            fs_path("gpio") / "FP0" / attr.second) -                        .set(std::vector<std::string>( -                            32, usrp::gpio_atr::default_attr_value_map.at(attr.first))) -                        .add_coerced_subscriber([this](const std::vector<std::string>&) { -                            throw uhd::runtime_error("This device does not support " -                                                     "setting the GPIO_SRC attribute."); -                        }); -                    break; -                case usrp::gpio_atr::GPIO_CTRL: -                case usrp::gpio_atr::GPIO_DDR: -                    _tree -                        ->create<std::vector<std::string>>( -                            fs_path("gpio") / "FP0" / attr.second) -                        .set(std::vector<std::string>( -                            32, usrp::gpio_atr::default_attr_value_map.at(attr.first))) -                        .add_coerced_subscriber( -                            [this, attr](const std::vector<std::string> str_val) { -                                uint32_t val = 0; -                                for (size_t i = 0; i < str_val.size(); i++) { -                                    val += usrp::gpio_atr::gpio_attr_value_pair -                                               .at(attr.second) -                                               .at(str_val[i]) -                                           << i; -                                } -                                _fp_gpio->set_gpio_attr(attr.first, val); -                            }); -                    break; -                case usrp::gpio_atr::GPIO_READBACK: -                    _tree->create<uint32_t>(fs_path("gpio") / "FP0" / "READBACK") -                        .set_publisher([this]() { return _fp_gpio->read_gpio(); }); -                    break; -                default: -                    _tree->create<uint32_t>(fs_path("gpio") / "FP0" / attr.second) -                        .set(0) -                        .add_coerced_subscriber([this, attr](const uint32_t val) { -                            _fp_gpio->set_gpio_attr(attr.first, val); -                        }); -            } -        } -    } - -    //////////////////////////////////////////////////////////////// -    // create legacy codec control objects -    //////////////////////////////////////////////////////////////// -    _tree->create<int>( -        "rx_codecs" / _radio_slot / "gains"); // phony property so this dir exists -    _tree->create<int>( -        "tx_codecs" / _radio_slot / "gains"); // phony property so this dir exists -    _tree->create<std::string>("rx_codecs" / _radio_slot / "name").set("ads62p48"); -    _tree->create<std::string>("tx_codecs" / _radio_slot / "name").set("ad9146"); - -    _tree->create<meta_range_t>("rx_codecs" / _radio_slot / "gains" / "digital" / "range") -        .set(meta_range_t(0, 6.0, 0.5)); -    _tree->create<double>("rx_codecs" / _radio_slot / "gains" / "digital" / "value") -        .add_coerced_subscriber(boost::bind(&x300_adc_ctrl::set_gain, _adc, _1)) -        .set(0); - -    //////////////////////////////////////////////////////////////// -    // create front-end objects -    //////////////////////////////////////////////////////////////// -    for (size_t i = 0; i < _get_num_radios(); i++) { -        _leds[i] = gpio_atr::gpio_atr_3000::make_write_only( -            _get_ctrl(i), regs::sr_addr(regs::LEDS)); -        _leds[i]->set_atr_mode( -            usrp::gpio_atr::MODE_ATR, usrp::gpio_atr::gpio_atr_3000::MASK_SET_ALL); - -        _rx_fe_map[i].core = rx_frontend_core_3000::make( -            _get_ctrl(i), regs::sr_addr(x300_regs::RX_FE_BASE)); -        _rx_fe_map[i].core->set_adc_rate(_radio_clk_rate); -        _rx_fe_map[i].core->set_dc_offset(rx_frontend_core_3000::DEFAULT_DC_OFFSET_VALUE); -        _rx_fe_map[i].core->set_dc_offset_auto( -            rx_frontend_core_3000::DEFAULT_DC_OFFSET_ENABLE); -        _rx_fe_map[i].core->populate_subtree( -            _tree->subtree(_root_path / "rx_fe_corrections" / i)); - -        _tx_fe_map[i].core = tx_frontend_core_200::make( -            _get_ctrl(i), regs::sr_addr(x300_regs::TX_FE_BASE)); -        _tx_fe_map[i].core->set_dc_offset(tx_frontend_core_200::DEFAULT_DC_OFFSET_VALUE); -        _tx_fe_map[i].core->set_iq_balance( -            tx_frontend_core_200::DEFAULT_IQ_BALANCE_VALUE); -        _tx_fe_map[i].core->populate_subtree( -            _tree->subtree(_root_path / "tx_fe_corrections" / i)); - -        //////////////////////////////////////////////////////////////// -        // Bind the daughterboard command time to the motherboard level property -        //////////////////////////////////////////////////////////////// - -        if (_tree->exists(fs_path("time") / "cmd")) { -            _tree->access<time_spec_t>(fs_path("time") / "cmd") -                .add_coerced_subscriber( -                    boost::bind(&x300_radio_ctrl_impl::set_fe_cmd_time, this, _1, i)); -        } -    } - -    //////////////////////////////////////////////////////////////// -    // Update default SPP (overwrites the default value from the XML file) -    //////////////////////////////////////////////////////////////// -    const size_t max_bytes_header = -        uhd::transport::vrt::chdr::max_if_hdr_words64 * sizeof(uint64_t); -    const size_t default_spp = -        (_tree->access<size_t>("mtu/recv").get() - max_bytes_header) -        / (2 * sizeof(int16_t)); -    _tree->access<int>(get_arg_path("spp") / "value").set(default_spp); -} - -x300_radio_ctrl_impl::~x300_radio_ctrl_impl() -{ -    UHD_SAFE_CALL( -        // Tear down our part of the tree: -        _tree->remove(fs_path("rx_codecs" / _radio_slot)); -        _tree->remove(fs_path("tx_codecs" / _radio_slot)); -        _tree->remove(_root_path / "rx_fe_corrections"); -        _tree->remove(_root_path / "tx_fe_corrections"); -        if (_radio_type == PRIMARY) { -            for (const gpio_atr::gpio_attr_map_t::value_type attr : -                gpio_atr::gpio_attr_map) { -                _tree->remove(fs_path("gpio") / "FP0" / attr.second); -            } -        } - -        // Reset peripherals -        if (_radio_type == PRIMARY) { -            _regs->misc_outs_reg.set(radio_regmap_t::misc_outs_reg_t::ADC_RESET, 1); -            _regs->misc_outs_reg.set(radio_regmap_t::misc_outs_reg_t::DAC_RESET_N, 0); -        } _regs->misc_outs_reg.write(radio_regmap_t::misc_outs_reg_t::DAC_ENABLED, 0); -        _regs->misc_outs_reg.flush();) -} - -/**************************************************************************** - * API calls - ***************************************************************************/ -double x300_radio_ctrl_impl::set_rate(double rate) -{ -    const double actual_rate = get_rate(); -    if (not uhd::math::frequencies_are_equal(rate, actual_rate)) { -        UHD_LOGGER_WARNING("X300 RADIO") -            << "Requesting invalid sampling rate from device: " << rate / 1e6 -            << " MHz. Actual rate is: " << actual_rate / 1e6 << " MHz."; -    } -    // On X3x0, tick rate can't actually be changed at runtime -    return actual_rate; -} - -void x300_radio_ctrl_impl::set_fe_cmd_time(const time_spec_t& time, const size_t chan) -{ -    if (_tree->exists(fs_path("dboards" / _radio_slot / "rx_frontends" -                              / _rx_fe_map.at(chan).db_fe_name / "time" / "cmd"))) { -        _tree -            ->access<time_spec_t>( -                fs_path("dboards" / _radio_slot / "rx_frontends" -                        / _rx_fe_map.at(chan).db_fe_name / "time" / "cmd")) -            .set(time); -    } -} - -void x300_radio_ctrl_impl::set_tx_antenna(const std::string& ant, const size_t chan) -{ -    _tree -        ->access<std::string>( -            fs_path("dboards" / _radio_slot / "tx_frontends" -                    / _tx_fe_map.at(chan).db_fe_name / "antenna" / "value")) -        .set(ant); -} - -std::string x300_radio_ctrl_impl::get_tx_antenna(const size_t chan) -{ -    return _tree -        ->access<std::string>( -            fs_path("dboards" / _radio_slot / "tx_frontends" -                    / _tx_fe_map.at(chan).db_fe_name / "antenna" / "value")) -        .get(); -} - -void x300_radio_ctrl_impl::set_rx_antenna(const std::string& ant, const size_t chan) -{ -    _tree -        ->access<std::string>( -            fs_path("dboards" / _radio_slot / "rx_frontends" -                    / _rx_fe_map.at(chan).db_fe_name / "antenna" / "value")) -        .set(ant); -} - -std::string x300_radio_ctrl_impl::get_rx_antenna(const size_t chan) -{ -    return _tree -        ->access<std::string>( -            fs_path("dboards" / _radio_slot / "rx_frontends" -                    / _rx_fe_map.at(chan).db_fe_name / "antenna" / "value")) -        .get(); -} - -double x300_radio_ctrl_impl::set_tx_frequency(const double freq, const size_t chan) -{ -    return _tree -        ->access<double>(fs_path("dboards" / _radio_slot / "tx_frontends" -                                 / _tx_fe_map.at(chan).db_fe_name / "freq" / "value")) -        .set(freq) -        .get(); -} - -double x300_radio_ctrl_impl::get_tx_frequency(const size_t chan) -{ -    return _tree -        ->access<double>(fs_path("dboards" / _radio_slot / "tx_frontends" -                                 / _tx_fe_map.at(chan).db_fe_name / "freq" / "value")) -        .get(); -} - -double x300_radio_ctrl_impl::set_rx_frequency(const double freq, const size_t chan) -{ -    return _tree -        ->access<double>(fs_path("dboards" / _radio_slot / "rx_frontends" -                                 / _rx_fe_map.at(chan).db_fe_name / "freq" / "value")) -        .set(freq) -        .get(); -} - -double x300_radio_ctrl_impl::get_rx_frequency(const size_t chan) -{ -    return _tree -        ->access<double>(fs_path("dboards" / _radio_slot / "rx_frontends" -                                 / _rx_fe_map.at(chan).db_fe_name / "freq" / "value")) -        .get(); -} - -double x300_radio_ctrl_impl::set_rx_bandwidth(const double bandwidth, const size_t chan) -{ -    return _tree -        ->access<double>( -            fs_path("dboards" / _radio_slot / "rx_frontends" -                    / _rx_fe_map.at(chan).db_fe_name / "bandwidth" / "value")) -        .set(bandwidth) -        .get(); -} - -double x300_radio_ctrl_impl::get_rx_bandwidth(const size_t chan) -{ -    return _tree -        ->access<double>( -            fs_path("dboards" / _radio_slot / "rx_frontends" -                    / _rx_fe_map.at(chan).db_fe_name / "bandwidth" / "value")) -        .get(); -} - -double x300_radio_ctrl_impl::set_tx_gain(const double gain, const size_t chan) -{ -    if (_tx_gain_groups.count(chan)) { -        auto& gg = _tx_gain_groups.at(chan); -        gg->set_value(gain); -        return radio_ctrl_impl::set_tx_gain(gg->get_value(), chan); -    } -    return radio_ctrl_impl::set_tx_gain(0.0, chan); -} - -double x300_radio_ctrl_impl::set_rx_gain(const double gain, const size_t chan) -{ -    auto& gg = _rx_gain_groups.at(chan); -    gg->set_value(gain); -    return radio_ctrl_impl::set_rx_gain(gg->get_value(), chan); -} - -double x300_radio_ctrl_impl::get_rx_gain(const size_t chan) -{ -    return _rx_gain_groups.at(chan)->get_value(); -} - -std::vector<std::string> x300_radio_ctrl_impl::get_rx_lo_names(const size_t chan) -{ -    fs_path rx_fe_fe_root = fs_path( -        "dboards" / _radio_slot / "rx_frontends" / _rx_fe_map.at(chan).db_fe_name); - -    std::vector<std::string> lo_names; -    if (_tree->exists(rx_fe_fe_root / "los")) { -        for (const std::string& name : _tree->list(rx_fe_fe_root / "los")) { -            lo_names.push_back(name); -        } -    } -    return lo_names; -} - -std::vector<std::string> x300_radio_ctrl_impl::get_rx_lo_sources( -    const std::string& name, const size_t chan) -{ -    fs_path rx_fe_fe_root = fs_path( -        "dboards" / _radio_slot / "rx_frontends" / _rx_fe_map.at(chan).db_fe_name); - -    if (_tree->exists(rx_fe_fe_root / "los")) { -        if (name == ALL_LOS) { -            if (_tree->exists(rx_fe_fe_root / "los" / ALL_LOS)) { -                // Special value ALL_LOS support atomically sets the source for all LOs -                return _tree -                    ->access<std::vector<std::string>>( -                        rx_fe_fe_root / "los" / ALL_LOS / "source" / "options") -                    .get(); -            } else { -                return std::vector<std::string>(); -            } -        } else { -            if (_tree->exists(rx_fe_fe_root / "los")) { -                return _tree -                    ->access<std::vector<std::string>>( -                        rx_fe_fe_root / "los" / name / "source" / "options") -                    .get(); -            } else { -                throw uhd::runtime_error("Could not find LO stage " + name); -            } -        } -    } else { -        // If the daughterboard doesn't expose it's LO(s) then it can only be internal -        return std::vector<std::string>(1, "internal"); -    } -} - -void x300_radio_ctrl_impl::set_rx_lo_source( -    const std::string& src, const std::string& name, const size_t chan) -{ -    fs_path rx_fe_fe_root = fs_path( -        "dboards" / _radio_slot / "rx_frontends" / _rx_fe_map.at(chan).db_fe_name); - -    if (_tree->exists(rx_fe_fe_root / "los")) { -        if (name == ALL_LOS) { -            if (_tree->exists(rx_fe_fe_root / "los" / ALL_LOS)) { -                // Special value ALL_LOS support atomically sets the source for all LOs -                _tree -                    ->access<std::string>( -                        rx_fe_fe_root / "los" / ALL_LOS / "source" / "value") -                    .set(src); -            } else { -                for (const std::string& n : _tree->list(rx_fe_fe_root / "los")) { -                    this->set_rx_lo_source(src, n, chan); -                } -            } -        } else { -            if (_tree->exists(rx_fe_fe_root / "los")) { -                _tree -                    ->access<std::string>( -                        rx_fe_fe_root / "los" / name / "source" / "value") -                    .set(src); -            } else { -                throw uhd::runtime_error("Could not find LO stage " + name); -            } -        } -    } else { -        throw uhd::runtime_error( -            "This device does not support manual configuration of LOs"); -    } -} - -const std::string x300_radio_ctrl_impl::get_rx_lo_source( -    const std::string& name, const size_t chan) -{ -    fs_path rx_fe_fe_root = fs_path( -        "dboards" / _radio_slot / "rx_frontends" / _rx_fe_map.at(chan).db_fe_name); - -    if (_tree->exists(rx_fe_fe_root / "los")) { -        if (name == ALL_LOS) { -            // Special value ALL_LOS support atomically sets the source for all LOs -            return _tree -                ->access<std::string>( -                    rx_fe_fe_root / "los" / ALL_LOS / "source" / "value") -                .get(); -        } else { -            if (_tree->exists(rx_fe_fe_root / "los")) { -                return _tree -                    ->access<std::string>( -                        rx_fe_fe_root / "los" / name / "source" / "value") -                    .get(); -            } else { -                throw uhd::runtime_error("Could not find LO stage " + name); -            } -        } -    } else { -        // If the daughterboard doesn't expose it's LO(s) then it can only be internal -        return "internal"; -    } -} - -void x300_radio_ctrl_impl::set_rx_lo_export_enabled( -    bool enabled, const std::string& name, const size_t chan) -{ -    fs_path rx_fe_fe_root = fs_path( -        "dboards" / _radio_slot / "rx_frontends" / _rx_fe_map.at(chan).db_fe_name); - -    if (_tree->exists(rx_fe_fe_root / "los")) { -        if (name == ALL_LOS) { -            if (_tree->exists(rx_fe_fe_root / "los" / ALL_LOS)) { -                // Special value ALL_LOS support atomically sets the source for all LOs -                _tree->access<bool>(rx_fe_fe_root / "los" / ALL_LOS / "export") -                    .set(enabled); -            } else { -                for (const std::string& n : _tree->list(rx_fe_fe_root / "los")) { -                    this->set_rx_lo_export_enabled(enabled, n, chan); -                } -            } -        } else { -            if (_tree->exists(rx_fe_fe_root / "los")) { -                _tree->access<bool>(rx_fe_fe_root / "los" / name / "export").set(enabled); -            } else { -                throw uhd::runtime_error("Could not find LO stage " + name); -            } -        } -    } else { -        throw uhd::runtime_error( -            "This device does not support manual configuration of LOs"); -    } -} - -bool x300_radio_ctrl_impl::get_rx_lo_export_enabled( -    const std::string& name, const size_t chan) -{ -    fs_path rx_fe_fe_root = fs_path( -        "dboards" / _radio_slot / "rx_frontends" / _rx_fe_map.at(chan).db_fe_name); - -    if (_tree->exists(rx_fe_fe_root / "los")) { -        if (name == ALL_LOS) { -            // Special value ALL_LOS support atomically sets the source for all LOs -            return _tree->access<bool>(rx_fe_fe_root / "los" / ALL_LOS / "export").get(); -        } else { -            if (_tree->exists(rx_fe_fe_root / "los")) { -                return _tree->access<bool>(rx_fe_fe_root / "los" / name / "export").get(); -            } else { -                throw uhd::runtime_error("Could not find LO stage " + name); -            } -        } -    } else { -        // If the daughterboard doesn't expose it's LO(s), assume it cannot export -        return false; -    } -} - -double x300_radio_ctrl_impl::set_rx_lo_freq( -    double freq, const std::string& name, const size_t chan) -{ -    fs_path rx_fe_fe_root = fs_path( -        "dboards" / _radio_slot / "rx_frontends" / _rx_fe_map.at(chan).db_fe_name); - -    if (_tree->exists(rx_fe_fe_root / "los")) { -        if (name == ALL_LOS) { -            throw uhd::runtime_error( -                "LO frequency must be set for each stage individually"); -        } else { -            if (_tree->exists(rx_fe_fe_root / "los")) { -                _tree->access<double>(rx_fe_fe_root / "los" / name / "freq" / "value") -                    .set(freq); -                return _tree -                    ->access<double>(rx_fe_fe_root / "los" / name / "freq" / "value") -                    .get(); -            } else { -                throw uhd::runtime_error("Could not find LO stage " + name); -            } -        } -    } else { -        throw uhd::runtime_error( -            "This device does not support manual configuration of LOs"); -    } -} - -double x300_radio_ctrl_impl::get_rx_lo_freq(const std::string& name, const size_t chan) -{ -    fs_path rx_fe_fe_root = fs_path( -        "dboards" / _radio_slot / "rx_frontends" / _rx_fe_map.at(chan).db_fe_name); - -    if (_tree->exists(rx_fe_fe_root / "los")) { -        if (name == ALL_LOS) { -            throw uhd::runtime_error( -                "LO frequency must be retrieved for each stage individually"); -        } else { -            if (_tree->exists(rx_fe_fe_root / "los")) { -                return _tree -                    ->access<double>(rx_fe_fe_root / "los" / name / "freq" / "value") -                    .get(); -            } else { -                throw uhd::runtime_error("Could not find LO stage " + name); -            } -        } -    } else { -        // Return actual RF frequency if the daughterboard doesn't expose it's LO(s) -        return _tree->access<double>(rx_fe_fe_root / "freq" / " value").get(); -    } -} - -freq_range_t x300_radio_ctrl_impl::get_rx_lo_freq_range( -    const std::string& name, const size_t chan) -{ -    fs_path rx_fe_fe_root = fs_path( -        "dboards" / _radio_slot / "rx_frontends" / _rx_fe_map.at(chan).db_fe_name); - -    if (_tree->exists(rx_fe_fe_root / "los")) { -        if (name == ALL_LOS) { -            throw uhd::runtime_error( -                "LO frequency range must be retrieved for each stage individually"); -        } else { -            if (_tree->exists(rx_fe_fe_root / "los")) { -                return _tree -                    ->access<freq_range_t>( -                        rx_fe_fe_root / "los" / name / "freq" / "range") -                    .get(); -            } else { -                throw uhd::runtime_error("Could not find LO stage " + name); -            } -        } -    } else { -        // Return the actual RF range if the daughterboard doesn't expose it's LO(s) -        return _tree->access<meta_range_t>(rx_fe_fe_root / "freq" / "range").get(); -    } -} - -template <typename map_type> -static size_t _get_chan_from_map(std::map<size_t, map_type> map, const std::string& fe) -{ -    for (auto it = map.begin(); it != map.end(); ++it) { -        if (it->second.db_fe_name == fe) { -            return it->first; -        } -    } -    throw uhd::runtime_error( -        str(boost::format("Invalid daughterboard frontend name: %s") % fe)); -} - -size_t x300_radio_ctrl_impl::get_chan_from_dboard_fe( -    const std::string& fe, const uhd::direction_t direction) -{ -    switch (direction) { -        case uhd::TX_DIRECTION: -            return _get_chan_from_map(_tx_fe_map, fe); -        case uhd::RX_DIRECTION: -            return _get_chan_from_map(_rx_fe_map, fe); -        default: -            UHD_THROW_INVALID_CODE_PATH(); -    } -} - -std::string x300_radio_ctrl_impl::get_dboard_fe_from_chan( -    const size_t chan, const uhd::direction_t direction) -{ -    switch (direction) { -        case uhd::TX_DIRECTION: -            return _tx_fe_map.at(chan).db_fe_name; -        case uhd::RX_DIRECTION: -            return _rx_fe_map.at(chan).db_fe_name; -        default: -            UHD_THROW_INVALID_CODE_PATH(); -    } -} - -double x300_radio_ctrl_impl::get_output_samp_rate(size_t chan) -{ -    // TODO: chan should never be ANY_PORT, but due to our current graph search -    // method, this can actually happen: -    if (chan == ANY_PORT) { -        chan = 0; -        for (size_t i = 0; i < _get_num_radios(); i++) { -            if (_is_streamer_active(uhd::RX_DIRECTION, chan)) { -                chan = i; -                break; -            } -        } -    } -    return _rx_fe_map.at(chan).core->get_output_rate(); -} - -std::vector<std::string> x300_radio_ctrl_impl::get_gpio_banks() const -{ -    std::vector<std::string> banks{"RX", "TX"}; -    // These pairs are the same, but RXA/TXA are from pre-rfnoc era and are kept for -    // backward compat: -    banks.push_back("RX" + _radio_slot); -    banks.push_back("TX" + _radio_slot); -    if (_fp_gpio) { -        banks.push_back("FP0"); -    } -    return banks; -} - -void x300_radio_ctrl_impl::set_gpio_attr(const std::string& bank, -    const std::string& attr, -    const uint32_t value, -    const uint32_t mask) -{ -    if (bank == "FP0" and _fp_gpio) { -        std::vector<std::string> attr_value; -        const auto attr_type = usrp::gpio_atr::gpio_attr_rev_map.at(attr); -        switch (attr_type) { -            case usrp::gpio_atr::GPIO_SRC: -            case usrp::gpio_atr::GPIO_CTRL: -            case usrp::gpio_atr::GPIO_DDR: { -                attr_value = -                    _tree->access<std::vector<std::string>>(fs_path("gpio") / bank / attr) -                        .get(); -                std::bitset<32> bit_mask  = std::bitset<32>(mask); -                std::bitset<32> new_value = std::bitset<32>(value); -                for (size_t i = 0; i < bit_mask.size(); i++) { -                    if (bit_mask[i] == 1) { -                        attr_value[i] = -                            usrp::gpio_atr::attr_value_map.at(attr_type).at(new_value[i]); -                    } -                } -                _tree->access<std::vector<std::string>>(fs_path("gpio") / bank / attr) -                    .set(attr_value); -                return; -            } break; -            default: { -                const uint32_t curr_value = -                    _tree->access<uint32_t>(fs_path("gpio") / bank / attr).get(); -                uint32_t new_value = (curr_value & ~mask) | (value & mask); -                _tree->access<uint32_t>(fs_path("gpio") / bank / attr).set(new_value); -            } break; -        } -    } -    if (bank.size() > 2 and bank[1] == 'X') { -        const std::string name          = bank.substr(2); -        const dboard_iface::unit_t unit = (bank[0] == 'R') ? dboard_iface::UNIT_RX -                                                           : dboard_iface::UNIT_TX; -        dboard_iface::sptr iface = -            _tree->access<dboard_iface::sptr>(fs_path("dboards") / name / "iface").get(); -        if (attr == "CTRL") -            iface->set_pin_ctrl(unit, uint16_t(value), uint16_t(mask)); -        if (attr == "DDR") -            iface->set_gpio_ddr(unit, uint16_t(value), uint16_t(mask)); -        if (attr == "OUT") -            iface->set_gpio_out(unit, uint16_t(value), uint16_t(mask)); -        if (attr == "ATR_0X") -            iface->set_atr_reg( -                unit, gpio_atr::ATR_REG_IDLE, uint16_t(value), uint16_t(mask)); -        if (attr == "ATR_RX") -            iface->set_atr_reg( -                unit, gpio_atr::ATR_REG_RX_ONLY, uint16_t(value), uint16_t(mask)); -        if (attr == "ATR_TX") -            iface->set_atr_reg( -                unit, gpio_atr::ATR_REG_TX_ONLY, uint16_t(value), uint16_t(mask)); -        if (attr == "ATR_XX") -            iface->set_atr_reg( -                unit, gpio_atr::ATR_REG_FULL_DUPLEX, uint16_t(value), uint16_t(mask)); -    } -} - -uint32_t x300_radio_ctrl_impl::get_gpio_attr( -    const std::string& bank, const std::string& attr) -{ -    if (bank == "FP0" and _fp_gpio) { -        const auto attr_type = usrp::gpio_atr::gpio_attr_rev_map.at(attr); -        switch(attr_type) { -            case usrp::gpio_atr::GPIO_SRC: -            case usrp::gpio_atr::GPIO_CTRL: -            case usrp::gpio_atr::GPIO_DDR: { -                auto str_val = -                    _tree->access<std::vector<std::string>>( -                        fs_path("gpio") / bank / attr).get(); -                uint32_t val = 0; -                for (size_t i = 0; i < str_val.size(); i++) { -                    val += usrp::gpio_atr::gpio_attr_value_pair.at(attr).at(str_val[i]) << i; -                } -                return val; -            } -            break; -            default: { -                return _tree->access<uint32_t>(fs_path("gpio") / bank / attr).get(); -            } -            break; -        } -    } -    if (bank.size() > 2 and bank[1] == 'X') { -        const std::string name          = bank.substr(2); -        const dboard_iface::unit_t unit = (bank[0] == 'R') ? dboard_iface::UNIT_RX -                                                           : dboard_iface::UNIT_TX; -        dboard_iface::sptr iface = -            _tree->access<dboard_iface::sptr>(fs_path("dboards") / name / "iface").get(); -        if (attr == "CTRL") -            return iface->get_pin_ctrl(unit); -        if (attr == "DDR") -            return iface->get_gpio_ddr(unit); -        if (attr == "OUT") -            return iface->get_gpio_out(unit); -        if (attr == "ATR_0X") -            return iface->get_atr_reg(unit, gpio_atr::ATR_REG_IDLE); -        if (attr == "ATR_RX") -            return iface->get_atr_reg(unit, gpio_atr::ATR_REG_RX_ONLY); -        if (attr == "ATR_TX") -            return iface->get_atr_reg(unit, gpio_atr::ATR_REG_TX_ONLY); -        if (attr == "ATR_XX") -            return iface->get_atr_reg(unit, gpio_atr::ATR_REG_FULL_DUPLEX); -        if (attr == "READBACK") -            return iface->read_gpio(unit); -    } -    return 0; -} - -/**************************************************************************** - * Radio control and setup - ***************************************************************************/ -void x300_radio_ctrl_impl::setup_radio(uhd::i2c_iface::sptr zpu_i2c, -    x300_clock_ctrl::sptr clock, -    bool ignore_cal_file, -    bool verbose) -{ -    _self_cal_adc_capture_delay(verbose); -    _ignore_cal_file = ignore_cal_file; - -    //////////////////////////////////////////////////////////////////// -    // create RF frontend interfacing -    //////////////////////////////////////////////////////////////////// -    static const size_t BASE_ADDR       = 0x50; -    static const size_t RX_EEPROM_ADDR  = 0x5; -    static const size_t TX_EEPROM_ADDR  = 0x4; -    static const size_t GDB_EEPROM_ADDR = 0x1; -    const static std::vector<size_t> EEPROM_ADDRS{ -        RX_EEPROM_ADDR, TX_EEPROM_ADDR, GDB_EEPROM_ADDR}; -    const static std::vector<std::string> EEPROM_PATHS{ -        "rx_eeprom", "tx_eeprom", "gdb_eeprom"}; - -    const size_t DB_OFFSET = (_radio_slot == "A") ? 0x0 : 0x2; -    const fs_path db_path  = ("dboards" / _radio_slot); -    for (size_t i = 0; i < EEPROM_ADDRS.size(); i++) { -        const size_t addr = EEPROM_ADDRS[i] + DB_OFFSET; -        // Load EEPROM -        _db_eeproms[addr].load(*zpu_i2c, BASE_ADDR | addr); -        // Add to tree -        _tree->create<dboard_eeprom_t>(db_path / EEPROM_PATHS[i]) -            .set(_db_eeproms[addr]) -            .add_coerced_subscriber(boost::bind(&x300_radio_ctrl_impl::_set_db_eeprom, -                this, -                zpu_i2c, -                (BASE_ADDR | addr), -                _1)); -    } - -    // create a new dboard interface -    x300_dboard_iface_config_t db_config; -    db_config.gpio = gpio_atr::db_gpio_atr_3000::make(_get_ctrl(IO_MASTER_RADIO), -        radio_ctrl_impl::regs::sr_addr(radio_ctrl_impl::regs::GPIO), -        radio_ctrl_impl::regs::rb_addr(radio_ctrl_impl::regs::RB_DB_GPIO)); -    db_config.spi  = _spi; -    db_config.rx_spi_slaveno = DB_RX_SEN; -    db_config.tx_spi_slaveno = DB_TX_SEN; -    db_config.i2c            = zpu_i2c; -    db_config.clock          = clock; -    db_config.which_rx_clk   = (_radio_slot == "A") ? X300_CLOCK_WHICH_DB0_RX -                                                  : X300_CLOCK_WHICH_DB1_RX; -    db_config.which_tx_clk = (_radio_slot == "A") ? X300_CLOCK_WHICH_DB0_TX -                                                  : X300_CLOCK_WHICH_DB1_TX; -    db_config.dboard_slot   = (_radio_slot == "A") ? 0 : 1; -    db_config.cmd_time_ctrl = _get_ctrl(IO_MASTER_RADIO); - -    // create a new dboard manager -    boost::shared_ptr<x300_dboard_iface> db_iface = -        boost::make_shared<x300_dboard_iface>(db_config); -    _db_manager = dboard_manager::make(_db_eeproms[RX_EEPROM_ADDR + DB_OFFSET], -        _db_eeproms[TX_EEPROM_ADDR + DB_OFFSET], -        _db_eeproms[GDB_EEPROM_ADDR + DB_OFFSET], -        db_iface, -        _tree->subtree(db_path), -        true // defer daughterboard intitialization -    ); - -    size_t rx_chan = 0, tx_chan = 0; -    for (const std::string& fe : _db_manager->get_rx_frontends()) { -        if (rx_chan >= _get_num_radios()) { -            break; -        } -        _rx_fe_map[rx_chan].db_fe_name = fe; -        db_iface->add_rx_fe(fe, _rx_fe_map[rx_chan].core); -        const fs_path fe_path(db_path / "rx_frontends" / fe); -        const std::string conn = _tree->access<std::string>(fe_path / "connection").get(); -        const double if_freq = -            (_tree->exists(fe_path / "if_freq/value")) -                ? _tree->access<double>(fe_path / "if_freq/value").get() -                : 0.0; -        _rx_fe_map[rx_chan].core->set_fe_connection(usrp::fe_connection_t(conn, if_freq)); -        rx_chan++; -    } -    for (const std::string& fe : _db_manager->get_tx_frontends()) { -        if (tx_chan >= _get_num_radios()) { -            break; -        } -        _tx_fe_map[tx_chan].db_fe_name = fe; -        const fs_path fe_path(db_path / "tx_frontends" / fe); -        const std::string conn = _tree->access<std::string>(fe_path / "connection").get(); -        _tx_fe_map[tx_chan].core->set_mux(conn); -        tx_chan++; -    } -    UHD_ASSERT_THROW(rx_chan or tx_chan); - -    // Initialize the daughterboards now that frontend cores and connections exist -    _db_manager->initialize_dboards(); - -    // now that dboard is created -- register into rx antenna event -    if (not _rx_fe_map.empty()) { -        for (size_t i = 0; i < _get_num_radios(); i++) { -            if (_tree->exists(db_path / "rx_frontends" / _rx_fe_map[i].db_fe_name -                              / "antenna" / "value")) { -                // We need a desired subscriber for antenna/value because the experts -                // don't coerce that property. -                _tree -                    ->access<std::string>(db_path / "rx_frontends" -                                          / _rx_fe_map[i].db_fe_name / "antenna" -                                          / "value") -                    .add_desired_subscriber(boost::bind( -                        &x300_radio_ctrl_impl::_update_atr_leds, this, _1, i)); -                _update_atr_leds(_tree -                                     ->access<std::string>(db_path / "rx_frontends" -                                                           / _rx_fe_map[i].db_fe_name -                                                           / "antenna" / "value") -                                     .get(), -                    i); -            } else { -                _update_atr_leds("", i); // init anyway, even if never called -            } -        } -    } - -    // bind frontend corrections to the dboard freq props -    const fs_path db_tx_fe_path = db_path / "tx_frontends"; -    if (not _tx_fe_map.empty()) { -        for (size_t i = 0; i < _get_num_radios(); i++) { -            if (_tree->exists( -                    db_tx_fe_path / _tx_fe_map[i].db_fe_name / "freq" / "value")) { -                _tree -                    ->access<double>( -                        db_tx_fe_path / _tx_fe_map[i].db_fe_name / "freq" / "value") -                    .add_coerced_subscriber( -                        boost::bind(&x300_radio_ctrl_impl::set_tx_fe_corrections, -                            this, -                            db_path, -                            _root_path / "tx_fe_corrections" / _tx_fe_map[i].db_fe_name, -                            _1)); -            } -        } -    } -    const fs_path db_rx_fe_path = db_path / "rx_frontends"; -    if (not _rx_fe_map.empty()) { -        for (size_t i = 0; i < _get_num_radios(); i++) { -            if (_tree->exists( -                    db_rx_fe_path / _tx_fe_map[i].db_fe_name / "freq" / "value")) { -                _tree -                    ->access<double>( -                        db_rx_fe_path / _tx_fe_map[i].db_fe_name / "freq" / "value") -                    .add_coerced_subscriber( -                        boost::bind(&x300_radio_ctrl_impl::set_rx_fe_corrections, -                            this, -                            db_path, -                            _root_path / "rx_fe_corrections" / _tx_fe_map[i].db_fe_name, -                            _1)); -            } -        } -    } - -    //////////////////////////////////////////////////////////////// -    // Set tick rate -    //////////////////////////////////////////////////////////////// -    const double tick_rate = _tree->access<double>("tick_rate").get(); -    radio_ctrl_impl::set_rate(tick_rate); - -    //////////////////////////////////////////////////////////////// -    // Set gain groups -    // Note: The actual gain control comes from the daughterboard drivers, thus, -    // we need to call into the prop tree at the appropriate location in order -    // to modify the gains. -    //////////////////////////////////////////////////////////////// -    // TX -    for (size_t chan = 0; chan < _num_tx_channels; chan++) { -        fs_path rf_gains_path(db_tx_fe_path / _tx_fe_map.at(chan).db_fe_name / "gains"); -        if (!_tree->exists(rf_gains_path)) { -            continue; -        } - -        std::vector<std::string> gain_stages = _tree->list(rf_gains_path); -        if (gain_stages.empty()) { -            continue; -        } - -        // DAC does not have a gain path -        auto gg = gain_group::make(); -        for (const auto& name : gain_stages) { -            gg->register_fcns(name, -                make_gain_fcns_from_subtree(_tree->subtree(rf_gains_path / name)), -                1 /* high prio */); -        } -        _tx_gain_groups[chan] = gg; -    } -    // RX -    for (size_t chan = 0; chan < _num_rx_channels; chan++) { -        fs_path rf_gains_path(db_rx_fe_path / _rx_fe_map.at(chan).db_fe_name / "gains"); -        fs_path adc_gains_path("rx_codecs" / _radio_slot / "gains"); - -        auto gg = gain_group::make(); -        // ADC also has a gain path -        for (const auto& name : _tree->list(adc_gains_path)) { -            gg->register_fcns("ADC-" + name, -                make_gain_fcns_from_subtree(_tree->subtree(adc_gains_path / name)), -                0 /* low prio */); -        } -        if (_tree->exists(rf_gains_path)) { -            for (const auto& name : _tree->list(rf_gains_path)) { -                gg->register_fcns(name, -                    make_gain_fcns_from_subtree(_tree->subtree(rf_gains_path / name)), -                    1 /* high prio */); -            } -        } -        _rx_gain_groups[chan] = gg; -    } -} - -void x300_radio_ctrl_impl::set_rx_fe_corrections( -    const fs_path& db_path, const fs_path& rx_fe_corr_path, const double lo_freq) -{ -    if (not _ignore_cal_file) { -        apply_rx_fe_corrections(_tree, db_path, rx_fe_corr_path, lo_freq); -    } -} - -void x300_radio_ctrl_impl::set_tx_fe_corrections( -    const fs_path& db_path, const fs_path& tx_fe_corr_path, const double lo_freq) -{ -    if (not _ignore_cal_file) { -        apply_tx_fe_corrections(_tree, db_path, tx_fe_corr_path, lo_freq); -    } -} - -void x300_radio_ctrl_impl::reset_codec() -{ -    if (_radio_type == PRIMARY) { // ADC/DAC reset lines only exist in Radio0 -        _regs->misc_outs_reg.set(radio_regmap_t::misc_outs_reg_t::ADC_RESET, 1); -        _regs->misc_outs_reg.set(radio_regmap_t::misc_outs_reg_t::DAC_RESET_N, 0); -        _regs->misc_outs_reg.flush(); -        _regs->misc_outs_reg.set(radio_regmap_t::misc_outs_reg_t::ADC_RESET, 0); -        _regs->misc_outs_reg.set(radio_regmap_t::misc_outs_reg_t::DAC_RESET_N, 1); -        _regs->misc_outs_reg.flush(); -    } -    UHD_ASSERT_THROW(bool(_adc)); -    UHD_ASSERT_THROW(bool(_dac)); -    _adc->reset(); -    _dac->reset(); -} - -void x300_radio_ctrl_impl::self_test_adc(uint32_t ramp_time_ms) -{ -    // Bypass all front-end corrections -    for (size_t i = 0; i < _get_num_radios(); i++) { -        _rx_fe_map[i].core->bypass_all(true); -    } - -    // Test basic patterns -    _adc->set_test_word("ones", "ones"); -    _check_adc(0xfffcfffc); -    _adc->set_test_word("zeros", "zeros"); -    _check_adc(0x00000000); -    _adc->set_test_word("ones", "zeros"); -    _check_adc(0xfffc0000); -    _adc->set_test_word("zeros", "ones"); -    _check_adc(0x0000fffc); -    for (size_t k = 0; k < 14; k++) { -        _adc->set_test_word("zeros", "custom", 1 << k); -        _check_adc(1 << (k + 2)); -    } -    for (size_t k = 0; k < 14; k++) { -        _adc->set_test_word("custom", "zeros", 1 << k); -        _check_adc(1 << (k + 18)); -    } - -    // Turn on ramp pattern test -    _adc->set_test_word("ramp", "ramp"); -    _regs->misc_outs_reg.write(radio_regmap_t::misc_outs_reg_t::ADC_CHECKER_ENABLED, 0); -    // Sleep added for SPI transactions to finish and ramp to start before checker is -    // enabled. -    std::this_thread::sleep_for(std::chrono::microseconds(1000)); -    _regs->misc_outs_reg.write(radio_regmap_t::misc_outs_reg_t::ADC_CHECKER_ENABLED, 1); - -    std::this_thread::sleep_for(std::chrono::milliseconds(ramp_time_ms)); -    _regs->misc_ins_reg.refresh(); - -    std::string i_status, q_status; -    if (_regs->misc_ins_reg.get(radio_regmap_t::misc_ins_reg_t::ADC_CHECKER1_I_LOCKED)) -        if (_regs->misc_ins_reg.get(radio_regmap_t::misc_ins_reg_t::ADC_CHECKER1_I_ERROR)) -            i_status = "Bit Errors!"; -        else -            i_status = "Good"; -    else -        i_status = "Not Locked!"; - -    if (_regs->misc_ins_reg.get(radio_regmap_t::misc_ins_reg_t::ADC_CHECKER1_Q_LOCKED)) -        if (_regs->misc_ins_reg.get(radio_regmap_t::misc_ins_reg_t::ADC_CHECKER1_Q_ERROR)) -            q_status = "Bit Errors!"; -        else -            q_status = "Good"; -    else -        q_status = "Not Locked!"; - -    // Return to normal mode -    _adc->set_test_word("normal", "normal"); - -    if ((i_status != "Good") or (q_status != "Good")) { -        throw uhd::runtime_error( -            (boost::format( -                 "ADC self-test failed for %s. Ramp checker status: {ADC_A=%s, ADC_B=%s}") -                % unique_id() % i_status % q_status) -                .str()); -    } - -    // Restore front-end corrections -    for (size_t i = 0; i < _get_num_radios(); i++) { -        _rx_fe_map[i].core->bypass_all(false); -    } -} - -void x300_radio_ctrl_impl::extended_adc_test( -    const std::vector<x300_radio_ctrl_impl::sptr>& radios, double duration_s) -{ -    static const size_t SECS_PER_ITER = 5; -    UHD_LOGGER_INFO("X300 RADIO") -        << boost::format( -               "Running Extended ADC Self-Test (Duration=%.0fs, %ds/iteration)...") -               % duration_s % SECS_PER_ITER; - -    size_t num_iters    = static_cast<size_t>(ceil(duration_s / SECS_PER_ITER)); -    size_t num_failures = 0; -    for (size_t iter = 0; iter < num_iters; iter++) { -        // Run self-test -        UHD_LOGGER_INFO("X300 RADIO") -            << boost::format("Extended ADC Self-Test Iteration %06d... ") % (iter + 1); -        try { -            for (size_t i = 0; i < radios.size(); i++) { -                radios[i]->self_test_adc((SECS_PER_ITER * 1000) / radios.size()); -            } -            UHD_LOGGER_INFO("X300 RADIO") -                << boost::format("Extended ADC Self-Test Iteration %06d passed ") -                       % (iter + 1); -        } catch (std::exception& e) { -            num_failures++; -            UHD_LOGGER_ERROR("X300 RADIO") << e.what(); -        } -    } -    if (num_failures == 0) { -        UHD_LOGGER_INFO("X300 RADIO") << "Extended ADC Self-Test PASSED"; -    } else { -        throw uhd::runtime_error( -            (boost::format("Extended ADC Self-Test FAILED!!! (%d/%d failures)\n") -                % num_failures % num_iters) -                .str()); -    } -} - -void x300_radio_ctrl_impl::synchronize_dacs( -    const std::vector<x300_radio_ctrl_impl::sptr>& radios) -{ -    if (radios.size() < 2) -        return; // Nothing to synchronize - -    //**PRECONDITION** -    // This function assumes that all the VITA times in "radios" are synchronized -    // to a common reference. Currently, this function is called in get_tx_stream -    // which also has the same precondition. - -    // Get a rough estimate of the cumulative command latency -    boost::posix_time::ptime t_start = boost::posix_time::microsec_clock::local_time(); -    for (size_t i = 0; i < radios.size(); i++) { -        radios[i]->user_reg_read64( -            regs::RB_TIME_NOW); // Discard value. We are just timing the call -    } -    boost::posix_time::time_duration t_elapsed = -        boost::posix_time::microsec_clock::local_time() - t_start; - -    // Add 100% of headroom + uncertainty to the command time -    uint64_t t_sync_us = -        (t_elapsed.total_microseconds() * 2) + 16000 /*Scheduler latency*/; - -    std::string err_str; -    // Try to sync 3 times before giving up -    for (size_t attempt = 0; attempt < 3; attempt++) { -        try { -            // Reinitialize and resync all DACs -            for (size_t i = 0; i < radios.size(); i++) { -                radios[i]->_dac->sync(); -            } - -            // Set tick rate and make sure FRAMEP/N is 0 -            for (size_t i = 0; i < radios.size(); i++) { -                radios[i]->set_command_tick_rate( -                    radios[i]->_radio_clk_rate, IO_MASTER_RADIO); -                radios[i]->_regs->misc_outs_reg.write( -                    radio_regmap_t::misc_outs_reg_t::DAC_SYNC, 0); -            } - -            // Pick radios[0] as the time reference. -            uhd::time_spec_t sync_time = radios[0]->_time64->get_time_now() -                                         + uhd::time_spec_t(((double)t_sync_us) / 1e6); - -            // Send the sync command -            for (size_t i = 0; i < radios.size(); i++) { -                radios[i]->set_command_time(sync_time, IO_MASTER_RADIO); -                // Arm FRAMEP/N sync pulse by asserting a rising edge -                radios[i]->_regs->misc_outs_reg.write( -                    radio_regmap_t::misc_outs_reg_t::DAC_SYNC, 1); -            } - -            // Reset FRAMEP/N to 0 after 2 clock cycles -            for (size_t i = 0; i < radios.size(); i++) { -                radios[i]->set_command_time( -                    sync_time + (2.0 / radios[i]->_radio_clk_rate), IO_MASTER_RADIO); -                radios[i]->_regs->misc_outs_reg.write( -                    radio_regmap_t::misc_outs_reg_t::DAC_SYNC, 0); -                radios[i]->set_command_time(uhd::time_spec_t(0.0), IO_MASTER_RADIO); -            } - -            // Wait and check status -            std::this_thread::sleep_for(std::chrono::microseconds(t_sync_us)); -            for (size_t i = 0; i < radios.size(); i++) { -                radios[i]->_dac->verify_sync(); -            } - -            return; -        } catch (const uhd::runtime_error& e) { -            err_str = e.what(); -            UHD_LOGGER_TRACE("X300 RADIO") << "Retrying DAC synchronization: " << err_str; -        } -    } -    throw uhd::runtime_error(err_str); -} - -double x300_radio_ctrl_impl::self_cal_adc_xfer_delay( -    const std::vector<x300_radio_ctrl_impl::sptr>& radios, -    x300_clock_ctrl::sptr clock, -    boost::function<void(double)> wait_for_clk_locked, -    bool apply_delay) -{ -    UHD_LOGGER_INFO("X300 RADIO") << "Running ADC transfer delay self-cal: "; - -    // Effective resolution of the self-cal. -    static const size_t NUM_DELAY_STEPS = 100; - -    double master_clk_period = (1.0e9 / clock->get_master_clock_rate()); // in ns -    double delay_start       = 0.0; -    double delay_range       = 2 * master_clk_period; -    double delay_incr        = delay_range / NUM_DELAY_STEPS; - -    double cached_clk_delay = clock->get_clock_delay(X300_CLOCK_WHICH_ADC0); -    double fpga_clk_delay   = clock->get_clock_delay(X300_CLOCK_WHICH_FPGA); - -    // Iterate through several values of delays and measure ADC data integrity -    std::vector<std::pair<double, bool>> results; -    for (size_t i = 0; i < NUM_DELAY_STEPS; i++) { -        // Delay the ADC clock (will set both Ch0 and Ch1 delays) -        double delay = -            clock->set_clock_delay(X300_CLOCK_WHICH_ADC0, delay_incr * i + delay_start); -        wait_for_clk_locked(0.1); - -        uint32_t err_code = 0; -        for (size_t r = 0; r < radios.size(); r++) { -            // Test each channel (I and Q) individually so as to not accidentally trigger -            // on the data from the other channel if there is a swap - -            // -- Test I Channel -- -            // Put ADC in ramp test mode. Tie the other channel to all ones. -            radios[r]->_adc->set_test_word("ramp", "ones"); -            // Turn on the pattern checker in the FPGA. It will lock when it sees a zero -            // and count deviations from the expected value -            radios[r]->_regs->misc_outs_reg.write( -                radio_regmap_t::misc_outs_reg_t::ADC_CHECKER_ENABLED, 0); -            radios[r]->_regs->misc_outs_reg.write( -                radio_regmap_t::misc_outs_reg_t::ADC_CHECKER_ENABLED, 1); -            // 50ms @ 200MHz = 10 million samples -            std::this_thread::sleep_for(std::chrono::milliseconds(50)); -            if (radios[r]->_regs->misc_ins_reg.read( -                    radio_regmap_t::misc_ins_reg_t::ADC_CHECKER1_I_LOCKED)) { -                err_code += radios[r]->_regs->misc_ins_reg.get( -                    radio_regmap_t::misc_ins_reg_t::ADC_CHECKER1_I_ERROR); -            } else { -                err_code += 100; // Increment error code by 100 to indicate no lock -            } - -            // -- Test Q Channel -- -            // Put ADC in ramp test mode. Tie the other channel to all ones. -            radios[r]->_adc->set_test_word("ones", "ramp"); -            // Turn on the pattern checker in the FPGA. It will lock when it sees a zero -            // and count deviations from the expected value -            radios[r]->_regs->misc_outs_reg.write( -                radio_regmap_t::misc_outs_reg_t::ADC_CHECKER_ENABLED, 0); -            radios[r]->_regs->misc_outs_reg.write( -                radio_regmap_t::misc_outs_reg_t::ADC_CHECKER_ENABLED, 1); -            // 50ms @ 200MHz = 10 million samples -            std::this_thread::sleep_for(std::chrono::milliseconds(50)); -            if (radios[r]->_regs->misc_ins_reg.read( -                    radio_regmap_t::misc_ins_reg_t::ADC_CHECKER1_Q_LOCKED)) { -                err_code += radios[r]->_regs->misc_ins_reg.get( -                    radio_regmap_t::misc_ins_reg_t::ADC_CHECKER1_Q_ERROR); -            } else { -                err_code += 100; // Increment error code by 100 to indicate no lock -            } -        } -        // UHD_LOGGER_INFO("X300 RADIO") << (boost::format("XferDelay=%fns, Error=%d") % -        // delay % err_code); -        results.push_back(std::pair<double, bool>(delay, err_code == 0)); -    } - -    // Calculate the valid window -    int win_start_idx = -1, win_stop_idx = -1, cur_start_idx = -1, cur_stop_idx = -1; -    for (size_t i = 0; i < results.size(); i++) { -        std::pair<double, bool>& item = results[i]; -        if (item.second) { // If data is stable -            if (cur_start_idx == -1) { // This is the first window -                cur_start_idx = i; -                cur_stop_idx  = i; -            } else { // We are extending the window -                cur_stop_idx = i; -            } -        } else { -            if (cur_start_idx == -1) { // We haven't yet seen valid data -                // Do nothing -            } else if (win_start_idx == -1) { // We passed the first valid window -                win_start_idx = cur_start_idx; -                win_stop_idx  = cur_stop_idx; -            } else { // Update cached window if current window is larger -                double cur_win_len = -                    results[cur_stop_idx].first - results[cur_start_idx].first; -                double cached_win_len = -                    results[win_stop_idx].first - results[win_start_idx].first; -                if (cur_win_len > cached_win_len) { -                    win_start_idx = cur_start_idx; -                    win_stop_idx  = cur_stop_idx; -                } -            } -            // Reset current window -            cur_start_idx = -1; -            cur_stop_idx  = -1; -        } -    } -    if (win_start_idx == -1) { -        throw uhd::runtime_error( -            "self_cal_adc_xfer_delay: Self calibration failed. Convergence error."); -    } - -    double win_center = -        (results[win_stop_idx].first + results[win_start_idx].first) / 2.0; -    double win_length = results[win_stop_idx].first - results[win_start_idx].first; -    if (win_length < master_clk_period / 4) { -        throw uhd::runtime_error( -            "self_cal_adc_xfer_delay: Self calibration failed. Valid window too narrow."); -    } - -    // Cycle slip the relative delay by a clock cycle to prevent sample misalignment -    // fpga_clk_delay > 0 and 0 < win_center < 2*(1/MCR) so one cycle slip is all we need -    bool cycle_slip = (win_center - fpga_clk_delay >= master_clk_period); -    if (cycle_slip) { -        win_center -= master_clk_period; -    } - -    if (apply_delay) { -        // Apply delay -        win_center = clock->set_clock_delay( -            X300_CLOCK_WHICH_ADC0, win_center); // Sets ADC0 and ADC1 -        wait_for_clk_locked(0.1); -        // Validate -        for (size_t r = 0; r < radios.size(); r++) { -            radios[r]->self_test_adc(2000); -        } -    } else { -        // Restore delay -        clock->set_clock_delay( -            X300_CLOCK_WHICH_ADC0, cached_clk_delay); // Sets ADC0 and ADC1 -    } - -    // Teardown -    for (size_t r = 0; r < radios.size(); r++) { -        radios[r]->_adc->set_test_word("normal", "normal"); -        radios[r]->_regs->misc_outs_reg.write( -            radio_regmap_t::misc_outs_reg_t::ADC_CHECKER_ENABLED, 0); -    } -    UHD_LOGGER_INFO("X300 RADIO") -        << (boost::format( -                "ADC transfer delay self-cal done (FPGA->ADC=%.3fns%s, Window=%.3fns)") -               % (win_center - fpga_clk_delay) % (cycle_slip ? " +cyc" : "") -               % win_length); - -    return win_center; -} -/**************************************************************************** - * Helpers - ***************************************************************************/ -void x300_radio_ctrl_impl::_update_atr_leds(const std::string& rx_ant, const size_t chan) -{ -    // The "RX1" port is used by TwinRX and the "TX/RX" port is used by all -    // other full-duplex dboards. We need to handle both here. -    const bool is_txrx = (rx_ant == "TX/RX" or rx_ant == "RX1"); -    const int TXRX_RX  = (1 << 0); -    const int TXRX_TX  = (1 << 1); -    const int RX2_RX   = (1 << 2); -    _leds.at(chan)->set_atr_reg(gpio_atr::ATR_REG_IDLE, 0); -    _leds.at(chan)->set_atr_reg(gpio_atr::ATR_REG_RX_ONLY, is_txrx ? TXRX_RX : RX2_RX); -    _leds.at(chan)->set_atr_reg(gpio_atr::ATR_REG_TX_ONLY, TXRX_TX); -    _leds.at(chan)->set_atr_reg(gpio_atr::ATR_REG_FULL_DUPLEX, RX2_RX | TXRX_TX); -} - -void x300_radio_ctrl_impl::_self_cal_adc_capture_delay(bool print_status) -{ -    if (print_status) -        UHD_LOGGER_INFO("X300 RADIO") << "Running ADC capture delay self-cal..."; - -    static const uint32_t NUM_DELAY_STEPS = 32; // The IDELAYE2 element has 32 steps -    static const uint32_t NUM_RETRIES = -        2; // Retry self-cal if it fails in warmup situations -    static const int32_t MIN_WINDOW_LEN = 4; - -    int32_t win_start = -1, win_stop = -1; -    uint32_t iter = 0; -    while (iter++ < NUM_RETRIES) { -        for (uint32_t dly_tap = 0; dly_tap < NUM_DELAY_STEPS; dly_tap++) { -            // Apply delay -            _regs->misc_outs_reg.write( -                radio_regmap_t::misc_outs_reg_t::ADC_DATA_DLY_VAL, dly_tap); -            _regs->misc_outs_reg.write( -                radio_regmap_t::misc_outs_reg_t::ADC_DATA_DLY_STB, 1); -            _regs->misc_outs_reg.write( -                radio_regmap_t::misc_outs_reg_t::ADC_DATA_DLY_STB, 0); - -            uint32_t err_code = 0; - -            // -- Test I Channel -- -            // Put ADC in ramp test mode. Tie the other channel to all ones. -            _adc->set_test_word("ramp", "ones"); -            // Turn on the pattern checker in the FPGA. It will lock when it sees a zero -            // and count deviations from the expected value -            _regs->misc_outs_reg.write( -                radio_regmap_t::misc_outs_reg_t::ADC_CHECKER_ENABLED, 0); -            _regs->misc_outs_reg.write( -                radio_regmap_t::misc_outs_reg_t::ADC_CHECKER_ENABLED, 1); -            // 5ms @ 200MHz = 1 million samples -            std::this_thread::sleep_for(std::chrono::milliseconds(5)); -            if (_regs->misc_ins_reg.read( -                    radio_regmap_t::misc_ins_reg_t::ADC_CHECKER0_I_LOCKED)) { -                err_code += _regs->misc_ins_reg.get( -                    radio_regmap_t::misc_ins_reg_t::ADC_CHECKER0_I_ERROR); -            } else { -                err_code += 100; // Increment error code by 100 to indicate no lock -            } - -            // -- Test Q Channel -- -            // Put ADC in ramp test mode. Tie the other channel to all ones. -            _adc->set_test_word("ones", "ramp"); -            // Turn on the pattern checker in the FPGA. It will lock when it sees a zero -            // and count deviations from the expected value -            _regs->misc_outs_reg.write( -                radio_regmap_t::misc_outs_reg_t::ADC_CHECKER_ENABLED, 0); -            _regs->misc_outs_reg.write( -                radio_regmap_t::misc_outs_reg_t::ADC_CHECKER_ENABLED, 1); -            // 5ms @ 200MHz = 1 million samples -            std::this_thread::sleep_for(std::chrono::milliseconds(5)); -            if (_regs->misc_ins_reg.read( -                    radio_regmap_t::misc_ins_reg_t::ADC_CHECKER0_Q_LOCKED)) { -                err_code += _regs->misc_ins_reg.get( -                    radio_regmap_t::misc_ins_reg_t::ADC_CHECKER0_Q_ERROR); -            } else { -                err_code += 100; // Increment error code by 100 to indicate no lock -            } - -            if (err_code == 0) { -                if (win_start == -1) { // This is the first window -                    win_start = dly_tap; -                    win_stop  = dly_tap; -                } else { // We are extending the window -                    win_stop = dly_tap; -                } -            } else { -                if (win_start != -1) { // A valid window turned invalid -                    if (win_stop - win_start >= MIN_WINDOW_LEN) { -                        break; // Valid window found -                    } else { -                        win_start = -1; // Reset window -                    } -                } -            } -            // UHD_LOGGER_INFO("X300 RADIO") << (boost::format("CapTap=%d, Error=%d") % -            // dly_tap % err_code); -        } - -        // Retry the self-cal if it fails -        if ((win_start == -1 || (win_stop - win_start) < MIN_WINDOW_LEN) -            && iter < NUM_RETRIES /*not last iteration*/) { -            win_start = -1; -            win_stop  = -1; -            std::this_thread::sleep_for(std::chrono::milliseconds(2000)); -        } else { -            break; -        } -    } -    _adc->set_test_word("normal", "normal"); -    _regs->misc_outs_reg.write(radio_regmap_t::misc_outs_reg_t::ADC_CHECKER_ENABLED, 0); - -    if (win_start == -1) { -        throw uhd::runtime_error( -            "self_cal_adc_capture_delay: Self calibration failed. Convergence error."); -    } - -    if (win_stop - win_start < MIN_WINDOW_LEN) { -        throw uhd::runtime_error("self_cal_adc_capture_delay: Self calibration failed. " -                                 "Valid window too narrow."); -    } - -    uint32_t ideal_tap = (win_stop + win_start) / 2; -    _regs->misc_outs_reg.write( -        radio_regmap_t::misc_outs_reg_t::ADC_DATA_DLY_VAL, ideal_tap); -    _regs->misc_outs_reg.write(radio_regmap_t::misc_outs_reg_t::ADC_DATA_DLY_STB, 1); -    _regs->misc_outs_reg.write(radio_regmap_t::misc_outs_reg_t::ADC_DATA_DLY_STB, 0); - -    if (print_status) { -        double tap_delay = (1.0e12 / _radio_clk_rate) / (2 * 32); // in ps -        UHD_LOGGER_INFO("X300 RADIO") -            << boost::format("ADC capture delay self-cal done (Tap=%d, Window=%d, " -                             "TapDelay=%.3fps, Iter=%d)") -                   % ideal_tap % (win_stop - win_start) % tap_delay % iter; -    } -} - -void x300_radio_ctrl_impl::_check_adc(const uint32_t val) -{ -    // Wait for previous control transaction to flush -    user_reg_read64(regs::RB_TEST); -    // Wait for ADC test pattern to propagate -    std::this_thread::sleep_for(std::chrono::microseconds(5)); -    // Read value of RX readback register and verify -    uint32_t adc_rb = static_cast<uint32_t>(user_reg_read64(regs::RB_TEST) >> 32); -    adc_rb ^= 0xfffc0000; // adapt for I inversion in FPGA -    if (val != adc_rb) { -        throw uhd::runtime_error( -            (boost::format("ADC self-test failed for %s. (Exp=0x%x, Got=0x%x)") -                % unique_id() % val % adc_rb) -                .str()); -    } -} - -void x300_radio_ctrl_impl::_set_db_eeprom( -    i2c_iface::sptr i2c, const size_t addr, const uhd::usrp::dboard_eeprom_t& db_eeprom) -{ -    db_eeprom.store(*i2c, addr); -    _db_eeproms[addr] = db_eeprom; -} - -void x300_radio_ctrl_impl::_set_command_time(const time_spec_t& spec, const size_t port) -{ -    set_fe_cmd_time(spec, port); -} -/**************************************************************************** - * Helpers - ***************************************************************************/ -bool x300_radio_ctrl_impl::check_radio_config() -{ -    UHD_RFNOC_BLOCK_TRACE() << "x300_radio_ctrl_impl::check_radio_config() "; -    const fs_path rx_fe_path = fs_path("dboards" / _radio_slot / "rx_frontends"); -    for (size_t chan = 0; chan < _num_rx_channels; chan++) { -        if (_tree->exists(rx_fe_path / _rx_fe_map.at(chan).db_fe_name / "enabled")) { -            const bool chan_active = _is_streamer_active(uhd::RX_DIRECTION, chan); -            if (chan_active) { -                _tree -                    ->access<bool>( -                        rx_fe_path / _rx_fe_map.at(chan).db_fe_name / "enabled") -                    .set(chan_active); -            } -        } -    } - -    const fs_path tx_fe_path = fs_path("dboards" / _radio_slot / "tx_frontends"); -    for (size_t chan = 0; chan < _num_tx_channels; chan++) { -        if (_tree->exists(tx_fe_path / _tx_fe_map.at(chan).db_fe_name / "enabled")) { -            const bool chan_active = _is_streamer_active(uhd::TX_DIRECTION, chan); -            if (chan_active) { -                _tree -                    ->access<bool>( -                        tx_fe_path / _tx_fe_map.at(chan).db_fe_name / "enabled") -                    .set(chan_active); -            } -        } -    } - -    return true; -} - -/**************************************************************************** - * Register block - ***************************************************************************/ -UHD_RFNOC_BLOCK_REGISTER(x300_radio_ctrl, "X300Radio"); diff --git a/host/lib/usrp/x300/x300_radio_ctrl_impl.hpp b/host/lib/usrp/x300/x300_radio_ctrl_impl.hpp deleted file mode 100644 index 63aac876d..000000000 --- a/host/lib/usrp/x300/x300_radio_ctrl_impl.hpp +++ /dev/null @@ -1,246 +0,0 @@ -// -// Copyright 2015-2016 Ettus Research -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#ifndef INCLUDED_LIBUHD_RFNOC_X300_RADIO_CTRL_IMPL_HPP -#define INCLUDED_LIBUHD_RFNOC_X300_RADIO_CTRL_IMPL_HPP - -#include "x300_adc_ctrl.hpp" -#include "x300_clock_ctrl.hpp" -#include "x300_dac_ctrl.hpp" -#include "x300_regs.hpp" -#include <uhd/usrp/dboard_eeprom.hpp> -#include <uhd/usrp/dboard_manager.hpp> -#include <uhd/usrp/gpio_defs.hpp> -#include <uhd/utils/gain_group.hpp> -#include <uhdlib/rfnoc/radio_ctrl_impl.hpp> -#include <uhdlib/usrp/cores/rx_frontend_core_3000.hpp> -#include <uhdlib/usrp/cores/spi_core_3000.hpp> -#include <uhdlib/usrp/cores/tx_frontend_core_200.hpp> -#include <unordered_map> - -namespace uhd { namespace rfnoc { - -/*! \brief Provide access to an X300 radio. - */ -class x300_radio_ctrl_impl : public radio_ctrl_impl -{ -public: -    typedef boost::shared_ptr<x300_radio_ctrl_impl> sptr; - -    /************************************************************************ -     * Structors -     ***********************************************************************/ -    UHD_RFNOC_RADIO_BLOCK_CONSTRUCTOR_DECL(x300_radio_ctrl) -    virtual ~x300_radio_ctrl_impl(); - -    /************************************************************************ -     * API calls -     ***********************************************************************/ -    double set_rate(double rate); - -    void set_tx_antenna(const std::string& ant, const size_t chan); -    void set_rx_antenna(const std::string& ant, const size_t chan); -    std::string get_tx_antenna(const size_t chan); -    std::string get_rx_antenna(const size_t chan); - -    double set_tx_frequency(const double freq, const size_t chan); -    double set_rx_frequency(const double freq, const size_t chan); -    double set_rx_bandwidth(const double bandwidth, const size_t chan); -    double get_tx_frequency(const size_t chan); -    double get_rx_frequency(const size_t chan); -    double get_rx_bandwidth(const size_t chan); - -    double set_tx_gain(const double gain, const size_t chan); -    double set_rx_gain(const double gain, const size_t chan); -    double get_rx_gain(const size_t chan); - -    std::vector<std::string> get_rx_lo_names(const size_t chan); -    std::vector<std::string> get_rx_lo_sources( -        const std::string& name, const size_t chan); -    freq_range_t get_rx_lo_freq_range(const std::string& name, const size_t chan); - -    void set_rx_lo_source( -        const std::string& src, const std::string& name, const size_t chan); -    const std::string get_rx_lo_source(const std::string& name, const size_t chan); - -    void set_rx_lo_export_enabled( -        bool enabled, const std::string& name, const size_t chan); -    bool get_rx_lo_export_enabled(const std::string& name, const size_t chan); - -    double set_rx_lo_freq(double freq, const std::string& name, const size_t chan); -    double get_rx_lo_freq(const std::string& name, const size_t chan); - -    size_t get_chan_from_dboard_fe(const std::string& fe, const direction_t dir); -    std::string get_dboard_fe_from_chan(const size_t chan, const direction_t dir); - -    std::vector<std::string> get_gpio_banks() const; -    void set_gpio_attr(const std::string& bank, -        const std::string& attr, -        const uint32_t value, -        const uint32_t mask); -    uint32_t get_gpio_attr(const std::string& bank, const std::string& attr); - -    double get_output_samp_rate(size_t port); - -    /************************************************************************ -     * Hardware setup and control -     ***********************************************************************/ -    /*! Set up the radio. No API calls may be made before this one. -     */ -    void setup_radio(uhd::i2c_iface::sptr zpu_i2c, -        x300_clock_ctrl::sptr clock, -        bool ignore_cal_file, -        bool verbose); - -    void reset_codec(); - -    void self_test_adc(uint32_t ramp_time_ms = 100); - -    static void extended_adc_test( -        const std::vector<x300_radio_ctrl_impl::sptr>&, double duration_s); - -    static void synchronize_dacs(const std::vector<x300_radio_ctrl_impl::sptr>& radios); - -    static double self_cal_adc_xfer_delay( -        const std::vector<x300_radio_ctrl_impl::sptr>& radios, -        x300_clock_ctrl::sptr clock, -        boost::function<void(double)> wait_for_clk_locked, -        bool apply_delay); - -protected: -    virtual bool check_radio_config(); - -private: -    class radio_regmap_t : public uhd::soft_regmap_t -    { -    public: -        typedef boost::shared_ptr<radio_regmap_t> sptr; -        class misc_outs_reg_t : public uhd::soft_reg32_wo_t -        { -        public: -            UHD_DEFINE_SOFT_REG_FIELD(DAC_ENABLED, /*width*/ 1, /*shift*/ 0); //[0] -            UHD_DEFINE_SOFT_REG_FIELD(DAC_RESET_N, /*width*/ 1, /*shift*/ 1); //[1] -            UHD_DEFINE_SOFT_REG_FIELD(ADC_RESET, /*width*/ 1, /*shift*/ 2); //[2] -            UHD_DEFINE_SOFT_REG_FIELD(ADC_DATA_DLY_STB, /*width*/ 1, /*shift*/ 3); //[3] -            UHD_DEFINE_SOFT_REG_FIELD(ADC_DATA_DLY_VAL, /*width*/ 5, /*shift*/ 4); //[8:4] -            UHD_DEFINE_SOFT_REG_FIELD( -                ADC_CHECKER_ENABLED, /*width*/ 1, /*shift*/ 9); //[9] -            UHD_DEFINE_SOFT_REG_FIELD(DAC_SYNC, /*width*/ 1, /*shift*/ 10); //[10] - -            misc_outs_reg_t() : uhd::soft_reg32_wo_t(regs::sr_addr(regs::MISC_OUTS)) -            { -                // Initial values -                set(DAC_ENABLED, 0); -                set(DAC_RESET_N, 0); -                set(ADC_RESET, 0); -                set(ADC_DATA_DLY_STB, 0); -                set(ADC_DATA_DLY_VAL, 16); -                set(ADC_CHECKER_ENABLED, 0); -                set(DAC_SYNC, 0); -            } -        } misc_outs_reg; - -        class misc_ins_reg_t : public uhd::soft_reg64_ro_t -        { -        public: -            UHD_DEFINE_SOFT_REG_FIELD( -                ADC_CHECKER0_Q_LOCKED, /*width*/ 1, /*shift*/ 32); //[0] -            UHD_DEFINE_SOFT_REG_FIELD( -                ADC_CHECKER0_I_LOCKED, /*width*/ 1, /*shift*/ 33); //[1] -            UHD_DEFINE_SOFT_REG_FIELD( -                ADC_CHECKER1_Q_LOCKED, /*width*/ 1, /*shift*/ 34); //[2] -            UHD_DEFINE_SOFT_REG_FIELD( -                ADC_CHECKER1_I_LOCKED, /*width*/ 1, /*shift*/ 35); //[3] -            UHD_DEFINE_SOFT_REG_FIELD( -                ADC_CHECKER0_Q_ERROR, /*width*/ 1, /*shift*/ 36); //[4] -            UHD_DEFINE_SOFT_REG_FIELD( -                ADC_CHECKER0_I_ERROR, /*width*/ 1, /*shift*/ 37); //[5] -            UHD_DEFINE_SOFT_REG_FIELD( -                ADC_CHECKER1_Q_ERROR, /*width*/ 1, /*shift*/ 38); //[6] -            UHD_DEFINE_SOFT_REG_FIELD( -                ADC_CHECKER1_I_ERROR, /*width*/ 1, /*shift*/ 39); //[7] - -            misc_ins_reg_t() : uhd::soft_reg64_ro_t(regs::rb_addr(regs::RB_MISC_IO)) {} -        } misc_ins_reg; - -        radio_regmap_t(int radio_num) -            : soft_regmap_t("radio" + std::to_string(radio_num) + "_regmap") -        { -            add_to_map(misc_outs_reg, "misc_outs_reg", PRIVATE); -            add_to_map(misc_ins_reg, "misc_ins_reg", PRIVATE); -        } -    }; - -    struct x300_regs -    { -        static const uint32_t TX_FE_BASE = 224; -        static const uint32_t RX_FE_BASE = 232; -    }; - -    void _update_atr_leds(const std::string& rx_ant, const size_t chan); - -    void _self_cal_adc_capture_delay(bool print_status); - -    void _check_adc(const uint32_t val); - -    void _set_db_eeprom( -        uhd::i2c_iface::sptr i2c, const size_t, const uhd::usrp::dboard_eeprom_t&); - -    void set_rx_fe_corrections(const uhd::fs_path& db_path, -        const uhd::fs_path& rx_fe_corr_path, -        const double lo_freq); -    void set_tx_fe_corrections(const uhd::fs_path& db_path, -        const uhd::fs_path& tx_fe_corr_path, -        const double lo_freq); - -    void _set_command_time(const uhd::time_spec_t& spec, const size_t port); -    void set_fe_cmd_time(const time_spec_t& time, const size_t chan); - -private: // members -    enum radio_connection_t { PRIMARY, SECONDARY }; - -    radio_connection_t _radio_type; -    std::string _radio_slot; -    //! Radio clock rate is the rate at which the ADC and DAC are running at. -    // Not necessarily this block's sampling rate (tick rate). -    double _radio_clk_rate; - -    radio_regmap_t::sptr _regs; -    std::map<size_t, usrp::gpio_atr::gpio_atr_3000::sptr> _leds; -    spi_core_3000::sptr _spi; -    x300_adc_ctrl::sptr _adc; -    x300_dac_ctrl::sptr _dac; -    usrp::gpio_atr::gpio_atr_3000::sptr _fp_gpio; - -    std::map<size_t, usrp::dboard_eeprom_t> _db_eeproms; -    usrp::dboard_manager::sptr _db_manager; - -    struct rx_fe_perif -    { -        std::string name; -        std::string db_fe_name; -        rx_frontend_core_3000::sptr core; -    }; -    struct tx_fe_perif -    { -        std::string name; -        std::string db_fe_name; -        tx_frontend_core_200::sptr core; -    }; - -    std::map<size_t, rx_fe_perif> _rx_fe_map; -    std::map<size_t, tx_fe_perif> _tx_fe_map; - -    bool _ignore_cal_file; - -    std::unordered_map<size_t, uhd::gain_group::sptr> _tx_gain_groups; -    std::unordered_map<size_t, uhd::gain_group::sptr> _rx_gain_groups; -}; /* class radio_ctrl_impl */ - -}} /* namespace uhd::rfnoc */ - -#endif /* INCLUDED_LIBUHD_RFNOC_X300_RADIO_CTRL_IMPL_HPP */ diff --git a/host/tests/CMakeLists.txt b/host/tests/CMakeLists.txt index d790b214e..8a477b181 100644 --- a/host/tests/CMakeLists.txt +++ b/host/tests/CMakeLists.txt @@ -42,7 +42,6 @@ set(test_sources      property_test.cpp      ranges_test.cpp      scope_exit_test.cpp -    sid_t_test.cpp      sensors_test.cpp      soft_reg_test.cpp      sph_recv_test.cpp @@ -53,29 +52,16 @@ set(test_sources      vrt_test.cpp      expert_test.cpp      fe_conn_test.cpp -    rfnoc_node_test.cpp      link_test.cpp      rx_streamer_test.cpp      tx_streamer_test.cpp +    block_id_test.cpp +    rfnoc_property_test.cpp  )  #turn each test cpp file into an executable with an int main() function  add_definitions(-DBOOST_TEST_DYN_LINK -DBOOST_TEST_MAIN) -if(ENABLE_RFNOC) -    list(APPEND test_sources -        block_id_test.cpp -        blockdef_test.cpp -        device3_test.cpp -        graph_search_test.cpp -        node_connect_test.cpp -        rate_node_test.cpp -        stream_sig_test.cpp -        tick_node_test.cpp -        rfnoc_property_test.cpp -    ) -endif(ENABLE_RFNOC) -  if(ENABLE_C_API)      list(APPEND test_sources          eeprom_c_test.c @@ -149,15 +135,6 @@ if(ENABLE_DPDK)  ENDIF(ENABLE_DPDK)  UHD_ADD_NONAPI_TEST( -    TARGET "nocscript_expr_test.cpp" -    EXTRA_SOURCES -    "${CMAKE_SOURCE_DIR}/lib/rfnoc/nocscript/expression.cpp" -    INCLUDE_DIRS -    ${CMAKE_BINARY_DIR}/lib/rfnoc/nocscript/ -    ${CMAKE_SOURCE_DIR}/lib/rfnoc/nocscript/ -) - -UHD_ADD_NONAPI_TEST(      TARGET "system_time_test.cpp"      EXTRA_SOURCES      "${CMAKE_SOURCE_DIR}/lib/utils/system_time.cpp" @@ -175,36 +152,6 @@ UHD_ADD_NONAPI_TEST(      NOAUTORUN # Don't register for auto-run  ) -#UHD_ADD_NONAPI_TEST( -    #TARGET "nocscript_expr_test.cpp" -    #EXTRA_SOURCES -    #"${CMAKE_SOURCE_DIR}/lib/rfnoc/nocscript/expression.cpp" -    #INCLUDE_DIRS -    #${CMAKE_BINARY_DIR}/lib/rfnoc/nocscript/ -    #${CMAKE_SOURCE_DIR}/lib/rfnoc/nocscript/ -#) - -#UHD_ADD_NONAPI_TEST( -    #TARGET "nocscript_ftable_test.cpp" -    #EXTRA_SOURCES -    #${CMAKE_SOURCE_DIR}/lib/rfnoc/nocscript/function_table.cpp -    #${CMAKE_SOURCE_DIR}/lib/rfnoc/nocscript/expression.cpp -    #INCLUDE_DIRS -    #${CMAKE_BINARY_DIR}/lib/rfnoc/nocscript/ -    #${CMAKE_SOURCE_DIR}/lib/rfnoc/nocscript/ -#) - -UHD_ADD_NONAPI_TEST( -    TARGET "nocscript_parser_test.cpp" -    EXTRA_SOURCES -    ${CMAKE_SOURCE_DIR}/lib/rfnoc/nocscript/parser.cpp -    ${CMAKE_SOURCE_DIR}/lib/rfnoc/nocscript/function_table.cpp -    ${CMAKE_SOURCE_DIR}/lib/rfnoc/nocscript/expression.cpp -    INCLUDE_DIRS -    ${CMAKE_BINARY_DIR}/lib/rfnoc/nocscript/ -    ${CMAKE_SOURCE_DIR}/lib/rfnoc/nocscript/ -) -  UHD_ADD_NONAPI_TEST(      TARGET "packet_handler_benchmark.cpp"      NOAUTORUN diff --git a/host/tests/common/CMakeLists.txt b/host/tests/common/CMakeLists.txt index 58299c688..7f31f3463 100644 --- a/host/tests/common/CMakeLists.txt +++ b/host/tests/common/CMakeLists.txt @@ -8,8 +8,6 @@  # Build uhd_test static lib  ########################################################################  include_directories("${CMAKE_SOURCE_DIR}/lib/include") -add_library(uhd_test ${CMAKE_CURRENT_SOURCE_DIR}/mock_ctrl_iface_impl.cpp -                     ${CMAKE_CURRENT_SOURCE_DIR}/mock_zero_copy.cpp -                     ${CMAKE_SOURCE_DIR}/lib/rfnoc/graph_impl.cpp -                     ${CMAKE_SOURCE_DIR}/lib/rfnoc/async_msg_handler.cpp +add_library(uhd_test +    ${CMAKE_CURRENT_SOURCE_DIR}/mock_zero_copy.cpp  ) diff --git a/host/tests/common/mock_ctrl_iface_impl.cpp b/host/tests/common/mock_ctrl_iface_impl.cpp deleted file mode 100644 index af32637df..000000000 --- a/host/tests/common/mock_ctrl_iface_impl.cpp +++ /dev/null @@ -1,38 +0,0 @@ -// -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#include "mock_ctrl_iface_impl.hpp" -static const uint64_t TEST_NOC_ID = 0xAAAABBBBCCCCDDDD; - -uint64_t mock_ctrl_iface_impl::send_cmd_pkt(const size_t addr, -    const size_t data, -    const bool readback, -    const uint64_t /* timestamp */ -) -{ -    if (not readback) { -        std::cout << str(boost::format("[MOCK] poke to addr: %016X, data == %016X") % addr -                         % data) -                  << std::endl; -    } else { -        std::cout << str(boost::format("[MOCK] peek64 to addr: %016X") % data) -                  << std::endl; -        switch (data) { -            case uhd::rfnoc::SR_READBACK_REG_ID: -                return TEST_NOC_ID; -            case uhd::rfnoc::SR_READBACK_REG_FIFOSIZE: -                return 0x0000000000010000; -            case uhd::rfnoc::SR_READBACK_REG_USER: -                return 0x0123456789ABCDEF; -            case uhd::rfnoc::SR_READBACK_COMPAT: -                return uint64_t(uhd::rfnoc::NOC_SHELL_COMPAT_MAJOR) << 32 -                       | uint64_t(uhd::rfnoc::NOC_SHELL_COMPAT_MINOR); -            default: -                return 0; -        } -    } -    return 0; -} diff --git a/host/tests/common/mock_ctrl_iface_impl.hpp b/host/tests/common/mock_ctrl_iface_impl.hpp deleted file mode 100644 index f20858b63..000000000 --- a/host/tests/common/mock_ctrl_iface_impl.hpp +++ /dev/null @@ -1,29 +0,0 @@ -// -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - - -#ifndef INCLUDED_MOCK_CTRL_IFACE_IMPL_HPP -#define INCLUDED_MOCK_CTRL_IFACE_IMPL_HPP - -#include <uhd/rfnoc/constants.hpp> -#include <uhdlib/rfnoc/ctrl_iface.hpp> -#include <boost/bind.hpp> -#include <boost/format.hpp> -#include <boost/make_shared.hpp> -#include <boost/thread/mutex.hpp> -#include <boost/thread/thread.hpp> -#include <queue> - -class mock_ctrl_iface_impl : public uhd::rfnoc::ctrl_iface -{ -    uint64_t send_cmd_pkt(const size_t addr, -        const size_t data, -        const bool readback      = false, -        const uint64_t timestamp = 0); - -    void set_cmd_fifo_size(const size_t) {} -}; -#endif /* INCLUDED_MOCK_CTRL_IFACE_IMPL_HPP */ diff --git a/host/tests/common/mock_zero_copy.hpp b/host/tests/common/mock_zero_copy.hpp index 60e5f4659..515fde498 100644 --- a/host/tests/common/mock_zero_copy.hpp +++ b/host/tests/common/mock_zero_copy.hpp @@ -12,9 +12,7 @@  #include <uhd/transport/vrt_if_packet.hpp>  #include <uhd/transport/zero_copy.hpp>  #include <uhd/types/endianness.hpp> -#include <uhd/types/sid.hpp>  #include <uhd/utils/byteswap.hpp> -#include <uhdlib/rfnoc/xports.hpp>  #include <boost/make_shared.hpp>  #include <boost/shared_array.hpp>  #include <boost/shared_ptr.hpp> diff --git a/host/tests/device3_test.cpp b/host/tests/device3_test.cpp deleted file mode 100644 index b737e7012..000000000 --- a/host/tests/device3_test.cpp +++ /dev/null @@ -1,201 +0,0 @@ -// -// Copyright 2014 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - - -#include "mock_ctrl_iface_impl.hpp" -#include "mock_zero_copy.hpp" -#include <uhd/device3.hpp> -#include <uhd/property_tree.hpp> -#include <uhd/rfnoc/block_ctrl.hpp> -#include <uhd/rfnoc/graph.hpp> -#include <uhdlib/rfnoc/graph_impl.hpp> -#include <boost/enable_shared_from_this.hpp> -#include <boost/shared_ptr.hpp> -#include <boost/test/unit_test.hpp> -#include <exception> -#include <iostream> - - -using namespace uhd; -using namespace uhd::rfnoc; -using namespace uhd::transport::vrt; -using uhd::transport::managed_recv_buffer; -using uhd::transport::managed_send_buffer; - -static const sid_t TEST_SID0 = 0x00000200; // 0.0.2.0 -static const sid_t TEST_SID1 = 0x00000210; // 0.0.2.F - -uhd::both_xports_t make_mock_transport(const uhd::sid_t& tx_sid) -{ -    uhd::both_xports_t xports; -    xports.send_sid = tx_sid; -    xports.recv_sid = tx_sid.reversed(); -    xports.send = boost::make_shared<mock_zero_copy>(if_packet_info_t::LINK_TYPE_CHDR); -    xports.recv = xports.send; -    xports.send_buff_size = xports.send->get_send_frame_size(); -    xports.recv_buff_size = xports.recv->get_recv_frame_size(); -    return xports; -} - -// Mock-device -class mock_device3_impl : public uhd::device3, -                          public boost::enable_shared_from_this<mock_device3_impl> -{ -public: -    mock_device3_impl() -    { -        _tree = uhd::property_tree::make(); -        _tree->create<std::string>("/name").set("Test Mock-Device3"); -        // We can re-use this: -        std::map<size_t, ctrl_iface::sptr> ctrl_ifaces{ -            {0, ctrl_iface::sptr(new mock_ctrl_iface_impl())}}; - -        // Add two block controls: -        uhd::rfnoc::make_args_t make_args; -        make_args.ctrl_ifaces  = ctrl_ifaces; -        make_args.base_address = TEST_SID0.get_dst(); -        make_args.device_index = 0; -        make_args.tree         = _tree; -        std::cout << "[MOCK] Generating block controls 1/2:" << std::endl; -        _rfnoc_block_ctrl.push_back(block_ctrl_base::make(make_args)); -        std::cout << "[MOCK] Generating block controls 2/2:" << std::endl; -        make_args.base_address = TEST_SID1.get_dst(); -        _rfnoc_block_ctrl.push_back(block_ctrl::make(make_args)); -    } - -    rx_streamer::sptr get_rx_stream(const stream_args_t& args) -    { -        throw uhd::not_implemented_error(args.args.to_string()); -    } - -    tx_streamer::sptr get_tx_stream(const stream_args_t& args) -    { -        throw uhd::not_implemented_error(args.args.to_string()); -    } - -    bool recv_async_msg(async_metadata_t& async_metadata, double timeout) -    { -        throw uhd::not_implemented_error( -            str(boost::format("%d %f") % async_metadata.channel % timeout)); -    } - -    rfnoc::graph::sptr create_graph(const std::string& name) -    { -        sid_t async_sid(0); -        async_sid.set_dst_addr(2); -        auto async_xports = make_mock_transport(async_sid); - -        auto async_msg_handler = uhd::rfnoc::async_msg_handler::make(async_xports.recv, -            async_xports.send, -            async_xports.send_sid, -            async_xports.endianness); -        auto graph             = boost::make_shared<uhd::rfnoc::graph_impl>( -            name, shared_from_this(), async_msg_handler); -        return graph; -    } -}; - -device3::sptr make_mock_device() -{ -    return device3::sptr(new mock_device3_impl()); -} - -class mock_block_ctrl : public block_ctrl -{ -    int foo; -}; - -BOOST_AUTO_TEST_CASE(test_device3) -{ -    device3::sptr my_device = make_mock_device(); - -    std::cout << "Checking block 0..." << std::endl; -    BOOST_REQUIRE(my_device->find_blocks("Block").size()); - -    std::cout << "Getting block 0..." << std::endl; -    block_ctrl_base::sptr block0 = -        my_device->get_block_ctrl(my_device->find_blocks("Block")[0]); -    BOOST_REQUIRE(block0); -    BOOST_CHECK_EQUAL(block0->get_block_id(), "0/Block#0"); - -    std::cout << "Checking block 1..." << std::endl; -    BOOST_REQUIRE(my_device->has_block(block_id_t("0/Block#1"))); - -    std::cout << "Getting block 1..." << std::endl; -    block_ctrl_base::sptr block1 = my_device->get_block_ctrl(block_id_t("0/Block#1")); -    BOOST_REQUIRE(block1); -    BOOST_CHECK_EQUAL(block1->get_block_id(), "0/Block#1"); -} - - -BOOST_AUTO_TEST_CASE(test_device3_graph) -{ -    auto my_device = make_mock_device(); -    std::cout << "Start device3 test graph.." << std::endl; -    std::cout << "Checking block 0..." << std::endl; -    BOOST_REQUIRE(my_device->find_blocks("Block").size()); -    std::cout << "Getting block 0..." << std::endl; -    auto block0 = my_device->get_block_ctrl(my_device->find_blocks("Block")[0]); -    BOOST_REQUIRE(block0); -    BOOST_CHECK_EQUAL(block0->get_block_id(), "0/Block#0"); - -    std::cout << "Checking block 1..." << std::endl; -    BOOST_REQUIRE(my_device->has_block(block_id_t("0/Block#1"))); - -    std::cout << "Getting block 1..." << std::endl; -    auto block1 = my_device->get_block_ctrl(block_id_t("0/Block#1")); -    BOOST_REQUIRE(block1); -    BOOST_CHECK_EQUAL(block1->get_block_id(), "0/Block#1"); -    std::cout << "Creating graph..." << std::endl; -    auto graph = my_device->create_graph("test_graph"); -    BOOST_CHECK(graph); -    std::cout << "Connecting block_0 to block_1 ..." << std::endl; -    graph->connect(block_id_t("0/Block#0"), 0, block_id_t("0/Block#1"), 0); - -    BOOST_CHECK_EQUAL(block0->list_upstream_nodes().size(), 0); -    BOOST_CHECK_EQUAL(block0->list_downstream_nodes().size(), 1); -    BOOST_CHECK_EQUAL( -        block0->list_downstream_nodes()[0].lock()->unique_id(), "0/Block#1"); -    BOOST_CHECK_EQUAL(block1->list_upstream_nodes().size(), 1); -    BOOST_CHECK_EQUAL(block1->list_downstream_nodes().size(), 0); -    BOOST_CHECK_EQUAL(block1->list_upstream_nodes()[0].lock()->unique_id(), "0/Block#0"); -} - -BOOST_AUTO_TEST_CASE(test_device3_cast) -{ -    device3::sptr my_device = make_mock_device(); - -    std::cout << "Getting block 0..." << std::endl; -    block_ctrl::sptr block0 = -        my_device->get_block_ctrl<block_ctrl>(block_id_t("0/Block#0")); -    BOOST_REQUIRE(block0); -    BOOST_CHECK_EQUAL(block0->get_block_id(), "0/Block#0"); - -    std::cout << "Getting block 1..." << std::endl; -    block_ctrl_base::sptr block1 = -        my_device->get_block_ctrl<block_ctrl>(block_id_t("0/Block#1")); -    BOOST_CHECK_EQUAL(block1->get_block_id(), "0/Block#1"); -} - -BOOST_AUTO_TEST_CASE(test_device3_fail) -{ -    device3::sptr my_device = make_mock_device(); - -    BOOST_CHECK(not my_device->has_block(block_id_t("0/FooBarBlock#0"))); -    BOOST_CHECK(not my_device->has_block<mock_block_ctrl>(block_id_t("0/Block#1"))); - -    BOOST_CHECK(my_device->find_blocks("FooBarBlock").size() == 0); -    BOOST_CHECK(my_device->find_blocks<block_ctrl>("FooBarBlock").size() == 0); - -    BOOST_REQUIRE_THROW( -        my_device->get_block_ctrl(block_id_t("0/FooBarBlock#17")), uhd::lookup_error); -    BOOST_REQUIRE_THROW( -        my_device->get_block_ctrl<mock_block_ctrl>(block_id_t("0/Block#1")), -        uhd::lookup_error); -} - -// vim: sw=4 et: diff --git a/host/tests/graph.hpp b/host/tests/graph.hpp deleted file mode 100644 index fb36ae510..000000000 --- a/host/tests/graph.hpp +++ /dev/null @@ -1,47 +0,0 @@ -// -// Copyright 2014 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#ifndef INCLUDED_TEST_GRAPH_HPP -#define INCLUDED_TEST_GRAPH_HPP - -#include <uhd/rfnoc/node_ctrl_base.hpp> -#include <uhd/rfnoc/sink_node_ctrl.hpp> -#include <uhd/rfnoc/source_node_ctrl.hpp> - -#define MAKE_NODE(name) test_node::sptr name(new test_node(#name)); - -// Smallest possible test class -class test_node : virtual public uhd::rfnoc::sink_node_ctrl, -                  virtual public uhd::rfnoc::source_node_ctrl -{ -public: -    typedef boost::shared_ptr<test_node> sptr; - -    test_node(const std::string& test_id) : _test_id(test_id){}; - -    void issue_stream_cmd(const uhd::stream_cmd_t&, const size_t){/* nop */}; - -    std::string get_test_id() const -    { -        return _test_id; -    }; - -private: -    const std::string _test_id; - -}; /* class test_node */ - -void connect_nodes( -    uhd::rfnoc::source_node_ctrl::sptr A, uhd::rfnoc::sink_node_ctrl::sptr B) -{ -    const size_t actual_src_port = A->connect_downstream(B); -    const size_t actual_dst_port = B->connect_upstream(A); -    A->set_downstream_port(actual_src_port, actual_dst_port); -    B->set_upstream_port(actual_dst_port, actual_src_port); -} - -#endif /* INCLUDED_TEST_GRAPH_HPP */ diff --git a/host/tests/graph_search_test.cpp b/host/tests/graph_search_test.cpp deleted file mode 100644 index 932647d98..000000000 --- a/host/tests/graph_search_test.cpp +++ /dev/null @@ -1,161 +0,0 @@ -// -// Copyright 2014-2016 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#include "graph.hpp" -#include <boost/test/unit_test.hpp> -#include <iostream> - -using namespace uhd::rfnoc; - -// test class derived, this is what we search for -class result_node : public test_node -{ -public: -    typedef boost::shared_ptr<result_node> sptr; - -    result_node(const std::string& test_id) : test_node(test_id){}; - -}; /* class result_node */ - -#define MAKE_RESULT_NODE(name) result_node::sptr name(new result_node(#name)); - -BOOST_AUTO_TEST_CASE(test_simplest_downstream_search) -{ -    MAKE_NODE(node_A); -    MAKE_NODE(node_B); - -    // Simplest possible scenario: Connect B downstream of A and let -    // A find B -    connect_nodes(node_A, node_B); - -    test_node::sptr result = node_A->find_downstream_node<test_node>()[0]; -    BOOST_REQUIRE(result); -    BOOST_CHECK_EQUAL(result->get_test_id(), "node_B"); -} - -BOOST_AUTO_TEST_CASE(test_simple_downstream_search) -{ -    MAKE_NODE(node_A); -    MAKE_NODE(node_B0); -    MAKE_NODE(node_B1); - -    // Simple scenario: Connect both B{1,2} downstream of A and let -    // it find them -    connect_nodes(node_A, node_B0); -    connect_nodes(node_A, node_B1); - -    // We're still searching for test_node, so any downstream block will match -    std::vector<test_node::sptr> result = node_A->find_downstream_node<test_node>(); -    BOOST_REQUIRE(result.size() == 2); -    BOOST_CHECK( -        (result[0]->get_test_id() == "node_B0" and result[1]->get_test_id() == "node_B1") -        or (result[1]->get_test_id() == "node_B0" -               and result[0]->get_test_id() == "node_B1")); -    BOOST_CHECK(result[0] == node_B0 or result[0] == node_B1); -} - -BOOST_AUTO_TEST_CASE(test_linear_downstream_search) -{ -    MAKE_NODE(node_A); -    MAKE_RESULT_NODE(node_B); -    MAKE_RESULT_NODE(node_C); - -    // Slightly more complex graph: -    connect_nodes(node_A, node_B); -    connect_nodes(node_B, node_C); - -    // This time, we search for result_node -    std::vector<result_node::sptr> result = node_A->find_downstream_node<result_node>(); -    std::cout << "size: " << result.size() << std::endl; -    BOOST_CHECK_EQUAL(result.size(), 1); -    BOOST_CHECK_EQUAL(result[0]->get_test_id(), "node_B"); -    for (const result_node::sptr& node : result) { -        std::cout << node->get_test_id() << std::endl; -    } -} - -BOOST_AUTO_TEST_CASE(test_multi_iter_downstream_search) -{ -    MAKE_NODE(node_A); -    MAKE_NODE(node_B0); -    MAKE_NODE(node_B1); -    MAKE_NODE(node_C0); -    MAKE_RESULT_NODE(node_C1); -    MAKE_RESULT_NODE(node_C2); -    MAKE_RESULT_NODE(node_C3); -    MAKE_RESULT_NODE(node_D0); - -    // Slightly more complex graph: -    connect_nodes(node_A, node_B0); -    connect_nodes(node_A, node_B1); -    connect_nodes(node_B0, node_C0); -    connect_nodes(node_B0, node_C1); -    connect_nodes(node_B1, node_C2); -    connect_nodes(node_B1, node_C3); -    connect_nodes(node_C0, node_D0); - -    // This time, we search for result_node -    std::vector<result_node::sptr> result = node_A->find_downstream_node<result_node>(); -    BOOST_REQUIRE(result.size() == 4); -    for (const result_node::sptr& node : result) { -        std::cout << node->get_test_id() << std::endl; -    } -} - -BOOST_AUTO_TEST_CASE(test_multi_iter_cycle_downstream_search) -{ -    MAKE_NODE(node_A); -    MAKE_NODE(node_B0); -    MAKE_NODE(node_B1); -    MAKE_NODE(node_C0); -    MAKE_RESULT_NODE(node_C1); -    MAKE_RESULT_NODE(node_C2); -    MAKE_RESULT_NODE(node_C3); -    MAKE_RESULT_NODE(node_D0); - -    // Slightly more complex graph: -    connect_nodes(node_A, node_B0); -    // This connection goes both ways, causing a cycle -    connect_nodes(node_A, node_B1); -    connect_nodes(node_B1, node_A); -    connect_nodes(node_B0, node_C0); -    connect_nodes(node_B0, node_C1); -    connect_nodes(node_B1, node_C2); -    connect_nodes(node_B1, node_C3); -    connect_nodes(node_C0, node_D0); - -    // This time, we search for result_node -    std::vector<result_node::sptr> result = node_A->find_downstream_node<result_node>(); -    BOOST_REQUIRE(result.size() == 4); -    for (const result_node::sptr& node : result) { -        std::cout << node->get_test_id() << std::endl; -    } -} - -BOOST_AUTO_TEST_CASE(test_mini_cycle_downstream_and_upstream) -{ -    MAKE_NODE(node_A); -    MAKE_NODE(node_B); - -    // Connect them in a loop -    connect_nodes(node_A, node_B); -    connect_nodes(node_B, node_A); - -    std::vector<test_node::sptr> result; -    result = node_A->find_downstream_node<test_node>(); -    BOOST_REQUIRE_EQUAL(result.size(), 1); -    BOOST_REQUIRE(result[0] == node_B); -    result = node_B->find_downstream_node<test_node>(); -    BOOST_REQUIRE_EQUAL(result.size(), 1); -    BOOST_REQUIRE(result[0] == node_A); -    result = node_A->find_upstream_node<test_node>(); -    BOOST_REQUIRE_EQUAL(result.size(), 1); -    BOOST_REQUIRE(result[0] == node_B); -    result = node_B->find_upstream_node<test_node>(); -    BOOST_REQUIRE_EQUAL(result.size(), 1); -    BOOST_REQUIRE(result[0] == node_A); -} diff --git a/host/tests/nocscript_common.hpp b/host/tests/nocscript_common.hpp deleted file mode 100644 index ad254fa0e..000000000 --- a/host/tests/nocscript_common.hpp +++ /dev/null @@ -1,30 +0,0 @@ -// -// Copyright 2015 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#include "../lib/rfnoc/nocscript/expression.hpp" -#include <boost/assign/list_of.hpp> - -using namespace uhd::rfnoc::nocscript; - -// Some global defs to make tests easier to write -expression_function::argtype_list_type one_int_arg = -    boost::assign::list_of(expression::TYPE_INT); -expression_function::argtype_list_type two_int_args = -    boost::assign::list_of(expression::TYPE_INT)(expression::TYPE_INT); -expression_function::argtype_list_type one_double_arg = -    boost::assign::list_of(expression::TYPE_DOUBLE); -expression_function::argtype_list_type two_double_args = -    boost::assign::list_of(expression::TYPE_DOUBLE)(expression::TYPE_DOUBLE); -expression_function::argtype_list_type one_bool_arg = -    boost::assign::list_of(expression::TYPE_BOOL); -expression_function::argtype_list_type two_bool_args = -    boost::assign::list_of(expression::TYPE_BOOL)(expression::TYPE_BOOL); -expression_function::argtype_list_type no_args; - -expression_container::expr_list_type empty_arg_list; - -#define E(x) expression_literal::make(x) diff --git a/host/tests/nocscript_expr_test.cpp b/host/tests/nocscript_expr_test.cpp deleted file mode 100644 index ed5f6598d..000000000 --- a/host/tests/nocscript_expr_test.cpp +++ /dev/null @@ -1,405 +0,0 @@ -// -// Copyright 2015 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#include "../lib/rfnoc/nocscript/function_table.hpp" -#include "nocscript_common.hpp" -#include <boost/bind.hpp> -#include <boost/format.hpp> -#include <boost/make_shared.hpp> -#include <boost/test/floating_point_comparison.hpp> -#include <boost/test/unit_test.hpp> -#include <algorithm> -#include <iostream> - -// We need this global variable for one of the later tests -int and_counter = 0; - -BOOST_AUTO_TEST_CASE(test_literals) -{ -    expression_literal literal_int("5", expression::TYPE_INT); -    BOOST_CHECK_EQUAL(literal_int.infer_type(), expression::TYPE_INT); -    BOOST_CHECK_EQUAL(literal_int.get_int(), 5); -    BOOST_CHECK_EQUAL(literal_int.to_bool(), true); -    BOOST_REQUIRE_THROW(literal_int.get_string(), uhd::type_error); -    BOOST_REQUIRE_THROW(literal_int.get_bool(), uhd::type_error); - -    expression_literal literal_int0("0", expression::TYPE_INT); -    BOOST_CHECK_EQUAL(literal_int0.infer_type(), expression::TYPE_INT); -    BOOST_CHECK_EQUAL(literal_int0.to_bool(), false); - -    expression_literal literal_double("2.3", expression::TYPE_DOUBLE); -    BOOST_CHECK_EQUAL(literal_double.infer_type(), expression::TYPE_DOUBLE); -    BOOST_CHECK_CLOSE(literal_double.get_double(), 2.3, 0.01); -    BOOST_CHECK_EQUAL(literal_double.to_bool(), true); -    BOOST_REQUIRE_THROW(literal_double.get_string(), uhd::type_error); -    BOOST_REQUIRE_THROW(literal_double.get_bool(), uhd::type_error); - -    expression_literal literal_bool(true); -    BOOST_CHECK_EQUAL(literal_bool.infer_type(), expression::TYPE_BOOL); -    BOOST_CHECK_EQUAL(literal_bool.get_bool(), true); -    BOOST_CHECK_EQUAL(literal_bool.to_bool(), true); -    BOOST_CHECK_EQUAL(literal_bool.eval().get_bool(), true); -    BOOST_REQUIRE_THROW(literal_bool.get_string(), uhd::type_error); -    BOOST_REQUIRE_THROW(literal_bool.get_int(), uhd::type_error); - -    expression_literal literal_bool_false(false); -    BOOST_CHECK_EQUAL(literal_bool_false.infer_type(), expression::TYPE_BOOL); -    BOOST_CHECK_EQUAL(literal_bool_false.get_bool(), false); -    BOOST_CHECK_EQUAL(literal_bool_false.to_bool(), false); -    BOOST_REQUIRE_EQUAL(literal_bool_false.eval().get_bool(), false); -    BOOST_REQUIRE_THROW(literal_bool_false.get_string(), uhd::type_error); -    BOOST_REQUIRE_THROW(literal_bool_false.get_int(), uhd::type_error); - -    expression_literal literal_string("'foo bar'", expression::TYPE_STRING); -    BOOST_CHECK_EQUAL(literal_string.infer_type(), expression::TYPE_STRING); -    BOOST_CHECK_EQUAL(literal_string.get_string(), "foo bar"); -    BOOST_REQUIRE_THROW(literal_string.get_bool(), uhd::type_error); -    BOOST_REQUIRE_THROW(literal_string.get_int(), uhd::type_error); - -    expression_literal literal_int_vec("[1, 2, 3]", expression::TYPE_INT_VECTOR); -    BOOST_CHECK_EQUAL(literal_int_vec.infer_type(), expression::TYPE_INT_VECTOR); -    std::vector<int> test_data{1, 2, 3}; -    std::vector<int> result = literal_int_vec.get_int_vector(); -    BOOST_CHECK_EQUAL_COLLECTIONS( -        test_data.begin(), test_data.end(), result.begin(), result.end()); -    BOOST_REQUIRE_THROW(literal_int_vec.get_bool(), uhd::type_error); -    BOOST_REQUIRE_THROW(literal_int_vec.get_int(), uhd::type_error); -} - - -// Need those for the variable testing: -expression::type_t variable_get_type(const std::string& var_name) -{ -    if (var_name == "spp") { -        std::cout << "Returning type for $spp..." << std::endl; -        return expression::TYPE_INT; -    } -    if (var_name == "is_true") { -        std::cout << "Returning type for $is_true..." << std::endl; -        return expression::TYPE_BOOL; -    } - -    throw uhd::syntax_error("Cannot infer type (unknown variable)"); -} - -expression_literal variable_get_value(const std::string& var_name) -{ -    if (var_name == "spp") { -        std::cout << "Returning value for $spp..." << std::endl; -        return expression_literal(5); -    } -    if (var_name == "is_true") { -        std::cout << "Returning value for $is_true..." << std::endl; -        return expression_literal(true); -    } - -    throw uhd::syntax_error("Cannot read value (unknown variable)"); -} - -BOOST_AUTO_TEST_CASE(test_variables) -{ -    BOOST_REQUIRE_THROW(expression_variable v_fail("foo", // Invalid token -                            boost::bind(&variable_get_type, _1), -                            boost::bind(&variable_get_value, _1)), -        uhd::assertion_error); - -    expression_variable v("$spp", // The token -        boost::bind(&variable_get_type, _1), // type-getter -        boost::bind(&variable_get_value, _1) // value-getter -    ); -    BOOST_CHECK_EQUAL(v.infer_type(), expression::TYPE_INT); -    BOOST_CHECK_EQUAL(v.eval().get_int(), 5); -} - -BOOST_AUTO_TEST_CASE(test_container) -{ -    // Create some sub-expressions: -    expression_literal::sptr l_true  = E(true); -    expression_literal::sptr l_false = E(false); -    expression_literal::sptr l_int   = E(5); -    BOOST_REQUIRE_EQUAL(l_false->get_bool(), false); -    BOOST_REQUIRE_EQUAL(l_false->to_bool(), false); -    expression_variable::sptr l_boolvar = -        boost::make_shared<expression_variable>("$is_true", -            boost::bind(&variable_get_type, _1), -            boost::bind(&variable_get_value, _1)); - -    // This will throw anytime it's evaluated: -    expression_variable::sptr l_failvar = -        boost::make_shared<expression_variable>("$does_not_exist", -            boost::bind(&variable_get_type, _1), -            boost::bind(&variable_get_value, _1)); - -    expression_container c; -    std::cout << "One true, OR: " << std::endl; -    c.add(l_true); -    c.set_combiner_safe(expression_container::COMBINE_OR); -    expression_literal ret_val_1 = c.eval(); -    BOOST_CHECK_EQUAL(ret_val_1.infer_type(), expression::TYPE_BOOL); -    BOOST_CHECK_EQUAL(ret_val_1.eval().get_bool(), true); - -    std::cout << std::endl << std::endl << "Two true, one false, OR: " << std::endl; -    c.add(l_true); -    c.add(l_false); -    expression_literal ret_val_2 = c.eval(); -    BOOST_CHECK_EQUAL(ret_val_2.infer_type(), expression::TYPE_BOOL); -    BOOST_CHECK_EQUAL(ret_val_2.eval().get_bool(), true); - -    expression_container c2; -    c2.add(l_false); -    c2.add(l_false); -    c2.set_combiner(expression_container::COMBINE_AND); -    std::cout << std::endl << std::endl << "Two false, AND: " << std::endl; -    expression_literal ret_val_3 = c2.eval(); -    BOOST_CHECK_EQUAL(ret_val_3.infer_type(), expression::TYPE_BOOL); -    BOOST_REQUIRE_EQUAL(ret_val_3.eval().get_bool(), false); - -    c2.add(l_failvar); -    // Will not fail, because l_failvar never gets eval'd: -    expression_literal ret_val_4 = c2.eval(); -    BOOST_CHECK_EQUAL(ret_val_4.infer_type(), expression::TYPE_BOOL); -    BOOST_CHECK_EQUAL(ret_val_4.eval().get_bool(), false); - -    // Same here: -    c.add(l_failvar); -    expression_literal ret_val_5 = c.eval(); -    BOOST_CHECK_EQUAL(ret_val_5.infer_type(), expression::TYPE_BOOL); -    BOOST_CHECK_EQUAL(ret_val_5.eval().get_bool(), true); - -    // Now it'll throw: -    c.set_combiner(expression_container::COMBINE_ALL); -    BOOST_REQUIRE_THROW(c.eval(), uhd::syntax_error); - -    std::cout << "Checking type inference on ',' sequences: " << std::endl; -    // Check types match -    BOOST_CHECK_EQUAL(c2.infer_type(), expression::TYPE_BOOL); -    expression_container c3; -    c3.set_combiner(expression_container::COMBINE_ALL); -    c3.add(l_false); -    c3.add(l_int); -    BOOST_CHECK_EQUAL(c3.infer_type(), expression::TYPE_INT); -} - - -// We'll define two functions here: ADD and XOR. The former shall -// be defined for INT and DOUBLE -class functable_mockup_impl : public function_table -{ -public: -    functable_mockup_impl(void){}; - -    bool function_exists(const std::string& name) const -    { -        return name == "ADD" or name == "XOR" or name == "AND"; -    } - -    bool function_exists(const std::string& name, -        const expression_function::argtype_list_type& arg_types) const -    { -        if (name == "ADD") { -            if (arg_types.size() == 2 and arg_types[0] == expression::TYPE_DOUBLE -                and arg_types[1] == expression::TYPE_DOUBLE) { -                return true; -            } -            if (arg_types.size() == 2 and arg_types[0] == expression::TYPE_INT -                and arg_types[1] == expression::TYPE_INT) { -                return true; -            } -            return false; -        } - -        if (name == "XOR" or name == "AND") { -            if (arg_types.size() == 2 and arg_types[0] == expression::TYPE_BOOL -                and arg_types[1] == expression::TYPE_BOOL) { -                return true; -            } -            return false; -        } - -        return false; -    } - -    expression::type_t get_type(const std::string& name, -        const expression_function::argtype_list_type& arg_types) const -    { -        if (not function_exists(name, arg_types)) { -            throw uhd::syntax_error( -                str(boost::format( -                        "[EXPR_TEXT] get_type(): Unknown function: %s, %d arguments") -                    % name % arg_types.size())); -        } - -        if (name == "XOR" or name == "AND") { -            return expression::TYPE_BOOL; -        } -        if (name == "ADD") { -            return arg_types[0]; -        } -        UHD_THROW_INVALID_CODE_PATH(); -    } - -    expression_literal eval(const std::string& name, -        const expression_function::argtype_list_type& arg_types, -        expression_container::expr_list_type& args) -    { -        if (name == "XOR") { -            if (arg_types.size() != 2 or args.size() != 2 -                or arg_types[0] != expression::TYPE_BOOL -                or arg_types[1] != expression::TYPE_BOOL -                or args[0]->infer_type() != expression::TYPE_BOOL -                or args[1]->infer_type() != expression::TYPE_BOOL) { -                throw uhd::syntax_error("eval(): XOR type mismatch"); -            } -            return expression_literal( -                bool(args[0]->eval().get_bool() xor args[1]->eval().get_bool())); -        } - -        if (name == "AND") { -            if (arg_types.size() != 2 or args.size() != 2 -                or arg_types[0] != expression::TYPE_BOOL -                or arg_types[1] != expression::TYPE_BOOL -                or args[0]->infer_type() != expression::TYPE_BOOL -                or args[1]->infer_type() != expression::TYPE_BOOL) { -                throw uhd::syntax_error("eval(): AND type mismatch"); -            } -            std::cout << "Calling AND" << std::endl; -            and_counter++; -            return expression_literal( -                bool(args[0]->eval().get_bool() and args[1]->eval().get_bool())); -        } - -        if (name == "ADD") { -            if (args.size() != 2) { -                throw uhd::syntax_error("eval(): ADD type mismatch"); -            } -            if ((args[0]->infer_type() == expression::TYPE_INT) -                and (args[1]->infer_type() == expression::TYPE_INT)) { -                return expression_literal( -                    int(args[0]->eval().get_int() + args[1]->eval().get_int())); -            } else if ((args[0]->infer_type() == expression::TYPE_DOUBLE) -                       and (args[1]->infer_type() == expression::TYPE_DOUBLE)) { -                return expression_literal( -                    double(args[0]->eval().get_double() + args[1]->eval().get_double())); -            } -            throw uhd::syntax_error("eval(): ADD type mismatch"); -        } -        throw uhd::syntax_error("eval(): unknown function"); -    } - -    // We don't actually need this -    void register_function(const std::string&, -        const function_table::function_ptr&, -        const expression::type_t, -        const expression_function::argtype_list_type&){}; -}; - - -// The annoying part: Testing the test fixtures -BOOST_AUTO_TEST_CASE(test_functable_mockup) -{ -    functable_mockup_impl functable; - -    BOOST_CHECK(functable.function_exists("ADD")); -    BOOST_CHECK(functable.function_exists("XOR")); -    BOOST_CHECK(not functable.function_exists("FOOBAR")); - -    BOOST_CHECK(functable.function_exists("ADD", two_int_args)); -    BOOST_CHECK(functable.function_exists("ADD", two_double_args)); -    BOOST_CHECK(functable.function_exists("XOR", two_bool_args)); -    BOOST_CHECK(not functable.function_exists("ADD", two_bool_args)); -    BOOST_CHECK(not functable.function_exists("ADD", no_args)); -    BOOST_CHECK(not functable.function_exists("XOR", no_args)); - -    BOOST_CHECK_EQUAL(functable.get_type("ADD", two_int_args), expression::TYPE_INT); -    BOOST_CHECK_EQUAL( -        functable.get_type("ADD", two_double_args), expression::TYPE_DOUBLE); -    BOOST_CHECK_EQUAL(functable.get_type("XOR", two_bool_args), expression::TYPE_BOOL); - -    expression_container::expr_list_type add_args_int{E(2), E(3)}; -    expression_container::expr_list_type add_args_dbl{E(2.25), E(5.0)}; -    expression_container::expr_list_type xor_args_bool{E(true), E(false)}; - -    BOOST_CHECK_EQUAL( -        functable.eval("ADD", two_int_args, add_args_int), expression_literal(5)); -    BOOST_CHECK_EQUAL( -        functable.eval("ADD", two_double_args, add_args_dbl), expression_literal(7.25)); -    BOOST_CHECK_EQUAL( -        functable.eval("XOR", two_bool_args, xor_args_bool), expression_literal(true)); -} - -BOOST_AUTO_TEST_CASE(test_function_expression) -{ -    function_table::sptr ft = boost::make_shared<functable_mockup_impl>(); - -    // Very simple function: ADD(2, 3) -    expression_function func1("ADD", ft); -    func1.add(E(2)); -    func1.add(E(3)); - -    BOOST_CHECK_EQUAL(func1.eval(), expression_literal(5)); - -    // More elaborate: ADD(ADD(2, 3), ADD(ADD(4, 5), 6)) ?= 20 -    //                 f4  f1         f3  f2 -    expression_function f1("ADD", ft); -    f1.add(E(2)); -    f1.add(E(3)); -    expression_function f2("ADD", ft); -    f2.add(E(4)); -    f2.add(E(5)); -    expression_function f3("ADD", ft); -    f3.add(boost::make_shared<expression_function>(f2)); -    f3.add(E(6)); -    expression_function f4("ADD", ft); -    f4.add(boost::make_shared<expression_function>(f1)); -    f4.add(boost::make_shared<expression_function>(f3)); - -    BOOST_CHECK_EQUAL(f4.eval().get_int(), 20); -} - -BOOST_AUTO_TEST_CASE(test_function_expression_laziness) -{ -    function_table::sptr ft = boost::make_shared<functable_mockup_impl>(); - -    // We run AND(AND(false, false), AND(false, false)). -    //        f1  f2                 f3 -    // That makes three ANDs -    // in total. However, we will only see AND being evaluated twice, because -    // the outcome is clear after running the first AND in the argument list. -    expression_function::sptr f2 = boost::make_shared<expression_function>("AND", ft); -    f2->add(E(false)); -    f2->add(E(false)); -    BOOST_CHECK(not f2->eval().get_bool()); - -    expression_function::sptr f3 = boost::make_shared<expression_function>("AND", ft); -    f3->add(E(false)); -    f3->add(E(false)); -    BOOST_CHECK(not f3->eval().get_bool()); - -    and_counter                  = 0; -    expression_function::sptr f1 = boost::make_shared<expression_function>("AND", ft); -    f1->add(f2); -    f1->add(f3); - -    BOOST_CHECK(not f1->eval().get_bool()); -    BOOST_CHECK_EQUAL(and_counter, 2); -} - -BOOST_AUTO_TEST_CASE(test_sptrs) -{ -    expression_container::sptr c = expression_container::make(); -    BOOST_CHECK_EQUAL(c->infer_type(), expression::TYPE_BOOL); -    BOOST_CHECK(c->eval().get_bool()); - -    expression_variable::sptr v = expression_variable::make("$spp", -        boost::bind(&variable_get_type, _1), // type-getter -        boost::bind(&variable_get_value, _1) // value-getter -    ); - -    c->add(v); -    BOOST_REQUIRE_EQUAL(c->infer_type(), expression::TYPE_INT); -    BOOST_CHECK_EQUAL(c->eval().get_int(), 5); -} diff --git a/host/tests/nocscript_ftable_test.cpp b/host/tests/nocscript_ftable_test.cpp deleted file mode 100644 index 36aa314f2..000000000 --- a/host/tests/nocscript_ftable_test.cpp +++ /dev/null @@ -1,248 +0,0 @@ -// -// Copyright 2015 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#include "../lib/rfnoc/nocscript/function_table.hpp" -#include "nocscript_common.hpp" -#include <boost/bind.hpp> -#include <boost/make_shared.hpp> -#include <boost/test/floating_point_comparison.hpp> -#include <boost/test/unit_test.hpp> -#include <algorithm> -#include <iostream> - -BOOST_AUTO_TEST_CASE(test_basic_funcs) -{ -    function_table::sptr ft = function_table::make(); -    BOOST_CHECK(ft->function_exists("ADD")); -    BOOST_CHECK(ft->function_exists("ADD", two_int_args)); -    BOOST_CHECK(ft->function_exists("LE", two_int_args)); -    BOOST_CHECK(ft->function_exists("GE")); -    BOOST_CHECK(ft->function_exists("GE", two_int_args)); -    BOOST_CHECK(ft->function_exists("TRUE")); -    BOOST_CHECK(ft->function_exists("FALSE")); - -    // Math -    expression_container::expr_list_type two_int_values{E(2), E(3)}; -    expression_container::expr_list_type two_int_values2{E(3), E(2)}; -    expression_container::expr_list_type two_double_values{E(2.0), E(3.0)}; - -    BOOST_REQUIRE_EQUAL(ft->get_type("ADD", two_int_args), expression::TYPE_INT); -    expression_literal e_add = ft->eval("ADD", two_int_args, two_int_values); -    BOOST_REQUIRE_EQUAL(e_add.infer_type(), expression::TYPE_INT); -    BOOST_CHECK_EQUAL(e_add.get_int(), 5); - -    BOOST_REQUIRE_EQUAL(ft->get_type("MULT", two_int_args), expression::TYPE_INT); -    expression_literal e_mult_i = ft->eval("MULT", two_int_args, two_int_values); -    BOOST_REQUIRE_EQUAL(e_mult_i.infer_type(), expression::TYPE_INT); -    BOOST_CHECK_EQUAL(e_mult_i.get_int(), 6); - -    BOOST_REQUIRE_EQUAL(ft->get_type("MULT", two_double_args), expression::TYPE_DOUBLE); -    expression_literal e_mult_d = ft->eval("MULT", two_double_args, two_double_values); -    BOOST_REQUIRE_EQUAL(e_mult_d.infer_type(), expression::TYPE_DOUBLE); -    BOOST_CHECK_CLOSE(e_mult_d.get_double(), 6.0, 0.01); - -    BOOST_REQUIRE_EQUAL(ft->get_type("DIV", two_double_args), expression::TYPE_DOUBLE); -    expression_literal e_div_d = ft->eval("DIV", two_double_args, two_double_values); -    BOOST_REQUIRE_EQUAL(e_div_d.infer_type(), expression::TYPE_DOUBLE); -    BOOST_CHECK_CLOSE(e_div_d.get_double(), 2.0 / 3.0, 0.01); - -    BOOST_REQUIRE_EQUAL(ft->get_type("MODULO", two_int_args), expression::TYPE_INT); -    expression_literal e_modulo_i = ft->eval("MODULO", two_int_args, two_int_values); -    BOOST_REQUIRE_EQUAL(e_modulo_i.infer_type(), expression::TYPE_INT); -    BOOST_CHECK_EQUAL(e_modulo_i.get_int(), 2 % 3); - -    BOOST_REQUIRE_EQUAL(ft->get_type("LE", two_int_args), expression::TYPE_BOOL); -    expression_literal e_le = ft->eval("LE", two_int_args, two_int_values); -    BOOST_REQUIRE_EQUAL(e_le.infer_type(), expression::TYPE_BOOL); -    BOOST_CHECK_EQUAL(e_le.get_bool(), true); -    BOOST_CHECK_EQUAL(ft->eval("LE", two_int_args, two_int_values2).get_bool(), false); -    expression_literal e_ge = ft->eval("GE", two_int_args, two_int_values); -    BOOST_REQUIRE_EQUAL(ft->get_type("GE", two_int_args), expression::TYPE_BOOL); -    BOOST_REQUIRE_EQUAL(e_ge.infer_type(), expression::TYPE_BOOL); -    BOOST_CHECK_EQUAL(e_ge.get_bool(), false); - -    expression_container::expr_list_type sixty_four{E(64)}; -    expression_literal e_pwr2 = ft->eval("IS_PWR_OF_2", one_int_arg, sixty_four); -    BOOST_REQUIRE_EQUAL(e_pwr2.infer_type(), expression::TYPE_BOOL); -    BOOST_CHECK_EQUAL(e_pwr2.get_bool(), true); -    expression_literal e_log2 = ft->eval("LOG2", one_int_arg, sixty_four); -    BOOST_REQUIRE_EQUAL(e_log2.infer_type(), expression::TYPE_INT); -    BOOST_CHECK_EQUAL(e_log2.get_int(), 6); - -    // Boolean Logic -    expression_container::expr_list_type e_true{E(true)}; -    expression_container::expr_list_type e_false{E(false)}; -    BOOST_CHECK(ft->eval("TRUE", no_args, empty_arg_list).to_bool()); -    BOOST_CHECK(ft->eval("TRUE", no_args, empty_arg_list).get_bool()); -    BOOST_CHECK_EQUAL(ft->eval("FALSE", no_args, empty_arg_list).to_bool(), false); -    BOOST_CHECK_EQUAL(ft->eval("FALSE", no_args, empty_arg_list).get_bool(), false); -    BOOST_CHECK(ft->eval("NOT", one_bool_arg, e_false).to_bool()); - -    // Control -    std::cout << "Checking ~1s sleep until... "; -    expression_container::expr_list_type e_sleeptime{E(.999)}; -    BOOST_CHECK(ft->eval("SLEEP", one_double_arg, e_sleeptime).get_bool()); -    std::cout << "Now." << std::endl; -} - -// Some bogus function to test the registry -expression_literal add_plus2_int(expression_container::expr_list_type args) -{ -    return expression_literal(args[0]->eval().get_int() + args[1]->eval().get_int() + 2); -} - -BOOST_AUTO_TEST_CASE(test_add_funcs) -{ -    function_table::sptr ft = function_table::make(); - -    BOOST_CHECK(not ft->function_exists("ADD_PLUS_2")); - -    expression_function::argtype_list_type add_int_args{ -        expression::TYPE_INT, expression::TYPE_INT}; -    ft->register_function("ADD_PLUS_2", -        boost::bind(&add_plus2_int, _1), -        expression::TYPE_INT, -        add_int_args); - -    BOOST_CHECK(ft->function_exists("ADD_PLUS_2")); -    BOOST_CHECK(ft->function_exists("ADD_PLUS_2", add_int_args)); - -    expression_container::expr_list_type add_int_values{E(2), E(3)}; -    expression_literal e = ft->eval("ADD_PLUS_2", two_int_args, add_int_values); -    BOOST_REQUIRE_EQUAL(e.infer_type(), expression::TYPE_INT); -    BOOST_CHECK_EQUAL(e.get_int(), 7); -} - -int dummy_true_counter = 0; -// Some bogus function to test the registry -expression_literal dummy_true(expression_container::expr_list_type) -{ -    dummy_true_counter++; -    std::cout << "Running dummy/true statement." << std::endl; -    return expression_literal(true); -} - -int dummy_false_counter = 0; -// Some bogus function to test the registry -expression_literal dummy_false(expression_container::expr_list_type) -{ -    dummy_false_counter++; -    std::cout << "Running dummy/false statement." << std::endl; -    return expression_literal(false); -} - -BOOST_AUTO_TEST_CASE(test_conditionals) -{ -    function_table::sptr ft = function_table::make(); -    ft->register_function( -        "DUMMY", boost::bind(&dummy_true, _1), expression::TYPE_BOOL, no_args); -    ft->register_function( -        "DUMMY_F", boost::bind(&dummy_false, _1), expression::TYPE_BOOL, no_args); -    BOOST_REQUIRE(ft->function_exists("DUMMY", no_args)); -    BOOST_REQUIRE(ft->function_exists("DUMMY_F", no_args)); - -    expression_function::sptr dummy_statement = -        boost::make_shared<expression_function>("DUMMY", ft); -    expression_function::sptr if_statement = -        boost::make_shared<expression_function>("IF", ft); -    if_statement->add(E(true)); -    if_statement->add(dummy_statement); - -    std::cout << "Dummy statement should run once until END:" << std::endl; -    dummy_true_counter = 0; -    BOOST_CHECK(if_statement->eval().get_bool()); -    BOOST_CHECK_EQUAL(dummy_true_counter, 1); -    std::cout << "END." << std::endl; - -    std::cout << "Dummy statement should not run until END:" << std::endl; -    expression_function::sptr if_statement2 = -        boost::make_shared<expression_function>("IF", ft); -    if_statement2->add(E(false)); -    if_statement2->add(dummy_statement); -    dummy_true_counter = 0; -    BOOST_CHECK(not if_statement2->eval().get_bool()); -    BOOST_CHECK_EQUAL(dummy_true_counter, 0); -    std::cout << "END." << std::endl; - -    expression_function::sptr if_else_statement = -        boost::make_shared<expression_function>("IF_ELSE", ft); -    expression_function::sptr dummy_statement_f = -        boost::make_shared<expression_function>("DUMMY_F", ft); -    if_else_statement->add(E(true)); -    if_else_statement->add(dummy_statement); -    if_else_statement->add(dummy_statement_f); -    dummy_true_counter  = 0; -    dummy_false_counter = 0; -    std::cout << "Should execute dummy/true statement before END:" << std::endl; -    BOOST_CHECK(if_else_statement->eval().get_bool()); -    BOOST_CHECK_EQUAL(dummy_true_counter, 1); -    BOOST_CHECK_EQUAL(dummy_false_counter, 0); -    std::cout << "END." << std::endl; - -    expression_function::sptr if_else_statement2 = -        boost::make_shared<expression_function>("IF_ELSE", ft); -    if_else_statement2->add(E(false)); -    if_else_statement2->add(dummy_statement); -    if_else_statement2->add(dummy_statement_f); -    dummy_true_counter  = 0; -    dummy_false_counter = 0; -    std::cout << "Should execute dummy/false statement before END:" << std::endl; -    BOOST_CHECK(not if_else_statement2->eval().get_bool()); -    BOOST_CHECK_EQUAL(dummy_true_counter, 0); -    BOOST_CHECK_EQUAL(dummy_false_counter, 1); -    std::cout << "END." << std::endl; -} - -BOOST_AUTO_TEST_CASE(test_bitwise_funcs) -{ -    function_table::sptr ft = function_table::make(); -    BOOST_CHECK(ft->function_exists("SHIFT_RIGHT")); -    BOOST_CHECK(ft->function_exists("SHIFT_RIGHT", two_int_args)); -    BOOST_CHECK(ft->function_exists("SHIFT_LEFT")); -    BOOST_CHECK(ft->function_exists("SHIFT_LEFT", two_int_args)); -    BOOST_CHECK(ft->function_exists("BITWISE_AND")); -    BOOST_CHECK(ft->function_exists("BITWISE_AND", two_int_args)); -    BOOST_CHECK(ft->function_exists("BITWISE_OR")); -    BOOST_CHECK(ft->function_exists("BITWISE_OR", two_int_args)); -    BOOST_CHECK(ft->function_exists("BITWISE_XOR")); -    BOOST_CHECK(ft->function_exists("BITWISE_XOR", two_int_args)); - -    // Bitwise Math -    int int_value1 = 0x2; -    int int_value2 = 0x3; -    expression_container::expr_list_type two_int_values{E(int_value1), E(int_value2)}; - -    BOOST_REQUIRE_EQUAL(ft->get_type("SHIFT_RIGHT", two_int_args), expression::TYPE_INT); -    expression_literal e_shift_right = -        ft->eval("SHIFT_RIGHT", two_int_args, two_int_values); -    BOOST_REQUIRE_EQUAL(e_shift_right.infer_type(), expression::TYPE_INT); -    BOOST_CHECK_EQUAL(e_shift_right.get_int(), int_value1 >> int_value2); - -    BOOST_REQUIRE_EQUAL(ft->get_type("SHIFT_LEFT", two_int_args), expression::TYPE_INT); -    expression_literal e_shift_left = -        ft->eval("SHIFT_LEFT", two_int_args, two_int_values); -    BOOST_REQUIRE_EQUAL(e_shift_left.infer_type(), expression::TYPE_INT); -    BOOST_CHECK_EQUAL(e_shift_left.get_int(), int_value1 << int_value2); - -    BOOST_REQUIRE_EQUAL(ft->get_type("BITWISE_AND", two_int_args), expression::TYPE_INT); -    expression_literal e_bitwise_and = -        ft->eval("BITWISE_AND", two_int_args, two_int_values); -    BOOST_REQUIRE_EQUAL(e_bitwise_and.infer_type(), expression::TYPE_INT); -    BOOST_CHECK_EQUAL(e_bitwise_and.get_int(), int_value1 & int_value2); - -    BOOST_REQUIRE_EQUAL(ft->get_type("BITWISE_OR", two_int_args), expression::TYPE_INT); -    expression_literal e_bitwise_or = -        ft->eval("BITWISE_OR", two_int_args, two_int_values); -    BOOST_REQUIRE_EQUAL(e_bitwise_or.infer_type(), expression::TYPE_INT); -    BOOST_CHECK_EQUAL(e_bitwise_or.get_int(), int_value1 | int_value2); - -    BOOST_REQUIRE_EQUAL(ft->get_type("BITWISE_XOR", two_int_args), expression::TYPE_INT); -    expression_literal e_bitwise_xor = -        ft->eval("BITWISE_XOR", two_int_args, two_int_values); -    BOOST_REQUIRE_EQUAL(e_bitwise_xor.infer_type(), expression::TYPE_INT); -    BOOST_CHECK_EQUAL(e_bitwise_xor.get_int(), int_value1 ^ int_value2); -} diff --git a/host/tests/nocscript_parser_test.cpp b/host/tests/nocscript_parser_test.cpp deleted file mode 100644 index eb9352995..000000000 --- a/host/tests/nocscript_parser_test.cpp +++ /dev/null @@ -1,147 +0,0 @@ -// -// Copyright 2015 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#include "../lib/rfnoc/nocscript/function_table.hpp" -#include "../lib/rfnoc/nocscript/parser.hpp" -#include "nocscript_common.hpp" -#include <uhd/exception.hpp> -#include <boost/assign/list_of.hpp> -#include <boost/bind.hpp> -#include <boost/make_shared.hpp> -#include <boost/test/floating_point_comparison.hpp> -#include <boost/test/unit_test.hpp> -#include <algorithm> -#include <iostream> - -const int SPP_VALUE = 64; - -// Need those for the variable testing: -expression::type_t variable_get_type(const std::string& var_name) -{ -    if (var_name == "spp") { -        std::cout << "Returning type for $spp..." << std::endl; -        return expression::TYPE_INT; -    } -    if (var_name == "is_true") { -        std::cout << "Returning type for $is_true..." << std::endl; -        return expression::TYPE_BOOL; -    } - -    throw uhd::syntax_error("Cannot infer type (unknown variable)"); -} - -expression_literal variable_get_value(const std::string& var_name) -{ -    if (var_name == "spp") { -        std::cout << "Returning value for $spp..." << std::endl; -        return expression_literal(SPP_VALUE); -    } -    if (var_name == "is_true") { -        std::cout << "Returning value for $is_true..." << std::endl; -        return expression_literal(true); -    } - -    throw uhd::syntax_error("Cannot read value (unknown variable)"); -} - -#define SETUP_FT_AND_PARSER()                         \ -    function_table::sptr ft = function_table::make(); \ -    parser::sptr p          = parser::make(           \ -        ft, boost::bind(&variable_get_type, _1), boost::bind(&variable_get_value, _1)); - -BOOST_AUTO_TEST_CASE(test_fail) -{ -    SETUP_FT_AND_PARSER(); - -    // Missing closing parens: -    BOOST_REQUIRE_THROW(p->create_expr_tree("ADD1(1, "), uhd::syntax_error); -    // Double comma: -    BOOST_REQUIRE_THROW(p->create_expr_tree("ADD(1,, 2)"), uhd::syntax_error); -    // No comma: -    BOOST_REQUIRE_THROW(p->create_expr_tree("ADD(1 2)"), uhd::syntax_error); -    // Double closing parens: -    BOOST_REQUIRE_THROW(p->create_expr_tree("ADD(1, 2))"), uhd::syntax_error); -    // Unknown function: -    BOOST_REQUIRE_THROW(p->create_expr_tree("GLORPGORP(1, 2)"), uhd::syntax_error); -} - -BOOST_AUTO_TEST_CASE(test_adds_no_vars) -{ -    SETUP_FT_AND_PARSER(); -    BOOST_REQUIRE(ft->function_exists("ADD")); - -    const std::string line("ADD(1, ADD(2, ADD(3, 4)))"); -    expression::sptr e        = p->create_expr_tree(line); -    expression_literal result = e->eval(); - -    BOOST_REQUIRE_EQUAL(result.infer_type(), expression::TYPE_INT); -    BOOST_CHECK_EQUAL(result.get_int(), 1 + 2 + 3 + 4); -} - -BOOST_AUTO_TEST_CASE(test_adds_with_vars) -{ -    SETUP_FT_AND_PARSER(); - -    const std::string line("ADD(1, ADD(2, $spp))"); -    expression::sptr e        = p->create_expr_tree(line); -    expression_literal result = e->eval(); - -    BOOST_REQUIRE_EQUAL(result.infer_type(), expression::TYPE_INT); -    BOOST_CHECK_EQUAL(result.get_int(), 1 + 2 + SPP_VALUE); -} - -BOOST_AUTO_TEST_CASE(test_fft_check) -{ -    SETUP_FT_AND_PARSER(); - -    const std::string line("GE($spp, 16) AND LE($spp, 4096) AND IS_PWR_OF_2($spp)"); -    expression::sptr e        = p->create_expr_tree(line); -    expression_literal result = e->eval(); - -    BOOST_REQUIRE_EQUAL(result.infer_type(), expression::TYPE_BOOL); -    BOOST_CHECK(result.get_bool()); -} - -BOOST_AUTO_TEST_CASE(test_pure_string) -{ -    SETUP_FT_AND_PARSER(); - -    // Eval all, return last expression -    const std::string line("'foo foo', \"bar\""); -    expression_literal result = p->create_expr_tree(line)->eval(); - -    BOOST_REQUIRE_EQUAL(result.infer_type(), expression::TYPE_STRING); -    BOOST_CHECK_EQUAL(result.get_string(), "bar"); -} - -int dummy_false_counter = 0; -expression_literal dummy_false(expression_container::expr_list_type) -{ -    dummy_false_counter++; -    std::cout << "Running dummy/false statement." << std::endl; -    return expression_literal(false); -} - -BOOST_AUTO_TEST_CASE(test_multi_commmand) -{ -    SETUP_FT_AND_PARSER(); - -    ft->register_function( -        "DUMMY", boost::bind(&dummy_false, _1), expression::TYPE_BOOL, no_args); - -    dummy_false_counter = 0; -    p->create_expr_tree("DUMMY(), DUMMY(), DUMMY()")->eval(); -    BOOST_CHECK_EQUAL(dummy_false_counter, 3); - -    dummy_false_counter = 0; -    p->create_expr_tree("DUMMY() AND DUMMY() AND DUMMY()")->eval(); -    BOOST_CHECK_EQUAL(dummy_false_counter, 1); - -    dummy_false_counter = 0; -    p->create_expr_tree("DUMMY() OR DUMMY() OR DUMMY()")->eval(); -    BOOST_CHECK_EQUAL(dummy_false_counter, 3); -} diff --git a/host/tests/node_connect_test.cpp b/host/tests/node_connect_test.cpp deleted file mode 100644 index 97d052a06..000000000 --- a/host/tests/node_connect_test.cpp +++ /dev/null @@ -1,127 +0,0 @@ -// -// Copyright 2014 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#include "graph.hpp" -#include <boost/test/unit_test.hpp> -#include <iostream> - -using namespace uhd::rfnoc; - -class source_node : public test_node -{ -public: -    typedef boost::shared_ptr<source_node> sptr; - -    source_node(const std::string& test_id, size_t output_port) -        : test_node(test_id), active_rx_streamer_on_port(0), _output_port(output_port){}; - -    void set_rx_streamer(bool active, const size_t port) -    { -        if (active) { -            std::cout << "[source_node] Someone is registering a rx streamer on port " -                      << port << std::endl; -            active_rx_streamer_on_port = port; -        } -    } -    size_t active_rx_streamer_on_port; - -protected: -    size_t _request_output_port(const size_t, const uhd::device_addr_t&) const -    { -        return _output_port; -    } - -    const size_t _output_port; - -}; /* class result_node */ - -class sink_node : public test_node -{ -public: -    typedef boost::shared_ptr<sink_node> sptr; - -    sink_node(const std::string& test_id, size_t input_port) -        : test_node(test_id), active_tx_streamer_on_port(0), _input_port(input_port){}; - -    void set_tx_streamer(bool active, const size_t port) -    { -        if (active) { -            std::cout << "[sink_node] Someone is registering a tx streamer on port " -                      << port << std::endl; -            active_tx_streamer_on_port = port; -        } -    } -    size_t active_tx_streamer_on_port; - -protected: -    size_t _request_input_port(const size_t, const uhd::device_addr_t&) const -    { -        return _input_port; -    } - -    const size_t _input_port; - -}; /* class result_node */ - -#define MAKE_SOURCE_NODE(name, port) source_node::sptr name(new source_node(#name, port)); -#define MAKE_SINK_NODE(name, port) sink_node::sptr name(new sink_node(#name, port)); - -BOOST_AUTO_TEST_CASE(test_simple_connect) -{ -    MAKE_SOURCE_NODE(node_A, 42); -    MAKE_SINK_NODE(node_B, 23); - -    size_t src_port = node_A->connect_downstream(node_B, 1); -    size_t dst_port = node_B->connect_upstream(node_A, 2); - -    BOOST_CHECK_EQUAL(src_port, 42); -    BOOST_CHECK_EQUAL(dst_port, 23); - -    node_A->set_downstream_port(src_port, dst_port); -    node_B->set_upstream_port(dst_port, src_port); -    BOOST_CHECK_EQUAL(node_A->get_downstream_port(src_port), dst_port); -    BOOST_CHECK_EQUAL(node_B->get_upstream_port(dst_port), src_port); - -    BOOST_REQUIRE_THROW(node_A->get_downstream_port(999), uhd::value_error); -} - -BOOST_AUTO_TEST_CASE(test_fail) -{ -    MAKE_SOURCE_NODE(node_A, 42); -    MAKE_SINK_NODE(node_B, ANY_PORT); - -    node_A->connect_downstream(node_B, 1); -    BOOST_REQUIRE_THROW(node_B->connect_upstream(node_A, 2), uhd::type_error); -} - -BOOST_AUTO_TEST_CASE(test_set_streamers) -{ -    MAKE_SOURCE_NODE(node_A, 0); -    MAKE_NODE(node_B); -    MAKE_SINK_NODE(node_C, 0); - -    size_t src_port_A = node_A->connect_downstream(node_B, 0); -    size_t src_port_B = node_B->connect_downstream(node_C, 0); -    size_t dst_port_B = node_B->connect_upstream(node_A, 0); -    size_t dst_port_C = node_C->connect_upstream(node_B, 0); - -    std::cout << "src_port_A: " << src_port_A << std::endl; -    std::cout << "src_port_B: " << src_port_B << std::endl; -    std::cout << "dst_port_B: " << dst_port_B << std::endl; -    std::cout << "dst_port_C: " << dst_port_C << std::endl; - -    node_A->set_downstream_port(src_port_A, dst_port_B); -    node_B->set_upstream_port(dst_port_B, src_port_A); -    node_B->set_downstream_port(src_port_B, dst_port_C); -    node_C->set_upstream_port(dst_port_C, src_port_B); - -    node_A->set_tx_streamer(true, 0); -    node_C->set_rx_streamer(true, 0); - -    BOOST_CHECK_EQUAL(node_A->active_rx_streamer_on_port, src_port_A); -    BOOST_CHECK_EQUAL(node_C->active_tx_streamer_on_port, dst_port_C); -} diff --git a/host/tests/packet_handler_benchmark.cpp b/host/tests/packet_handler_benchmark.cpp index 6d4849831..d0a28bdc2 100644 --- a/host/tests/packet_handler_benchmark.cpp +++ b/host/tests/packet_handler_benchmark.cpp @@ -13,13 +13,11 @@  #include "../lib/transport/super_recv_packet_handler.hpp"  #include "../lib/transport/super_send_packet_handler.hpp" -#include "../lib/usrp/device3/device3_flow_ctrl.hpp"  #include "common/mock_zero_copy.hpp"  #include <uhd/convert.hpp>  #include <uhd/transport/chdr.hpp>  #include <uhd/transport/zero_copy.hpp>  #include <uhd/transport/zero_copy_flow_ctrl.hpp> -#include <uhd/types/sid.hpp>  #include <uhd/utils/safe_main.hpp>  #include <uhd/utils/thread.hpp>  #include <boost/program_options.hpp> @@ -47,7 +45,6 @@ struct rx_fc_cache_t      uint32_t total_packets_consumed = 0;      //! Sequence number of next flow control packet      uint64_t seq_num = 0; -    uhd::sid_t sid;      uhd::transport::zero_copy_if::sptr xport;      std::function<uint32_t(uint32_t)> to_host;      std::function<uint32_t(uint32_t)> from_host; @@ -155,8 +152,7 @@ inline bool tx_flow_ctrl(boost::shared_ptr<tx_fc_cache_t> fc_cache,  }  inline void tx_flow_ctrl_ack(boost::shared_ptr<tx_fc_cache_t> fc_cache, -    uhd::transport::zero_copy_if::sptr /*send_xport*/, -    uhd::sid_t /*send_sid*/) +    uhd::transport::zero_copy_if::sptr /*send_xport*/)  {      if (not fc_cache->fc_received) {          return; @@ -296,7 +292,7 @@ void benchmark_send_packet_handler(      // Configure flow control ack      streamer->set_xport_chan_post_send_cb(0, [fc_cache, zero_copy_xport]() { -        tx_flow_ctrl_ack(fc_cache, zero_copy_xport, 0); +        tx_flow_ctrl_ack(fc_cache, zero_copy_xport);      });      // Allocate buffer diff --git a/host/tests/rate_node_test.cpp b/host/tests/rate_node_test.cpp deleted file mode 100644 index 85502c325..000000000 --- a/host/tests/rate_node_test.cpp +++ /dev/null @@ -1,136 +0,0 @@ -// -// Copyright 2014 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#include "graph.hpp" -#include <uhd/rfnoc/rate_node_ctrl.hpp> -#include <boost/test/unit_test.hpp> -#include <iostream> - -using namespace uhd::rfnoc; - -// test class derived, knows about rates -class rate_aware_node : public test_node, public rate_node_ctrl -{ -public: -    typedef boost::shared_ptr<rate_aware_node> sptr; - -    rate_aware_node(const std::string& test_id) : test_node(test_id){}; - -}; /* class rate_aware_node */ - -// test class derived, sets rates -class rate_setting_node : public test_node, public rate_node_ctrl -{ -public: -    typedef boost::shared_ptr<rate_setting_node> sptr; - -    rate_setting_node(const std::string& test_id, double samp_rate) -        : test_node(test_id), _samp_rate(samp_rate){}; - -    double get_input_samp_rate(size_t) -    { -        return _samp_rate; -    }; -    double get_output_samp_rate(size_t) -    { -        return _samp_rate; -    }; - -private: -    double _samp_rate; - -}; /* class rate_setting_node */ - -#define MAKE_RATE_NODE(name) rate_aware_node::sptr name(new rate_aware_node(#name)); -#define MAKE_RATE_SETTING_NODE(name, rate) \ -    rate_setting_node::sptr name(new rate_setting_node(#name, rate)); - -BOOST_AUTO_TEST_CASE(test_simplest_downstream_search) -{ -    const double test_rate = 0.25; -    MAKE_RATE_NODE(node_A); -    MAKE_RATE_SETTING_NODE(node_B, test_rate); - -    // Simplest possible scenario: Connect B downstream of A and let -    // it find B -    connect_nodes(node_A, node_B); - -    double result_rate = node_A->get_input_samp_rate(); -    BOOST_CHECK_EQUAL(result_rate, test_rate); -} - -BOOST_AUTO_TEST_CASE(test_skip_downstream_search) -{ -    const double test_rate = 0.25; -    MAKE_RATE_NODE(node_A); -    MAKE_NODE(node_B); -    MAKE_RATE_SETTING_NODE(node_C, test_rate); - -    // Slightly more elaborate: Add another block in between that has no -    // clue about rates -    connect_nodes(node_A, node_B); -    connect_nodes(node_B, node_C); - -    double result_rate = node_A->get_input_samp_rate(); -    BOOST_CHECK_EQUAL(result_rate, test_rate); -} - -BOOST_AUTO_TEST_CASE(test_tree_downstream_search) -{ -    const double test_rate = 0.25; -    MAKE_RATE_NODE(node_A); -    MAKE_NODE(node_B0); -    MAKE_RATE_SETTING_NODE(node_B1, test_rate); -    MAKE_RATE_SETTING_NODE(node_C0, test_rate); -    MAKE_RATE_SETTING_NODE(node_C1, rate_node_ctrl::RATE_UNDEFINED); - -    // Tree: Downstream of our first node are 3 rate setting blocks. -    // Two set the same rate, the third does not care. -    connect_nodes(node_A, node_B0); -    connect_nodes(node_A, node_B1); -    connect_nodes(node_B0, node_C0); -    connect_nodes(node_B0, node_C1); - -    double result_rate = node_A->get_input_samp_rate(); -    BOOST_CHECK_EQUAL(result_rate, test_rate); -} - -BOOST_AUTO_TEST_CASE(test_tree_downstream_search_throw) -{ -    const double test_rate = 0.25; -    MAKE_RATE_NODE(node_A); -    MAKE_NODE(node_B0); -    MAKE_RATE_SETTING_NODE(node_B1, test_rate); -    MAKE_RATE_SETTING_NODE(node_C0, test_rate); -    MAKE_RATE_SETTING_NODE(node_C1, test_rate * 2); - -    // Tree: Downstream of our first node are 3 rate setting blocks. -    // Two set the same rate, the third has a different rate. -    // This will cause a throw. -    connect_nodes(node_A, node_B0); -    connect_nodes(node_A, node_B1); -    connect_nodes(node_B0, node_C0); -    connect_nodes(node_B0, node_C1); - -    BOOST_CHECK_THROW(node_A->get_input_samp_rate(), uhd::runtime_error); -} - -BOOST_AUTO_TEST_CASE(test_skip_upstream_search) -{ -    const double test_rate = 0.25; -    MAKE_RATE_SETTING_NODE(node_A, test_rate); -    MAKE_NODE(node_B); -    MAKE_RATE_NODE(node_C); - -    // Slightly more elaborate: Add another block in between that has no -    // clue about rates -    connect_nodes(node_A, node_B); -    connect_nodes(node_B, node_C); - -    double result_rate = node_C->get_output_samp_rate(); -    BOOST_CHECK_EQUAL(result_rate, test_rate); -} diff --git a/host/tests/sid_t_test.cpp b/host/tests/sid_t_test.cpp deleted file mode 100644 index 2a13995df..000000000 --- a/host/tests/sid_t_test.cpp +++ /dev/null @@ -1,155 +0,0 @@ -// -// Copyright 2014 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#include <uhd/exception.hpp> -#include <uhd/types/sid.hpp> -#include <boost/test/unit_test.hpp> -#include <iostream> -#include <sstream> - -using uhd::sid_t; - -BOOST_AUTO_TEST_CASE(test_sid_t) -{ -    uint32_t sid_value = 0x01020310; -    sid_t sid(sid_value); - -    BOOST_CHECK_EQUAL(sid.is_set(), true); -    BOOST_CHECK_EQUAL(sid.to_pp_string(), "1.2>3.16"); -    BOOST_CHECK_EQUAL(sid.to_pp_string_hex(), "01:02>03:10"); -    BOOST_CHECK_EQUAL(sid.get_src(), (uint32_t)0x0102); -    BOOST_CHECK_EQUAL(sid.get_dst(), (uint32_t)0x0310); -    BOOST_CHECK_EQUAL(sid.get_src_addr(), (uint32_t)0x01); -    BOOST_CHECK_EQUAL(sid.get_src_endpoint(), (uint32_t)0x02); -    BOOST_CHECK_EQUAL(sid.get_dst_addr(), (uint32_t)0x03); -    BOOST_CHECK_EQUAL(sid.get_dst_endpoint(), (uint32_t)0x10); -    BOOST_CHECK_EQUAL(sid == sid, true); -    BOOST_CHECK_EQUAL(sid == sid_value, true); - -    uint32_t check_sid_val = (uint32_t)sid; -    BOOST_CHECK_EQUAL(check_sid_val, sid_value); - -    std::stringstream ss_dec; -    ss_dec << sid; -    BOOST_CHECK_EQUAL(ss_dec.str(), "1.2>3.16"); - -    std::stringstream ss_hex; -    ss_hex << std::hex << sid; -    BOOST_CHECK_EQUAL(ss_hex.str(), "01:02>03:10"); - -    sid_t empty_sid; -    BOOST_CHECK_EQUAL(empty_sid.is_set(), false); -    BOOST_CHECK_EQUAL(empty_sid.to_pp_string(), "x.x>x.x"); -    BOOST_CHECK_EQUAL(empty_sid.to_pp_string_hex(), "xx:xx>xx:xx"); -    BOOST_CHECK_EQUAL(empty_sid == sid, false); -    BOOST_CHECK_EQUAL(empty_sid == sid_value, false); -    BOOST_CHECK_EQUAL((bool)empty_sid, false); - -    empty_sid = sid_value; // No longer empty -    BOOST_CHECK_EQUAL(empty_sid.is_set(), true); -    BOOST_CHECK_EQUAL(empty_sid == sid, true); -} - -BOOST_AUTO_TEST_CASE(test_sid_t_set) -{ -    uint32_t sid_value = 0x0; -    sid_t sid(sid_value); - -    sid.set(0x01020304); -    BOOST_CHECK_EQUAL(sid.get(), (uint32_t)0x01020304); -    BOOST_CHECK_EQUAL(sid.get_src_addr(), (uint32_t)0x01); -    BOOST_CHECK_EQUAL(sid.get_src_endpoint(), (uint32_t)0x02); -    BOOST_CHECK_EQUAL(sid.get_dst_addr(), (uint32_t)0x03); -    BOOST_CHECK_EQUAL(sid.get_dst_endpoint(), (uint32_t)0x04); -    BOOST_CHECK_EQUAL(sid.get_dst_xbarport(), (uint32_t)0x0); -    BOOST_CHECK_EQUAL(sid.get_dst_blockport(), (uint32_t)0x4); - -    sid.set_src_addr(0x0a); -    BOOST_CHECK_EQUAL(sid.get(), (uint32_t)0x0a020304); -    BOOST_CHECK_EQUAL(sid.get_src_addr(), (uint32_t)0x0a); -    BOOST_CHECK_EQUAL(sid.get_src_endpoint(), (uint32_t)0x02); -    BOOST_CHECK_EQUAL(sid.get_dst_addr(), (uint32_t)0x03); -    BOOST_CHECK_EQUAL(sid.get_dst_endpoint(), (uint32_t)0x04); - -    sid.set_src_endpoint(0x0b); -    BOOST_CHECK_EQUAL(sid.get(), (uint32_t)0x0a0b0304); -    BOOST_CHECK_EQUAL(sid.get_src_addr(), (uint32_t)0x0a); -    BOOST_CHECK_EQUAL(sid.get_src_endpoint(), (uint32_t)0x0b); -    BOOST_CHECK_EQUAL(sid.get_dst_addr(), (uint32_t)0x03); -    BOOST_CHECK_EQUAL(sid.get_dst_endpoint(), (uint32_t)0x04); - -    sid.set_dst_addr(0x0c); -    BOOST_CHECK_EQUAL(sid.get(), (uint32_t)0x0a0b0c04); -    BOOST_CHECK_EQUAL(sid.get_src_addr(), (uint32_t)0x0a); -    BOOST_CHECK_EQUAL(sid.get_src_endpoint(), (uint32_t)0x0b); -    BOOST_CHECK_EQUAL(sid.get_dst_addr(), (uint32_t)0x0c); -    BOOST_CHECK_EQUAL(sid.get_dst_endpoint(), (uint32_t)0x04); - -    sid.set_dst_endpoint(0x0d); -    BOOST_CHECK_EQUAL(sid.get(), (uint32_t)0x0a0b0c0d); -    BOOST_CHECK_EQUAL(sid.get_src_addr(), (uint32_t)0x0a); -    BOOST_CHECK_EQUAL(sid.get_src_endpoint(), (uint32_t)0x0b); -    BOOST_CHECK_EQUAL(sid.get_dst_addr(), (uint32_t)0x0c); -    BOOST_CHECK_EQUAL(sid.get_dst_endpoint(), (uint32_t)0x0d); - -    sid.set_dst_xbarport(0xb); -    BOOST_CHECK_EQUAL(sid.get(), (uint32_t)0x0a0b0cbd); -    BOOST_CHECK_EQUAL(sid.get_src_addr(), (uint32_t)0x0a); -    BOOST_CHECK_EQUAL(sid.get_src_endpoint(), (uint32_t)0x0b); -    BOOST_CHECK_EQUAL(sid.get_dst_addr(), (uint32_t)0x0c); -    BOOST_CHECK_EQUAL(sid.get_dst_endpoint(), (uint32_t)0xbd); - -    sid.set_dst_blockport(0xc); -    BOOST_CHECK_EQUAL(sid.get(), (uint32_t)0x0a0b0cbc); -    BOOST_CHECK_EQUAL(sid.get_src_addr(), (uint32_t)0x0a); -    BOOST_CHECK_EQUAL(sid.get_src_endpoint(), (uint32_t)0x0b); -    BOOST_CHECK_EQUAL(sid.get_dst_addr(), (uint32_t)0x0c); -    BOOST_CHECK_EQUAL(sid.get_dst_endpoint(), (uint32_t)0xbc); - -    const sid_t flipped_sid = sid.reversed(); -    BOOST_CHECK_EQUAL(flipped_sid.get(), (uint32_t)0x0cbc0a0b); -    BOOST_CHECK_EQUAL(flipped_sid.reversed(), sid); - -    const sid_t sid2 = sid_t(sid.get_sid()); -    BOOST_CHECK_EQUAL(sid2, sid); - -    // In-place -    sid.reverse(); -    BOOST_CHECK_EQUAL(sid.get(), (uint32_t)0x0cbc0a0b); -} - -BOOST_AUTO_TEST_CASE(test_sid_t_from_str) -{ -    sid_t sid("1.2>3.4"); -    BOOST_CHECK_EQUAL(sid.get_src_addr(), (uint32_t)1); -    BOOST_CHECK_EQUAL(sid.get_src_endpoint(), (uint32_t)2); -    BOOST_CHECK_EQUAL(sid.get_dst_addr(), (uint32_t)3); -    BOOST_CHECK_EQUAL(sid.get_dst_endpoint(), (uint32_t)4); - -    sid = "01:02>03:10"; -    BOOST_CHECK_EQUAL(sid.get_src_addr(), (uint32_t)1); -    BOOST_CHECK_EQUAL(sid.get_src_endpoint(), (uint32_t)2); -    BOOST_CHECK_EQUAL(sid.get_dst_addr(), (uint32_t)3); -    BOOST_CHECK_EQUAL(sid.get_dst_endpoint(), (uint32_t)16); - -    sid = "01:06/03:10"; -    BOOST_CHECK_EQUAL(sid.get_src_addr(), (uint32_t)1); -    BOOST_CHECK_EQUAL(sid.get_src_endpoint(), (uint32_t)6); -    BOOST_CHECK_EQUAL(sid.get_dst_addr(), (uint32_t)3); -    BOOST_CHECK_EQUAL(sid.get_dst_endpoint(), (uint32_t)16); - -    sid = "01:02:04:10"; -    BOOST_CHECK_EQUAL(sid.get_src_addr(), (uint32_t)1); -    BOOST_CHECK_EQUAL(sid.get_src_endpoint(), (uint32_t)2); -    BOOST_CHECK_EQUAL(sid.get_dst_addr(), (uint32_t)4); -    BOOST_CHECK_EQUAL(sid.get_dst_endpoint(), (uint32_t)16); - -    BOOST_REQUIRE_THROW(sid_t fail_sid("foobar"), uhd::value_error); -    BOOST_REQUIRE_THROW(sid_t fail_sid("01:02:03:4"), uhd::value_error); -    BOOST_REQUIRE_THROW(sid_t fail_sid("01:02:03:004"), uhd::value_error); -    BOOST_REQUIRE_THROW(sid_t fail_sid("1.2.3.0004"), uhd::value_error); -} diff --git a/host/tests/stream_sig_test.cpp b/host/tests/stream_sig_test.cpp deleted file mode 100644 index 41c07c14f..000000000 --- a/host/tests/stream_sig_test.cpp +++ /dev/null @@ -1,75 +0,0 @@ -// -// Copyright 2014-2015 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#include <uhd/exception.hpp> -#include <uhd/rfnoc/stream_sig.hpp> -#include <boost/test/unit_test.hpp> -#include <iostream> - -using namespace uhd::rfnoc; - -BOOST_AUTO_TEST_CASE(test_stream_sig) -{ -    stream_sig_t stream_sig; - -    BOOST_CHECK_EQUAL(stream_sig.item_type, ""); -    BOOST_CHECK_EQUAL(stream_sig.vlen, 0); -    BOOST_CHECK_EQUAL(stream_sig.packet_size, 0); -    BOOST_CHECK_EQUAL(stream_sig.is_bursty, false); - -    std::stringstream ss; -    ss << stream_sig; -    // Eventually actually test the contents -    std::cout << ss.str() << std::endl; -} - -BOOST_AUTO_TEST_CASE(test_stream_sig_compat) -{ -    stream_sig_t upstream_sig; -    stream_sig_t downstream_sig; - -    BOOST_CHECK(stream_sig_t::is_compatible(upstream_sig, downstream_sig)); -    upstream_sig.vlen = 32; -    BOOST_CHECK(stream_sig_t::is_compatible(upstream_sig, downstream_sig)); -    downstream_sig.vlen = 32; -    BOOST_CHECK(stream_sig_t::is_compatible(upstream_sig, downstream_sig)); -    upstream_sig.vlen = 16; -    BOOST_CHECK(not stream_sig_t::is_compatible(upstream_sig, downstream_sig)); -    upstream_sig.vlen = 32; -    BOOST_CHECK(stream_sig_t::is_compatible(upstream_sig, downstream_sig)); -    upstream_sig.packet_size = 8; -    BOOST_CHECK(stream_sig_t::is_compatible(upstream_sig, downstream_sig)); -    downstream_sig.packet_size = 12; -    BOOST_CHECK(not stream_sig_t::is_compatible(upstream_sig, downstream_sig)); -    upstream_sig.packet_size = 0; -    BOOST_CHECK(stream_sig_t::is_compatible(upstream_sig, downstream_sig)); -    downstream_sig.item_type = ""; -    BOOST_CHECK(stream_sig_t::is_compatible(upstream_sig, downstream_sig)); -    upstream_sig.item_type   = "sc16"; -    downstream_sig.item_type = "s8"; -    BOOST_CHECK(not stream_sig_t::is_compatible(upstream_sig, downstream_sig)); -} - -BOOST_AUTO_TEST_CASE(test_stream_sig_types) -{ -    stream_sig_t stream_sig; -    BOOST_CHECK_EQUAL(stream_sig.get_bytes_per_item(), 0); -    stream_sig.item_type = "sc16"; -    BOOST_CHECK_EQUAL(stream_sig.get_bytes_per_item(), 4); -    stream_sig.item_type = "sc12"; -    BOOST_CHECK_EQUAL(stream_sig.get_bytes_per_item(), 3); -    stream_sig.item_type = "sc8"; -    BOOST_CHECK_EQUAL(stream_sig.get_bytes_per_item(), 2); -    stream_sig.item_type = "s16"; -    BOOST_CHECK_EQUAL(stream_sig.get_bytes_per_item(), 2); -    stream_sig.item_type = "s8"; -    BOOST_CHECK_EQUAL(stream_sig.get_bytes_per_item(), 1); -    stream_sig.item_type = "fc32"; -    BOOST_CHECK_EQUAL(stream_sig.get_bytes_per_item(), 8); -    stream_sig.item_type = "not_a_type"; -    BOOST_REQUIRE_THROW(stream_sig.get_bytes_per_item(), uhd::key_error); -} diff --git a/host/tests/tick_node_test.cpp b/host/tests/tick_node_test.cpp deleted file mode 100644 index ccec67c43..000000000 --- a/host/tests/tick_node_test.cpp +++ /dev/null @@ -1,116 +0,0 @@ -// -// Copyright 2014 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#include "graph.hpp" -#include <uhd/rfnoc/tick_node_ctrl.hpp> -#include <boost/test/unit_test.hpp> -#include <iostream> - -using namespace uhd::rfnoc; - -// test class derived, knows about rates -class tick_aware_node : public test_node, public tick_node_ctrl -{ -public: -    typedef boost::shared_ptr<tick_aware_node> sptr; - -    tick_aware_node(const std::string& test_id) : test_node(test_id){}; - -}; /* class tick_aware_node */ - -// test class derived, sets rates -class tick_setting_node : public test_node, public tick_node_ctrl -{ -public: -    typedef boost::shared_ptr<tick_setting_node> sptr; - -    tick_setting_node(const std::string& test_id, double tick_rate) -        : test_node(test_id), _tick_rate(tick_rate){}; - -protected: -    double _get_tick_rate() -    { -        return _tick_rate; -    }; - -private: -    const double _tick_rate; - -}; /* class tick_setting_node */ - -#define MAKE_TICK_NODE(name) tick_aware_node::sptr name(new tick_aware_node(#name)); -#define MAKE_TICK_SETTING_NODE(name, rate) \ -    tick_setting_node::sptr name(new tick_setting_node(#name, rate)); - -BOOST_AUTO_TEST_CASE(test_simplest_downstream_search) -{ -    const double test_rate = 0.25; -    MAKE_TICK_NODE(node_A); -    MAKE_TICK_SETTING_NODE(node_B, test_rate); - -    // Simplest possible scenario: Connect B downstream of A and let -    // it find B -    connect_nodes(node_A, node_B); -    node_A->set_tx_streamer(true, 0); -    node_B->set_rx_streamer(true, 0); - -    double result_rate = node_A->get_tick_rate(); -    BOOST_CHECK_EQUAL(result_rate, test_rate); -} - -BOOST_AUTO_TEST_CASE(test_both_ways_search) -{ -    const double test_rate = 0.25; -    MAKE_TICK_SETTING_NODE(node_A, tick_node_ctrl::RATE_UNDEFINED); -    MAKE_TICK_NODE(node_B); -    MAKE_TICK_SETTING_NODE(node_C, test_rate); - -    connect_nodes(node_A, node_B); -    connect_nodes(node_B, node_C); -    node_A->set_tx_streamer(true, 0); -    node_B->set_tx_streamer(true, 0); -    node_B->set_rx_streamer(true, 0); -    node_C->set_rx_streamer(true, 0); - -    double result_rate = node_B->get_tick_rate(); -    BOOST_CHECK_EQUAL(result_rate, test_rate); -} - -BOOST_AUTO_TEST_CASE(test_both_ways_search_reversed) -{ -    const double test_rate = 0.25; -    MAKE_TICK_SETTING_NODE(node_A, test_rate); -    MAKE_TICK_NODE(node_B); -    MAKE_TICK_SETTING_NODE(node_C, tick_node_ctrl::RATE_UNDEFINED); - -    connect_nodes(node_A, node_B); -    connect_nodes(node_B, node_C); -    node_A->set_tx_streamer(true, 0); -    node_B->set_tx_streamer(true, 0); -    node_B->set_rx_streamer(true, 0); -    node_C->set_rx_streamer(true, 0); - -    double result_rate = node_B->get_tick_rate(); -    BOOST_CHECK_EQUAL(result_rate, test_rate); -} - -BOOST_AUTO_TEST_CASE(test_both_ways_search_fail) -{ -    const double test_rate = 0.25; -    MAKE_TICK_SETTING_NODE(node_A, test_rate); -    MAKE_TICK_NODE(node_B); -    MAKE_TICK_SETTING_NODE(node_C, 2 * test_rate); - -    connect_nodes(node_A, node_B); -    connect_nodes(node_B, node_C); -    node_A->set_tx_streamer(true, 0); -    node_B->set_tx_streamer(true, 0); -    node_B->set_rx_streamer(true, 0); -    node_C->set_rx_streamer(true, 0); - -    BOOST_CHECK_THROW(node_B->get_tick_rate(), uhd::runtime_error); -} diff --git a/host/utils/CMakeLists.txt b/host/utils/CMakeLists.txt index 834c69c19..8542f30bb 100644 --- a/host/utils/CMakeLists.txt +++ b/host/utils/CMakeLists.txt @@ -165,7 +165,7 @@ add_subdirectory(rfnoc)  set(OUTPUT      "${CMAKE_CURRENT_BINARY_DIR}/build/timestamp")  set(SETUP_PY_IN "${CMAKE_CURRENT_SOURCE_DIR}/setup.py.in")  set(SETUP_PY    "${CMAKE_CURRENT_BINARY_DIR}/setup.py") -set(CONFIG_PATH "${CMAKE_INSTALL_PREFIX}/share/uhd") +set(CONFIG_PATH "${CMAKE_INSTALL_PREFIX}/${PKG_DATA_DIR}")  # construct site-package folder from install prefix  execute_process(COMMAND ${PYTHON_EXECUTABLE} -c diff --git a/host/utils/rfnoc/image_builder.py b/host/utils/rfnoc/image_builder.py index 0ed75dcc2..df3cfc3f1 100755 --- a/host/utils/rfnoc/image_builder.py +++ b/host/utils/rfnoc/image_builder.py @@ -449,7 +449,7 @@ def collect_module_paths(config_path):      :return: list of noc block directories      """      # rfnoc blocks -    result = [os.path.join(config_path, 'erfnoc', 'blocks')] +    result = [os.path.join(config_path, 'rfnoc', 'blocks')]      # additional OOT blocks      # TODO parse modules from external includes as well      return result @@ -675,7 +675,7 @@ def get_core_config_path(config_path):      """      returns the path where core configuration files are stored      """ -    return os.path.join(config_path, 'erfnoc', 'core') +    return os.path.join(config_path, 'rfnoc', 'core')  def generate_image_core_path(output_path, source):      """ diff --git a/host/utils/rfnoc_blocktool/templates/Makefile b/host/utils/rfnoc_blocktool/templates/Makefile index 25e61c05b..ca397bf7d 100644 --- a/host/utils/rfnoc_blocktool/templates/Makefile +++ b/host/utils/rfnoc_blocktool/templates/Makefile @@ -1,5 +1,5 @@  # -# Copyright 2019 Ettus Research, A National Instruments Company +# Copyright 2019 Ettus Research, A National Instruments Brand  #  # SPDX-License-Identifier: LGPL-3.0-or-later  # @@ -16,26 +16,26 @@ include $(BASE_DIR)/../tools/make/viv_sim_preamble.mak  # Design Specific  #-------------------------------------------------  # Include makefiles and sources for the DUT and its dependencies -include $(BASE_DIR)/../lib/erfnoc/core/Makefile.srcs -include $(BASE_DIR)/../lib/erfnoc/utils/Makefile.srcs +include $(BASE_DIR)/../lib/rfnoc/core/Makefile.srcs +include $(BASE_DIR)/../lib/rfnoc/utils/Makefile.srcs  include Makefile.srcs  DESIGN_SRCS += $(abspath ${"\\"}  $(RFNOC_CORE_SRCS) ${"\\"}  $(RFNOC_UTIL_SRCS) ${"\\"} -$(RFNOC_BLOCK_${config.module_name.upper()}_SRCS) ${"\\"} +$(RFNOC_BLOCK_${config['module_name'].upper()}_SRCS) ${"\\"}  )  #-------------------------------------------------  # Testbench Specific  #------------------------------------------------- -include $(BASE_DIR)/../sim/erfnoc/Makefile.srcs +include $(BASE_DIR)/../sim/rfnoc/Makefile.srcs -SIM_TOP = rfnoc_block_${config.module_name}_tb +SIM_TOP = rfnoc_block_${config['module_name']}_tb  SIM_SRCS = ${"\\"} -$(abspath rfnoc_block_${config.module_name}_tb.sv) ${"\\"} -$(SIM_ERFNOC_SRCS) +$(abspath rfnoc_block_${config['module_name']}_tb.sv) ${"\\"} +$(SIM_RFNOC_SRCS)  # MODELSIM_USER_DO = $(abspath wave.do) diff --git a/host/utils/rfnoc_blocktool/templates/Makefile.srcs b/host/utils/rfnoc_blocktool/templates/Makefile.srcs index f346007af..67fcb1ccc 100644 --- a/host/utils/rfnoc_blocktool/templates/Makefile.srcs +++ b/host/utils/rfnoc_blocktool/templates/Makefile.srcs @@ -7,7 +7,7 @@  ${'##################################################'}  # RFNoC Utility Sources  ${'##################################################'} -RFNOC_BLOCK_${config.module_name.upper()}_SRCS = $(abspath $(addprefix $(BASE_DIR)/../lib/erfnoc/blocks/${destination}/, ${"\\"} -rfnoc_block_${config.module_name}.v ${"\\"} -noc_shell_${config.module_name}.v ${"\\"} +RFNOC_BLOCK_${config['module_name'].upper()}_SRCS = $(abspath $(addprefix $(BASE_DIR)/../lib/rfnoc/blocks/${destination}/, ${"\\"} +rfnoc_block_${config['module_name']}.v ${"\\"} +noc_shell_${config['module_name']}.v ${"\\"}  )) diff --git a/host/utils/uhd_usrp_probe.cpp b/host/utils/uhd_usrp_probe.cpp index c35a5af23..7fd42941e 100644 --- a/host/utils/uhd_usrp_probe.cpp +++ b/host/utils/uhd_usrp_probe.cpp @@ -6,7 +6,6 @@  //  #include <uhd/device.hpp> -#include <uhd/device3.hpp>  #include <uhd/property_tree.hpp>  #include <uhd/types/ranges.hpp>  #include <uhd/types/sensors.hpp> diff --git a/mpm/include/mpm/CMakeLists.txt b/mpm/include/mpm/CMakeLists.txt index f3637c913..d4caff1c4 100644 --- a/mpm/include/mpm/CMakeLists.txt +++ b/mpm/include/mpm/CMakeLists.txt @@ -4,7 +4,6 @@  # SPDX-License-Identifier: GPL-3.0-or-later  #  install(FILES -    xbar_iface.hpp      exception.hpp      DESTINATION ${INCLUDE_DIR}/mpm  ) diff --git a/mpm/include/mpm/xbar_iface.hpp b/mpm/include/mpm/xbar_iface.hpp deleted file mode 100644 index bf4399593..000000000 --- a/mpm/include/mpm/xbar_iface.hpp +++ /dev/null @@ -1,60 +0,0 @@ -// -// Copyright 2017 Ettus Research, a National Instruments Company -// Copyright 2019 Ettus Research, a National Instruments Brand -// -// SPDX-License-Identifier: GPL-3.0-or-later -// -#pragma once -#include <boost/noncopyable.hpp> -#include <cstdint> -#include <memory> -#include <mutex> - -namespace mpm { - -/*! - * Crossbar route command - */ -using rfnoc_crossbar_cmd = struct rfnoc_crossbar_cmd -{ -    /*! destination address */ -    uint8_t dest_addr; -    /*! destination port */ -    uint8_t dest_port; -}; - -#define RFNCBWROUTIOC _IOW('R', 1, struct rfnoc_crossbar_cmd) -#define RFNCDELROUTIOC _IOW('D', 1, struct rfnoc_crossbar_cmd) - -/*! - * Crossbar interface class holding a crossbar context - */ -class xbar_iface : boost::noncopyable -{ -public: -    // use static mutex! lock_guard -    using sptr = std::shared_ptr<xbar_iface>; -    static sptr make(const std::string& device); -    void set_route(uint8_t dst_addr, uint8_t dst_port); -    void del_route(uint8_t dst_addr, uint8_t dst_port); -    ~xbar_iface(); -    xbar_iface(const std::string& device); - -private: -    static std::mutex _lock; -    int _fd; -}; -} // namespace mpm - - -#ifdef LIBMPM_PYTHON -void export_xbar(py::module& top_module) -{ -    auto m = top_module.def_submodule("xbar"); - -    py::class_<mpm::xbar_iface, std::shared_ptr<mpm::xbar_iface>>(m, "xbar") -        .def(py::init(&mpm::xbar_iface::make)) -        .def("set_route", &mpm::xbar_iface::set_route) -        .def("del_route", &mpm::xbar_iface::del_route); -} -#endif diff --git a/mpm/lib/CMakeLists.txt b/mpm/lib/CMakeLists.txt index 82a5d8e16..940a23138 100644 --- a/mpm/lib/CMakeLists.txt +++ b/mpm/lib/CMakeLists.txt @@ -20,7 +20,6 @@ endif(ENABLE_MYKONOS)  USRP_PERIPHS_ADD_OBJECT(periphs      exception.cpp -    xbar_iface.cpp      ${UHD_HOST_ROOT}/lib/exception.cpp  ) diff --git a/mpm/lib/xbar_iface.cpp b/mpm/lib/xbar_iface.cpp deleted file mode 100644 index 05d1e2053..000000000 --- a/mpm/lib/xbar_iface.cpp +++ /dev/null @@ -1,52 +0,0 @@ -// -// Copyright 2017 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#include "mpm/xbar_iface.hpp" -#include <fcntl.h> -#include <mpm/exception.hpp> -#include <sys/ioctl.h> -#include <boost/format.hpp> - -using namespace mpm; - -std::mutex xbar_iface::_lock; // Initialize lock for all objects - -xbar_iface::xbar_iface(const std::string& device) -{ -    _fd = open(device.c_str(), O_RDWR); -} - -xbar_iface::~xbar_iface() -{ -    close(_fd); -} - -void xbar_iface::set_route(uint8_t dst_addr, uint8_t dst_port) -{ -    std::lock_guard<std::mutex> lock(_lock); -    rfnoc_crossbar_cmd cmd = {.dest_addr = dst_addr, .dest_port = dst_port}; -    int err                = ioctl(_fd, RFNCBWROUTIOC, &cmd); -    if (err < 0) { -        throw mpm::os_error( -            str(boost::format("setting crossbar route failed! Error: %d") % err)); -    } -} - -void xbar_iface::del_route(uint8_t dst_addr, uint8_t dst_port) -{ -    std::lock_guard<std::mutex> lock(_lock); -    rfnoc_crossbar_cmd cmd = {.dest_addr = dst_addr, .dest_port = dst_port}; -    int err                = ioctl(_fd, RFNCDELROUTIOC, &cmd); -    if (err < 0) { -        throw mpm::os_error( -            str(boost::format("deleting crossbar route failed! Error: %d") % err)); -    } -} - -xbar_iface::sptr xbar_iface::make(const std::string& device) -{ -    return std::make_shared<xbar_iface>(device); -} diff --git a/mpm/python/pyusrp_periphs/e31x/pyusrp_periphs.cpp b/mpm/python/pyusrp_periphs/e31x/pyusrp_periphs.cpp index b7971407c..ffd32edbf 100644 --- a/mpm/python/pyusrp_periphs/e31x/pyusrp_periphs.cpp +++ b/mpm/python/pyusrp_periphs/e31x/pyusrp_periphs.cpp @@ -18,13 +18,11 @@ PYBIND11_DECLARE_HOLDER_TYPE(T, boost::shared_ptr<T>);  #include <mpm/dboards/e31x_db_manager.hpp>  #include <mpm/spi/spi_python.hpp>  #include <mpm/types/types_python.hpp> -#include <mpm/xbar_iface.hpp>  PYBIND11_MODULE(libpyusrp_periphs, m)  {      export_types(m);      export_spi(m); -    export_xbar(m);      export_catalina(m);      export_e31x_db(m);  } diff --git a/mpm/python/pyusrp_periphs/e320/pyusrp_periphs.cpp b/mpm/python/pyusrp_periphs/e320/pyusrp_periphs.cpp index 74a3647db..2a3c01064 100644 --- a/mpm/python/pyusrp_periphs/e320/pyusrp_periphs.cpp +++ b/mpm/python/pyusrp_periphs/e320/pyusrp_periphs.cpp @@ -18,13 +18,11 @@ PYBIND11_DECLARE_HOLDER_TYPE(T, boost::shared_ptr<T>);  #include <mpm/dboards/neon_manager.hpp>  #include <mpm/spi/spi_python.hpp>  #include <mpm/types/types_python.hpp> -#include <mpm/xbar_iface.hpp>  PYBIND11_MODULE(libpyusrp_periphs, m)  {      export_types(m);      export_spi(m); -    export_xbar(m);      export_catalina(m);      export_neon(m);  } diff --git a/mpm/python/pyusrp_periphs/n3xx/pyusrp_periphs.cpp b/mpm/python/pyusrp_periphs/n3xx/pyusrp_periphs.cpp index d4c430f72..4719f486e 100644 --- a/mpm/python/pyusrp_periphs/n3xx/pyusrp_periphs.cpp +++ b/mpm/python/pyusrp_periphs/n3xx/pyusrp_periphs.cpp @@ -19,7 +19,6 @@ PYBIND11_DECLARE_HOLDER_TYPE(T, boost::shared_ptr<T>);  #include <mpm/i2c/i2c_python.hpp>  #include <mpm/spi/spi_python.hpp>  #include <mpm/types/types_python.hpp> -#include <mpm/xbar_iface.hpp>  PYBIND11_MODULE(libpyusrp_periphs, m)  { @@ -27,6 +26,5 @@ PYBIND11_MODULE(libpyusrp_periphs, m)      export_spi(m);      export_i2c(m);      export_mykonos(m); -    export_xbar(m);      export_magnesium(m);  }  | 
