45#include <boost/program_options.hpp>
46#include <boost/mem_fn.hpp>
61 const double uniformRandom =
static_cast<double> ( rand() ) / RAND_MAX;
63 const double inverseRandom = 0.5 * pow (
static_cast<double> ( ( maxSize+1 ) / 0.5 ) , uniformRandom );
64 uint32_t retVal =
static_cast<uint32_t
>( floor(inverseRandom) );
66 if ( retVal > maxSize )
69 " * uniformRandom=", uniformRandom,
"\n",
70 " * inverseRandom=", inverseRandom,
"\n",
71 "Correcting block size as temporary fix." );
86 for (
unsigned i = 0 ; i < size ; ++i )
88 buffer.push_back ( rand() + rand() );
98 std::ostringstream oss_details;
99 oss_details <<
"Single-register write-read @ 0x" << std::hex <<
addr << ( perTransactionDispatch ?
" (multiple dispatches)" :
" (single dispatch)" );
103 cout << oss_details.str() << endl;
106 const uint32_t
x = rand();
112 if ( perTransactionDispatch )
122 cout <<
"TEST FAILED: " << oss_details.str() <<
". Wrote value 0x" << std::hex <<
x <<
" but read-back 0x" <<
reg.
value() << std::dec << endl;
126 catch (
const std::exception& e )
128 cout <<
"TEST FAILED: " << oss_details.str() <<
". Exception of type '" <<
typeid ( e ).
name() <<
"' thrown ..." << endl << e.what() << endl;
139 std::ostringstream oss_details;
140 oss_details << depth <<
"-word write-read @ 0x" << std::hex <<
addr;
144 oss_details <<
" to 0x" <<
addr+depth-1 << std::dec;
147 oss_details << ( perTransactionDispatch ?
" (multiple dispatches)" :
" (single dispatch)" );
151 cout <<
"Running test: " << oss_details.str() << endl;
154 const U32Vec xx = getRandomBuffer ( depth );
160 if ( perTransactionDispatch )
167 std::vector<uint32_t>::const_iterator valVecIt = ram.
begin();
168 std::vector<uint32_t>::const_iterator xxIt =
xx.begin();
170 for ( ; valVecIt != ram.
end(); valVecIt++, xxIt++ )
172 if ( ( *valVecIt ) != ( *xxIt ) )
174 uint32_t reg_addr =
addr + ( valVecIt - ram.
begin() );
175 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;
180 log (
Notice(),
"TEST PASSED: ", oss_details.str() );
182 catch (
const std::exception& e )
184 cout <<
"TEST FAILED: " << oss_details.str() <<
"! EXCEPTION of type '" <<
typeid ( e ).
name() <<
"' thrown ..." << endl << e.what() << endl;
195 std::ostringstream oss_details;
196 oss_details <<
"RMW-bits @ 0x" << std::hex <<
addr << ( perTransactionDispatch ?
" (multiple dispatches)" :
" (single dispatch)" );
200 cout <<
"TESTING: " << oss_details.str() << endl;
203 const uint32_t x0 = rand();
205 const uint32_t a = rand();
207 const uint32_t b = rand();
209 const uint32_t x1 = ( x0 & a ) | b;
211 std::ostringstream oss_values;
213 oss_values <<
"Wrote value 0x" << std::hex << x0 <<
", then did RMW-bits with AND-term 0x" << a <<
", OR-term 0x" << b;
215 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 ) );
221 if ( perTransactionDispatch )
229 if ( ipbus2 ? ( x0 != reg_rmw.
value() ) : ( x1 != reg_rmw.
value() ) )
231 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;
238 if ( x1 != reg_read.
value() )
240 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;
244 catch (
const std::exception& e )
246 cout <<
"TEST FAILED: " << oss_values.str() <<
". Exception of type '" <<
typeid ( e ).
name() <<
"' thrown ..." << endl << e.what() << endl;
256 std::ostringstream oss_details;
257 oss_details <<
"RMW-sum @ 0x" << std::hex <<
addr << ( perTransactionDispatch ?
" (multiple dispatches)" :
" (single dispatch)" );
261 cout <<
"TESTING: " << oss_details.str() << endl;
264 const uint32_t x0 = rand();
266 const uint32_t a = rand();
268 const uint32_t x1 = x0 + a;
270 std::ostringstream oss_values;
272 oss_values <<
"Wrote value 0x" << std::hex << x0 <<
", then did RMW-sum with ADDEND 0x" << a;
274 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 ) );
280 if ( perTransactionDispatch )
288 if ( ipbus2 ? ( x0 != reg_sum.
value() ) : ( x1 != reg_sum.
value() ) )
290 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;
297 if ( x1 != reg_read.
value() )
299 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;
303 catch (
const std::exception& e )
305 cout <<
"TEST FAILED: " << oss_values.str() <<
". Exception of type '" <<
typeid ( e ).
name() <<
"' thrown ..." << endl << e.what() << endl;
313bool 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)
315 unsigned nrTestsFailed = 0;
316 unsigned nrTestsTotal = 0;
320 typedef std::vector<ClientInterface*>::const_iterator ClientIt_t;
321 for ( ClientIt_t clientIt = aClients.begin(); clientIt != aClients.end(); clientIt++ )
324 cout <<
"\n\nWRITE READ-BACK TESTS for device at '" <<
client->
uri() <<
"'" << endl;
325 vector<uint32_t> addr_vec;
326 addr_vec.push_back ( aBaseAddr );
327 addr_vec.push_back ( aBaseAddr + aDepth - 1 );
329 for (
unsigned i = 0; i < 2498; i++ )
331 addr_vec.push_back ( aBaseAddr + ( rand() % aDepth ) );
334 cout <<
"\n 1. Single-register write/read (" << addr_vec.size() * 2 <<
" tests)" << endl;
336 for (
unsigned i = 0; i < addr_vec.size(); i++ )
340 if ( ! validation_test_single_write_read ( *
client, addr_vec.at ( i ),
true, aVerbose ) )
348 if ( ! validation_test_single_write_read ( *
client, addr_vec.at ( i ),
false || aDispatchEachIteration, aVerbose ) )
355 cout <<
"\n 2. Block write/read (" << addr_vec.size() * 2 <<
" tests)" << endl;
357 for (
unsigned i = 0; i < addr_vec.size(); i++ )
359 uint32_t
addr = addr_vec.at ( i );
360 uint32_t max_depth = aBaseAddr + aDepth -
addr;
361 uint32_t depth = rand() % ( max_depth + 1 );
365 if ( ! validation_test_block_write_read ( *
client,
addr, depth,
true, aVerbose ) )
373 if ( ! validation_test_block_write_read ( *
client,
addr, depth,
false || aDispatchEachIteration, aVerbose ) )
380 cout <<
"\n 3. Testing RMW-bits (write, RMWbits, read; " << addr_vec.size() * 2 <<
" tests)" << endl;
382 for ( std::vector<uint32_t>::const_iterator it = addr_vec.begin(); it != addr_vec.end(); it++ )
386 if ( ! validation_test_write_rmwbits_read ( *
client, *it,
true, aVerbose ) )
394 if ( ! validation_test_write_rmwbits_read ( *
client, *it,
false || aDispatchEachIteration, aVerbose ) )
401 cout <<
"\n 4. Testing RMW-sum (write, RMW-sum, read; " << addr_vec.size() * 2 <<
" tests)" << endl;
403 for ( std::vector<uint32_t>::const_iterator it = addr_vec.begin(); it != addr_vec.end(); it++ )
407 if ( ! validation_test_write_rmwsum_read ( *
client, *it,
true, aVerbose ) )
415 if ( ! validation_test_write_rmwsum_read ( *
client, *it,
false || aDispatchEachIteration, aVerbose ) )
423 if ( nrTestsFailed == 0 )
425 cout <<
"\n\nBASIC TESTS SUMMARY: All " << nrTestsTotal <<
" tests passed!" << endl << endl << endl;
429 cout <<
"\n\nBASIC TESTS SUMMARY: Total of " << nrTestsTotal <<
" tests run -- " << nrTestsFailed <<
" tests FAILED , " << ( nrTestsTotal - nrTestsFailed ) <<
" tests PASSED" << endl;
435 for ( ClientIt_t clientIt = aClients.begin(); clientIt != aClients.end(); clientIt++ )
438 cout <<
"\nSOAK TEST to device '" <<
client->
uri() <<
"'\n Random sequence of " << aNrIterations <<
" transactions will be sent to hardware" << endl << endl;
441 size_t found =
client->
uri().find (
"-1.3" );
443 if ( found!=std::string::npos )
451 if ( found!=std::string::npos )
457 log (
Error() ,
"Cannot deduce protocol from URI " ,
Quote (
client->
uri() ),
" Exiting before performing soak test." );
463 std::vector< uint32_t > registers ( aDepth , 0x00000000 );
468 uint32_t tempUInt1, tempUInt2;
469 vector< std::shared_ptr<QueuedTransaction> > queuedTransactions;
470 uint32_t nrQueuedWords = 0;
472 for (
unsigned i = 1; i <= aNrIterations; i++ )
474 type = ( rand() % 4 );
475 addr = aBaseAddr + ( rand() % aDepth );
481 blockSize = getRandomBlockSize ( aBaseAddr + aDepth -
addr );
486 nrQueuedWords += blockSize;
491 blockSize = getRandomBlockSize ( aBaseAddr + aDepth -
addr );
494 vector<uint32_t> randomData = getRandomBuffer ( blockSize );
496 std::copy ( randomData.begin(), randomData.end(), registers.begin() + (
addr - aBaseAddr ) );
497 queuedTransactions.push_back ( std::shared_ptr<QueuedTransaction> (
new QueuedBlockWrite (
addr, blockSize, result ) ) );
498 nrQueuedWords += blockSize;
506 vector<uint32_t>::iterator regIt = registers.begin() + (
addr - aBaseAddr );
508 if ( ipbus_vsn == 1 )
515 queuedTransactions.push_back ( std::shared_ptr<QueuedTransaction> (
new QueuedRmwBits (
addr, tempUInt1, tempUInt2, result, *regIt ) ) );
518 if ( ipbus_vsn == 2 )
530 vector<uint32_t>::iterator regIt = registers.begin() + (
addr - aBaseAddr );
532 if ( ipbus_vsn == 1 )
538 queuedTransactions.push_back ( std::shared_ptr<QueuedTransaction> (
new QueuedRmwSum (
addr, tempUInt1, result, *regIt ) ) );
541 if ( ipbus_vsn == 2 )
550 if ( aDispatchEachIteration || ( nrQueuedWords > 20000000 ) || ( i == aNrIterations ) )
552 log (
Notice(),
"Soak test - issuing dispatch" );
554 log (
Notice(),
"Soak test - issuing empty dispatch" );
557 for ( vector< std::shared_ptr<QueuedTransaction> >::const_iterator it = queuedTransactions.begin(); it != queuedTransactions.end(); it++ )
559 if ( ! ( *it )->check_values() )
561 cout <<
"ERROR OCCURED IN SOAK TEST to '" <<
client->
uri() <<
"' - after " << i <<
" successful transactions" << endl;
566 queuedTransactions.clear();
571 std::cout <<
"No errors after " << i <<
" transactions -- " << setiosflags ( ios::fixed ) << setprecision ( 1 ) << ( 100.0 * i ) / aNrIterations <<
"% done\r";
578 cout << endl <<
"Reached end of soak testing successfully!" << endl;
586 m_depth ( valVector.size() ),
588 m_valVector ( valVector )
598 std::vector<uint32_t>::const_iterator valVecIt = m_valVector.begin();
599 std::vector<uint32_t>::const_iterator expdIt = m_expected.begin();
601 for ( ; valVecIt != m_valVector.end(); valVecIt++, expdIt++ )
603 if ( ( *valVecIt ) != ( *expdIt ) )
605 uint32_t
addr = m_addr + ( valVecIt - m_valVector.begin() );
606 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>() ) );
611 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>() ) );
621 m_valHeader ( valHeader )
629 if ( ! m_valHeader.valid() )
635 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>() ) );
646 m_valWord ( valWord ),
647 m_expected ( expected )
655 if ( m_valWord.value() != m_expected )
657 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>() ) );
671 m_valWord ( valWord ),
672 m_expected ( expected )
680 if ( m_valWord.value() != m_expected )
682 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<>() ) );
An abstract base class for defining the interface to the various IPbus clients as well as providing t...
ValHeader write(const uint32_t &aAddr, const uint32_t &aValue)
Write a single, unmasked word to a register.
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 dispatch()
Method to dispatch all queued transactions, and wait until all corresponding responses have been rece...
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...
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...
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.
ValWord< uint32_t > read(const uint32_t &aAddr)
Read a single, unmasked, unsigned word.
const std::string & uri() const
Return the url of the target for this client.
A class which wraps a block of data and marks whether or not it is valid.
const_iterator begin() const
If the memory has previously been marked as valid, return a const iterator to the beginning of the un...
void push_back(const T &aValue)
If the memory has not previously been marked as valid, add an entry to the end of it.
const_iterator end() const
If the memory has previously been marked as valid, return a const iterator to the end (one past last ...
A class which wraps a single word of data and marks whether or not it is valid.
T value() const
Return the value of the validated memory with check on validity.
virtual bool check_values()
std::vector< uint32_t > m_expected
QueuedBlockRead(const uint32_t addr, const ValVector< uint32_t > &valVector, std::vector< uint32_t >::const_iterator expectedValuesIt)
virtual bool check_values()
QueuedBlockWrite(const uint32_t addr, const uint32_t depth, const ValHeader &valHeader)
virtual bool check_values()
QueuedRmwBits(const uint32_t addr, const uint32_t a, const uint32_t b, const ValWord< uint32_t > &valWord, const uint32_t expected)
QueuedRmwSum(const uint32_t addr, const uint32_t a, const ValWord< uint32_t > &valWord, const uint32_t expected)
virtual bool check_values()
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.
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.
std::vector< U32 > U32Vec
A vector of unsigned 32-bit words.
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.
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.
static U32Vec getRandomBuffer(unsigned size)
Returns a buffer of random numbers.
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...
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)
std::vector< uint32_t > xx
_Quote< T > Quote(const T &aT)
_Integer< T, IntFmt<> > Integer(const T &aT)
Forward declare a function which creates an instance of the ultra-lightweight wrapper from an integer...
void log(FatalLevel &aFatal, const T0 &aArg0)
Function to add a log entry at Fatal level.
Annotation for function names.
Empty struct which acts as a dummy variable for passing the formatting information around.