|
μHAL (v2.7.9)
Part of the IPbus software repository
|
Go to the documentation of this file.
36 #include <boost/bind.hpp>
37 #include <boost/chrono/chrono_io.hpp>
38 #include <boost/chrono/system_clocks.hpp>
39 #include <boost/spirit/include/qi.hpp>
40 #include <boost/date_time/posix_time/posix_time.hpp>
41 #include <boost/algorithm/string/replace.hpp>
42 #include <boost/filesystem.hpp>
51 #if BOOST_VERSION >= 106000
53 using boost::placeholders::_1;
54 using boost::placeholders::_2;
55 using boost::placeholders::_3;
157 std::vector< std::pair<std::string, std::string> > lAddressFiles;
160 if ( lAddressFiles.size() != 1 )
162 exception::IncorrectAddressTableFileCount lExc;
163 log ( lExc ,
"Exactly one address table file must be specified. The expression " ,
Quote ( aFilenameExpr ) ,
" contains " ,
Integer ( lAddressFiles.size() ) ,
" valid file expressions." );
167 std::vector< const Node* > lNodes;
170 if ( lNodes.size() != 1 )
172 exception::IncorrectAddressTableFileCount lExc;
173 log ( lExc ,
"Exactly one address table file must be specified. The expression " ,
Quote ( lAddressFiles[0].second ) ,
" refers to " ,
Integer ( lNodes.size() ) ,
" valid files." );
177 Node* lNode ( lNodes[0]->clone() );
184 for(boost::unordered_map<std::string, const Node*>::const_iterator it=
mNodes.begin(); it !=
mNodes.end(); it++)
204 void NodeTreeBuilder::CallBack (
const std::string& aProtocol ,
const boost::filesystem::path& aPath , std::vector<uint8_t>& aFile , std::vector< const Node* >& aNodes )
206 std::string lName ( aProtocol + ( aPath.string() ) );
207 boost::unordered_map< std::string , const Node* >::iterator lNodeIt =
mNodes.find ( lName );
209 if ( lNodeIt !=
mNodes.end() )
211 aNodes.push_back ( lNodeIt->second );
215 std::string lExtension ( aPath.extension().string().substr ( 0,4 ) );
216 boost::to_lower ( lExtension );
218 if ( lExtension ==
".xml" )
220 log (
Info() ,
"Reading XML address file " ,
Quote( aPath.c_str() ) );
234 log (
Error() ,
"No XML node called ",
Quote (
"node" ) ,
" in file " , aPath.c_str() );
238 Node* lNode (
build ( lXmlNode , aPath ) );
239 mNodes.insert ( std::make_pair ( lName , lNode ) );
240 aNodes.push_back ( lNode );
243 else if ( lExtension ==
".txt" )
246 log (
Error() ,
"Parser problems mean that this method has been disabled." );
251 log (
Error() ,
"Extension " ,
Quote ( lExtension ) ,
" not known." );
260 setUid ( aRequireId , aXmlNode , lNode );
272 log (
Debug() , lNode->
mUid ,
" built by " , __PRETTY_FUNCTION__ );
289 setUid ( aRequireId , aXmlNode , lNode );
301 log (
Debug() , lNode->
mUid ,
" built by " , __PRETTY_FUNCTION__ );
316 if ( aXmlNode.
child (
"node" ) )
318 exception::MaskedNodeCannotHaveChild lExc;
319 log ( lExc ,
"Bit-masked nodes are not allowed to have child nodes" );
324 setUid ( aRequireId , aXmlNode , lNode );
336 log (
Debug() , lNode->
mUid ,
" built by " , __PRETTY_FUNCTION__ );
347 if ( aRequireId and ( not lHasId ) )
350 throw exception::NodeMustHaveUID(
"'id' attribute is missing from address table node");
355 if ( aNode->
mUid.empty() )
356 throw exception::NodeAttributeIncorrectValue(
"Invalid node ID specified (empty)");
357 else if ( aNode->
mUid.find(
'.') != std::string::npos )
358 throw exception::NodeAttributeIncorrectValue(
"Invalid node ID '" + aNode->
mUid +
"' specified (contains dots)");
359 else if ( ( aNode->
mUid.at(0) ==
' ' ) or ( aNode->
mUid.at(aNode->
mUid.size()-1) ==
' ' ) )
360 throw exception::NodeAttributeIncorrectValue(
"Invalid node ID '" + aNode->
mUid +
"' specified (contains spaces)");
367 uint32_t lAddr ( 0 );
376 std::string lClassStr;
384 std::string lParsStr;
388 if ( lParsStr.size() )
391 std::string::const_iterator lBegin ( lParsStr.begin() );
392 std::string::const_iterator lEnd ( lParsStr.end() );
393 boost::unordered_map<std::string, std::string> lPars;
409 if ( lStr.size() && aNode->
mTags.size() )
412 aNode->
mTags += lStr;
415 else if ( lStr.size() && !aNode->
mTags.size() )
451 std::string lPermissionAttr;
456 if (lPermission == NULL)
458 throw exception::NodeAttributeIncorrectValue(
"Permission attribute for node with ID '" + aNode->
mUid +
"' has incorrect value '" + lPermissionAttr +
"'");
476 std::string lModeAttr;
483 throw exception::NodeAttributeIncorrectValue(
"Mode attribute for node with ID '" + aNode->
mUid +
"' has incorrect value '" + lModeAttr +
"'");
486 aNode->
mMode = *lMode;
493 exception::IncrementalNodeRequiresSizeAttribute lExc;
503 log (
Notice() ,
"Node " ,
Quote ( aNode->
mUid ) ,
" has type " ,
Quote (
"NON_INCREMENTAL" ) ,
" but does not have a " ,
Quote (
NodeTreeBuilder::mSizeAttribute ) ,
" attribute. This is not necessarily a problem, but if there is a limit to the size of the read/write operation from this port, then please consider adding this attribute for the sake of safety." );
509 log (
Warning() ,
"Invalid combination of attributes for node " ,
Quote ( aNode->
mUid ) ,
": Size attribute specified, but mode missing, hence size ignored. Please specify mode here or remove the size attribute. Address table parser will throw an exception for this in future releases.");
517 std::string lFwInfoStr;
520 if ( lFwInfoStr.size() )
523 std::string::const_iterator lBegin ( lFwInfoStr.begin() );
524 std::string::const_iterator lEnd ( lFwInfoStr.end() );
545 exception::BlockAccessNodeCannotHaveChild lExc;
546 log ( lExc ,
"Block access nodes are not allowed to have child nodes, but the node " ,
Quote ( aNode->
mUid ) ,
" has a child node in the address table" );
552 for ( ; lXmlNode; lXmlNode = lXmlNode.
next_sibling (
"node" ) )
557 for ( std::vector< Node* >::iterator lIt = aNode->
mChildren.begin(); lIt != aNode->
mChildren.end(); ++lIt )
559 aNode->
mChildrenMap.insert ( std::make_pair ( ( **lIt ).mUid , *lIt ) );
575 bool lAllMasked (
true );
577 for ( std::vector< Node* >::iterator lIt = aNode->
mChildren.begin(); lIt != aNode->
mChildren.end(); ++lIt )
605 uint64_t lTopAddr ( ( uint64_t ) ( aNode->
mPartialAddr ) + ( uint64_t ) ( aNode->
mSize-1 ) );
608 if ( lTopAddr >> 32 )
610 exception::ArraySizeExceedsRegisterBound lExc;
635 for ( std::vector< Node* >::iterator lIt = aNode->
mChildren.begin(); lIt != aNode->
mChildren.end(); ++lIt )
637 ( **lIt ).mParent = aNode;
649 if ( not lOverlappingNodes.empty() )
652 std::string lDirName(
"/tmp");
653 if (
char* lUsername = std::getenv(
"USER"))
655 lDirName +=
"/" + std::string(lUsername);
659 boost::filesystem::path lDir ( lDirName );
660 lDir.make_preferred();
663 if ( !boost::filesystem::is_directory ( lDir ) )
665 if ( boost::filesystem::create_directories ( lDir ) )
667 boost::filesystem::permissions( lDir , boost::filesystem::all_all );
671 log (
Error() ,
"Address overlaps observed - attempted and failed to create directory " ,
Quote ( lDirName ) );
677 catch(
const boost::filesystem::filesystem_error& e)
679 log (
Error() ,
"Address overlaps observed - failed to create directory " ,
Quote ( lDirName ) ,
" for report file; caught filesystem_error exception with what returning: ", e.what() );
683 std::string lFilename ( aPath.string() );
684 boost::replace_all ( lFilename ,
"/" ,
"-" );
685 const std::string lReportPath( ( lDir / (
"OverlapReport" + lFilename +
".txt" ) ).
string() );
689 log (
Warning() ,
"Address overlaps observed - report file written at " ,
Quote ( lReportPath ) );
693 log (
Error() ,
"Address overlaps observed - failed to create report file " ,
Quote ( lReportPath ) );
void setPermissions(const pugi::xml_node &aXmlNode, Node *aNode)
std::string mTags
Optional string which the user can specify.
static const std::string mAddressAttribute
bool compareNodeAddr(const Node *aNodeL, const Node *aNodeR)
NodeTreeBuilder()
Default constructor This is private since only a single instance is to be created,...
A look-up table that the boost qi parser uses for associating strings ("single","block",...
Struct to store the name and member variables within a node endpoint attribute when parsed by boost s...
std::string mModule
The name of the module in which the current node resides.
static const std::string mClassAttribute
NodePermission
define Read and Write permissions of a uhal Node
void setMask(const pugi::xml_node &aXmlNode, Node *aNode)
void CallBack(const std::string &aProtocol, const boost::filesystem::path &aPath, std::vector< uint8_t > &aFile, std::vector< const Node * > &aAddressTable)
Method called once the file specified in the call to getNodeTree( aFilenameExpr ) has been opened.
uint32_t mAddr
The register address with which this node is associated.
boost::unordered_map< std::string, std::string > mFirmwareInfo
parameters to infer the VHDL address decoding
permissions_lut()
The actual function that the boost qi parser uses for associating strings with enumerated permissions...
std::string mType
The endpoint type.
std::string mUid
The Unique ID of this node.
std::string mDescription
Optional string which the user can specify.
void setClassName(const pugi::xml_node &aXmlNode, Node *aNode)
PUGI__FN void sort(I begin, I end, const Pred &pred)
static const std::string mTagsAttribute
Node * build(const pugi::xml_node &aNode, const boost::filesystem::path &aAddressFilePath)
void setFirmwareInfo(const pugi::xml_node &aXmlNode, Node *aNode)
Empty struct which acts as a dummy variable for passing the formatting information around.
uhal::NodeTreeBuilder::mode_lut mModeLut
An instance of a look-up table that the boost qi parser uses for associating strings with enumerated ...
static const std::string mDescriptionAttribute
uint32_t mPartialAddr
The register address with which this node is associated.
static const std::string mModuleAttribute
std::vector< Node * > mChildren
The direct children of the node.
static const std::string mMaskAttribute
static const std::string mIdAttribute
xml_node child(const char_t *name) const
A class to build a node tree from an Address table file NOTE! This is a factory method and must be Mu...
void setModeAndSize(const pugi::xml_node &aXmlNode, Node *aNode)
Node * plainNodeCreator(const bool &aRequireId, const pugi::xml_node &aXmlNode)
void ParseSemicolonDelimitedUriList(const std::string &aSemicolonDelimitedUriList, std::vector< std::pair< std::string, std::string > > &aUriList)
Parse a semicolon delimited list of URIs into a vector of protocol/address pairs.
static const std::string mParametersAttribute
grammars::NodeTreeFirmwareinfoAttributeGrammar mNodeTreeFirmwareInfoAttributeGrammar
NameValuePairVectorType mArguments
The member variable of the endpoint stored as "name1=val1;name2=val2;name3=val3".
void setUid(const bool &aRequireId, const pugi::xml_node &aXmlNode, Node *aNode)
static const std::string mPermissionsAttribute
defs::BlockReadWriteMode mMode
Whether the node represents a single register, a block of registers or a block-read/write port.
boost::unordered_map< std::string, const Node * > mNodes
Hash map associating a Node tree with a file name so that we do not need to repeatedly parse the xml ...
grammars::NodeTreeParametersGrammar mNodeTreeParametersGrammar
A heirarchical node for navigating heirarchical firmwares.
void checkForAddressCollisions(Node *aNode, const boost::filesystem::path &aPath)
std::deque< boost::filesystem::path > mFileCallStack
Rule< R > & optional(const std::string &aStr)
Add an optional attribute to the rule.
std::vector< std::pair< const Node *, const Node * > > getAddressOverlaps(const Node &aNode)
void setPars(const pugi::xml_node &aXmlNode, Node *aNode)
BlockReadWriteMode
define whether transactions target a single register, a block of registers, a block-read/write port o...
void log(FatalLevel &aFatal, const T0 &aArg0)
Function to add a log entry at Fatal level.
void setDescription(const pugi::xml_node &aXmlNode, Node *aNode)
_Integer< T, IntFmt<> > Integer(const T &aT)
Forward declare a function which creates an instance of the ultra-lightweight wrapper from an integer...
Rule for matching XML attributes.
Parser< Node * > mTopLevelNodeParser
Parser< Node * > mNodeParser
static const std::string mFirmwareInfo
_Quote< T > Quote(const T &aT)
Rule< R > & require(const std::string &aStr)
Add a required attribute to the rule.
std::string mClassName
Class name used to construct the derived node type.
static const std::string mSizeAttribute
Node * convertToClassType(Node *aNode)
xml_node next_sibling() const
virtual ~NodeTreeBuilder()
Destructor.
A look-up table that the boost qi parser uses for associating strings ("r","w","rw",...
Node * bitmaskNodeCreator(const bool &aRequireId, const pugi::xml_node &aXmlNode)
mode_lut()
The actual function that the boost qi parser uses for associating strings with enumerated permissions...
uint32_t mSize
The maximum size available to a block read/write.
template bool GetXMLattribute< false >(const pugi::xml_node &aNode, const std::string &aAttrName, std::string &aTarget)
void OpenFile(const std::string &aProtocol, const std::string &aFilenameExpr, const boost::filesystem::path &aParentPath, boost::_bi::bind_t< R, F, L > aBinder)
Given a protocol and either a URL or a linux shell expression, open the file and call the callback fu...
bool writeNodeOverlapReport(const std::string &aFilePath, const std::vector< std::pair< const Node *, const Node * > > &aNodes, const std::string &aHeader)
void PugiXMLParseResultPrettifier(const pugi::xml_parse_result &aLoadResult, const boost::filesystem::path &aPath, const std::vector< uint8_t > &aFile)
Helper function to make debugging failures when parsing XML files easier.
defs::NodePermission mPermission
The read/write access permissions of this node.
xml_attribute attribute(const char_t *name) const
boost::unordered_map< std::string, Node * > mChildrenMap
Helper to assist look-up of a particular child node, given a name.
uint32_t mMask
The mask to be applied if this node is a sub-field, rather than an entire register.
void setTags(const pugi::xml_node &aXmlNode, Node *aNode)
void addChildren(const pugi::xml_node &aXmlNode, Node *aNode)
Node * getNodeTree(const std::string &aFilenameExpr, const boost::filesystem::path &aPath)
Construct a node tree from file whose name is specified.
xml_parse_result load_buffer_inplace(void *contents, size_t size, unsigned int options=parse_default, xml_encoding encoding=encoding_auto)
void setModule(const pugi::xml_node &aXmlNode, Node *aNode)
static DerivedNodeFactory & getInstance()
Static method to retrieve the single instance of the class.
boost::unordered_map< std::string, std::string > mParameters
Additional parameters of the node.
static NodeTreeBuilder & getInstance()
Static method to retrieve the single instance of the class.
const uint32_t NOMASK
define what it means to have no mask
static boost::shared_ptr< NodeTreeBuilder > mInstance
The single instance of the class.
static const std::string mModeAttribute
Node * moduleNodeCreator(const bool &aRequireId, const pugi::xml_node &aXmlNode)
void clearAddressFileCache()
Clears address filename -> Node tree cache. NOT thread safe; for tread-safety, use ConnectionManager ...
void setAddr(const pugi::xml_node &aXmlNode, Node *aNode)
uhal::NodeTreeBuilder::permissions_lut mPermissionsLut
An instance of a look-up table that the boost qi parser uses for associating strings with enumerated ...
void calculateHierarchicalAddresses(Node *aNode, const uint32_t &aAddr)
Propagate the addresses down through the hierarchical structure.