μHAL (v2.6.5)
Part of the IPbus software repository
test_block.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  Marc Magrans de Abril, CERN
24  email: marc.magrans.de.abril <AT> cern.ch
25 
26  Andrew Rose, Imperial College, London
27  email: awr01 <AT> imperial.ac.uk
28 
29  Tom Williams, Rutherford Appleton Laboratory, Oxfordshire
30  email: tom.williams <AT> cern.ch
31 
32 ---------------------------------------------------------------------------
33 */
34 
35 #include "uhal/uhal.hpp"
36 
38 #include "uhal/tests/fixtures.hpp"
39 #include "uhal/tests/tools.hpp"
40 
41 #include <boost/test/unit_test.hpp>
42 
43 #include <vector>
44 #include <iostream>
45 #include <cstdlib>
46 #include <typeinfo>
47 
48 
49 using namespace uhal;
50 
51 #define N_4B 1
52 #define N_1kB 1024/4
53 #define N_1MB 1024*1024/4
54 #define N_10MB 10*1024*1024/4
55 #define N_200MB 100*1024*1024/4
56 
57 
58 namespace uhal {
59 namespace tests {
60 
61 std::vector<size_t> getBlockUnitTestDepths()
62 {
63  std::vector<size_t> lDepths;
64  lDepths.push_back(0);
65  lDepths.push_back(N_4B);
66  lDepths.push_back(N_1kB);
67  lDepths.push_back(N_1MB);
68  lDepths.push_back(N_10MB);
69  return lDepths;
70 }
71 
72 
73 UHAL_TESTS_DEFINE_CLIENT_TEST_CASES(BlockReadWriteTestSuite, block_write_read, DummyHardwareFixture,
74 {
75  std::vector<size_t> lDepths = getBlockUnitTestDepths();
76 
77  for(size_t i=0; i<lDepths.size(); i++) {
78  const size_t N = lDepths.at(i);
79  BOOST_TEST_MESSAGE(" N = " << N);
80 
81  HwInterface hw = getHwInterface();
82 
83  std::vector<uint32_t> xx;
84  xx.reserve ( N );
85  for ( size_t i=0; i!= N; ++i )
86  {
87  xx.push_back ( static_cast<uint32_t> ( rand() ) );
88  }
89 
90  hw.getNode ( "LARGE_MEM" ).writeBlock ( xx );
91  ValVector< uint32_t > mem = hw.getNode ( "LARGE_MEM" ).readBlock ( N );
92  BOOST_CHECK ( !mem.valid() );
93  BOOST_CHECK_EQUAL ( mem.size(), N );
94  if ( N > 0 )
95  {
96  BOOST_CHECK_THROW ( mem.at ( 0 ), uhal::exception::NonValidatedMemory );
97  }
98  BOOST_CHECK_THROW ( mem.value(), uhal::exception::NonValidatedMemory );
100  BOOST_CHECK ( mem.valid() );
101  BOOST_CHECK_EQUAL ( mem.size(), N );
102 
103  //This check will fail when DummyHardware::ADDRESS_MASK < N
104  if ( N < N_10MB )
105  {
106  bool correct_block_write_read = true;
107  std::vector< uint32_t >::const_iterator j=xx.begin();
108 
109  for ( ValVector< uint32_t >::const_iterator i ( mem.begin() ); i!=mem.end(); ++i , ++j )
110  {
111  correct_block_write_read = correct_block_write_read && ( *i == *j );
112  }
113 
114  BOOST_CHECK ( correct_block_write_read );
115  }
116  }
117 }
118 )
119 
120 
122 {
123  std::vector<size_t> lDepths = getBlockUnitTestDepths();
124  lDepths.push_back(N_200MB);
125 
126  for(size_t i=0; i<lDepths.size(); i++) {
127  const size_t N = lDepths.at(i);
128  BOOST_TEST_MESSAGE(" N = " << N);
129 
130  HwInterface hw = getHwInterface();
131  // Scope the large source vector so that the memory is freed up after the call to write. The data is safe, since it is copied into the send buffers.
132  std::vector<uint32_t> xx;
133  xx.reserve ( N );
134 
135  for ( size_t i=0; i!= N; ++i )
136  {
137  xx.push_back ( static_cast<uint32_t> ( rand() ) );
138  }
139 
140  hw.getNode ( "FIFO" ).writeBlock ( xx );
141  ValVector< uint32_t > mem = hw.getNode ( "FIFO" ).readBlock ( N );
142  BOOST_CHECK ( !mem.valid() );
143  BOOST_CHECK_EQUAL ( mem.size(), N );
144  if ( N > 0 )
145  {
146  BOOST_CHECK_THROW ( mem.at ( 0 ),uhal::exception::NonValidatedMemory );
147  }
148  BOOST_CHECK_THROW ( mem.value(), uhal::exception::NonValidatedMemory );
150  BOOST_CHECK ( mem.valid() );
151  BOOST_CHECK_EQUAL ( mem.size(), N );
152  //The FIFO implementation on the dummy HW is a single memory location so there is not much to check
153  }
154 }
155 )
156 
157 
158 UHAL_TESTS_DEFINE_CLIENT_TEST_CASES(BlockReadWriteTestSuite, block_offset_write_read, DummyHardwareFixture,
159 {
160  std::vector<size_t> lDepths = getBlockUnitTestDepths();
161 
162  for(size_t i=0; i<lDepths.size(); i++) {
163  const size_t N = lDepths.at(i);
164  BOOST_TEST_MESSAGE(" N = " << N);
165 
166  HwInterface hw = getHwInterface();
167 
168  std::vector<uint32_t> xx;
169  xx.reserve ( N );
170  std::vector<uint32_t> yy;
171  yy.reserve ( N );
172  for ( size_t i=0; i!= N; ++i )
173  {
174  xx.push_back ( static_cast<uint32_t> ( rand() ) );
175  yy.push_back ( static_cast<uint32_t> ( rand() ) );
176  }
177 
178  hw.getNode ( "LARGE_MEM" ).writeBlockOffset ( xx , 0 );
179  ValVector< uint32_t > mem = hw.getNode ( "LARGE_MEM" ).readBlockOffset ( N , 0 );
180 
181  BOOST_CHECK ( !mem.valid() );
182  BOOST_CHECK_EQUAL ( mem.size(), N );
183 
184  if ( N > 0 )
185  {
186  BOOST_CHECK_THROW ( mem.at ( 0 ),uhal::exception::NonValidatedMemory );
187  }
188  BOOST_CHECK_THROW ( mem.value(), uhal::exception::NonValidatedMemory );
189 
190 
191  hw.getNode ( "LARGE_MEM" ).writeBlockOffset ( yy , N );
192  ValVector< uint32_t > mem2 = hw.getNode ( "LARGE_MEM" ).readBlockOffset ( N , N );
193 
194  BOOST_CHECK ( !mem2.valid() );
195  BOOST_CHECK_EQUAL ( mem2.size(), N );
196 
197  if ( N > 0 )
198  {
199  BOOST_CHECK_THROW ( mem2.at ( 0 ),uhal::exception::NonValidatedMemory );
200  }
201  BOOST_CHECK_THROW ( mem2.value(), uhal::exception::NonValidatedMemory );
202 
204 
205  BOOST_CHECK ( mem.valid() );
206  BOOST_CHECK_EQUAL ( mem.size(), N );
207 
208  BOOST_CHECK ( mem2.valid() );
209  BOOST_CHECK_EQUAL ( mem2.size(), N );
210 
211 
212  //This check will fail when DummyHardware::ADDRESS_MASK < N
213  if ( N < N_10MB )
214  {
215  bool correct_block_write_read = true;
216  std::vector< uint32_t >::const_iterator j=xx.begin();
217 
218  for ( ValVector< uint32_t >::const_iterator i ( mem.begin() ); i!=mem.end(); ++i , ++j )
219  {
220  correct_block_write_read = correct_block_write_read && ( *i == *j );
221  }
222 
223  j=yy.begin();
224 
225  for ( ValVector< uint32_t >::const_iterator i ( mem2.begin() ); i!=mem2.end(); ++i , ++j )
226  {
227  correct_block_write_read = correct_block_write_read && ( *i == *j );
228  }
229 
230  BOOST_CHECK ( correct_block_write_read );
231  }
232  }
233 }
234 )
235 
236 
238 {
239  HwInterface hw = getHwInterface();
240  std::vector<uint32_t> xx;
241 
242  //We allow the user to call a bulk access of size=1 to a single register
243  xx.resize ( N_4B );
244  BOOST_CHECK_NO_THROW ( hw.getNode ( "REG" ).writeBlock ( xx ) );
246 
247  //These should all throw
248  BOOST_CHECK_THROW ( hw.getNode ( "REG" ).writeBlockOffset ( xx , 0 ) , uhal::exception::BulkTransferOffsetRequestedForSingleRegister );
249  BOOST_CHECK_THROW ( ValVector< uint32_t > mem = hw.getNode ( "REG" ).readBlockOffset ( N_1kB , 0 ) , uhal::exception::BulkTransferOffsetRequestedForSingleRegister );
250 
251  xx.resize ( N_1kB );
252  BOOST_CHECK_THROW ( hw.getNode ( "REG" ).writeBlock ( xx ) , uhal::exception::BulkTransferOnSingleRegister );
253  BOOST_CHECK_THROW ( ValVector< uint32_t > mem = hw.getNode ( "REG" ).readBlock( N_1kB ) , uhal::exception::BulkTransferOnSingleRegister );
254 
255  BOOST_CHECK_THROW ( hw.getNode ( "FIFO" ).writeBlockOffset ( xx , 1 ) , uhal::exception::BulkTransferOffsetRequestedForFifo );
256  BOOST_CHECK_THROW ( ValVector< uint32_t > mem = hw.getNode ( "FIFO" ).readBlockOffset ( N_1kB , 1 ) , uhal::exception::BulkTransferOffsetRequestedForFifo );
257 
258 }
259 )
260 
261 
262 UHAL_TESTS_DEFINE_CLIENT_TEST_CASES(BlockReadWriteTestSuite, block_bigger_than_size_attribute, MinimalFixture,
263 {
264  HwInterface hw = getHwInterface();
265  std::vector<uint32_t> xx;
266  xx.resize ( N_1MB );
267  BOOST_CHECK_THROW ( hw.getNode ( "SMALL_MEM" ).writeBlock ( xx ) , uhal::exception::BulkTransferRequestedTooLarge );
268  BOOST_CHECK_THROW ( ValVector< uint32_t > mem = hw.getNode ( "SMALL_MEM" ).readBlock ( N_1MB ) , uhal::exception::BulkTransferRequestedTooLarge );
269 }
270 )
271 
272 
274 {
275  HwInterface hw = getHwInterface();
276  std::vector<uint32_t> xx;
277  // Size OK but offset too large
278  xx.resize ( N_4B );
279  BOOST_CHECK_THROW ( hw.getNode ( "SMALL_MEM" ).writeBlockOffset ( xx , 256 ) , uhal::exception::BulkTransferRequestedTooLarge );
280  BOOST_CHECK_THROW ( ValVector< uint32_t > mem = hw.getNode ( "SMALL_MEM" ).readBlockOffset ( N_4B , 256 ) , uhal::exception::BulkTransferRequestedTooLarge );
281  // Size OK, offset OK, combination too large
282  xx.resize ( N_1kB );
283  BOOST_CHECK_THROW ( hw.getNode ( "SMALL_MEM" ).writeBlockOffset ( xx , 1 ) , uhal::exception::BulkTransferRequestedTooLarge );
284  BOOST_CHECK_THROW ( ValVector< uint32_t > mem = hw.getNode ( "SMALL_MEM" ).readBlockOffset ( N_1kB , 1 ) , uhal::exception::BulkTransferRequestedTooLarge );
285 }
286 )
287 
288 
289 } // end ns tests
290 } // end ns uhal
291 
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:551
#define N_200MB
Definition: test_block.cpp:55
bool correct_block_write_read
A class which bundles a node tree and an IPbus client interface together providing everything you nee...
Definition: HwInterface.hpp:59
std::vector< uint32_t >::const_iterator j
UHAL_TESTS_DEFINE_CLIENT_TEST_CASES(BlockReadWriteTestSuite, block_write_read, DummyHardwareFixture, { std::vector< size_t > lDepths=getBlockUnitTestDepths();for(size_t i=0;i< lDepths.size();i++) { const size_t N=lDepths.at(i);BOOST_TEST_MESSAGE(" N = "<< N);HwInterface hw=getHwInterface();std::vector< uint32_t > xx;xx.reserve(N);for(size_t i=0;i!=N;++i) { xx.push_back(static_cast< uint32_t >(rand()));} hw.getNode("LARGE_MEM").writeBlock(xx);ValVector< uint32_t > mem=hw.getNode("LARGE_MEM").readBlock(N);BOOST_CHECK(!mem.valid());BOOST_CHECK_EQUAL(mem.size(), N);if(N > 0) { BOOST_CHECK_THROW(mem.at(0), uhal::exception::NonValidatedMemory);} BOOST_CHECK_THROW(mem.value(), uhal::exception::NonValidatedMemory);BOOST_CHECK_NO_THROW(hw.dispatch());BOOST_CHECK(mem.valid());BOOST_CHECK_EQUAL(mem.size(), N);if(N< N_10MB) { bool correct_block_write_read=true;std::vector< uint32_t >::const_iterator j=xx.begin();for(ValVector< uint32_t >::const_iterator i(mem.begin());i!=mem.end();++i,++j) { correct_block_write_read=correct_block_write_read &&(*i== *j);} BOOST_CHECK(correct_block_write_read);} } }) UHAL_TESTS_DEFINE_CLIENT_TEST_CASES(BlockReadWriteTestSuite
#define N_1MB
Definition: test_block.cpp:53
#define N_4B
Definition: test_block.cpp:51
void dispatch()
Make the IPbus client issue a dispatch.
#define N_10MB
Definition: test_block.cpp:54
BOOST_CHECK(!mem.valid())
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:641
BOOST_CHECK_THROW(hw.getNode("REG").writeBlockOffset(xx, 0), uhal::exception::BulkTransferOffsetRequestedForSingleRegister)
std::vector< size_t > getBlockUnitTestDepths()
Definition: test_block.cpp:61
#define N_1kB
Definition: test_block.cpp:52
const_iterator end() const
If the memory has previously been marked as valid, return a const iterator to the end (one past last ...
Definition: ValMem.cpp:389
bool valid()
Return whether the Validated memory is marked as valid.
Definition: ValMem.cpp:290
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:610
HwInterface hw
block_access_type_violations
Definition: test_block.cpp:237
BOOST_CHECK_EQUAL(hw.getNode("SUBSYSTEM1.SUBMODULE.REG").getAddress(), hw.getNode("SUBSYSTEM1").getNode("SUBMODULE").getNode("REG").getAddress())
BOOST_CHECK_NO_THROW(hw.getNode("REG").writeBlock(xx))
const_iterator begin() const
If the memory has previously been marked as valid, return a const iterator to the beginning of the un...
Definition: ValMem.cpp:374
std::vector< uint32_t > xx
Definition: test_block.cpp:238
std::size_t size() const
Return the size of the underlying memory.
Definition: ValMem.cpp:349
ValVector< uint32_t > mem
std::vector< T > value() const
Return the value of the validated memory with check on validity.
Definition: ValMem.cpp:435
block_offset_bigger_than_size_attribute
Definition: test_block.cpp:273
const T & at(std::size_t aIndex) const
If the memory has previously been marked as valid, give random access into memory.
Definition: ValMem.cpp:334
const Node & getNode() const
Ping the target for this client.
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:520