diff options
author | Virendra Kakade <virendra.kakade@ni.com> | 2019-11-22 17:46:41 -0600 |
---|---|---|
committer | Martin Braun <martin.braun@ettus.com> | 2019-11-26 12:21:35 -0800 |
commit | c7ee53d04123044bab1f7ad61cce742558751c66 (patch) | |
tree | 9638364037510667fe1a6fecfe2193b6394df42f /host/lib | |
parent | 4d319c244aae601e4efc1780fa10ea1290789557 (diff) | |
download | uhd-c7ee53d04123044bab1f7ad61cce742558751c66.tar.gz uhd-c7ee53d04123044bab1f7ad61cce742558751c66.tar.bz2 uhd-c7ee53d04123044bab1f7ad61cce742558751c66.zip |
x300: pcie manager updates
Signed-off-by: Virendra Kakade <virendra.kakade@ni.com>
Diffstat (limited to 'host/lib')
-rw-r--r-- | host/lib/usrp/x300/x300_pcie_mgr.cpp | 199 | ||||
-rw-r--r-- | host/lib/usrp/x300/x300_pcie_mgr.hpp | 23 |
2 files changed, 93 insertions, 129 deletions
diff --git a/host/lib/usrp/x300/x300_pcie_mgr.cpp b/host/lib/usrp/x300/x300_pcie_mgr.cpp index 8466a5174..41d9407f9 100644 --- a/host/lib/usrp/x300/x300_pcie_mgr.cpp +++ b/host/lib/usrp/x300/x300_pcie_mgr.cpp @@ -16,11 +16,17 @@ #include <uhd/utils/log.hpp> #include <uhd/utils/static.hpp> #include <uhdlib/rfnoc/device_id.hpp> +#include <uhdlib/transport/inline_io_service.hpp> #include <uhdlib/transport/nirio_link.hpp> #include <uhdlib/usrp/cores/i2c_core_100_wb32.hpp> #include <unordered_map> #include <mutex> +using namespace uhd; +using namespace uhd::transport; +using namespace uhd::usrp::x300; +using namespace uhd::niusrprio; + namespace { //uint32_t extract_sid_from_pkt(void* pkt, size_t) @@ -42,20 +48,48 @@ constexpr size_t PCIE_TX_DATA_FRAME_SIZE = 4096; // bytes constexpr size_t PCIE_TX_DATA_NUM_FRAMES = 4096; constexpr size_t PCIE_MSG_FRAME_SIZE = 256; // bytes constexpr size_t PCIE_MSG_NUM_FRAMES = 64; -constexpr size_t PCIE_MAX_MUXED_CTRL_XPORTS = 32; -constexpr size_t PCIE_MAX_MUXED_ASYNC_XPORTS = 4; constexpr size_t PCIE_MAX_CHANNELS = 6; -constexpr size_t MAX_RATE_PCIE = 800000000; // bytes/s +// constexpr size_t MAX_RATE_PCIE = 800000000; // bytes/s + + +//! Get default send/recv num frames and frame size per link type +link_params_t get_default_link_params(const link_type_t link_type) +{ + link_params_t link_params; + switch (link_type) { + case link_type_t::CTRL: + link_params.send_frame_size = PCIE_MSG_FRAME_SIZE; + link_params.recv_frame_size = PCIE_MSG_FRAME_SIZE; + link_params.num_send_frames = PCIE_MSG_NUM_FRAMES; + link_params.num_recv_frames = PCIE_MSG_NUM_FRAMES; + break; + case link_type_t::TX_DATA: + link_params.send_frame_size = PCIE_TX_DATA_FRAME_SIZE; + link_params.recv_frame_size = PCIE_MSG_FRAME_SIZE; + link_params.num_send_frames = PCIE_TX_DATA_NUM_FRAMES; + link_params.num_recv_frames = PCIE_MSG_NUM_FRAMES; + break; + case link_type_t::RX_DATA: + link_params.send_frame_size = PCIE_MSG_FRAME_SIZE; + link_params.recv_frame_size = PCIE_RX_DATA_FRAME_SIZE; + link_params.num_send_frames = PCIE_MSG_NUM_FRAMES; + link_params.num_recv_frames = PCIE_RX_DATA_NUM_FRAMES; + break; + default: + UHD_THROW_INVALID_CODE_PATH(); + } + link_params.recv_buff_size = + link_params.num_recv_frames * link_params.recv_frame_size; + link_params.send_buff_size = + link_params.num_send_frames * link_params.send_frame_size; + return link_params; } +} // namespace + uhd::wb_iface::sptr x300_make_ctrl_iface_pcie( uhd::niusrprio::niriok_proxy::sptr drv_proxy, bool enable_errors = true); -using namespace uhd; -using namespace uhd::transport; -using namespace uhd::usrp::x300; -using namespace uhd::niusrprio; - // We need a zpu xport registry to ensure synchronization between the static // finder method and the instances of the x300_impl class. typedef std::unordered_map<std::string, std::weak_ptr<uhd::wb_iface>> @@ -272,124 +306,59 @@ void pcie_manager::release_ctrl_iface(std::function<void(void)>&& release_fn) } uint32_t pcie_manager::allocate_pcie_dma_chan( - const rfnoc::sep_id_t& /*remote_epid*/, const link_type_t /*link_type*/) + 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::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(); - - //if (_dma_chan_pool.count(raw_sid) == 0) { - //size_t channel = _dma_chan_pool.size() + FIRST_DATA_CHANNEL; - //if (channel > PCIE_MAX_CHANNELS) { - //throw uhd::runtime_error( - //"Trying to allocate more DMA channels than are available"); - //} - //_dma_chan_pool[raw_sid] = channel; - //UHD_LOGGER_DEBUG("X300") - //<< "Assigning PCIe DMA channel " << _dma_chan_pool[raw_sid] << " to SID " - //<< tx_sid.to_pp_string_hex(); - //} - - //return _dma_chan_pool[raw_sid]; - //} -} + constexpr uint32_t CTRL_CHANNEL = 0; + constexpr uint32_t FIRST_DATA_CHANNEL = 1; + + std::lock_guard<std::mutex> l(_dma_chan_mutex); + uint32_t dma_chan = CTRL_CHANNEL; + if (link_type == link_type_t::CTRL) { + if (_dma_chan_pool.count(CTRL_CHANNEL)) { + throw uhd::runtime_error("[X300] Cannot reallocate PCIe control channel!"); + } + } else { + dma_chan = FIRST_DATA_CHANNEL; + while (_dma_chan_pool.count(dma_chan)) { + dma_chan++; + } + if (dma_chan >= PCIE_MAX_CHANNELS) { + throw uhd::runtime_error( + "Trying to allocate more DMA channels than are available"); + } + } -muxed_zero_copy_if::sptr pcie_manager::make_muxed_pcie_msg_xport( - uint32_t dma_channel_num, size_t max_muxed_ports) -{ - throw uhd::not_implemented_error("NI-RIO links not yet implemented!"); - //zero_copy_xport_params buff_args; - //buff_args.send_frame_size = PCIE_MSG_FRAME_SIZE; - //buff_args.recv_frame_size = PCIE_MSG_FRAME_SIZE; - //buff_args.num_send_frames = PCIE_MSG_NUM_FRAMES; - //buff_args.num_recv_frames = PCIE_MSG_NUM_FRAMES; - - //zero_copy_if::sptr base_xport = nirio_zero_copy::make( - //_rio_fpga_interface, dma_channel_num, buff_args, uhd::device_addr_t()); - //return muxed_zero_copy_if::make(base_xport, extract_sid_from_pkt, max_muxed_ports); + _dma_chan_pool[dma_chan] = remote_epid; + UHD_LOG_DEBUG("X300", + "Assigning DMA channel " << dma_chan << " to remote EPID " << remote_epid); + return dma_chan; } -both_links_t pcie_manager::get_links(link_type_t /*link_type*/, +both_links_t pcie_manager::get_links(link_type_t link_type, const rfnoc::device_id_t local_device_id, const rfnoc::sep_id_t& /*local_epid*/, - const rfnoc::sep_id_t& /*remote_epid*/, - const device_addr_t& /*link_args*/) + const rfnoc::sep_id_t& remote_epid, + const device_addr_t& link_args) { - throw uhd::not_implemented_error("NI-RIO links not yet implemented!"); if (local_device_id != _local_device_id) { throw uhd::runtime_error( std::string("[X300] Cannot create NI-RIO link through local device ID ") + 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::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; - - //// Router config word is: - //// - Upper 16 bits: Destination address (e.g. 0.0) - //// - Lower 16 bits: DMA channel - //uint32_t router_config_word = (xports.recv_sid.get_dst() << 16) | dma_channel_num; - //_rio_fpga_interface->get_kernel_proxy()->poke(PCIE_ROUTER_REG(0), router_config_word); - - //// For the nirio transport, buffer size is depends on the frame size and num - //// frames - //xports.recv_buff_size = - //xports.recv->get_num_recv_frames() * xports.recv->get_recv_frame_size(); - //xports.send_buff_size = - //xports.send->get_num_send_frames() * xports.send->get_send_frame_size(); - - //return xports; + + const uint32_t dma_channel_num = allocate_pcie_dma_chan(remote_epid, link_type); + // Note: The nirio_link object's factory has a lot of code for sanity + // checking the link params, and merging the link_args with the default + // link_params, so we use that. + link_params_t link_params = get_default_link_params(link_type); + + // PCIe: Lossless, and little endian + size_t recv_buff_size, send_buff_size; + auto link = nirio_link::make(_rio_fpga_interface, + dma_channel_num, + link_params, + link_args); + + return std::make_tuple(link, send_buff_size, link, recv_buff_size, false /*not lossy*/); } diff --git a/host/lib/usrp/x300/x300_pcie_mgr.hpp b/host/lib/usrp/x300/x300_pcie_mgr.hpp index 146a2ff93..f0a5ed911 100644 --- a/host/lib/usrp/x300/x300_pcie_mgr.hpp +++ b/host/lib/usrp/x300/x300_pcie_mgr.hpp @@ -16,6 +16,7 @@ #include <uhd/types/direction.hpp> #include <uhdlib/rfnoc/rfnoc_common.hpp> #include <uhdlib/transport/links.hpp> +#include <mutex> namespace uhd { namespace usrp { namespace x300 { @@ -67,26 +68,20 @@ private: * * Note the SID is always the transmit SID (i.e. from host to device). */ - uint32_t allocate_pcie_dma_chan( - const uhd::rfnoc::sep_id_t& remote_epid, const uhd::transport::link_type_t link_type); - - uhd::transport::muxed_zero_copy_if::sptr make_muxed_pcie_msg_xport( - uint32_t dma_channel_num, size_t max_muxed_ports); + uint32_t allocate_pcie_dma_chan(const uhd::rfnoc::sep_id_t& remote_epid, + const uhd::transport::link_type_t link_type); + /*** Attributes **********************************************************/ const x300_device_args_t _args; const std::string _resource; - uhd::niusrprio::niusrprio_session::sptr _rio_fpga_interface; + uhd::rfnoc::device_id_t _local_device_id; - //! Maps Remote EPID -> DMA channel - std::map<uhd::rfnoc::sep_id_t, uint32_t> _dma_chan_pool; - - //! Control transport for one PCIe connection - uhd::transport::muxed_zero_copy_if::sptr _ctrl_dma_xport; - //! Async message transport - uhd::transport::muxed_zero_copy_if::sptr _async_msg_dma_xport; + //! Maps Remote DMA channel -> EPID + std::unordered_map<uint32_t, uhd::rfnoc::sep_id_t> _dma_chan_pool; - uhd::rfnoc::device_id_t _local_device_id; + //! Locks access to the map + std::mutex _dma_chan_mutex; }; }}} // namespace uhd::usrp::x300 |