aboutsummaryrefslogtreecommitdiffstats
path: root/host/tests
diff options
context:
space:
mode:
authormattprost <matt.prost@ni.com>2020-03-19 16:09:20 -0500
committerAaron Rossetto <aaron.rossetto@ni.com>2020-04-02 12:12:26 -0500
commit6aed4b5a45cf0057bc175e19a86888259bf17cec (patch)
treed92b825a039345957385d6d0f689dc5f4adb3c91 /host/tests
parent7ad64600fe3db643ba10a88990263b13dac7d063 (diff)
downloaduhd-6aed4b5a45cf0057bc175e19a86888259bf17cec.tar.gz
uhd-6aed4b5a45cf0057bc175e19a86888259bf17cec.tar.bz2
uhd-6aed4b5a45cf0057bc175e19a86888259bf17cec.zip
rfnoc: Add multichannel register interface
This utility class implements the register access methods of reg_iface but adds built-in address translation features for consecutive instances of an RFNoC block. The register peek and poke methods accept an extra 'instance' parameter which is used to calculate the absolute address for the register access. This can be used for accessing registers for the different channels of a multi-channel block (i.e. Radio, DDC, DUC, etc). Signed-off-by: mattprost <matt.prost@ni.com>
Diffstat (limited to 'host/tests')
-rw-r--r--host/tests/CMakeLists.txt1
-rw-r--r--host/tests/multichan_register_iface_test.cpp180
2 files changed, 181 insertions, 0 deletions
diff --git a/host/tests/CMakeLists.txt b/host/tests/CMakeLists.txt
index 2742c0385..3665a9d17 100644
--- a/host/tests/CMakeLists.txt
+++ b/host/tests/CMakeLists.txt
@@ -59,6 +59,7 @@ set(test_sources
tx_streamer_test.cpp
block_id_test.cpp
rfnoc_property_test.cpp
+ multichan_register_iface_test.cpp
)
#turn each test cpp file into an executable with an int main() function
diff --git a/host/tests/multichan_register_iface_test.cpp b/host/tests/multichan_register_iface_test.cpp
new file mode 100644
index 000000000..3a97d56cd
--- /dev/null
+++ b/host/tests/multichan_register_iface_test.cpp
@@ -0,0 +1,180 @@
+//
+// Copyright 2020 Ettus Research, a National Instruments Brand
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+//
+
+#include <uhd/rfnoc/mock_block.hpp>
+#include <uhd/rfnoc/multichan_register_iface.hpp>
+#include <boost/test/unit_test.hpp>
+#include <algorithm>
+#include <iostream>
+#include <vector>
+
+using namespace uhd::rfnoc;
+
+namespace {
+
+constexpr uint32_t BASE_ADDR = 0x8000;
+constexpr size_t INSTANCE_SIZE = 0x1000;
+
+inline uint32_t get_addr_translation(uint32_t offset, size_t instance)
+{
+ return offset + BASE_ADDR + INSTANCE_SIZE * instance;
+}
+
+} // namespace
+
+BOOST_AUTO_TEST_CASE(test_poke32)
+{
+ auto mock_reg_iface = std::make_shared<mock_reg_iface_t>();
+ register_iface_holder mock_holder{mock_reg_iface};
+ multichan_register_iface block_reg_iface{mock_holder, BASE_ADDR, INSTANCE_SIZE};
+ uint32_t addr = 0x100;
+ uint32_t data = 0x1230;
+ block_reg_iface.poke32(addr, data);
+ uint32_t abs_addr = get_addr_translation(addr, 0);
+ BOOST_CHECK_EQUAL(mock_reg_iface->write_memory[abs_addr], data);
+ for (size_t instance = 0; instance < 4; instance++) {
+ data = 0xabc0 | instance;
+ block_reg_iface.poke32(addr, data, instance);
+ abs_addr = get_addr_translation(addr, instance);
+ BOOST_CHECK_EQUAL(mock_reg_iface->write_memory[abs_addr], data);
+ }
+}
+
+BOOST_AUTO_TEST_CASE(test_peek32)
+{
+ auto mock_reg_iface = std::make_shared<mock_reg_iface_t>();
+ register_iface_holder mock_holder{mock_reg_iface};
+ multichan_register_iface block_reg_iface{mock_holder, BASE_ADDR, INSTANCE_SIZE};
+ uint32_t addr = 0x200;
+ for (size_t instance = 0; instance < 4; instance++) {
+ uint32_t data = 0xdef0 | instance;
+ uint32_t abs_addr = get_addr_translation(addr, instance);
+ mock_reg_iface->read_memory[abs_addr] = data;
+ if (instance == 0) {
+ BOOST_CHECK_EQUAL(block_reg_iface.peek32(addr), data);
+ }
+ BOOST_CHECK_EQUAL(block_reg_iface.peek32(addr, instance), data);
+ }
+}
+
+BOOST_AUTO_TEST_CASE(test_multi_poke32)
+{
+ auto mock_reg_iface = std::make_shared<mock_reg_iface_t>();
+ register_iface_holder mock_holder{mock_reg_iface};
+ multichan_register_iface block_reg_iface{mock_holder, BASE_ADDR, INSTANCE_SIZE};
+ std::vector<uint32_t> addrs = {0, 4, 8, 12, 16, 20, 24, 28};
+ std::vector<uint32_t> data = {
+ 0x0000, 0x0010, 0x0200, 0x3000, 0x0004, 0x0050, 0x0600, 0x7000};
+ block_reg_iface.multi_poke32(addrs, data);
+ for (size_t i = 0; i < addrs.size(); i++) {
+ uint32_t abs_addr = get_addr_translation(addrs[i], 0);
+ BOOST_CHECK_EQUAL(mock_reg_iface->write_memory[abs_addr], data[i]);
+ }
+ std::reverse(data.begin(), data.end());
+ for (size_t instance = 0; instance < 4; instance++) {
+ block_reg_iface.multi_poke32(addrs, data, instance);
+ for (size_t i = 0; i < addrs.size(); i++) {
+ uint32_t abs_addr = get_addr_translation(addrs[i], instance);
+ BOOST_CHECK_EQUAL(mock_reg_iface->write_memory[abs_addr], data[i]);
+ }
+ }
+}
+
+BOOST_AUTO_TEST_CASE(test_block_poke32)
+{
+ auto mock_reg_iface = std::make_shared<mock_reg_iface_t>();
+ register_iface_holder mock_holder{mock_reg_iface};
+ multichan_register_iface block_reg_iface{mock_holder, BASE_ADDR, INSTANCE_SIZE};
+ uint32_t addr = 0x100;
+ std::vector<uint32_t> data = {
+ 0x0000, 0x0010, 0x0200, 0x3000, 0x0004, 0x0050, 0x0600, 0x7000};
+ block_reg_iface.block_poke32(addr, data);
+ for (size_t i = 0; i < data.size(); i++) {
+ uint32_t abs_addr = get_addr_translation(addr + i * sizeof(uint32_t), 0);
+ BOOST_CHECK_EQUAL(mock_reg_iface->write_memory[abs_addr], data[i]);
+ }
+ std::reverse(data.begin(), data.end());
+ for (size_t instance = 0; instance < 4; instance++) {
+ block_reg_iface.block_poke32(addr, data, instance);
+ for (size_t i = 0; i < data.size(); i++) {
+ uint32_t abs_addr =
+ get_addr_translation(addr + i * sizeof(uint32_t), instance);
+ BOOST_CHECK_EQUAL(mock_reg_iface->write_memory[abs_addr], data[i]);
+ }
+ }
+}
+
+BOOST_AUTO_TEST_CASE(test_block_peek32)
+{
+ auto mock_reg_iface = std::make_shared<mock_reg_iface_t>();
+ register_iface_holder mock_holder{mock_reg_iface};
+ multichan_register_iface block_reg_iface{mock_holder, BASE_ADDR, INSTANCE_SIZE};
+ uint32_t addr = 0x200;
+ std::vector<uint32_t> data = {
+ 0x0008, 0x0090, 0x0a00, 0xb000, 0x000c, 0x00d0, 0x0e00, 0xf000};
+ for (size_t instance = 0; instance < 4; instance++) {
+ for (size_t i = 0; i < data.size(); i++) {
+ uint32_t abs_addr =
+ get_addr_translation(addr + i * sizeof(uint32_t), instance);
+ mock_reg_iface->read_memory[abs_addr] = data[i];
+ }
+ std::vector<uint32_t> peek_data =
+ block_reg_iface.block_peek32(addr, data.size(), instance);
+ BOOST_CHECK_EQUAL(peek_data.size(), data.size());
+ for (size_t i = 0; i < data.size(); i++) {
+ BOOST_CHECK_EQUAL(peek_data[i], data[i]);
+ }
+ if (instance == 0) {
+ peek_data = block_reg_iface.block_peek32(addr, data.size());
+ BOOST_CHECK_EQUAL(peek_data.size(), data.size());
+ for (size_t i = 0; i < data.size(); i++) {
+ BOOST_CHECK_EQUAL(peek_data[i], data[i]);
+ }
+ }
+ }
+}
+
+BOOST_AUTO_TEST_CASE(test_poke64)
+{
+ auto mock_reg_iface = std::make_shared<mock_reg_iface_t>();
+ register_iface_holder mock_holder{mock_reg_iface};
+ multichan_register_iface block_reg_iface{mock_holder, BASE_ADDR, INSTANCE_SIZE};
+ uint32_t addr = 0x100;
+ uint64_t data = 0xabcdef12;
+ block_reg_iface.poke64(addr, data);
+ uint32_t abs_addr = get_addr_translation(addr, 0);
+ BOOST_CHECK_EQUAL(
+ mock_reg_iface->write_memory[abs_addr], uint32_t(data & 0xFFFFFFFF));
+ BOOST_CHECK_EQUAL(
+ mock_reg_iface->write_memory[abs_addr + 4], uint32_t((data >> 32) & 0xFFFFFFFF));
+ for (size_t instance = 0; instance < 4; instance++) {
+ data = 0x12345670 | instance;
+ block_reg_iface.poke64(addr, data, instance);
+ abs_addr = get_addr_translation(addr, instance);
+ BOOST_CHECK_EQUAL(
+ mock_reg_iface->write_memory[abs_addr], uint32_t(data & 0xFFFFFFFF));
+ BOOST_CHECK_EQUAL(mock_reg_iface->write_memory[abs_addr + 4],
+ uint32_t((data >> 32) & 0xFFFFFFFF));
+ }
+}
+
+BOOST_AUTO_TEST_CASE(test_peek64)
+{
+ auto mock_reg_iface = std::make_shared<mock_reg_iface_t>();
+ register_iface_holder mock_holder{mock_reg_iface};
+ multichan_register_iface block_reg_iface{mock_holder, BASE_ADDR, INSTANCE_SIZE};
+ uint32_t addr = 0x200;
+ for (size_t instance = 0; instance < 4; instance++) {
+ uint64_t data = 0x9abcdef0 | instance;
+ uint32_t abs_addr = get_addr_translation(addr, instance);
+ mock_reg_iface->read_memory[abs_addr] = uint32_t(data & 0xFFFFFFFF);
+ mock_reg_iface->read_memory[abs_addr + 4] = uint32_t((data >> 32) & 0xFFFFFFFF);
+ if (instance == 0) {
+ BOOST_CHECK_EQUAL(block_reg_iface.peek64(addr), data);
+ }
+ BOOST_CHECK_EQUAL(block_reg_iface.peek64(addr, instance), data);
+ }
+}