1 //
2 // Copyright 2020 Ettus Research, a National Instruments Brand
3 //
4 // SPDX-License-Identifier: GPL-3.0-or-later
5 //
6
7 #include <uhd/rfnoc/mock_block.hpp>
8 #include <uhd/rfnoc/multichan_register_iface.hpp>
9 #include <boost/test/unit_test.hpp>
10 #include <algorithm>
11 #include <iostream>
12 #include <vector>
13
14 using namespace uhd::rfnoc;
15
16 namespace {
17
18 constexpr uint32_t BASE_ADDR = 0x8000;
19 constexpr size_t INSTANCE_SIZE = 0x1000;
20
get_addr_translation(uint32_t offset,size_t instance)21 inline uint32_t get_addr_translation(uint32_t offset, size_t instance)
22 {
23 return offset + BASE_ADDR + INSTANCE_SIZE * instance;
24 }
25
26 } // namespace
27
BOOST_AUTO_TEST_CASE(test_poke32)28 BOOST_AUTO_TEST_CASE(test_poke32)
29 {
30 auto mock_reg_iface = std::make_shared<mock_reg_iface_t>();
31 register_iface_holder mock_holder{mock_reg_iface};
32 multichan_register_iface block_reg_iface{mock_holder, BASE_ADDR, INSTANCE_SIZE};
33 uint32_t addr = 0x100;
34 uint32_t data = 0x1230;
35 block_reg_iface.poke32(addr, data);
36 uint32_t abs_addr = get_addr_translation(addr, 0);
37 BOOST_CHECK_EQUAL(mock_reg_iface->write_memory[abs_addr], data);
38 for (size_t instance = 0; instance < 4; instance++) {
39 data = 0xabc0 | instance;
40 block_reg_iface.poke32(addr, data, instance);
41 abs_addr = get_addr_translation(addr, instance);
42 BOOST_CHECK_EQUAL(mock_reg_iface->write_memory[abs_addr], data);
43 }
44 }
45
BOOST_AUTO_TEST_CASE(test_peek32)46 BOOST_AUTO_TEST_CASE(test_peek32)
47 {
48 auto mock_reg_iface = std::make_shared<mock_reg_iface_t>();
49 register_iface_holder mock_holder{mock_reg_iface};
50 multichan_register_iface block_reg_iface{mock_holder, BASE_ADDR, INSTANCE_SIZE};
51 uint32_t addr = 0x200;
52 for (size_t instance = 0; instance < 4; instance++) {
53 uint32_t data = 0xdef0 | instance;
54 uint32_t abs_addr = get_addr_translation(addr, instance);
55 mock_reg_iface->read_memory[abs_addr] = data;
56 if (instance == 0) {
57 BOOST_CHECK_EQUAL(block_reg_iface.peek32(addr), data);
58 }
59 BOOST_CHECK_EQUAL(block_reg_iface.peek32(addr, instance), data);
60 }
61 }
62
BOOST_AUTO_TEST_CASE(test_multi_poke32)63 BOOST_AUTO_TEST_CASE(test_multi_poke32)
64 {
65 auto mock_reg_iface = std::make_shared<mock_reg_iface_t>();
66 register_iface_holder mock_holder{mock_reg_iface};
67 multichan_register_iface block_reg_iface{mock_holder, BASE_ADDR, INSTANCE_SIZE};
68 std::vector<uint32_t> addrs = {0, 4, 8, 12, 16, 20, 24, 28};
69 std::vector<uint32_t> data = {
70 0x0000, 0x0010, 0x0200, 0x3000, 0x0004, 0x0050, 0x0600, 0x7000};
71 block_reg_iface.multi_poke32(addrs, data);
72 for (size_t i = 0; i < addrs.size(); i++) {
73 uint32_t abs_addr = get_addr_translation(addrs[i], 0);
74 BOOST_CHECK_EQUAL(mock_reg_iface->write_memory[abs_addr], data[i]);
75 }
76 std::reverse(data.begin(), data.end());
77 for (size_t instance = 0; instance < 4; instance++) {
78 block_reg_iface.multi_poke32(addrs, data, instance);
79 for (size_t i = 0; i < addrs.size(); i++) {
80 uint32_t abs_addr = get_addr_translation(addrs[i], instance);
81 BOOST_CHECK_EQUAL(mock_reg_iface->write_memory[abs_addr], data[i]);
82 }
83 }
84 }
85
BOOST_AUTO_TEST_CASE(test_block_poke32)86 BOOST_AUTO_TEST_CASE(test_block_poke32)
87 {
88 auto mock_reg_iface = std::make_shared<mock_reg_iface_t>();
89 register_iface_holder mock_holder{mock_reg_iface};
90 multichan_register_iface block_reg_iface{mock_holder, BASE_ADDR, INSTANCE_SIZE};
91 uint32_t addr = 0x100;
92 std::vector<uint32_t> data = {
93 0x0000, 0x0010, 0x0200, 0x3000, 0x0004, 0x0050, 0x0600, 0x7000};
94 block_reg_iface.block_poke32(addr, data);
95 for (size_t i = 0; i < data.size(); i++) {
96 uint32_t abs_addr = get_addr_translation(addr + i * sizeof(uint32_t), 0);
97 BOOST_CHECK_EQUAL(mock_reg_iface->write_memory[abs_addr], data[i]);
98 }
99 std::reverse(data.begin(), data.end());
100 for (size_t instance = 0; instance < 4; instance++) {
101 block_reg_iface.block_poke32(addr, data, instance);
102 for (size_t i = 0; i < data.size(); i++) {
103 uint32_t abs_addr =
104 get_addr_translation(addr + i * sizeof(uint32_t), instance);
105 BOOST_CHECK_EQUAL(mock_reg_iface->write_memory[abs_addr], data[i]);
106 }
107 }
108 }
109
BOOST_AUTO_TEST_CASE(test_block_peek32)110 BOOST_AUTO_TEST_CASE(test_block_peek32)
111 {
112 auto mock_reg_iface = std::make_shared<mock_reg_iface_t>();
113 register_iface_holder mock_holder{mock_reg_iface};
114 multichan_register_iface block_reg_iface{mock_holder, BASE_ADDR, INSTANCE_SIZE};
115 uint32_t addr = 0x200;
116 std::vector<uint32_t> data = {
117 0x0008, 0x0090, 0x0a00, 0xb000, 0x000c, 0x00d0, 0x0e00, 0xf000};
118 for (size_t instance = 0; instance < 4; instance++) {
119 for (size_t i = 0; i < data.size(); i++) {
120 uint32_t abs_addr =
121 get_addr_translation(addr + i * sizeof(uint32_t), instance);
122 mock_reg_iface->read_memory[abs_addr] = data[i];
123 }
124 std::vector<uint32_t> peek_data =
125 block_reg_iface.block_peek32(addr, data.size(), instance);
126 BOOST_CHECK_EQUAL(peek_data.size(), data.size());
127 for (size_t i = 0; i < data.size(); i++) {
128 BOOST_CHECK_EQUAL(peek_data[i], data[i]);
129 }
130 if (instance == 0) {
131 peek_data = block_reg_iface.block_peek32(addr, data.size());
132 BOOST_CHECK_EQUAL(peek_data.size(), data.size());
133 for (size_t i = 0; i < data.size(); i++) {
134 BOOST_CHECK_EQUAL(peek_data[i], data[i]);
135 }
136 }
137 }
138 }
139
BOOST_AUTO_TEST_CASE(test_poke64)140 BOOST_AUTO_TEST_CASE(test_poke64)
141 {
142 auto mock_reg_iface = std::make_shared<mock_reg_iface_t>();
143 register_iface_holder mock_holder{mock_reg_iface};
144 multichan_register_iface block_reg_iface{mock_holder, BASE_ADDR, INSTANCE_SIZE};
145 uint32_t addr = 0x100;
146 uint64_t data = 0xabcdef12;
147 block_reg_iface.poke64(addr, data);
148 uint32_t abs_addr = get_addr_translation(addr, 0);
149 BOOST_CHECK_EQUAL(
150 mock_reg_iface->write_memory[abs_addr], uint32_t(data & 0xFFFFFFFF));
151 BOOST_CHECK_EQUAL(
152 mock_reg_iface->write_memory[abs_addr + 4], uint32_t((data >> 32) & 0xFFFFFFFF));
153 for (size_t instance = 0; instance < 4; instance++) {
154 data = 0x12345670 | instance;
155 block_reg_iface.poke64(addr, data, instance);
156 abs_addr = get_addr_translation(addr, instance);
157 BOOST_CHECK_EQUAL(
158 mock_reg_iface->write_memory[abs_addr], uint32_t(data & 0xFFFFFFFF));
159 BOOST_CHECK_EQUAL(mock_reg_iface->write_memory[abs_addr + 4],
160 uint32_t((data >> 32) & 0xFFFFFFFF));
161 }
162 }
163
BOOST_AUTO_TEST_CASE(test_peek64)164 BOOST_AUTO_TEST_CASE(test_peek64)
165 {
166 auto mock_reg_iface = std::make_shared<mock_reg_iface_t>();
167 register_iface_holder mock_holder{mock_reg_iface};
168 multichan_register_iface block_reg_iface{mock_holder, BASE_ADDR, INSTANCE_SIZE};
169 uint32_t addr = 0x200;
170 for (size_t instance = 0; instance < 4; instance++) {
171 uint64_t data = 0x9abcdef0 | instance;
172 uint32_t abs_addr = get_addr_translation(addr, instance);
173 mock_reg_iface->read_memory[abs_addr] = uint32_t(data & 0xFFFFFFFF);
174 mock_reg_iface->read_memory[abs_addr + 4] = uint32_t((data >> 32) & 0xFFFFFFFF);
175 if (instance == 0) {
176 BOOST_CHECK_EQUAL(block_reg_iface.peek64(addr), data);
177 }
178 BOOST_CHECK_EQUAL(block_reg_iface.peek64(addr, instance), data);
179 }
180 }
181