aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib/usrp/x300/x300_impl.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'host/lib/usrp/x300/x300_impl.hpp')
-rw-r--r--host/lib/usrp/x300/x300_impl.hpp287
1 files changed, 90 insertions, 197 deletions
diff --git a/host/lib/usrp/x300/x300_impl.hpp b/host/lib/usrp/x300/x300_impl.hpp
index e04b06d65..d491e2bc0 100644
--- a/host/lib/usrp/x300/x300_impl.hpp
+++ b/host/lib/usrp/x300/x300_impl.hpp
@@ -19,51 +19,36 @@
#define INCLUDED_X300_IMPL_HPP
#include <uhd/property_tree.hpp>
-#include <uhd/device.hpp>
+#include "../device3/device3_impl.hpp"
#include <uhd/usrp/mboard_eeprom.hpp>
-#include <uhd/usrp/dboard_manager.hpp>
-#include <uhd/usrp/dboard_eeprom.hpp>
#include <uhd/usrp/subdev_spec.hpp>
#include <uhd/types/sensors.hpp>
+#include "x300_radio_ctrl_impl.hpp"
#include "x300_clock_ctrl.hpp"
#include "x300_fw_common.h"
#include <uhd/transport/udp_simple.hpp> //mtu
-#include <uhd/utils/tasks.hpp>
-#include "spi_core_3000.hpp"
-#include "x300_adc_ctrl.hpp"
-#include "x300_dac_ctrl.hpp"
-#include "rx_vita_core_3000.hpp"
-#include "tx_vita_core_3000.hpp"
-#include "time_core_3000.hpp"
-#include "rx_dsp_core_3000.hpp"
-#include "tx_dsp_core_3000.hpp"
#include "i2c_core_100_wb32.hpp"
-#include "radio_ctrl_core_3000.hpp"
-#include "rx_frontend_core_200.hpp"
-#include "tx_frontend_core_200.hpp"
-#include "gpio_core_200.hpp"
#include <boost/weak_ptr.hpp>
#include <uhd/usrp/gps_ctrl.hpp>
-#include <uhd/usrp/mboard_eeprom.hpp>
-#include <uhd/transport/bounded_buffer.hpp>
#include <uhd/transport/nirio/niusrprio_session.h>
#include <uhd/transport/vrt_if_packet.hpp>
+#include <uhd/transport/muxed_zero_copy_if.hpp>
#include "recv_packet_demuxer_3000.hpp"
#include "x300_regs.hpp"
+///////////// RFNOC /////////////////////
+#include <uhd/rfnoc/block_ctrl.hpp>
+///////////// RFNOC /////////////////////
+#include <boost/dynamic_bitset.hpp>
static const std::string X300_FW_FILE_NAME = "usrp_x300_fw.bin";
+static const std::string X300_DEFAULT_CLOCK_SOURCE = "internal";
-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 = 520*1024; //512K SRAM buffer + 8K 2Clk FIFO
-static const size_t X300_TX_FC_RESPONSE_FREQ = 8; //per flow-control window
+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_RX_SW_BUFF_SIZE_ETH = 0x2000000;//32MiB For an ~8k frame size any size >32MiB is just wasted buffer space
static const size_t X300_RX_SW_BUFF_SIZE_ETH_MACOS = 0x100000; //1Mib
-static const double X300_RX_SW_BUFF_FULL_FACTOR = 0.90; //Buffer should ideally be 90% full.
-static const size_t X300_RX_FC_REQUEST_FREQ = 32; //per flow-control window
//The FIFO closest to the DMA controller is 1023 elements deep for RX and 1029 elements deep for TX
//where an element is 8 bytes. For best throughput ensure that the data frame fits in these buffers.
@@ -73,93 +58,66 @@ static const size_t X300_PCIE_TX_DATA_FRAME_SIZE = 8192; //bytes
static const size_t X300_PCIE_DATA_NUM_FRAMES = 2048;
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_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;
-static const size_t X300_TX_MAX_HDR_LEN = // bytes
- sizeof(boost::uint32_t) // Header
- + sizeof(uhd::transport::vrt::if_packet_info_t().sid) // SID
- + sizeof(uhd::transport::vrt::if_packet_info_t().tsf); // Timestamp
-static const size_t X300_RX_MAX_HDR_LEN = // bytes
- sizeof(boost::uint32_t) // Header
- + sizeof(uhd::transport::vrt::if_packet_info_t().sid) // SID
- + sizeof(uhd::transport::vrt::if_packet_info_t().tsf); // Timestamp
-
static const size_t X300_MAX_RATE_PCIE = 800000000; // bytes/s
static const size_t X300_MAX_RATE_10GIGE = 800000000; // bytes/s
static const size_t X300_MAX_RATE_1GIGE = 100000000; // bytes/s
#define X300_RADIO_DEST_PREFIX_TX 0
-#define X300_RADIO_DEST_PREFIX_CTRL 1
-#define X300_RADIO_DEST_PREFIX_RX 2
-
-#define X300_XB_DST_E0 0
-#define X300_XB_DST_E1 1
-#define X300_XB_DST_R0 2 // Radio 0 -> Slot A
-#define X300_XB_DST_R1 3 // Radio 1 -> Slot B
-#define X300_XB_DST_CE0 4
-#define X300_XB_DST_CE1 5
-#define X300_XB_DST_CE2 5
-#define X300_XB_DST_PCI 7
-
-#define X300_DEVICE_THERE 2
-#define X300_DEVICE_HERE 0
-
-//eeprom addrs for various boards
-enum
+
+#define X300_XB_DST_E0 0
+#define X300_XB_DST_E1 1
+#define X300_XB_DST_PCI 2
+#define X300_XB_DST_R0 3 // Radio 0 -> Slot A
+#define X300_XB_DST_R1 4 // Radio 1 -> Slot B
+#define X300_XB_DST_CE0 5
+
+#define X300_SRC_ADDR0 0
+#define X300_SRC_ADDR1 1
+#define X300_DST_ADDR 2
+
+// Ethernet ports
+enum x300_eth_iface_t
{
- X300_DB0_RX_EEPROM = 0x5,
- X300_DB0_TX_EEPROM = 0x4,
- X300_DB0_GDB_EEPROM = 0x1,
- X300_DB1_RX_EEPROM = 0x7,
- X300_DB1_TX_EEPROM = 0x6,
- X300_DB1_GDB_EEPROM = 0x3,
+ X300_IFACE_NONE = 0,
+ X300_IFACE_ETH0 = 1,
+ X300_IFACE_ETH1 = 2,
};
-struct x300_dboard_iface_config_t
+struct x300_eth_conn_t
{
- gpio_core_200::sptr gpio;
- spi_core_3000::sptr spi;
- size_t rx_spi_slaveno;
- size_t tx_spi_slaveno;
- i2c_core_100_wb32::sptr i2c;
- x300_clock_ctrl::sptr clock;
- x300_clock_which_t which_rx_clk;
- x300_clock_which_t which_tx_clk;
- boost::uint8_t dboard_slot;
- uhd::timed_wb_iface::sptr cmd_time_ctrl;
+ std::string addr;
+ x300_eth_iface_t type;
};
-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_);
-class x300_impl : public uhd::device
+class x300_impl : public uhd::usrp::device3_impl
{
public:
- typedef uhd::transport::bounded_buffer<uhd::async_metadata_t> async_md_type;
x300_impl(const uhd::device_addr_t &);
void setup_mb(const size_t which, const uhd::device_addr_t &);
~x300_impl(void);
- //the io interface
- uhd::rx_streamer::sptr get_rx_stream(const uhd::stream_args_t &);
- uhd::tx_streamer::sptr get_tx_stream(const uhd::stream_args_t &);
-
- //support old async call
- bool recv_async_msg(uhd::async_metadata_t &, double);
-
// used by x300_find_with_addr to find X300 devices.
static boost::mutex claimer_mutex; //All claims and checks in this process are serialized
static bool is_claimed(uhd::wb_iface::sptr);
@@ -170,43 +128,37 @@ public:
static x300_mboard_t get_mb_type_from_pcie(const std::string& resource, const std::string& rpc_port);
static x300_mboard_t get_mb_type_from_eeprom(const uhd::usrp::mboard_eeprom_t& mb_eeprom);
-private:
- boost::shared_ptr<async_md_type> _async_md;
-
- //perifs in the radio core
- struct radio_perifs_t
- {
- //Interfaces
- radio_ctrl_core_3000::sptr ctrl;
- spi_core_3000::sptr spi;
- x300_adc_ctrl::sptr adc;
- x300_dac_ctrl::sptr dac;
- time_core_3000::sptr time64;
- rx_vita_core_3000::sptr framer;
- rx_dsp_core_3000::sptr ddc;
- tx_vita_core_3000::sptr deframer;
- tx_dsp_core_3000::sptr duc;
- gpio_core_200_32wo::sptr leds;
- rx_frontend_core_200::sptr rx_fe;
- tx_frontend_core_200::sptr tx_fe;
- //Registers
- uhd::usrp::x300::radio_regmap_t::sptr regmap;
- };
+protected:
+ void subdev_to_blockid(
+ const uhd::usrp::subdev_spec_pair_t &spec, const size_t mb_i,
+ uhd::rfnoc::block_id_t &block_id, uhd::device_addr_t &block_args
+ );
+ uhd::usrp::subdev_spec_pair_t blockid_to_subdev(
+ const uhd::rfnoc::block_id_t &blockid, const uhd::device_addr_t &block_args
+ );
- //overflow recovery impl
- void handle_overflow(radio_perifs_t &perif, boost::weak_ptr<uhd::rx_streamer> streamer);
+private:
//vector of member objects per motherboard
struct mboard_members_t
{
- uhd::dict<size_t, boost::weak_ptr<uhd::rx_streamer> > rx_streamers;
- uhd::dict<size_t, boost::weak_ptr<uhd::tx_streamer> > tx_streamers;
-
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;
+ size_t next_src_addr;
+
+ // 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;
@@ -217,20 +169,9 @@ private:
spi_core_3000::sptr zpu_spi;
i2c_core_100_wb32::sptr zpu_i2c;
- //perifs in each radio
- static const size_t NUM_RADIOS = 2;
- radio_perifs_t radio_perifs[NUM_RADIOS]; //!< This is hardcoded s.t. radio_perifs[0] points to slot A and [1] to B
- uhd::usrp::dboard_eeprom_t db_eeproms[8];
- //! Return the index of a radio component, given a slot name. This means DSPs, radio_perifs
- size_t get_radio_index(const std::string &slot_name) {
- UHD_ASSERT_THROW(slot_name == "A" or slot_name == "B");
- return slot_name == "A" ? 0 : 1;
- }
-
//other perifs on mboard
x300_clock_ctrl::sptr clock;
uhd::gps_ctrl::sptr gps;
- gpio_core_200::sptr fp_gpio;
uhd::usrp::x300::fw_regmap_t::sptr fw_regmap;
@@ -240,57 +181,25 @@ private:
size_t hw_rev;
std::string current_refclk_src;
- uhd::soft_regmap_db_t::sptr regmap_db;
+ std::vector<uhd::rfnoc::x300_radio_ctrl_impl::sptr> radios;
};
std::vector<mboard_members_t> _mb;
//task for periodically reclaiming the device from others
void claimer_loop(uhd::wb_iface::sptr);
- boost::mutex _transport_setup_mutex;
-
- void register_loopback_self_test(uhd::wb_iface::sptr iface);
-
- void radio_loopback(uhd::wb_iface::sptr iface, const bool on);
-
- /*! \brief Initialize the radio component on a given slot.
- *
- * Call this function once per slot (A and B) and motherboard to initialize all the radio components.
- * This will:
- * - Reset and init DACs and ADCs
- * - Setup controls for DAC, ADC, SPI and LEDs
- * - Self test ADC
- * - Sync DACs (for MIMO)
- * - Initialize the property tree for control objects etc. (gain, rate...)
- *
- * \param mb_i Motherboard index
- * \param slot_name Slot name (A or B).
- */
- void setup_radio(const size_t, const std::string &slot_name, const uhd::device_addr_t &dev_addr);
-
size_t _sid_framer;
- struct sid_config_t
- {
- boost::uint8_t router_addr_there;
- boost::uint8_t dst_prefix; //2bits
- boost::uint8_t router_dst_there;
- boost::uint8_t router_dst_here;
- };
- boost::uint32_t allocate_sid(mboard_members_t &mb, const sid_config_t &config);
- struct both_xports_t
- {
- uhd::transport::zero_copy_if::sptr recv;
- uhd::transport::zero_copy_if::sptr send;
- size_t recv_buff_size;
- size_t send_buff_size;
- };
- both_xports_t make_transport(
- const size_t mb_index,
- const boost::uint8_t& destination,
- const boost::uint8_t& prefix,
- const uhd::device_addr_t& args,
- boost::uint32_t& sid);
+ uhd::sid_t allocate_sid(
+ mboard_members_t &mb,
+ const uhd::sid_t &address,
+ const uint32_t src_addr,
+ const uint32_t src_dst);
+ uhd::both_xports_t make_transport(
+ const uhd::sid_t &address,
+ const xport_type_t xport_type,
+ const uhd::device_addr_t& args
+ );
struct frame_size_t
{
@@ -306,6 +215,15 @@ private:
*/
frame_size_t determine_max_frame_size(const std::string &addr, const frame_size_t &user_mtu);
+ std::map<uint32_t, uint32_t> _dma_chan_pool;
+ uhd::transport::muxed_zero_copy_if::sptr _ctrl_dma_xport;
+
+ /*! Allocate or return a previously allocated PCIe channel pair
+ *
+ * Note the SID is always the transmit SID (i.e. from host to device).
+ */
+ uint32_t allocate_pcie_dma_chan(const uhd::sid_t &tx_sid, const xport_type_t xport_type);
+
////////////////////////////////////////////////////////////////////
//
//Caching for transport interface re-use -- like sharing a DMA.
@@ -328,28 +246,9 @@ private:
////////////////////////////////////////////////////////////////////
uhd::dict<std::string, uhd::usrp::dboard_manager::sptr> _dboard_managers;
- uhd::dict<std::string, uhd::usrp::dboard_iface::sptr> _dboard_ifaces;
- void set_rx_fe_corrections(const uhd::fs_path &mb_path, const std::string &fe_name, const double lo_freq);
- void set_tx_fe_corrections(const uhd::fs_path &mb_path, const std::string &fe_name, const double lo_freq);
bool _ignore_cal_file;
-
- /*! Update the IQ MUX settings for the radio peripheral according to given subdev spec.
- *
- * Also checks if the given subdev is valid for this device and updates the channel to DSP mapping.
- *
- * \param tx_rx "tx" or "rx", depending where you're setting the subdev spec
- * \param mb_i Mainboard index number.
- * \param spec Subdev spec
- */
- void update_subdev_spec(const std::string &tx_rx, const size_t mb_i, const uhd::usrp::subdev_spec_t &spec);
-
- void set_tick_rate(mboard_members_t &, const double);
- void update_tick_rate(mboard_members_t &, const double);
- void update_rx_samp_rate(mboard_members_t&, const size_t, const double);
- void update_tx_samp_rate(mboard_members_t&, const size_t, const double);
-
void update_clock_control(mboard_members_t&);
void initialize_clock_control(mboard_members_t &mb);
void set_time_source_out(mboard_members_t&, const bool);
@@ -367,21 +266,15 @@ private:
void check_fw_compat(const uhd::fs_path &mb_path, uhd::wb_iface::sptr iface);
void check_fpga_compat(const uhd::fs_path &mb_path, const mboard_members_t &members);
- void update_atr_leds(gpio_core_200_32wo::sptr, const std::string &ant);
- boost::uint32_t get_fp_gpio(gpio_core_200::sptr);
- void set_fp_gpio(gpio_core_200::sptr, const gpio_attr_t, const boost::uint32_t);
-
- void self_cal_adc_capture_delay(mboard_members_t& mb, const size_t radio_i, bool print_status = false);
- double self_cal_adc_xfer_delay(mboard_members_t& mb, bool apply_delay = false);
- void self_test_adcs(mboard_members_t& mb, boost::uint32_t ramp_time_ms = 100);
-
- void extended_adc_test(mboard_members_t& mb, double duration_s);
+ /// More IO stuff
+ uhd::device_addr_t get_tx_hints(size_t mb_index);
+ uhd::device_addr_t get_rx_hints(size_t mb_index);
+ uhd::endianness_t get_transport_endianness(size_t mb_index) {
+ return _mb[mb_index].if_pkt_is_big_endian ? uhd::ENDIANNESS_BIG : uhd::ENDIANNESS_LITTLE;
+ };
- //**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.
- static void synchronize_dacs(const std::vector<radio_perifs_t*>& mboards);
+ void post_streamer_hooks(uhd::direction_t dir);
};
#endif /* INCLUDED_X300_IMPL_HPP */
+// vim: sw=4 expandtab: