μHAL (v2.7.9)
Part of the IPbus software repository
utilities.cpp
Go to the documentation of this file.
1 
2 /*
3 ---------------------------------------------------------------------------
4 
5  This file is part of uHAL.
6 
7  uHAL is a hardware access library and programming framework
8  originally developed for upgrades of the Level-1 trigger of the CMS
9  experiment at CERN.
10 
11  uHAL is free software: you can redistribute it and/or modify
12  it under the terms of the GNU General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  uHAL is distributed in the hope that it will be useful,
17  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  GNU General Public License for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with uHAL. If not, see <http://www.gnu.org/licenses/>.
23 
24  Tom Williams, Rutherford Appleton Laboratory, Oxfordshire
25  email: tom.williams <AT> cern.ch
26 
27 ---------------------------------------------------------------------------
28 */
29 
31 
32 
33 #include <fstream>
34 #include <iomanip>
35 
36 #include <boost/date_time/posix_time/posix_time.hpp>
37 #include <boost/filesystem.hpp>
38 #include "boost/lexical_cast.hpp"
39 #include "boost/shared_ptr.hpp"
40 
41 #include "uhal/Node.hpp"
42 
43 
44 namespace uhal {
45  namespace detail {
46 
47  std::string getAddressDescription(const Node& aNode, const uint32_t aAddress, const size_t& aMaxListSize)
48  {
49  std::vector<const Node*> lMatches;
50  for ( Node::const_iterator lIt = aNode.begin(); lIt != aNode.end(); lIt++ ) {
51 
52  if ( lIt->getMode() == uhal::defs::INCREMENTAL ) {
53  if ( ( aAddress >= lIt->getAddress() ) and ( aAddress < ( lIt->getAddress() + lIt->getSize() ) ) )
54  lMatches.push_back(&*lIt);
55  }
56  else if ( lIt->getMode() != uhal::defs::HIERARCHICAL ) {
57  if ( lIt->getAddress() == aAddress )
58  lMatches.push_back(&*lIt);
59  }
60  }
61 
62  if ( lMatches.empty() )
63  return "no matching nodes";
64  else if ( lMatches.size() == 1 )
65  return "node \"" + lMatches.front()->getPath() + "\"";
66 
67  const Node* lCommonAncestor = lMatches.front();
68  std::vector<const Node*> lCommonAncestorLineage = lCommonAncestor->getLineage(aNode);
69 
70  for ( std::vector<const Node*>::const_iterator lIt = lMatches.begin()+1; lIt != lMatches.end(); lIt++ ) {
71  const std::vector<const Node*> lLineage = (*lIt)->getLineage(aNode);
72 
73  size_t i = 0;
74  for ( ; i < std::min(lLineage.size(), lCommonAncestorLineage.size()); i++ ) {
75  if ( lCommonAncestorLineage.at(i) != lLineage.at(i) )
76  break;
77  }
78  lCommonAncestor = lLineage.at(i - 1);
79  lCommonAncestorLineage.assign(lLineage.begin(), lLineage.begin() + i);
80  }
81 
82  if ( (aMaxListSize != 0) and (lMatches.size() > aMaxListSize) )
83  {
84  if ( lCommonAncestor == &aNode )
85  return boost::lexical_cast<std::string>(lMatches.size()) + " nodes match";
86  else
87  return boost::lexical_cast<std::string>(lMatches.size()) + " nodes under \"" + lCommonAncestor->getPath() + "\" match";
88  }
89  else
90  {
91  const std::string lCommonAncestorPath(lCommonAncestor->getPath());
92  const size_t lCommonPathLength(lCommonAncestor == &aNode ? 0 : lCommonAncestorPath.size() + 1);
93  std::ostringstream lOSS;
94  lOSS << "nodes \"" << lMatches.front()->getPath().substr(lCommonPathLength) << "\"";
95  for (std::vector<const Node*>::const_iterator lIt = lMatches.begin() + 1; lIt < lMatches.end(); lIt++)
96  lOSS << ", \"" << (*lIt)->getPath().substr(lCommonPathLength) << "\"";
97 
98  if (lCommonAncestor != &aNode)
99  lOSS << " under \"" << lCommonAncestorPath << "\"";
100 
101  return lOSS.str();
102  }
103  }
104 
105 
106  std::string getAddressDescription(const ClientInterface& aClient, const uint32_t aAddress, const size_t& aMaxListSize)
107  {
108  if ( boost::shared_ptr<Node> lNode = aClient.mNode.lock() )
109  return getAddressDescription(*lNode, aAddress, aMaxListSize);
110  else
111  return "";
112  }
113 
114 
115  bool compareNodeAddr ( const Node* aNodeL, const Node* aNodeR )
116  {
117  return ( aNodeL->getAddress() < aNodeR->getAddress() );
118  }
119 
120 
121  std::vector<std::pair<const Node*, const Node*> > getAddressOverlaps(const Node& aNode)
122  {
123  std::vector<const Node*> lNodes;
124  for (Node::const_iterator lIt = aNode.begin() ; lIt.next() ; )
125  lNodes.push_back(&*lIt);
126  std::stable_sort ( lNodes.begin() , lNodes.end() , compareNodeAddr );
127 
128  std::vector<std::pair<const Node*, const Node*> > lOverlappingNodes;
129  if (lNodes.size() < 2)
130  return lOverlappingNodes;
131 
132  for (std::vector<const Node*>::const_iterator lIt1 = lNodes.begin() ; lIt1 != (lNodes.end() - 1); lIt1++)
133  {
134  const Node& lNode1 = **lIt1;
135  if (lNode1.getMode() == defs::HIERARCHICAL)
136  continue;
137 
138  const uint32_t lMaxAddr1(lNode1.getMode() == defs::INCREMENTAL ? lNode1.getAddress() + lNode1.getSize() - 1 : lNode1.getAddress());
139 
140  for (std::vector<const Node*>::const_iterator lIt2(lIt1 + 1) ; (lIt2 != lNodes.end()) and (*lIt2)->getAddress() <= lMaxAddr1; lIt2++)
141  {
142  if ((*lIt2)->getMode() == defs::HIERARCHICAL)
143  continue;
144 
145  const Node& lNode2 = **lIt2;
146 
147  if (lNode1.getMode() != defs::SINGLE or lNode2.getMode() != defs::SINGLE)
148  lOverlappingNodes.push_back( std::make_pair(&lNode1, &lNode2) );
149 
150  else if (lNode1.getMask() & lNode2.getMask())
151  {
152  if (lNode1.getMask() == defs::NOMASK and lNode2.isChildOf(lNode1))
153  {
154  // Node 2 is masked child of node 1: No overlap
155  }
156  else if (lNode2.getMask() == defs::NOMASK and lNode1.isChildOf(lNode2))
157  {
158  // Node 1 is masked child of node 2: No overlap
159  }
160  else
161  lOverlappingNodes.push_back( std::make_pair(&lNode1, &lNode2) );
162  }
163  }
164  }
165 
166  return lOverlappingNodes;
167  }
168 
169 
170  void printNodeOverlapDescription(std::ostream& aStream, const Node& aNode1, const Node& aNode2)
171  {
172  std::ios_base::fmtflags lInitialFlags = aStream.flags();
173  char lInitialFillChar = aStream.fill('0');
174  aStream << std::hex;
175 
176  aStream << "Node '" << aNode1.getPath() << "' [";
177  if (aNode1.getMode() == defs::INCREMENTAL)
178  aStream << "addresses 0x" << std::setw ( 8 ) << aNode1.getAddress() << " - 0x" << std::setw ( 8 ) << aNode1.getAddress() + aNode1.getSize() - 1;
179  else if ( aNode2.getMode() == defs::INCREMENTAL )
180  aStream << "address 0x" << std::setw ( 8 ) << aNode1.getAddress();
181  else
182  aStream << "address 0x" << std::setw ( 8 ) << aNode1.getAddress() << ", mask 0x" << std::setw ( 8 ) << aNode1.getMask();
183 
184  aStream << "] overlaps with '" << aNode2.getPath() << "' [";
185  if (aNode2.getMode() == defs::INCREMENTAL)
186  aStream << "addresses 0x" << std::setw ( 8 ) << aNode2.getAddress() << " - 0x" << std::setw ( 8 ) << aNode2.getAddress() + aNode2.getSize() - 1;
187  else if ( aNode1.getMode() == defs::INCREMENTAL )
188  aStream << "address 0x" << std::setw ( 8 ) << aNode2.getAddress();
189  else
190  aStream << "address 0x" << std::setw ( 8 ) << aNode2.getAddress() << ", mask 0x" << std::setw ( 8 ) << aNode2.getMask();
191  aStream << "].";
192 
193  aStream.flags(lInitialFlags);
194  aStream.fill(lInitialFillChar);
195  }
196 
197 
198  bool writeNodeOverlapReport(const std::string& aFilePath, const std::vector<std::pair<const Node*, const Node*> >& aNodes, const std::string& aHeader)
199  {
200  // 1. Create main contents of report
201  std::stringstream lReport;
202  lReport << std::hex << std::setfill ( '0' );
203 
204  for (std::vector<std::pair<const Node*, const Node*> >::const_iterator lIt = aNodes.begin(); lIt != aNodes.end(); lIt++)
205  {
206  printNodeOverlapDescription(lReport, *lIt->first, *lIt->second);
207  lReport << std::endl;
208  }
209 
210  // 2. Write report to file
211  const bool lNewlyCreatedFile = not boost::filesystem::is_regular_file( boost::filesystem::path(aFilePath) );
212  std::ofstream lReportFile ( aFilePath.c_str() );
213 
214  if ( lReportFile.is_open() )
215  {
216  lReportFile << aHeader << std::endl;
217  lReportFile << "Written at " << boost::posix_time::microsec_clock::local_time() << "." << std::endl;
218  lReportFile << std::endl;
219  lReportFile << lReport.rdbuf();
220  lReportFile.close();
221 
222  if ( lNewlyCreatedFile )
223  {
224  boost::filesystem::permissions( aFilePath , boost::filesystem::perms( 0666 ) );
225  }
226 
227  return true;
228  }
229  else
230  return false;
231  }
232 
233  }
234 }
uhal::detail::compareNodeAddr
bool compareNodeAddr(const Node *aNodeL, const Node *aNodeR)
Definition: utilities.cpp:115
boost::shared_ptr
Definition: DerivedNodeFactory.hpp:52
uhal::Node::isChildOf
bool isChildOf(const Node &aParent) const
Returns whether this node is child of the function's argument.
Definition: Node.cpp:698
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::begin
const_iterator begin() const
Definition: Node.cpp:174
uhal::min
@ min
minutes past the hour formatted as two digits e.g.
Definition: log_inserters.time.hpp:63
uhal::Node::getAddress
const uint32_t & getAddress() const
Return the register address with which this node is associated.
Definition: Node.cpp:260
uhal::Node::getSize
const uint32_t & getSize() const
Return the maximum size available to a block read/write.
Definition: Node.cpp:278
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
A heirarchical node for navigating heirarchical firmwares.
Definition: Node.hpp:86
uhal::detail::getAddressOverlaps
std::vector< std::pair< const Node *, const Node * > > getAddressOverlaps(const Node &aNode)
Definition: utilities.cpp:121
uhal::Node::const_iterator::next
bool next()
Definition: Node.cpp:757
uhal::hex
@ hex
Hexadecimal.
Definition: log_inserters.integer.hpp:51
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::INCREMENTAL
@ INCREMENTAL
Definition: definitions.hpp:53
uhal::Node::getPath
std::string getPath() const
Return the full path to the current node.
Definition: Node.cpp:201
uhal::detail::printNodeOverlapDescription
void printNodeOverlapDescription(std::ostream &aStream, const Node &aNode1, const Node &aNode2)
Definition: utilities.cpp:170
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::detail::writeNodeOverlapReport
bool writeNodeOverlapReport(const std::string &aFilePath, const std::vector< std::pair< const Node *, const Node * > > &aNodes, const std::string &aHeader)
Definition: utilities.cpp:198
uhal::Node::const_iterator
Definition: Node.hpp:94
uhal::detail::getAddressDescription
std::string getAddressDescription(const ClientInterface &, const uint32_t, const size_t &)
Generates a short string summarising which nodes match the specified address.
Definition: utilities.cpp:106
uhal::defs::NOMASK
const uint32_t NOMASK
define what it means to have no mask
Definition: definitions.hpp:56
utilities.hpp
uhal::ClientInterface::mNode
boost::weak_ptr< Node > mNode
Definition: ClientInterface.hpp:415
uhal::defs::SINGLE
@ SINGLE
Definition: definitions.hpp:53