μHAL (v2.6.5)
Part of the IPbus software repository
PerfTester_static.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 
36 
37 // C++ headers
38 #include <iostream>
39 #include <iomanip>
40 #include <sstream>
41 #include <cstdlib>
42 #include <unistd.h>
43 
44 // Boost headers
45 #include <boost/program_options.hpp>
46 #include <boost/bind.hpp>
47 #include <boost/foreach.hpp>
48 #include <boost/mem_fn.hpp>
49 
50 // uHAL headers
51 #include "uhal/ClientFactory.hpp"
52 #include "uhal/tests/tools.hpp"
53 
54 // Namespace resolution
55 using namespace std;
56 
57 
58 
59 
60 uint32_t uhal::tests::PerfTester::getRandomBlockSize ( const uint32_t maxSize )
61 {
62  // Generate uniformly-distributed random float in range: 0 <= x < 1
63  const double uniformRandom = static_cast<double> ( rand() ) / RAND_MAX; //TODO -- replace with boost::random random-double-generating function
64  // Transform to 1/x distributed random float in range: 0.5 <= x < maxSize+1
65  const double inverseRandom = 0.5 * pow ( static_cast<double> ( ( maxSize+1 ) / 0.5 ) , uniformRandom );
66  uint32_t retVal = static_cast<uint32_t>( floor(inverseRandom) );
67 
68  if ( retVal > maxSize )
69  {
70  log ( Warning(), "Random block size (", Integer(retVal), ") is larger than maxSize (" , Integer(retVal) , ") ...\n",
71  " * uniformRandom=", uniformRandom, "\n",
72  " * inverseRandom=", inverseRandom, "\n",
73  "Correcting block size as temporary fix." );
74  retVal = maxSize;
75  }
76 
77  // Floor the float to get integer with desired distribution
78  return retVal;
79 }
80 
81 
83 {
84  U32Vec buffer;
85  buffer.reserve ( size );
86 
87  // Never said anything about it being a flat random distribution... ;-)
88  for ( unsigned i = 0 ; i < size ; ++i )
89  {
90  buffer.push_back ( rand() + rand() );
91  }
92 
93  return buffer;
94 }
95 
96 
97 // Validation test -- single-register write/read-back
98 bool uhal::tests::PerfTester::validation_test_single_write_read ( ClientInterface& c, const uint32_t addr, const bool perTransactionDispatch, const bool aVerbose )
99 {
100  std::ostringstream oss_details;
101  oss_details << "Single-register write-read @ 0x" << std::hex << addr << ( perTransactionDispatch ? " (multiple dispatches)" : " (single dispatch)" );
102 
103  if ( aVerbose )
104  {
105  cout << oss_details.str() << endl;
106  }
107 
108  const uint32_t x = rand();
109 
110  try
111  {
112  c.write ( addr, x );
113 
114  if ( perTransactionDispatch )
115  {
116  c.dispatch();
117  }
118 
119  ValWord<uint32_t> reg = c.read ( addr );
120  c.dispatch();
121 
122  if ( x != reg.value() )
123  {
124  cout << "TEST FAILED: " << oss_details.str() << ". Wrote value 0x" << std::hex << x << " but read-back 0x" << reg.value() << std::dec << endl;
125  return false;
126  }
127  }
128  catch ( const std::exception& e )
129  {
130  cout << "TEST FAILED: " << oss_details.str() << ". Exception of type '" << typeid ( e ).name() << "' thrown ..." << endl << e.what() << endl;
131  return false;
132  }
133 
134  return true;
135 }
136 
137 
138 // Validation test -- block write/read-back
139 bool uhal::tests::PerfTester::validation_test_block_write_read ( ClientInterface& c, const uint32_t addr, const uint32_t depth, const bool perTransactionDispatch, const bool aVerbose )
140 {
141  std::ostringstream oss_details;
142  oss_details << depth << "-word write-read @ 0x" << std::hex << addr;
143 
144  if ( depth>1 )
145  {
146  oss_details << " to 0x" << addr+depth-1 << std::dec;
147  }
148 
149  oss_details << ( perTransactionDispatch ? " (multiple dispatches)" : " (single dispatch)" );
150 
151  if ( aVerbose )
152  {
153  cout << "Running test: " << oss_details.str() << endl;
154  }
155 
156  const U32Vec xx = getRandomBuffer ( depth );
157 
158  try
159  {
160  c.writeBlock ( addr, xx );
161 
162  if ( perTransactionDispatch )
163  {
164  c.dispatch();
165  }
166 
167  U32ValVec ram = c.readBlock ( addr, depth );
168  c.dispatch();
169  std::vector<uint32_t>::const_iterator valVecIt = ram.begin();
170  std::vector<uint32_t>::const_iterator xxIt = xx.begin();
171 
172  for ( ; valVecIt != ram.end(); valVecIt++, xxIt++ )
173  {
174  if ( ( *valVecIt ) != ( *xxIt ) )
175  {
176  uint32_t reg_addr = addr + ( valVecIt - ram.begin() );
177  cout << "TEST FAILED: " << oss_details.str() << ". Wrote value Ox" << std::hex << *xxIt << " to register 0x" << reg_addr << " but read-back 0x" << *valVecIt << std::dec << std::endl;
178  return false;
179  }
180  }
181 
182  log ( Notice(), "TEST PASSED: ", oss_details.str() );
183  }
184  catch ( const std::exception& e )
185  {
186  cout << "TEST FAILED: " << oss_details.str() << "! EXCEPTION of type '" << typeid ( e ).name() << "' thrown ..." << endl << e.what() << endl;
187  return false;
188  }
189 
190  return true;
191 }
192 
193 
194 // Validation test -- write, RMW bits, read
195 bool uhal::tests::PerfTester::validation_test_write_rmwbits_read ( ClientInterface& c, const uint32_t addr, const bool perTransactionDispatch, const bool aVerbose )
196 {
197  std::ostringstream oss_details;
198  oss_details << "RMW-bits @ 0x" << std::hex << addr << ( perTransactionDispatch ? " (multiple dispatches)" : " (single dispatch)" );
199 
200  if ( aVerbose )
201  {
202  cout << "TESTING: " << oss_details.str() << endl;
203  }
204 
205  const uint32_t x0 = rand();
206 
207  const uint32_t a = rand();
208 
209  const uint32_t b = rand();
210 
211  const uint32_t x1 = ( x0 & a ) | b;
212 
213  std::ostringstream oss_values;
214 
215  oss_values << "Wrote value 0x" << std::hex << x0 << ", then did RMW-bits with AND-term 0x" << a << ", OR-term 0x" << b;
216 
217  const bool ipbus2 = ( ( c.uri().find ( "ipbusudp-2.0" ) != string::npos ) || ( c.uri().find ( "ipbustcp-2.0" ) != string::npos ) || ( c.uri().find ( "chtcp-2.0" ) != string::npos ) || ( c.uri().find ( "ipbuspcie-2.0" ) != string::npos ) || ( c.uri().find ( "ipbusmmap-2.0" ) != string::npos ) );
218 
219  try
220  {
221  c.write ( addr, x0 );
222 
223  if ( perTransactionDispatch )
224  {
225  c.dispatch();
226  }
227 
228  ValWord<uint32_t> reg_rmw = c.rmw_bits ( addr, a, b );
229  c.dispatch();
230 
231  if ( ipbus2 ? ( x0 != reg_rmw.value() ) : ( x1 != reg_rmw.value() ) )
232  {
233  cout << "TEST FAILED: " << oss_details.str() << " ... RMW-bits returned value 0x" << std::hex << reg_rmw.value() << ", but expected 0x" << ( ipbus2 ? x0 : x1 ) << std::dec << endl << oss_values.str() << endl;
234  return false;
235  }
236 
237  ValWord<uint32_t> reg_read = c.read ( addr );
238  c.dispatch();
239 
240  if ( x1 != reg_read.value() )
241  {
242  cout << "TEST FAILED: " << oss_details.str() << " ... Read after RMW-bits returned value 0x" << std::hex << reg_read.value() << ", but expected 0x" << x1 << std::dec << endl << oss_values.str() << endl;
243  return false;
244  }
245  }
246  catch ( const std::exception& e )
247  {
248  cout << "TEST FAILED: " << oss_values.str() << ". Exception of type '" << typeid ( e ).name() << "' thrown ..." << endl << e.what() << endl;
249  return false;
250  }
251 
252  return true;
253 }
254 
255 // Validation test -- write, RMW sum, read
256 bool uhal::tests::PerfTester::validation_test_write_rmwsum_read ( ClientInterface& c, const uint32_t addr, const bool perTransactionDispatch, const bool aVerbose )
257 {
258  std::ostringstream oss_details;
259  oss_details << "RMW-sum @ 0x" << std::hex << addr << ( perTransactionDispatch ? " (multiple dispatches)" : " (single dispatch)" );
260 
261  if ( aVerbose )
262  {
263  cout << "TESTING: " << oss_details.str() << endl;
264  }
265 
266  const uint32_t x0 = rand();
267 
268  const uint32_t a = rand();
269 
270  const uint32_t x1 = x0 + a;
271 
272  std::ostringstream oss_values;
273 
274  oss_values << "Wrote value 0x" << std::hex << x0 << ", then did RMW-sum with ADDEND 0x" << a;
275 
276  const bool ipbus2 = ( ( c.uri().find ( "ipbusudp-2.0" ) != string::npos ) || ( c.uri().find ( "ipbustcp-2.0" ) != string::npos ) || ( c.uri().find ( "chtcp-2.0" ) != string::npos ) || ( c.uri().find ( "ipbuspcie-2.0" ) != string::npos ) || ( c.uri().find ( "ipbusmmap-2.0" ) != string::npos ) );
277 
278  try
279  {
280  c.write ( addr, x0 );
281 
282  if ( perTransactionDispatch )
283  {
284  c.dispatch();
285  }
286 
287  ValWord<uint32_t> reg_sum = c.rmw_sum ( addr, a );
288  c.dispatch();
289 
290  if ( ipbus2 ? ( x0 != reg_sum.value() ) : ( x1 != reg_sum.value() ) )
291  {
292  cout << "TEST FAILED: " << oss_details.str() << " ... RMW-sum returned value 0x" << std::hex << reg_sum.value() << ", but expected 0x" << ( ipbus2 ? x0 : x1 ) << std::dec << endl << oss_values.str() << endl;
293  return false;
294  }
295 
296  ValWord<uint32_t> reg_read = c.read ( addr );
297  c.dispatch();
298 
299  if ( x1 != reg_read.value() )
300  {
301  cout << "TEST FAILED: " << oss_details.str() << " ... Read after RMW-sum returned value 0x" << std::hex << reg_read.value() << ", but expected 0x" << x1 << std::dec << endl << oss_values.str() << endl;
302  return false;
303  }
304  }
305  catch ( const std::exception& e )
306  {
307  cout << "TEST FAILED: " << oss_values.str() << ". Exception of type '" << typeid ( e ).name() << "' thrown ..." << endl << e.what() << endl;
308  return false;
309  }
310 
311  return true;
312 }
313 
314 
315 bool uhal::tests::PerfTester::runValidationTest(const std::vector<ClientInterface*>& aClients, const uint32_t aBaseAddr, const uint32_t aDepth, const size_t aNrIterations, const bool aDispatchEachIteration, const bool aVerbose)
316 {
317  unsigned nrTestsFailed = 0;
318  unsigned nrTestsTotal = 0;
319 
320  // ---> A) Write read-back tests
321  //
322  typedef std::vector<ClientInterface*>::const_iterator ClientIt_t;
323  for ( ClientIt_t clientIt = aClients.begin(); clientIt != aClients.end(); clientIt++ )
324  {
325  ClientInterface* client = *clientIt;
326  cout << "\n\nWRITE READ-BACK TESTS for device at '" << client->uri() << "'" << endl;
327  vector<uint32_t> addr_vec;
328  addr_vec.push_back ( aBaseAddr );
329  addr_vec.push_back ( aBaseAddr + aDepth - 1 );
330 
331  for ( unsigned i = 0; i < 2498; i++ )
332  {
333  addr_vec.push_back ( aBaseAddr + ( rand() % aDepth ) );
334  }
335 
336  cout << "\n 1. Single-register write/read (" << addr_vec.size() * 2 << " tests)" << endl;
337 
338  for ( unsigned i = 0; i < addr_vec.size(); i++ )
339  {
340  nrTestsTotal++;
341 
342  if ( ! validation_test_single_write_read ( *client, addr_vec.at ( i ), true, aVerbose ) )
343  {
344  nrTestsFailed++;
345  }
346 
347  nrTestsTotal++;
348 
349  if ( ! validation_test_single_write_read ( *client, addr_vec.at ( i ), false || aDispatchEachIteration, aVerbose ) )
350  {
351  nrTestsFailed++;
352  }
353  }
354 
355  cout << "\n 2. Block write/read (" << addr_vec.size() * 2 << " tests)" << endl;
356 
357  for ( unsigned i = 0; i < addr_vec.size(); i++ )
358  {
359  uint32_t addr = addr_vec.at ( i );
360  uint32_t max_depth = aBaseAddr + aDepth - addr;
361  uint32_t depth = rand() % ( max_depth + 1 );
362 
363  nrTestsTotal++;
364 
365  if ( ! validation_test_block_write_read ( *client, addr, depth, true, aVerbose ) )
366  {
367  nrTestsFailed++;
368  }
369 
370  nrTestsTotal++;
371 
372  if ( ! validation_test_block_write_read ( *client, addr, depth, false || aDispatchEachIteration, aVerbose ) )
373  {
374  nrTestsFailed++;
375  }
376  }
377 
378  cout << "\n 3. Testing RMW-bits (write, RMWbits, read; " << addr_vec.size() * 2 << " tests)" << endl;
379 
380  for ( std::vector<uint32_t>::const_iterator it = addr_vec.begin(); it != addr_vec.end(); it++ )
381  {
382  nrTestsTotal++;
383 
384  if ( ! validation_test_write_rmwbits_read ( *client, *it, true, aVerbose ) )
385  {
386  nrTestsFailed++;
387  }
388 
389  nrTestsTotal++;
390 
391  if ( ! validation_test_write_rmwbits_read ( *client, *it, false || aDispatchEachIteration, aVerbose ) )
392  {
393  nrTestsFailed++;
394  }
395  }
396 
397  cout << "\n 4. Testing RMW-sum (write, RMW-sum, read; " << addr_vec.size() * 2 << " tests)" << endl;
398 
399  for ( std::vector<uint32_t>::const_iterator it = addr_vec.begin(); it != addr_vec.end(); it++ )
400  {
401  nrTestsTotal++;
402 
403  if ( ! validation_test_write_rmwsum_read ( *client, *it, true, aVerbose ) )
404  {
405  nrTestsFailed++;
406  }
407 
408  nrTestsTotal++;
409 
410  if ( ! validation_test_write_rmwsum_read ( *client, *it, false || aDispatchEachIteration, aVerbose ) )
411  {
412  nrTestsFailed++;
413  }
414  }
415  }//end: for, m_clients
416 
417  if ( nrTestsFailed == 0 )
418  {
419  cout << "\n\nBASIC TESTS SUMMARY: All " << nrTestsTotal << " tests passed!" << endl << endl << endl;
420  }
421  else
422  {
423  cout << "\n\nBASIC TESTS SUMMARY: Total of " << nrTestsTotal << " tests run -- " << nrTestsFailed << " tests FAILED , " << ( nrTestsTotal - nrTestsFailed ) << " tests PASSED" << endl;
424  return false;
425  }
426 
427  // ---> B) SOAK TESTs
428  //
429  for ( ClientIt_t clientIt = aClients.begin(); clientIt != aClients.end(); clientIt++ )
430  {
431  ClientInterface* client = *clientIt;
432  cout << "\nSOAK TEST to device '" << client->uri() << "'\n Random sequence of " << aNrIterations << " transactions will be sent to hardware" << endl << endl;
433  // Setup
434  uint32_t ipbus_vsn;
435  size_t found = client->uri().find ( "-1.3" );
436 
437  if ( found!=std::string::npos )
438  {
439  ipbus_vsn = 1;
440  }
441  else
442  {
443  found = client->uri().find ( "-2.0" );
444 
445  if ( found!=std::string::npos )
446  {
447  ipbus_vsn = 2;
448  }
449  else
450  {
451  log ( Error() , "Cannot deduce protocol from URI " , Quote ( client->uri() ), " Exiting before performing soak test." );
452  return false;
453  }
454  }
455 
456  // Initialise registers to 0x0
457  std::vector< uint32_t > registers ( aDepth , 0x00000000 );
458  client->writeBlock ( aBaseAddr, registers );
459  client->dispatch();
460  // ACTUAL MEAT OF SOAK TEST
461  uint32_t type, addr, blockSize;
462  uint32_t tempUInt1, tempUInt2;
463  vector< boost::shared_ptr<QueuedTransaction> > queuedTransactions;
464  uint32_t nrQueuedWords = 0;
465 
466  for ( unsigned i = 1; i <= aNrIterations; i++ )
467  {
468  type = ( rand() % 4 );
469  addr = aBaseAddr + ( rand() % aDepth );
470 
471  switch ( type )
472  {
473  case 0: // read
474  {
475  blockSize = getRandomBlockSize ( aBaseAddr + aDepth - addr );
476  log ( Notice(), "Soak test - queueing: ", Integer ( blockSize ), "-word read at ", Integer ( addr, IntFmt<hex,fixed>() ) );
477 
478  ValVector<uint32_t> result = client->readBlock ( addr, blockSize, defs::INCREMENTAL );
479  queuedTransactions.push_back ( boost::shared_ptr<QueuedTransaction> ( new QueuedBlockRead ( addr, result, registers.begin() + ( addr - aBaseAddr ) ) ) );
480  nrQueuedWords += blockSize;
481  break;
482  }
483  case 1: // write
484  {
485  blockSize = getRandomBlockSize ( aBaseAddr + aDepth - addr );
486  log ( Notice(), "Soak test - queueing: ", Integer ( blockSize ), "-word write at ", Integer ( addr, IntFmt<hex,fixed>() ) );
487 
488  vector<uint32_t> randomData = getRandomBuffer ( blockSize );
489  ValHeader result = client->writeBlock ( addr, randomData, defs::INCREMENTAL );
490  std::copy ( randomData.begin(), randomData.end(), registers.begin() + ( addr - aBaseAddr ) );
491  queuedTransactions.push_back ( boost::shared_ptr<QueuedTransaction> ( new QueuedBlockWrite ( addr, blockSize, result ) ) );
492  nrQueuedWords += blockSize;
493  break;
494  }
495  case 2: // RMW-bits
496  {
497  log ( Notice(), "Soak test - queueing: RMW-bits at ", Integer ( addr, IntFmt<hex,fixed>() ) );
498  tempUInt1 = rand();
499  tempUInt2 = rand();
500  vector<uint32_t>::iterator regIt = registers.begin() + ( addr - aBaseAddr );
501 
502  if ( ipbus_vsn == 1 )
503  {
504  *regIt &= tempUInt1;
505  *regIt |= tempUInt2;
506  }
507 
508  ValWord<uint32_t> result = client->rmw_bits ( addr, tempUInt1, tempUInt2 );
509  queuedTransactions.push_back ( boost::shared_ptr<QueuedTransaction> ( new QueuedRmwBits ( addr, tempUInt1, tempUInt2, result, *regIt ) ) );
510  nrQueuedWords += 1;
511 
512  if ( ipbus_vsn == 2 )
513  {
514  *regIt &= tempUInt1;
515  *regIt |= tempUInt2;
516  }
517 
518  break;
519  }
520  case 3: // RMW-sum
521  {
522  log ( Notice(), "Soak test - queueing: RMW-sum at ", Integer ( addr, IntFmt<hex,fixed>() ) );
523  tempUInt1 = rand();
524  vector<uint32_t>::iterator regIt = registers.begin() + ( addr - aBaseAddr );
525 
526  if ( ipbus_vsn == 1 )
527  {
528  *regIt += tempUInt1;
529  }
530 
531  ValWord<uint32_t> result = client->rmw_sum ( addr, tempUInt1 );
532  queuedTransactions.push_back ( boost::shared_ptr<QueuedTransaction> ( new QueuedRmwSum ( addr, tempUInt1, result, *regIt ) ) );
533  nrQueuedWords += 1;
534 
535  if ( ipbus_vsn == 2 )
536  {
537  *regIt += tempUInt1;
538  }
539 
540  break;
541  }
542  }
543 
544  if ( aDispatchEachIteration || ( nrQueuedWords > 20000000 ) || ( i == aNrIterations ) )
545  {
546  log ( Notice(), "Soak test - issuing dispatch" );
547  client->dispatch();
548  log ( Notice(), "Soak test - issuing empty dispatch" );
549  client->dispatch();
550 
551  for ( vector< boost::shared_ptr<QueuedTransaction> >::const_iterator it = queuedTransactions.begin(); it != queuedTransactions.end(); it++ )
552  {
553  if ( ! ( *it )->check_values() )
554  {
555  cout << "ERROR OCCURED IN SOAK TEST to '" << client->uri() << "' - after " << i << " successful transactions" << endl;
556  return false;
557  }
558  }
559 
560  queuedTransactions.clear();
561  nrQueuedWords = 0;
562 
563  if ( ! aVerbose )
564  {
565  std::cout << "No errors after " << i << " transactions -- " << setiosflags ( ios::fixed ) << setprecision ( 1 ) << ( 100.0 * i ) / aNrIterations << "% done\r";
566  std::cout.flush();
567  }
568  }
569  }
570  }//end: for, aClients
571 
572  cout << endl << "Reached end of soak testing successfully!" << endl;
573  return true;
574 }
575 
576 
577 // PerfTester::QueuedBlockRead MEMBER FUNCTIONS
578 
579 uhal::tests::PerfTester::QueuedBlockRead::QueuedBlockRead ( const uint32_t addr, const ValVector<uint32_t>& valVector, std::vector<uint32_t>::const_iterator expectedValuesIt ) :
580  m_depth ( valVector.size() ),
581  m_addr ( addr ),
582  m_valVector ( valVector )
583 {
584  m_expected.assign ( expectedValuesIt, expectedValuesIt + m_depth );
585 }
586 
588 { }
589 
591 {
592  std::vector<uint32_t>::const_iterator valVecIt = m_valVector.begin();
593  std::vector<uint32_t>::const_iterator expdIt = m_expected.begin();
594 
595  for ( ; valVecIt != m_valVector.end(); valVecIt++, expdIt++ )
596  {
597  if ( ( *valVecIt ) != ( *expdIt ) )
598  {
599  uint32_t addr = m_addr + ( valVecIt - m_valVector.begin() );
600  log ( Error(), "TEST FAILED: In ", Integer ( m_depth ), "-word read @ ", Integer ( m_addr, IntFmt<hex,fixed>() ), ", register ", Integer ( addr, IntFmt<hex,fixed>() ), " has value ", Integer ( *valVecIt, IntFmt<hex,fixed>() ), ", but expected value ", Integer ( *expdIt, IntFmt<hex,fixed>() ) );
601  return false;
602  }
603  }
604 
605  log ( Notice(), "TEST PASSED: Incrementing ", Integer ( m_depth ), "-word read @ ", Integer ( m_addr, IntFmt<hex,fixed>() ), " --> ", Integer ( m_addr + m_depth - 1, IntFmt<hex,fixed>() ) );
606  return true;
607 }
608 
609 
610 // PerfTester::QueuedBlockWrite MEMBER FUNCTIONS
611 
612 uhal::tests::PerfTester::QueuedBlockWrite::QueuedBlockWrite ( const uint32_t addr, const uint32_t depth, const ValHeader& valHeader ) :
613  m_depth ( depth ),
614  m_addr ( addr ),
615  m_valHeader ( valHeader )
616 { }
617 
619 { }
620 
622 {
623  if ( ! m_valHeader.valid() )
624  {
625  log ( Error(), "TEST FAILED: Incrementing ", Integer ( m_depth ), "-word write @ ", Integer ( m_addr, IntFmt<hex,fixed>() ), " unsuccessful." );
626  return false;
627  }
628 
629  log ( Notice(), "TEST PASSED: Incrementing ", Integer ( m_depth ), "-word write @ ", Integer ( m_addr, IntFmt<hex,fixed>() ), " --> ", Integer ( m_addr + m_depth - 1, IntFmt<hex,fixed>() ) );
630  return true;
631 }
632 
633 
634 // PerfTester::QueuedRmwBits MEMBER FUNCTIONS
635 
636 uhal::tests::PerfTester::QueuedRmwBits::QueuedRmwBits ( const uint32_t addr, const uint32_t a, const uint32_t b, const ValWord<uint32_t>& valWord, const uint32_t expected ) :
637  m_addr ( addr ),
638  m_and ( a ),
639  m_or ( b ),
640  m_valWord ( valWord ),
641  m_expected ( expected )
642 { }
643 
645 { }
646 
648 {
649  if ( m_valWord.value() != m_expected )
650  {
651  log ( Error(), "TEST FAILED: RMW-bits @ ", Integer ( m_addr, IntFmt<hex,fixed>() ), " (AND=", Integer ( m_and, IntFmt<hex,fixed>() ), ", OR=", Integer ( m_or, IntFmt<hex,fixed>() ), "). Transaction returned ", Integer ( m_valWord.value(), IntFmt<hex,fixed>() ), ", but expected ", Integer ( m_expected, IntFmt<hex,fixed>() ) );
652  return false;
653  }
654 
655  log ( Notice(), "TEST PASSED: RMW-bits @ ", Integer ( m_addr, IntFmt<hex,fixed>() ) );
656  return true;
657 }
658 
659 
660 // PerfTester::QueuedRmwSum MEMBER FUNCTIONS
661 
662 uhal::tests::PerfTester::QueuedRmwSum::QueuedRmwSum ( const uint32_t addr, const uint32_t a, const ValWord<uint32_t>& valWord, const uint32_t expected ) :
663  m_addr ( addr ),
664  m_addend ( a ),
665  m_valWord ( valWord ),
666  m_expected ( expected )
667 { }
668 
670 { }
671 
673 {
674  if ( m_valWord.value() != m_expected )
675  {
676  log ( Error(), "TEST FAILED: RMW-sum @ ", Integer ( m_addr, IntFmt<hex,fixed>() ), ", ADDEND=", Integer ( m_addend, IntFmt<hex,fixed>() ), ". Transaction returned ", Integer ( m_valWord.value(), IntFmt<hex,fixed>() ), ", but I expected ", Integer ( m_expected, IntFmt<>() ) );
677  return false;
678  }
679 
680  log ( Notice(), "TEST PASSED: RMW-sum @ ", Integer ( m_addr, IntFmt<hex,fixed>() ) );
681  return true;
682 }
NoticeLevel Notice
Definition: LogLevels.cpp:96
ValWord< uint32_t > read(const uint32_t &aAddr)
Read a single, unmasked, unsigned word.
void dispatch()
Method to dispatch all IPbus packets which are in the queue of IPbusPacketInfo&#39;s and wait until all q...
T value() const
Return the value of the validated memory with check on validity.
Definition: ValMem.cpp:185
A class which wraps a block of data and marks whether or not it is valid.
Definition: ValMem.hpp:76
ValWord< uint32_t > rmw_sum(const uint32_t &aAddr, const int32_t &aAddend)
Read the value of a register, add the addend, set the register to this new value and return a copy of...
WarningLevel Warning
Definition: LogLevels.cpp:79
ValWord< uint32_t > reg
std::vector< U32 > U32Vec
A vector of unsigned 32-bit words.
Definition: PerfTester.hxx:83
ValHeader write(const uint32_t &aAddr, const uint32_t &aValue)
Write a single, unmasked word to a register.
static bool runValidationTest(const std::vector< ClientInterface *> &aClients, const uint32_t aBaseAddr, const uint32_t aDepth, const size_t aNrIterations, const bool aDispatchEachIteration, const bool aVerbose)
Definition: PerfTester.cxx:361
bool valid()
Return whether the Validated memory is marked as valid.
Definition: ValMem.cpp:79
static bool validation_test_block_write_read(uhal::ClientInterface &c, const uint32_t addr, const uint32_t depth, const bool perTransactionDispatch, const bool aVerbose)
Validation test – block write/read-back.
std::string uri() const
Ping the target for this client.
void push_back(const T &aValue)
If the memory has not previously been marked as valid, add an entry to the end of it...
Definition: ValMem.cpp:304
ErrorLevel Error
Definition: LogLevels.cpp:61
static bool validation_test_write_rmwbits_read(uhal::ClientInterface &c, const uint32_t addr, const bool perTransactionDispatch, const bool aVerbose)
Validation test – write, RMW bits, read.
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
Empty struct which acts as a dummy variable for passing the formatting information around...
_Quote< T > Quote(const T &aT)
IPbusCore & client
static uint32_t getRandomBlockSize(const uint32_t maxSize)
Returns a random uint32_t in the range [0,maxSize], with 1/x probability distribution – so that p(x=...
ClientInterface * c
static bool validation_test_single_write_read(uhal::ClientInterface &c, const uint32_t addr, const bool perTransactionDispatch, const bool aVerbose)
Validation test – single-register write/read-back.
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
ValVector< uint32_t > readBlock(const uint32_t &aAddr, const uint32_t &aSize, const defs::BlockReadWriteMode &aMode=defs::INCREMENTAL)
Read a block of unsigned data from a block of registers or a block-read port.
std::vector< uint32_t > xx
Definition: test_block.cpp:238
static bool validation_test_write_rmwsum_read(uhal::ClientInterface &c, const uint32_t addr, const bool perTransactionDispatch, const bool aVerbose)
Validation test – write, RMW sum, read.
ValHeader writeBlock(const uint32_t &aAddr, const std::vector< uint32_t > &aValues, const defs::BlockReadWriteMode &aMode=defs::INCREMENTAL)
Write a block of data to a block of registers or a block-write port.
An abstract base class for defining the interface to the various IPbus clients as well as providing t...
QueuedBlockRead(const uint32_t addr, const ValVector< uint32_t > &valVector, std::vector< uint32_t >::const_iterator expectedValuesIt)
QueuedRmwSum(const uint32_t addr, const uint32_t a, const ValWord< uint32_t > &valWord, const uint32_t expected)
Hexadecimal.
A class which wraps a single word of data and marks whether or not it is valid.
Definition: ValMem.hpp:156
ValWord< uint32_t > rmw_bits(const uint32_t &aAddr, const uint32_t &aANDterm, const uint32_t &aORterm)
Read the value of a register, apply the AND-term, apply the OR-term, set the register to this new val...
static U32Vec getRandomBuffer(unsigned size)
Returns a buffer of random numbers.
_Integer< T, IntFmt<> > Integer(const T &aT)
Forward declare a function which creates an instance of the ultra-lightweight wrapper from an integer...
QueuedRmwBits(const uint32_t addr, const uint32_t a, const uint32_t b, const ValWord< uint32_t > &valWord, const uint32_t expected)
QueuedBlockWrite(const uint32_t addr, const uint32_t depth, const ValHeader &valHeader)