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