diff options
| author | Paul David <paul.david@ettus.com> | 2016-04-13 15:46:25 -0700 | 
|---|---|---|
| committer | Ashish Chaudhari <ashish@ettus.com> | 2016-04-18 12:23:45 -0700 | 
| commit | b28fcee59998512f15c1f693f5a5958b6a464a56 (patch) | |
| tree | 0e03172b64a2d0626c648c5f2d149b3dfc88c6a2 /host/lib/usrp | |
| parent | d4bb4266b58dd5ef33040afb6c6f101f2c9895b1 (diff) | |
| download | uhd-b28fcee59998512f15c1f693f5a5958b6a464a56.tar.gz uhd-b28fcee59998512f15c1f693f5a5958b6a464a56.tar.bz2 uhd-b28fcee59998512f15c1f693f5a5958b6a464a56.zip  | |
transport optimize: Integrated the transport offloading into the X3XX codebase
Diffstat (limited to 'host/lib/usrp')
| -rw-r--r-- | host/lib/usrp/x300/x300_fw_ctrl.cpp | 35 | ||||
| -rw-r--r-- | host/lib/usrp/x300/x300_impl.cpp | 196 | ||||
| -rw-r--r-- | host/lib/usrp/x300/x300_impl.hpp | 44 | ||||
| -rw-r--r-- | host/lib/usrp/x300/x300_io_impl.cpp | 4 | 
4 files changed, 226 insertions, 53 deletions
diff --git a/host/lib/usrp/x300/x300_fw_ctrl.cpp b/host/lib/usrp/x300/x300_fw_ctrl.cpp index 3a8d984fb..25960ede0 100644 --- a/host/lib/usrp/x300/x300_fw_ctrl.cpp +++ b/host/lib/usrp/x300/x300_fw_ctrl.cpp @@ -37,6 +37,11 @@ class x300_ctrl_iface : public wb_iface  public:      enum {num_retries = 3}; +    x300_ctrl_iface(bool enable_errors = true) : errors(enable_errors) +    { +        /* NOP */ +    } +      void flush(void)      {          boost::mutex::scoped_lock lock(reg_access); @@ -52,11 +57,11 @@ public:              {                  return this->__poke32(addr, data);              } -            catch(const std::exception &ex) +            catch(const uhd::io_error &ex)              { -                const std::string error_msg = str(boost::format( +                std::string error_msg = str(boost::format(                      "x300 fw communication failure #%u\n%s") % i % ex.what()); -                UHD_MSG(error) << error_msg << std::endl; +                if (errors) UHD_MSG(error) << error_msg << std::endl;                  if (i == num_retries) throw uhd::io_error(error_msg);              }          } @@ -72,11 +77,11 @@ public:                  boost::uint32_t data = this->__peek32(addr);                  return data;              } -            catch(const std::exception &ex) +            catch(const uhd::io_error &ex)              { -                const std::string error_msg = str(boost::format( +                std::string error_msg = str(boost::format(                      "x300 fw communication failure #%u\n%s") % i % ex.what()); -                UHD_MSG(error) << error_msg << std::endl; +                if (errors) UHD_MSG(error) << error_msg << std::endl;                  if (i == num_retries) throw uhd::io_error(error_msg);              }          } @@ -84,6 +89,8 @@ public:      }  protected: +    bool errors; +      virtual void __poke32(const wb_addr_type addr, const boost::uint32_t data) = 0;      virtual boost::uint32_t __peek32(const wb_addr_type addr) = 0;      virtual void __flush() = 0; @@ -98,8 +105,8 @@ protected:  class x300_ctrl_iface_enet : public x300_ctrl_iface  {  public: -    x300_ctrl_iface_enet(uhd::transport::udp_simple::sptr udp): -        udp(udp), seq(0) +    x300_ctrl_iface_enet(uhd::transport::udp_simple::sptr udp, bool enable_errors = true): +        x300_ctrl_iface(enable_errors), udp(udp), seq(0)      {          try          { @@ -187,8 +194,8 @@ private:  class x300_ctrl_iface_pcie : public x300_ctrl_iface  {  public: -    x300_ctrl_iface_pcie(niriok_proxy::sptr drv_proxy): -        _drv_proxy(drv_proxy) +    x300_ctrl_iface_pcie(niriok_proxy::sptr drv_proxy, bool enable_errors = true): +        x300_ctrl_iface(enable_errors), _drv_proxy(drv_proxy)      {          nirio_status status = 0;          nirio_status_chain(_drv_proxy->set_attribute(RIO_ADDRESS_SPACE, BUS_INTERFACE), status); @@ -289,12 +296,12 @@ private:      static const boost::uint32_t INIT_TIMEOUT_IN_MS = 5000;  }; -wb_iface::sptr x300_make_ctrl_iface_enet(uhd::transport::udp_simple::sptr udp) +wb_iface::sptr x300_make_ctrl_iface_enet(uhd::transport::udp_simple::sptr udp, bool enable_errors = true)  { -    return wb_iface::sptr(new x300_ctrl_iface_enet(udp)); +    return wb_iface::sptr(new x300_ctrl_iface_enet(udp, enable_errors));  } -wb_iface::sptr x300_make_ctrl_iface_pcie(niriok_proxy::sptr drv_proxy) +wb_iface::sptr x300_make_ctrl_iface_pcie(niriok_proxy::sptr drv_proxy, bool enable_errors = true)  { -    return wb_iface::sptr(new x300_ctrl_iface_pcie(drv_proxy)); +    return wb_iface::sptr(new x300_ctrl_iface_pcie(drv_proxy, enable_errors));  } diff --git a/host/lib/usrp/x300/x300_impl.cpp b/host/lib/usrp/x300/x300_impl.cpp index b9d4e56b1..399d640c3 100644 --- a/host/lib/usrp/x300/x300_impl.cpp +++ b/host/lib/usrp/x300/x300_impl.cpp @@ -18,9 +18,9 @@  #include "x300_impl.hpp"  #include "x300_lvbitx.hpp"  #include "x310_lvbitx.hpp" +#include "apply_corrections.hpp"  #include <boost/algorithm/string.hpp>  #include <boost/asio.hpp> -#include "apply_corrections.hpp"  #include <uhd/utils/static.hpp>  #include <uhd/utils/msg.hpp>  #include <uhd/utils/paths.hpp> @@ -32,12 +32,14 @@  #include <boost/make_shared.hpp>  #include <boost/functional/hash.hpp>  #include <boost/assign/list_of.hpp> -#include <fstream>  #include <uhd/transport/udp_zero_copy.hpp>  #include <uhd/transport/udp_constants.hpp> +#include <uhd/transport/zero_copy_recv_offload.hpp>  #include <uhd/transport/nirio_zero_copy.hpp>  #include <uhd/transport/nirio/niusrprio_session.h>  #include <uhd/utils/platform.hpp> +#include <uhd/types/sid.hpp> +#include <fstream>  #define NIUSRPRIO_DEFAULT_RPC_PORT "5444" @@ -111,7 +113,12 @@ static device_addrs_t x300_find_with_addr(const device_addr_t &hint)          //This operation can throw due to compatibility mismatch.          try          { -            wb_iface::sptr zpu_ctrl = x300_make_ctrl_iface_enet(udp_simple::make_connected(new_addr["addr"], BOOST_STRINGIZE(X300_FW_COMMS_UDP_PORT))); +            wb_iface::sptr zpu_ctrl = x300_make_ctrl_iface_enet( +                udp_simple::make_connected(new_addr["addr"], +                    BOOST_STRINGIZE(X300_FW_COMMS_UDP_PORT)), +                false /* Suppress timeout errors */ +            ); +              if (x300_impl::is_claimed(zpu_ctrl)) continue; //claimed by another process              new_addr["fpga"] = get_fpga_option(zpu_ctrl); @@ -208,7 +215,7 @@ static device_addrs_t x300_find_pcie(const device_addr_t &hint, bool explicit_qu              if (get_pcie_zpu_iface_registry().has_key(resource_d)) {                  zpu_ctrl = get_pcie_zpu_iface_registry()[resource_d].lock();              } else { -                zpu_ctrl = x300_make_ctrl_iface_pcie(kernel_proxy); +                zpu_ctrl = x300_make_ctrl_iface_pcie(kernel_proxy, false /* suppress timeout errors */);                  //We don't put this zpu_ctrl in the registry because we need                  //a persistent niriok_proxy associated with the object              } @@ -386,13 +393,108 @@ x300_impl::x300_impl(const uhd::device_addr_t &dev_addr)      }  } +void x300_impl::mboard_members_t::discover_eth( +        const mboard_eeprom_t mb_eeprom, +        const std::vector<std::string> &ip_addrs) +{ +    // Clear any previous addresses added +    eth_conns.clear(); + +    // Index the MB EEPROM addresses +    std::vector<std::string> mb_eeprom_addrs; +    mb_eeprom_addrs.push_back(mb_eeprom["ip-addr0"]); +    mb_eeprom_addrs.push_back(mb_eeprom["ip-addr1"]); +    mb_eeprom_addrs.push_back(mb_eeprom["ip-addr2"]); +    mb_eeprom_addrs.push_back(mb_eeprom["ip-addr3"]); + +    BOOST_FOREACH(const std::string& addr, ip_addrs) { +        x300_eth_conn_t conn_iface; +        conn_iface.addr = addr; +        conn_iface.type = X300_IFACE_NONE; + +        // Decide from the mboard eeprom what IP corresponds +        // to an interface +        for (size_t i = 0; i < mb_eeprom_addrs.size(); i++) { +            if (addr == mb_eeprom_addrs[i]) { +                // Choose the interface based on the index parity +                if (i % 2 == 0) { +                    conn_iface.type = X300_IFACE_ETH0; +                } else { +                    conn_iface.type = X300_IFACE_ETH1; +                } +            } +        } + +        // Check default IP addresses +        if (addr == boost::asio::ip::address_v4( +            boost::uint32_t(X300_DEFAULT_IP_ETH0_1G)).to_string()) { +            conn_iface.type = X300_IFACE_ETH0; +        } else if (addr == boost::asio::ip::address_v4( +            boost::uint32_t(X300_DEFAULT_IP_ETH1_1G)).to_string()) { +            conn_iface.type = X300_IFACE_ETH1; +        } else if (addr == boost::asio::ip::address_v4( +            boost::uint32_t(X300_DEFAULT_IP_ETH0_10G)).to_string()) { +            conn_iface.type = X300_IFACE_ETH0; +        } else if (addr == boost::asio::ip::address_v4( +            boost::uint32_t(X300_DEFAULT_IP_ETH1_10G)).to_string()) { +            conn_iface.type = X300_IFACE_ETH1; +        } + +        // Save to a vector of connections +        if (conn_iface.type != X300_IFACE_NONE) { +            // Check the address before we add it +            try +            { +                wb_iface::sptr zpu_ctrl = x300_make_ctrl_iface_enet( +                    udp_simple::make_connected(conn_iface.addr, +                        BOOST_STRINGIZE(X300_FW_COMMS_UDP_PORT)), +                    false /* Suppress timeout errors */ +                ); + +                // Peek the ZPU ctrl to make sure this connection works +                zpu_ctrl->peek32(0); +            } + +            // If the address does not work, throw an error +            catch(std::exception &) +            { +                throw uhd::io_error(str(boost::format( +                    "X300 Initialization: Invalid address %s") +                    % conn_iface.addr)); +            } +            eth_conns.push_back(conn_iface); +        } +    } + +    if (eth_conns.size() == 0) +        throw uhd::assertion_error("X300 Initialization Error: No ethernet interfaces specified."); +} +  void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr)  {      const fs_path mb_path = "/mboards/"+boost::lexical_cast<std::string>(mb_i);      mboard_members_t &mb = _mb[mb_i];      mb.initialization_done = false; -    mb.addr = dev_addr.has_key("resource") ? dev_addr["resource"] : dev_addr["addr"]; +    std::vector<std::string> eth_addrs; +    // Not choosing eth0 based on resource might cause user issues +    std::string eth0_addr = dev_addr.has_key("resource") ? dev_addr["resource"] : dev_addr["addr"]; +    eth_addrs.push_back(eth0_addr); + +    if (dev_addr.has_key("second_addr")) { +        std::string eth1_addr = dev_addr["second_addr"]; + +        // Ensure we do not have duplicate addresses +        if (eth1_addr != eth0_addr) +            eth_addrs.push_back(eth1_addr); +    } + +    // Initially store the first address provided to setup communication +    // Once we read the eeprom, we use it to map IP to its interface +    x300_eth_conn_t init; +    init.addr = eth_addrs[0]; +    mb.eth_conns.push_back(init); +      mb.xport_path = dev_addr.has_key("resource") ? "nirio" : "eth";      mb.if_pkt_is_big_endian = mb.xport_path != "nirio"; @@ -469,7 +571,7 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr)          // Detect the frame size on the path to the USRP          try { -            _max_frame_sizes = determine_max_frame_size(mb.addr, req_max_frame_size); +            _max_frame_sizes = determine_max_frame_size(mb.get_pri_eth().addr, req_max_frame_size);          } catch(std::exception &e) {              UHD_MSG(error) << e.what() << std::endl;          } @@ -503,15 +605,15 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr)      UHD_MSG(status) << "Setup basic communication..." << std::endl;      if (mb.xport_path == "nirio") {          boost::mutex::scoped_lock(pcie_zpu_iface_registry_mutex); -        if (get_pcie_zpu_iface_registry().has_key(mb.addr)) { +        if (get_pcie_zpu_iface_registry().has_key(mb.get_pri_eth().addr)) {              throw uhd::assertion_error("Someone else has a ZPU transport to the device open. Internal error!");          } else {              mb.zpu_ctrl = x300_make_ctrl_iface_pcie(mb.rio_fpga_interface->get_kernel_proxy()); -            get_pcie_zpu_iface_registry()[mb.addr] = boost::weak_ptr<wb_iface>(mb.zpu_ctrl); +            get_pcie_zpu_iface_registry()[mb.get_pri_eth().addr] = boost::weak_ptr<wb_iface>(mb.zpu_ctrl);          }      } else { -        mb.zpu_ctrl = x300_make_ctrl_iface_enet(udp_simple::make_connected(mb.addr, -                    BOOST_STRINGIZE(X300_FW_COMMS_UDP_PORT))); +        mb.zpu_ctrl = x300_make_ctrl_iface_enet(udp_simple::make_connected( +                    mb.get_pri_eth().addr, BOOST_STRINGIZE(X300_FW_COMMS_UDP_PORT)));      }      mb.claimer_task = uhd::task::make(boost::bind(&x300_impl::claimer_loop, this, mb.zpu_ctrl)); @@ -614,14 +716,8 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr)      if (mb.xport_path == "nirio") {          mb.router_dst_here = X300_XB_DST_PCI;      } else { -        if (mb.addr == mb_eeprom["ip-addr0"]) mb.router_dst_here = X300_XB_DST_E0; -        else if (mb.addr == mb_eeprom["ip-addr1"]) mb.router_dst_here = X300_XB_DST_E1; -        else if (mb.addr == mb_eeprom["ip-addr2"]) mb.router_dst_here = X300_XB_DST_E0; -        else if (mb.addr == mb_eeprom["ip-addr3"]) mb.router_dst_here = X300_XB_DST_E1; -        else if (mb.addr == boost::asio::ip::address_v4(boost::uint32_t(X300_DEFAULT_IP_ETH0_1G)).to_string()) mb.router_dst_here = X300_XB_DST_E0; -        else if (mb.addr == boost::asio::ip::address_v4(boost::uint32_t(X300_DEFAULT_IP_ETH1_1G)).to_string()) mb.router_dst_here = X300_XB_DST_E1; -        else if (mb.addr == boost::asio::ip::address_v4(boost::uint32_t(X300_DEFAULT_IP_ETH0_10G)).to_string()) mb.router_dst_here = X300_XB_DST_E0; -        else if (mb.addr == boost::asio::ip::address_v4(boost::uint32_t(X300_DEFAULT_IP_ETH1_10G)).to_string()) mb.router_dst_here = X300_XB_DST_E1; +        // Discover ethernet interfaces +        mb.discover_eth(mb_eeprom, eth_addrs);      }      //////////////////////////////////////////////////////////////////// @@ -928,7 +1024,7 @@ x300_impl::~x300_impl(void)                  mb.zpu_ctrl->poke32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_CLAIM_SRC), 0);                  //If the process is killed, the entire registry will disappear so we                  //don't need to worry about unclean shutdowns here. -                get_pcie_zpu_iface_registry().pop(mb.addr); +                get_pcie_zpu_iface_registry().pop(mb.get_pri_eth().addr);              }          }      } @@ -1132,7 +1228,6 @@ boost::uint32_t get_pcie_dma_channel(boost::uint8_t destination, boost::uint8_t      return ((radio_grp * RADIO_GRP_SIZE) + prefix);  } -  x300_impl::both_xports_t x300_impl::make_transport(      const size_t mb_index,      const boost::uint8_t& destination, @@ -1148,8 +1243,19 @@ x300_impl::both_xports_t x300_impl::make_transport(      config.dst_prefix           = prefix;      config.router_dst_there     = destination;      config.router_dst_here      = mb.router_dst_here; -    sid = this->allocate_sid(mb, config); +    // Choose the endpoint based on the destination +    size_t endpoint = 0; +    if (destination == X300_XB_DST_R1) { +        if (mb.eth_conns.size() > 1) +            endpoint = 1; +    } + +    // Decide on the IP/Interface pair based on the endpoint index +    std::string interface_addr = mb.eth_conns[endpoint].addr; +    config.iface_index = mb.eth_conns[endpoint].type; + +    sid = this->allocate_sid(mb, config);      static const uhd::device_addr_t DEFAULT_XPORT_ARGS;      const uhd::device_addr_t& xport_args = @@ -1196,17 +1302,21 @@ x300_impl::both_xports_t x300_impl::make_transport(           * connection type.*/          size_t eth_data_rec_frame_size = 0; +        fs_path mboard_path = fs_path("/mboards/"+boost::lexical_cast<std::string>(mb_index) / "link_max_rate"); +          if (mb.loaded_fpga_image.substr(0,2) == "HG") {              if (mb.router_dst_here == X300_XB_DST_E0) {                  eth_data_rec_frame_size = X300_1GE_DATA_FRAME_MAX_SIZE; -                _tree->access<double>("/mboards/"+boost::lexical_cast<std::string>(mb_index) / "link_max_rate").set(X300_MAX_RATE_1GIGE); +                _tree->access<double>(mboard_path).set(X300_MAX_RATE_1GIGE);              } else if (mb.router_dst_here == X300_XB_DST_E1) {                  eth_data_rec_frame_size = X300_10GE_DATA_FRAME_MAX_SIZE; -                _tree->access<double>("/mboards/"+boost::lexical_cast<std::string>(mb_index) / "link_max_rate").set(X300_MAX_RATE_10GIGE); +                _tree->access<double>(mboard_path).set(X300_MAX_RATE_10GIGE);              }          } else if (mb.loaded_fpga_image.substr(0,2) == "XG") {              eth_data_rec_frame_size = X300_10GE_DATA_FRAME_MAX_SIZE; -            _tree->access<double>("/mboards/"+boost::lexical_cast<std::string>(mb_index) / "link_max_rate").set(X300_MAX_RATE_10GIGE); +            size_t max_link_rate = X300_MAX_RATE_10GIGE; +            max_link_rate *= mb.eth_conns.size(); +            _tree->access<double>(mboard_path).set(max_link_rate);          }          if (eth_data_rec_frame_size == 0) { @@ -1261,12 +1371,22 @@ x300_impl::both_xports_t x300_impl::make_transport(          //make a new transport - fpga has no idea how to talk to us on this yet          udp_zero_copy::buff_params buff_params; -        xports.recv = udp_zero_copy::make(mb.addr, + +        xports.recv = udp_zero_copy::make( +                interface_addr,                  BOOST_STRINGIZE(X300_VITA_UDP_PORT),                  default_buff_args,                  buff_params,                  xport_args); +        // Create a threaded transport for the receive chain only +        // Note that this shouldn't affect PCIe +        if (prefix == X300_RADIO_DEST_PREFIX_RX) { +            xports.recv = zero_copy_recv_offload::make( +                    xports.recv, +                    X300_THREAD_BUFFER_TIMEOUT +            ); +        }          xports.send = xports.recv;          //For the UDP transport the buffer size if the size of the socket buffer @@ -1281,7 +1401,7 @@ x300_impl::both_xports_t x300_impl::make_transport(          //send a mini packet with SID into the ZPU          //ZPU will reprogram the ethernet framer          UHD_LOG << "programming packet for new xport on " -            << mb.addr << std::hex << "sid 0x" << sid << std::dec << std::endl; +            << mb.get_pri_eth().addr << std::hex << "sid 0x" << sid << std::dec << std::endl;          //YES, get a __send__ buffer from the __recv__ socket          //-- this is the only way to program the framer for recv:          managed_send_buffer::sptr buff = xports.recv->get_send_buff(); @@ -1299,7 +1419,6 @@ x300_impl::both_xports_t x300_impl::make_transport(          //ethernet framer has been programmed before we return.          mb.zpu_ctrl->peek32(0);      } -      return xports;  } @@ -1308,15 +1427,32 @@ boost::uint32_t x300_impl::allocate_sid(mboard_members_t &mb, const sid_config_t  {      const std::string &xport_path = mb.xport_path;      const boost::uint32_t stream = (config.dst_prefix | (config.router_dst_there << 2)) & 0xff; +    boost::uint8_t sid_ret_addr = X300_SRC_ADDR_ETH0; +    boost::uint32_t xb_port     = X300_XB_DST_E0; + +    // Use the interface index to decide on the ethernet port +    if (config.iface_index == X300_IFACE_ETH1) { +        sid_ret_addr = X300_SRC_ADDR_ETH1; +        xb_port = X300_XB_DST_E1; +    } + +    // Ensure we choose the right port in the case of NI-RIO +    if (xport_path == "nirio") { +        xb_port = X300_XB_DST_PCI; +    } + +    int int_sid_ret_addr = int(sid_ret_addr);      const boost::uint32_t sid = 0 -        | (X300_DEVICE_HERE << 24) +        | (sid_ret_addr << 24)          | (_sid_framer << 16)          | (config.router_addr_there << 8)          | (stream << 0)      ; +      UHD_LOG << std::hex          << " sid 0x" << sid +        << " return address 0x" << int_sid_ret_addr          << " framer 0x" << _sid_framer          << " stream 0x" << stream          << " router_dst_there 0x" << int(config.router_dst_there) @@ -1330,7 +1466,7 @@ boost::uint32_t x300_impl::allocate_sid(mboard_members_t &mb, const sid_config_t      mb.zpu_ctrl->poke32(SR_ADDR(SETXB_BASE, 256 + (stream)), config.router_dst_there);      // Program CAM entry for returning packets to us (for example GR host via Eth0)      // This type of packet does not match the XB_LOCAL address and is looked up in the lower half of the CAM -    mb.zpu_ctrl->poke32(SR_ADDR(SETXB_BASE, 0 + (X300_DEVICE_HERE)), config.router_dst_here); +    mb.zpu_ctrl->poke32(SR_ADDR(SETXB_BASE, 0 + (sid_ret_addr)), xb_port);      if (xport_path == "nirio") {          boost::uint32_t router_config_word = ((_sid_framer & 0xff) << 16) |                                    //Return SID @@ -1709,7 +1845,7 @@ void x300_impl::check_fpga_compat(const fs_path &mb_path, const mboard_members_t                                                % image_loader_path                                                % (members.xport_path == "eth" ? "addr"                                                                               : "resource") -                                              % members.addr); +                                              % members.get_pri_eth().addr);          throw uhd::runtime_error(str(boost::format(              "Expected FPGA compatibility number %d, but got %d:\n" diff --git a/host/lib/usrp/x300/x300_impl.hpp b/host/lib/usrp/x300/x300_impl.hpp index dd94708b7..f7e33ec70 100644 --- a/host/lib/usrp/x300/x300_impl.hpp +++ b/host/lib/usrp/x300/x300_impl.hpp @@ -54,9 +54,9 @@  static const std::string X300_FW_FILE_NAME  = "usrp_x300_fw.bin"; -static const double X300_DEFAULT_TICK_RATE      = 200e6;        //Hz -static const double X300_DEFAULT_DBOARD_CLK_RATE = 50e6;        //Hz -static const double X300_BUS_CLOCK_RATE         = 166.666667e6; //Hz +static const double X300_DEFAULT_TICK_RATE          = 200e6;        //Hz +static const double X300_DEFAULT_DBOARD_CLK_RATE    = 50e6;         //Hz +static const double X300_BUS_CLOCK_RATE             = 166.666667e6; //Hz  static const size_t X300_TX_HW_BUFF_SIZE_SRAM       = 520*1024;      //512K SRAM buffer + 8K 2Clk FIFO  static const size_t X300_TX_FC_RESPONSE_FREQ_SRAM   = 8;             //per flow-control window @@ -82,6 +82,8 @@ static const size_t X300_10GE_DATA_FRAME_MAX_SIZE   = 8000;     //bytes  static const size_t X300_1GE_DATA_FRAME_MAX_SIZE    = 1472;     //bytes  static const size_t X300_ETH_MSG_FRAME_SIZE         = uhd::transport::udp_simple::mtu;  //bytes +static const double X300_THREAD_BUFFER_TIMEOUT      = 0.1;   // Time in seconds +  static const size_t X300_ETH_MSG_NUM_FRAMES         = 64;  static const size_t X300_ETH_DATA_NUM_FRAMES        = 32;  static const double X300_DEFAULT_SYSREF_RATE        = 10e6; @@ -113,7 +115,8 @@ static const size_t X300_MAX_RATE_1GIGE             = 100000000; // bytes/s  #define X300_XB_DST_PCI 7  #define X300_DEVICE_THERE 2 -#define X300_DEVICE_HERE 0 +#define X300_SRC_ADDR_ETH0 0 +#define X300_SRC_ADDR_ETH1 1  //eeprom addrs for various boards  enum @@ -126,6 +129,20 @@ enum      X300_DB1_GDB_EEPROM = 0x3,  }; +// Ethernet ports +enum x300_eth_iface_t +{ +    X300_IFACE_NONE = 0, +    X300_IFACE_ETH0 = 1, +    X300_IFACE_ETH1 = 2, +}; + +struct x300_eth_conn_t +{ +    std::string addr; +    x300_eth_iface_t type; +}; +  struct x300_dboard_iface_config_t  {      uhd::usrp::gpio_atr::db_gpio_atr_3000::sptr gpio; @@ -144,8 +161,8 @@ struct x300_dboard_iface_config_t  uhd::usrp::dboard_iface::sptr x300_make_dboard_iface(const x300_dboard_iface_config_t &);  uhd::uart_iface::sptr x300_make_uart_iface(uhd::wb_iface::sptr iface); -uhd::wb_iface::sptr x300_make_ctrl_iface_enet(uhd::transport::udp_simple::sptr udp); -uhd::wb_iface::sptr x300_make_ctrl_iface_pcie(uhd::niusrprio::niriok_proxy::sptr drv_proxy); +uhd::wb_iface::sptr x300_make_ctrl_iface_enet(uhd::transport::udp_simple::sptr udp, bool enable_errors = true); +uhd::wb_iface::sptr x300_make_ctrl_iface_pcie(uhd::niusrprio::niriok_proxy::sptr drv_proxy, bool enable_errors = true);  uhd::device_addrs_t x300_find(const uhd::device_addr_t &hint_); @@ -209,9 +226,21 @@ private:          bool initialization_done;          uhd::task::sptr claimer_task; -        std::string addr;          std::string xport_path;          int router_dst_here; + +        std::vector<x300_eth_conn_t> eth_conns; + +        // Discover the ethernet connections per motherboard +        void discover_eth(const uhd::usrp::mboard_eeprom_t mb_eeprom, +                          const std::vector<std::string> &ip_addrs); + +        // Get the primary ethernet connection +        inline const x300_eth_conn_t& get_pri_eth() const +        { +            return eth_conns[0]; +        } +          uhd::device_addr_t send_args;          uhd::device_addr_t recv_args;          bool if_pkt_is_big_endian; @@ -284,6 +313,7 @@ private:          boost::uint8_t dst_prefix; //2bits          boost::uint8_t router_dst_there;          boost::uint8_t router_dst_here; +        x300_eth_iface_t iface_index;      };      boost::uint32_t allocate_sid(mboard_members_t &mb, const sid_config_t &config); diff --git a/host/lib/usrp/x300/x300_io_impl.cpp b/host/lib/usrp/x300/x300_io_impl.cpp index a4621c89f..329405261 100644 --- a/host/lib/usrp/x300/x300_io_impl.cpp +++ b/host/lib/usrp/x300/x300_io_impl.cpp @@ -383,8 +383,8 @@ rx_streamer::sptr x300_impl::get_rx_stream(const uhd::stream_args_t &args_)          both_xports_t xport = this->make_transport(mb_index, dest, X300_RADIO_DEST_PREFIX_RX, device_addr, data_sid);          UHD_LOG << boost::format("data_sid = 0x%08x, actual recv_buff_size = %d\n") % data_sid % xport.recv_buff_size << std::endl; -	// To calculate the max number of samples per packet, we assume the maximum header length -	// to avoid fragmentation should the entire header be used. +        // 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 = xport.recv->get_recv_frame_size() - X300_RX_MAX_HDR_LEN; // bytes per packet          const size_t bpi = convert::get_bytes_per_item(args.otw_format); // bytes per item          const size_t spp = unsigned(args.args.cast<double>("spp", bpp/bpi)); // samples per packet  | 
