μHAL (v2.7.9)
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 
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  std::exit(1);
346  }
347 
348  nrTestsTotal++;
349 
350  if ( ! validation_test_single_write_read ( *client, addr_vec.at ( i ), false || aDispatchEachIteration, aVerbose ) )
351  {
352  nrTestsFailed++;
353  std::exit(1);
354  }
355  }
356 
357  cout << "\n 2. Block write/read (" << addr_vec.size() * 2 << " tests)" << endl;
358 
359  for ( unsigned i = 0; i < addr_vec.size(); i++ )
360  {
361  uint32_t addr = addr_vec.at ( i );
362  uint32_t max_depth = aBaseAddr + aDepth - addr;
363  uint32_t depth = rand() % ( max_depth + 1 );
364 
365  nrTestsTotal++;
366 
367  if ( ! validation_test_block_write_read ( *client, addr, depth, true, aVerbose ) )
368  {
369  nrTestsFailed++;
370  std::exit(1);
371  }
372 
373  nrTestsTotal++;
374 
375  if ( ! validation_test_block_write_read ( *client, addr, depth, false || aDispatchEachIteration, aVerbose ) )
376  {
377  nrTestsFailed++;
378  std::exit(1);
379  }
380  }
381 
382  cout << "\n 3. Testing RMW-bits (write, RMWbits, read; " << addr_vec.size() * 2 << " tests)" << endl;
383 
384  for ( std::vector<uint32_t>::const_iterator it = addr_vec.begin(); it != addr_vec.end(); it++ )
385  {
386  nrTestsTotal++;
387 
388  if ( ! validation_test_write_rmwbits_read ( *client, *it, true, aVerbose ) )
389  {
390  nrTestsFailed++;
391  std::exit(1);
392  }
393 
394  nrTestsTotal++;
395 
396  if ( ! validation_test_write_rmwbits_read ( *client, *it, false || aDispatchEachIteration, aVerbose ) )
397  {
398  nrTestsFailed++;
399  std::exit(1);
400  }
401  }
402 
403  cout << "\n 4. Testing RMW-sum (write, RMW-sum, read; " << addr_vec.size() * 2 << " tests)" << endl;
404 
405  for ( std::vector<uint32_t>::const_iterator it = addr_vec.begin(); it != addr_vec.end(); it++ )
406  {
407  nrTestsTotal++;
408 
409  if ( ! validation_test_write_rmwsum_read ( *client, *it, true, aVerbose ) )
410  {
411  nrTestsFailed++;
412  std::exit(1);
413  }
414 
415  nrTestsTotal++;
416 
417  if ( ! validation_test_write_rmwsum_read ( *client, *it, false || aDispatchEachIteration, aVerbose ) )
418  {
419  nrTestsFailed++;
420  std::exit(1);
421  }
422  }
423  }//end: for, m_clients
424 
425  if ( nrTestsFailed == 0 )
426  {
427  cout << "\n\nBASIC TESTS SUMMARY: All " << nrTestsTotal << " tests passed!" << endl << endl << endl;
428  }
429  else
430  {
431  cout << "\n\nBASIC TESTS SUMMARY: Total of " << nrTestsTotal << " tests run -- " << nrTestsFailed << " tests FAILED , " << ( nrTestsTotal - nrTestsFailed ) << " tests PASSED" << endl;
432  return false;
433  }
434 
435  // ---> B) SOAK TESTs
436  //
437  for ( ClientIt_t clientIt = aClients.begin(); clientIt != aClients.end(); clientIt++ )
438  {
439  ClientInterface* client = *clientIt;
440  cout << "\nSOAK TEST to device '" << client->uri() << "'\n Random sequence of " << aNrIterations << " transactions will be sent to hardware" << endl << endl;
441  // Setup
442  uint32_t ipbus_vsn;
443  size_t found = client->uri().find ( "-1.3" );
444 
445  if ( found!=std::string::npos )
446  {
447  ipbus_vsn = 1;
448  }
449  else
450  {
451  found = client->uri().find ( "-2.0" );
452 
453  if ( found!=std::string::npos )
454  {
455  ipbus_vsn = 2;
456  }
457  else
458  {
459  log ( Error() , "Cannot deduce protocol from URI " , Quote ( client->uri() ), " Exiting before performing soak test." );
460  return false;
461  }
462  }
463 
464  // Initialise registers to 0x0
465  std::vector< uint32_t > registers ( aDepth , 0x00000000 );
466  client->writeBlock ( aBaseAddr, registers );
467  client->dispatch();
468  // ACTUAL MEAT OF SOAK TEST
469  uint32_t type, addr, blockSize;
470  uint32_t tempUInt1, tempUInt2;
471  vector< boost::shared_ptr<QueuedTransaction> > queuedTransactions;
472  uint32_t nrQueuedWords = 0;
473 
474  for ( unsigned i = 1; i <= aNrIterations; i++ )
475  {
476  type = ( rand() % 4 );
477  addr = aBaseAddr + ( rand() % aDepth );
478 
479  switch ( type )
480  {
481  case 0: // read
482  {
483  blockSize = getRandomBlockSize ( aBaseAddr + aDepth - addr );
484  log ( Notice(), "Soak test - queueing: ", Integer ( blockSize ), "-word read at ", Integer ( addr, IntFmt<hex,fixed>() ) );
485 
486  ValVector<uint32_t> result = client->readBlock ( addr, blockSize, defs::INCREMENTAL );
487  queuedTransactions.push_back ( boost::shared_ptr<QueuedTransaction> ( new QueuedBlockRead ( addr, result, registers.begin() + ( addr - aBaseAddr ) ) ) );
488  nrQueuedWords += blockSize;
489  break;
490  }
491  case 1: // write
492  {
493  blockSize = getRandomBlockSize ( aBaseAddr + aDepth - addr );
494  log ( Notice(), "Soak test - queueing: ", Integer ( blockSize ), "-word write at ", Integer ( addr, IntFmt<hex,fixed>() ) );
495 
496  vector<uint32_t> randomData = getRandomBuffer ( blockSize );
497  ValHeader result = client->writeBlock ( addr, randomData, defs::INCREMENTAL );
498  std::copy ( randomData.begin(), randomData.end(), registers.begin() + ( addr - aBaseAddr ) );
499  queuedTransactions.push_back ( boost::shared_ptr<QueuedTransaction> ( new QueuedBlockWrite ( addr, blockSize, result ) ) );
500  nrQueuedWords += blockSize;
501  break;
502  }
503  case 2: // RMW-bits
504  {
505  log ( Notice(), "Soak test - queueing: RMW-bits at ", Integer ( addr, IntFmt<hex,fixed>() ) );
506  tempUInt1 = rand();
507  tempUInt2 = rand();
508  vector<uint32_t>::iterator regIt = registers.begin() + ( addr - aBaseAddr );
509 
510  if ( ipbus_vsn == 1 )
511  {
512  *regIt &= tempUInt1;
513  *regIt |= tempUInt2;
514  }
515 
516  ValWord<uint32_t> result = client->rmw_bits ( addr, tempUInt1, tempUInt2 );
517  queuedTransactions.push_back ( boost::shared_ptr<QueuedTransaction> ( new QueuedRmwBits ( addr, tempUInt1, tempUInt2, result, *regIt ) ) );
518  nrQueuedWords += 1;
519 
520  if ( ipbus_vsn == 2 )
521  {
522  *regIt &= tempUInt1;
523  *regIt |= tempUInt2;
524  }
525 
526  break;
527  }
528  case 3: // RMW-sum
529  {
530  log ( Notice(), "Soak test - queueing: RMW-sum at ", Integer ( addr, IntFmt<hex,fixed>() ) );
531  tempUInt1 = rand();
532  vector<uint32_t>::iterator regIt = registers.begin() + ( addr - aBaseAddr );
533 
534  if ( ipbus_vsn == 1 )
535  {
536  *regIt += tempUInt1;
537  }
538 
539  ValWord<uint32_t> result = client->rmw_sum ( addr, tempUInt1 );
540  queuedTransactions.push_back ( boost::shared_ptr<QueuedTransaction> ( new QueuedRmwSum ( addr, tempUInt1, result, *regIt ) ) );
541  nrQueuedWords += 1;
542 
543  if ( ipbus_vsn == 2 )
544  {
545  *regIt += tempUInt1;
546  }
547 
548  break;
549  }
550  }
551 
552  if ( aDispatchEachIteration || ( nrQueuedWords > 20000000 ) || ( i == aNrIterations ) )
553  {
554  log ( Notice(), "Soak test - issuing dispatch" );
555  client->dispatch();
556  log ( Notice(), "Soak test - issuing empty dispatch" );
557  client->dispatch();
558 
559  for ( vector< boost::shared_ptr<QueuedTransaction> >::const_iterator it = queuedTransactions.begin(); it != queuedTransactions.end(); it++ )
560  {
561  if ( ! ( *it )->check_values() )
562  {
563  cout << "ERROR OCCURED IN SOAK TEST to '" << client->uri() << "' - after " << i << " successful transactions" << endl;
564  return false;
565  }
566  }
567 
568  queuedTransactions.clear();
569  nrQueuedWords = 0;
570 
571  if ( ! aVerbose )
572  {
573  std::cout << "No errors after " << i << " transactions -- " << setiosflags ( ios::fixed ) << setprecision ( 1 ) << ( 100.0 * i ) / aNrIterations << "% done\r";
574  std::cout.flush();
575  }
576  }
577  }
578  }//end: for, aClients
579 
580  cout << endl << "Reached end of soak testing successfully!" << endl;
581  return true;
582 }
583 
584 
585 // PerfTester::QueuedBlockRead MEMBER FUNCTIONS
586 
587 uhal::tests::PerfTester::QueuedBlockRead::QueuedBlockRead ( const uint32_t addr, const ValVector<uint32_t>& valVector, std::vector<uint32_t>::const_iterator expectedValuesIt ) :
588  m_depth ( valVector.size() ),
589  m_addr ( addr ),
590  m_valVector ( valVector )
591 {
592  m_expected.assign ( expectedValuesIt, expectedValuesIt + m_depth );
593 }
594 
596 { }
597 
599 {
600  std::vector<uint32_t>::const_iterator valVecIt = m_valVector.begin();
601  std::vector<uint32_t>::const_iterator expdIt = m_expected.begin();
602 
603  for ( ; valVecIt != m_valVector.end(); valVecIt++, expdIt++ )
604  {
605  if ( ( *valVecIt ) != ( *expdIt ) )
606  {
607  uint32_t addr = m_addr + ( valVecIt - m_valVector.begin() );
608  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>() ) );
609  return false;
610  }
611  }
612 
613  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>() ) );
614  return true;
615 }
616 
617 
618 // PerfTester::QueuedBlockWrite MEMBER FUNCTIONS
619 
620 uhal::tests::PerfTester::QueuedBlockWrite::QueuedBlockWrite ( const uint32_t addr, const uint32_t depth, const ValHeader& valHeader ) :
621  m_depth ( depth ),
622  m_addr ( addr ),
623  m_valHeader ( valHeader )
624 { }
625 
627 { }
628 
630 {
631  if ( ! m_valHeader.valid() )
632  {
633  log ( Error(), "TEST FAILED: Incrementing ", Integer ( m_depth ), "-word write @ ", Integer ( m_addr, IntFmt<hex,fixed>() ), " unsuccessful." );
634  return false;
635  }
636 
637  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>() ) );
638  return true;
639 }
640 
641 
642 // PerfTester::QueuedRmwBits MEMBER FUNCTIONS
643 
644 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 ) :
645  m_addr ( addr ),
646  m_and ( a ),
647  m_or ( b ),
648  m_valWord ( valWord ),
649  m_expected ( expected )
650 { }
651 
653 { }
654 
656 {
657  if ( m_valWord.value() != m_expected )
658  {
659  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>() ) );
660  return false;
661  }
662 
663  log ( Notice(), "TEST PASSED: RMW-bits @ ", Integer ( m_addr, IntFmt<hex,fixed>() ) );
664  return true;
665 }
666 
667 
668 // PerfTester::QueuedRmwSum MEMBER FUNCTIONS
669 
670 uhal::tests::PerfTester::QueuedRmwSum::QueuedRmwSum ( const uint32_t addr, const uint32_t a, const ValWord<uint32_t>& valWord, const uint32_t expected ) :
671  m_addr ( addr ),
672  m_addend ( a ),
673  m_valWord ( valWord ),
674  m_expected ( expected )
675 { }
676 
678 { }
679 
681 {
682  if ( m_valWord.value() != m_expected )
683  {
684  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<>() ) );
685  return false;
686  }
687 
688  log ( Notice(), "TEST PASSED: RMW-sum @ ", Integer ( m_addr, IntFmt<hex,fixed>() ) );
689  return true;
690 }
tools.hpp
uhal::ValVector
A class which wraps a block of data and marks whether or not it is valid.
Definition: ValMem.hpp:75
uhal::ValVector::push_back
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:232
uhal::dec
@ dec
Decimal.
Definition: log_inserters.integer.hpp:50
uhal::ClientInterface::writeBlock
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.
Definition: ClientInterface.cpp:449
uhal::tests::PerfTester::QueuedRmwBits::~QueuedRmwBits
~QueuedRmwBits()
Definition: PerfTester_static.cpp:652
boost::shared_ptr
Definition: DerivedNodeFactory.hpp:52
uhal::tests::PerfTester::QueuedRmwSum
Definition: PerfTester.hxx:235
uhal::tests::PerfTester::QueuedBlockRead
Definition: PerfTester.hxx:190
uhal::ClientInterface::dispatch
void dispatch()
Method to dispatch all queued transactions, and wait until all corresponding responses have been rece...
Definition: ClientInterface.cpp:144
uhal::tests::PerfTester::getRandomBuffer
static U32Vec getRandomBuffer(unsigned size)
Returns a buffer of random numbers.
Definition: PerfTester_static.cpp:82
uhal::tests::PerfTester::QueuedRmwBits::check_values
virtual bool check_values()
Definition: PerfTester_static.cpp:655
uhal::tests::reg
ValWord< uint32_t > reg
Definition: test_rawclient.cpp:194
uhal::ValVector::begin
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:295
uhal::tests::PerfTester::QueuedRmwSum::QueuedRmwSum
QueuedRmwSum(const uint32_t addr, const uint32_t a, const ValWord< uint32_t > &valWord, const uint32_t expected)
Definition: PerfTester_static.cpp:670
uhal::tests::PerfTester::QueuedBlockRead::m_expected
std::vector< uint32_t > m_expected
Definition: PerfTester.hxx:201
uhal::tests::PerfTester::QueuedBlockWrite
Definition: PerfTester.hxx:206
uhal::ClientInterface
An abstract base class for defining the interface to the various IPbus clients as well as providing t...
Definition: ClientInterface.hpp:100
uhal::ValWord::value
T value() const
Return the value of the validated memory with check on validity.
Definition: ValMem.cpp:141
uhal::IntFmt
Empty struct which acts as a dummy variable for passing the formatting information around.
Definition: log_inserters.integer.hpp:68
uhal::tests::PerfTester::runValidationTest
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_static.cpp:315
uhal::tests::PerfTester::QueuedBlockRead::check_values
virtual bool check_values()
Definition: PerfTester_static.cpp:598
setupTemplate.name
name
Definition: setupTemplate.py:32
uhal::tests::PerfTester::QueuedBlockRead::QueuedBlockRead
QueuedBlockRead(const uint32_t addr, const ValVector< uint32_t > &valVector, std::vector< uint32_t >::const_iterator expectedValuesIt)
Definition: PerfTester_static.cpp:587
uhal::ValHeader
A class which wraps a single word of data and marks whether or not it is valid.
Definition: ValMem.hpp:148
uhal::tests::PerfTester::QueuedBlockRead::m_depth
uint32_t m_depth
Definition: PerfTester.hxx:199
uhal::tests::x
uint32_t x
Definition: test_single.cpp:93
uhal::tests::PerfTester::validation_test_write_rmwbits_read
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.
Definition: PerfTester_static.cpp:195
uhal::tests::PerfTester::QueuedRmwBits
Definition: PerfTester.hxx:221
uhal::tests::PerfTester::validation_test_block_write_read
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.
Definition: PerfTester_static.cpp:139
uhal::tests::PerfTester::U32Vec
std::vector< U32 > U32Vec
A vector of unsigned 32-bit words.
Definition: PerfTester.hxx:83
uhal::tests::addr
uint32_t addr
Definition: test_rawclient.cpp:102
uhal::log
void log(FatalLevel &aFatal, const T0 &aArg0)
Function to add a log entry at Fatal level.
Definition: log.hxx:20
uhal::ClientInterface::read
ValWord< uint32_t > read(const uint32_t &aAddr)
Read a single, unmasked, unsigned word.
Definition: ClientInterface.cpp:458
uhal::tests::PerfTester::QueuedRmwSum::check_values
virtual bool check_values()
Definition: PerfTester_static.cpp:680
uhal::Integer
_Integer< T, IntFmt<> > Integer(const T &aT)
Forward declare a function which creates an instance of the ultra-lightweight wrapper from an integer...
Definition: log_inserters.integer.hxx:43
uhal::tests::xx
std::vector< uint32_t > xx
Definition: test_block.cpp:247
uhal::tests::PerfTester::QueuedBlockWrite::~QueuedBlockWrite
~QueuedBlockWrite()
Definition: PerfTester_static.cpp:626
uhal::tests::PerfTester::QueuedBlockWrite::QueuedBlockWrite
QueuedBlockWrite(const uint32_t addr, const uint32_t depth, const ValHeader &valHeader)
Definition: PerfTester_static.cpp:620
uhal::tests::client
IPbusCore & client
Definition: test_config_space.cpp:79
uhal::hex
@ hex
Hexadecimal.
Definition: log_inserters.integer.hpp:51
uhal::tests::PerfTester::validation_test_single_write_read
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.
Definition: PerfTester_static.cpp:98
uhal::tests::PerfTester::validation_test_write_rmwsum_read
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.
Definition: PerfTester_static.cpp:256
uhal::Warning
WarningLevel Warning
Definition: LogLevels.cpp:79
uhal::ClientInterface::readBlock
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.
Definition: ClientInterface.cpp:472
uhal::tests::PerfTester::QueuedRmwBits::QueuedRmwBits
QueuedRmwBits(const uint32_t addr, const uint32_t a, const uint32_t b, const ValWord< uint32_t > &valWord, const uint32_t expected)
Definition: PerfTester_static.cpp:644
PerfTester.hxx
uhal::Error
ErrorLevel Error
Definition: LogLevels.cpp:61
uhal::tests::c
ClientInterface * c
Definition: test_rawclient.cpp:94
uhal::Quote
_Quote< T > Quote(const T &aT)
Definition: log_inserters.quote.hxx:49
uhal::ClientInterface::rmw_bits
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...
Definition: ClientInterface.cpp:481
uhal::ClientInterface::rmw_sum
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...
Definition: ClientInterface.cpp:490
uhal::defs::INCREMENTAL
@ INCREMENTAL
Definition: definitions.hpp:53
uhal::tests::PerfTester::QueuedBlockWrite::check_values
virtual bool check_values()
Definition: PerfTester_static.cpp:629
uhal::tests::PerfTester::QueuedBlockRead::~QueuedBlockRead
~QueuedBlockRead()
Definition: PerfTester_static.cpp:595
uhal::tests::PerfTester::getRandomBlockSize
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=0...
Definition: PerfTester_static.cpp:60
uhal::Notice
NoticeLevel Notice
Definition: LogLevels.cpp:97
uhal::ClientInterface::uri
const std::string & uri() const
Return the url of the target for this client.
Definition: ClientInterface.cpp:138
uhal::ValWord< uint32_t >
uhal::tests::PerfTester::QueuedRmwSum::~QueuedRmwSum
~QueuedRmwSum()
Definition: PerfTester_static.cpp:677
uhal::fixed
@ fixed
Fixed width.
Definition: log_inserters.integer.hpp:57
uhal::ValVector::end
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:311
uhal::ClientInterface::write
ValHeader write(const uint32_t &aAddr, const uint32_t &aValue)
Write a single, unmasked word to a register.
Definition: ClientInterface.cpp:413
ClientFactory.hpp