40#include <boost/regex.hpp>
54 mPartialAddr ( 0x00000000 ),
56 mMask ( defs::NOMASK ),
57 mPermission ( defs::READWRITE ),
58 mMode ( defs::HIERARCHICAL ),
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 ),
148 return new Node ( *
this );
199 std::deque< const Node* > lPath;
203 for (
const Node* lNode: lPath)
205 if ( lNode->mUid.size() )
214 lRet.resize ( lRet.size() - 1 );
223 std::deque< const Node* > lPath;
227 for (std::deque< const Node* >::iterator lIt ( std::find(lPath.begin(), lPath.end(), &aAncestor) + 1 ) ; lIt != lPath.end() ; ++lIt )
229 if ( ( **lIt ).mUid.size() )
231 lRet += ( **lIt ).mUid;
238 lRet.resize ( lRet.size() - 1 );
247 aPath.push_front (
this );
318 std::ios_base::fmtflags original_flags = std::cout.flags();
320 aStr << std::setfill (
'0' ) << std::uppercase;
321 aStr <<
'\n' << std::string ( aIndent ,
' ' ) <<
"+ ";
322 aStr <<
"Node \"" <<
mUid <<
"\", ";
324 if ( &
typeid ( *
this ) != &
typeid (
Node ) )
326 aStr <<
"of type \"";
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 ) );
334 aStr <<
typeid ( *this ).name();
342 aStr <<
"SINGLE register, "
343 << std::hex <<
"Address 0x" << std::setw ( 8 ) <<
mAddr <<
", "
344 << std::hex <<
"Mask 0x" << std::setw ( 8 ) <<
mMask <<
", "
348 aStr <<
"INCREMENTAL block, "
349 << std::dec <<
"Size " <<
mSize <<
", "
350 << std::hex <<
"Addresses [0x" << std::setw ( 8 ) <<
mAddr <<
"-" << std::setw ( 8 ) << (
mAddr+
mSize-1 ) <<
"], "
354 aStr <<
"NON-INCREMENTAL block, ";
358 aStr << std::dec <<
"Size " <<
mSize <<
", ";
361 aStr << std::hex <<
"Address 0x" << std::setw ( 8 ) <<
mAddr <<
", "
365 aStr << std::hex <<
"Address 0x" << std::setw ( 8 ) <<
mAddr;
371 aStr <<
", Tags \"" <<
mTags <<
"\"";
381 aStr <<
", Module \"" <<
mModule <<
"\"";
386 aStr <<
", Class Name \"" <<
mClassName <<
"\"";
391 aStr <<
", Parameters: ";
392 std::unordered_map<std::string, std::string>::const_iterator lIt;
396 aStr << lIt->first <<
"=" << lIt->second <<
";";
401 aStr.flags(original_flags);
404 for ( std::vector< Node* >::const_iterator lIt =
mChildren.begin(); lIt !=
mChildren.end(); ++lIt )
406 ( **lIt ).stream ( aStr , aIndent+2 );
413 if ( aId.size() == 0 )
418 size_t lStartIdx = 0;
421 const Node* lDescendant =
this;
424 lDotIdx = aId.find(
'.', lStartIdx);
425 std::unordered_map< std::string , Node* >::const_iterator lIt = lDescendant->
mChildrenMap.find ( aId.substr(lStartIdx, lDotIdx - lStartIdx) );
428 lDescendant = lIt->second;
434 lStartIdx = lDotIdx + 1;
435 }
while (lDotIdx != std::string::npos);
443 if ( aId.size() == 0 )
448 size_t lStartIdx = 0;
451 const Node* lDescendant =
this;
454 lDotIdx = aId.find(
'.', lStartIdx);
455 std::unordered_map< std::string , Node* >::const_iterator lIt = lDescendant->
mChildrenMap.find ( aId.substr(lStartIdx, lDotIdx - lStartIdx) );
458 lDescendant = lIt->second;
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)" );
466 exception::NoBranchFoundWithGivenUID lExc;
471 lStartIdx = lDotIdx + 1;
472 }
while (lDotIdx != std::string::npos);
480 std::vector<std::string> lNodes;
485 lNodes.push_back(lIt->getRelativePath(*
this));
494 std::vector<std::string> lNodes;
495 log (
Info() ,
"Regular Expression : " , aRegex );
500 const std::string lRelativePath(lIt->getRelativePath(*
this));
501 boost::cmatch lMatch;
503 if ( boost::regex_match ( lRelativePath.c_str() , lMatch , boost::regex ( aRegex ) ) )
505 log (
Info() , lRelativePath ,
" matches" );
506 lNodes.push_back ( lRelativePath );
511 std::sort ( lNodes.begin(), lNodes.end() );
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." );
536 exception::WriteAccessDenied lExc;
537 log ( lExc ,
"Node " ,
Quote ( this->
getPath() ) ,
": permissions denied write access" );
544 if ( ( mMode ==
defs::SINGLE ) && ( aValues.size() != 1 ) )
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" );
552 if ( ( mSize != 1 ) && ( aValues.size() >mSize ) )
554 exception::BulkTransferRequestedTooLarge lExc;
555 log ( lExc ,
"Requested bulk write of greater size than the specified endpoint size of node ",
Quote ( this->getPath() ) );
561 return mHw->getClient().writeBlock ( mAddr , aValues , mMode );
565 exception::WriteAccessDenied lExc;
566 log ( lExc ,
"Node " ,
Quote ( this->getPath() ) ,
": permissions denied write access" );
577 exception::BulkTransferOffsetRequestedForFifo lExc;
578 log ( lExc ,
"Bulk Transfer Offset requested for non-incremental node " ,
Quote ( this->getPath() ) );
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" );
590 if ( (aValues.size()+aOffset) > mSize )
592 exception::BulkTransferRequestedTooLarge lExc;
593 log ( lExc ,
"Requested bulk write size and offset would overflow the specified endpoint node ",
Quote ( this->getPath() ) );
599 return mHw->getClient().writeBlock ( mAddr+aOffset , aValues , mMode );
603 exception::WriteAccessDenied lExc;
604 log ( lExc ,
"Node " ,
Quote ( this->getPath() ) ,
": permissions denied write access" );
625 exception::ReadAccessDenied lExc;
626 log ( lExc ,
"Node " ,
Quote ( this->
getPath() ) ,
": permissions denied read access" );
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" );
642 if ( ( mSize != 1 ) && ( aSize>mSize ) )
644 exception::BulkTransferRequestedTooLarge lExc;
645 log ( lExc ,
"Requested bulk read of greater size than the specified endpoint size of node " ,
Quote ( this->getPath() ) );
651 return mHw->getClient().readBlock ( mAddr , aSize , mMode );
655 exception::ReadAccessDenied lExc;
656 log ( lExc ,
"Node " ,
Quote ( this->getPath() ) ,
": permissions denied read access" );
667 exception::BulkTransferOffsetRequestedForFifo lExc;
668 log ( lExc ,
"Bulk Transfer offset requested for non-incremental node " ,
Quote ( this->getPath() ) );
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" );
680 if ( (aSize+aOffset) > mSize )
682 exception::BulkTransferRequestedTooLarge lExc;
683 log ( lExc ,
"Requested bulk read size and offset would overflow the specified endpoint node " ,
Quote ( this->getPath() ) );
689 return mHw->getClient().readBlock ( mAddr+aOffset , aSize , mMode );
693 exception::ReadAccessDenied lExc;
694 log ( lExc ,
"Node " ,
Quote ( this->getPath() ) ,
": permissions denied read access" );
709 std::vector<const Node*> lAncestors;
713 if (lAncestor == NULL)
714 throw std::runtime_error(
"Node '" + aAncestor.
getPath() +
"' is not an ancestor of '" +
getPath() +
"'");
716 lAncestors.push_back(lAncestor);
717 lAncestor = lAncestor->
mParent;
719 while (lAncestors.back() != &aAncestor);
721 return std::vector<const Node*>(lAncestors.rbegin(), lAncestors.rend());
741 mBegin ( aOrig.mBegin ) ,
742 mItStack ( aOrig.mItStack )
758 return & ( value() );
764 return ( mItStack.empty() ) ? ( *mBegin ) : ( **mItStack.front() );
791 if ( mItStack.empty() )
794 if ( mBegin->mChildren.size() )
797 mItStack.push_front ( mBegin->mChildren.begin() );
807 if ( not ( **mItStack.front() ).mChildren.empty() )
810 mItStack.push_front ( ( **mItStack.front() ).mChildren.begin() );
815 while ( not mItStack.empty() )
817 if ( ++ ( mItStack.front() ) != ( ( mItStack.size() == 1 ) ? ( *mBegin ) : ( **mItStack.at(1) ) ).mChildren.end() )
824 mItStack.pop_front();
835 return ! ( *
this == aIt ) ;
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.
const_iterator & operator++()
const Node & operator*() const
virtual ~const_iterator()
const Node & value() const
bool operator!=(const const_iterator &aIt) const
bool operator==(const const_iterator &aIt) const
const Node * operator->() const
A heirarchical node for navigating heirarchical firmwares.
ClientInterface & getClient() const
Get the underlying IPbus client.
std::unordered_map< std::string, std::string > mFirmwareInfo
parameters to infer the VHDL address decoding
std::vector< Node * > mChildren
The direct children of the node.
const defs::NodePermission & getPermission() const
Return the read/write access permissions of this node.
const std::unordered_map< std::string, std::string > & getFirmwareInfo() const
Return parameters for inferring the VHDL address decoding.
ValWord< uint32_t > read() const
Read a single, unmasked, unsigned word.
const uint32_t & getMask() const
Return the mask to be applied if this node is a sub-field, rather than an entire register.
const std::string & getId() const
Return the unique ID of the current node.
uint32_t mAddr
The register address with which this node is associated.
bool isChildOf(const Node &aParent) const
Returns whether this node is child of the function's argument.
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.
void stream(std::ostream &aStr, std::size_t aIndent=0) const
A streaming helper function to create pretty, indented tree diagrams.
defs::BlockReadWriteMode mMode
Whether the node represents a single register, a block of registers or a block-read/write port.
std::vector< const Node * > getLineage(const Node &aAncestor) const
Returns ancestry path of nodes from (but not including) aAncestor to this node.
virtual Node & operator=(const Node &aNode)
Assignment operator.
uint32_t mMask
The mask to be applied if this node is a sub-field, rather than an entire register.
std::unordered_map< std::string, Node * > mChildrenMap
Helper to assist look-up of a particular child node, given a name.
const std::unordered_map< std::string, std::string > & getParameters() const
Return parameters of the current node.
const Node & getNode(const std::string &aId) const
Retrieve the Node given by a full-stop delimeted name path relative, to the current node.
const defs::BlockReadWriteMode & getMode() const
Return whether the node represents a single register, a block of registers or a block-read/write port...
std::string mUid
The Unique ID of this node.
virtual Node * clone() const
Function to produce a new copy of the current Node.
std::string getPath() const
Return the full path to the current node.
std::string mClassName
Class name used to construct the derived node type.
ValHeader writeBlock(const std::vector< uint32_t > &aValues) const
Write a block of data to a block of registers or a block-write port.
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.
ValHeader write(const uint32_t &aValue) const
Write a single, unmasked word to a register.
virtual ~Node()
Destructor.
std::string mDescription
Optional string which the user can specify.
const uint32_t & getAddress() const
Return the register address with which this node is associated.
void getAncestors(std::deque< const Node * > &aPath) const
Get the full path to the current node.
const std::string & getDescription() const
Return the optional description string which the user can specify for the current node.
const_iterator end() const
std::unordered_map< std::string, std::string > mParameters
Additional parameters of the node.
const uint32_t & getSize() const
Return the maximum size available to a block read/write.
defs::NodePermission mPermission
The read/write access permissions of this node.
std::string mModule
The name of the module in which the current node resides.
uint32_t mPartialAddr
The register address with which this node is associated.
std::string getRelativePath(const Node &aAncestor) const
bool operator==(const Node &aNode) const
A function to determine whether two Nodes are identical.
std::vector< std::string > getNodes() const
Return all node IDs known to this HwInterface.
const std::string & getTags() const
Return the optional tags string which the user can specify for the current node.
const_iterator begin() const
uint32_t mSize
The maximum size available to a block read/write.
std::string mTags
Optional string which the user can specify.
HwInterface * mHw
The parent hardware interface of which this node is a child (or rather decendent)
const std::string & getModule() const
Return the name of the module in which the current node resides.
Node * mParent
The parent of the current node.
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.
bool hasNode(const std::string &aId) const
BlockReadWriteMode
define whether transactions target a single register, a block of registers, a block-read/write port o...
NodePermission
define Read and Write permissions of a uhal Node
const uint32_t NOMASK
define what it means to have no mask
_Quote< T > Quote(const T &aT)
void log(FatalLevel &aFatal, const T0 &aArg0)
Function to add a log entry at Fatal level.
std::ostream & operator<<(std::ostream &aStr, const uhal::HttpResponseType &aHttpResponse)