37#include <boost/date_time/posix_time/posix_time.hpp>
38#include <boost/filesystem.hpp>
48 std::vector<const Node*> lMatches;
52 if ( ( aAddress >= lIt->getAddress() ) and ( aAddress < ( lIt->getAddress() + lIt->getSize() ) ) )
53 lMatches.push_back(&*lIt);
56 if ( lIt->getAddress() == aAddress )
57 lMatches.push_back(&*lIt);
61 if ( lMatches.empty() )
62 return "no matching nodes";
63 else if ( lMatches.size() == 1 )
64 return "node \"" + lMatches.front()->getPath() +
"\"";
66 const Node* lCommonAncestor = lMatches.front();
67 std::vector<const Node*> lCommonAncestorLineage = lCommonAncestor->
getLineage(aNode);
69 for ( std::vector<const Node*>::const_iterator lIt = lMatches.begin()+1; lIt != lMatches.end(); lIt++ ) {
70 const std::vector<const Node*> lLineage = (*lIt)->getLineage(aNode);
73 for ( ; i < std::min(lLineage.size(), lCommonAncestorLineage.size()); i++ ) {
74 if ( lCommonAncestorLineage.at(i) != lLineage.at(i) )
77 lCommonAncestor = lLineage.at(i - 1);
78 lCommonAncestorLineage.assign(lLineage.begin(), lLineage.begin() + i);
81 if ( (aMaxListSize != 0) and (lMatches.size() > aMaxListSize) )
83 if ( lCommonAncestor == &aNode )
84 return std::to_string(lMatches.size()) +
" nodes match";
86 return std::to_string(lMatches.size()) +
" nodes under \"" + lCommonAncestor->
getPath() +
"\" match";
90 const std::string lCommonAncestorPath(lCommonAncestor->
getPath());
91 const size_t lCommonPathLength(lCommonAncestor == &aNode ? 0 : lCommonAncestorPath.size() + 1);
92 std::ostringstream lOSS;
93 lOSS <<
"nodes \"" << lMatches.front()->getPath().substr(lCommonPathLength) <<
"\"";
94 for (
auto lIt = lMatches.begin() + 1; lIt < lMatches.end(); lIt++)
95 lOSS <<
", \"" << (*lIt)->getPath().substr(lCommonPathLength) <<
"\"";
97 if (lCommonAncestor != &aNode)
98 lOSS <<
" under \"" << lCommonAncestorPath <<
"\"";
107 if ( std::shared_ptr<Node> lNode = aClient.
mNode.lock() )
122 std::vector<const Node*> lNodes;
124 lNodes.push_back(&*lIt);
127 std::vector<std::pair<const Node*, const Node*> > lOverlappingNodes;
128 if (lNodes.size() < 2)
129 return lOverlappingNodes;
131 for (std::vector<const Node*>::const_iterator lIt1 = lNodes.begin() ; lIt1 != (lNodes.end() - 1); lIt1++)
133 const Node& lNode1 = **lIt1;
139 for (std::vector<const Node*>::const_iterator lIt2(lIt1 + 1) ; (lIt2 != lNodes.end()) and (*lIt2)->getAddress() <= lMaxAddr1; lIt2++)
144 const Node& lNode2 = **lIt2;
147 lOverlappingNodes.push_back( std::make_pair(&lNode1, &lNode2) );
160 lOverlappingNodes.push_back( std::make_pair(&lNode1, &lNode2) );
165 return lOverlappingNodes;
171 std::ios_base::fmtflags lInitialFlags = aStream.flags();
172 char lInitialFillChar = aStream.fill(
'0');
175 aStream <<
"Node '" << aNode1.
getPath() <<
"' [";
177 aStream <<
"addresses 0x" << std::setw ( 8 ) << aNode1.
getAddress() <<
" - 0x" << std::setw ( 8 ) << aNode1.
getAddress() + aNode1.
getSize() - 1;
179 aStream <<
"address 0x" << std::setw ( 8 ) << aNode1.
getAddress();
181 aStream <<
"address 0x" << std::setw ( 8 ) << aNode1.
getAddress() <<
", mask 0x" << std::setw ( 8 ) << aNode1.
getMask();
183 aStream <<
"] overlaps with '" << aNode2.
getPath() <<
"' [";
185 aStream <<
"addresses 0x" << std::setw ( 8 ) << aNode2.
getAddress() <<
" - 0x" << std::setw ( 8 ) << aNode2.
getAddress() + aNode2.
getSize() - 1;
187 aStream <<
"address 0x" << std::setw ( 8 ) << aNode2.
getAddress();
189 aStream <<
"address 0x" << std::setw ( 8 ) << aNode2.
getAddress() <<
", mask 0x" << std::setw ( 8 ) << aNode2.
getMask();
192 aStream.flags(lInitialFlags);
193 aStream.fill(lInitialFillChar);
197 bool writeNodeOverlapReport(
const std::string& aFilePath,
const std::vector<std::pair<const Node*, const Node*> >& aNodes,
const std::string& aHeader)
200 std::stringstream lReport;
201 lReport << std::hex << std::setfill (
'0' );
203 for (
const auto& x: aNodes)
206 lReport << std::endl;
210 const bool lNewlyCreatedFile = not boost::filesystem::is_regular_file( boost::filesystem::path(aFilePath) );
211 std::ofstream lReportFile ( aFilePath.c_str() );
213 if ( lReportFile.is_open() )
215 lReportFile << aHeader << std::endl;
216 lReportFile <<
"Written at " << boost::posix_time::microsec_clock::local_time() <<
"." << std::endl;
217 lReportFile << std::endl;
218 lReportFile << lReport.rdbuf();
221 if ( lNewlyCreatedFile )
223 boost::filesystem::permissions( aFilePath , boost::filesystem::perms( 0666 ) );
An abstract base class for defining the interface to the various IPbus clients as well as providing t...
std::weak_ptr< Node > mNode
A heirarchical node for navigating heirarchical firmwares.
const uint32_t & getMask() const
Return the mask to be applied if this node is a sub-field, rather than an entire register.
bool isChildOf(const Node &aParent) const
Returns whether this node is child of the function's argument.
std::vector< const Node * > getLineage(const Node &aAncestor) const
Returns ancestry path of nodes from (but not including) aAncestor to this 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 getPath() const
Return the full path to the current node.
const uint32_t & getAddress() const
Return the register address with which this node is associated.
const_iterator end() const
const uint32_t & getSize() const
Return the maximum size available to a block read/write.
const_iterator begin() const
const uint32_t NOMASK
define what it means to have no mask
bool writeNodeOverlapReport(const std::string &aFilePath, const std::vector< std::pair< const Node *, const Node * > > &aNodes, const std::string &aHeader)
std::string getAddressDescription(const ClientInterface &, const uint32_t, const size_t &)
Generates a short string summarising which nodes match the specified address.
bool compareNodeAddr(const Node *aNodeL, const Node *aNodeR)
void printNodeOverlapDescription(std::ostream &aStream, const Node &aNode1, const Node &aNode2)
std::vector< std::pair< const Node *, const Node * > > getAddressOverlaps(const Node &aNode)