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