μHAL (v2.6.5)
Part of the IPbus software repository
PerfTester.cxx
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 namespace po = boost::program_options;
56 using namespace std;
57 
58 
59 // PUBLIC METHODS
60 
62  m_testDescMap(),
63  m_testFuncMap(),
64  m_deviceURIs(),
65  m_clients(),
66  m_testName ( "BandwidthRx" ),
67  m_iterations ( 1000 ),
68  m_baseAddrStr ( "0x0" ),
69  m_baseAddr ( 0 ),
70  m_bandwidthTestDepth ( 0 ),
71  m_verbose ( false ),
72  m_perIterationDispatch ( false ),
73  m_includeConnect ( false )
74 {
75  // ***** DECLARE TESTS HERE - descriptions should not be longer than a shortish line. *****:
76  // Receive bandwidth test
78  m_testDescMap["BandwidthRx"] = "Block read test (default depth = 340) to find the receive bandwidth.";
79  // Transmit bandwidth test
81  m_testDescMap["BandwidthTx"] = "Block write test (default depth = 340) to find the transmit bandwidth.";
82  // Validation test
84  m_testDescMap["Validation"] = "For validating downstream subsystems, such as the Control Hub or the IPbus firmware.";
85  // Sandbox test
86  m_testFuncMap["Sandbox"] = &PerfTester::sandbox;
87  m_testDescMap["Sandbox"] = "A user-definable test - modify the sandbox() function to whatever you wish.";
88  // ***** END DECLARATION OF TESTS *****
89  // Initialise random number generator
90  srand ( time ( NULL ) );
91 }
92 
93 
94 int uhal::tests::PerfTester::run ( int argc, char* argv[] )
95 {
96  try
97  {
98  // This just defines and parses the command line parameters that are allowed.
99  po::options_description argDescriptions ( "Allowed options" );
100  argDescriptions.add_options()
101  ( "help,h", "Produce help message" )
102  ( "list,l", "List the names of the different tests that can be performed." )
103  ( "verbose,v", "Make the output more verbose." )
104  ( "test,t", po::value<string> ( &m_testName )->default_value ( "BandwidthRx" ), "Name of the test to be performed." )
105  ( "iterations,i", po::value<uint64_t> ( &m_iterations )->default_value ( 1000 ), "Number of test iterations to run." )
106  ( "devices,d", po::value<StringVec> ( &m_deviceURIs )->multitoken(), "List of device connection URIs, e.g. chtcp-1.3://..., etc" )
107  ( "baseAddr,b", po::value<string> ( &m_baseAddrStr )->default_value ( "0x0" ), "Base address (in hex) of the test location on the target device(s)." )
108  ( "bandwidthTestDepth,w", po::value<boost::uint32_t> ( &m_bandwidthTestDepth )->default_value ( 340 ), "Depth of read/write used in bandwidth tests." )
109  ( "perIterationDispatch,p", "Force a network dispatch every test iteration instead of the default single dispatch call at the end." )
110  ( "includeConnect,c", "Include connect time in reported bandwidths and latencies" );
111  po::variables_map argMap;
112  po::store ( po::parse_command_line ( argc, argv, argDescriptions ), argMap );
113  po::notify ( argMap );
114  // Convert the hexadecimal base addr value into an actual number.
115  // This is just a workaround for boost:program_options not understanding hex input
116  istringstream convert ( m_baseAddrStr );
117  convert >> std::hex >> m_baseAddr;
118 
119  if ( convert.fail() )
120  {
121  cerr << "The specified base address was not valid hexadecimal!" << endl;
122  return 10;
123  }
124 
125  // Display help info and exit
126  if ( argc < 2 || argMap.count ( "help" ) )
127  {
128  ostringstream oss;
129  oss << argDescriptions;
130  outputHelpText ( oss.str() );
131  return 20;
132  }
133 
134  if ( argMap.count ( "list" ) )
135  {
137  return 30;
138  }
139 
140  if ( argMap.count ( "verbose" ) )
141  {
142  m_verbose = true;
143  }
144 
145  if ( argMap.count ( "perIterationDispatch" ) )
146  {
147  m_perIterationDispatch = true;
148  }
149 
150  if ( argMap.count ( "includeConnect" ) )
151  {
152  m_includeConnect = true;
153  }
154 
155  if ( badInput() )
156  {
157  return 40; // Report bad user input and exit if necessary.
158  }
159 
160  outputUserChoices(); // Echo back to the user the settings they have selected.
161  buildClients(); // Build the clients from the device URIs provided by the user
162  ( this->*m_testFuncMap.find ( m_testName )->second ) (); // Calls the test function, based on the test name.
163  }
164  catch ( std::exception& e )
165  {
166  cerr << "Error - exception thrown ..." << endl << e.what() << endl;
167  return 50;
168  }
169  catch ( ... )
170  {
171  cerr << "Caught exception of unknown type!" << endl;
172  return 60;
173  }
174 
175  return 0; // The program ran successfully (even if the test didn't...)
176 }
177 
178 
179 // PRIVATE METHODS - Test infrastructure
180 
181 void uhal::tests::PerfTester::outputHelpText ( const string& argDescriptions ) const
182 {
183  cout << "\n -----------------------------------------\n"
184  " PerfTester.exe - IPbus Performance Tester\n"
185  " -----------------------------------------\n\n"
186  " Generate custom IPbus/uHAL tests from the command line\n\n"
187  << argDescriptions
188  << "Usage examples:\n\n"
189  " PerfTester.exe -t BandwidthTx -b 0xf0 -d ipbusudp-1.3://localhost:50001 ipbusudp-1.3://localhost:50002\n"
190  " PerfTester.exe -t BandwidthTx -w 5 -i 100 chtcp-1.3://localhost:10203?target=127.0.0.1:50001" << endl;
192 }
193 
194 
196 {
197  cout << "\nNames and descriptions of available tests:\n" << endl;
198  cout << " " << setw ( 16 ) << left << "Name" << " " << "Description" << endl;
199  cout << " " << setw ( 16 ) << left << "----" << " " << "-----------" << endl;
200  TestDescMap::const_iterator iTest = m_testDescMap.begin(), iTestEnd = m_testDescMap.end();
201 
202  for ( ; iTest != iTestEnd ; ++iTest )
203  {
204  cout << " " << setw ( 16 ) << left << iTest->first << " " << iTest->second << endl;
205  }
206 
207  cout << endl;
208 }
209 
210 
212 {
213  if ( m_deviceURIs.empty() )
214  {
215  cerr << "You must specify at least one device connection URI by using the -d option!" << endl;
216  return true;
217  }
218 
219  if ( m_testFuncMap.find ( m_testName ) == m_testFuncMap.end() )
220  {
221  cerr << "The test name '" << m_testName
222  << "' is not one of the available tests!\nDo 'PerfTester -l' to see names of available tests!" << endl;
223  return true;
224  }
225 
226  return false;
227 }
228 
229 
231 {
232  cout << "Test settings:\n" << endl
233  << " Test Name --------------> " << m_testName << endl
234  << " Test register addr -----> " << std::hex << showbase << m_baseAddr << noshowbase << std::dec << endl
235  << " Test iterations --------> " << m_iterations << endl
236  << " Per-iteration dispatch --> " << ( m_perIterationDispatch?"Yes":"No" ) << endl
237  << " Device URIs:" << endl;
238  StringVec::const_iterator iDevice = m_deviceURIs.begin(), iDeviceEnd = m_deviceURIs.end();
239 
240  for ( ; iDevice != iDeviceEnd ; ++iDevice )
241  {
242  cout << " " << *iDevice << endl;
243  }
244 
245  cout << "\nRunning test now...\n" << endl;
246 }
247 
248 
250 {
251  if ( m_verbose )
252  {
253  setLogLevelTo ( Debug() );
254  cout << "Building device clients..." << endl;
255  }
256  else
257  {
258  setLogLevelTo ( Warning() );
259  }
260 
261  m_clients.reserve ( m_deviceURIs.size() );
262 
263  for ( unsigned int iURI = 0 ; iURI < m_deviceURIs.size() ; ++iURI )
264  {
265  m_clients.push_back ( ClientFactory::getInstance().getClient ( "MyDevice", m_deviceURIs.at ( iURI ) ) );
266  }
267 
268  if ( m_verbose )
269  {
270  cout << "Device clients built successfully!" << endl;
271  }
272 }
273 
274 
275 void uhal::tests::PerfTester::outputStandardResults ( double totalSeconds ) const
276 {
277  string underline;
278  underline.assign ( m_testName.size() + 14, '-' );
279  cout << m_testName << " Test Results:\n"
280  << underline << "\n\n"
281  << "Number of IPbus hosts in test = " << m_deviceURIs.size() << "\n"
282  << "Total test iterations = " << m_iterations << "\n"
283  << "Total time taken = " << totalSeconds << " s\n"
284  << "Test iteration frequency = " << m_iterations/totalSeconds << " Hz" << endl;
285 }
286 
287 
288 bool uhal::tests::PerfTester::buffersEqual ( const U32Vec& writeBuffer, const U32ValVec& readBuffer ) const
289 {
290  return std::equal ( readBuffer.begin(), readBuffer.end(), writeBuffer.begin() );
291 }
292 
293 
294 // PRIVATE MEMBER FUNCTIONS - IPbus test functions that users can run
295 
297 {
298  if ( ! m_includeConnect )
299  {
300  BOOST_FOREACH ( ClientPtr& iClient, m_clients )
301  {
302  iClient->readBlock ( m_baseAddr, 1, defs::NON_INCREMENTAL );
303  iClient->dispatch();
304  }
305  }
306 
307  std::vector<ClientInterface*> lClients;
308  BOOST_FOREACH ( ClientPtr& iClient, m_clients )
309  {
310  lClients.push_back( &*iClient );
311  }
312 
314  double totalPayloadKB = m_deviceURIs.size() * m_iterations * m_bandwidthTestDepth * 4. / 1024.;
315  double dataRateKB_s = totalPayloadKB/totalSeconds;
316  outputStandardResults ( totalSeconds );
317  cout << "Read depth used each iteration = " << m_bandwidthTestDepth << " 32-bit words\n"
318  << "Total IPbus payload received = " << totalPayloadKB << " KB\n"
319  << "Average read bandwidth = " << dataRateKB_s << " KB/s" << endl;
320 }
321 
322 
324 {
325  if ( ! m_includeConnect )
326  {
327  BOOST_FOREACH ( ClientPtr& iClient, m_clients )
328  {
329  iClient->writeBlock ( m_baseAddr, std::vector<uint32_t>(1,0x0), defs::NON_INCREMENTAL );
330  iClient->dispatch();
331  }
332  }
333 
334  std::vector<ClientInterface*> lClients;
335  BOOST_FOREACH ( ClientPtr& iClient, m_clients )
336  {
337  lClients.push_back( &*iClient );
338  }
339 
341  double totalPayloadKB = m_deviceURIs.size() * m_iterations * m_bandwidthTestDepth * 4. / 1024.;
342  double dataRateKB_s = totalPayloadKB/totalSeconds;
343  outputStandardResults ( totalSeconds );
344  cout << "Write depth used each iteration = " << m_bandwidthTestDepth << " 32-bit words\n"
345  << "Total IPbus payload sent = " << totalPayloadKB << " KB\n"
346  << "Average write bandwidth = " << dataRateKB_s << " KB/s" << endl;
347 }
348 
349 
351 {
352  std::vector<ClientInterface*> lClients;
353  for(ClientVec::iterator lIt = m_clients.begin(); lIt != m_clients.end(); lIt++)
354  lClients.push_back(&**lIt);
355 
357  std::exit( 1 );
358 }
359 
360 
361 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)
362 {
363  unsigned nrTestsFailed = 0;
364  unsigned nrTestsTotal = 0;
365 
366  // ---> A) Write read-back tests
367  //
368  typedef std::vector<ClientInterface*>::const_iterator ClientIt_t;
369  for ( ClientIt_t clientIt = aClients.begin(); clientIt != aClients.end(); clientIt++ )
370  {
371  ClientInterface* client = *clientIt;
372  cout << "\n\nWRITE READ-BACK TESTS for device at '" << client->uri() << "'" << endl;
373  vector<uint32_t> addr_vec;
374  addr_vec.push_back ( aBaseAddr );
375  addr_vec.push_back ( aBaseAddr + aDepth - 1 );
376 
377  for ( unsigned i = 0; i < 2498; i++ )
378  {
379  addr_vec.push_back ( aBaseAddr + ( rand() % aDepth ) );
380  }
381 
382  cout << "\n 1. Single-register write/read (" << addr_vec.size() * 2 << " tests)" << endl;
383 
384  for ( unsigned i = 0; i < addr_vec.size(); i++ )
385  {
386  nrTestsTotal++;
387 
388  if ( ! validation_test_single_write_read ( *client, addr_vec.at ( i ), true, aVerbose ) )
389  {
390  nrTestsFailed++;
391  }
392 
393  nrTestsTotal++;
394 
395  if ( ! validation_test_single_write_read ( *client, addr_vec.at ( i ), false || aDispatchEachIteration, aVerbose ) )
396  {
397  nrTestsFailed++;
398  }
399  }
400 
401  cout << "\n 2. Block write/read (" << addr_vec.size() * 2 << " tests)" << endl;
402 
403  for ( unsigned i = 0; i < addr_vec.size(); i++ )
404  {
405  uint32_t addr = addr_vec.at ( i );
406  uint32_t max_depth = aBaseAddr + aDepth - addr;
407  uint32_t depth = rand() % ( max_depth + 1 );
408 
409  nrTestsTotal++;
410 
411  if ( ! validation_test_block_write_read ( *client, addr, depth, true, aVerbose ) )
412  {
413  nrTestsFailed++;
414  }
415 
416  nrTestsTotal++;
417 
418  if ( ! validation_test_block_write_read ( *client, addr, depth, false || aDispatchEachIteration, aVerbose ) )
419  {
420  nrTestsFailed++;
421  }
422  }
423 
424  cout << "\n 3. Testing RMW-bits (write, RMWbits, read; " << addr_vec.size() * 2 << " tests)" << endl;
425 
426  for ( std::vector<uint32_t>::const_iterator it = addr_vec.begin(); it != addr_vec.end(); it++ )
427  {
428  nrTestsTotal++;
429 
430  if ( ! validation_test_write_rmwbits_read ( *client, *it, true, aVerbose ) )
431  {
432  nrTestsFailed++;
433  }
434 
435  nrTestsTotal++;
436 
437  if ( ! validation_test_write_rmwbits_read ( *client, *it, false || aDispatchEachIteration, aVerbose ) )
438  {
439  nrTestsFailed++;
440  }
441  }
442 
443  cout << "\n 4. Testing RMW-sum (write, RMW-sum, read; " << addr_vec.size() * 2 << " tests)" << endl;
444 
445  for ( std::vector<uint32_t>::const_iterator it = addr_vec.begin(); it != addr_vec.end(); it++ )
446  {
447  nrTestsTotal++;
448 
449  if ( ! validation_test_write_rmwsum_read ( *client, *it, true, aVerbose ) )
450  {
451  nrTestsFailed++;
452  }
453 
454  nrTestsTotal++;
455 
456  if ( ! validation_test_write_rmwsum_read ( *client, *it, false || aDispatchEachIteration, aVerbose ) )
457  {
458  nrTestsFailed++;
459  }
460  }
461  }//end: for, m_clients
462 
463  if ( nrTestsFailed == 0 )
464  {
465  cout << "\n\nBASIC TESTS SUMMARY: All " << nrTestsTotal << " tests passed!" << endl << endl << endl;
466  }
467  else
468  {
469  cout << "\n\nBASIC TESTS SUMMARY: Total of " << nrTestsTotal << " tests run -- " << nrTestsFailed << " tests FAILED , " << ( nrTestsTotal - nrTestsFailed ) << " tests PASSED" << endl;
470  return false;
471  }
472 
473  // ---> B) SOAK TESTs
474  //
475  for ( ClientIt_t clientIt = aClients.begin(); clientIt != aClients.end(); clientIt++ )
476  {
477  ClientInterface* client = *clientIt;
478  cout << "\nSOAK TEST to device '" << client->uri() << "'\n Random sequence of " << aNrIterations << " transactions will be sent to hardware" << endl << endl;
479  // Setup
480  uint32_t ipbus_vsn;
481  size_t found = client->uri().find ( "-1.3" );
482 
483  if ( found!=std::string::npos )
484  {
485  ipbus_vsn = 1;
486  }
487  else
488  {
489  found = client->uri().find ( "-2.0" );
490 
491  if ( found!=std::string::npos )
492  {
493  ipbus_vsn = 2;
494  }
495  else
496  {
497  log ( Error() , "Cannot deduce protocol from URI " , Quote ( client->uri() ), " Exiting before performing soak test." );
498  return false;
499  }
500  }
501 
502  // Initialise registers to 0x0
503  std::vector< uint32_t > registers ( aDepth , 0x00000000 );
504  client->writeBlock ( aBaseAddr, registers );
505  client->dispatch();
506  // ACTUAL MEAT OF SOAK TEST
507  uint32_t type, addr, blockSize;
508  uint32_t tempUInt1, tempUInt2;
509  vector< boost::shared_ptr<QueuedTransaction> > queuedTransactions;
510  uint32_t nrQueuedWords = 0;
511 
512  for ( unsigned i = 1; i <= aNrIterations; i++ )
513  {
514  type = ( rand() % 4 );
515  addr = aBaseAddr + ( rand() % aDepth );
516 
517  switch ( type )
518  {
519  case 0: // read
520  {
521  blockSize = getRandomBlockSize ( aBaseAddr + aDepth - addr );
522  log ( Notice(), "Soak test - queueing: ", Integer ( blockSize ), "-word read at ", Integer ( addr, IntFmt<hex,fixed>() ) );
523 
524  ValVector<uint32_t> result = client->readBlock ( addr, blockSize, defs::INCREMENTAL );
525  queuedTransactions.push_back ( boost::shared_ptr<QueuedTransaction> ( new QueuedBlockRead ( addr, result, registers.begin() + ( addr - aBaseAddr ) ) ) );
526  nrQueuedWords += blockSize;
527  break;
528  }
529  case 1: // write
530  {
531  blockSize = getRandomBlockSize ( aBaseAddr + aDepth - addr );
532  log ( Notice(), "Soak test - queueing: ", Integer ( blockSize ), "-word write at ", Integer ( addr, IntFmt<hex,fixed>() ) );
533 
534  vector<uint32_t> randomData = getRandomBuffer ( blockSize );
535  ValHeader result = client->writeBlock ( addr, randomData, defs::INCREMENTAL );
536  std::copy ( randomData.begin(), randomData.end(), registers.begin() + ( addr - aBaseAddr ) );
537  queuedTransactions.push_back ( boost::shared_ptr<QueuedTransaction> ( new QueuedBlockWrite ( addr, blockSize, result ) ) );
538  nrQueuedWords += blockSize;
539  break;
540  }
541  case 2: // RMW-bits
542  {
543  log ( Notice(), "Soak test - queueing: RMW-bits at ", Integer ( addr, IntFmt<hex,fixed>() ) );
544  tempUInt1 = rand();
545  tempUInt2 = rand();
546  vector<uint32_t>::iterator regIt = registers.begin() + ( addr - aBaseAddr );
547 
548  if ( ipbus_vsn == 1 )
549  {
550  *regIt &= tempUInt1;
551  *regIt |= tempUInt2;
552  }
553 
554  ValWord<uint32_t> result = client->rmw_bits ( addr, tempUInt1, tempUInt2 );
555  queuedTransactions.push_back ( boost::shared_ptr<QueuedTransaction> ( new QueuedRmwBits ( addr, tempUInt1, tempUInt2, result, *regIt ) ) );
556  nrQueuedWords += 1;
557 
558  if ( ipbus_vsn == 2 )
559  {
560  *regIt &= tempUInt1;
561  *regIt |= tempUInt2;
562  }
563 
564  break;
565  }
566  case 3: // RMW-sum
567  {
568  log ( Notice(), "Soak test - queueing: RMW-sum at ", Integer ( addr, IntFmt<hex,fixed>() ) );
569  tempUInt1 = rand();
570  vector<uint32_t>::iterator regIt = registers.begin() + ( addr - aBaseAddr );
571 
572  if ( ipbus_vsn == 1 )
573  {
574  *regIt += tempUInt1;
575  }
576 
577  ValWord<uint32_t> result = client->rmw_sum ( addr, tempUInt1 );
578  queuedTransactions.push_back ( boost::shared_ptr<QueuedTransaction> ( new QueuedRmwSum ( addr, tempUInt1, result, *regIt ) ) );
579  nrQueuedWords += 1;
580 
581  if ( ipbus_vsn == 2 )
582  {
583  *regIt += tempUInt1;
584  }
585 
586  break;
587  }
588  }
589 
590  if ( aDispatchEachIteration || ( nrQueuedWords > 20000000 ) || ( i == aNrIterations ) )
591  {
592  log ( Notice(), "Soak test - issuing dispatch" );
593  client->dispatch();
594  log ( Notice(), "Soak test - issuing empty dispatch" );
595  client->dispatch();
596 
597  for ( vector< boost::shared_ptr<QueuedTransaction> >::const_iterator it = queuedTransactions.begin(); it != queuedTransactions.end(); it++ )
598  {
599  if ( ! ( *it )->check_values() )
600  {
601  cout << "ERROR OCCURED IN SOAK TEST to '" << client->uri() << "' - after " << i << " successful transactions" << endl;
602  return false;
603  }
604  }
605 
606  queuedTransactions.clear();
607  nrQueuedWords = 0;
608 
609  if ( ! aVerbose )
610  {
611  std::cout << "No errors after " << i << " transactions -- " << setiosflags ( ios::fixed ) << setprecision ( 1 ) << ( 100.0 * i ) / aNrIterations << "% done\r";
612  std::cout.flush();
613  }
614  }
615  }
616  }//end: for, aClients
617 
618  cout << endl << "Reached end of soak testing successfully!" << endl;
619  return true;
620 }
621 
622 
624 {
625  try
626  {
627  BOOST_FOREACH ( ClientPtr& iClient, m_clients )
628  {
629  // *** Your code here ***
630  // For example:
631  ValWord<uint32_t> result = iClient->read ( m_baseAddr );
632  iClient->dispatch();
633  cout << "Read: " << std::hex << result.value() << " from address: " << m_baseAddr << std::dec << endl;
634  }
635  }
636  catch ( const std::exception& e )
637  {
638  cout << e.what() << endl;
639  }
640 }
641 
642 // END OF PerfTester MEMBER FUNCTIONS
643 
644 
645 
646 // The main() func...
647 int main ( int argc, char* argv[] )
648 {
649  uhal::tests::PerfTester perfTester;
650  return perfTester.run ( argc, argv );
651 }
NoticeLevel Notice
Definition: LogLevels.cpp:96
void outputHelpText(const std::string &argDescriptions) const
Outputs the standard help text to screen.
Definition: PerfTester.cxx:181
void dispatch()
Method to dispatch all IPbus packets which are in the queue of IPbusPacketInfo&#39;s and wait until all q...
std::string m_testName
Holds the test name.
Definition: PerfTester.hxx:113
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
double measureReadLatency(ClientInterface &aClient, uint32_t aBaseAddr, uint32_t aDepth, size_t aNrIterations, bool aDispatchEachIteration, bool aVerbose)
Definition: tools.cpp:67
std::string m_baseAddrStr
Base addr of reg/ram the test will use. Use a string as workaround for hex input via boost::program_o...
Definition: PerfTester.hxx:115
static ClientFactory & getInstance()
Static method to retrieve the single instance of the class.
ClientVec m_clients
Vector of low-level uHAL clients.
Definition: PerfTester.hxx:112
bool m_perIterationDispatch
Perform a network dispatch every iteration flag.
Definition: PerfTester.hxx:119
TestDescMap m_testDescMap
Maps test name to test description.
Definition: PerfTester.hxx:109
void validationTest()
Historic basic firmware/software validation test.
Definition: PerfTester.cxx:350
int main(int argc, char *argv[])
Definition: PerfTester.cxx:647
bool badInput() const
Returns true if the user has entered bad command line arguments.
Definition: PerfTester.cxx:211
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
std::vector< U32 > U32Vec
A vector of unsigned 32-bit words.
Definition: PerfTester.hxx:83
double measureWriteLatency(ClientInterface &aClient, uint32_t aBaseAddr, uint32_t aDepth, size_t aNrIterations, bool aDispatchEachIteration, bool aVerbose)
Definition: tools.cpp:111
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
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
PerfTester()
Constructor - takes no arguments, does nothing.
Definition: PerfTester.cxx: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)
uint64_t m_iterations
Number of test iterations.
Definition: PerfTester.hxx:114
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=...
void outputTestDescriptionsList() const
Outputs the test names and descriptions to screen.
Definition: PerfTester.cxx:195
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.
void sandbox()
An area for a user-definable test.
Definition: PerfTester.cxx:623
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.
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.
void bandwidthTxTest()
Write bandwidth test.
Definition: PerfTester.cxx:323
int run(int argc, char *argv[])
Pass in the two command-line parameter variables, this will define the test that then gets run...
Definition: PerfTester.cxx:94
An abstract base class for defining the interface to the various IPbus clients as well as providing t...
TestFuncMap m_testFuncMap
Maps test name to test function.
Definition: PerfTester.hxx:110
bool m_includeConnect
Include (e.g. TCP) connect time in reported bandwidth/latency.
Definition: PerfTester.hxx:120
bool m_verbose
Verbosity true/false flag.
Definition: PerfTester.hxx:118
Hexadecimal.
DebugLevel Debug
Definition: LogLevels.cpp:133
void buildClients()
Constructs and sets up the appropriate IPbusClient for use in the test.
Definition: PerfTester.cxx:249
A class which wraps a single word of data and marks whether or not it is valid.
Definition: ValMem.hpp:156
void outputUserChoices() const
Outputs the user&#39;s choices to screen.
Definition: PerfTester.cxx:230
void bandwidthRxTest()
Read bandwidth test.
Definition: PerfTester.cxx:296
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...
boost::uint32_t m_baseAddr
The m_baseAddrStr as converted into an actual unsigned value.
Definition: PerfTester.hxx:116
boost::uint32_t m_bandwidthTestDepth
The depth of read/write used in bandwidth tests.
Definition: PerfTester.hxx:117
bool buffersEqual(const U32Vec &writeBuffer, const U32ValVec &readBuffer) const
Compares a write buffer with one or more ValVec read responses.
Definition: PerfTester.cxx:288
void outputStandardResults(double totalSeconds) const
Outputs a standard result set to screen - provide it with the number of seconds the test took...
Definition: PerfTester.cxx:275
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...
StringVec m_deviceURIs
Vector of individual connection URI strings.
Definition: PerfTester.hxx:111