Added derived peripherals, fixed line endings, fixed display()

This commit is contained in:
Łukasz Czyż 2019-11-15 12:42:48 +01:00
parent 5fa14dbc99
commit f2f00aad77
4 changed files with 307 additions and 289 deletions

View file

@ -1,21 +1,21 @@
#ifndef DEVICE_INFO #ifndef DEVICE_INFO
#define DEVICE_INFO #define DEVICE_INFO
#include <iostream> #include <iostream>
struct DeviceInfo{ struct DeviceInfo{
std::string schemaVersion; std::string schemaVersion;
std::string name; std::string name;
std::string version; std::string version;
unsigned int resetValue; unsigned int resetValue;
void printDeviceInfo() const{ void printDeviceInfo() const{
std::cout << "schemaVersion " << schemaVersion << std::endl std::cout << "schemaVersion " << schemaVersion << std::endl
<< "name " << name << std::endl << "name " << name << std::endl
<< "version " << version << std::endl << "version " << version << std::endl
<< "resetValue 0x" << std::hex << resetValue << std::dec << std::endl; << "resetValue 0x" << std::hex << resetValue << std::dec << std::endl;
} }
}; };
#endif #endif

View file

@ -1,91 +1,90 @@
#ifndef PERIPHERAL #ifndef PERIPHERAL
#define PERIPHERAL #define PERIPHERAL
#include <string> #include <string>
#include <vector> #include <vector>
enum class EAccess{ enum class EAccess{
Read_Only, Read_Only,
Write_Only, Write_Only,
Read_Write Read_Write
}; };
struct IDisplay{ struct IDisplay{
virtual void display() = 0; virtual void display() = 0;
}; };
struct Field : public IDisplay{ struct Field : public IDisplay{
std::string name; std::string name;
std::string description; std::string description;
unsigned int bitOffset; unsigned int bitOffset;
unsigned int bitWidth; unsigned int bitWidth;
EAccess fieldAccess; EAccess fieldAccess;
void display() final{ void display() final{
std::cout << std::endl std::cout << "\t\tname: " << name << std::endl
<< "\t\tname: " << name << std::endl << "\t\tdescription: " << description << std::endl
<< "\t\tdescription: " << description << std::endl << "\t\tbitOffset: " << bitOffset << std::endl
<< "\t\tbitOffset: " << bitOffset << std::endl << "\t\tbitWidth: " << bitWidth << std::endl
<< "\t\tbitWidth: " << bitWidth << std::endl << "\t\tfieldAccess: " << (int)fieldAccess << std::endl
<< "\t\tfieldAccess: " << (int)fieldAccess << std::endl; << std::endl;
} }
}; };
struct Register : public IDisplay{ struct Register : public IDisplay{
std::string name; std::string name;
std::string description; std::string description;
unsigned int addressOffset; unsigned int addressOffset;
unsigned int size; unsigned int size;
EAccess registerAccess; EAccess registerAccess;
unsigned int resetValue; unsigned int resetValue;
std::vector<Field> fields; std::vector<Field> fields;
void display() final{ void display() final{
std::cout << std::endl std::cout << "\tname: " << name << std::endl
<< "\tname: " << name << std::endl << "\tdescription: " << description << std::endl
<< "\tdescription: " << description << std::endl << "\taddressOffset: " << addressOffset << std::endl
<< "\taddressOffset: " << addressOffset << std::endl << "\tsize: " << size << std::endl
<< "\tsize: " << size << std::endl << "\tregisterAccess: " << (int)registerAccess << std::endl
<< "\tregisterAccess: " << (int)registerAccess << std::endl << "\tresetValue: " << resetValue << std::endl;
<< "\tresetValue: " << resetValue << std::endl;
std::cout << "\tfields: " << std::endl;
std::cout << std::endl << "\tfields: " << std::endl; for(auto& i : fields){
for(auto& i : fields){ i.display();
i.display(); }
} }
} };
};
struct AddressBlock : public IDisplay{
struct AddressBlock : public IDisplay{ unsigned int offset;
unsigned int offset; unsigned int size;
unsigned int size; void display() final{
void display() final{ std::cout << std::endl
std::cout << std::endl << "\toffset: " << offset << std::endl
<< "\toffset: " << offset << std::endl << "\tsize: " << size << std::endl;
<< "\tsize: " << size << std::endl; }
} };
};
struct Peripheral : public IDisplay{
struct Peripheral : public IDisplay{ std::string name;
std::string name; std::string description;
std::string description; std::string groupName;
std::string groupName; unsigned int baseAddress;
unsigned int baseAddress; AddressBlock addressBlock;
AddressBlock addressBlock; std::vector<Register> registers;
std::vector<Register> registers; void display() final{
void display() final{ std::cout << std::endl
std::cout << std::endl << "name: " << name << std::endl
<< "name: " << name << std::endl << "description: " << description << std::endl
<< "description: " << description << std::endl << "groupName: " << groupName << std::endl
<< "groupName: " << groupName << std::endl << "baseAddress: " << baseAddress << std::endl
<< "baseAddress: " << baseAddress << std::endl << "addressBlock: ";
<< "addressBlock: "; addressBlock.display();
addressBlock.display(); std::cout << "registers: " << std::endl;
std::cout << std::endl << "registers: " << std::endl; for(auto& i : registers){
for(auto& i : registers){ i.display();
i.display(); }
} }
} };
};
#endif
#endif

