From 2f7f873b7f0299ec1f8ae7c752246cb2f1608c0a Mon Sep 17 00:00:00 2001 From: Michael West Date: Wed, 29 Mar 2017 13:24:32 -0700 Subject: X300: Dual channel TX performance improvements --- host/lib/usrp/x300/x300_impl.cpp | 14 ++++++++++---- host/lib/usrp/x300/x300_impl.hpp | 2 ++ 2 files changed, 12 insertions(+), 4 deletions(-) (limited to 'host/lib/usrp/x300') diff --git a/host/lib/usrp/x300/x300_impl.cpp b/host/lib/usrp/x300/x300_impl.cpp index 4f3870357..934e2eaa5 100644 --- a/host/lib/usrp/x300/x300_impl.cpp +++ b/host/lib/usrp/x300/x300_impl.cpp @@ -511,6 +511,8 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr) eth_addrs.push_back(eth0_addr); mb.next_src_addr = 0; //Host source address for blocks + mb.next_tx_src_addr = 0; + mb.next_rx_src_addr = 0; if (dev_addr.has_key("second_addr")) { std::string eth1_addr = dev_addr["second_addr"]; @@ -1136,12 +1138,16 @@ uhd::both_xports_t x300_impl::make_transport( } else if (mb.xport_path == "eth") { // Decide on the IP/Interface pair based on the endpoint index - std::string interface_addr = mb.eth_conns[mb.next_src_addr].addr; + size_t &next_src_addr = + xport_type == TX_DATA ? mb.next_tx_src_addr : + xport_type == RX_DATA ? mb.next_rx_src_addr : + mb.next_src_addr; + std::string interface_addr = mb.eth_conns[next_src_addr].addr; const uint32_t xbar_src_addr = - mb.next_src_addr==0 ? X300_SRC_ADDR0 : X300_SRC_ADDR1; + next_src_addr==0 ? X300_SRC_ADDR0 : X300_SRC_ADDR1; const uint32_t xbar_src_dst = - mb.eth_conns[mb.next_src_addr].type==X300_IFACE_ETH0 ? X300_XB_DST_E0 : X300_XB_DST_E1; - mb.next_src_addr = (mb.next_src_addr + 1) % mb.eth_conns.size(); + mb.eth_conns[next_src_addr].type==X300_IFACE_ETH0 ? X300_XB_DST_E0 : X300_XB_DST_E1; + next_src_addr = (next_src_addr + 1) % mb.eth_conns.size(); xports.send_sid = this->allocate_sid(mb, address, xbar_src_addr, xbar_src_dst); xports.recv_sid = xports.send_sid.reversed(); diff --git a/host/lib/usrp/x300/x300_impl.hpp b/host/lib/usrp/x300/x300_impl.hpp index 14120bd1f..8f4f81156 100644 --- a/host/lib/usrp/x300/x300_impl.hpp +++ b/host/lib/usrp/x300/x300_impl.hpp @@ -162,6 +162,8 @@ private: std::vector eth_conns; size_t next_src_addr; + size_t next_tx_src_addr; + size_t next_rx_src_addr; // Discover the ethernet connections per motherboard void discover_eth(const uhd::usrp::mboard_eeprom_t mb_eeprom, -- cgit v1.2.3 From 0b403340c3e924b642ba72679a8a1bfa23bbfd4c Mon Sep 17 00:00:00 2001 From: Michael West Date: Wed, 14 Jun 2017 10:22:25 -0700 Subject: X300: Implement single DMA channel for all async messages --- host/lib/usrp/device3/device3_impl.hpp | 4 +-- host/lib/usrp/device3/device3_io_impl.cpp | 2 +- host/lib/usrp/x300/x300_impl.cpp | 49 ++++++++++++++++++++++++------- host/lib/usrp/x300/x300_impl.hpp | 5 +++- 4 files changed, 45 insertions(+), 15 deletions(-) (limited to 'host/lib/usrp/x300') diff --git a/host/lib/usrp/device3/device3_impl.hpp b/host/lib/usrp/device3/device3_impl.hpp index 22c93f25f..043379108 100644 --- a/host/lib/usrp/device3/device3_impl.hpp +++ b/host/lib/usrp/device3/device3_impl.hpp @@ -56,9 +56,9 @@ public: //! The purpose of a transport enum xport_type_t { CTRL = 0, + ASYNC_MSG, TX_DATA, - RX_DATA, - ASYNC_TX_MSG + RX_DATA }; enum xport_t {AXI, ETH, PCIE}; diff --git a/host/lib/usrp/device3/device3_io_impl.cpp b/host/lib/usrp/device3/device3_io_impl.cpp index dc4aacff8..198ee4022 100644 --- a/host/lib/usrp/device3/device3_io_impl.cpp +++ b/host/lib/usrp/device3/device3_io_impl.cpp @@ -773,7 +773,7 @@ tx_streamer::sptr device3_impl::get_tx_stream(const uhd::stream_args_t &args_) uhd::sid_t stream_address = blk_ctrl->get_address(block_port); UHD_STREAMER_LOG() << "[TX Streamer] creating tx stream " << tx_hints.to_string() << std::endl; both_xports_t xport = make_transport(stream_address, TX_DATA, tx_hints); - both_xports_t async_xport = make_transport(stream_address, ASYNC_TX_MSG, device_addr_t("")); + both_xports_t async_xport = make_transport(stream_address, ASYNC_MSG, device_addr_t("")); UHD_STREAMER_LOG() << std::hex << "[TX Streamer] data_sid = " << xport.send_sid << std::dec << std::endl; // To calculate the max number of samples per packet, we assume the maximum header length diff --git a/host/lib/usrp/x300/x300_impl.cpp b/host/lib/usrp/x300/x300_impl.cpp index 934e2eaa5..71cb7f341 100644 --- a/host/lib/usrp/x300/x300_impl.cpp +++ b/host/lib/usrp/x300/x300_impl.cpp @@ -1039,9 +1039,12 @@ x300_impl::~x300_impl(void) uint32_t x300_impl::mboard_members_t::allocate_pcie_dma_chan(const uhd::sid_t &tx_sid, const xport_type_t xport_type) { static const uint32_t CTRL_CHANNEL = 0; - static const uint32_t FIRST_DATA_CHANNEL = 1; + static const uint32_t ASYNC_MSG_CHANNEL = 1; + static const uint32_t FIRST_DATA_CHANNEL = 2; if (xport_type == CTRL) { return CTRL_CHANNEL; + } else if (xport_type == 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(); @@ -1063,6 +1066,24 @@ static uint32_t extract_sid_from_pkt(void* pkt, size_t) { return uhd::sid_t(uhd::wtohx(static_cast(pkt)[1])).get_dst(); } +static uhd::transport::muxed_zero_copy_if::sptr make_muxed_pcie_msg_xport +( + uhd::niusrprio::niusrprio_session::sptr rio_fpga_interface, + uint32_t dma_channel_num, + size_t max_muxed_ports +) { + zero_copy_xport_params buff_args; + buff_args.send_frame_size = X300_PCIE_MSG_FRAME_SIZE; + buff_args.recv_frame_size = X300_PCIE_MSG_FRAME_SIZE; + buff_args.num_send_frames = X300_PCIE_MSG_NUM_FRAMES * max_muxed_ports; + buff_args.num_recv_frames = X300_PCIE_MSG_NUM_FRAMES * max_muxed_ports; + + 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); +} + uhd::both_xports_t x300_impl::make_transport( const uhd::sid_t &address, const xport_type_t xport_type, @@ -1084,19 +1105,25 @@ uhd::both_xports_t x300_impl::make_transport( if (not mb.ctrl_dma_xport) { //One underlying DMA channel will handle //all control traffic - zero_copy_xport_params ctrl_buff_args; - ctrl_buff_args.send_frame_size = X300_PCIE_MSG_FRAME_SIZE; - ctrl_buff_args.recv_frame_size = X300_PCIE_MSG_FRAME_SIZE; - ctrl_buff_args.num_send_frames = X300_PCIE_MSG_NUM_FRAMES * X300_PCIE_MAX_MUXED_XPORTS; - ctrl_buff_args.num_recv_frames = X300_PCIE_MSG_NUM_FRAMES * X300_PCIE_MAX_MUXED_XPORTS; - - zero_copy_if::sptr base_xport = nirio_zero_copy::make( - mb.rio_fpga_interface, dma_channel_num, - ctrl_buff_args, uhd::device_addr_t()); - mb.ctrl_dma_xport = muxed_zero_copy_if::make(base_xport, extract_sid_from_pkt, X300_PCIE_MAX_MUXED_XPORTS); + mb.ctrl_dma_xport = make_muxed_pcie_msg_xport( + mb.rio_fpga_interface, + dma_channel_num, + X300_PCIE_MAX_MUXED_CTRL_XPORTS); } //Create a virtual control transport xports.recv = mb.ctrl_dma_xport->make_stream(xports.recv_sid.get_dst()); + } else if (xport_type == ASYNC_MSG) { + //Transport for async message stream + if (not mb.async_msg_dma_xport) { + //One underlying DMA channel will handle + //all async message traffic + mb.async_msg_dma_xport = make_muxed_pcie_msg_xport( + mb.rio_fpga_interface, + dma_channel_num, + X300_PCIE_MAX_MUXED_ASYNC_XPORTS); + } + //Create a virtual async message transport + xports.recv = mb.async_msg_dma_xport->make_stream(xports.recv_sid.get_dst()); } else { //Transport for data stream default_buff_args.send_frame_size = diff --git a/host/lib/usrp/x300/x300_impl.hpp b/host/lib/usrp/x300/x300_impl.hpp index 8f4f81156..982369396 100644 --- a/host/lib/usrp/x300/x300_impl.hpp +++ b/host/lib/usrp/x300/x300_impl.hpp @@ -62,7 +62,8 @@ static const size_t X300_PCIE_TX_DATA_NUM_FRAMES = 4096; static const size_t X300_PCIE_MSG_FRAME_SIZE = 256; //bytes static const size_t X300_PCIE_MSG_NUM_FRAMES = 64; static const size_t X300_PCIE_MAX_CHANNELS = 6; -static const size_t X300_PCIE_MAX_MUXED_XPORTS = 32; +static const size_t X300_PCIE_MAX_MUXED_CTRL_XPORTS = 32; +static const size_t X300_PCIE_MAX_MUXED_ASYNC_XPORTS = 4; static const size_t X300_10GE_DATA_FRAME_MAX_SIZE = 8000; // CHDR packet size in bytes static const size_t X300_1GE_DATA_FRAME_MAX_SIZE = 1472; // CHDR packet size in bytes @@ -205,6 +206,8 @@ private: std::map _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; /*! Allocate or return a previously allocated PCIe channel pair * -- cgit v1.2.3 From e1b686318fab1cb2b11542c28d82d810d1fc63a2 Mon Sep 17 00:00:00 2001 From: michael-west Date: Mon, 8 May 2017 11:48:45 -0700 Subject: X300: Fix DAC sync --- host/lib/usrp/x300/x300_adc_dac_utils.cpp | 47 ----------------------------- host/lib/usrp/x300/x300_radio_ctrl_impl.cpp | 20 ++++++++---- 2 files changed, 14 insertions(+), 53 deletions(-) (limited to 'host/lib/usrp/x300') diff --git a/host/lib/usrp/x300/x300_adc_dac_utils.cpp b/host/lib/usrp/x300/x300_adc_dac_utils.cpp index 6fd0ca50b..a6815286e 100644 --- a/host/lib/usrp/x300/x300_adc_dac_utils.cpp +++ b/host/lib/usrp/x300/x300_adc_dac_utils.cpp @@ -20,53 +20,6 @@ using namespace uhd::usrp::x300; -/*********************************************************************** - * DAC: Reset and synchronization operations - **********************************************************************/ - -void x300_impl::synchronize_dacs(const std::vector& 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. - - //Reinitialize and resync all DACs - for (size_t i = 0; i < radios.size(); i++) { - radios[i]->dac->reset(); - } - - //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]->ctrl->peek64(uhd::usrp::radio::RB64_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 + uncertaintly to the command time - uint64_t t_sync_us = (t_elapsed.total_microseconds() * 2) + 13000 /*Scheduler latency*/; - - //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]->ctrl->set_time(sync_time); - radios[i]->ctrl->poke32(uhd::usrp::radio::sr_addr(uhd::usrp::radio::DACSYNC), 0x1); //Arm FRAMEP/N sync pulse - radios[i]->ctrl->set_time(uhd::time_spec_t(0.0)); //Clear command time - } - - //Wait and check status - boost::this_thread::sleep(boost::posix_time::microseconds(t_sync_us)); - for (size_t i = 0; i < radios.size(); i++) { - radios[i]->dac->verify_sync(); - } -} - /*********************************************************************** * ADC: Self-test operations **********************************************************************/ diff --git a/host/lib/usrp/x300/x300_radio_ctrl_impl.cpp b/host/lib/usrp/x300/x300_radio_ctrl_impl.cpp index 69eb51f55..a3bc2e691 100644 --- a/host/lib/usrp/x300/x300_radio_ctrl_impl.cpp +++ b/host/lib/usrp/x300/x300_radio_ctrl_impl.cpp @@ -608,8 +608,14 @@ void x300_radio_ctrl_impl::synchronize_dacs(const std::vectorset_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); + } + + //Add 100% of headroom + uncertainty to the command time + uint64_t t_sync_us = (t_elapsed.total_microseconds() * 2) + 16000 /*Scheduler latency*/; //Pick radios[0] as the time reference. uhd::time_spec_t sync_time = @@ -617,15 +623,17 @@ void x300_radio_ctrl_impl::synchronize_dacs(const std::vectorset_command_tick_rate(radios[i]->_radio_clk_rate, IO_MASTER_RADIO); - radios[i]->_regs->misc_outs_reg.set(radio_regmap_t::misc_outs_reg_t::DAC_SYNC, 0); 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.set(radio_regmap_t::misc_outs_reg_t::DAC_SYNC, 1); - radios[i]->_regs->misc_outs_reg.set(radio_regmap_t::misc_outs_reg_t::DAC_SYNC, 0); + radios[i]->_regs->misc_outs_reg.write(radio_regmap_t::misc_outs_reg_t::DAC_SYNC, 1); radios[i]->set_command_time(uhd::time_spec_t(0.0), IO_MASTER_RADIO); } + //Reset FRAMEP/N to 0 + for (size_t i = 0; i < radios.size(); i++) { + radios[i]->_regs->misc_outs_reg.write(radio_regmap_t::misc_outs_reg_t::DAC_SYNC, 0); + } + //Wait and check status boost::this_thread::sleep(boost::posix_time::microseconds(t_sync_us)); for (size_t i = 0; i < radios.size(); i++) { -- cgit v1.2.3