μHAL (v2.6.5)
Part of the IPbus software repository
Node.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 
24  Andrew Rose, Imperial College, London
25  email: awr01 <AT> imperial.ac.uk
26 
27  Marc Magrans de Abril, CERN
28  email: marc.magrans.de.abril <AT> cern.ch
29 
30 ---------------------------------------------------------------------------
31 */
32 
33 #include "uhal/Node.hpp"
34 
35 #include "uhal/log/log.hpp"
36 #include "uhal/HwInterface.hpp"
37 #include "uhal/ValMem.hpp"
38 #include "uhal/NodeTreeBuilder.hpp"
39 
40 #include <boost/regex.hpp>
41 
42 #include <iomanip>
43 
44 #ifdef __GNUG__
45 #include <cxxabi.h>
46 #endif
47 
48 
49 namespace uhal
50 {
57  std::ostream& operator<< ( std::ostream& aStr , const uhal::Node& aNode )
58  {
59  aNode.stream ( aStr );
60  return aStr;
61  }
62 
63 
64  Node::Node ( ) :
65  mHw ( NULL ),
66  mUid ( "" ),
67  mPartialAddr ( 0x00000000 ),
68  mAddr ( 0x00000000 ),
69  mMask ( defs::NOMASK ),
70  mPermission ( defs::READWRITE ),
71  mMode ( defs::HIERARCHICAL ),
72  mSize ( 0x00000001 ),
73  mTags ( "" ),
74  mDescription ( "" ),
75  mModule ( "" ),
76  mClassName ( "" ),
77  mParameters ( ),
78  mFirmwareInfo( ),
79  mParent ( NULL ),
80  mChildren ( ),
81  mChildrenMap ( )
82  {
83  }
84 
85 
86  Node::Node ( const Node& aNode ) :
87  mHw ( aNode.mHw ),
88  mUid ( aNode.mUid ),
89  mPartialAddr ( aNode.mPartialAddr ),
90  mAddr ( aNode.mAddr ),
91  mMask ( aNode.mMask ),
92  mPermission ( aNode.mPermission ),
93  mMode ( aNode.mMode ),
94  mSize ( aNode.mSize ),
95  mTags ( aNode.mTags ),
96  mDescription ( aNode.mDescription ),
97  mModule ( aNode.mModule ),
98  mClassName ( aNode.mClassName ),
99  mParameters ( aNode.mParameters ),
100  mFirmwareInfo ( aNode.mFirmwareInfo ),
101  mParent ( NULL ),
102  mChildren ( ),
103  mChildrenMap ( )
104  {
105  for ( std::deque< Node* >::const_iterator lIt = aNode.mChildren.begin(); lIt != aNode.mChildren.end(); ++lIt )
106  {
107  mChildren.push_back ( ( **lIt ).clone() );
108  }
109 
110  for ( std::deque< Node* >::iterator lIt = mChildren.begin(); lIt != mChildren.end(); ++lIt )
111  {
112  ( **lIt ).mParent = this;
113  mChildrenMap.insert ( std::make_pair ( ( **lIt ).mUid , *lIt ) );
114 
115  for ( boost::unordered_map< std::string , Node* >::iterator lSubMapIt = ( **lIt ).mChildrenMap.begin() ; lSubMapIt != ( **lIt ).mChildrenMap.end() ; ++lSubMapIt )
116  {
117  mChildrenMap.insert ( std::make_pair ( ( ( **lIt ).mUid ) +'.'+ ( lSubMapIt->first ) , lSubMapIt->second ) );
118  }
119  }
120  }
121 
122 
123 
124 
125  Node& Node::operator= ( const Node& aNode )
126  {
127  mHw = aNode.mHw;
128  mUid = aNode.mUid ;
129  mPartialAddr = aNode.mPartialAddr;
130  mAddr = aNode.mAddr;
131  mMask = aNode.mMask;
132  mPermission = aNode.mPermission;
133  mMode = aNode.mMode;
134  mSize = aNode.mSize;
135  mTags = aNode.mTags;
136  mDescription = aNode.mDescription;
137  mModule = aNode.mModule;
138  mClassName = aNode.mClassName;
139  mParameters = aNode.mParameters;
140 
141  for ( std::deque< Node* >::iterator lIt = mChildren.begin(); lIt != mChildren.end(); ++lIt )
142  {
143  if ( *lIt )
144  {
145  delete ( *lIt );
146  ( *lIt ) = NULL;
147  }
148  }
149 
150  mChildren.clear();
151  mChildrenMap.clear();
152 
153  for ( std::deque< Node* >::const_iterator lIt = aNode.mChildren.begin(); lIt != aNode.mChildren.end(); ++lIt )
154  {
155  mChildren.push_back ( ( **lIt ).clone() );
156  }
157 
158  for ( std::deque< Node* >::iterator lIt = mChildren.begin(); lIt != mChildren.end(); ++lIt )
159  {
160  ( **lIt ).mParent = this;
161  mChildrenMap.insert ( std::make_pair ( ( **lIt ).mUid , *lIt ) );
162 
163  for ( boost::unordered_map< std::string , Node* >::iterator lSubMapIt = ( **lIt ).mChildrenMap.begin() ; lSubMapIt != ( **lIt ).mChildrenMap.end() ; ++lSubMapIt )
164  {
165  mChildrenMap.insert ( std::make_pair ( ( ( **lIt ).mUid ) +'.'+ ( lSubMapIt->first ) , lSubMapIt->second ) );
166  }
167  }
168 
169  return *this;
170  }
171 
172 
173  Node* Node::clone ( ) const
174  {
175  return new Node ( *this );
176  }
177 
178 
179 
180 
182  {
183  for ( std::deque< Node* >::iterator lIt = mChildren.begin(); lIt != mChildren.end(); ++lIt )
184  {
185  if ( *lIt )
186  {
187  delete ( *lIt );
188  ( *lIt ) = NULL;
189  }
190  }
191 
192  mChildren.clear();
193  mChildrenMap.clear();
194  }
195 
196 
197 
198 
200  {
201  Node::const_iterator lIt ( this );
202  return lIt;
203  }
204 
205 
207  {
209  return lIt;
210  }
211 
212  bool Node::operator == ( const Node& aNode ) const
213  {
214  return this->getAddress() == aNode.getAddress() &&
215  this->getMask() == aNode.getMask() &&
216  this->getPermission() == aNode.getPermission() &&
217  this->getId() == aNode.getId();
218  }
219 
220 
221  const std::string& Node::getId() const
222  {
223  return mUid;
224  }
225 
226  std::string Node::getPath() const
227  {
228  std::deque< const Node* > lPath;
229  getAncestors ( lPath );
230  std::string lRet;
231 
232  for ( std::deque< const Node* >::iterator lIt ( lPath.begin() ) ; lIt != lPath.end() ; ++lIt )
233  {
234  if ( ( **lIt ).mUid.size() )
235  {
236  lRet += ( **lIt ).mUid;
237  lRet += ".";
238  }
239  }
240 
241  if ( lRet.size() )
242  {
243  lRet.resize ( lRet.size() - 1 );
244  }
245 
246  return lRet;
247  }
248 
249 
250  void Node::getAncestors ( std::deque< const Node* >& aPath ) const
251  {
252  aPath.push_front ( this );
253 
254  if ( mParent )
255  {
256  mParent->getAncestors ( aPath );
257  }
258  }
259 
260 
261  const uint32_t& Node::getAddress() const
262  {
263  return mAddr;
264  }
265 
266  const uint32_t& Node::getMask() const
267  {
268  return mMask;
269  }
270 
272  {
273  return mMode;
274  }
275 
276  const uint32_t& Node::getSize() const
277  {
278  return mSize;
279  }
280 
282  {
283  return mPermission;
284  }
285 
286 
287  const std::string& Node::getTags() const
288  {
289  return mTags;
290  }
291 
292 
293  const std::string& Node::getDescription() const
294  {
295  return mDescription;
296  }
297 
298 
299  const std::string& Node::getModule() const
300  {
301  return mModule;
302  }
303 
304  const boost::unordered_map< std::string, std::string >& Node::getParameters() const
305  {
306  return mParameters;
307  }
308 
309  const boost::unordered_map< std::string, std::string >& Node::getFirmwareInfo() const
310  {
311  return mFirmwareInfo;
312  }
313 
314  void Node::stream ( std::ostream& aStr , std::size_t aIndent ) const
315  {
316  std::ios_base::fmtflags original_flags = std::cout.flags();
317 
318  aStr << std::setfill ( '0' ) << std::uppercase;
319  aStr << '\n' << std::string ( aIndent , ' ' ) << "+ ";
320  aStr << "Node \"" << mUid << "\", ";
321 
322  if ( &typeid ( *this ) != &typeid ( Node ) )
323  {
324  aStr << "of type \"";
325 #ifdef __GNUG__
326  // this is fugly but necessary due to the way that typeid::name() returns the object type name under g++.
327  int lStatus ( 0 );
328  static std::size_t lSize ( 1024 );
329  static char* lDemangled = new char[lSize];
330  aStr << ( abi::__cxa_demangle ( typeid ( *this ).name() , lDemangled , &lSize , &lStatus ) );
331 #else
332  aStr << typeid ( *this ).name();
333 #endif
334  aStr << "\", ";
335  }
336 
337  switch ( mMode )
338  {
339  case defs::SINGLE:
340  aStr << "SINGLE register, "
341  << std::hex << "Address 0x" << std::setw ( 8 ) << mAddr << ", "
342  << std::hex << "Mask 0x" << std::setw ( 8 ) << mMask << ", "
343  << "Permissions " << ( mPermission&defs::READ?'r':'-' ) << ( mPermission&defs::WRITE?'w':'-' ) ;
344  break;
345  case defs::INCREMENTAL:
346  aStr << "INCREMENTAL block, "
347  << std::dec << "Size " << mSize << ", "
348  << std::hex << "Addresses [0x" << std::setw ( 8 ) << mAddr << "-" << std::setw ( 8 ) << ( mAddr+mSize-1 ) << "], "
349  << "Permissions " << ( mPermission&defs::READ?'r':'-' ) << ( mPermission&defs::WRITE?'w':'-' ) ;
350  break;
352  aStr << "NON-INCREMENTAL block, ";
353 
354  if ( mSize != 1 )
355  {
356  aStr << std::dec << "Size " << mSize << ", ";
357  }
358 
359  aStr << std::hex << "Address 0x" << std::setw ( 8 ) << mAddr << ", "
360  << "Permissions " << ( mPermission&defs::READ?'r':'-' ) << ( mPermission&defs::WRITE?'w':'-' ) ;
361  break;
362  case defs::HIERARCHICAL:
363  aStr << std::hex << "Address 0x" << std::setw ( 8 ) << mAddr;
364  break;
365  }
366 
367  if ( mTags.size() )
368  {
369  aStr << ", Tags \"" << mTags << "\"";
370  }
371 
372  if ( mDescription.size() )
373  {
374  aStr << ", Description \"" << mDescription << "\"";
375  }
376 
377  if ( mModule.size() )
378  {
379  aStr << ", Module \"" << mModule << "\"";
380  }
381 
382  if ( mClassName.size() )
383  {
384  aStr << ", Class Name \"" << mClassName << "\"";
385  }
386 
387  if ( mParameters.size() )
388  {
389  aStr << ", Parameters: ";
390  boost::unordered_map<std::string, std::string>::const_iterator lIt;
391 
392  for ( lIt = mParameters.begin(); lIt != mParameters.end(); ++lIt )
393  {
394  aStr << lIt->first << "=" << lIt->second << ";";
395  }
396  }
397 
398  // Reset the integer base (i.e. std::dec, std::hex, etc) to its original value
399  aStr.flags(original_flags);
400 
401  // Recursively print children
402  for ( std::deque< Node* >::const_iterator lIt = mChildren.begin(); lIt != mChildren.end(); ++lIt )
403  {
404  ( **lIt ).stream ( aStr , aIndent+2 );
405  }
406  }
407 
408  const Node& Node::getNode ( const std::string& aId ) const
409  {
410  if ( aId.size() == 0 )
411  {
412  return *this;
413  }
414 
415  boost::unordered_map< std::string , Node* >::const_iterator lIt = mChildrenMap.find ( aId );
416 
417  if ( lIt==mChildrenMap.end() )
418  {
419  exception::NoBranchFoundWithGivenUID lExc;
420  log ( lExc , "No branch found with ID-path " , Quote ( aId ) , " from node " , Quote ( this->getPath() ) );
421  std::size_t lPos ( std::string::npos );
422  bool lPartialMatch ( false );
423 
424  while ( true )
425  {
426  lPos = aId.rfind ( '.' , lPos );
427 
428  if ( lPos == std::string::npos )
429  {
430  break;
431  }
432 
433  boost::unordered_map< std::string , Node* >::const_iterator lIt = mChildrenMap.find ( aId.substr ( 0 , lPos ) );
434 
435  if ( lIt!=mChildrenMap.end() )
436  {
437  log ( lExc , "Partial match " , Quote ( aId.substr ( 0 , lPos ) ) , " found for ID-path " , Quote ( aId ) , " from node " , Quote ( this->getPath() ) );
438  log ( Error() , "Tree structure of partial match is:" , * ( lIt->second ) );
439  lPartialMatch = true;
440  break;
441  }
442 
443  lPos--;
444  }
445 
446  if ( !lPartialMatch )
447  {
448  log ( lExc , "Not even a partial match found for ID-path " , Quote ( aId ) , " from node " , Quote ( this->getPath() ) , ". If this address looks correct, please check for leading, trailing and stray whitespace." );
449  log ( Error(), "Tree structure is:" , *this );
450  }
451 
452  throw lExc;
453  }
454 
455  return * ( lIt->second );
456  }
457 
458 
459  std::vector<std::string> Node::getNodes() const
460  {
461  std::vector<std::string> lNodes;
462  lNodes.reserve ( mChildrenMap.size() ); //prevent reallocations
463 
464  for ( boost::unordered_map< std::string , Node* >::const_iterator lIt = mChildrenMap.begin(); lIt != mChildrenMap.end(); ++lIt )
465  {
466  lNodes.push_back ( lIt->first );
467  }
468 
469  return lNodes;
470  }
471 
472  std::vector<std::string> Node::getNodes ( const std::string& aRegex ) const
473  {
474  std::vector<std::string> lNodes;
475  lNodes.reserve ( mChildrenMap.size() ); //prevent reallocations
476  log ( Info() , "Regular Expression : " , aRegex );
477 
478  for ( boost::unordered_map< std::string , Node* >::const_iterator lIt = mChildrenMap.begin(); lIt != mChildrenMap.end(); ++lIt )
479  {
480  boost::cmatch lMatch;
481 
482  if ( boost::regex_match ( lIt->first.c_str() , lMatch , boost::regex ( aRegex ) ) ) //to allow partial match, add boost::match_default|boost::match_partial as fourth argument
483  {
484  log ( Info() , lIt->first , " matches" );
485  lNodes.push_back ( lIt->first );
486  }
487  }
488 
489  //bit dirty but since the hash map sorts them by the hash, not the value, they are completely scrambled here making it very hard to use.
490  std::sort ( lNodes.begin(), lNodes.end() );
491  return lNodes;
492  }
493 
494  ValHeader Node::write ( const uint32_t& aValue ) const
495  {
496  if ( mPermission & defs::WRITE )
497  {
498  if ( mMask == defs::NOMASK )
499  {
500  return mHw->getClient().write ( mAddr , aValue );
501  }
502  else if ( mPermission & defs::READ )
503  {
504  return mHw->getClient().write ( mAddr , aValue , mMask );
505  }
506  else // Masked write-only register
507  {
508  // RMWbits transaction should not be performed automatically on masked write-only node, since RMW transactions involve reading the register
509  exception::WriteAccessDenied lExc;
510  log ( lExc , "Cannot automatically perform write on write-only masked node " , Quote ( this->getPath() ) , "; masked write would have to be implemented as RMW transaction, which requires read permissions." );
511  }
512  }
513 
514  exception::WriteAccessDenied lExc;
515  log ( lExc , "Node " , Quote ( this->getPath() ) , ": permissions denied write access" );
516  throw lExc;
517  }
518 
519 
520  ValHeader Node::writeBlock ( const std::vector< uint32_t >& aValues ) const // , const defs::BlockReadWriteMode& aMode )
521  {
522  if ( ( mMode == defs::SINGLE ) && ( aValues.size() != 1 ) ) //We allow the user to call a bulk access of size=1 to a single register
523  {
524  exception::BulkTransferOnSingleRegister lExc;
525  log ( lExc , "Bulk Transfer requested on single register node " , Quote ( this->getPath() ) );
526  log ( lExc , "If you were expecting an incremental write, please modify your address file to add the 'mode=", Quote ( "incremental" ) , "' flags there" );
527  throw lExc;
528  }
529 
530  if ( ( mSize != 1 ) && ( aValues.size() >mSize ) )
531  {
532  exception::BulkTransferRequestedTooLarge lExc;
533  log ( lExc , "Requested bulk write of greater size than the specified endpoint size of node ", Quote ( this->getPath() ) );
534  throw lExc;
535  }
536 
537  if ( mPermission & defs::WRITE )
538  {
539  return mHw->getClient().writeBlock ( mAddr , aValues , mMode ); //aMode );
540  }
541  else
542  {
543  exception::WriteAccessDenied lExc;
544  log ( lExc , "Node " , Quote ( this->getPath() ) , ": permissions denied write access" );
545  throw lExc;
546  }
547 
548  }
549 
550 
551  ValHeader Node::writeBlockOffset ( const std::vector< uint32_t >& aValues , const uint32_t& aOffset ) const // , const defs::BlockReadWriteMode& aMode )
552  {
553  if ( mMode == defs::NON_INCREMENTAL )
554  {
555  exception::BulkTransferOffsetRequestedForFifo lExc;
556  log ( lExc , "Bulk Transfer Offset requested for non-incremental node " , Quote ( this->getPath() ) );
557  throw lExc;
558  }
559 
560  if ( mMode == defs::SINGLE ) //We allow the user to call a bulk access of size=1 to a single register
561  {
562  exception::BulkTransferOffsetRequestedForSingleRegister lExc;
563  log ( lExc , "Bulk Transfer with offset requested on single register node " , Quote ( this->getPath() ) );
564  log ( lExc , "If you were expecting an incremental write, please modify your address file to add the 'mode=", Quote ( "incremental" ) , "' flags there" );
565  throw lExc;
566  }
567 
568  if ( (aValues.size()+aOffset) > mSize )
569  {
570  exception::BulkTransferRequestedTooLarge lExc;
571  log ( lExc , "Requested bulk write size and offset would overflow the specified endpoint node ", Quote ( this->getPath() ) );
572  throw lExc;
573  }
574 
575  if ( mPermission & defs::WRITE )
576  {
577  return mHw->getClient().writeBlock ( mAddr+aOffset , aValues , mMode ); //aMode );
578  }
579  else
580  {
581  exception::WriteAccessDenied lExc;
582  log ( lExc , "Node " , Quote ( this->getPath() ) , ": permissions denied write access" );
583  throw lExc;
584  }
585 
586  }
587 
588 
590  {
591  if ( mPermission & defs::READ )
592  {
593  if ( mMask == defs::NOMASK )
594  {
595  return mHw->getClient().read ( mAddr );
596  }
597  else
598  {
599  return mHw->getClient().read ( mAddr , mMask );
600  }
601  }
602 
603  exception::ReadAccessDenied lExc;
604  log ( lExc , "Node " , Quote ( this->getPath() ) , ": permissions denied read access" );
605  throw lExc;
606 
607  }
608 
609 
610  ValVector< uint32_t > Node::readBlock ( const uint32_t& aSize ) const //, const defs::BlockReadWriteMode& aMode )
611  {
612  if ( ( mMode == defs::SINGLE ) && ( aSize != 1 ) ) //We allow the user to call a bulk access of size=1 to a single register
613  {
614  exception::BulkTransferOnSingleRegister lExc;
615  log ( lExc , "Bulk Transfer requested on single register node ", Quote ( this->getPath() ) );
616  log ( lExc , "If you were expecting an incremental read, please modify your address file to add the 'mode=", Quote ( "incremental" ) , "' flags there" );
617  throw lExc;
618  }
619 
620  if ( ( mSize != 1 ) && ( aSize>mSize ) )
621  {
622  exception::BulkTransferRequestedTooLarge lExc;
623  log ( lExc , "Requested bulk read of greater size than the specified endpoint size of node " , Quote ( this->getPath() ) );
624  throw lExc;
625  }
626 
627  if ( mPermission & defs::READ )
628  {
629  return mHw->getClient().readBlock ( mAddr , aSize , mMode ); //aMode );
630  }
631  else
632  {
633  exception::ReadAccessDenied lExc;
634  log ( lExc , "Node " , Quote ( this->getPath() ) , ": permissions denied read access" );
635  throw lExc;
636  }
637 
638  }
639 
640 
641  ValVector< uint32_t > Node::readBlockOffset ( const uint32_t& aSize , const uint32_t& aOffset ) const //, const defs::BlockReadWriteMode& aMode )
642  {
643  if ( mMode == defs::NON_INCREMENTAL )
644  {
645  exception::BulkTransferOffsetRequestedForFifo lExc;
646  log ( lExc , "Bulk Transfer offset requested for non-incremental node " , Quote ( this->getPath() ) );
647  throw lExc;
648  }
649 
650  if ( mMode == defs::SINGLE ) //We do not allow the user to use an offset from a single register
651  {
652  exception::BulkTransferOffsetRequestedForSingleRegister lExc;
653  log ( lExc , "Bulk Transfer with offset requested on single register node ", Quote ( this->getPath() ) );
654  log ( lExc , "If you were expecting an incremental read, please modify your address file to add the 'mode=", Quote ( "incremental" ) , "' flags there" );
655  throw lExc;
656  }
657 
658  if ( (aSize+aOffset) > mSize )
659  {
660  exception::BulkTransferRequestedTooLarge lExc;
661  log ( lExc , "Requested bulk read size and offset would overflow the specified endpoint node " , Quote ( this->getPath() ) );
662  throw lExc;
663  }
664 
665  if ( mPermission & defs::READ )
666  {
667  return mHw->getClient().readBlock ( mAddr+aOffset , aSize , mMode ); //aMode );
668  }
669  else
670  {
671  exception::ReadAccessDenied lExc;
672  log ( lExc , "Node " , Quote ( this->getPath() ) , ": permissions denied read access" );
673  throw lExc;
674  }
675 
676  }
677  // ValWord< int32_t > Node::readSigned()
678  // {
679  // try
680  // {
681  // if ( mPermission & defs::READ )
682  // {
683  // if ( mMask == defs::NOMASK )
684  // {
685  // return mHw->getClient().readSigned ( mAddr );
686  // }
687  // else
688  // {
689  // return mHw->getClient().readSigned ( mAddr , mMask );
690  // }
691  // }
692  // else
693  // {
694  // log ( Error() , "Node permissions denied read access" );
695  // throw exception::// ReadAccessDenied();
696  // }
697  // }
698  // catch ( uhal::exception& aExc )
699  // {
700  // aExc.throw r;
701  // }
702  // catch ( const std::exception& aExc )
703  // {
704  // throw // StdException ( aExc );
705  // }
706  // }
707 
708 
709  // ValVector< int32_t > Node::readBlockSigned ( const uint32_t& aSize ) //, const defs::BlockReadWriteMode& aMode )
710  // {
711  // try
712  // {
713  // if ( ( mMode == defs::SINGLE ) && ( aSize != 1 ) ) //We allow the user to call a bulk access of size=1 to a single register
714  // {
715  // log ( Error() , "Bulk Transfer requested on single register node" );
716  // log ( Error() , "If you were expecting an incremental read, please modify your address file to add the 'mode=", Quote ( "incremental" ) , "' flags there" );
717  // throw exception::// BulkTransferOnSingleRegister();
718  // }
719  // else
720  // {
721  // if ( ( mSize != 1 ) && ( aSize>mSize ) )
722  // {
723  // log ( Error() , "Requested bulk read of greater size than the specified endpoint size" );
724  // throw exception::// BulkTransferRequestedTooLarge();
725  // }
726 
727  // if ( mPermission & defs::READ )
728  // {
729  // return mHw->getClient().readBlockSigned ( mAddr , aSize , mMode ); //aMode );
730  // }
731  // else
732  // {
733  // log ( Error() , "Node permissions denied read access" );
734  // throw exception::// ReadAccessDenied();
735  // }
736  // }
737  // }
738  // catch ( uhal::exception& aExc )
739  // {
740  // aExc.throw r;
741  // }
742  // catch ( const std::exception& aExc )
743  // {
744  // throw // StdException ( aExc );
745  // }
746  // }
747 
748 
749 
750 
751  // ValWord< uint32_t > Node::rmw_bits ( const uint32_t& aANDterm , const uint32_t& aORterm )
752  // {
753  // try
754  // {
755  // if ( mPermission == defs::READWRITE )
756  // {
757  // return mHw->getClient().rmw_bits ( mAddr , aANDterm , aORterm );
758  // }
759  // else
760  // {
761  // log ( Error() , "Node permissions denied read/write access" );
762  // throw exception::// ReadAccessDenied();
763  // }
764  // }
765  // catch ( uhal::exception& aExc )
766  // {
767  // aExc.throw r;
768  // }
769  // catch ( const std::exception& aExc )
770  // {
771  // throw // StdException ( aExc );
772  // }
773  // }
774 
775 
776 
777  // ValWord< uint32_t > Node::rmw_sum ( const int32_t& aAddend )
778  // {
779  // try
780  // {
781  // if ( mPermission == defs::READWRITE )
782  // {
783  // return mHw->getClient().rmw_sum ( mAddr , aAddend );
784  // }
785  // else
786  // {
787  // log ( Error() , "Node permissions denied read/write access" );
788  // throw exception::// ReadAccessDenied();
789  // }
790  // }
791  // catch ( uhal::exception& aExc )
792  // {
793  // aExc.throw r;
794  // }
795  // catch ( const std::exception& aExc )
796  // {
797  // throw // StdException ( aExc );
798  // }
799  // }
800 
802  {
803  return mHw->getClient();
804  }
805 
806 
807 
809  {}
810 
811  Node::const_iterator::const_iterator ( const Node* aBegin ) : mBegin ( aBegin )
812  {}
813 
815  {}
816 
817 
819  {}
820 
822  {
823  return value();
824  }
825 
827  {
828  return & ( value() );
829  }
830 
832  {
833  return ( mItStack.size() ) ? ( **mItStack[0] ) : ( *mBegin );
834  }
835 
837  {
838  next();
839  return *this;
840  }
841 
842 
844  {
845  Node::const_iterator lTemp ( *this );
846  next();
847  return lTemp;
848  }
849 
850 
852  {
853  // Null iterator can't be incremented...
854  if ( !mBegin )
855  {
856  return false;
857  }
858 
859  if ( ! mItStack.size() )
860  {
861  //We have just started and have no stack...
862  if ( mBegin->mChildren.size() )
863  {
864  //We have children so recurse down to them
865  mItStack.push_front ( mBegin->mChildren.begin() );
866  return true;
867  }
868 
869  //We have no children so we are at the end of the iteration. Make Buffer NULL to stop infinite loop
870  mBegin = NULL;
871  return false;
872  }
873 
874  //We are already in the tree...
875  if ( ( **mItStack[0] ).mChildren.size() )
876  {
877  // Entry has children, recurse...
878  mItStack.push_front ( ( **mItStack[0] ).mChildren.begin() );
879  return true;
880  }
881 
882  // No children so go to the next entry on this level
883  while ( mItStack.size() )
884  {
885  if ( ++ ( mItStack[0] ) != ( ( mItStack.size() == 1 ) ? ( *mBegin ) : ( **mItStack[1] ) ).mChildren.end() )
886  {
887  // Next entry on this level is valid - return
888  return true;
889  }
890 
891  // No more valid entries in this level, go back up tree
892  mItStack.pop_front();
893  }
894 
895  //We have no more children so we are at the end of the iteration. Make Buffer NULL to stop infinite loop
896  mBegin = NULL;
897  return false;
898  }
899 
900 
902  {
903  return ! ( *this == aIt ) ;
904  }
905 
907  {
908  return ( aIt.mBegin == mBegin ) && ( aIt.mItStack == mItStack ) ;
909  }
910 
911 }
boost::unordered_map< std::string, std::string > mFirmwareInfo
parameters to infer the VHDL address decoding
Definition: Node.hpp:372
ValWord< uint32_t > read(const uint32_t &aAddr)
Read a single, unmasked, unsigned word.
std::vector< std::string > getNodes() const
Return all node IDs known to this HwInterface.
Definition: Node.cpp:459
HwInterface * mHw
The parent hardware interface of which this node is a child (or rather decendent) ...
Definition: Node.hpp:337
ValHeader writeBlockOffset(const std::vector< uint32_t > &aValues, const uint32_t &aOffset) const
Write a block of data to a block of registers or a block-write port.
Definition: Node.cpp:551
bool operator!=(const const_iterator &aIt) const
Definition: Node.cpp:901
const std::string & getId() const
Return the unique ID of the current node.
Definition: Node.cpp:221
std::string mClassName
Class name used to construct the derived node type.
Definition: Node.hpp:366
const defs::BlockReadWriteMode & getMode() const
Return whether the node represents a single register, a block of registers or a block-read/write port...
Definition: Node.cpp:271
std::string getPath() const
Return the full path to the current node.
Definition: Node.cpp:226
const std::string & getModule() const
Return the name of the module in which the current node resides.
Definition: Node.cpp:299
const uint32_t & getAddress() const
Return the register address with which this node is associated.
Definition: Node.cpp:261
const std::string & getTags() const
Return the optional tags string which the user can specify for the current node.
Definition: Node.cpp:287
void getAncestors(std::deque< const Node * > &aPath) const
Get the full path to the current node.
Definition: Node.cpp:250
const uint32_t & getMask() const
Return the mask to be applied if this node is a sub-field, rather than an entire register.
Definition: Node.cpp:266
virtual Node * clone() const
Function to produce a new copy of the current Node.
Definition: Node.cpp:173
defs::NodePermission mPermission
The read/write access permissions of this node.
Definition: Node.hpp:350
bool operator==(const const_iterator &aIt) const
Definition: Node.cpp:906
const std::string & getDescription() const
Return the optional description string which the user can specify for the current node...
Definition: Node.cpp:293
Node()
Empty node.
Definition: Node.cpp:64
const uint32_t & getSize() const
Return the maximum size available to a block read/write.
Definition: Node.cpp:276
const_iterator end() const
Definition: Node.cpp:206
defs::BlockReadWriteMode mMode
Whether the node represents a single register, a block of registers or a block-read/write port...
Definition: Node.hpp:352
std::string mTags
Optional string which the user can specify.
Definition: Node.hpp:357
virtual ~const_iterator()
Definition: Node.cpp:818
ValVector< uint32_t > readBlockOffset(const uint32_t &aSize, const uint32_t &aOffset) const
Read a block of unsigned data from a block of registers or a block-read port.
Definition: Node.cpp:641
bool operator==(const Node &aNode) const
A function to determine whether two Nodes are identical.
Definition: Node.cpp:212
uint32_t mSize
The maximum size available to a block read/write.
Definition: Node.hpp:354
ValHeader write(const uint32_t &aAddr, const uint32_t &aValue)
Write a single, unmasked word to a register.
std::string mDescription
Optional string which the user can specify.
Definition: Node.hpp:360
const uint32_t NOMASK
define what it means to have no mask
Definition: definitions.hpp:56
virtual ~Node()
Destructor.
Definition: Node.cpp:181
const_iterator begin() const
Definition: Node.cpp:199
std::string mModule
The name of the module in which the current node resides.
Definition: Node.hpp:363
boost::unordered_map< std::string, std::string > mParameters
Additional parameters of the node.
Definition: Node.hpp:369
uint32_t mPartialAddr
The register address with which this node is associated.
Definition: Node.hpp:343
uint32_t mMask
The mask to be applied if this node is a sub-field, rather than an entire register.
Definition: Node.hpp:348
ErrorLevel Error
Definition: LogLevels.cpp:61
ValHeader write(const uint32_t &aValue) const
Write a single, unmasked word to a register.
Definition: Node.cpp:494
A heirarchical node for navigating heirarchical firmwares.
Definition: Node.hpp:83
_Quote< T > Quote(const T &aT)
ValVector< uint32_t > readBlock(const uint32_t &aSize) const
Read a block of unsigned data from a block of registers or a block-read port.
Definition: Node.cpp:610
std::deque< Node *> mChildren
The direct children of the node.
Definition: Node.hpp:378
const Node & getNode(const std::string &aId) const
Retrieve the Node given by a full-stop delimeted name path relative, to the current node...
Definition: Node.cpp:408
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.
ClientInterface & getClient()
Get the underlying IPbus client.
Definition: HwInterface.cpp:79
virtual Node & operator=(const Node &aNode)
Assignment operator.
Definition: Node.cpp:125
const Node & value() const
Definition: Node.cpp:831
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.
uint32_t mAddr
The register address with which this node is associated.
Definition: Node.hpp:345
An abstract base class for defining the interface to the various IPbus clients as well as providing t...
const Node & operator*() const
Definition: Node.cpp:821
std::string mUid
The Unique ID of this node.
Definition: Node.hpp:340
const Node * mBegin
Definition: Node.hpp:115
NodePermission
define Read and Write permissions of a uhal Node
Definition: definitions.hpp:50
const boost::unordered_map< std::string, std::string > & getParameters() const
Return parameters of the current node.
Definition: Node.cpp:304
Hexadecimal.
Node * mParent
The parent of the current node.
Definition: Node.hpp:375
BlockReadWriteMode
define whether transactions target a single register, a block of registers, a block-read/write port o...
Definition: definitions.hpp:53
A class which wraps a single word of data and marks whether or not it is valid.
Definition: ValMem.hpp:156
void stream(std::ostream &aStr, std::size_t aIndent=0) const
A streaming helper function to create pretty, indented tree diagrams.
Definition: Node.cpp:314
boost::unordered_map< std::string, Node *> mChildrenMap
Helper to assist look-up of a particular child node, given a name.
Definition: Node.hpp:381
const defs::NodePermission & getPermission() const
Return the read/write access permissions of this node.
Definition: Node.cpp:281
const Node * operator->() const
Definition: Node.cpp:826
const_iterator & operator++()
Definition: Node.cpp:836
InfoLevel Info
Definition: LogLevels.cpp:114
ValWord< uint32_t > read() const
Read a single, unmasked, unsigned word.
Definition: Node.cpp:589
const boost::unordered_map< std::string, std::string > & getFirmwareInfo() const
Return parameters for inferring the VHDL address decoding.
Definition: Node.cpp:309
ClientInterface & getClient() const
Get the underlying IPbus client.
Definition: Node.cpp:801
std::ostream & operator<<(std::ostream &aStr, const uhal::HttpResponseType &aHttpResponse)
ValHeader writeBlock(const std::vector< uint32_t > &aValues) const
Write a block of data to a block of registers or a block-write port.
Definition: Node.cpp:520