diff options
| author | Martin Braun <martin.braun@ettus.com> | 2019-08-19 17:14:11 -0700 | 
|---|---|---|
| committer | Martin Braun <martin.braun@ettus.com> | 2019-11-26 11:49:40 -0800 | 
| commit | 4c6ee083ef13184ba828d73b9dd2a95d7fa5453f (patch) | |
| tree | 3364e7e147ed229732fca66282323c65d5de4102 /host/lib/include/uhdlib | |
| parent | a4274c19ebb42db112aa68a26fa499a52b9dd103 (diff) | |
| download | uhd-4c6ee083ef13184ba828d73b9dd2a95d7fa5453f.tar.gz uhd-4c6ee083ef13184ba828d73b9dd2a95d7fa5453f.tar.bz2 uhd-4c6ee083ef13184ba828d73b9dd2a95d7fa5453f.zip  | |
rfnoc: Add nirio_link link object
Diffstat (limited to 'host/lib/include/uhdlib')
| -rw-r--r-- | host/lib/include/uhdlib/transport/nirio_link.hpp | 210 | 
1 files changed, 210 insertions, 0 deletions
diff --git a/host/lib/include/uhdlib/transport/nirio_link.hpp b/host/lib/include/uhdlib/transport/nirio_link.hpp new file mode 100644 index 000000000..055874146 --- /dev/null +++ b/host/lib/include/uhdlib/transport/nirio_link.hpp @@ -0,0 +1,210 @@ +// +// Copyright 2019 Ettus Research, a National Instruments Brand +// +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#ifndef INCLUDED_UHD_TRANSPORT_NIRIO_LINK_HPP +#define INCLUDED_UHD_TRANSPORT_NIRIO_LINK_HPP + +#include <uhd/config.hpp> +#include <uhd/transport/buffer_pool.hpp> +#include <uhd/transport/nirio/nirio_fifo.h> +#include <uhd/transport/nirio/niriok_proxy.h> +#include <uhd/transport/nirio/niusrprio_session.h> +#include <uhd/types/device_addr.hpp> +#include <uhdlib/transport/adapter_info.hpp> +#include <uhdlib/transport/link_base.hpp> +#include <uhdlib/transport/links.hpp> +#include <memory> +#include <vector> + +namespace uhd { namespace transport { + +using fifo_data_t = uint64_t; + +/*! NI-RIO frame_buff + * + * NI-RIO internally manages the memory, so these frame_buff objects just need + * a way of internally manipulating the _data pointer + */ +class nirio_frame_buff : public frame_buff +{ +public: +    nirio_frame_buff() +    { +        _data = nullptr; +    } + +    fifo_data_t** get_fifo_ptr_ref() +    { +        return reinterpret_cast<fifo_data_t**>(&_data); +    }; +}; + +class nirio_adapter_info : public adapter_info +{ +public: +    nirio_adapter_info(const std::string& resource) : _resource(resource) {} + +    ~nirio_adapter_info() {} + +    std::string to_string() +    { +        return std::string("NIRIO:") + _resource; +    } + +    bool operator==(const nirio_adapter_info& rhs) const +    { +        return (_resource == rhs._resource); +    } + +private: +    const std::string _resource; +}; + +/*! Link object to talking to NI-RIO USRPs (X310 variants using PCIe) + * + * \b Note: This link cannot release frame buffers out of order, which means it + *          can't be used with an IO service that does that. + */ +class nirio_link : public recv_link_base<nirio_link>, public send_link_base<nirio_link> +{ +public: +    using sptr = std::shared_ptr<nirio_link>; + +    ~nirio_link(); + +    /*! Make a new NI-RIO link. +     * +     * \param addr a string representing the destination address +     * \param port a string representing the destination port +     * \param params Values for frame sizes, num frames, and buffer sizes +     * \param[out] recv_socket_buff_size Returns the recv socket buffer size +     * \param[out] send_socket_buff_size Returns the send socket buffer size +     */ +    static sptr make(uhd::niusrprio::niusrprio_session::sptr fpga_session, +        const uint32_t instance, +        const link_params_t& params, +        const uhd::device_addr_t& hints); + +    /*! +     * Get the physical adapter ID used for this link +     */ +    adapter_id_t get_send_adapter_id() const +    { +        return _adapter_id; +    } + +    /*! +     * Get the physical adapter ID used for this link +     */ +    adapter_id_t get_recv_adapter_id() const +    { +        return _adapter_id; +    } + +private: +    using recv_link_base_t = recv_link_base<nirio_link>; +    using send_link_base_t = send_link_base<nirio_link>; + +    // Friend declarations to allow base classes to call private methods +    friend recv_link_base_t; +    friend send_link_base_t; + +    nirio_link(uhd::niusrprio::niusrprio_session::sptr fpga_session, +        uint32_t instance, +        const link_params_t& params); + +    /************************************************************************** +     * NI-RIO specific helpers +     *************************************************************************/ +    void _flush_rx_buff(); + +    void _wait_until_stream_ready(); + +    /************************************************************************** +     * recv_link/send_link API +     *************************************************************************/ +    // Methods called by recv_link_base +    UHD_FORCE_INLINE size_t get_recv_buff_derived(frame_buff& buff, int32_t timeout_ms) +    { +        using namespace uhd::niusrprio; +        nirio_status status    = 0; +        size_t elems_acquired  = 0; +        size_t elems_remaining = 0; +        // This will modify the data pointer in buff if successful: +        fifo_data_t** data_ptr = static_cast<nirio_frame_buff&>(buff).get_fifo_ptr_ref(); +        nirio_status_chain(_recv_fifo->acquire(*data_ptr, +                               _link_params.recv_frame_size / sizeof(fifo_data_t), +                               static_cast<uint32_t>(timeout_ms * 1000), +                               elems_acquired, +                               elems_remaining), +            status); +        const size_t length = elems_acquired * sizeof(fifo_data_t); + +        if (nirio_status_not_fatal(status)) { +            return length; +        } else if (status == NiRio_Status_CommunicationTimeout) { +            nirio_status_to_exception(status, "NI-RIO PCIe data transfer failed."); +        } +        return 0; // zero for timeout or error. +    } + +    UHD_FORCE_INLINE void release_recv_buff_derived(frame_buff& /*buff*/) +    { +        _recv_fifo->release(_link_params.recv_frame_size / sizeof(fifo_data_t)); +    } + +    // Methods called by send_link_base +    UHD_FORCE_INLINE bool get_send_buff_derived(frame_buff& buff, int32_t timeout_ms) +    { +        using namespace uhd::niusrprio; +        nirio_status status    = 0; +        size_t elems_acquired  = 0; +        size_t elems_remaining = 0; +        // This will modify the data pointer in buff if successful: +        fifo_data_t** data_ptr = static_cast<nirio_frame_buff&>(buff).get_fifo_ptr_ref(); +        nirio_status_chain(_send_fifo->acquire(*data_ptr, +                               _link_params.send_frame_size / sizeof(fifo_data_t), +                               static_cast<uint32_t>(timeout_ms * 1000), +                               elems_acquired, +                               elems_remaining), +            status); +        // const size_t length = elems_acquired * sizeof(fifo_data_t); + +        if (nirio_status_not_fatal(status)) { +            return true; +        } else if (status == NiRio_Status_CommunicationTimeout) { +            nirio_status_to_exception(status, "NI-RIO PCIe data transfer failed."); +        } +        return false; +    } + +    UHD_FORCE_INLINE void release_send_buff_derived(frame_buff& /*buff*/) +    { +        _send_fifo->release(_link_params.send_frame_size / sizeof(fifo_data_t)); +    } + +    /************************************************************************** +     * Private attributes +     *************************************************************************/ +    //! Reference to the NI-RIO session +    niusrprio::niusrprio_session::sptr _fpga_session; +    //! DMA channel index +    const uint32_t _fifo_instance; +    //! Recv and send FIFO objects +    uhd::niusrprio::nirio_fifo<fifo_data_t>::sptr _recv_fifo, _send_fifo; + +    const link_params_t _link_params; + +    std::vector<nirio_frame_buff> _recv_buffs; +    std::vector<nirio_frame_buff> _send_buffs; + +    adapter_id_t _adapter_id; +}; + +}} // namespace uhd::transport + + +#endif /* INCLUDED_UHD_TRANSPORT_NIRIO_LINK_HPP */  | 