View file

@ -1,144 +1,163 @@
#include <XmlParser.hpp> #include <XmlParser.hpp>
#include <iostream> #include <iostream>
#include <algorithm>
XmlParser::XmlParser(const std::string& inputFile){ XmlParser::XmlParser(const std::string& inputFile){
xmlDocument.LoadFile(inputFile.c_str()); xmlDocument.LoadFile(inputFile.c_str());
} }
std::optional<std::string> XmlParser::isError() const{ std::optional<std::string> XmlParser::isError() const{
return xmlDocument.Error() ? std::optional<std::string>(xmlDocument.ErrorStr()) : std::nullopt; return xmlDocument.Error() ? std::optional<std::string>(xmlDocument.ErrorStr()) : std::nullopt;
} }
void XmlParser::parseXml(){ void XmlParser::parseXml(){
tinyxml2::XMLElement* deviceRoot = xmlDocument.FirstChildElement("device"); tinyxml2::XMLElement* deviceRoot = xmlDocument.FirstChildElement("device");
if(deviceRoot == nullptr) if(deviceRoot == nullptr)
return; return;
//Set Schema Version //Set Schema Version
deviceInfo.schemaVersion = deviceRoot->Attribute("schemaVersion"); deviceInfo.schemaVersion = deviceRoot->Attribute("schemaVersion");
//Set attributes //Set attributes
setDeviceInfoAttrib(deviceRoot, "name", deviceInfo.name); setDeviceInfoAttrib(deviceRoot, "name", deviceInfo.name);
setDeviceInfoAttrib(deviceRoot, "version", deviceInfo.version); setDeviceInfoAttrib(deviceRoot, "version", deviceInfo.version);
setDeviceInfoAttrib(deviceRoot, "resetValue", deviceInfo.resetValue); setDeviceInfoAttrib(deviceRoot, "resetValue", deviceInfo.resetValue);
deviceInfo.printDeviceInfo(); deviceInfo.printDeviceInfo();
//Iterate over all peripherals and append them to peripherals //Iterate over all peripherals and append them to peripherals
tinyxml2::XMLElement *peripheralsRoot = deviceRoot->FirstChildElement("peripherals"); tinyxml2::XMLElement *peripheralsRoot = deviceRoot->FirstChildElement("peripherals");
if(peripheralsRoot != nullptr){ if(peripheralsRoot != nullptr){
for (tinyxml2::XMLNode* peripheralRoot = peripheralsRoot->FirstChild(); for (tinyxml2::XMLNode* peripheralRoot = peripheralsRoot->FirstChild();
peripheralRoot; peripheralRoot;
peripheralRoot = peripheralRoot->NextSibling()){ peripheralRoot = peripheralRoot->NextSibling()){
//Parse only "peripheral" node //Parse only "peripheral" node
if(std::string(peripheralRoot->Value()) != "peripheral"){ if(std::string(peripheralRoot->Value()) != "peripheral"){
std::cout << "Register node has value " << peripheralRoot->Value(); std::cout << "Register node has value " << peripheralRoot->Value();
continue; continue;
} }
peripherals.push_back(parsePeripheral(peripheralRoot->ToElement())); peripherals.push_back(parsePeripheral(peripheralRoot->ToElement()));
} }
} }
} }
void XmlParser::setDeviceInfoAttrib(tinyxml2::XMLElement* deviceRoot, const char* name, std::string &field){ void XmlParser::setDeviceInfoAttrib(tinyxml2::XMLElement* deviceRoot, const char* name, std::string &field) const{
tinyxml2::XMLElement* deviceEntry = deviceRoot->FirstChildElement(name); tinyxml2::XMLElement* deviceEntry = deviceRoot->FirstChildElement(name);
field = deviceEntry != nullptr ? deviceEntry->GetText() : noValue; field = deviceEntry != nullptr ? deviceEntry->GetText() : noValue;
} }
void XmlParser::setDeviceInfoAttrib(tinyxml2::XMLElement* deviceRoot, const char* name, unsigned int &field){ void XmlParser::setDeviceInfoAttrib(tinyxml2::XMLElement* deviceRoot, const char* name, unsigned int &field) const{
tinyxml2::XMLElement* deviceEntry = deviceRoot->FirstChildElement(name); tinyxml2::XMLElement* deviceEntry = deviceRoot->FirstChildElement(name);
field = deviceEntry != nullptr ? std::stol(deviceEntry->GetText(), 0, 16) : 0; field = deviceEntry != nullptr ? std::stol(deviceEntry->GetText(), 0, 16) : 0;
} }
void XmlParser::setDeviceInfoAttrib(tinyxml2::XMLElement* deviceRoot, const char* name, EAccess &field){ void XmlParser::setDeviceInfoAttrib(tinyxml2::XMLElement* deviceRoot, const char* name, EAccess &field) const{
tinyxml2::XMLElement* deviceEntry = deviceRoot->FirstChildElement(name); tinyxml2::XMLElement* deviceEntry = deviceRoot->FirstChildElement(name);
if(deviceEntry == nullptr){ if(deviceEntry == nullptr){
field = EAccess::Read_Write; field = EAccess::Read_Write;
return; return;
} }
const std::string text = deviceEntry->GetText(); const std::string text = deviceEntry->GetText();
if(text == "read-only"){ if(text == "read-only"){
field = EAccess::Read_Only; field = EAccess::Read_Only;
} }
else if(text == "write-only"){ else if(text == "write-only"){
field = EAccess::Write_Only; field = EAccess::Write_Only;
} }
else if(text == "read-write"){ else if(text == "read-write"){
field = EAccess::Read_Write; field = EAccess::Read_Write;
} }
else{ else{
std::cout << "Wrong field for access: " << text << std::endl; std::cout << "Wrong field for access: " << text << std::endl;
} }
} }
unsigned int peripheralCount = 0; unsigned int peripheralCount = 0; //Debug
Peripheral XmlParser::parsePeripheral(tinyxml2::XMLElement* peripheralRoot){ Peripheral XmlParser::parsePeripheral(tinyxml2::XMLElement* peripheralRoot) const{
std::cout << "Peripheral: " << peripheralCount++ << std::endl; std::cout << "Peripheral: " << peripheralCount++ << std::endl; //Debug
Peripheral peripheral; //Check if peripheral is derived from previous one
setDeviceInfoAttrib(peripheralRoot, "name", peripheral.name); const char* attribute = peripheralRoot->Attribute("derivedFrom");
setDeviceInfoAttrib(peripheralRoot, "description", peripheral.description); const bool isDerived = attribute != nullptr;
setDeviceInfoAttrib(peripheralRoot, "groupName", peripheral.groupName); const std::string derivedFrom = isDerived ? attribute : "";
setDeviceInfoAttrib(peripheralRoot, "baseAddress", peripheral.baseAddress);
peripheral.addressBlock = parseAddressBlock(peripheralRoot->FirstChildElement("addressBlock")); Peripheral peripheral;
if(isDerived == true){
//Iterate over all registers and append them to peripheral std::cout << "Derived from " << derivedFrom << std::endl;
tinyxml2::XMLElement *registersRoot = peripheralRoot->FirstChildElement("registers"); //Find the base peripheral and copy it to the new one
if(registersRoot != nullptr){ auto crit = [&](auto &periph) { return periph.name == derivedFrom; };
for (tinyxml2::XMLNode* registerRoot = registersRoot->FirstChild(); auto resultIt = std::find_if(peripherals.begin(), peripherals.end(), crit);
registerRoot; if(resultIt < peripherals.end()){
registerRoot = registerRoot->NextSibling()){ peripheral = *resultIt;
//Parse only "register" node }
if(std::string(registerRoot->Value()) != "register"){ else{
std::cout << "Register node has value " << registerRoot->Value(); std::cout << "Couldn't find peripheral " << derivedFrom << std::endl;
continue; }
} }
peripheral.registers.push_back(parseRegister(registerRoot->ToElement())); setDeviceInfoAttrib(peripheralRoot, "name", peripheral.name);
} setDeviceInfoAttrib(peripheralRoot, "baseAddress", peripheral.baseAddress);
} if(isDerived == false){
peripheral.display(); setDeviceInfoAttrib(peripheralRoot, "description", peripheral.description);
return peripheral; setDeviceInfoAttrib(peripheralRoot, "groupName", peripheral.groupName);
} peripheral.addressBlock = parseAddressBlock(peripheralRoot->FirstChildElement("addressBlock"));
AddressBlock XmlParser::parseAddressBlock(tinyxml2::XMLElement* addressBlockRoot){ //Iterate over all registers and append them to peripheral
AddressBlock addressBlock; tinyxml2::XMLElement *registersRoot = peripheralRoot->FirstChildElement("registers");
if(addressBlockRoot){ if(registersRoot != nullptr){
setDeviceInfoAttrib(addressBlockRoot, "offset", addressBlock.offset); for (tinyxml2::XMLNode* registerRoot = registersRoot->FirstChild();
setDeviceInfoAttrib(addressBlockRoot, "size", addressBlock.size); registerRoot;
} registerRoot = registerRoot->NextSibling()){
else //Parse only "register" node
std::cout << "parseAddressBlock is nullptr!" << std::endl; if(std::string(registerRoot->Value()) != "register"){
1 / 0; std::cout << "Register node has value " << registerRoot->Value();
return addressBlock; continue;
} }
peripheral.registers.push_back(parseRegister(registerRoot->ToElement()));
Register XmlParser::parseRegister(tinyxml2::XMLElement* registerRoot){ }
Register registe; }
setDeviceInfoAttrib(registerRoot, "name", registe.name); }
setDeviceInfoAttrib(registerRoot, "description", registe.description); peripheral.display();
setDeviceInfoAttrib(registerRoot, "addressOffset", registe.addressOffset); return peripheral;
setDeviceInfoAttrib(registerRoot, "size", registe.size); }
setDeviceInfoAttrib(registerRoot, "access", registe.registerAccess);
setDeviceInfoAttrib(registerRoot, "resetValue", registe.resetValue); AddressBlock XmlParser::parseAddressBlock(tinyxml2::XMLElement* addressBlockRoot) const{
AddressBlock addressBlock;
//Iterate over all fields and append them to registe if(addressBlockRoot != nullptr){
tinyxml2::XMLElement* fieldsRoot = registerRoot->FirstChildElement("fields"); setDeviceInfoAttrib(addressBlockRoot, "offset", addressBlock.offset);
if(fieldsRoot != nullptr){ setDeviceInfoAttrib(addressBlockRoot, "size", addressBlock.size);
for (tinyxml2::XMLNode *fieldRoot = fieldsRoot->FirstChild(); }
fieldRoot; else{
fieldRoot = fieldRoot->NextSibling()){ std::cout << "addressBlockRoot is nullptr" << std::endl;
//Parse only "field" node }
if(std::string(fieldRoot->Value()) != "field"){ return addressBlock;
std::cout << "Field node has value " << fieldRoot->Value(); }
continue;
} Register XmlParser::parseRegister(tinyxml2::XMLElement* registerRoot) const{
registe.fields.push_back(parseField(fieldRoot->ToElement())); Register registe;
} setDeviceInfoAttrib(registerRoot, "name", registe.name);
} setDeviceInfoAttrib(registerRoot, "description", registe.description);
return registe; setDeviceInfoAttrib(registerRoot, "addressOffset", registe.addressOffset);
} setDeviceInfoAttrib(registerRoot, "size", registe.size);
Field XmlParser::parseField(tinyxml2::XMLElement* fieldRoot){ setDeviceInfoAttrib(registerRoot, "access", registe.registerAccess);
Field field; setDeviceInfoAttrib(registerRoot, "resetValue", registe.resetValue);
setDeviceInfoAttrib(fieldRoot, "name", field.name);
setDeviceInfoAttrib(fieldRoot, "description", field.description); //Iterate over all fields and append them to registe
setDeviceInfoAttrib(fieldRoot, "bitOffset", field.bitOffset); tinyxml2::XMLElement* fieldsRoot = registerRoot->FirstChildElement("fields");
setDeviceInfoAttrib(fieldRoot, "bitWidth", field.bitWidth); if(fieldsRoot != nullptr){
setDeviceInfoAttrib(fieldRoot, "access", field.fieldAccess); for (tinyxml2::XMLNode *fieldRoot = fieldsRoot->FirstChild();
return field; fieldRoot;
fieldRoot = fieldRoot->NextSibling()){
//Parse only "field" node
if(std::string(fieldRoot->Value()) != "field"){
std::cout << "Field node has value " << fieldRoot->Value();
continue;
}
registe.fields.push_back(parseField(fieldRoot->ToElement()));
}
}
return registe;
}
Field XmlParser::parseField(tinyxml2::XMLElement* fieldRoot) const{
Field field;
setDeviceInfoAttrib(fieldRoot, "name", field.name);
setDeviceInfoAttrib(fieldRoot, "description", field.description);
setDeviceInfoAttrib(fieldRoot, "bitOffset", field.bitOffset);
setDeviceInfoAttrib(fieldRoot, "bitWidth", field.bitWidth);
setDeviceInfoAttrib(fieldRoot, "access", field.fieldAccess);
return field;
} }

View file

@ -1,35 +1,35 @@
#ifndef XML_PARSER #ifndef XML_PARSER
#define XML_PARSER #define XML_PARSER
#include <tinyxml2.h> #include <tinyxml2.h>
#include <string> #include <string>
#include <optional> #include <optional>
#include <memory> #include <memory>
#include <DeviceInfo.hpp> #include <DeviceInfo.hpp>
#include <vector> #include <vector>
#include <Peripheral.hpp> #include <Peripheral.hpp>
struct XmlParser{ struct XmlParser{
XmlParser(const std::string& inputFile); XmlParser(const std::string& inputFile);
std::optional<std::string> isError() const; std::optional<std::string> isError() const;
void parseXml(); void parseXml();
private: private:
// tinyxml2::XMLElement* getDevice // tinyxml2::XMLElement* getDevice
void setDeviceInfoAttrib(tinyxml2::XMLElement* deviceRoot, const char* name, std::string &field); void setDeviceInfoAttrib(tinyxml2::XMLElement* deviceRoot, const char* name, std::string &field) const;
void setDeviceInfoAttrib(tinyxml2::XMLElement* deviceRoot, const char* name, unsigned int &field); void setDeviceInfoAttrib(tinyxml2::XMLElement* deviceRoot, const char* name, unsigned int &field) const;
void setDeviceInfoAttrib(tinyxml2::XMLElement* deviceRoot, const char* name, EAccess &field); void setDeviceInfoAttrib(tinyxml2::XMLElement* deviceRoot, const char* name, EAccess &field) const;
Peripheral parsePeripheral(tinyxml2::XMLElement* peripheralRoot); Peripheral parsePeripheral(tinyxml2::XMLElement* peripheralRoot) const;
AddressBlock parseAddressBlock(tinyxml2::XMLElement* addressBlockRoot); AddressBlock parseAddressBlock(tinyxml2::XMLElement* addressBlockRoot) const;
Register parseRegister(tinyxml2::XMLElement* registerRoot); Register parseRegister(tinyxml2::XMLElement* registerRoot) const;
Field parseField(tinyxml2::XMLElement* fieldRoot); Field parseField(tinyxml2::XMLElement* fieldRoot) const;
private: private:
tinyxml2::XMLDocument xmlDocument; tinyxml2::XMLDocument xmlDocument;
static const inline std::string noValue = "Not found"; static const inline std::string noValue = "Not found";
DeviceInfo deviceInfo; DeviceInfo deviceInfo;
std::vector<Peripheral> peripherals; std::vector<Peripheral> peripherals;
}; };
#endif #endif