better svd parsing
This commit is contained in:
parent
6d33ec1220
commit
9be811f585
@ -192,9 +192,9 @@ struct Register {
|
|||||||
// bit-mask created by merging all provided bit-masks.
|
// bit-mask created by merging all provided bit-masks.
|
||||||
// If no masks are given, a mask selecting all bits is used.
|
// If no masks are given, a mask selecting all bits is used.
|
||||||
template<typename... Masks>
|
template<typename... Masks>
|
||||||
static void apply(auto fn) {
|
static constexpr void apply(auto fn) {
|
||||||
if constexpr (sizeof...(Masks) > 0) {
|
if constexpr (sizeof...(Masks) > 0) {
|
||||||
auto mask = mergeMasks<Masks...>();
|
constexpr auto mask = mergeMasks<Masks...>();
|
||||||
if constexpr (mask)
|
if constexpr (mask)
|
||||||
write(fn(read(), mask));
|
write(fn(read(), mask));
|
||||||
} else {
|
} else {
|
||||||
@ -205,7 +205,7 @@ struct Register {
|
|||||||
// Takes a list of bit-masks, and returns a merged mask of those which are
|
// Takes a list of bit-masks, and returns a merged mask of those which are
|
||||||
// meant for this register.
|
// meant for this register.
|
||||||
template<typename... Masks>
|
template<typename... Masks>
|
||||||
static auto mergeMasks() {
|
static constexpr auto mergeMasks() {
|
||||||
if constexpr (sizeof...(Masks) > 0) {
|
if constexpr (sizeof...(Masks) > 0) {
|
||||||
if constexpr ((isThis<typename Masks::reg> | ...)) {
|
if constexpr ((isThis<typename Masks::reg> | ...)) {
|
||||||
auto mask =
|
auto mask =
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
all:
|
all:
|
||||||
g++ -o main main.cpp pugixml/src/pugixml.cpp -I pugixml/src
|
g++ -o main main.cpp pugixml/src/pugixml.cpp -I pugixml/src -std=c++20
|
||||||
|
@ -1,13 +1,50 @@
|
|||||||
#include "pugixml.hpp"
|
#include "pugixml.hpp"
|
||||||
|
|
||||||
|
#include <cctype>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
static void parse_peripheral(const pugi::xml_node& node);
|
struct Field {
|
||||||
static void parse_register(uint32_t base_address, const pugi::xml_node& node);
|
std::string reg;
|
||||||
static void parse_field(const char *reg, const pugi::xml_node& node);
|
std::string name;
|
||||||
|
int offset;
|
||||||
|
int width;
|
||||||
|
|
||||||
|
Field() = default;
|
||||||
|
Field(const char *r, const pugi::xml_node& node);
|
||||||
|
void operator()();
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Register {
|
||||||
|
std::string name;
|
||||||
|
int offset;
|
||||||
|
int size;
|
||||||
|
|
||||||
|
std::vector<Field> fields;
|
||||||
|
|
||||||
|
Register() = default;
|
||||||
|
Register(std::string peri, const pugi::xml_node& node);
|
||||||
|
void operator()(uint32_t base);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Peripheral {
|
||||||
|
std::string name;
|
||||||
|
std::string group;
|
||||||
|
uint32_t base;
|
||||||
|
|
||||||
|
std::vector<Register> registers;
|
||||||
|
|
||||||
|
Peripheral() = default;
|
||||||
|
Peripheral(const pugi::xml_node& node);
|
||||||
|
Peripheral(const pugi::xml_node& node, const Peripheral& derived);
|
||||||
|
void operator()();
|
||||||
|
};
|
||||||
|
|
||||||
|
std::map<std::string, Peripheral> device;
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
@ -19,63 +56,111 @@ int main(int argc, char *argv[])
|
|||||||
if (!result)
|
if (!result)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
std::cout << std::hex;
|
|
||||||
std::cout << "namespace " << doc.child("device").child_value("name")
|
|
||||||
<< " {\n";
|
|
||||||
|
|
||||||
for (auto node : doc.child("device")
|
for (auto node : doc.child("device")
|
||||||
.child("peripherals")
|
.child("peripherals")
|
||||||
.children("peripheral"))
|
.children("peripheral"))
|
||||||
{
|
{
|
||||||
parse_peripheral(node);
|
const auto df = node.attribute("derivedFrom");
|
||||||
|
Peripheral p = df ? Peripheral {node, device[df.value()]} : Peripheral {node};
|
||||||
|
|
||||||
|
device[p.name] = p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::cout << std::hex;
|
||||||
|
std::cout << "#include \"funreg.hpp\"\n\n"
|
||||||
|
<< "namespace " << doc.child("device").child_value("name")
|
||||||
|
<< " {\n"
|
||||||
|
<< " using namespace fr;\n";
|
||||||
|
|
||||||
|
for (auto& [_, p] : device) p();
|
||||||
|
|
||||||
std::cout << "}\n";
|
std::cout << "}\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
void parse_peripheral(const pugi::xml_node& node)
|
Field::Field(const char *r, const pugi::xml_node& node):
|
||||||
|
reg(r),
|
||||||
|
name(node.child_value("name")),
|
||||||
|
offset(std::strtol(node.child_value("bitOffset"), nullptr, 0)),
|
||||||
|
width(std::strtol(node.child_value("bitWidth"), nullptr, 0))
|
||||||
{
|
{
|
||||||
const auto base = std::strtol(node.child_value("baseAddress"), nullptr, 0);
|
if (name == reg)
|
||||||
|
name = "val";
|
||||||
std::cout << " namespace " << node.child_value("name") << " {\n";
|
|
||||||
|
|
||||||
for (auto n : node.child("registers").children("register"))
|
|
||||||
parse_register(base, n);
|
|
||||||
|
|
||||||
std::cout << " }\n";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void parse_register(uint32_t base_address, const pugi::xml_node& node)
|
void Field::operator()()
|
||||||
{
|
{
|
||||||
const auto offs = std::strtol(node.child_value("addressOffset"), nullptr, 0);
|
std::cout << " using " << name << " = RegisterMask<"
|
||||||
const auto size = std::strtol(node.child_value("size"), nullptr, 0);
|
<< reg << ", (0x" << (1 << width) - 1 << "u << 0x" << offset << "u)>;\n";
|
||||||
const auto name = node.child_value("name");
|
}
|
||||||
|
|
||||||
std::cout << " struct " << name << " : public fr::MemRegister<";
|
Register::Register(std::string peri, const pugi::xml_node& node):
|
||||||
|
name(node.child_value("name")),
|
||||||
|
offset(std::strtol(node.child_value("addressOffset"), nullptr, 0)),
|
||||||
|
size(std::strtol(node.child_value("size"), nullptr, 0))
|
||||||
|
{
|
||||||
|
if (isdigit(peri.back())) {
|
||||||
|
if (name.starts_with(name.substr(0, name.size() - 1))
|
||||||
|
&& name.at(peri.size() - 1) == '_')
|
||||||
|
{
|
||||||
|
name = name.substr(peri.size());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (name.starts_with(name.substr(0, name.size()))
|
||||||
|
&& name.at(peri.size()) == '_')
|
||||||
|
{
|
||||||
|
name = name.substr(peri.size() + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto n : node.child("fields").children("field"))
|
||||||
|
fields.emplace_back(name.c_str(), n);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Register::operator()(uint32_t base)
|
||||||
|
{
|
||||||
|
std::cout << " struct " << name << " : public MemRegister<";
|
||||||
switch (size) {
|
switch (size) {
|
||||||
case 8: std::cout << "uint8_t, "; break;
|
case 8: std::cout << "uint8_t, "; break;
|
||||||
case 16: std::cout << "uint16_t, "; break;
|
case 16: std::cout << "uint16_t, "; break;
|
||||||
case 32:
|
case 32:
|
||||||
default: std::cout << "uint32_t, "; break;
|
default: std::cout << "uint32_t, "; break;
|
||||||
}
|
}
|
||||||
std::cout << "0x" << base_address + offs << "> {\n";
|
std::cout << "0x" << base + offset << "> {\n";
|
||||||
|
|
||||||
for (auto n : node.child("fields").children("field"))
|
for (auto& f : fields) f();
|
||||||
parse_field(name, n);
|
|
||||||
|
|
||||||
std::cout << " };\n";
|
std::cout << " };\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
void parse_field(const char *reg, const pugi::xml_node& node)
|
Peripheral::Peripheral(const pugi::xml_node& node):
|
||||||
|
name(node.child_value("name")),
|
||||||
|
base(std::strtol(node.child_value("baseAddress"), nullptr, 0))
|
||||||
{
|
{
|
||||||
const auto offs = std::strtol(node.child_value("bitOffset"), nullptr, 0);
|
for (auto n : node.child("registers").children("register")) {
|
||||||
const auto width = std::strtol(node.child_value("bitWidth"), nullptr, 0);
|
registers.emplace_back(name, n);
|
||||||
std::string name = node.child_value("name");
|
group += registers.back().name;
|
||||||
|
group += ", ";
|
||||||
if (name == reg)
|
}
|
||||||
name += "_val";
|
}
|
||||||
|
|
||||||
std::cout << " using " << name << " = fr::RegisterMask<"
|
Peripheral::Peripheral(const pugi::xml_node& node, const Peripheral& derived):
|
||||||
<< reg << ", (0x" << (1 << width) - 1 << "u << 0x" << offs << "u)>;\n";
|
name(node.child_value("name")),
|
||||||
|
base(std::strtol(node.child_value("baseAddress"), nullptr, 0)),
|
||||||
|
registers(derived.registers)
|
||||||
|
{
|
||||||
|
for (auto& r : registers) {
|
||||||
|
group += r.name;
|
||||||
|
group += ", ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Peripheral::operator()()
|
||||||
|
{
|
||||||
|
std::cout << " namespace " << name << " {\n";
|
||||||
|
|
||||||
|
for (auto& r : registers) r(base);
|
||||||
|
|
||||||
|
std::cout << " using ALL = RegisterGroup<" << group.substr(0, group.size() - 2) << ">;\n";
|
||||||
|
std::cout << " }\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user