aboutsummaryrefslogtreecommitdiffstats
path: root/host
diff options
context:
space:
mode:
Diffstat (limited to 'host')
-rw-r--r--host/tests/rfnoc_block_tests/x4xx_radio_block_test.cpp299
-rw-r--r--host/tests/rfnoc_block_tests/x4xx_radio_mock.hpp263
2 files changed, 293 insertions, 269 deletions
diff --git a/host/tests/rfnoc_block_tests/x4xx_radio_block_test.cpp b/host/tests/rfnoc_block_tests/x4xx_radio_block_test.cpp
index 79cb27039..92ed07a25 100644
--- a/host/tests/rfnoc_block_tests/x4xx_radio_block_test.cpp
+++ b/host/tests/rfnoc_block_tests/x4xx_radio_block_test.cpp
@@ -4,24 +4,15 @@
// SPDX-License-Identifier: GPL-3.0-or-later
//
-#include "../../lib/usrp/x400/x400_radio_control.hpp"
#include "../rfnoc_graph_mock_nodes.hpp"
+#include "x4xx_radio_mock.hpp"
#include "x4xx_zbx_mpm_mock.hpp"
-#include <uhd/rfnoc/actions.hpp>
-#include <uhd/rfnoc/defaults.hpp>
#include <uhd/rfnoc/mock_block.hpp>
#include <uhd/utils/log.hpp>
#include <uhd/utils/math.hpp>
#include <uhdlib/rfnoc/graph.hpp>
-#include <uhdlib/rfnoc/node_accessor.hpp>
-#include <uhdlib/usrp/dboard/zbx/zbx_constants.hpp>
-#include <uhdlib/usrp/dboard/zbx/zbx_dboard.hpp>
-#include <uhdlib/utils/narrow.hpp>
-#include <math.h>
#include <boost/test/unit_test.hpp>
-#include <chrono>
-#include <cmath>
-#include <iomanip>
+#include <cstddef>
#include <iostream>
#include <thread>
@@ -31,247 +22,6 @@ using namespace std::chrono_literals;
using namespace uhd::usrp::zbx;
using namespace uhd::experts;
-// Redeclare this here, since it's only defined outside of UHD_API
-noc_block_base::make_args_t::~make_args_t() = default;
-
-namespace {
-
-/* This class extends mock_reg_iface_t by adding a constructor that initializes
- * some of the read memory to contain the memory size for the radio block.
- */
-class x4xx_radio_mock_reg_iface_t : public mock_reg_iface_t
-{
- // Start address of CPLD register space
- static constexpr uint32_t cpld_offset = radio_control_impl::regmap::PERIPH_BASE;
- // Start address of RFDC control register space
- static constexpr uint32_t rfdc_offset =
- radio_control_impl::regmap::PERIPH_BASE + 0x8000;
-
-public:
- x4xx_radio_mock_reg_iface_t(size_t num_channels)
- {
- for (size_t chan = 0; chan < num_channels; chan++) {
- const uint32_t reg_compat =
- radio_control_impl::regmap::REG_COMPAT_NUM
- + chan * radio_control_impl::regmap::REG_CHAN_OFFSET;
- read_memory[reg_compat] = (radio_control_impl::MINOR_COMPAT
- | (radio_control_impl::MAJOR_COMPAT << 16));
- }
- read_memory[radio_control_impl::regmap::REG_RADIO_WIDTH] =
- (32 /* bits per sample */ << 16) | 1 /* sample per clock */;
- }
-
- void _poke_cb(uint32_t addr, uint32_t data, uhd::time_spec_t, bool) override
- {
- // Are we on the peripheral?
- if (addr >= radio_control_impl::regmap::PERIPH_BASE) {
- // handle all the periphs stuff that is not CPLD here
- } else {
- return;
- }
-
- // Are we on the CPLD?
- if (addr >= cpld_offset && addr < rfdc_offset) {
- _poke_cpld_cb(addr, data);
- return;
- }
-
- // Are we poking the RFDC controls?
- if (addr >= rfdc_offset) {
- _poke_rfdc_cb(addr, data);
- return;
- }
- }
-
- void _poke_cpld_cb(const uint32_t addr, const uint32_t data)
- {
- switch (addr - cpld_offset) {
- /// CURRENT_CONFIG_REG
- case 0x1000:
- // FIXME: We write to all regs during init
- // BOOST_REQUIRE(false); // Not a write-register
- break;
- /// SW_CONFIG
- case 0x1008: {
- // This register is RW so update read_memory
- read_memory[addr] = data;
- // If we're in SW-defined mode, also update CURRENT_CONFIG_REG
- uint32_t& rf_opt = read_memory[cpld_offset + 0x1004];
- uint32_t& ccr = read_memory[cpld_offset + 0x1000];
- // Check if RF0_OPTION is SW_DEFINED
- if ((rf_opt & 0x00FF) == 0) {
- ccr = (ccr & 0xFF00) | (data & 0x00FF);
- }
- // Check if RF1_OPTION is SW_DEFINED
- if ((rf_opt & 0xFF00) == 0) {
- ccr = (ccr & 0x00FF) | (data & 0xFF00);
- }
- } break;
- /// LO SPI transactions
- case 0x1020:
- _poke_lo_spi(addr, data);
- return;
- /// LO SYNC
- case 0x1024:
- // We make these bits sticky, because they might get strobed in
- // multiple calls. In order to see what was strobed within an
- // API call, we keep bits as they are.
- read_memory[addr] |= data;
- return;
- // TX0 Table Select
- case 0x4000:
- case 0x4004:
- case 0x4008:
- case 0x400C:
- case 0x4010:
- case 0x4014: {
- read_memory[addr] = data;
- const uint32_t src_table_offset = data * 4;
- const uint32_t dst_table_offset = (addr - cpld_offset) - 0x4000;
- // Now we fake the transaction that copies ?X?_TABLE_* to
- // ?X?_DSA*
- read_memory[cpld_offset + 0x3000 + dst_table_offset] =
- read_memory[cpld_offset + 0x5000 + src_table_offset];
- }
- return;
- // RX0 Table Select
- case 0x4800:
- case 0x4804:
- case 0x4808:
- case 0x480C:
- case 0x4810:
- case 0x4814: {
- read_memory[addr] = data;
- const uint32_t src_table_offset = data * 4;
- const uint32_t dst_table_offset = (addr - cpld_offset) - 0x4800;
- // Now we fake the transaction that copies ?X?_TABLE_* to
- // ?X?_DSA*
- read_memory[cpld_offset + 0x3800 + dst_table_offset] =
- read_memory[cpld_offset + 0x5800 + src_table_offset];
- }
- return;
- default: // All other CPLD registers are read-write
- read_memory[addr] = data;
- return;
- }
- }
-
- void _poke_rfdc_cb(const uint32_t addr, const uint32_t data)
- {
- read_memory[addr] |= data;
- }
-
- void _poke_lo_spi(const uint32_t addr, const uint32_t data)
- {
- // UHD_LOG_INFO("TEST", "Detected LO SPI transaction!");
- const uint16_t spi_data = data & 0xFFFF;
- const uint8_t spi_addr = (data >> 16) & 0x7F;
- const bool read = bool(data & (1 << 23));
- const uint8_t lo_sel = (data >> 24) & 0x7;
- const bool start_xact = bool(data & (1 << 28));
- // UHD_LOG_INFO("TEST",
- // "Transaction record: Read: "
- // << (read ? "yes" : "no") << " Address: " << int(spi_addr) << std::hex
- // << " Data: 0x" << spi_data << " LO sel: " << int(lo_sel) << std::dec
- // << " Start Transaction: " << start_xact);
- if (!start_xact) {
- // UHD_LOG_INFO("TEST", "Register probably just initialized. Ignoring.");
- return;
- }
- switch (spi_addr) {
- case 0:
- _muxout_to_lock = spi_data & (1 << 2);
- break;
- case 125:
- BOOST_REQUIRE(read);
- read_memory[addr] = 0x2288;
- break;
- default:
- break;
- }
- if (read) {
- read_memory[addr] = (read_memory[addr] & 0xFFFF) | (spi_addr << 16)
- | (lo_sel << 24) | (1 << 31);
- }
- if (_muxout_to_lock) {
- // UHD_LOG_INFO("TEST", "Muxout set to lock. Returning all ones.");
- read_memory[addr] = 0xFFFF;
- return;
- }
- return;
- }
-
- bool _muxout_to_lock = false;
-}; // class x4xx_radio_mock_reg_iface_t
-
-/*
- * x400_radio_fixture is a class which is instantiated before each test
- * case is run. It sets up the block container, mock register interface,
- * and x400_radio_control object, all of which are accessible to the test
- * case. The instance of the object is destroyed at the end of each test
- * case.
- */
-constexpr size_t DEFAULT_MTU = 8000;
-
-//! Helper class to make sure we get the most logging regardless of environment
-// settings
-struct uhd_log_enabler
-{
- uhd_log_enabler(uhd::log::severity_level level)
- {
- std::cout << "Setting log level to " << level << "..." << std::endl;
- uhd::log::set_log_level(level);
- uhd::log::set_console_level(level);
- std::this_thread::sleep_for(10ms);
- }
-};
-
-struct x400_radio_fixture
-{
- x400_radio_fixture()
- : ule(uhd::log::warning) // Note: When debugging this test, either set
- // this to a lower level, or create a
- // uhd_log_enabler in the test-under-test
- , num_channels(uhd::usrp::zbx::ZBX_NUM_CHANS)
- , num_input_ports(num_channels)
- , num_output_ports(num_channels)
- , reg_iface(std::make_shared<x4xx_radio_mock_reg_iface_t>(num_channels))
- , rpcs(std::make_shared<uhd::test::x4xx_mock_rpc_server>(device_info))
- , mbc(std::make_shared<mpmd_mb_controller>(rpcs, device_info))
- , block_container(get_mock_block(RADIO_BLOCK,
- num_channels,
- num_channels,
- device_info,
- DEFAULT_MTU,
- X400,
- reg_iface,
- mbc))
- , test_radio(block_container.get_block<x400_radio_control_impl>())
- {
- node_accessor.init_props(test_radio.get());
- }
-
- ~x400_radio_fixture() {}
-
-
- // Must remain the first member so we make sure the log level is high
- uhd_log_enabler ule;
- const size_t num_channels;
- const size_t num_input_ports;
- const size_t num_output_ports;
- uhd::device_addr_t device_info = uhd::device_addr_t("master_clock_rate=122.88e6");
- std::shared_ptr<x4xx_radio_mock_reg_iface_t> reg_iface;
- std::shared_ptr<uhd::test::x4xx_mock_rpc_server> rpcs;
- mpmd_mb_controller::sptr mbc;
-
- mock_block_container block_container;
- std::shared_ptr<x400_radio_control_impl> test_radio;
- node_accessor_t node_accessor{};
-};
-
-} // namespace
-
-
/******************************************************************************
* RFNoC Graph Test
*
@@ -369,57 +119,67 @@ BOOST_FIXTURE_TEST_CASE(x400_radio_test_prop_prop, x400_radio_fixture)
mock_source_term.set_edge_property<size_t>(
"atomic_item_size", 1, {res_source_info::OUTPUT_EDGE, 0});
BOOST_CHECK_EQUAL(mock_source_term.get_edge_property<size_t>(
- "atomic_item_size", {res_source_info::OUTPUT_EDGE, 0}), 4);
+ "atomic_item_size", {res_source_info::OUTPUT_EDGE, 0}),
+ 4);
mock_source_term.set_edge_property<size_t>(
"atomic_item_size", 4, {res_source_info::OUTPUT_EDGE, 1});
- BOOST_CHECK_EQUAL(mock_source_term.get_edge_property<size_t>
- ("atomic_item_size", {res_source_info::OUTPUT_EDGE, 1}), 4);
+ BOOST_CHECK_EQUAL(mock_source_term.get_edge_property<size_t>(
+ "atomic_item_size", {res_source_info::OUTPUT_EDGE, 1}),
+ 4);
mock_source_term.set_edge_property<size_t>(
"atomic_item_size", 9, {res_source_info::OUTPUT_EDGE, 0});
BOOST_CHECK_EQUAL(mock_source_term.get_edge_property<size_t>(
- "atomic_item_size", {res_source_info::OUTPUT_EDGE, 0}), 36);
+ "atomic_item_size", {res_source_info::OUTPUT_EDGE, 0}),
+ 36);
mock_source_term.set_edge_property<size_t>(
"atomic_item_size", 10, {res_source_info::OUTPUT_EDGE, 1});
BOOST_CHECK_EQUAL(mock_source_term.get_edge_property<size_t>(
- "atomic_item_size", {res_source_info::OUTPUT_EDGE, 1}), 20);
+ "atomic_item_size", {res_source_info::OUTPUT_EDGE, 1}),
+ 20);
mock_source_term.set_edge_property<size_t>(
"mtu", 99, {res_source_info::OUTPUT_EDGE, 0});
mock_source_term.set_edge_property<size_t>(
"atomic_item_size", 25, {res_source_info::OUTPUT_EDGE, 0});
BOOST_CHECK_EQUAL(mock_source_term.get_edge_property<size_t>(
- "atomic_item_size", {res_source_info::OUTPUT_EDGE, 0}), 96);
+ "atomic_item_size", {res_source_info::OUTPUT_EDGE, 0}),
+ 96);
- //repeat for sink
+ // repeat for sink
mock_sink_term.set_edge_property<size_t>(
"atomic_item_size", 1, {res_source_info::INPUT_EDGE, 0});
BOOST_CHECK_EQUAL(mock_sink_term.get_edge_property<size_t>(
- "atomic_item_size", {res_source_info::INPUT_EDGE, 0}), 4);
+ "atomic_item_size", {res_source_info::INPUT_EDGE, 0}),
+ 4);
mock_sink_term.set_edge_property<size_t>(
"atomic_item_size", 4, {res_source_info::INPUT_EDGE, 1});
- BOOST_CHECK_EQUAL(mock_sink_term.get_edge_property<size_t>
- ("atomic_item_size", {res_source_info::INPUT_EDGE, 1}), 4);
+ BOOST_CHECK_EQUAL(mock_sink_term.get_edge_property<size_t>(
+ "atomic_item_size", {res_source_info::INPUT_EDGE, 1}),
+ 4);
mock_sink_term.set_edge_property<size_t>(
"atomic_item_size", 7, {res_source_info::INPUT_EDGE, 0});
BOOST_CHECK_EQUAL(mock_sink_term.get_edge_property<size_t>(
- "atomic_item_size", {res_source_info::INPUT_EDGE, 0}), 28);
+ "atomic_item_size", {res_source_info::INPUT_EDGE, 0}),
+ 28);
mock_sink_term.set_edge_property<size_t>(
"atomic_item_size", 22, {res_source_info::INPUT_EDGE, 1});
BOOST_CHECK_EQUAL(mock_sink_term.get_edge_property<size_t>(
- "atomic_item_size", {res_source_info::INPUT_EDGE, 1}), 44);
+ "atomic_item_size", {res_source_info::INPUT_EDGE, 1}),
+ 44);
mock_sink_term.set_edge_property<size_t>(
"mtu", 179, {res_source_info::INPUT_EDGE, 0});
mock_sink_term.set_edge_property<size_t>(
"atomic_item_size", 47, {res_source_info::INPUT_EDGE, 0});
BOOST_CHECK_EQUAL(mock_sink_term.get_edge_property<size_t>(
- "atomic_item_size", {res_source_info::INPUT_EDGE, 0}), 176);
+ "atomic_item_size", {res_source_info::INPUT_EDGE, 0}),
+ 176);
}
BOOST_FIXTURE_TEST_CASE(zbx_api_freq_tx_test, x400_radio_fixture)
@@ -803,8 +563,8 @@ BOOST_FIXTURE_TEST_CASE(zbx_lo_tree_test, x400_radio_fixture)
const double req_lo2 = iter_lo->at(1);
UHD_LOG_INFO(log,
"Testing lo1 freq " << req_lo1 / 1e6 << "MHz, lo2 freq "
- << req_lo2 / 1e6 << "MHz at center frequency "
- << req_freq / 1e6 << "MHz");
+ << req_lo2 / 1e6 << "MHz at center frequency "
+ << req_freq / 1e6 << "MHz");
tree->access<double>(fe_path / "freq").set(req_freq);
const double ret_lo1 =
tree->access<double>(fe_path / "los" / ZBX_LO1 / "freq" / "value")
@@ -1024,7 +784,8 @@ BOOST_FIXTURE_TEST_CASE(zbx_tx_power_api, x400_radio_fixture)
// regarding power
const double pow_diff =
std::abs(tx_given_power - test_radio->get_tx_power_reference(chan));
- BOOST_CHECK_MESSAGE(pow_diff < 3.0, "power differential is too large: " << pow_diff);
+ BOOST_CHECK_MESSAGE(
+ pow_diff < 3.0, "power differential is too large: " << pow_diff);
// Back to gain mode
gain_coerced = test_radio->set_tx_gain(tx_given_gain, chan);
@@ -1058,7 +819,7 @@ BOOST_FIXTURE_TEST_CASE(zbx_rx_power_api, x400_radio_fixture)
BOOST_CHECK_MESSAGE(pow_diff < 3.0,
"power differential is too large ("
<< pow_diff << "): Expected close to: " << rx_given_power
- << " Actual: " << actual_power << " Frequency: " << (freq/1e6));
+ << " Actual: " << actual_power << " Frequency: " << (freq / 1e6));
gain_coerced = test_radio->set_rx_gain(rx_given_gain, chan);
BOOST_REQUIRE_EQUAL(gain_coerced, rx_given_gain);
diff --git a/host/tests/rfnoc_block_tests/x4xx_radio_mock.hpp b/host/tests/rfnoc_block_tests/x4xx_radio_mock.hpp
new file mode 100644
index 000000000..597ffac7e
--- /dev/null
+++ b/host/tests/rfnoc_block_tests/x4xx_radio_mock.hpp
@@ -0,0 +1,263 @@
+//
+// Copyright 2022 Ettus Research, a National Instruments Brand
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+//
+
+#pragma once
+
+#include "../../lib/usrp/x400/x400_radio_control.hpp"
+#include "x4xx_zbx_mpm_mock.hpp"
+#include <uhd/rfnoc/mock_block.hpp>
+#include <uhd/utils/log.hpp>
+#include <uhdlib/rfnoc/node_accessor.hpp>
+#include <iostream>
+
+using namespace uhd;
+using namespace uhd::rfnoc;
+using namespace std::chrono_literals;
+using namespace uhd::usrp::zbx;
+using namespace uhd::experts;
+
+// Redeclare this here, since it's only defined outside of UHD_API
+noc_block_base::make_args_t::~make_args_t() = default;
+
+namespace {
+/* This class extends mock_reg_iface_t by adding a constructor that initializes
+ * some of the read memory to contain the memory size for the radio block.
+ */
+class x4xx_radio_mock_reg_iface_t : public mock_reg_iface_t
+{
+ // Start address of CPLD register space
+ static constexpr uint32_t cpld_offset = radio_control_impl::regmap::PERIPH_BASE;
+ // Start address of RFDC control register space
+ static constexpr uint32_t rfdc_offset =
+ radio_control_impl::regmap::PERIPH_BASE + 0x8000;
+ static constexpr uint32_t spi_offset =
+ radio_control_impl::regmap::PERIPH_BASE
+ + 0xC000 /*DIO Window*/ + 0x2000 /*DIO Regmap*/;
+
+public:
+ x4xx_radio_mock_reg_iface_t(size_t num_channels)
+ {
+ for (size_t chan = 0; chan < num_channels; chan++) {
+ const uint32_t reg_compat =
+ radio_control_impl::regmap::REG_COMPAT_NUM
+ + chan * radio_control_impl::regmap::REG_CHAN_OFFSET;
+ read_memory[reg_compat] = (radio_control_impl::MINOR_COMPAT
+ | (radio_control_impl::MAJOR_COMPAT << 16));
+ }
+ read_memory[radio_control_impl::regmap::REG_RADIO_WIDTH] =
+ (32 /* bits per sample */ << 16) | 1 /* sample per clock */;
+ // Ensure that the SPI Status is always SPI_READY
+ read_memory[spi_offset + 0x18] |= 1 << 24;
+ }
+
+ void _poke_cb(uint32_t addr, uint32_t data, uhd::time_spec_t, bool) override
+ {
+ // Are we on the peripheral?
+ if (addr >= radio_control_impl::regmap::PERIPH_BASE) {
+ // handle all the periphs stuff that is not CPLD here
+ } else {
+ return;
+ }
+
+ // Are we on the CPLD?
+ if (addr >= cpld_offset && addr < rfdc_offset) {
+ _poke_cpld_cb(addr, data);
+ return;
+ }
+
+ // Are we poking the RFDC controls?
+ if (addr >= rfdc_offset) {
+ _poke_rfdc_cb(addr, data);
+ return;
+ }
+ }
+
+ void _poke_cpld_cb(const uint32_t addr, const uint32_t data)
+ {
+ switch (addr - cpld_offset) {
+ /// CURRENT_CONFIG_REG
+ case 0x1000:
+ // FIXME: We write to all regs during init
+ // BOOST_REQUIRE(false); // Not a write-register
+ break;
+ /// SW_CONFIG
+ case 0x1008: {
+ // This register is RW so update read_memory
+ read_memory[addr] = data;
+ // If we're in SW-defined mode, also update CURRENT_CONFIG_REG
+ uint32_t& rf_opt = read_memory[cpld_offset + 0x1004];
+ uint32_t& ccr = read_memory[cpld_offset + 0x1000];
+ // Check if RF0_OPTION is SW_DEFINED
+ if ((rf_opt & 0x00FF) == 0) {
+ ccr = (ccr & 0xFF00) | (data & 0x00FF);
+ }
+ // Check if RF1_OPTION is SW_DEFINED
+ if ((rf_opt & 0xFF00) == 0) {
+ ccr = (ccr & 0x00FF) | (data & 0xFF00);
+ }
+ } break;
+ /// LO SPI transactions
+ case 0x1020:
+ _poke_lo_spi(addr, data);
+ return;
+ /// LO SYNC
+ case 0x1024:
+ // We make these bits sticky, because they might get strobed in
+ // multiple calls. In order to see what was strobed within an
+ // API call, we keep bits as they are.
+ read_memory[addr] |= data;
+ return;
+ // TX0 Table Select
+ case 0x4000:
+ case 0x4004:
+ case 0x4008:
+ case 0x400C:
+ case 0x4010:
+ case 0x4014: {
+ read_memory[addr] = data;
+ const uint32_t src_table_offset = data * 4;
+ const uint32_t dst_table_offset = (addr - cpld_offset) - 0x4000;
+ // Now we fake the transaction that copies ?X?_TABLE_* to
+ // ?X?_DSA*
+ read_memory[cpld_offset + 0x3000 + dst_table_offset] =
+ read_memory[cpld_offset + 0x5000 + src_table_offset];
+ }
+ return;
+ // RX0 Table Select
+ case 0x4800:
+ case 0x4804:
+ case 0x4808:
+ case 0x480C:
+ case 0x4810:
+ case 0x4814: {
+ read_memory[addr] = data;
+ const uint32_t src_table_offset = data * 4;
+ const uint32_t dst_table_offset = (addr - cpld_offset) - 0x4800;
+ // Now we fake the transaction that copies ?X?_TABLE_* to
+ // ?X?_DSA*
+ read_memory[cpld_offset + 0x3800 + dst_table_offset] =
+ read_memory[cpld_offset + 0x5800 + src_table_offset];
+ }
+ return;
+ default: // All other CPLD registers are read-write
+ read_memory[addr] = data;
+ return;
+ }
+ }
+
+ void _poke_rfdc_cb(const uint32_t addr, const uint32_t data)
+ {
+ read_memory[addr] |= data;
+ }
+
+ void _poke_lo_spi(const uint32_t addr, const uint32_t data)
+ {
+ // UHD_LOG_INFO("TEST", "Detected LO SPI transaction!");
+ const uint16_t spi_data = data & 0xFFFF;
+ const uint8_t spi_addr = (data >> 16) & 0x7F;
+ const bool read = bool(data & (1 << 23));
+ const uint8_t lo_sel = (data >> 24) & 0x7;
+ const bool start_xact = bool(data & (1 << 28));
+ // UHD_LOG_INFO("TEST",
+ // "Transaction record: Read: "
+ // << (read ? "yes" : "no") << " Address: " << int(spi_addr) << std::hex
+ // << " Data: 0x" << spi_data << " LO sel: " << int(lo_sel) << std::dec
+ // << " Start Transaction: " << start_xact);
+ if (!start_xact) {
+ // UHD_LOG_INFO("TEST", "Register probably just initialized. Ignoring.");
+ return;
+ }
+ switch (spi_addr) {
+ case 0:
+ _muxout_to_lock = spi_data & (1 << 2);
+ break;
+ case 125:
+ BOOST_REQUIRE(read);
+ read_memory[addr] = 0x2288;
+ break;
+ default:
+ break;
+ }
+ if (read) {
+ read_memory[addr] = (read_memory[addr] & 0xFFFF) | (spi_addr << 16)
+ | (lo_sel << 24) | (1 << 31);
+ }
+ if (_muxout_to_lock) {
+ // UHD_LOG_INFO("TEST", "Muxout set to lock. Returning all ones.");
+ read_memory[addr] = 0xFFFF;
+ return;
+ }
+ return;
+ }
+
+ bool _muxout_to_lock = false;
+}; // class x4xx_radio_mock_reg_iface_t
+
+/*
+ * x400_radio_fixture is a class which is instantiated before each test
+ * case is run. It sets up the block container, mock register interface,
+ * and x400_radio_control object, all of which are accessible to the test
+ * case. The instance of the object is destroyed at the end of each test
+ * case.
+ */
+constexpr size_t DEFAULT_MTU = 8000;
+
+//! Helper class to make sure we get the most logging regardless of environment
+// settings
+struct uhd_log_enabler
+{
+ uhd_log_enabler(uhd::log::severity_level level)
+ {
+ std::cout << "Setting log level to " << level << "..." << std::endl;
+ uhd::log::set_log_level(level);
+ uhd::log::set_console_level(level);
+ std::this_thread::sleep_for(10ms);
+ }
+};
+
+struct x400_radio_fixture
+{
+ x400_radio_fixture()
+ : ule(uhd::log::trace) // Note: When debugging this test, either set
+ // this to a lower level, or create a
+ // uhd_log_enabler in the test-under-test
+ , num_channels(uhd::usrp::zbx::ZBX_NUM_CHANS)
+ , num_input_ports(num_channels)
+ , num_output_ports(num_channels)
+ , reg_iface(std::make_shared<x4xx_radio_mock_reg_iface_t>(num_channels))
+ , rpcs(std::make_shared<uhd::test::x4xx_mock_rpc_server>(device_info))
+ , mbc(std::make_shared<mpmd_mb_controller>(rpcs, device_info))
+ , block_container(get_mock_block(RADIO_BLOCK,
+ num_channels,
+ num_channels,
+ device_info,
+ DEFAULT_MTU,
+ X400,
+ reg_iface,
+ mbc))
+ , test_radio(block_container.get_block<x400_radio_control_impl>())
+ {
+ node_accessor.init_props(test_radio.get());
+ }
+
+ ~x400_radio_fixture() {}
+
+
+ // Must remain the first member so we make sure the log level is high
+ uhd_log_enabler ule;
+ const size_t num_channels;
+ const size_t num_input_ports;
+ const size_t num_output_ports;
+ uhd::device_addr_t device_info = uhd::device_addr_t("master_clock_rate=122.88e6");
+ std::shared_ptr<x4xx_radio_mock_reg_iface_t> reg_iface;
+ std::shared_ptr<uhd::test::x4xx_mock_rpc_server> rpcs;
+ mpmd_mb_controller::sptr mbc;
+
+ mock_block_container block_container;
+ std::shared_ptr<x400_radio_control_impl> test_radio;
+ node_accessor_t node_accessor{};
+};
+} // namespace