45 #include <boost/program_options.hpp> 46 #include <boost/bind.hpp> 47 #include <boost/foreach.hpp> 48 #include <boost/mem_fn.hpp> 63 const double uniformRandom =
static_cast<double> ( rand() ) / RAND_MAX;
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) );
68 if ( retVal > maxSize )
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." );
85 buffer.reserve ( size );
88 for (
unsigned i = 0 ; i < size ; ++i )
90 buffer.push_back ( rand() + rand() );
100 std::ostringstream oss_details;
101 oss_details <<
"Single-register write-read @ 0x" <<
std::hex << addr << ( perTransactionDispatch ?
" (multiple dispatches)" :
" (single dispatch)" );
105 cout << oss_details.str() << endl;
108 const uint32_t
x = rand();
114 if ( perTransactionDispatch )
122 if ( x != reg.
value() )
124 cout <<
"TEST FAILED: " << oss_details.str() <<
". Wrote value 0x" <<
std::hex << x <<
" but read-back 0x" << reg.
value() <<
std::dec << endl;
128 catch (
const std::exception& e )
130 cout <<
"TEST FAILED: " << oss_details.str() <<
". Exception of type '" <<
typeid ( e ).
name() <<
"' thrown ..." << endl << e.what() << endl;
141 std::ostringstream oss_details;
142 oss_details << depth <<
"-word write-read @ 0x" <<
std::hex <<
addr;
146 oss_details <<
" to 0x" << addr+depth-1 <<
std::dec;
149 oss_details << ( perTransactionDispatch ?
" (multiple dispatches)" :
" (single dispatch)" );
153 cout <<
"Running test: " << oss_details.str() << endl;
156 const U32Vec xx = getRandomBuffer ( depth );
162 if ( perTransactionDispatch )
169 std::vector<uint32_t>::const_iterator valVecIt = ram.
begin();
170 std::vector<uint32_t>::const_iterator xxIt = xx.begin();
172 for ( ; valVecIt != ram.
end(); valVecIt++, xxIt++ )
174 if ( ( *valVecIt ) != ( *xxIt ) )
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;
182 log (
Notice(),
"TEST PASSED: ", oss_details.str() );
184 catch (
const std::exception& e )
186 cout <<
"TEST FAILED: " << oss_details.str() <<
"! EXCEPTION of type '" <<
typeid ( e ).
name() <<
"' thrown ..." << endl << e.what() << endl;
197 std::ostringstream oss_details;
198 oss_details <<
"RMW-bits @ 0x" <<
std::hex << addr << ( perTransactionDispatch ?
" (multiple dispatches)" :
" (single dispatch)" );
202 cout <<
"TESTING: " << oss_details.str() << endl;
205 const uint32_t x0 = rand();
207 const uint32_t a = rand();
209 const uint32_t b = rand();
211 const uint32_t x1 = ( x0 & a ) | b;
213 std::ostringstream oss_values;
215 oss_values <<
"Wrote value 0x" <<
std::hex << x0 <<
", then did RMW-bits with AND-term 0x" << a <<
", OR-term 0x" << b;
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 ) );
221 c.
write ( addr, x0 );
223 if ( perTransactionDispatch )
231 if ( ipbus2 ? ( x0 != reg_rmw.
value() ) : ( x1 != reg_rmw.
value() ) )
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;
240 if ( x1 != reg_read.
value() )
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;
246 catch (
const std::exception& e )
248 cout <<
"TEST FAILED: " << oss_values.str() <<
". Exception of type '" <<
typeid ( e ).
name() <<
"' thrown ..." << endl << e.what() << endl;
258 std::ostringstream oss_details;
259 oss_details <<
"RMW-sum @ 0x" <<
std::hex << addr << ( perTransactionDispatch ?
" (multiple dispatches)" :
" (single dispatch)" );
263 cout <<
"TESTING: " << oss_details.str() << endl;
266 const uint32_t x0 = rand();
268 const uint32_t a = rand();
270 const uint32_t x1 = x0 + a;
272 std::ostringstream oss_values;
274 oss_values <<
"Wrote value 0x" <<
std::hex << x0 <<
", then did RMW-sum with ADDEND 0x" << a;
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 ) );
280 c.
write ( addr, x0 );
282 if ( perTransactionDispatch )
290 if ( ipbus2 ? ( x0 != reg_sum.
value() ) : ( x1 != reg_sum.
value() ) )
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;
299 if ( x1 != reg_read.
value() )
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;
305 catch (
const std::exception& e )
307 cout <<
"TEST FAILED: " << oss_values.str() <<
". Exception of type '" <<
typeid ( e ).
name() <<
"' thrown ..." << endl << e.what() << endl;
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)
317 unsigned nrTestsFailed = 0;
318 unsigned nrTestsTotal = 0;
322 typedef std::vector<ClientInterface*>::const_iterator ClientIt_t;
323 for ( ClientIt_t clientIt = aClients.begin(); clientIt != aClients.end(); 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 );
331 for (
unsigned i = 0; i < 2498; i++ )
333 addr_vec.push_back ( aBaseAddr + ( rand() % aDepth ) );
336 cout <<
"\n 1. Single-register write/read (" << addr_vec.size() * 2 <<
" tests)" << endl;
338 for (
unsigned i = 0; i < addr_vec.size(); i++ )
342 if ( ! validation_test_single_write_read ( *client, addr_vec.at ( i ),
true, aVerbose ) )
349 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 ) )
372 if ( ! validation_test_block_write_read ( *client, addr, depth,
false || aDispatchEachIteration, aVerbose ) )
378 cout <<
"\n 3. Testing RMW-bits (write, RMWbits, read; " << addr_vec.size() * 2 <<
" tests)" << endl;
380 for ( std::vector<uint32_t>::const_iterator it = addr_vec.begin(); it != addr_vec.end(); it++ )
384 if ( ! validation_test_write_rmwbits_read ( *client, *it,
true, aVerbose ) )
391 if ( ! validation_test_write_rmwbits_read ( *client, *it,
false || aDispatchEachIteration, aVerbose ) )
397 cout <<
"\n 4. Testing RMW-sum (write, RMW-sum, read; " << addr_vec.size() * 2 <<
" tests)" << endl;
399 for ( std::vector<uint32_t>::const_iterator it = addr_vec.begin(); it != addr_vec.end(); it++ )
403 if ( ! validation_test_write_rmwsum_read ( *client, *it,
true, aVerbose ) )
410 if ( ! validation_test_write_rmwsum_read ( *client, *it,
false || aDispatchEachIteration, aVerbose ) )
417 if ( nrTestsFailed == 0 )
419 cout <<
"\n\nBASIC TESTS SUMMARY: All " << nrTestsTotal <<
" tests passed!" << endl << endl << endl;
423 cout <<
"\n\nBASIC TESTS SUMMARY: Total of " << nrTestsTotal <<
" tests run -- " << nrTestsFailed <<
" tests FAILED , " << ( nrTestsTotal - nrTestsFailed ) <<
" tests PASSED" << endl;
429 for ( ClientIt_t clientIt = aClients.begin(); clientIt != aClients.end(); clientIt++ )
432 cout <<
"\nSOAK TEST to device '" << client->
uri() <<
"'\n Random sequence of " << aNrIterations <<
" transactions will be sent to hardware" << endl << endl;
435 size_t found = client->
uri().find (
"-1.3" );
437 if ( found!=std::string::npos )
443 found = client->
uri().find (
"-2.0" );
445 if ( found!=std::string::npos )
451 log (
Error() ,
"Cannot deduce protocol from URI " ,
Quote ( client->
uri() ),
" Exiting before performing soak test." );
457 std::vector< uint32_t > registers ( aDepth , 0x00000000 );
461 uint32_t type,
addr, blockSize;
462 uint32_t tempUInt1, tempUInt2;
463 vector< boost::shared_ptr<QueuedTransaction> > queuedTransactions;
464 uint32_t nrQueuedWords = 0;
466 for (
unsigned i = 1; i <= aNrIterations; i++ )
468 type = ( rand() % 4 );
469 addr = aBaseAddr + ( rand() % aDepth );
475 blockSize = getRandomBlockSize ( aBaseAddr + aDepth - addr );
480 nrQueuedWords += blockSize;
485 blockSize = getRandomBlockSize ( aBaseAddr + aDepth - addr );
488 vector<uint32_t> randomData = getRandomBuffer ( blockSize );
490 std::copy ( randomData.begin(), randomData.end(), registers.begin() + ( addr - aBaseAddr ) );
492 nrQueuedWords += blockSize;
500 vector<uint32_t>::iterator regIt = registers.begin() + ( addr - aBaseAddr );
502 if ( ipbus_vsn == 1 )
512 if ( ipbus_vsn == 2 )
524 vector<uint32_t>::iterator regIt = registers.begin() + ( addr - aBaseAddr );
526 if ( ipbus_vsn == 1 )
535 if ( ipbus_vsn == 2 )
544 if ( aDispatchEachIteration || ( nrQueuedWords > 20000000 ) || ( i == aNrIterations ) )
546 log (
Notice(),
"Soak test - issuing dispatch" );
548 log (
Notice(),
"Soak test - issuing empty dispatch" );
553 if ( ! ( *it )->check_values() )
555 cout <<
"ERROR OCCURED IN SOAK TEST to '" << client->
uri() <<
"' - after " << i <<
" successful transactions" << endl;
560 queuedTransactions.clear();
565 std::cout <<
"No errors after " << i <<
" transactions -- " << setiosflags (
ios::fixed ) << setprecision ( 1 ) << ( 100.0 * i ) / aNrIterations <<
"% done\r";
572 cout << endl <<
"Reached end of soak testing successfully!" << endl;
580 m_depth ( valVector.size() ),
582 m_valVector ( valVector )
593 std::vector<uint32_t>::const_iterator expdIt =
m_expected.begin();
597 if ( ( *valVecIt ) != ( *expdIt ) )
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>() ) );
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>() ) );
615 m_valHeader ( valHeader )
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>() ) );
640 m_valWord ( valWord ),
641 m_expected ( expected )
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>() ) );
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<>() ) );
const uint32_t m_expected
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's and wait until all q...
T value() const
Return the value of the validated memory with check on validity.
A class which wraps a block of data and marks whether or not it is valid.
ValWord< uint32_t > m_valWord
virtual bool check_values()
virtual bool check_values()
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...
std::vector< U32 > U32Vec
A vector of unsigned 32-bit words.
ValHeader write(const uint32_t &aAddr, const uint32_t &aValue)
Write a single, unmasked word to a register.
ValVector< uint32_t > m_valVector
std::vector< uint32_t > m_expected
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)
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...
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 ...
Empty struct which acts as a dummy variable for passing the formatting information around...
_Quote< T > Quote(const T &aT)
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=...
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 uint32_t m_expected
const_iterator begin() const
If the memory has previously been marked as valid, return a const iterator to the beginning of the un...
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
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)
ValWord< uint32_t > m_valWord
QueuedRmwSum(const uint32_t addr, const uint32_t a, const ValWord< uint32_t > &valWord, const uint32_t expected)
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...
virtual bool check_values()
virtual bool check_values()
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)