35 #include "uhal/log/log.hpp" 40 #include <boost/regex.hpp> 67 mPartialAddr ( 0x00000000 ),
105 for ( std::deque< Node* >::const_iterator lIt = aNode.
mChildren.begin(); lIt != aNode.
mChildren.end(); ++lIt )
107 mChildren.push_back ( ( **lIt ).clone() );
110 for ( std::deque< Node* >::iterator lIt =
mChildren.begin(); lIt !=
mChildren.end(); ++lIt )
112 ( **lIt ).mParent =
this;
113 mChildrenMap.insert ( std::make_pair ( ( **lIt ).mUid , *lIt ) );
115 for ( boost::unordered_map< std::string , Node* >::iterator lSubMapIt = ( **lIt ).mChildrenMap.begin() ; lSubMapIt != ( **lIt ).mChildrenMap.end() ; ++lSubMapIt )
117 mChildrenMap.insert ( std::make_pair ( ( ( **lIt ).mUid ) +
'.'+ ( lSubMapIt->first ) , lSubMapIt->second ) );
141 for ( std::deque< Node* >::iterator lIt =
mChildren.begin(); lIt !=
mChildren.end(); ++lIt )
153 for ( std::deque< Node* >::const_iterator lIt = aNode.
mChildren.begin(); lIt != aNode.
mChildren.end(); ++lIt )
155 mChildren.push_back ( ( **lIt ).clone() );
158 for ( std::deque< Node* >::iterator lIt =
mChildren.begin(); lIt !=
mChildren.end(); ++lIt )
160 ( **lIt ).mParent =
this;
161 mChildrenMap.insert ( std::make_pair ( ( **lIt ).mUid , *lIt ) );
163 for ( boost::unordered_map< std::string , Node* >::iterator lSubMapIt = ( **lIt ).mChildrenMap.begin() ; lSubMapIt != ( **lIt ).mChildrenMap.end() ; ++lSubMapIt )
165 mChildrenMap.insert ( std::make_pair ( ( ( **lIt ).mUid ) +
'.'+ ( lSubMapIt->first ) , lSubMapIt->second ) );
175 return new Node ( *
this );
183 for ( std::deque< Node* >::iterator lIt =
mChildren.begin(); lIt !=
mChildren.end(); ++lIt )
228 std::deque< const Node* > lPath;
232 for ( std::deque< const Node* >::iterator lIt ( lPath.begin() ) ; lIt != lPath.end() ; ++lIt )
234 if ( ( **lIt ).mUid.size() )
236 lRet += ( **lIt ).mUid;
243 lRet.resize ( lRet.size() - 1 );
252 aPath.push_front (
this );
316 std::ios_base::fmtflags original_flags = std::cout.flags();
318 aStr << std::setfill (
'0' ) << std::uppercase;
319 aStr <<
'\n' << std::string ( aIndent ,
' ' ) <<
"+ ";
320 aStr <<
"Node \"" <<
mUid <<
"\", ";
322 if ( &
typeid ( *
this ) != &
typeid (
Node ) )
324 aStr <<
"of type \"";
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 ) );
332 aStr <<
typeid ( *this ).name();
340 aStr <<
"SINGLE register, " 341 <<
std::hex <<
"Address 0x" << std::setw ( 8 ) <<
mAddr <<
", " 346 aStr <<
"INCREMENTAL block, " 348 <<
std::hex <<
"Addresses [0x" << std::setw ( 8 ) <<
mAddr <<
"-" << std::setw ( 8 ) << (
mAddr+
mSize-1 ) <<
"], " 352 aStr <<
"NON-INCREMENTAL block, ";
359 aStr <<
std::hex <<
"Address 0x" << std::setw ( 8 ) <<
mAddr <<
", " 363 aStr <<
std::hex <<
"Address 0x" << std::setw ( 8 ) <<
mAddr;
369 aStr <<
", Tags \"" <<
mTags <<
"\"";
379 aStr <<
", Module \"" <<
mModule <<
"\"";
384 aStr <<
", Class Name \"" <<
mClassName <<
"\"";
389 aStr <<
", Parameters: ";
390 boost::unordered_map<std::string, std::string>::const_iterator lIt;
394 aStr << lIt->first <<
"=" << lIt->second <<
";";
399 aStr.flags(original_flags);
402 for ( std::deque< Node* >::const_iterator lIt =
mChildren.begin(); lIt !=
mChildren.end(); ++lIt )
404 ( **lIt ).stream ( aStr , aIndent+2 );
410 if ( aId.size() == 0 )
415 boost::unordered_map< std::string , Node* >::const_iterator lIt =
mChildrenMap.find ( aId );
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 );
426 lPos = aId.rfind (
'.' , lPos );
428 if ( lPos == std::string::npos )
433 boost::unordered_map< std::string , Node* >::const_iterator lIt =
mChildrenMap.find ( aId.substr ( 0 , lPos ) );
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;
446 if ( !lPartialMatch )
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 );
455 return * ( lIt->second );
461 std::vector<std::string> lNodes;
464 for ( boost::unordered_map< std::string , Node* >::const_iterator lIt =
mChildrenMap.begin(); lIt !=
mChildrenMap.end(); ++lIt )
466 lNodes.push_back ( lIt->first );
474 std::vector<std::string> lNodes;
476 log (
Info() ,
"Regular Expression : " , aRegex );
478 for ( boost::unordered_map< std::string , Node* >::const_iterator lIt =
mChildrenMap.begin(); lIt !=
mChildrenMap.end(); ++lIt )
480 boost::cmatch lMatch;
482 if ( boost::regex_match ( lIt->first.c_str() , lMatch , boost::regex ( aRegex ) ) )
484 log (
Info() , lIt->first ,
" matches" );
485 lNodes.push_back ( lIt->first );
490 std::sort ( lNodes.begin(), lNodes.end() );
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." );
514 exception::WriteAccessDenied lExc;
515 log ( lExc ,
"Node " ,
Quote ( this->
getPath() ) ,
": permissions denied write access" );
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" );
530 if ( (
mSize != 1 ) && ( aValues.size() >
mSize ) )
532 exception::BulkTransferRequestedTooLarge lExc;
533 log ( lExc ,
"Requested bulk write of greater size than the specified endpoint size of node ",
Quote ( this->
getPath() ) );
543 exception::WriteAccessDenied lExc;
544 log ( lExc ,
"Node " ,
Quote ( this->
getPath() ) ,
": permissions denied write access" );
555 exception::BulkTransferOffsetRequestedForFifo lExc;
556 log ( lExc ,
"Bulk Transfer Offset requested for non-incremental node " ,
Quote ( this->
getPath() ) );
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" );
568 if ( (aValues.size()+aOffset) >
mSize )
570 exception::BulkTransferRequestedTooLarge lExc;
571 log ( lExc ,
"Requested bulk write size and offset would overflow the specified endpoint node ",
Quote ( this->
getPath() ) );
581 exception::WriteAccessDenied lExc;
582 log ( lExc ,
"Node " ,
Quote ( this->
getPath() ) ,
": permissions denied write access" );
603 exception::ReadAccessDenied lExc;
604 log ( lExc ,
"Node " ,
Quote ( this->
getPath() ) ,
": permissions denied read access" );
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" );
622 exception::BulkTransferRequestedTooLarge lExc;
623 log ( lExc ,
"Requested bulk read of greater size than the specified endpoint size of node " ,
Quote ( this->
getPath() ) );
633 exception::ReadAccessDenied lExc;
634 log ( lExc ,
"Node " ,
Quote ( this->
getPath() ) ,
": permissions denied read access" );
645 exception::BulkTransferOffsetRequestedForFifo lExc;
646 log ( lExc ,
"Bulk Transfer offset requested for non-incremental node " ,
Quote ( this->
getPath() ) );
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" );
658 if ( (aSize+aOffset) >
mSize )
660 exception::BulkTransferRequestedTooLarge lExc;
661 log ( lExc ,
"Requested bulk read size and offset would overflow the specified endpoint node " ,
Quote ( this->
getPath() ) );
671 exception::ReadAccessDenied lExc;
672 log ( lExc ,
"Node " ,
Quote ( this->
getPath() ) ,
": permissions denied read access" );
828 return & (
value() );
875 if ( ( **
mItStack[0] ).mChildren.size() )
903 return ! ( *
this == aIt ) ;
boost::unordered_map< std::string, std::string > mFirmwareInfo
parameters to infer the VHDL address decoding
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.
HwInterface * mHw
The parent hardware interface of which this node is a child (or rather decendent) ...
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.
bool operator!=(const const_iterator &aIt) const
const std::string & getId() const
Return the unique ID of the current node.
std::string mClassName
Class name used to construct the derived node type.
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 getPath() const
Return the full path to the current node.
const std::string & getModule() const
Return the name of the module in which the current node resides.
const uint32_t & getAddress() const
Return the register address with which this node is associated.
const std::string & getTags() const
Return the optional tags string which the user can specify for the current node.
void getAncestors(std::deque< const Node * > &aPath) const
Get the full path to the current node.
const uint32_t & getMask() const
Return the mask to be applied if this node is a sub-field, rather than an entire register.
virtual Node * clone() const
Function to produce a new copy of the current Node.
defs::NodePermission mPermission
The read/write access permissions of this node.
bool operator==(const const_iterator &aIt) const
const std::string & getDescription() const
Return the optional description string which the user can specify for the current node...
const uint32_t & getSize() const
Return the maximum size available to a block read/write.
const_iterator end() const
defs::BlockReadWriteMode mMode
Whether the node represents a single register, a block of registers or a block-read/write port...
std::string mTags
Optional string which the user can specify.
virtual ~const_iterator()
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.
bool operator==(const Node &aNode) const
A function to determine whether two Nodes are identical.
uint32_t mSize
The maximum size available to a block read/write.
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.
const uint32_t NOMASK
define what it means to have no mask
virtual ~Node()
Destructor.
const_iterator begin() const
std::string mModule
The name of the module in which the current node resides.
boost::unordered_map< std::string, std::string > mParameters
Additional parameters of the node.
uint32_t mPartialAddr
The register address with which this node is associated.
uint32_t mMask
The mask to be applied if this node is a sub-field, rather than an entire register.
ValHeader write(const uint32_t &aValue) const
Write a single, unmasked word to a register.
A heirarchical node for navigating heirarchical firmwares.
_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.
std::deque< Node *> mChildren
The direct children of the 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...
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.
virtual Node & operator=(const Node &aNode)
Assignment operator.
const Node & value() const
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.
An abstract base class for defining the interface to the various IPbus clients as well as providing t...
const Node & operator*() const
std::string mUid
The Unique ID of this node.
NodePermission
define Read and Write permissions of a uhal Node
const boost::unordered_map< std::string, std::string > & getParameters() const
Return parameters of the current node.
Node * mParent
The parent of the current node.
BlockReadWriteMode
define whether transactions target a single register, a block of registers, a block-read/write port o...
void stream(std::ostream &aStr, std::size_t aIndent=0) const
A streaming helper function to create pretty, indented tree diagrams.
boost::unordered_map< std::string, Node *> mChildrenMap
Helper to assist look-up of a particular child node, given a name.
const defs::NodePermission & getPermission() const
Return the read/write access permissions of this node.
const Node * operator->() const
const_iterator & operator++()
ValWord< uint32_t > read() const
Read a single, unmasked, unsigned word.
const boost::unordered_map< std::string, std::string > & getFirmwareInfo() const
Return parameters for inferring the VHDL address decoding.
ClientInterface & getClient() const
Get the underlying IPbus client.
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.