μHAL (v2.8.17)
Part of the IPbus software repository
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
test_nodes.cpp
Go to the documentation of this file.
1/*
2---------------------------------------------------------------------------
3
4 This file is part of uHAL.
5
6 uHAL is a hardware access library and programming framework
7 originally developed for upgrades of the Level-1 trigger of the CMS
8 experiment at CERN.
9
10 uHAL is free software: you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation, either version 3 of the License, or
13 (at your option) any later version.
14
15 uHAL is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with uHAL. If not, see <http://www.gnu.org/licenses/>.
22
23 Tom Williams, Rutherford Appleton Laboratory, Oxfordshire
24 email: tom.williams <AT> cern.ch
25
26---------------------------------------------------------------------------
27*/
28
29#include <iomanip>
30#include <typeinfo>
31
34#include "uhal/uhal.hpp"
35
39
40#include <boost/filesystem.hpp>
41#include <boost/test/unit_test.hpp>
42
43
44
45namespace uhal {
46
47
48std::ostream& operator<< (std::ostream& aStream, const std::pair<const Node*, const Node*>& aNodes)
49{
50 aStream << "{";
51 if (aNodes.first != NULL)
52 aStream << "'" << aNodes.first->getPath() << "'";
53 else
54 aStream << "NULL";
55
56 aStream << ", ";
57 if (aNodes.second != NULL)
58 aStream << "'" << aNodes.second->getPath() << "'";
59 else
60 aStream << "NULL";
61
62 aStream << "}";
63 return aStream;
64}
65
66
67namespace tests {
68
70 NodeProperties(const std::string& aIdPath, const uint32_t aAddress, const defs::BlockReadWriteMode aMode, const defs::NodePermission aPermission, const size_t aSize, const std::string& aModule, const size_t aNrDescendants);
72
73 std::string path;
74 std::string id;
75 uint32_t address;
78 size_t size;
79 uint32_t mask;
80 std::string description;
81 std::string module;
82 std::vector<std::string> descendantIds;
83 std::map<std::string, const std::type_info*> descendantTypes;
84 std::string tags;
85 std::unordered_map<std::string,std::string> parameters;
86 std::unordered_map<std::string,std::string> fwInfo;
87 const std::type_info* type;
88};
89
90
92public:
95
96 const std::string addrTableStr;
98
99 std::vector<NodeProperties> nodeProperties;
100};
101
102
104public:
107
108 const std::string addrTableStr;
110
111 std::vector<NodeProperties> nodeProperties;
112};
113
114
117public:
120
121 std::string getAddrFileAbsPath(const std::string& aSuffix)
122 {
123 std::string lResult(addrFileAbsPath);
124 lResult.replace(addrFileAbsPath.size() - 11, 7, aSuffix);
125 return lResult;
126 }
127
128 const std::string addrFileURI;
129 const std::string addrFileAbsPath;
132 std::vector<NodeProperties> nodeProperties;
133};
134
135
136
137NodeProperties::NodeProperties(const std::string& aIdPath, const uint32_t aAddress, const defs::BlockReadWriteMode aMode, const defs::NodePermission aPermission, const size_t aSize, const std::string& aModule, const size_t aNrDescendants) :
138 path(aIdPath),
139 id((aIdPath.rfind('.') == std::string::npos) ? aIdPath : aIdPath.substr(aIdPath.rfind('.') + 1)),
140 address(aAddress),
141 mode(aMode),
142 permission(aPermission),
143 size(aSize),
144 mask(defs::NOMASK),
145 module(aModule),
146 descendantIds(aNrDescendants),
147 type(&typeid(Node))
148{
149}
150
151
153 addrTableStr("<node>"
154 "<node id='regA' address='0x0' />"
155 "<node id='regB' address='0x1' />"
156 "<node id='ram1' address='0x100' mode='block' size='256' />"
157 "<node id='ram2' address='0x210' mode='block' size='16' />"
158 "<node id='aPort' address='0x300' mode='port' size='1024' />"
159 "</node>")
160{
161 BOOST_REQUIRE(addrTableDoc.load_string(addrTableStr.c_str()));
162
163 nodeProperties.push_back(NodeProperties("regA", 0, defs::SINGLE, defs::READWRITE, 1, "", 0));
164 nodeProperties.push_back(NodeProperties("regB", 1, defs::SINGLE, defs::READWRITE, 1, "", 0));
165 nodeProperties.push_back(NodeProperties("ram1", 256, defs::INCREMENTAL, defs::READWRITE, 256, "", 0));
166 nodeProperties.push_back(NodeProperties("ram2", 528, defs::INCREMENTAL, defs::READWRITE, 16, "", 0));
167 nodeProperties.push_back(NodeProperties("aPort", 768, defs::NON_INCREMENTAL, defs::READWRITE, 1024, "", 0));
168}
169
170
172 addrTableStr("<node>"
173 "<node id='reg1' address='0x0'/>"
174 "<node id='reg2' address='0x1'/>"
175
176 "<node id='reg3' address='0x2'>"
177 " <node id='A' mask='0x0000ffff'/>"
178 " <node id='B' mask='0xffff0000'/>"
179 "</node>"
180 "<node id='reg4' address='0x3'>"
181 " <node id='A' mask='0x000000ff'/>"
182 " <node id='B' mask='0x0000ff00'/>"
183 " <node id='C' mask='0x00ff0000'/>"
184 " <node id='D' mask='0xff000000'/>"
185 "</node>"
186
187 "<node id='port1' address='0x4' mode='port' size='256'/>"
188 "<node id='port2' address='0x5' mode='port' size='1024'/>"
189 "<node id='ram1' address='0x08' mode='block' size='8'/>"
190 "<node id='ram2' address='0x10' mode='block' size='16'/>"
191
192 "<node id='module1' address='0x40'>"
193 " <node id='reg1' address='0x0'/>"
194 " <node id='reg2' address='0x1'>"
195 " <node id='mask1' mask='0x00000fff'/>"
196 " <node id='mask2' mask='0x00fff000'/>"
197 " <node id='mask3' mask='0xff000000'/>"
198 " </node>"
199 " <node id='port' address='0x2' mode='port' size='256'/>"
200 " <node id='ram' address='0x10' mode='block' size='16'/>"
201 "</node>"
202
203 "<node id='module2' address='0x60'>"
204 " <node id='regA' address='0x0'/>"
205 " <node id='regB' address='0x1'>"
206 " <node id='A' mask='0x00000fff'/>"
207 " <node id='B' mask='0x00fff000'/>"
208 " <node id='C' mask='0xff000000'/>"
209 " </node>"
210 " <node id='fifo' address='0x2' mode='port' size='256'/>"
211 " <node id='block' address='0x10' mode='block' size='16'/>"
212 "</node>"
213 "</node>")
214{
215 BOOST_REQUIRE(addrTableDoc.load_string(addrTableStr.c_str()));
216
217 nodeProperties.push_back(NodeProperties("reg1", 0, defs::SINGLE, defs::READWRITE, 1, "", 0));
218 nodeProperties.push_back(NodeProperties("reg2", 1, defs::SINGLE, defs::READWRITE, 1, "", 0));
219 nodeProperties.push_back(NodeProperties("reg3", 2, defs::SINGLE, defs::READWRITE, 1, "", 2));
220 nodeProperties.push_back(NodeProperties("reg3.A", 2, defs::SINGLE, defs::READWRITE, 1, "", 0));
221 nodeProperties.back().mask = 0xffff;
222 nodeProperties.push_back(NodeProperties("reg3.B", 2, defs::SINGLE, defs::READWRITE, 1, "", 0));
223 nodeProperties.back().mask = 0xffff0000;
224 nodeProperties.push_back(NodeProperties("reg4", 3, defs::SINGLE, defs::READWRITE, 1, "", 4));
225 nodeProperties.push_back(NodeProperties("reg4.A", 3, defs::SINGLE, defs::READWRITE, 1, "", 0));
226 nodeProperties.back().mask = 0xff;
227 nodeProperties.push_back(NodeProperties("reg4.B", 3, defs::SINGLE, defs::READWRITE, 1, "", 0));
228 nodeProperties.back().mask = 0xff00;
229 nodeProperties.push_back(NodeProperties("reg4.C", 3, defs::SINGLE, defs::READWRITE, 1, "", 0));
230 nodeProperties.back().mask = 0xff0000;
231 nodeProperties.push_back(NodeProperties("reg4.D", 3, defs::SINGLE, defs::READWRITE, 1, "", 0));
232 nodeProperties.back().mask = 0xff000000;
233
234 nodeProperties.push_back(NodeProperties("port1", 4, defs::NON_INCREMENTAL, defs::READWRITE, 256, "", 0));
235 nodeProperties.push_back(NodeProperties("port2", 5, defs::NON_INCREMENTAL, defs::READWRITE, 1024, "", 0));
236 nodeProperties.push_back(NodeProperties("ram1", 8, defs::INCREMENTAL, defs::READWRITE, 8, "", 0));
237 nodeProperties.push_back(NodeProperties("ram2", 16, defs::INCREMENTAL, defs::READWRITE, 16, "", 0));
238
239 nodeProperties.push_back(NodeProperties("module1", 64, defs::HIERARCHICAL, defs::READWRITE, 1, "", 7));
240 nodeProperties.push_back(NodeProperties("module1.reg1", 64, defs::SINGLE, defs::READWRITE, 1, "", 0));
241 nodeProperties.push_back(NodeProperties("module1.reg2", 65, defs::SINGLE, defs::READWRITE, 1, "", 3));
242 nodeProperties.push_back(NodeProperties("module1.reg2.mask1", 65, defs::SINGLE, defs::READWRITE, 1, "", 0));
243 nodeProperties.back().mask = 0xfff;
244 nodeProperties.push_back(NodeProperties("module1.reg2.mask2", 65, defs::SINGLE, defs::READWRITE, 1, "", 0));
245 nodeProperties.back().mask = 0xfff000;
246 nodeProperties.push_back(NodeProperties("module1.reg2.mask3", 65, defs::SINGLE, defs::READWRITE, 1, "", 0));
247 nodeProperties.back().mask = 0xff000000;
248 nodeProperties.push_back(NodeProperties("module1.port", 66, defs::NON_INCREMENTAL, defs::READWRITE, 256, "", 0));
249 nodeProperties.push_back(NodeProperties("module1.ram", 80, defs::INCREMENTAL, defs::READWRITE, 16, "", 0));
250
251 nodeProperties.push_back(NodeProperties("module2", 96, defs::HIERARCHICAL, defs::READWRITE, 1, "", 7));
252 nodeProperties.push_back(NodeProperties("module2.regA", 96, defs::SINGLE, defs::READWRITE, 1, "", 0));
253 nodeProperties.push_back(NodeProperties("module2.regB", 97, defs::SINGLE, defs::READWRITE, 1, "", 3));
254 nodeProperties.push_back(NodeProperties("module2.regB.A", 97, defs::SINGLE, defs::READWRITE, 1, "", 0));
255 nodeProperties.back().mask = 0xfff;
256 nodeProperties.push_back(NodeProperties("module2.regB.B", 97, defs::SINGLE, defs::READWRITE, 1, "", 0));
257 nodeProperties.back().mask = 0xfff000;
258 nodeProperties.push_back(NodeProperties("module2.regB.C", 97, defs::SINGLE, defs::READWRITE, 1, "", 0));
259 nodeProperties.back().mask = 0xff000000;
260 nodeProperties.push_back(NodeProperties("module2.fifo", 98, defs::NON_INCREMENTAL, defs::READWRITE, 256, "", 0));
261 nodeProperties.push_back(NodeProperties("module2.block", 112, defs::INCREMENTAL, defs::READWRITE, 16, "", 0));
262
263 for (size_t i=0; i < nodeProperties.size(); i++) {
264 BOOST_REQUIRE_LE(nodeProperties.at(i).descendantIds.size(), (nodeProperties.size() - i - 1));
265 for (size_t j=0; j < nodeProperties.at(i).descendantIds.size(); j++) {
266 std::string lRelativePath = nodeProperties.at(i+j+1).path.substr(nodeProperties.at(i).path.empty() ? 0 : nodeProperties.at(i).path.size() + 1);
267 nodeProperties.at(i).descendantIds.at(j) = lRelativePath;
268 nodeProperties.at(i).descendantTypes[lRelativePath] = nodeProperties.at(i+j+1).type;
269 }
270 }
271}
272
273
276 addrFileURI(getAddressFileURI()),
277 addrFileAbsPath(boost::filesystem::absolute(boost::filesystem::path(addrFileURI.substr(7))).native()),
278 addrFileLevel2AbsPath(addrFileAbsPath),
279 addrFileLevel3AbsPath(addrFileAbsPath)
280{
281 addrFileLevel2AbsPath.replace(addrFileAbsPath.size() - 11, 0, "level2_");
282 addrFileLevel3AbsPath.replace(addrFileAbsPath.size() - 11, 0, "level3_");
283
285
287 nodeProperties.back().tags = "test";
288 nodeProperties.push_back(NodeProperties("REG_READ_ONLY", 2, defs::SINGLE, defs::READ, 1, addrFileAbsPath, 0));
289 nodeProperties.push_back(NodeProperties("REG_WRITE_ONLY", 3, defs::SINGLE, defs::WRITE, 1, addrFileAbsPath, 0));
290 nodeProperties.push_back(NodeProperties("REG_UPPER_MASK", 4, defs::SINGLE, defs::READWRITE, 1, addrFileAbsPath, 0));
291 nodeProperties.back().mask = 0xffff0000;
292 nodeProperties.push_back(NodeProperties("REG_LOWER_MASK", 4, defs::SINGLE, defs::READWRITE, 1, addrFileAbsPath, 0));
293 nodeProperties.back().mask = 0xffff;
294 nodeProperties.push_back(NodeProperties("REG_MASKED_READ_ONLY", 5, defs::SINGLE, defs::READ, 1, addrFileAbsPath, 0));
295 nodeProperties.back().mask = 0xffff0000;
296 nodeProperties.push_back(NodeProperties("REG_MASKED_WRITE_ONLY", 5, defs::SINGLE, defs::WRITE, 1, addrFileAbsPath, 0));
297 nodeProperties.back().mask = 0xffff;
299 nodeProperties.back().parameters["arg0"] = "val100";
300 nodeProperties.back().parameters["arg1"] = "val101";
301 nodeProperties.push_back(NodeProperties("FIFO", 0x100, defs::NON_INCREMENTAL, defs::READWRITE, 268435456, addrFileAbsPath, 0));
302 nodeProperties.back().tags = "test";
303 nodeProperties.push_back(NodeProperties("REG_OUT_OF_ORDER", 6, defs::SINGLE, defs::READWRITE, 1, addrFileAbsPath, 0));
304 nodeProperties.push_back(NodeProperties("MEM", 0x100000, defs::INCREMENTAL, defs::READWRITE, 262144, addrFileAbsPath, 0));
305 nodeProperties.back().description = "A block memory in an example XML file";
306
307 nodeProperties.push_back(NodeProperties("SUBSYSTEM1", 0x210001, defs::HIERARCHICAL, defs::READWRITE, 1, addrFileAbsPath, 5));
308 nodeProperties.back().parameters["arg0"] = "val200";
309 nodeProperties.back().parameters["arg1"] = "val201";
310 nodeProperties.back().parameters["arg2"] = "val202";
311 nodeProperties.push_back(NodeProperties("SUBSYSTEM1.REG", 0x210002, defs::SINGLE, defs::READWRITE, 1, addrFileLevel2AbsPath, 0));
312 nodeProperties.back().tags = "test";
313 nodeProperties.push_back(NodeProperties("SUBSYSTEM1.MEM", 0x210003, defs::INCREMENTAL, defs::READWRITE, 262144, addrFileLevel2AbsPath, 0));
314 nodeProperties.back().tags = "test";
315 nodeProperties.push_back(NodeProperties("SUBSYSTEM1.SUBMODULE", 0x270001, defs::HIERARCHICAL, defs::READWRITE, 1, addrFileLevel2AbsPath, 2));
316 nodeProperties.back().parameters["arg0"] = "val300";
317 nodeProperties.back().parameters["arg1"] = "val301";
318 nodeProperties.back().parameters["arg2"] = "val10302";
319 nodeProperties.back().parameters["arg3"] = "val10303";
320 nodeProperties.push_back(NodeProperties("SUBSYSTEM1.SUBMODULE.REG", 0x270002, defs::SINGLE, defs::READWRITE, 1, addrFileLevel3AbsPath, 0));
321 nodeProperties.back().tags = "test";
322 nodeProperties.push_back(NodeProperties("SUBSYSTEM1.SUBMODULE.MEM", 0x270003, defs::INCREMENTAL, defs::READWRITE, 256, addrFileLevel3AbsPath, 0));
323 nodeProperties.back().tags = "test";
324
325 nodeProperties.push_back(NodeProperties("SUBSYSTEM2", 0x310001, defs::HIERARCHICAL, defs::READWRITE, 1, addrFileAbsPath, 5));
326 nodeProperties.back().parameters["arg0"] = "val10000";
327 nodeProperties.back().parameters["arg1"] = "val201";
328 nodeProperties.back().parameters["arg2"] = "val202";
329 nodeProperties.back().parameters["arg5"] = "val10005";
330 nodeProperties.push_back(NodeProperties("SUBSYSTEM2.REG", 0x310002, defs::SINGLE, defs::READWRITE, 1, addrFileLevel2AbsPath, 0));
331 nodeProperties.back().tags = "test";
332 nodeProperties.push_back(NodeProperties("SUBSYSTEM2.MEM", 0x310003, defs::INCREMENTAL, defs::READWRITE, 262144, addrFileLevel2AbsPath, 0));
333 nodeProperties.back().tags = "test";
334 nodeProperties.push_back(NodeProperties("SUBSYSTEM2.SUBMODULE", 0x370001, defs::HIERARCHICAL, defs::READWRITE, 1, addrFileLevel2AbsPath, 2));
335 nodeProperties.back().parameters["arg0"] = "val300";
336 nodeProperties.back().parameters["arg1"] = "val301";
337 nodeProperties.back().parameters["arg2"] = "val10302";
338 nodeProperties.back().parameters["arg3"] = "val10303";
339 nodeProperties.push_back(NodeProperties("SUBSYSTEM2.SUBMODULE.REG", 0x370002, defs::SINGLE, defs::READWRITE, 1, addrFileLevel3AbsPath, 0));
340 nodeProperties.back().tags = "test";
341 nodeProperties.push_back(NodeProperties("SUBSYSTEM2.SUBMODULE.MEM", 0x370003, defs::INCREMENTAL, defs::READWRITE, 256, addrFileLevel3AbsPath, 0));
342 nodeProperties.back().tags = "test";
343
344 nodeProperties.push_back(NodeProperties("SMALL_MEM", 0x400000, defs::INCREMENTAL, defs::READWRITE, 256, addrFileAbsPath, 0));
345 nodeProperties.push_back(NodeProperties("LARGE_MEM", 0x1000000, defs::INCREMENTAL, defs::READWRITE, 26214400, addrFileAbsPath, 0));
346
347 nodeProperties.push_back(NodeProperties("SUBSYSTEM3", 0x600000, defs::HIERARCHICAL, defs::READWRITE, 1, addrFileAbsPath, 28));
348
349 nodeProperties.push_back(NodeProperties("SUBSYSTEM3.DERIVEDNODE", 0x600000, defs::HIERARCHICAL, defs::READWRITE, 1, getAddrFileAbsPath("derived_address"), 4));
350 nodeProperties.back().type = &typeid(DummyParentNode);
351 nodeProperties.push_back(NodeProperties("SUBSYSTEM3.DERIVEDNODE.REG", 0x600001, defs::SINGLE, defs::READWRITE, 1, getAddrFileAbsPath("derived_address"), 0));
352 nodeProperties.push_back(NodeProperties("SUBSYSTEM3.DERIVEDNODE.REG_WRITE_ONLY", 0x600003, defs::SINGLE, defs::WRITE, 1, getAddrFileAbsPath("derived_address"), 0));
353 nodeProperties.push_back(NodeProperties("SUBSYSTEM3.DERIVEDNODE.REG_UPPER_MASK", 0x600004, defs::SINGLE, defs::READWRITE, 1, getAddrFileAbsPath("derived_address"), 0));
354 nodeProperties.back().mask = 0xFFFF0000;
355 nodeProperties.push_back(NodeProperties("SUBSYSTEM3.DERIVEDNODE.REG_LOWER_MASK", 0x600004, defs::SINGLE, defs::READWRITE, 1, getAddrFileAbsPath("derived_address"), 0));
356 nodeProperties.back().mask = 0xFFFF;
357
358 // 0x600000 + 0x10 + 0x10010
359 const uint32_t lDerivedModule1Addr = 0x600000 + (0x10 | 0x10010);
360 nodeProperties.push_back(NodeProperties("SUBSYSTEM3.DERIVEDMODULE1", lDerivedModule1Addr, defs::HIERARCHICAL, defs::READWRITE, 1, getAddrFileAbsPath("derived_address"), 2));
361 nodeProperties.back().type = &typeid(DummyChildNode);
362 nodeProperties.push_back(NodeProperties("SUBSYSTEM3.DERIVEDMODULE1.REG", lDerivedModule1Addr + 1, defs::SINGLE, defs::READWRITE, 1, getAddrFileAbsPath("derived_level2_module1"), 0));
363 nodeProperties.back().tags = "test";
364 nodeProperties.push_back(NodeProperties("SUBSYSTEM3.DERIVEDMODULE1.MEM", lDerivedModule1Addr + 2, defs::INCREMENTAL, defs::READWRITE, 262144, getAddrFileAbsPath("derived_level2_module1"), 0));
365 nodeProperties.back().tags = "test";
366
367 const uint32_t lDerivedModule2Addr = 0x600000 + (0x30 | 0x10010 | 0x10010);
368 nodeProperties.push_back(NodeProperties("SUBSYSTEM3.DERIVEDMODULE2", lDerivedModule2Addr, defs::HIERARCHICAL, defs::READWRITE, 1, getAddrFileAbsPath("derived_address"), 4));
369 nodeProperties.back().parameters["arg3"] = "val3";
370 nodeProperties.back().type = &typeid(DummyChildNode);
371 nodeProperties.push_back(NodeProperties("SUBSYSTEM3.DERIVEDMODULE2.REG", lDerivedModule2Addr + 1, defs::SINGLE, defs::READWRITE, 1, getAddrFileAbsPath("derived_level3_plain"), 0));
372 nodeProperties.back().tags = "test";
373 nodeProperties.push_back(NodeProperties("SUBSYSTEM3.DERIVEDMODULE2.REG_WRITE_ONLY", lDerivedModule2Addr + 3, defs::SINGLE, defs::WRITE, 1, getAddrFileAbsPath("derived_level3_plain"), 0));
374 nodeProperties.push_back(NodeProperties("SUBSYSTEM3.DERIVEDMODULE2.REG_UPPER_MASK", lDerivedModule2Addr + 4, defs::SINGLE, defs::READWRITE, 1, getAddrFileAbsPath("derived_level3_plain"), 0));
375 nodeProperties.back().mask = 0xFFFF0000;
376 nodeProperties.push_back(NodeProperties("SUBSYSTEM3.DERIVEDMODULE2.REG_LOWER_MASK", lDerivedModule2Addr + 4, defs::SINGLE, defs::READWRITE, 1, getAddrFileAbsPath("derived_level3_plain"), 0));
377 nodeProperties.back().mask = 0xFFFF;
378
379 const uint32_t lDerivedModule3Addr = 0x600000 + (0x50 | 0x10010 | 0x10010);
380 nodeProperties.push_back(NodeProperties("SUBSYSTEM3.DERIVEDMODULE3", lDerivedModule3Addr, defs::HIERARCHICAL, defs::READWRITE, 1, getAddrFileAbsPath("derived_address"), 4));
381 nodeProperties.back().parameters["arg3"] = "val3";
382 nodeProperties.back().type = &typeid(DummyChildNode);
383 nodeProperties.push_back(NodeProperties("SUBSYSTEM3.DERIVEDMODULE3.REG", lDerivedModule3Addr + 1, defs::SINGLE, defs::READWRITE, 1, getAddrFileAbsPath("derived_level3_class"), 0));
384 nodeProperties.back().tags = "test";
385 nodeProperties.push_back(NodeProperties("SUBSYSTEM3.DERIVEDMODULE3.REG_WRITE_ONLY", lDerivedModule3Addr + 3, defs::SINGLE, defs::WRITE, 1, getAddrFileAbsPath("derived_level3_class"), 0));
386 nodeProperties.push_back(NodeProperties("SUBSYSTEM3.DERIVEDMODULE3.REG_UPPER_MASK", lDerivedModule3Addr + 4, defs::SINGLE, defs::READWRITE, 1, getAddrFileAbsPath("derived_level3_class"), 0));
387 nodeProperties.back().mask = 0xFFFF0000;
388 nodeProperties.push_back(NodeProperties("SUBSYSTEM3.DERIVEDMODULE3.REG_LOWER_MASK", lDerivedModule3Addr + 4, defs::SINGLE, defs::READWRITE, 1, getAddrFileAbsPath("derived_level3_class"), 0));
389 nodeProperties.back().mask = 0xFFFF;
390
391 nodeProperties.push_back(NodeProperties("SUBSYSTEM3.DERIVEDMODULE4", 0x610070, defs::HIERARCHICAL, defs::READWRITE, 1, getAddrFileAbsPath("derived_address"), 4));
392 nodeProperties.back().type = &typeid(DummyChildNode);
393 nodeProperties.push_back(NodeProperties("SUBSYSTEM3.DERIVEDMODULE4.REG", 0x610071, defs::SINGLE, defs::READWRITE, 1, getAddrFileAbsPath("derived_level3_class"), 0));
394 nodeProperties.back().tags = "test";
395 nodeProperties.push_back(NodeProperties("SUBSYSTEM3.DERIVEDMODULE4.REG_WRITE_ONLY", 0x610073, defs::SINGLE, defs::WRITE, 1, getAddrFileAbsPath("derived_level3_class"), 0));
396 nodeProperties.push_back(NodeProperties("SUBSYSTEM3.DERIVEDMODULE4.REG_UPPER_MASK", 0x610074, defs::SINGLE, defs::READWRITE, 1, getAddrFileAbsPath("derived_level3_class"), 0));
397 nodeProperties.back().mask = 0xFFFF0000;
398 nodeProperties.push_back(NodeProperties("SUBSYSTEM3.DERIVEDMODULE4.REG_LOWER_MASK", 0x610074, defs::SINGLE, defs::READWRITE, 1, getAddrFileAbsPath("derived_level3_class"), 0));
399 nodeProperties.back().mask = 0xFFFF;
400
401 nodeProperties.push_back(NodeProperties("SUBSYSTEM3.BADNODE", 0x600100, defs::HIERARCHICAL, defs::READWRITE, 1, getAddrFileAbsPath("derived_address"), 4));
402 nodeProperties.push_back(NodeProperties("SUBSYSTEM3.BADNODE.REG", 0x600101, defs::SINGLE, defs::READWRITE, 1, getAddrFileAbsPath("derived_address"), 0));
403 nodeProperties.push_back(NodeProperties("SUBSYSTEM3.BADNODE.REG_WRITE_ONLY", 0x600103, defs::SINGLE, defs::WRITE, 1, getAddrFileAbsPath("derived_address"), 0));
404 nodeProperties.push_back(NodeProperties("SUBSYSTEM3.BADNODE.REG_UPPER_MASK", 0x600104, defs::SINGLE, defs::READWRITE, 1, getAddrFileAbsPath("derived_address"), 0));
405 nodeProperties.back().mask = 0xFFFF0000;
406 nodeProperties.push_back(NodeProperties("SUBSYSTEM3.BADNODE.REG_LOWER_MASK", 0x600104, defs::SINGLE, defs::READWRITE, 1, getAddrFileAbsPath("derived_address"), 0));
407 nodeProperties.back().mask = 0xFFFF;
408
409 nodeProperties.push_back(NodeProperties("IPBUS_ENDPOINT", 0x700000, defs::SINGLE, defs::READWRITE, 1, addrFileAbsPath, 0));
410 nodeProperties.back().fwInfo["type"] = "endpoint";
411 nodeProperties.back().fwInfo["width"] = "0x10";
412
413 for (size_t i=0; i < nodeProperties.size(); i++) {
414 BOOST_REQUIRE_LE(nodeProperties.at(i).descendantIds.size(), (nodeProperties.size() - i - 1));
415 for (size_t j=0; j < nodeProperties.at(i).descendantIds.size(); j++) {
416 std::string lRelativePath = nodeProperties.at(i+j+1).path.substr(nodeProperties.at(i).path.empty() ? 0 : nodeProperties.at(i).path.size() + 1);
417 nodeProperties.at(i).descendantIds.at(j) = lRelativePath;
418 nodeProperties.at(i).descendantTypes[lRelativePath] = nodeProperties.at(i+j+1).type;
419 }
420 }
421}
422
423
424void checkProperties(const uhal::Node& aNode, const NodeProperties& aExpected)
425{
426 BOOST_CHECK_EQUAL(aNode.getPath(), aExpected.path);
427 BOOST_CHECK_EQUAL(aNode.getId(), aExpected.id);
428 BOOST_CHECK_EQUAL(aNode.getAddress(), aExpected.address);
429 BOOST_CHECK_EQUAL(aNode.getPermission(), aExpected.permission);
430 BOOST_CHECK_EQUAL(aNode.getSize(), aExpected.size);
431 BOOST_CHECK_EQUAL(aNode.getMask(), aExpected.mask);
432 BOOST_CHECK_EQUAL(aNode.getMode(), aExpected.mode);
433
434 BOOST_CHECK_EQUAL(aNode.getDescription(), aExpected.description);
435 BOOST_CHECK_EQUAL(aNode.getModule(), aExpected.module);
436 BOOST_CHECK_EQUAL(aNode.getTags(), aExpected.tags);
437
438 // Validate parameters map
439 BOOST_CHECK_EQUAL(aNode.getParameters().size(), aExpected.parameters.size());
440 for (std::unordered_map<std::string,std::string>::const_iterator lIt=aExpected.parameters.begin(); lIt!=aExpected.parameters.end(); lIt++) {
441 BOOST_CHECK_MESSAGE(aNode.getParameters().count(lIt->first) == size_t(1), "Parameter '" << lIt->first << "' was not found");
442 if (aNode.getParameters().count(lIt->first) == size_t(1)){
443 BOOST_CHECK_MESSAGE(aNode.getParameters().find(lIt->first)->second == lIt->second, "Parameter '" << lIt->first << "' has value '" << aNode.getParameters().find(lIt->first)->second << "'; expected value '" << lIt->second << "'");
444 }
445 }
446 for (std::unordered_map<std::string,std::string>::const_iterator lIt=aNode.getParameters().begin(); lIt!=aNode.getParameters().end(); lIt++) {
447 BOOST_CHECK_MESSAGE(aExpected.parameters.count(lIt->first) == size_t(1), "Node has unexpected parameter '" << lIt->first << "'" << " (value: '" << lIt->second << "')");
448 }
449
450 // Validate firmware info map
451 BOOST_CHECK_EQUAL(aNode.getFirmwareInfo().size(), aExpected.fwInfo.size());
452 for (std::unordered_map<std::string,std::string>::const_iterator lIt=aExpected.fwInfo.begin(); lIt!=aExpected.fwInfo.end(); lIt++) {
453 BOOST_CHECK_MESSAGE(aNode.getFirmwareInfo().count(lIt->first) == size_t(1), "FW info '" << lIt->first << "' was not found");
454 if (aNode.getFirmwareInfo().count(lIt->first) == size_t(1)){
455 BOOST_CHECK_MESSAGE(aNode.getFirmwareInfo().find(lIt->first)->second == lIt->second, "FW info '" << lIt->first << "' has value '" << aNode.getFirmwareInfo().find(lIt->first)->second << "'; expected value '" << lIt->second << "'");
456 }
457 }
458 for (std::unordered_map<std::string,std::string>::const_iterator lIt=aNode.getFirmwareInfo().begin(); lIt!=aNode.getFirmwareInfo().end(); lIt++) {
459 BOOST_CHECK_MESSAGE(aExpected.fwInfo.count(lIt->first) == size_t(1), "Node has unexpected FW info '" << lIt->first << "'" << " (value: '" << lIt->second << "')");
460 }
461}
462
463
464void checkExceptionsThrownByReadWrite(const uhal::Node& aNode, const NodeProperties& aProperties)
465{
466 // Single-word read/write methods - check exceptions thrown when they should be
467 if (aProperties.permission == defs::READ)
468 BOOST_CHECK_THROW(aNode.write(1), uhal::exception::WriteAccessDenied);
469 if (aProperties.permission == defs::WRITE) {
470 BOOST_CHECK_THROW(aNode.read(), uhal::exception::ReadAccessDenied);
471 if (aProperties.mask != 0xFFFFFFFF)
472 BOOST_CHECK_THROW(aNode.write(1), uhal::exception::WriteAccessDenied);
473 }
474
475 // Block read/write methods - check exceptions thrown when they should be
476 if (aProperties.mode == defs::SINGLE) {
477 for (size_t n=0; n <= 0xF; n++) {
478 if (n == 1)
479 continue;
480 BOOST_CHECK_THROW(aNode.readBlock(n), exception::BulkTransferOnSingleRegister);
481 BOOST_CHECK_THROW(aNode.writeBlock(std::vector<uint32_t>(n)), exception::BulkTransferOnSingleRegister);
482 }
483 if (aProperties.permission == defs::READ)
484 BOOST_CHECK_THROW(aNode.writeBlock(std::vector<uint32_t>(1)), exception::WriteAccessDenied);
485 if (aProperties.permission == defs::WRITE)
486 BOOST_CHECK_THROW(aNode.readBlock(1), exception::ReadAccessDenied);
487 }
488 else if (aProperties.mode != defs::HIERARCHICAL) {
489 for (size_t n=0; n <= aNode.getSize(); n++) {
490 if (aProperties.permission == defs::WRITE)
491 BOOST_CHECK_THROW(aNode.readBlock(n), exception::ReadAccessDenied);
492 if (aProperties.permission == defs::READ)
493 BOOST_CHECK_THROW(aNode.writeBlock(std::vector<uint32_t>(n)), exception::WriteAccessDenied);
494 }
495
496 for (size_t n=aNode.getSize()+1; n <= aNode.getSize() + 0x10; n++) {
497 BOOST_CHECK_THROW(aNode.readBlock(n), exception::BulkTransferRequestedTooLarge);
498 BOOST_CHECK_THROW(aNode.writeBlock(std::vector<uint32_t>(n)), exception::BulkTransferRequestedTooLarge);
499 }
500 }
501
502 // Block read/write offset methods - check exceptions thrown when they should be
503 switch (aProperties.mode) {
504 case defs::SINGLE :
505 for (size_t i=0; i <= 0xF; i++) {
506 // std::cout << " i = 0x" << std::hex << i << std::endl;
507 for (size_t j=0; j <= 0xF; j++) {
508 BOOST_CHECK_THROW(aNode.readBlockOffset(i, j), exception::BulkTransferOffsetRequestedForSingleRegister);
509 BOOST_CHECK_THROW(aNode.writeBlockOffset(std::vector<uint32_t>(i), j), exception::BulkTransferOffsetRequestedForSingleRegister);
510 }
511 }
512 break;
513
515 for (size_t i=0; i <= 0xF; i++) {
516 for (size_t j=0; j <= 0xF; j++) {
517 BOOST_CHECK_THROW(aNode.readBlockOffset(i, j), exception::BulkTransferOffsetRequestedForFifo);
518 BOOST_CHECK_THROW(aNode.writeBlockOffset(std::vector<uint32_t>(i), j), exception::BulkTransferOffsetRequestedForFifo);
519 }
520 }
521 break;
522
523 case defs::INCREMENTAL :
524 for (size_t lOffset=0; lOffset <= 0xF; lOffset++) {
525 for (size_t n = aNode.getSize() + 1 - lOffset; n <= aNode.getSize() + 0xF - lOffset; n++) {
526 BOOST_CHECK_THROW(aNode.readBlockOffset(n, lOffset), exception::BulkTransferRequestedTooLarge);
527 BOOST_CHECK_THROW(aNode.writeBlockOffset(std::vector<uint32_t>(n), lOffset), exception::BulkTransferRequestedTooLarge);
528 }
529 }
530 break;
531
532 case defs::HIERARCHICAL :
533 break;
534 }
535}
536
537
538void checkDescendants (const uhal::Node& aNode, const NodeProperties& aProperties)
539{
540 // 1) Given an empty ID string, 'getNode' should return same object
541 BOOST_CHECK_EQUAL(&aNode.getNode(""), &aNode);
542
543 // 2) 'getNode' should throw given an invalid ID
544 BOOST_CHECK_THROW(aNode.getNode("."), exception::NoBranchFoundWithGivenUID);
545 BOOST_CHECK_THROW(aNode.getNode("some_invalid_id"), exception::NoBranchFoundWithGivenUID);
546
547 // 3) 'getNodes' should return relative IDs of all descendants (order is not defined)
548 std::vector<std::string> lReturnedIds(aNode.getNodes());
549 BOOST_CHECK_EQUAL(lReturnedIds.size(), aProperties.descendantIds.size());
550 std::vector<std::string> lExpectedIds(aProperties.descendantIds);
551 std::sort(lReturnedIds.begin(), lReturnedIds.end());
552 std::sort(lExpectedIds.begin(), lExpectedIds.end());
553
554 BOOST_CHECK_EQUAL_COLLECTIONS(lReturnedIds.begin(), lReturnedIds.end(), lExpectedIds.begin(), lExpectedIds.end());
555
556 for (std::vector<std::string>::const_iterator lIt=lReturnedIds.begin(); lIt != lReturnedIds.end(); lIt++) {
557 const std::type_info& lType = *aProperties.descendantTypes.at(*lIt);
558
559 // 4) Each descendant should be accessible through 'getNode' method
560 BOOST_CHECK_NO_THROW(aNode.getNode(*lIt));
561 BOOST_CHECK(typeid(aNode.getNode(*lIt)) == lType);
562 BOOST_CHECK_EQUAL(&aNode.getNode(*lIt), &aNode.getNode(*lIt).getNode(""));
563
564 BOOST_CHECK_THROW(aNode.getNode("." + *lIt), exception::NoBranchFoundWithGivenUID);
565 BOOST_CHECK_THROW(aNode.getNode(*lIt + "."), exception::NoBranchFoundWithGivenUID);
566
567 // 5) Templated 'getNode' method should return pointer to same object instance as non-templated method, but throw for invalid casts
568 BOOST_CHECK_EQUAL(&aNode.getNode<Node>(*lIt), &aNode.getNode(*lIt));
569 if (lType == typeid(Node)) {
570 BOOST_CHECK_THROW(aNode.getNode<DummyParentNode>(*lIt), exception::BadNodeCast);
571 BOOST_CHECK_THROW(aNode.getNode<DummyChildNode>(*lIt), exception::BadNodeCast);
572 }
573 else if (lType == typeid(DummyParentNode)) {
574 BOOST_CHECK_EQUAL(static_cast<const Node*>(&aNode.getNode<DummyParentNode>(*lIt)), &aNode.getNode(*lIt));
575 BOOST_CHECK_THROW(aNode.getNode<DummyChildNode>(*lIt), exception::BadNodeCast);
576 }
577 else if (lType == typeid(DummyChildNode)) {
578 BOOST_CHECK_EQUAL(static_cast<const Node*>(&aNode.getNode<DummyParentNode>(*lIt)), &aNode.getNode(*lIt));
579 BOOST_CHECK_EQUAL(static_cast<const Node*>(&aNode.getNode<DummyChildNode>(*lIt)), &aNode.getNode(*lIt));
580 }
581 else {
582 BOOST_CHECK_MESSAGE(false, "Unit tests have not been written to handle node class '" << aProperties.type->name() << "'");
583 }
584
585 // 6) For each descendant, the same node object should be returned by calling 'getNode' once using relative ID path, or twice using 2 parts of relative ID path
586 size_t lPositionOfDot(lIt->find("."));
587 while (lPositionOfDot != std::string::npos) {
588 std::string lPathPart1(lIt->substr(0, lPositionOfDot));
589 std::string lPathPart2(lIt->substr(lPositionOfDot+1));
590
591 BOOST_CHECK_EQUAL(&aNode.getNode(*lIt), &aNode.getNode(lPathPart1).getNode(lPathPart2));
592
593 lPositionOfDot = lIt->find(".", lPositionOfDot + 1);
594 }
595 }
596
597 // TODO: Add test that vector returned by getNodes("someRegex") is correct
598}
599
600
601bool nodeAddrCompare (const Node* aNodeL, const Node* aNodeR)
602{
603 return ( aNodeL->getAddress() < aNodeR->getAddress() );
604}
605
606
607void checkIteration(const uhal::Node& aNode, const NodeProperties& aProperties)
608{
609 // Check that sequence of nodes returned by iterator is correct
610 std::vector<const uhal::Node*> lExpectedNodes;
611 lExpectedNodes.push_back(&aNode);
612 for (std::vector<std::string>::const_iterator lIt = aProperties.descendantIds.begin(); lIt != aProperties.descendantIds.end(); lIt++)
613 lExpectedNodes.push_back(&aNode.getNode(*lIt));
614 std::stable_sort(lExpectedNodes.begin(), lExpectedNodes.end(), nodeAddrCompare);
615
616 size_t lItCount = 0;
617 for (uhal::Node::const_iterator lIt = aNode.begin(); lIt != aNode.end(); lIt++, lItCount++) {
618 if (lItCount < lExpectedNodes.size())
619 BOOST_CHECK_EQUAL(&*lIt, lExpectedNodes.at(lItCount));
620 else
621 BOOST_CHECK(false);
622 }
623 BOOST_CHECK_EQUAL(lItCount, lExpectedNodes.size());
624}
625
626
627void checkLineage(const uhal::Node& aTopNode, const uhal::Node& aNode)
628{
629 // 1) Check lineage returned with top-most node as argument
630 std::vector<const Node*> lExpected(1, &aTopNode);
631 const std::string lPath(aNode.getPath());
632
633 size_t lDotIndex = aNode.getPath().find('.');
634 while (lDotIndex != std::string::npos) {
635 lExpected.push_back(&aTopNode.getNode(lPath.substr(0, lDotIndex)));
636 lDotIndex = aNode.getPath().find('.', lDotIndex + 1);
637 }
638
639 const std::vector<const Node*> lReturned = aNode.getLineage(aTopNode);
640 BOOST_CHECK_EQUAL_COLLECTIONS(lReturned.begin(), lReturned.end(), lExpected.begin(), lExpected.end());
641
642 // 2) Check lineage returned with intermediate-level nodes as argument (e.g. top node's child, grandchild, etc)
643 for (size_t i = 1; i < lExpected.size(); i++) {
644 const std::vector<const Node*> lExpected2(lExpected.begin()+i, lExpected.end());
645 const std::vector<const Node*> lReturned2(aNode.getLineage(*lExpected.at(i)));
646
647 BOOST_CHECK_EQUAL_COLLECTIONS(lReturned2.begin(), lReturned2.end(), lExpected2.begin(), lExpected2.end());
648 }
649}
650
651
652void checkNodeTree(const uhal::Node& aNode, const std::vector<NodeProperties>& aExpectedProperties)
653{
654 for (std::vector<NodeProperties>::const_iterator lIt = aExpectedProperties.begin(); lIt != aExpectedProperties.end(); lIt++) {
655 BOOST_TEST_MESSAGE("Node '" << lIt->path << "'");
656 const uhal::Node& lNode = (lIt->path.empty() ? aNode : aNode.getNode(lIt->path));
657
658 checkProperties(lNode, *lIt);
660 checkDescendants(lNode, *lIt);
661 checkIteration(lNode, *lIt);
662
663 if (&lNode != &aNode)
664 checkLineage(aNode, lNode);
665 else
666 BOOST_CHECK_THROW(lNode.getLineage(aNode), std::runtime_error);
667 }
668}
669
670
671pugi::xml_node getNthChild(const pugi::xml_node& aNode, const size_t aIndex)
672{
673 pugi::xml_node lNode = aNode.first_child();
674 for (size_t i = 0; i < aIndex; i++)
675 lNode = lNode.next_sibling();
676 return lNode;
677}
678
679void setAttribute(pugi::xml_node aNode, const std::string& aName, const std::string& aValue)
680{
681 aNode.remove_attribute(aName.c_str());
682 aNode.append_attribute(aName.c_str()).set_value(aValue.c_str());
683}
684
685
686BOOST_AUTO_TEST_SUITE( nodes )
687
688
690 const std::shared_ptr<uhal::Node> lTopNode(NodeTreeBuilder::getInstance().getNodeTree(addrFileURI, boost::filesystem::current_path() / "."));
691
692 checkNodeTree(*lTopNode, nodeProperties);
693}
694
695
697 const std::shared_ptr<uhal::Node> lTopNode(NodeTreeBuilder::getInstance().getNodeTree(addrFileURI, boost::filesystem::current_path() / "."));
698
699 BOOST_CHECK_EQUAL(detail::getAddressDescription(*lTopNode, 0, 0), "no matching nodes");
700 BOOST_CHECK_EQUAL(detail::getAddressDescription(*lTopNode, 1, 0), "node \"REG\"");
701 BOOST_CHECK_EQUAL(detail::getAddressDescription(*lTopNode, 2, 0), "node \"REG_READ_ONLY\"");
702 BOOST_CHECK_EQUAL(detail::getAddressDescription(*lTopNode, 3, 0), "node \"REG_WRITE_ONLY\"");
703 BOOST_CHECK_EQUAL(detail::getAddressDescription(*lTopNode, 4, 0), "nodes \"REG_UPPER_MASK\", \"REG_LOWER_MASK\"");
704 BOOST_CHECK_EQUAL(detail::getAddressDescription(*lTopNode, 4, 1), "2 nodes match");
705 BOOST_CHECK_EQUAL(detail::getAddressDescription(*lTopNode, 4, 2), "nodes \"REG_UPPER_MASK\", \"REG_LOWER_MASK\"");
706 BOOST_CHECK_EQUAL(detail::getAddressDescription(*lTopNode, 4, 3), "nodes \"REG_UPPER_MASK\", \"REG_LOWER_MASK\"");
707 BOOST_CHECK_EQUAL(detail::getAddressDescription(*lTopNode, 5, 0), "nodes \"REG_MASKED_READ_ONLY\", \"REG_MASKED_WRITE_ONLY\"");
708 BOOST_CHECK_EQUAL(detail::getAddressDescription(*lTopNode, 5, 1), "2 nodes match");
709 BOOST_CHECK_EQUAL(detail::getAddressDescription(*lTopNode, 5, 2), "nodes \"REG_MASKED_READ_ONLY\", \"REG_MASKED_WRITE_ONLY\"");
710 BOOST_CHECK_EQUAL(detail::getAddressDescription(*lTopNode, 5, 3), "nodes \"REG_MASKED_READ_ONLY\", \"REG_MASKED_WRITE_ONLY\"");
711 BOOST_CHECK_EQUAL(detail::getAddressDescription(*lTopNode, 6, 0), "nodes \"REG_PARS\", \"REG_OUT_OF_ORDER\"");
712 BOOST_CHECK_EQUAL(detail::getAddressDescription(*lTopNode, 6, 1), "2 nodes match");
713 BOOST_CHECK_EQUAL(detail::getAddressDescription(*lTopNode, 6, 2), "nodes \"REG_PARS\", \"REG_OUT_OF_ORDER\"");
714 BOOST_CHECK_EQUAL(detail::getAddressDescription(*lTopNode, 6, 3), "nodes \"REG_PARS\", \"REG_OUT_OF_ORDER\"");
715 BOOST_CHECK_EQUAL(detail::getAddressDescription(*lTopNode, 7, 0), "no matching nodes");
716
717 BOOST_CHECK_EQUAL(detail::getAddressDescription(*lTopNode, 0x0fffff, 0), "no matching nodes");
718 BOOST_CHECK_EQUAL(detail::getAddressDescription(*lTopNode, 0x100000, 0), "node \"MEM\"");
719 BOOST_CHECK_EQUAL(detail::getAddressDescription(*lTopNode, 0x100001, 0), "node \"MEM\"");
720 BOOST_CHECK_EQUAL(detail::getAddressDescription(*lTopNode, 0x100010, 0), "node \"MEM\"");
721 BOOST_CHECK_EQUAL(detail::getAddressDescription(*lTopNode, 0x130000, 0), "node \"MEM\"");
722 BOOST_CHECK_EQUAL(detail::getAddressDescription(*lTopNode, 0x13ffff, 0), "node \"MEM\"");
723 BOOST_CHECK_EQUAL(detail::getAddressDescription(*lTopNode, 0x140000, 0), "no matching nodes");
724
725 BOOST_CHECK_EQUAL(detail::getAddressDescription(*lTopNode, 0x200000, 0), "no matching nodes");
726 BOOST_CHECK_EQUAL(detail::getAddressDescription(*lTopNode, 0x210002, 0), "node \"SUBSYSTEM1.REG\"");
727 BOOST_CHECK_EQUAL(detail::getAddressDescription(*lTopNode, 0x210003, 0), "node \"SUBSYSTEM1.MEM\"");
728 BOOST_CHECK_EQUAL(detail::getAddressDescription(*lTopNode, 0x210004, 0), "node \"SUBSYSTEM1.MEM\"");
729 BOOST_CHECK_EQUAL(detail::getAddressDescription(*lTopNode, 0x250002, 0), "node \"SUBSYSTEM1.MEM\"");
730 BOOST_CHECK_EQUAL(detail::getAddressDescription(*lTopNode, 0x250003, 0), "no matching nodes");
731
732 BOOST_CHECK_EQUAL(detail::getAddressDescription(*lTopNode, 0x270001, 0), "no matching nodes");
733 BOOST_CHECK_EQUAL(detail::getAddressDescription(*lTopNode, 0x270002, 0), "node \"SUBSYSTEM1.SUBMODULE.REG\"");
734 BOOST_CHECK_EQUAL(detail::getAddressDescription(*lTopNode, 0x270003, 0), "node \"SUBSYSTEM1.SUBMODULE.MEM\"");
735 BOOST_CHECK_EQUAL(detail::getAddressDescription(*lTopNode, 0x270004, 0), "node \"SUBSYSTEM1.SUBMODULE.MEM\"");
736 BOOST_CHECK_EQUAL(detail::getAddressDescription(*lTopNode, 0x270102, 0), "node \"SUBSYSTEM1.SUBMODULE.MEM\"");
737 BOOST_CHECK_EQUAL(detail::getAddressDescription(*lTopNode, 0x270103, 0), "no matching nodes");
738
739 BOOST_CHECK_EQUAL(detail::getAddressDescription(*lTopNode, 0x600000, 0), "no matching nodes");
740 BOOST_CHECK_EQUAL(detail::getAddressDescription(*lTopNode, 0x600001, 0), "node \"SUBSYSTEM3.DERIVEDNODE.REG\"");
741 BOOST_CHECK_EQUAL(detail::getAddressDescription(*lTopNode, 0x600002, 0), "no matching nodes");
742 BOOST_CHECK_EQUAL(detail::getAddressDescription(*lTopNode, 0x600003, 0), "node \"SUBSYSTEM3.DERIVEDNODE.REG_WRITE_ONLY\"");
743 BOOST_CHECK_EQUAL(detail::getAddressDescription(*lTopNode, 0x600004, 0), "nodes \"REG_UPPER_MASK\", \"REG_LOWER_MASK\" under \"SUBSYSTEM3.DERIVEDNODE\"");
744 BOOST_CHECK_EQUAL(detail::getAddressDescription(*lTopNode, 0x600004, 1), "2 nodes under \"SUBSYSTEM3.DERIVEDNODE\" match");
745 BOOST_CHECK_EQUAL(detail::getAddressDescription(*lTopNode, 0x600004, 2), "nodes \"REG_UPPER_MASK\", \"REG_LOWER_MASK\" under \"SUBSYSTEM3.DERIVEDNODE\"");
746 BOOST_CHECK_EQUAL(detail::getAddressDescription(*lTopNode, 0x600004, 3), "nodes \"REG_UPPER_MASK\", \"REG_LOWER_MASK\" under \"SUBSYSTEM3.DERIVEDNODE\"");
747 BOOST_CHECK_EQUAL(detail::getAddressDescription(*lTopNode, 0x600005, 0), "no matching nodes");
748}
749
750
751BOOST_AUTO_TEST_SUITE( simple )
752
754{
755 std::shared_ptr<Node> lNode(NodeTreeBuilder::getInstance().build(addrTableDoc.child ( "node" ), boost::filesystem::path()));
756 checkNodeTree(*lNode, nodeProperties);
757}
758
760{
761 for (size_t i = 0; i < nodeProperties.size(); i++) {
762 BOOST_TEST_MESSAGE("Removing 'id' attribute from node " << i);
763
765 lDoc.load_string(addrTableStr.c_str());
766 getNthChild(lDoc.child("node"), i).remove_attribute("id");
767
768 BOOST_CHECK_THROW(NodeTreeBuilder::getInstance().build(lDoc.child ( "node" ), boost::filesystem::path()), exception::NoRulesPassed);
769 }
770}
771
773{
774 std::vector<std::string> lBadValues;
775 lBadValues.push_back("");
776 lBadValues.push_back(" ");
777 lBadValues.push_back(" ");
778 lBadValues.push_back(".");
779 lBadValues.push_back("bob.");
780 lBadValues.push_back(".bob");
781 lBadValues.push_back("some.value");
782
783 for (std::vector<std::string>::const_iterator lIt = lBadValues.begin(); lIt != lBadValues.end(); lIt++)
784 {
785 for (size_t i = 0; i < nodeProperties.size(); i++) {
786 BOOST_TEST_MESSAGE("Setting 'id' attribute of node " << i << " to '" << *lIt << "'");
787
789 lDoc.load_string(addrTableStr.c_str());
790 setAttribute(getNthChild(lDoc.child("node"), i), "id", *lIt);
791
792 BOOST_CHECK_THROW(NodeTreeBuilder::getInstance().build(lDoc.child ( "node" ), boost::filesystem::path()), exception::NodeAttributeIncorrectValue);
793 }
794 }
795}
796
798{
799 std::vector<std::string> lBadValues;
800 lBadValues.push_back("");
801 lBadValues.push_back(" ");
802 lBadValues.push_back(" ");
803 lBadValues.push_back("-1");
804 lBadValues.push_back("-0x11");
805 lBadValues.push_back("0x");
806 lBadValues.push_back("x");
807 lBadValues.push_back("3.14");
808 lBadValues.push_back("bob");
809 lBadValues.push_back("0x1234bob5678");
810
811 // lBadValues.push_back("0x100000000");
812 // lBadValues.push_back("0x1FFF1234abcd");
813
814 for (std::vector<std::string>::const_iterator lIt = lBadValues.begin(); lIt != lBadValues.end(); lIt++)
815 {
816 for (size_t i = 0; i < nodeProperties.size(); i++) {
817 BOOST_TEST_MESSAGE("Setting 'address' attribute of node " << i << " to '" << *lIt << "'");
818
820 lDoc.load_string(addrTableStr.c_str());
821 setAttribute(getNthChild(lDoc.child("node"), i), "address", *lIt);
822
823 BOOST_CHECK_THROW(NodeTreeBuilder::getInstance().build(lDoc.child ( "node" ), boost::filesystem::path()), exception::NodeAttributeIncorrectValue);
824 }
825 }
826}
827
829{
830 std::vector<std::string> lBadValues;
831 lBadValues.push_back("");
832 lBadValues.push_back(" ");
833 lBadValues.push_back(" ");
834 lBadValues.push_back("-1");
835 lBadValues.push_back("42a");
836 lBadValues.push_back("-0x11");
837 lBadValues.push_back("0x");
838 lBadValues.push_back("x");
839 lBadValues.push_back("3.14");
840 lBadValues.push_back("bob");
841 lBadValues.push_back("0x1234bob5678");
842
843 // lBadValues.push_back("0x100000000");
844 // lBadValues.push_back("0x1FFF1234abcd");
845
846 for (std::vector<std::string>::const_iterator lIt = lBadValues.begin(); lIt != lBadValues.end(); lIt++)
847 {
848 for (size_t i = 0; i < 2; i++) {
849 BOOST_TEST_MESSAGE("Setting 'mask' attribute of node " << i << " to '" << *lIt << "'");
850
852 lDoc.load_string(addrTableStr.c_str());
853 setAttribute(getNthChild(lDoc.child("node"), i), "mask", *lIt);
854
855 BOOST_CHECK_THROW(NodeTreeBuilder::getInstance().build(lDoc.child ( "node" ), boost::filesystem::path()), exception::NodeAttributeIncorrectValue);
856 }
857 }
858}
859
861{
862 std::vector<std::string> lBadValues;
863 lBadValues.push_back("");
864 lBadValues.push_back(" ");
865 lBadValues.push_back(" ");
866 lBadValues.push_back("-1");
867 lBadValues.push_back("42a");
868 lBadValues.push_back("-0x11");
869 lBadValues.push_back("0x");
870 lBadValues.push_back("x");
871 lBadValues.push_back("3.14");
872 lBadValues.push_back("bob");
873 lBadValues.push_back("0x1234bob5678");
874
875 // lBadValues.push_back("0x100000000");
876 // lBadValues.push_back("0x1FFF1234abcd");
877
878 for (std::vector<std::string>::const_iterator lIt = lBadValues.begin(); lIt != lBadValues.end(); lIt++)
879 {
880 for (size_t i = 2; i < nodeProperties.size(); i++) {
881 BOOST_TEST_MESSAGE("Setting 'size' attribute of node " << i << " to '" << *lIt << "'");
882
884 lDoc.load_string(addrTableStr.c_str());
885 setAttribute(getNthChild(lDoc.child("node"), i), "size", *lIt);
886
887 BOOST_CHECK_THROW(NodeTreeBuilder::getInstance().build(lDoc.child ( "node" ), boost::filesystem::path()), exception::NodeAttributeIncorrectValue);
888 }
889 }
890}
891
893{
894 std::vector<std::string> lBadValues;
895 lBadValues.push_back("bob");
896 lBadValues.push_back("some_invalid_string");
897 lBadValues.push_back("");
898 lBadValues.push_back("R");
899 lBadValues.push_back("W");
900 lBadValues.push_back("RW");
901 lBadValues.push_back("WR");
902 lBadValues.push_back("READ");
903 lBadValues.push_back("WRITE");
904 lBadValues.push_back("READWRITE");
905 lBadValues.push_back("WRITEREAD");
906
907 lBadValues.push_back("r ");
908
909 for (std::vector<std::string>::const_iterator lIt = lBadValues.begin(); lIt != lBadValues.end(); lIt++)
910 {
911 for (size_t i = 0; i < nodeProperties.size(); i++) {
912 BOOST_TEST_MESSAGE("Setting 'permission' attribute of node " << i << " to '" << *lIt << "'");
913
915 lDoc.load_string(addrTableStr.c_str());
916 setAttribute(getNthChild(lDoc.child("node"), i), "permission", *lIt);
917
918 BOOST_CHECK_THROW(NodeTreeBuilder::getInstance().build(lDoc.child ( "node" ), boost::filesystem::path()), exception::NodeAttributeIncorrectValue);
919 }
920 }
921}
922
924{
925 std::vector<std::string> lBadValues;
926 lBadValues.push_back("bob");
927 lBadValues.push_back("some_invalid_string");
928 lBadValues.push_back("");
929 lBadValues.push_back("SINGLE");
930 lBadValues.push_back("BLOCK");
931 lBadValues.push_back("INCREMENTAL");
932 lBadValues.push_back("INC");
933 lBadValues.push_back("PORT");
934 lBadValues.push_back("NON-INCREMENTAL");
935 lBadValues.push_back("NON-INC");
936
937 lBadValues.push_back("single ");
938
939 for (std::vector<std::string>::const_iterator lIt = lBadValues.begin(); lIt != lBadValues.end(); lIt++)
940 {
941 for (size_t i = 0; i < nodeProperties.size(); i++) {
942 BOOST_TEST_MESSAGE("Setting 'mode' attribute of node " << i << " to '" << *lIt << "'");
943
945 lDoc.load_string(addrTableStr.c_str());
946 setAttribute(getNthChild(lDoc.child("node"), i), "mode", *lIt);
947
948 BOOST_CHECK_THROW(NodeTreeBuilder::getInstance().build(lDoc.child ( "node" ), boost::filesystem::path()), exception::NodeAttributeIncorrectValue);
949 }
950 }
951}
952
954{
955 for (size_t i = 0; i < 2; i++) {
956 BOOST_TEST_MESSAGE("Adding 'size' attribute to node " << i << ", that doesn't have 'mode' attribute");
957
959 lDoc.load_string(addrTableStr.c_str());
960 setAttribute(getNthChild(lDoc.child("node"), i), "size", "42");
961
962 // This should change to 'BOOST_CHECK_THROW' in future release (after grace period discussed in issue #194 has ended)
963 BOOST_CHECK_NO_THROW(NodeTreeBuilder::getInstance().build(lDoc.child ( "node" ), boost::filesystem::path()));
964 }
965}
966
967
968BOOST_AUTO_TEST_SUITE_END()
969
970
971BOOST_AUTO_TEST_SUITE( overlapChecks )
972
973
975{
976 std::shared_ptr<Node> lNode(NodeTreeBuilder::getInstance().build(addrTableDoc.child ( "node" ), boost::filesystem::path()));
977
978 checkNodeTree(*lNode, nodeProperties);
979
981}
982
983
985{
986 // Move reg1 to same address as reg2 (0x1)
988 lDoc.load_string(addrTableStr.c_str());
989 setAttribute(getNthChild(lDoc.child("node"), 0), "address", "0x1");
990 std::shared_ptr<const Node> lNode(NodeTreeBuilder::getInstance().build(lDoc.child ( "node" ), boost::filesystem::path()));
991
992 // Expected overlaps
993 std::vector<std::pair<const Node*, const Node*> > lExpected;
994 lExpected.push_back( std::make_pair(&lNode->getNode("reg1"), &lNode->getNode("reg2")) );
995
996 // Compare expectations with result
997 std::vector<std::pair<const Node*, const Node*> > lResult = detail::getAddressOverlaps(*lNode);
998 BOOST_CHECK_EQUAL_COLLECTIONS(lResult.begin(), lResult.end(), lExpected.begin(), lExpected.end());
999}
1000
1001
1003{
1004 // Move reg4 to same address as reg3 (0x2)
1005 pugi::xml_document lDoc;
1006 lDoc.load_string(addrTableStr.c_str());
1007 setAttribute(getNthChild(lDoc.child("node"), 3), "address", "0x2");
1008 std::shared_ptr<const Node> lNode(NodeTreeBuilder::getInstance().build(lDoc.child ( "node" ), boost::filesystem::path()));
1009
1010 // Expected overlaps
1011 std::vector<std::pair<const Node*, const Node*> > lExpected;
1012 lExpected.push_back( std::make_pair(&lNode->getNode("reg3"), &lNode->getNode("reg4")) );
1013 lExpected.push_back( std::make_pair(&lNode->getNode("reg3"), &lNode->getNode("reg4.A")) );
1014 lExpected.push_back( std::make_pair(&lNode->getNode("reg3"), &lNode->getNode("reg4.B")) );
1015 lExpected.push_back( std::make_pair(&lNode->getNode("reg3"), &lNode->getNode("reg4.C")) );
1016 lExpected.push_back( std::make_pair(&lNode->getNode("reg3"), &lNode->getNode("reg4.D")) );
1017 lExpected.push_back( std::make_pair(&lNode->getNode("reg3.A"), &lNode->getNode("reg4")) );
1018 lExpected.push_back( std::make_pair(&lNode->getNode("reg3.A"), &lNode->getNode("reg4.A")) );
1019 lExpected.push_back( std::make_pair(&lNode->getNode("reg3.A"), &lNode->getNode("reg4.B")) );
1020 lExpected.push_back( std::make_pair(&lNode->getNode("reg3.B"), &lNode->getNode("reg4")) );
1021 lExpected.push_back( std::make_pair(&lNode->getNode("reg3.B"), &lNode->getNode("reg4.C")) );
1022 lExpected.push_back( std::make_pair(&lNode->getNode("reg3.B"), &lNode->getNode("reg4.D")) );
1023
1024 // Compare expectations with result
1025 std::vector<std::pair<const Node*, const Node*> > lResult = detail::getAddressOverlaps(*lNode);
1026 BOOST_CHECK_EQUAL_COLLECTIONS(lResult.begin(), lResult.end(), lExpected.begin(), lExpected.end());
1027}
1028
1029
1031{
1032 // Change mask of reg4.A to 0x10100ff to overlap with reg4.C and reg4.D
1033 pugi::xml_document lDoc;
1034 lDoc.load_string(addrTableStr.c_str());
1035 setAttribute(getNthChild(getNthChild(lDoc.child("node"), 3), 0), "mask", "0x10100ff");
1036 std::shared_ptr<const Node> lNode(NodeTreeBuilder::getInstance().build(lDoc.child ( "node" ), boost::filesystem::path()));
1037
1038 // Expected overlaps
1039 std::vector<std::pair<const Node*, const Node*> > lExpected;
1040 lExpected.push_back( std::make_pair(&lNode->getNode("reg4.A"), &lNode->getNode("reg4.C")) );
1041 lExpected.push_back( std::make_pair(&lNode->getNode("reg4.A"), &lNode->getNode("reg4.D")) );
1042
1043 // Compare expectations with result
1044 std::vector<std::pair<const Node*, const Node*> > lResult = detail::getAddressOverlaps(*lNode);
1045 BOOST_CHECK_EQUAL_COLLECTIONS(lResult.begin(), lResult.end(), lExpected.begin(), lExpected.end());
1046}
1047
1048
1050{
1051 // Move port1 to same address as port2 (0x5)
1052 pugi::xml_document lDoc;
1053 lDoc.load_string(addrTableStr.c_str());
1054 setAttribute(getNthChild(lDoc.child("node"), 4), "address", "0x5");
1055 std::shared_ptr<const Node> lNode(NodeTreeBuilder::getInstance().build(lDoc.child ( "node" ), boost::filesystem::path()));
1056
1057 // Expected overlaps
1058 std::vector<std::pair<const Node*, const Node*> > lExpected;
1059 lExpected.push_back( std::make_pair(&lNode->getNode("port1"), &lNode->getNode("port2")) );
1060
1061 // Compare expectations with result
1062 std::vector<std::pair<const Node*, const Node*> > lResult = detail::getAddressOverlaps(*lNode);
1063 BOOST_CHECK_EQUAL_COLLECTIONS(lResult.begin(), lResult.end(), lExpected.begin(), lExpected.end());
1064}
1065
1066
1067BOOST_FIXTURE_TEST_CASE (overlap_unmasked_reg_vs_masked_reg, AddressTableOverlapFixture)
1068{
1069 // Move reg1 to same address as reg3 (0x2)
1070 pugi::xml_document lDoc;
1071 lDoc.load_string(addrTableStr.c_str());
1072 setAttribute(getNthChild(lDoc.child("node"), 0), "address", "0x2");
1073 std::shared_ptr<const Node> lNode(NodeTreeBuilder::getInstance().build(lDoc.child ( "node" ), boost::filesystem::path()));
1074
1075 // Expected overlaps
1076 std::vector<std::pair<const Node*, const Node*> > lExpected;
1077 lExpected.push_back( std::make_pair(&lNode->getNode("reg1"), &lNode->getNode("reg3")) );
1078 lExpected.push_back( std::make_pair(&lNode->getNode("reg1"), &lNode->getNode("reg3.A")) );
1079 lExpected.push_back( std::make_pair(&lNode->getNode("reg1"), &lNode->getNode("reg3.B")) );
1080
1081 // Compare expectations with result
1082 std::vector<std::pair<const Node*, const Node*> > lResult = detail::getAddressOverlaps(*lNode);
1083 BOOST_CHECK_EQUAL_COLLECTIONS(lResult.begin(), lResult.end(), lExpected.begin(), lExpected.end());
1084}
1085
1086
1088{
1089 // Move reg1 to same address as port1 (0x4)
1090 pugi::xml_document lDoc;
1091 lDoc.load_string(addrTableStr.c_str());
1092 setAttribute(getNthChild(lDoc.child("node"), 0), "address", "0x4");
1093 std::shared_ptr<const Node> lNode(NodeTreeBuilder::getInstance().build(lDoc.child ( "node" ), boost::filesystem::path()));
1094
1095 // Expected overlaps
1096 std::vector<std::pair<const Node*, const Node*> > lExpected;
1097 lExpected.push_back( std::make_pair(&lNode->getNode("reg1"), &lNode->getNode("port1")) );
1098
1099 // Compare expectations with result
1100 std::vector<std::pair<const Node*, const Node*> > lResult = detail::getAddressOverlaps(*lNode);
1101 BOOST_CHECK_EQUAL_COLLECTIONS(lResult.begin(), lResult.end(), lExpected.begin(), lExpected.end());
1102}
1103
1104
1106{
1107 // Move reg3 to same address as port1 (0x4)
1108 pugi::xml_document lDoc;
1109 lDoc.load_string(addrTableStr.c_str());
1110 setAttribute(getNthChild(lDoc.child("node"), 2), "address", "0x4");
1111 std::shared_ptr<const Node> lNode(NodeTreeBuilder::getInstance().build(lDoc.child ( "node" ), boost::filesystem::path()));
1112
1113 // Expected overlaps
1114 std::vector<std::pair<const Node*, const Node*> > lExpected;
1115 lExpected.push_back( std::make_pair(&lNode->getNode("reg3"), &lNode->getNode("port1")) );
1116 lExpected.push_back( std::make_pair(&lNode->getNode("reg3.A"), &lNode->getNode("port1")) );
1117 lExpected.push_back( std::make_pair(&lNode->getNode("reg3.B"), &lNode->getNode("port1")) );
1118
1119 // Compare expectations with result
1120 std::vector<std::pair<const Node*, const Node*> > lResult = detail::getAddressOverlaps(*lNode);
1121 BOOST_CHECK_EQUAL_COLLECTIONS(lResult.begin(), lResult.end(), lExpected.begin(), lExpected.end());
1122}
1123
1124
1126{
1127 // Create list of nodes that will be moved
1128 // pair.first = index of XML nodes
1129 // pair.second = node paths that will be flagged by overlap check
1130 std::vector<std::pair<size_t, std::vector<std::string> > > lModifiedNodes(4);
1131
1132 lModifiedNodes.at(0).first = 0;
1133 lModifiedNodes.at(0).second.push_back("reg1");
1134
1135 lModifiedNodes.at(1).first = 2;
1136 lModifiedNodes.at(1).second.push_back("reg3");
1137 lModifiedNodes.at(1).second.push_back("reg3.A");
1138 lModifiedNodes.at(1).second.push_back("reg3.B");
1139
1140 lModifiedNodes.at(2).first = 4;
1141 lModifiedNodes.at(2).second.push_back("port1");
1142
1143 lModifiedNodes.at(3).first = 6;
1144 lModifiedNodes.at(3).second.push_back("ram1");
1145
1146 // Target addresses that above nodes will be moved to. First, middle and last address of 'ram2'
1147 std::vector<std::string> lAddresses;
1148 lAddresses.push_back("0x10");
1149 lAddresses.push_back("0x1a");
1150 lAddresses.push_back("0x1f");
1151
1152 for (std::vector<std::pair<size_t, std::vector<std::string> > >::const_iterator lNodeIt = lModifiedNodes.begin(); lNodeIt != lModifiedNodes.end(); lNodeIt++)
1153 {
1154 for (std::vector<std::string>::const_iterator lAddrIt = lAddresses.begin(); lAddrIt != lAddresses.end(); lAddrIt++)
1155 {
1156 BOOST_TEST_MESSAGE("Moving '" << lNodeIt->second.front() << "' to address " << *lAddrIt);
1157
1158 // Move node to get an overlap
1159 pugi::xml_document lDoc;
1160 lDoc.load_string(addrTableStr.c_str());
1161 setAttribute(getNthChild(lDoc.child("node"), lNodeIt->first), "address", lAddrIt->c_str());
1162 std::shared_ptr<const Node> lNode(NodeTreeBuilder::getInstance().build(lDoc.child ( "node" ), boost::filesystem::path()));
1163
1164 // Expected overlaps
1165 std::vector<std::pair<const Node*, const Node*> > lExpected;
1166 for (size_t i = 0; i < lNodeIt->second.size(); i++)
1167 {
1168 if (lAddrIt == lAddresses.begin())
1169 lExpected.push_back( std::make_pair(&lNode->getNode(lNodeIt->second.at(i)), &lNode->getNode("ram2")) );
1170 else
1171 lExpected.push_back( std::make_pair(&lNode->getNode("ram2"), &lNode->getNode(lNodeIt->second.at(i))) );
1172 }
1173
1174 // Compare expectations with result
1175 std::vector<std::pair<const Node*, const Node*> > lResult = detail::getAddressOverlaps(*lNode);
1176 BOOST_CHECK_EQUAL_COLLECTIONS(lResult.begin(), lResult.end(), lExpected.begin(), lExpected.end());
1177 }
1178 }
1179}
1180
1181
1183{
1184 // Move module 1 to address 0x0
1185 pugi::xml_document lDoc;
1186 lDoc.load_string(addrTableStr.c_str());
1187 setAttribute(getNthChild(lDoc.child("node"), 8), "address", "0x0");
1188 std::shared_ptr<const Node> lNode(NodeTreeBuilder::getInstance().build(lDoc.child ( "node" ), boost::filesystem::path()));
1189
1190 // Expected overlaps
1191 std::vector<std::pair<const Node*, const Node*> > lExpected;
1192 lExpected.push_back( std::make_pair(&lNode->getNode("reg1"), &lNode->getNode("module1.reg1")) );
1193 lExpected.push_back( std::make_pair(&lNode->getNode("module1.reg2"), &lNode->getNode("reg2")) );
1194 lExpected.push_back( std::make_pair(&lNode->getNode("module1.reg2.mask1"), &lNode->getNode("reg2")) );
1195 lExpected.push_back( std::make_pair(&lNode->getNode("module1.reg2.mask2"), &lNode->getNode("reg2")) );
1196 lExpected.push_back( std::make_pair(&lNode->getNode("module1.reg2.mask3"), &lNode->getNode("reg2")) );
1197 lExpected.push_back( std::make_pair(&lNode->getNode("module1.port"), &lNode->getNode("reg3")) );
1198 lExpected.push_back( std::make_pair(&lNode->getNode("module1.port"), &lNode->getNode("reg3.A")) );
1199 lExpected.push_back( std::make_pair(&lNode->getNode("module1.port"), &lNode->getNode("reg3.B")) );
1200 lExpected.push_back( std::make_pair(&lNode->getNode("module1.ram"), &lNode->getNode("ram2")) );
1201
1202 // Compare expectations with result
1203 std::vector<std::pair<const Node*, const Node*> > lResult = detail::getAddressOverlaps(*lNode);
1204 BOOST_CHECK_EQUAL_COLLECTIONS(lResult.begin(), lResult.end(), lExpected.begin(), lExpected.end());
1205}
1206
1207
1209{
1210 // Move module 2 to same address as module 1 (0x40)
1211 pugi::xml_document lDoc;
1212 lDoc.load_string(addrTableStr.c_str());
1213 setAttribute(getNthChild(lDoc.child("node"), 9), "address", "0x40");
1214 std::shared_ptr<const Node> lNode(NodeTreeBuilder::getInstance().build(lDoc.child ( "node" ), boost::filesystem::path()));
1215
1216 // Expected overlaps
1217 std::vector<std::pair<const Node*, const Node*> > lExpected;
1218 lExpected.push_back( std::make_pair(&lNode->getNode("module1.reg1"), &lNode->getNode("module2.regA")) );
1219 lExpected.push_back( std::make_pair(&lNode->getNode("module1.reg2"), &lNode->getNode("module2.regB")) );
1220 lExpected.push_back( std::make_pair(&lNode->getNode("module1.reg2"), &lNode->getNode("module2.regB.A")) );
1221 lExpected.push_back( std::make_pair(&lNode->getNode("module1.reg2"), &lNode->getNode("module2.regB.B")) );
1222 lExpected.push_back( std::make_pair(&lNode->getNode("module1.reg2"), &lNode->getNode("module2.regB.C")) );
1223 lExpected.push_back( std::make_pair(&lNode->getNode("module1.reg2.mask1"), &lNode->getNode("module2.regB")) );
1224 lExpected.push_back( std::make_pair(&lNode->getNode("module1.reg2.mask1"), &lNode->getNode("module2.regB.A")) );
1225 lExpected.push_back( std::make_pair(&lNode->getNode("module1.reg2.mask2"), &lNode->getNode("module2.regB")) );
1226 lExpected.push_back( std::make_pair(&lNode->getNode("module1.reg2.mask2"), &lNode->getNode("module2.regB.B")) );
1227 lExpected.push_back( std::make_pair(&lNode->getNode("module1.reg2.mask3"), &lNode->getNode("module2.regB")) );
1228 lExpected.push_back( std::make_pair(&lNode->getNode("module1.reg2.mask3"), &lNode->getNode("module2.regB.C")) );
1229 lExpected.push_back( std::make_pair(&lNode->getNode("module1.port"), &lNode->getNode("module2.fifo")) );
1230 lExpected.push_back( std::make_pair(&lNode->getNode("module1.ram"), &lNode->getNode("module2.block")) );
1231
1232 // Compare expectations with result
1233 std::vector<std::pair<const Node*, const Node*> > lResult = detail::getAddressOverlaps(*lNode);
1234 BOOST_CHECK_EQUAL_COLLECTIONS(lResult.begin(), lResult.end(), lExpected.begin(), lExpected.end());
1235}
1236
1237
1238BOOST_AUTO_TEST_SUITE_END()
1239
1240
1241BOOST_AUTO_TEST_SUITE_END()
1242
1243}
1244}
Wrapper for Python extension modules.
Definition: pybind11.h:1145
bool set_value(const char_t *rhs)
Definition: pugixml.cpp:5306
xml_parse_result load_string(const char_t *contents, unsigned int options=parse_default)
Definition: pugixml.cpp:7098
xml_node child(const char_t *name) const
Definition: pugixml.cpp:5497
xml_node first_child() const
Definition: pugixml.cpp:5629
xml_attribute append_attribute(const char_t *name)
Definition: pugixml.cpp:5659
xml_node next_sibling() const
Definition: pugixml.cpp:5528
bool remove_attribute(const xml_attribute &a)
Definition: pugixml.cpp:6048
Definition: pytypes.h:1167
A heirarchical node for navigating heirarchical firmwares.
Definition: Node.hpp:85
const defs::NodePermission & getPermission() const
Return the read/write access permissions of this node.
Definition: Node.cpp:280
const std::unordered_map< std::string, std::string > & getFirmwareInfo() const
Return parameters for inferring the VHDL address decoding.
Definition: Node.cpp:310
ValWord< uint32_t > read() const
Read a single, unmasked, unsigned word.
Definition: Node.cpp:611
const uint32_t & getMask() const
Return the mask to be applied if this node is a sub-field, rather than an entire register.
Definition: Node.cpp:262
const std::string & getId() const
Return the unique ID of the current node.
Definition: Node.cpp:191
ValHeader writeBlockOffset(const std::vector< uint32_t > &aValues, const uint32_t &aOffset) const
Write a block of data to a block of registers or a block-write port.
Definition: Node.cpp:573
std::vector< const Node * > getLineage(const Node &aAncestor) const
Returns ancestry path of nodes from (but not including) aAncestor to this node.
Definition: Node.cpp:707
const std::unordered_map< std::string, std::string > & getParameters() const
Return parameters of the current node.
Definition: Node.cpp:304
const Node & getNode(const std::string &aId) const
Retrieve the Node given by a full-stop delimeted name path relative, to the current node.
Definition: Node.cpp:441
const defs::BlockReadWriteMode & getMode() const
Return whether the node represents a single register, a block of registers or a block-read/write port...
Definition: Node.cpp:268
std::string getPath() const
Return the full path to the current node.
Definition: Node.cpp:197
ValHeader writeBlock(const std::vector< uint32_t > &aValues) const
Write a block of data to a block of registers or a block-write port.
Definition: Node.cpp:542
ValVector< uint32_t > readBlockOffset(const uint32_t &aSize, const uint32_t &aOffset) const
Read a block of unsigned data from a block of registers or a block-read port.
Definition: Node.cpp:663
ValHeader write(const uint32_t &aValue) const
Write a single, unmasked word to a register.
Definition: Node.cpp:516
const uint32_t & getAddress() const
Return the register address with which this node is associated.
Definition: Node.cpp:256
const std::string & getDescription() const
Return the optional description string which the user can specify for the current node.
Definition: Node.cpp:292
const_iterator end() const
Definition: Node.cpp:176
const uint32_t & getSize() const
Return the maximum size available to a block read/write.
Definition: Node.cpp:274
std::vector< std::string > getNodes() const
Return all node IDs known to this HwInterface.
Definition: Node.cpp:478
const std::string & getTags() const
Return the optional tags string which the user can specify for the current node.
Definition: Node.cpp:286
const_iterator begin() const
Definition: Node.cpp:170
const std::string & getModule() const
Return the name of the module in which the current node resides.
Definition: Node.cpp:298
ValVector< uint32_t > readBlock(const uint32_t &aSize) const
Read a block of unsigned data from a block of registers or a block-read port.
Definition: Node.cpp:632
static NodeTreeBuilder & getInstance()
Static method to retrieve the single instance of the class.
Class further derived from Level1.
BlockReadWriteMode
define whether transactions target a single register, a block of registers, a block-read/write port o...
Definition: definitions.hpp:53
NodePermission
define Read and Write permissions of a uhal Node
Definition: definitions.hpp:50
std::string getAddressDescription(const ClientInterface &, const uint32_t, const size_t &)
Generates a short string summarising which nodes match the specified address.
Definition: utilities.cpp:105
std::vector< std::pair< const Node *, const Node * > > getAddressOverlaps(const Node &aNode)
Definition: utilities.cpp:120
BOOST_FIXTURE_TEST_CASE(dummy_address_files, DummyAddressFileFixture)
Definition: test_nodes.cpp:689
BOOST_CHECK_THROW(hw.getNode("REG").writeBlockOffset(xx, 0), uhal::exception::BulkTransferOffsetRequestedForSingleRegister)
BOOST_CHECK_EQUAL(mem.size(), N)
void setAttribute(pugi::xml_node aNode, const std::string &aName, const std::string &aValue)
Definition: test_nodes.cpp:679
void checkProperties(const uhal::Node &aNode, const NodeProperties &aExpected)
Definition: test_nodes.cpp:424
std::vector< uint32_t >::const_iterator j
void checkLineage(const uhal::Node &aTopNode, const uhal::Node &aNode)
Definition: test_nodes.cpp:627
void checkExceptionsThrownByReadWrite(const uhal::Node &aNode, const NodeProperties &aProperties)
Definition: test_nodes.cpp:464
void checkNodeTree(const uhal::Node &aNode, const std::vector< NodeProperties > &aExpectedProperties)
Definition: test_nodes.cpp:652
BOOST_CHECK_NO_THROW(hw.getNode("REG").writeBlock(xx))
BOOST_CHECK(!mem.valid())
void checkIteration(const uhal::Node &aNode, const NodeProperties &aProperties)
Definition: test_nodes.cpp:607
pugi::xml_node getNthChild(const pugi::xml_node &aNode, const size_t aIndex)
Definition: test_nodes.cpp:671
void checkDescendants(const uhal::Node &aNode, const NodeProperties &aProperties)
Definition: test_nodes.cpp:538
bool nodeAddrCompare(const Node *aNodeL, const Node *aNodeR)
Definition: test_nodes.cpp:601
std::ostream & operator<<(std::ostream &aStr, const uhal::HttpResponseType &aHttpResponse)
std::vector< NodeProperties > nodeProperties
Definition: test_nodes.cpp:111
Fixture for tests based on 'dummy' address files.
Definition: test_nodes.cpp:116
std::vector< NodeProperties > nodeProperties
Definition: test_nodes.cpp:132
std::string getAddrFileAbsPath(const std::string &aSuffix)
Definition: test_nodes.cpp:121
std::vector< std::string > descendantIds
Definition: test_nodes.cpp:82
std::unordered_map< std::string, std::string > fwInfo
Definition: test_nodes.cpp:86
NodeProperties(const std::string &aIdPath, const uint32_t aAddress, const defs::BlockReadWriteMode aMode, const defs::NodePermission aPermission, const size_t aSize, const std::string &aModule, const size_t aNrDescendants)
Definition: test_nodes.cpp:137
const std::type_info * type
Definition: test_nodes.cpp:87
defs::NodePermission permission
Definition: test_nodes.cpp:77
std::map< std::string, const std::type_info * > descendantTypes
Definition: test_nodes.cpp:83
std::unordered_map< std::string, std::string > parameters
Definition: test_nodes.cpp:85
defs::BlockReadWriteMode mode
Definition: test_nodes.cpp:76
std::vector< NodeProperties > nodeProperties
Definition: test_nodes.cpp:99