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 */ |