diff --git a/Src/DeviceInfo.hpp b/Src/DeviceInfo.hpp index 77b804b..643f91c 100644 --- a/Src/DeviceInfo.hpp +++ b/Src/DeviceInfo.hpp @@ -1,21 +1,21 @@ -#ifndef DEVICE_INFO -#define DEVICE_INFO - -#include - - -struct DeviceInfo{ - std::string schemaVersion; - std::string name; - std::string version; - unsigned int resetValue; - - void printDeviceInfo() const{ - std::cout << "schemaVersion " << schemaVersion << std::endl - << "name " << name << std::endl - << "version " << version << std::endl - << "resetValue 0x" << std::hex << resetValue << std::dec << std::endl; - } -}; - -#endif +#ifndef DEVICE_INFO +#define DEVICE_INFO + +#include + + +struct DeviceInfo{ + std::string schemaVersion; + std::string name; + std::string version; + unsigned int resetValue; + + void printDeviceInfo() const{ + std::cout << "schemaVersion " << schemaVersion << std::endl + << "name " << name << std::endl + << "version " << version << std::endl + << "resetValue 0x" << std::hex << resetValue << std::dec << std::endl; + } +}; + +#endif diff --git a/Src/Peripheral.hpp b/Src/Peripheral.hpp index e9666cd..37d7a57 100644 --- a/Src/Peripheral.hpp +++ b/Src/Peripheral.hpp @@ -1,91 +1,90 @@ -#ifndef PERIPHERAL -#define PERIPHERAL - -#include -#include - - -enum class EAccess{ - Read_Only, - Write_Only, - Read_Write -}; - -struct IDisplay{ - virtual void display() = 0; -}; - -struct Field : public IDisplay{ - std::string name; - std::string description; - unsigned int bitOffset; - unsigned int bitWidth; - EAccess fieldAccess; - void display() final{ - std::cout << std::endl - << "\t\tname: " << name << std::endl - << "\t\tdescription: " << description << std::endl - << "\t\tbitOffset: " << bitOffset << std::endl - << "\t\tbitWidth: " << bitWidth << std::endl - << "\t\tfieldAccess: " << (int)fieldAccess << std::endl; - } -}; - -struct Register : public IDisplay{ - std::string name; - std::string description; - unsigned int addressOffset; - unsigned int size; - EAccess registerAccess; - unsigned int resetValue; - std::vector fields; - - void display() final{ - std::cout << std::endl - << "\tname: " << name << std::endl - << "\tdescription: " << description << std::endl - << "\taddressOffset: " << addressOffset << std::endl - << "\tsize: " << size << std::endl - << "\tregisterAccess: " << (int)registerAccess << std::endl - << "\tresetValue: " << resetValue << std::endl; - - std::cout << std::endl << "\tfields: " << std::endl; - for(auto& i : fields){ - i.display(); - } - } -}; - -struct AddressBlock : public IDisplay{ - unsigned int offset; - unsigned int size; - void display() final{ - std::cout << std::endl - << "\toffset: " << offset << std::endl - << "\tsize: " << size << std::endl; - } -}; - -struct Peripheral : public IDisplay{ - std::string name; - std::string description; - std::string groupName; - unsigned int baseAddress; - AddressBlock addressBlock; - std::vector registers; - void display() final{ - std::cout << std::endl - << "name: " << name << std::endl - << "description: " << description << std::endl - << "groupName: " << groupName << std::endl - << "baseAddress: " << baseAddress << std::endl - << "addressBlock: "; - addressBlock.display(); - std::cout << std::endl << "registers: " << std::endl; - for(auto& i : registers){ - i.display(); - } - } -}; - -#endif +#ifndef PERIPHERAL +#define PERIPHERAL + +#include +#include + + +enum class EAccess{ + Read_Only, + Write_Only, + Read_Write +}; + +struct IDisplay{ + virtual void display() = 0; +}; + +struct Field : public IDisplay{ + std::string name; + std::string description; + unsigned int bitOffset; + unsigned int bitWidth; + EAccess fieldAccess; + void display() final{ + std::cout << "\t\tname: " << name << std::endl + << "\t\tdescription: " << description << std::endl + << "\t\tbitOffset: " << bitOffset << std::endl + << "\t\tbitWidth: " << bitWidth << std::endl + << "\t\tfieldAccess: " << (int)fieldAccess << std::endl + << std::endl; + } +}; + +struct Register : public IDisplay{ + std::string name; + std::string description; + unsigned int addressOffset; + unsigned int size; + EAccess registerAccess; + unsigned int resetValue; + std::vector fields; + + void display() final{ + std::cout << "\tname: " << name << std::endl + << "\tdescription: " << description << std::endl + << "\taddressOffset: " << addressOffset << std::endl + << "\tsize: " << size << std::endl + << "\tregisterAccess: " << (int)registerAccess << std::endl + << "\tresetValue: " << resetValue << std::endl; + + std::cout << "\tfields: " << std::endl; + for(auto& i : fields){ + i.display(); + } + } +}; + +struct AddressBlock : public IDisplay{ + unsigned int offset; + unsigned int size; + void display() final{ + std::cout << std::endl + << "\toffset: " << offset << std::endl + << "\tsize: " << size << std::endl; + } +}; + +struct Peripheral : public IDisplay{ + std::string name; + std::string description; + std::string groupName; + unsigned int baseAddress; + AddressBlock addressBlock; + std::vector registers; + void display() final{ + std::cout << std::endl + << "name: " << name << std::endl + << "description: " << description << std::endl + << "groupName: " << groupName << std::endl + << "baseAddress: " << baseAddress << std::endl + << "addressBlock: "; + addressBlock.display(); + std::cout << "registers: " << std::endl; + for(auto& i : registers){ + i.display(); + } + } +}; + +#endif diff --git a/Src/XmlParser.cpp b/Src/XmlParser.cpp index 6870e37..3ecc174 100644 --- a/Src/XmlParser.cpp +++ b/Src/XmlParser.cpp @@ -1,144 +1,163 @@ -#include -#include - - -XmlParser::XmlParser(const std::string& inputFile){ - xmlDocument.LoadFile(inputFile.c_str()); -} -std::optional XmlParser::isError() const{ - return xmlDocument.Error() ? std::optional(xmlDocument.ErrorStr()) : std::nullopt; -} - -void XmlParser::parseXml(){ - tinyxml2::XMLElement* deviceRoot = xmlDocument.FirstChildElement("device"); - if(deviceRoot == nullptr) - return; - //Set Schema Version - deviceInfo.schemaVersion = deviceRoot->Attribute("schemaVersion"); - - //Set attributes - setDeviceInfoAttrib(deviceRoot, "name", deviceInfo.name); - setDeviceInfoAttrib(deviceRoot, "version", deviceInfo.version); - setDeviceInfoAttrib(deviceRoot, "resetValue", deviceInfo.resetValue); - - deviceInfo.printDeviceInfo(); - - //Iterate over all peripherals and append them to peripherals - tinyxml2::XMLElement *peripheralsRoot = deviceRoot->FirstChildElement("peripherals"); - if(peripheralsRoot != nullptr){ - for (tinyxml2::XMLNode* peripheralRoot = peripheralsRoot->FirstChild(); - peripheralRoot; - peripheralRoot = peripheralRoot->NextSibling()){ - //Parse only "peripheral" node - if(std::string(peripheralRoot->Value()) != "peripheral"){ - std::cout << "Register node has value " << peripheralRoot->Value(); - continue; - } - peripherals.push_back(parsePeripheral(peripheralRoot->ToElement())); - } - } -} - -void XmlParser::setDeviceInfoAttrib(tinyxml2::XMLElement* deviceRoot, const char* name, std::string &field){ - tinyxml2::XMLElement* deviceEntry = deviceRoot->FirstChildElement(name); - field = deviceEntry != nullptr ? deviceEntry->GetText() : noValue; -} - -void XmlParser::setDeviceInfoAttrib(tinyxml2::XMLElement* deviceRoot, const char* name, unsigned int &field){ - tinyxml2::XMLElement* deviceEntry = deviceRoot->FirstChildElement(name); - field = deviceEntry != nullptr ? std::stol(deviceEntry->GetText(), 0, 16) : 0; -} -void XmlParser::setDeviceInfoAttrib(tinyxml2::XMLElement* deviceRoot, const char* name, EAccess &field){ - tinyxml2::XMLElement* deviceEntry = deviceRoot->FirstChildElement(name); - if(deviceEntry == nullptr){ - field = EAccess::Read_Write; - return; - } - const std::string text = deviceEntry->GetText(); - if(text == "read-only"){ - field = EAccess::Read_Only; - } - else if(text == "write-only"){ - field = EAccess::Write_Only; - } - else if(text == "read-write"){ - field = EAccess::Read_Write; - } - else{ - std::cout << "Wrong field for access: " << text << std::endl; - } -} -unsigned int peripheralCount = 0; -Peripheral XmlParser::parsePeripheral(tinyxml2::XMLElement* peripheralRoot){ - std::cout << "Peripheral: " << peripheralCount++ << std::endl; - Peripheral peripheral; - setDeviceInfoAttrib(peripheralRoot, "name", peripheral.name); - setDeviceInfoAttrib(peripheralRoot, "description", peripheral.description); - setDeviceInfoAttrib(peripheralRoot, "groupName", peripheral.groupName); - setDeviceInfoAttrib(peripheralRoot, "baseAddress", peripheral.baseAddress); - peripheral.addressBlock = parseAddressBlock(peripheralRoot->FirstChildElement("addressBlock")); - - //Iterate over all registers and append them to peripheral - tinyxml2::XMLElement *registersRoot = peripheralRoot->FirstChildElement("registers"); - if(registersRoot != nullptr){ - for (tinyxml2::XMLNode* registerRoot = registersRoot->FirstChild(); - registerRoot; - registerRoot = registerRoot->NextSibling()){ - //Parse only "register" node - if(std::string(registerRoot->Value()) != "register"){ - std::cout << "Register node has value " << registerRoot->Value(); - continue; - } - peripheral.registers.push_back(parseRegister(registerRoot->ToElement())); - } - } - peripheral.display(); - return peripheral; -} - -AddressBlock XmlParser::parseAddressBlock(tinyxml2::XMLElement* addressBlockRoot){ - AddressBlock addressBlock; - if(addressBlockRoot){ - setDeviceInfoAttrib(addressBlockRoot, "offset", addressBlock.offset); - setDeviceInfoAttrib(addressBlockRoot, "size", addressBlock.size); - } - else - std::cout << "parseAddressBlock is nullptr!" << std::endl; - 1 / 0; - return addressBlock; -} - -Register XmlParser::parseRegister(tinyxml2::XMLElement* registerRoot){ - Register registe; - setDeviceInfoAttrib(registerRoot, "name", registe.name); - setDeviceInfoAttrib(registerRoot, "description", registe.description); - setDeviceInfoAttrib(registerRoot, "addressOffset", registe.addressOffset); - setDeviceInfoAttrib(registerRoot, "size", registe.size); - setDeviceInfoAttrib(registerRoot, "access", registe.registerAccess); - setDeviceInfoAttrib(registerRoot, "resetValue", registe.resetValue); - - //Iterate over all fields and append them to registe - tinyxml2::XMLElement* fieldsRoot = registerRoot->FirstChildElement("fields"); - if(fieldsRoot != nullptr){ - for (tinyxml2::XMLNode *fieldRoot = fieldsRoot->FirstChild(); - 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){ - 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; +#include +#include +#include + +XmlParser::XmlParser(const std::string& inputFile){ + xmlDocument.LoadFile(inputFile.c_str()); +} +std::optional XmlParser::isError() const{ + return xmlDocument.Error() ? std::optional(xmlDocument.ErrorStr()) : std::nullopt; +} + +void XmlParser::parseXml(){ + tinyxml2::XMLElement* deviceRoot = xmlDocument.FirstChildElement("device"); + if(deviceRoot == nullptr) + return; + //Set Schema Version + deviceInfo.schemaVersion = deviceRoot->Attribute("schemaVersion"); + + //Set attributes + setDeviceInfoAttrib(deviceRoot, "name", deviceInfo.name); + setDeviceInfoAttrib(deviceRoot, "version", deviceInfo.version); + setDeviceInfoAttrib(deviceRoot, "resetValue", deviceInfo.resetValue); + + deviceInfo.printDeviceInfo(); + + //Iterate over all peripherals and append them to peripherals + tinyxml2::XMLElement *peripheralsRoot = deviceRoot->FirstChildElement("peripherals"); + if(peripheralsRoot != nullptr){ + for (tinyxml2::XMLNode* peripheralRoot = peripheralsRoot->FirstChild(); + peripheralRoot; + peripheralRoot = peripheralRoot->NextSibling()){ + //Parse only "peripheral" node + if(std::string(peripheralRoot->Value()) != "peripheral"){ + std::cout << "Register node has value " << peripheralRoot->Value(); + continue; + } + peripherals.push_back(parsePeripheral(peripheralRoot->ToElement())); + } + } +} + +void XmlParser::setDeviceInfoAttrib(tinyxml2::XMLElement* deviceRoot, const char* name, std::string &field) const{ + tinyxml2::XMLElement* deviceEntry = deviceRoot->FirstChildElement(name); + field = deviceEntry != nullptr ? deviceEntry->GetText() : noValue; +} + +void XmlParser::setDeviceInfoAttrib(tinyxml2::XMLElement* deviceRoot, const char* name, unsigned int &field) const{ + tinyxml2::XMLElement* deviceEntry = deviceRoot->FirstChildElement(name); + field = deviceEntry != nullptr ? std::stol(deviceEntry->GetText(), 0, 16) : 0; +} +void XmlParser::setDeviceInfoAttrib(tinyxml2::XMLElement* deviceRoot, const char* name, EAccess &field) const{ + tinyxml2::XMLElement* deviceEntry = deviceRoot->FirstChildElement(name); + if(deviceEntry == nullptr){ + field = EAccess::Read_Write; + return; + } + const std::string text = deviceEntry->GetText(); + if(text == "read-only"){ + field = EAccess::Read_Only; + } + else if(text == "write-only"){ + field = EAccess::Write_Only; + } + else if(text == "read-write"){ + field = EAccess::Read_Write; + } + else{ + std::cout << "Wrong field for access: " << text << std::endl; + } +} +unsigned int peripheralCount = 0; //Debug +Peripheral XmlParser::parsePeripheral(tinyxml2::XMLElement* peripheralRoot) const{ + std::cout << "Peripheral: " << peripheralCount++ << std::endl; //Debug + //Check if peripheral is derived from previous one + const char* attribute = peripheralRoot->Attribute("derivedFrom"); + const bool isDerived = attribute != nullptr; + const std::string derivedFrom = isDerived ? attribute : ""; + + Peripheral peripheral; + if(isDerived == true){ + std::cout << "Derived from " << derivedFrom << std::endl; + //Find the base peripheral and copy it to the new one + auto crit = [&](auto &periph) { return periph.name == derivedFrom; }; + auto resultIt = std::find_if(peripherals.begin(), peripherals.end(), crit); + if(resultIt < peripherals.end()){ + peripheral = *resultIt; + } + else{ + std::cout << "Couldn't find peripheral " << derivedFrom << std::endl; + } + } + setDeviceInfoAttrib(peripheralRoot, "name", peripheral.name); + setDeviceInfoAttrib(peripheralRoot, "baseAddress", peripheral.baseAddress); + if(isDerived == false){ + setDeviceInfoAttrib(peripheralRoot, "description", peripheral.description); + setDeviceInfoAttrib(peripheralRoot, "groupName", peripheral.groupName); + peripheral.addressBlock = parseAddressBlock(peripheralRoot->FirstChildElement("addressBlock")); + + //Iterate over all registers and append them to peripheral + tinyxml2::XMLElement *registersRoot = peripheralRoot->FirstChildElement("registers"); + if(registersRoot != nullptr){ + for (tinyxml2::XMLNode* registerRoot = registersRoot->FirstChild(); + registerRoot; + registerRoot = registerRoot->NextSibling()){ + //Parse only "register" node + if(std::string(registerRoot->Value()) != "register"){ + std::cout << "Register node has value " << registerRoot->Value(); + continue; + } + peripheral.registers.push_back(parseRegister(registerRoot->ToElement())); + } + } + } + peripheral.display(); + return peripheral; +} + +AddressBlock XmlParser::parseAddressBlock(tinyxml2::XMLElement* addressBlockRoot) const{ + AddressBlock addressBlock; + if(addressBlockRoot != nullptr){ + setDeviceInfoAttrib(addressBlockRoot, "offset", addressBlock.offset); + setDeviceInfoAttrib(addressBlockRoot, "size", addressBlock.size); + } + else{ + std::cout << "addressBlockRoot is nullptr" << std::endl; + } + return addressBlock; +} + +Register XmlParser::parseRegister(tinyxml2::XMLElement* registerRoot) const{ + Register registe; + setDeviceInfoAttrib(registerRoot, "name", registe.name); + setDeviceInfoAttrib(registerRoot, "description", registe.description); + setDeviceInfoAttrib(registerRoot, "addressOffset", registe.addressOffset); + setDeviceInfoAttrib(registerRoot, "size", registe.size); + setDeviceInfoAttrib(registerRoot, "access", registe.registerAccess); + setDeviceInfoAttrib(registerRoot, "resetValue", registe.resetValue); + + //Iterate over all fields and append them to registe + tinyxml2::XMLElement* fieldsRoot = registerRoot->FirstChildElement("fields"); + if(fieldsRoot != nullptr){ + for (tinyxml2::XMLNode *fieldRoot = fieldsRoot->FirstChild(); + 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; } \ No newline at end of file diff --git a/Src/XmlParser.hpp b/Src/XmlParser.hpp index cf97a20..ecb9136 100644 --- a/Src/XmlParser.hpp +++ b/Src/XmlParser.hpp @@ -1,35 +1,35 @@ -#ifndef XML_PARSER -#define XML_PARSER - -#include -#include -#include -#include -#include -#include -#include - -struct XmlParser{ - XmlParser(const std::string& inputFile); - std::optional isError() const; - void parseXml(); - -private: - // tinyxml2::XMLElement* getDevice - void setDeviceInfoAttrib(tinyxml2::XMLElement* deviceRoot, const char* name, std::string &field); - void setDeviceInfoAttrib(tinyxml2::XMLElement* deviceRoot, const char* name, unsigned int &field); - void setDeviceInfoAttrib(tinyxml2::XMLElement* deviceRoot, const char* name, EAccess &field); - - Peripheral parsePeripheral(tinyxml2::XMLElement* peripheralRoot); - AddressBlock parseAddressBlock(tinyxml2::XMLElement* addressBlockRoot); - Register parseRegister(tinyxml2::XMLElement* registerRoot); - Field parseField(tinyxml2::XMLElement* fieldRoot); - -private: - tinyxml2::XMLDocument xmlDocument; - static const inline std::string noValue = "Not found"; - DeviceInfo deviceInfo; - std::vector peripherals; -}; - +#ifndef XML_PARSER +#define XML_PARSER + +#include +#include +#include +#include +#include +#include +#include + +struct XmlParser{ + XmlParser(const std::string& inputFile); + std::optional isError() const; + void parseXml(); + +private: + // tinyxml2::XMLElement* getDevice + void setDeviceInfoAttrib(tinyxml2::XMLElement* deviceRoot, const char* name, std::string &field) const; + void setDeviceInfoAttrib(tinyxml2::XMLElement* deviceRoot, const char* name, unsigned int &field) const; + void setDeviceInfoAttrib(tinyxml2::XMLElement* deviceRoot, const char* name, EAccess &field) const; + + Peripheral parsePeripheral(tinyxml2::XMLElement* peripheralRoot) const; + AddressBlock parseAddressBlock(tinyxml2::XMLElement* addressBlockRoot) const; + Register parseRegister(tinyxml2::XMLElement* registerRoot) const; + Field parseField(tinyxml2::XMLElement* fieldRoot) const; + +private: + tinyxml2::XMLDocument xmlDocument; + static const inline std::string noValue = "Not found"; + DeviceInfo deviceInfo; + std::vector peripherals; +}; + #endif \ No newline at end of file