aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--host/docs/rd_testing.dox218
-rw-r--r--host/examples/sync_to_gps.cpp3
-rw-r--r--host/examples/test_messages.cpp8
-rw-r--r--host/lib/usrp/common/adf5355.cpp13
-rw-r--r--host/lib/usrp/cores/gpio_atr_3000.cpp4
-rw-r--r--host/lib/usrp/usrp_c.cpp22
6 files changed, 245 insertions, 23 deletions
diff --git a/host/docs/rd_testing.dox b/host/docs/rd_testing.dox
index a77ec29c5..1d05bc94e 100644
--- a/host/docs/rd_testing.dox
+++ b/host/docs/rd_testing.dox
@@ -162,18 +162,18 @@ These tests are simulations and do not need any device. Vivado 15.4 should be in
1. Go to the fpga directory depending on which test needs to be run.
1. NoC block test benches:
- Most of the NoC blocks have a test bench written in System Verilog that provides stimuli to the noc_block to verify it. The test bench for a block resides in <fpga-dir>/usrp3/lib/rfnoc/*_tb.
+ Most of the NoC blocks have a test bench written in System Verilog that provides stimuli to the noc_block to verify it. The test bench for a block resides in `<fpga-dir>/usrp3/lib/rfnoc/&zwj;*_tb`.
2. Running unit test benches:
- A few sub-blocks like noc-shell and sine_tone are used within the bigger noc_blocks. They have their own test benches. Their test benches reside in <fpga-dir>/usrp3/lib/sim/rfnoc/*.
+ A few sub-blocks like noc-shell and sine_tone are used within the bigger noc_blocks. They have their own test benches. Their test benches reside in `<fpga-dir>/usrp3/lib/sim/rfnoc/&zwj;*`.
3. Radio test bench:
- The radio test bench resides in <fpga-dir>/usrp3/lib/radio/noc_block_radio_core_tb/.
+ The radio test bench resides in `<fpga-dir>/usrp3/lib/radio/noc_block_radio_core_tb/`.
4. Device specific test benches:
- IPs specific to a device have test benches that exist in <fpga-dir>/usrp3/top/x300/sim/*. e.g. DMA testbench, PCIe, etc.
+ IPs specific to a device have test benches that exist in `<fpga-dir>/usrp3/top/x300/sim/*`. e.g. DMA testbench, PCIe, etc.
-2. Setup the environment by running 'source <fpga-dir>/usrp3/top/<device>/setupenv.sh'.
+2. Setup the environment by running `source <fpga-dir>/usrp3/top/<device>/setupenv.sh`.
3. In the test bench directory and run the test bench by 'make xsim' or 'make vsim'.
@@ -210,6 +210,214 @@ Failing tests can be debugged by checking the waveform in a Vivado GUI by runnin
Go to <fpga-dir>/usrp3/ and run 'build.py xsim all'. All tests should report 'PASS'.
+\section rdtesting_fpgadspverif FPGA DSP Verification
+
+| Test Code | Device | Peripherals | Manual Test Procedure | Automatic Test Procedure |
+|--------------------------|---------------|-------------|------------------------------------|----------------------------------|
+| FPGADSPVERIF-X310-HG-v1 | USRP X310 | 2x UBX | \ref rdtesting_fpgadspverif_manual | \ref rdtesting_fpgadspverif_auto |
+| FPGADSPVERIF-X310-XG-v1 | USRP X300 | 2x UBX | \ref rdtesting_fpgadspverif_manual | \ref rdtesting_fpgadspverif_auto |
+| FPGADSPVERIF-X300-HG-v1 | USRP X310 | 2x UBX | \ref rdtesting_fpgadspverif_manual | \ref rdtesting_fpgadspverif_auto |
+| FPGADSPVERIF-X300-XG-v1 | USRP X300 | 2x UBX | \ref rdtesting_fpgadspverif_manual | \ref rdtesting_fpgadspverif_auto |
+| FPGADSPVERIF-E310-SG1-v1 | USRP E310 SG1 | None | \ref rdtesting_fpgadspverif_manual | \ref rdtesting_fpgadspverif_auto |
+| FPGADSPVERIF-E310-SG3-v1 | USRP E310 SG3 | None | \ref rdtesting_fpgadspverif_manual | \ref rdtesting_fpgadspverif_auto |
+
+\subsection rdtesting_fpgadspverif_requirements Requirements
+
+- Signal generator and spectrum analyzer
+- X300 & X310 with 2x UBX daughterboard
+- E310 SG1 & SG3 with SSH access
+
+\subsection rdtesting_fpgadspverif_manual FPGA DSP Verification: Manual Test Procedure
+
+This procedure tests the DDC and DUC signal quality and the block's capability
+to change sample rate while streaming.
+
+#### RX testing
+
+1. Run calibration on device, if applicable
+2. Using a signal generator, inject a sine tone into RX channel 0 at 915.5 MHz @
+ -40 dBm
+3. Inspect the received spectrum using `uhd_fft`
+ - X3x0: `uhd_fft -f 915e6 -s 10e6 -g 10`
+ - E3xx: `uhd_fft -f 915e6 -s 2e6 -g 50`
+ - Embedded devices will require either using network mode or using X
+ forwarding over ssh to run the app natively
+4. In the GUI, inspect the spectrum. There should be a strong tone at the test
+ tone frequency. There may be a small tone at the carrier frequency due to DC
+ offset and a quadrature image due to IQ imbalance.
+5. Check the input tone frequencies outlined below. The tone should shift from
+ left to right as the frequency changes and may have some amplitude variation,
+ especially at the band edges.
+ - X3x0: 910 MHz to 920 MHz in 1 MHz steps
+ - E3xx: 914 MHz to 916 MHz in 200 kHz steps
+6. Set input tone back to 915.5 MHz. Check the sampling rate as outlined below.
+ The spectrum should reflect the change in sample rate.
+ - X3x0: 1, 5, 20, 33.333, 50, 66.666, 100, 200 MHz
+ - E3x0: 0.1, 0.5, 1, 1.143, 1.684 MHz
+7. Repeat on each RX channel of the device.
+8. This test fails if:
+ - DC offset and IQ imbalance tones are unusally large
+ - There are any other strong tones or spectrum distortion
+ - The spectrum changes significantly between frequencies or sample rates
+ - An initial transient distortion is acceptable
+ - Amplitude variation on the order of +/-10 dB is acceptable
+ - Console reports any of the following:
+ - Overruns 'O' if continuous and not due to host computer's lack of
+ processing performance
+ - Dropped packets 'D'
+ - Sequence number errors 'S'
+ - Timeouts
+
+#### TX testing
+
+1. Run calibration on device, if applicable
+2. Using `uhd_siggen_gui`, generate a sine tone TX channel 0 at 915.5 MHz:
+ - X3x0: `uhd_siggen_gui -f 915e6 -s 10e6 -g 10 -x 500e3 --sine`
+ - E3xx: `uhd_siggen_gui -f 915e6 -s 2e6 -g 50 -x 500e3 --sine`
+3. Using a spectrum analyzer, inspect the output spectrum. There should be a
+ strong tone at the test tone frequency. There may be a small tone at the
+ carrier frequency due to DC offset and a quadrature image due to IQ
+ imbalance.
+4. Using the GUI, test the follow offset frequencies. The tone should shift from
+ left to right as the frequency changes and may have some amplitude variation,
+ especially at the band edges.
+ - X3x0: -5 to +5 MHz in 1 MHz steps
+ - E3xx: -1 to +1 MHz in 200 kHz steps
+5. Set output tone offset back to 500e3. Change sampling rate as outlined below.
+ The spectrum should not significantly differ between sample rates.
+ - X3x0: 1, 5, 20, 33.333, 50, 66.666, 100, 200 MHz
+ - E3x0: 0.1, 0.5, 1, 1.143, 1.684 MHz
+6. Repeat on each TX channel of the device
+7. This test fails if:
+ - DC offset and IQ imbalance tones are unusually large
+ - There are any other strong tones or spectrum distortion
+ - The spectrum changes significantly between sample rates
+ - An initial transient distortion is acceptable
+ - Console reports any of the following:
+ - Underruns 'U' if continuous and not due to host computer's lack of
+ processing performance
+ - Late packets 'L'
+ - Sequence number errors 'S'
+
+\subsection rdtesting_fpgadspverif_auto FPGA DSP Verification: Automatic Test Procedure
+
+tbd
+
+\section rdtesting_fpgafuncverif FPGA Functional Verification
+
+| Test Code | Device | Peripherals | Manual Test Procedure | Automatic Test Procedure |
+|---------------------------|---------------|-------------|-------------------------------------|-----------------------------------|
+| FPGAFUNCVERIF-X310-HG-v1 | USRP X310 | 2x UBX | \ref rdtesting_fpgafuncverif_manual | \ref rdtesting_fpgafuncverif_auto |
+| FPGAFUNCVERIF-X310-XG-v1 | USRP X300 | 2x UBX | \ref rdtesting_fpgafuncverif_manual | \ref rdtesting_fpgafuncverif_auto |
+| FPGAFUNCVERIF-X300-HG-v1 | USRP X310 | 2x UBX | \ref rdtesting_fpgafuncverif_manual | \ref rdtesting_fpgafuncverif_auto |
+| FPGAFUNCVERIF-X300-XG-v1 | USRP X300 | 2x UBX | \ref rdtesting_fpgafuncverif_manual | \ref rdtesting_fpgafuncverif_auto |
+| FPGAFUNCVERIF-E310-SG1-v1 | USRP E310 SG1 | None | \ref rdtesting_fpgafuncverif_manual | \ref rdtesting_fpgafuncverif_auto |
+| FPGAFUNCVERIF-E310-SG3-v1 | USRP E310 SG3 | None | \ref rdtesting_fpgafuncverif_manual | \ref rdtesting_fpgafuncverif_auto |
+
+The FPGA functional verification tests exercise the Digital Downconverter (DDC),
+Digital Upconverter (DUC), and Radio Core RFNoC blocks.
+
+\subsection rdtesting_fpgafuncverif_requirements Requirements
+
+- X300 & X310 with two daughterboards
+ - 2x UBX recommended
+ - HG tests require a single 10 GigE connection, XG requires two for the 2x RX
+ 200 MSPS test
+ - 1 GigE and PCIe adapters and cabling for optional tests
+- E310 SG1 & SG3 with SSH access
+
+\subsection rdtesting_fpgafuncverif_manual FPGA Functional Verification: Manual Test Procedure
+
+This procedure verifies that the DDC, DUC, and Radio Core can run at various sample
+rates and channel configurations without any data flow issues.
+
+1. Run `benchmark_rate` using the parameters outlined in the tables below
+2. Unless otherwise noted, to pass each test:
+ - Benchmark rate must run without reporting any of the following:
+ - Underruns 'U'
+ - Overruns 'O'
+ - Dropped packets 'D'
+ - Sequence number errors 'S'
+ - Late commands 'L'
+ - Timeouts
+ - Appropriate TX/RX LEDs must be illuminated
+3. Unless specified in 'Notes' column, use default values for unlisted
+ parameters
+4. Example commands:
+ - X3x0: `benchmark_rate --tx_rate 1e6 --rx_rate 1e6 --channels 0,1 --duration 120`
+ - E3xx: `benchmark_rate --args="master_clock_rate=10e6" --tx_rate 1e6 --rx_rate 1e6 --channels 0,1 --duration 120`
+
+#### USRP X3x0: 10 GigE Interface
+
+- Required images to test: X310 HG
+- Optional images to test: X310 XG, X300 HG, X300 XG
+- Note: On TX tests, initial Us within the first 5 seconds can be ignored and do not fail the test
+
+| Channels | Sample Rates | Duration | Notes |
+|---------------|--------------------------|----------|--------------------|
+| 1x RX | 10e6, 50e6, 100e6, 200e6 | 60 | Test both channels |
+| 2x RX | 10e6, 50e6, 100e6 | 60 | |
+| 2x RX | 200e6 | 60 | 2x 10G, XG only |
+| 1x TX | 10e6, 50e6, 100e6, 200e6 | 60 | Test both channels |
+| 2x TX | 10e6, 50e6, 100e6 | 60 | |
+| 1x RX & 1x TX | 10e6, 50e6, 100e6 | 60 | Test both channels |
+| 1x RX & 1x TX | 200e6 | 60 | Use channel 0 |
+| 2x RX & 2x TX | 10e6, 50e6 | 60 | |
+| 1x RX & 1x TX | 200e6 | 3600 | Use channel 1 |
+| 2x RX & 2x TX | 100e6 | 3600 | |
+
+#### USRP X3x0: 1 GigE Interface
+
+- Required images to test: None
+- Optional images to test: X310 HG, X310 XG, X300 HG, X300 XG
+- Note: On TX tests, initial Us within the first 5 seconds can be ignored and do not fail the test
+
+| Channels | Sample Rates | Duration |
+|---------------|-------------------------|----------|
+| 1x RX | 1e6, 10e6, 25e6, 50e6 | 60 |
+| 2x RX | 1e6, 10e6, 25e6 | 60 |
+| 1x TX | 1e6, 10e6, 25e6, 50e6 | 60 |
+| 2x TX | 1e6, 10e6, 25e6 | 60 |
+| 1x RX & 1x TX | 1e6, 10e6, 25e6, 50e6 | 60 |
+| 2x RX & 2x TX | 1e6, 10e6, 25e6 | 60 |
+
+#### USRP X3x0: PCIe Interface
+
+- Required images to test: None
+- Optional images to test: X310 HG, X310 XG, X300 HG, X300 XG
+- Note: On TX tests, initial Us within the first 5 seconds can be ignored and do not fail the test
+
+| Channels | Sample Rates | Duration |
+|---------------|--------------------------|----------|
+| 1x RX | 10e6, 50e6, 100e6, 200e6 | 60 |
+| 2x RX | 10e6, 50e6, 100e6 | 60 |
+| 1x TX | 10e6, 50e6, 100e6, 200e6 | 60 |
+| 2x TX | 10e6, 50e6, 100e6 | 60 |
+| 1x RX & 1x TX | 10e6, 50e6, 100e6 | 60 |
+| 1x RX & 1x TX | 200e6 | 60 |
+| 2x RX & 2x TX | 10e6, 50e6 | 60 |
+
+Note: On TX tests, initial Us within the first 5 seconds can be ignored and do not fail the test
+
+#### USRP E3xx (SG3 Required, SG1 Optional)
+
+| Channels | Master Clock Rates | Sample Rate | Duration | Notes |
+|---------------|-------------------------|-------------|----------|--------------------|
+| 1x RX | 1e6, 10e6, 61.44e6 | 1e6 | 60 | Test both channels |
+| 1x TX | 1e6, 10e6, 61.44e6 | 1e6 | 60 | Test both channels |
+| 2x RX | 1e6, 10e6, 30.72e6 | 1e6 | 60 | |
+| 2x TX | 1e6, 10e6, 30.72e6 | 1e6 | 60 | |
+| 1x RX & 1x TX | 1e6, 10e6, 61.44e6 | 1e6 | 60 | Test both channels |
+| 1x RX & 1x TX | 61.44e6 | 1e6 | 60 | Use channel 1 |
+| 2x RX & 2x TX | 1e6, 10e6, 30.72e6 | 1e6 | 60 | |
+| 1x RX & 1x TX | 61.44e6 | 1e6 | 3600 | Use channel 0 |
+| 2x RX & 2x TX | 30.72e6 | 1e6 | 3600 | |
+
+Note: Any sample rate warnings can be ignored.
+
+\subsection rdtesting_fpgafuncverif_auto FPGA Functional Verification: Automatic Test Procedure
+
+tbd
\section rdtesting_defining Defining R&D Tests
diff --git a/host/examples/sync_to_gps.cpp b/host/examples/sync_to_gps.cpp
index f27c3eff5..3a9b5c7e4 100644
--- a/host/examples/sync_to_gps.cpp
+++ b/host/examples/sync_to_gps.cpp
@@ -99,7 +99,8 @@ int UHD_SAFE_MAIN(int argc, char *argv[])
std::cout << "LOCKED" << std::endl;
} else {
std::cout << "FAILED" << std::endl;
- throw uhd::runtime_error("Failed to lock to GPSDO 10 MHz Reference");
+ std::cout << "Failed to lock to GPSDO 10 MHz Reference. Exiting." << std::endl;
+ exit(EXIT_FAILURE);
}
}
else
diff --git a/host/examples/test_messages.cpp b/host/examples/test_messages.cpp
index 2583811ba..8a50e4c85 100644
--- a/host/examples/test_messages.cpp
+++ b/host/examples/test_messages.cpp
@@ -73,8 +73,8 @@ bool test_late_command_message(uhd::usrp::multi_usrp::sptr usrp, uhd::rx_streame
default:
std::cout << boost::format(
"failed:\n"
- " Got unexpected error code 0x%x, nsamps %u.\n"
- ) % md.error_code % nsamps << std::endl;
+ " Got unexpected error code 0x%x (%s), nsamps %u.\n"
+ ) % md.error_code % md.strerror() % nsamps << std::endl;
return false;
}
}
@@ -121,8 +121,8 @@ bool test_broken_chain_message(UHD_UNUSED(uhd::usrp::multi_usrp::sptr usrp), uhd
default:
std::cout << boost::format(
"failed:\n"
- " Got unexpected error code 0x%x.\n"
- ) % md.error_code << std::endl;
+ " Got unexpected error code 0x%x (%s).\n"
+ ) % md.error_code % md.strerror() << std::endl;
return false;
}
}
diff --git a/host/lib/usrp/common/adf5355.cpp b/host/lib/usrp/common/adf5355.cpp
index e3fd66bc2..36d41a5c3 100644
--- a/host/lib/usrp/common/adf5355.cpp
+++ b/host/lib/usrp/common/adf5355.cpp
@@ -47,7 +47,8 @@ static const double ADF5355_MIN_OUT_FREQ = (3.4e9 / 64);
static const double ADF5355_PHASE_RESYNC_TIME = 400e-6;
static const uint32_t ADF5355_MOD1 = 16777216;
-static const uint32_t ADF5355_MAX_MOD2 = 16384;
+static const uint32_t ADF5355_MAX_MOD2 = 16383;
+static const uint32_t ADF5355_MAX_FRAC2 = 16383;
//static const uint16_t ADF5355_MIN_INT_PRESCALER_89 = 75;
class adf5355_impl : public adf5355_iface
@@ -261,15 +262,11 @@ public:
double N = prescaler_input_freq / _pfd_freq;
uint16_t INT = static_cast<uint16_t>(floor(N));
uint32_t FRAC1 = static_cast<uint32_t>(floor((N - INT) * ADF5355_MOD1));
- double residue = ADF5355_MOD1 * (N - (INT + FRAC1 / ADF5355_MOD1));
+ double residue = (N - INT) * ADF5355_MOD1 - FRAC1;
double gcd = boost::math::gcd(static_cast<int>(_pfd_freq), static_cast<int>(freq_resolution));
- uint16_t MOD2 = static_cast<uint16_t>(floor(_pfd_freq / gcd));
-
- if (MOD2 > ADF5355_MAX_MOD2) {
- MOD2 = ADF5355_MAX_MOD2;
- }
- uint16_t FRAC2 = ceil(residue * MOD2);
+ uint16_t MOD2 = static_cast<uint16_t>(std::min(floor(_pfd_freq / gcd), static_cast<double>(ADF5355_MAX_MOD2)));
+ uint16_t FRAC2 = static_cast<uint16_t>(std::min(ceil(residue * MOD2), static_cast<double>(ADF5355_MAX_FRAC2)));
double coerced_vco_freq = _pfd_freq * (
todbl(INT) + (
diff --git a/host/lib/usrp/cores/gpio_atr_3000.cpp b/host/lib/usrp/cores/gpio_atr_3000.cpp
index 6df592e1b..4b141e2ab 100644
--- a/host/lib/usrp/cores/gpio_atr_3000.cpp
+++ b/host/lib/usrp/cores/gpio_atr_3000.cpp
@@ -271,6 +271,7 @@ public:
return (~_atr_disable_reg.get()) >> compute_shift(unit);
}
+ using gpio_atr_3000_impl::set_gpio_ddr;
inline void set_gpio_ddr(const db_unit_t unit, const uint32_t value, const uint32_t mask)
{
gpio_atr_3000_impl::set_gpio_ddr(DDR_OUTPUT, compute_mask(unit, value&mask));
@@ -282,6 +283,7 @@ public:
return _ddr_reg.get() >> compute_shift(unit);
}
+ using gpio_atr_3000_impl::set_atr_reg;
inline void set_atr_reg(const db_unit_t unit, const gpio_atr_reg_t atr, const uint32_t value, const uint32_t mask)
{
gpio_atr_3000_impl::set_atr_reg(atr, value << compute_shift(unit), compute_mask(unit, mask));
@@ -300,6 +302,7 @@ public:
return (reg->get() & compute_mask(unit, MASK_SET_ALL)) >> compute_shift(unit);
}
+ using gpio_atr_3000_impl::set_gpio_out;
inline void set_gpio_out(const db_unit_t unit, const uint32_t value, const uint32_t mask)
{
gpio_atr_3000_impl::set_gpio_out(
@@ -312,6 +315,7 @@ public:
return (_atr_idle_reg.get_gpio_out() & compute_mask(unit, MASK_SET_ALL)) >> compute_shift(unit);
}
+ using gpio_atr_3000_impl::read_gpio;
inline uint32_t read_gpio(const db_unit_t unit)
{
return (gpio_atr_3000_impl::read_gpio() & compute_mask(unit, MASK_SET_ALL)) >> compute_shift(unit);
diff --git a/host/lib/usrp/usrp_c.cpp b/host/lib/usrp/usrp_c.cpp
index 4d144fcaa..3d50bd8be 100644
--- a/host/lib/usrp/usrp_c.cpp
+++ b/host/lib/usrp/usrp_c.cpp
@@ -377,6 +377,7 @@ uhd_error uhd_usrp_get_rx_info(
uhd::dict<std::string, std::string> rx_info = USRP(h)->get_usrp_rx_info(chan);
COPY_INFO_FIELD(info_out, rx_info, mboard_id);
+ COPY_INFO_FIELD(info_out, rx_info, mboard_name);
COPY_INFO_FIELD(info_out, rx_info, mboard_serial);
COPY_INFO_FIELD(info_out, rx_info, rx_id);
COPY_INFO_FIELD(info_out, rx_info, rx_subdev_name);
@@ -395,6 +396,7 @@ uhd_error uhd_usrp_get_tx_info(
uhd::dict<std::string, std::string> tx_info = USRP(h)->get_usrp_tx_info(chan);
COPY_INFO_FIELD(info_out, tx_info, mboard_id);
+ COPY_INFO_FIELD(info_out, tx_info, mboard_name);
COPY_INFO_FIELD(info_out, tx_info, mboard_serial);
COPY_INFO_FIELD(info_out, tx_info, tx_id);
COPY_INFO_FIELD(info_out, tx_info, tx_subdev_name);
@@ -612,6 +614,16 @@ uhd_error uhd_usrp_set_clock_source_out(
)
}
+uhd_error uhd_usrp_set_time_source_out(
+ uhd_usrp_handle h,
+ bool enb,
+ size_t mboard
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ USRP(h)->set_time_source_out(enb, mboard);
+ )
+}
+
uhd_error uhd_usrp_get_num_mboards(
uhd_usrp_handle h,
size_t *num_mboards_out
@@ -839,10 +851,10 @@ uhd_error uhd_usrp_get_fe_rx_freq_range(
UHD_API uhd_error uhd_usrp_get_rx_lo_names(
uhd_usrp_handle h,
size_t chan,
- uhd_string_vector_handle rx_lo_names_out
+ uhd_string_vector_handle *rx_lo_names_out
){
UHD_SAFE_C_SAVE_ERROR(h,
- rx_lo_names_out->string_vector_cpp = USRP(h)->get_rx_lo_names(chan);
+ (*rx_lo_names_out)->string_vector_cpp = USRP(h)->get_rx_lo_names(chan);
)
}
@@ -873,10 +885,10 @@ UHD_API uhd_error uhd_usrp_get_rx_lo_sources(
uhd_usrp_handle h,
const char* name,
size_t chan,
- uhd_string_vector_handle rx_lo_sources_out
+ uhd_string_vector_handle *rx_lo_sources_out
){
UHD_SAFE_C_SAVE_ERROR(h,
- rx_lo_sources_out->string_vector_cpp = USRP(h)->get_rx_lo_sources(name, chan);
+ (*rx_lo_sources_out)->string_vector_cpp = USRP(h)->get_rx_lo_sources(name, chan);
)
}
@@ -1488,7 +1500,7 @@ uhd_error uhd_usrp_write_register(
)
}
-uhd_error uhd_usrp_write_register(
+uhd_error uhd_usrp_read_register(
uhd_usrp_handle h,
const char* path,
uint32_t field,