Added builders

This commit is contained in:
Łukasz Czyż 2019-11-22 12:57:17 +01:00
parent 57a9cfc168
commit 04a24f9bbf
10 changed files with 158 additions and 39 deletions

View file

@ -8,8 +8,9 @@ include_directories(cxxopts/include)
include_directories(tinyxml2) include_directories(tinyxml2)
add_library(ClassBuilder Src/ClassBuilder.cpp) add_library(ClassBuilder Src/ClassBuilder.cpp)
add_library(Builders Src/Builders.cpp)
add_library(XmlParser Src/XmlParser.cpp) add_library(XmlParser Src/XmlParser.cpp)
add_library(tinyxml2 tinyxml2/tinyxml2.cpp) add_library(tinyxml2 tinyxml2/tinyxml2.cpp)
add_executable(svd2cpp Src/main.cpp) add_executable(svd2cpp Src/main.cpp)
target_link_libraries(svd2cpp ClassBuilder XmlParser tinyxml2) target_link_libraries(svd2cpp ClassBuilder Builders XmlParser tinyxml2)

39
Src/Builders.cpp Normal file
View file

@ -0,0 +1,39 @@
#include <Builders.hpp>
void ZeroPointerBuilder::build(std::stringstream& ss){
ss << "template <unsigned int zero = 0>\n"
"constexpr unsigned int *zeroVal = reinterpret_cast<unsigned int *>(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";
}

36
Src/Builders.hpp Normal file
View file

@ -0,0 +1,36 @@
#ifndef BUILDERS
#define BUILDERS
#include <IBuilder.hpp>
#include <sstream>
#include <Peripheral.hpp>
#include <sstream>
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

View file

@ -1,4 +1,6 @@
#include <ClassBuilder.hpp> #include <ClassBuilder.hpp>
#include <Builders.hpp>
ClassBuilder::ClassBuilder(const cxxopts::ParseResult& results, ClassBuilder::ClassBuilder(const cxxopts::ParseResult& results,
const DeviceInfo& deviceInfo, const DeviceInfo& deviceInfo,
@ -7,3 +9,17 @@ ClassBuilder::ClassBuilder(const cxxopts::ParseResult& results,
deviceInfo(deviceInfo), deviceInfo(deviceInfo),
peripherals(peripherals){ peripherals(peripherals){
} }
void ClassBuilder::setupBuilders(){
builders.push_back(std::make_unique<ZeroPointerBuilder>());
for(auto& peripheral : peripherals){
builders.push_back(std::make_unique<PeripheralBuilder>(peripheral));
}
}
void ClassBuilder::build(){
for(auto& builder : builders){
builder->build(outputStream);
}
std::cout << outputStream.str();
}

View file

@ -5,18 +5,25 @@
#include <DeviceInfo.hpp> #include <DeviceInfo.hpp>
#include <Peripheral.hpp> #include <Peripheral.hpp>
#include <vector> #include <vector>
#include <IBuilder.hpp>
#include <memory>
#include <sstream>
struct ClassBuilder struct ClassBuilder
{ {
ClassBuilder(const cxxopts::ParseResult& results, ClassBuilder(const cxxopts::ParseResult& results,
const DeviceInfo& deviceInfo, const DeviceInfo& deviceInfo,
const std::vector<Peripheral>& peripherals); const std::vector<Peripheral>& peripherals);
void setupBuilders();
void build();
private: private:
const cxxopts::ParseResult& results; const cxxopts::ParseResult& results;
const DeviceInfo& deviceInfo; const DeviceInfo& deviceInfo;
const std::vector<Peripheral>& peripherals; const std::vector<Peripheral>& peripherals;
std::vector<std::unique_ptr<IBuilder>> builders;
std::stringstream outputStream;
}; };
#endif #endif

12
Src/IBuilder.hpp Normal file
View file

@ -0,0 +1,12 @@
#ifndef I_BUILDER
#define I_BUILDER
#include <sstream>
struct IBuilder{
virtual void build(std::stringstream&) = 0;
virtual ~IBuilder() = default;
};
#endif

View file

@ -3,7 +3,7 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include <iostream>
enum class EAccess{ enum class EAccess{
Read_Only, Read_Only,

View file

@ -21,7 +21,7 @@ void XmlParser::parseXml(){
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");
@ -68,9 +68,7 @@ void XmlParser::setDeviceInfoAttrib(tinyxml2::XMLElement* deviceRoot, const char
std::cout << "Wrong field for access: " << text << std::endl; std::cout << "Wrong field for access: " << text << std::endl;
} }
} }
unsigned int peripheralCount = 0; //Debug
Peripheral XmlParser::parsePeripheral(tinyxml2::XMLElement* peripheralRoot) const{ Peripheral XmlParser::parsePeripheral(tinyxml2::XMLElement* peripheralRoot) const{
std::cout << "Peripheral: " << peripheralCount++ << std::endl; //Debug
//Check if peripheral is derived from previous one //Check if peripheral is derived from previous one
const char* attribute = peripheralRoot->Attribute("derivedFrom"); const char* attribute = peripheralRoot->Attribute("derivedFrom");
const bool isDerived = attribute != nullptr; const bool isDerived = attribute != nullptr;
@ -78,7 +76,6 @@ Peripheral XmlParser::parsePeripheral(tinyxml2::XMLElement* peripheralRoot) cons
Peripheral peripheral; Peripheral peripheral;
if(isDerived == true){ if(isDerived == true){
std::cout << "Derived from " << derivedFrom << std::endl;
//Find the base peripheral and copy it to the new one //Find the base peripheral and copy it to the new one
auto crit = [&](auto &periph) { return periph.name == derivedFrom; }; auto crit = [&](auto &periph) { return periph.name == derivedFrom; };
auto resultIt = std::find_if(peripherals.begin(), peripherals.end(), crit); 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; return peripheral;
} }

View file

@ -13,6 +13,12 @@ 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();
inline const DeviceInfo getDeviceInfo() const{
return deviceInfo;
}
inline const std::vector<Peripheral> getPeripherals() const{
return peripherals;
}
private: private:
// tinyxml2::XMLElement* getDevice // tinyxml2::XMLElement* getDevice

View file

@ -1,6 +1,8 @@
#include <iostream> #include <iostream>
#include <cxxopts.hpp> #include <cxxopts.hpp>
#include <XmlParser.hpp> #include <XmlParser.hpp>
#include <ClassBuilder.hpp>
int main(int argc, char** argv){ int main(int argc, char** argv){
// Create and configure options for the program // 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<std::string>()) ("i, input", "File to be parsed", cxxopts::value<std::string>())
("o, output", "OutputFile", cxxopts::value<std::string>()); ("o, output", "OutputFile", cxxopts::value<std::string>());
std::string inputFile, outputFile; std::string inputFile, outputFile;
auto result = options.parse(argc, argv);
try try
{ {
auto result = options.parse(argc, argv);
if(result.count("input") != 1){ if(result.count("input") != 1){
std::cout << "Missing input file!" << std::endl; std::cout << "Missing input file!" << std::endl;
return 1; return 1;
@ -35,4 +37,7 @@ int main(int argc, char** argv){
return 3; return 3;
} }
xmlParser.parseXml(); xmlParser.parseXml();
ClassBuilder classBuilder(result, xmlParser.getDeviceInfo(), xmlParser.getPeripherals());
classBuilder.setupBuilders();
classBuilder.build();
} }