]> code.bitgloo.com Git - clyne/funreg.git/commitdiff
better svd parsing master
authorClyne Sullivan <clyne@bitgloo.com>
Wed, 5 Feb 2025 20:53:00 +0000 (15:53 -0500)
committerClyne Sullivan <clyne@bitgloo.com>
Wed, 5 Feb 2025 20:53:00 +0000 (15:53 -0500)
funreg.hpp
svd2funreg/Makefile
svd2funreg/main.cpp

index 9dc54496b5a9fb02595d1d9ef78a2d6857f7025e..db0bb37ec9053fd78adbd6f5905d223044c424df 100644 (file)
@@ -192,9 +192,9 @@ struct Register {
     // bit-mask created by merging all provided bit-masks.
     // If no masks are given, a mask selecting all bits is used.
     template<typename... Masks>
     // bit-mask created by merging all provided bit-masks.
     // If no masks are given, a mask selecting all bits is used.
     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)
                 write(fn(read(), mask));
         } else {
             if constexpr (mask)
                 write(fn(read(), mask));
         } else {
@@ -205,7 +205,7 @@ struct Register {
     // Takes a list of bit-masks, and returns a merged mask of those which are
     // meant for this register.
     template<typename... Masks>
     // Takes a list of bit-masks, and returns a merged mask of those which are
     // meant for this register.
     template<typename... Masks>
-    static auto mergeMasks() {
+    static constexpr auto mergeMasks() {
         if constexpr (sizeof...(Masks) > 0) {
             if constexpr ((isThis<typename Masks::reg> | ...)) {
                 auto mask =
         if constexpr (sizeof...(Masks) > 0) {
             if constexpr ((isThis<typename Masks::reg> | ...)) {
                 auto mask =
index 743d59a254f0c0444288be8cebe9b1c0974869c6..7fd2c5ee5b881e069113ebac9ae86cf0df1363f8 100644 (file)
@@ -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
index d19d54d1035c436192aec7404178e94f4ab58517..15033818f05987622a377a4c1d15e1b98cd5d281 100644 (file)
@@ -1,13 +1,50 @@
 #include "pugixml.hpp"
 
 #include "pugixml.hpp"
 
+#include <cctype>
 #include <cstdint>
 #include <cstdlib>
 #include <iostream>
 #include <cstdint>
 #include <cstdlib>
 #include <iostream>
+#include <map>
 #include <string>
 #include <string>
+#include <vector>
 
 
-static void parse_peripheral(const pugi::xml_node& node);
-static void parse_register(uint32_t base_address, const pugi::xml_node& node);
-static void parse_field(const char *reg, const pugi::xml_node& node);
+struct Field {
+    std::string reg;
+    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)
         return -1;
 
     if (!result)
         return -1;
 
-    std::cout << std::hex;
-    std::cout << "namespace " << doc.child("device").child_value("name")
-              << " {\n";
-
     for (auto node : doc.child("device")
                         .child("peripherals")
                         .children("peripheral"))
     {
     for (auto node : doc.child("device")
                         .child("peripherals")
                         .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";
+void Field::operator()()
+{
+    std::cout << "            using " << name << " = RegisterMask<"
+              << reg << ", (0x" << (1 << width) - 1 << "u << 0x" << offset << "u)>;\n";
+}
 
 
-    for (auto n : node.child("registers").children("register"))
-        parse_register(base, n);
+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);
+        }
+    }
 
 
-    std::cout << "    }\n";
+    for (auto n : node.child("fields").children("field"))
+        fields.emplace_back(name.c_str(), n);
 }
 
 }
 
-void parse_register(uint32_t base_address, const pugi::xml_node& node)
+void Register::operator()(uint32_t base)
 {
 {
-    const auto offs = std::strtol(node.child_value("addressOffset"), nullptr, 0);
-    const auto size = std::strtol(node.child_value("size"), nullptr, 0);
-    const auto name = node.child_value("name");
-
-    std::cout << "        struct " << name << " : public fr::MemRegister<";
+    std::cout << "        struct " << name << " : public MemRegister<";
     switch (size) {
     case  8: std::cout << "uint8_t, "; break;
     case 16: std::cout << "uint16_t, "; break;
     case 32:
     default: std::cout << "uint32_t, "; break;
     }
     switch (size) {
     case  8: std::cout << "uint8_t, "; break;
     case 16: std::cout << "uint16_t, "; break;
     case 32:
     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"))
-        parse_field(name, n);
+    for (auto& f : fields) f();
 
     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);
-    const auto width = std::strtol(node.child_value("bitWidth"), nullptr, 0);
-    std::string name = node.child_value("name");
+    for (auto n : node.child("registers").children("register")) {
+        registers.emplace_back(name, n);
+        group += registers.back().name;
+        group += ", ";
+    }
+}
 
 
-    if (name == reg)
-        name += "_val";
+Peripheral::Peripheral(const pugi::xml_node& node, const Peripheral& derived):
+    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 += ", ";
+    }
+}
 
 
-    std::cout << "            using " << name << " = fr::RegisterMask<"
-              << reg << ", (0x" << (1 << width) - 1 << "u << 0x" << offs << "u)>;\n";
+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";
 }
 
 }