From 04a24f9bbf46ada460485223b792947564152e77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Czy=C5=BC?= Date: Fri, 22 Nov 2019 12:57:17 +0100 Subject: [PATCH] Added builders --- CMakeLists.txt | 3 ++- Src/Builders.cpp | 39 +++++++++++++++++++++++++++++++++ Src/Builders.hpp | 36 +++++++++++++++++++++++++++++++ Src/ClassBuilder.cpp | 34 +++++++++++++++++++++-------- Src/ClassBuilder.hpp | 51 +++++++++++++++++++++++++------------------- Src/IBuilder.hpp | 12 +++++++++++ Src/Peripheral.hpp | 2 +- Src/XmlParser.cpp | 7 ++---- Src/XmlParser.hpp | 6 ++++++ Src/main.cpp | 7 +++++- 10 files changed, 158 insertions(+), 39 deletions(-) create mode 100644 Src/Builders.cpp create mode 100644 Src/Builders.hpp create mode 100644 Src/IBuilder.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 7fc4e4b..8be0593 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,8 +8,9 @@ include_directories(cxxopts/include) include_directories(tinyxml2) add_library(ClassBuilder Src/ClassBuilder.cpp) +add_library(Builders Src/Builders.cpp) add_library(XmlParser Src/XmlParser.cpp) add_library(tinyxml2 tinyxml2/tinyxml2.cpp) add_executable(svd2cpp Src/main.cpp) -target_link_libraries(svd2cpp ClassBuilder XmlParser tinyxml2) \ No newline at end of file +target_link_libraries(svd2cpp ClassBuilder Builders XmlParser tinyxml2) \ No newline at end of file diff --git a/Src/Builders.cpp b/Src/Builders.cpp new file mode 100644 index 0000000..032cf3a --- /dev/null +++ b/Src/Builders.cpp @@ -0,0 +1,39 @@ +#include + +void ZeroPointerBuilder::build(std::stringstream& ss){ + ss << "template \n" + "constexpr unsigned int *zeroVal = reinterpret_cast(zero);\n"; +} + +void PeripheralBuilder::build(std::stringstream& ss){ + ss << "namespace " << peripheral.name.c_str() << "{\n"; + for(auto& registe : peripheral.registers){ + RegisterBuilder(registe).build(ss); + } + ss << "}\n"; +} + +void RegisterBuilder::build(std::stringstream& ss){ + //TODO: fix INVALID: some derived names are not copied + ss << " " + << "namespace " << (registe.name.length() > 100 ? "INVALID" : registe.name) << "{\n"; + for(auto& field : registe.fields){ + FieldBuilder(field).build(ss); + } + ss << " " << "}\n"; +} + +void FieldBuilder::build(std::stringstream& ss){ + ss << " " << "struct " << (field.name.length() > 100 ? "INVALID" : field.name) << "{\n"; + + //TODO: fix INVALID: some derived items are not copied + ss << " " << " " << "constexpr static inline unsigned int bitOffset(){" + << "return " << field.bitOffset << "}\n"; + + ss << " " << " " << "constexpr static inline unsigned int bitMask(){" + << "return " << field.bitWidth << "}\n"; + + ss << " " << " " << "constexpr static inline unsigned int address(){" + << "return " << "TODO" << "}\n"; + ss << " }\n"; +} \ No newline at end of file diff --git a/Src/Builders.hpp b/Src/Builders.hpp new file mode 100644 index 0000000..912e078 --- /dev/null +++ b/Src/Builders.hpp @@ -0,0 +1,36 @@ +#ifndef BUILDERS +#define BUILDERS + +#include +#include +#include +#include + +struct ZeroPointerBuilder : public IBuilder{ + void build(std::stringstream& ss) final; +}; + +struct PeripheralBuilder : public IBuilder{ + PeripheralBuilder(const Peripheral& peripheral_) : peripheral(peripheral_){} + void build(std::stringstream& ss) final; + +private: + const Peripheral& peripheral; +}; + +struct RegisterBuilder : public IBuilder{ + RegisterBuilder(const Register& register_) : registe(register_){} + void build(std::stringstream& ss) final; + +private: + const Register& registe; +}; + +struct FieldBuilder : public IBuilder{ + FieldBuilder(const Field& field_) : field(field_){} + void build(std::stringstream& ss) final; + +private: + const Field& field; +}; +#endif diff --git a/Src/ClassBuilder.cpp b/Src/ClassBuilder.cpp index 9ba502e..29218e9 100644 --- a/Src/ClassBuilder.cpp +++ b/Src/ClassBuilder.cpp @@ -1,9 +1,25 @@ -#include - -ClassBuilder::ClassBuilder(const cxxopts::ParseResult& results, - const DeviceInfo& deviceInfo, - const std::vector& peripherals) : - results(results), - deviceInfo(deviceInfo), - peripherals(peripherals){ - } +#include +#include + + +ClassBuilder::ClassBuilder(const cxxopts::ParseResult& results, + const DeviceInfo& deviceInfo, + const std::vector& peripherals) : + results(results), + deviceInfo(deviceInfo), + peripherals(peripherals){ + } + +void ClassBuilder::setupBuilders(){ + builders.push_back(std::make_unique()); + for(auto& peripheral : peripherals){ + builders.push_back(std::make_unique(peripheral)); + } +} + +void ClassBuilder::build(){ + for(auto& builder : builders){ + builder->build(outputStream); + } + std::cout << outputStream.str(); +} diff --git a/Src/ClassBuilder.hpp b/Src/ClassBuilder.hpp index c844c62..ec39105 100644 --- a/Src/ClassBuilder.hpp +++ b/Src/ClassBuilder.hpp @@ -1,22 +1,29 @@ -#ifndef CLASS_PRINTER -#define CLASS_PRINTER - -#include -#include -#include -#include - -struct ClassBuilder -{ - ClassBuilder(const cxxopts::ParseResult& results, - const DeviceInfo& deviceInfo, - const std::vector& peripherals); - -private: - const cxxopts::ParseResult& results; - const DeviceInfo& deviceInfo; - const std::vector& peripherals; -}; - - -#endif +#ifndef CLASS_PRINTER +#define CLASS_PRINTER + +#include +#include +#include +#include +#include +#include +#include + + +struct ClassBuilder +{ + ClassBuilder(const cxxopts::ParseResult& results, + const DeviceInfo& deviceInfo, + const std::vector& peripherals); + void setupBuilders(); + void build(); + +private: + const cxxopts::ParseResult& results; + const DeviceInfo& deviceInfo; + const std::vector& peripherals; + std::vector> builders; + std::stringstream outputStream; +}; + +#endif diff --git a/Src/IBuilder.hpp b/Src/IBuilder.hpp new file mode 100644 index 0000000..e785886 --- /dev/null +++ b/Src/IBuilder.hpp @@ -0,0 +1,12 @@ +#ifndef I_BUILDER +#define I_BUILDER + +#include + + +struct IBuilder{ + virtual void build(std::stringstream&) = 0; + virtual ~IBuilder() = default; +}; + +#endif diff --git a/Src/Peripheral.hpp b/Src/Peripheral.hpp index 37d7a57..f867296 100644 --- a/Src/Peripheral.hpp +++ b/Src/Peripheral.hpp @@ -3,7 +3,7 @@ #include #include - +#include enum class EAccess{ Read_Only, diff --git a/Src/XmlParser.cpp b/Src/XmlParser.cpp index 3ecc174..a0dd512 100644 --- a/Src/XmlParser.cpp +++ b/Src/XmlParser.cpp @@ -21,7 +21,7 @@ void XmlParser::parseXml(){ setDeviceInfoAttrib(deviceRoot, "version", deviceInfo.version); setDeviceInfoAttrib(deviceRoot, "resetValue", deviceInfo.resetValue); - deviceInfo.printDeviceInfo(); + // deviceInfo.printDeviceInfo(); //Iterate over all peripherals and append them to peripherals tinyxml2::XMLElement *peripheralsRoot = deviceRoot->FirstChildElement("peripherals"); @@ -68,9 +68,7 @@ void XmlParser::setDeviceInfoAttrib(tinyxml2::XMLElement* deviceRoot, const char 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; @@ -78,7 +76,6 @@ Peripheral XmlParser::parsePeripheral(tinyxml2::XMLElement* peripheralRoot) cons 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); @@ -111,7 +108,7 @@ Peripheral XmlParser::parsePeripheral(tinyxml2::XMLElement* peripheralRoot) cons } } } - peripheral.display(); + // peripheral.display(); return peripheral; } diff --git a/Src/XmlParser.hpp b/Src/XmlParser.hpp index ecb9136..3df6a4a 100644 --- a/Src/XmlParser.hpp +++ b/Src/XmlParser.hpp @@ -13,6 +13,12 @@ struct XmlParser{ XmlParser(const std::string& inputFile); std::optional isError() const; void parseXml(); + inline const DeviceInfo getDeviceInfo() const{ + return deviceInfo; + } + inline const std::vector getPeripherals() const{ + return peripherals; + } private: // tinyxml2::XMLElement* getDevice diff --git a/Src/main.cpp b/Src/main.cpp index 9649e17..dcc6387 100644 --- a/Src/main.cpp +++ b/Src/main.cpp @@ -1,6 +1,8 @@ #include #include #include +#include + int main(int argc, char** argv){ // Create and configure options for the program @@ -9,9 +11,9 @@ int main(int argc, char** argv){ ("i, input", "File to be parsed", cxxopts::value()) ("o, output", "OutputFile", cxxopts::value()); std::string inputFile, outputFile; + auto result = options.parse(argc, argv); try { - auto result = options.parse(argc, argv); if(result.count("input") != 1){ std::cout << "Missing input file!" << std::endl; return 1; @@ -35,4 +37,7 @@ int main(int argc, char** argv){ return 3; } xmlParser.parseXml(); + ClassBuilder classBuilder(result, xmlParser.getDeviceInfo(), xmlParser.getPeripherals()); + classBuilder.setupBuilders(); + classBuilder.build(); } \ No newline at end of file