aboutsummaryrefslogtreecommitdiffstats
path: root/svd2funreg/main.cpp
blob: d19d54d1035c436192aec7404178e94f4ab58517 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#include "pugixml.hpp"

#include <cstdint>
#include <cstdlib>
#include <iostream>
#include <string>

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);

int main(int argc, char *argv[])
{
    if (argc < 2)
        return -1;

    pugi::xml_document doc;
    pugi::xml_parse_result result = doc.load_file(argv[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"))
    {
        parse_peripheral(node);
    }

    std::cout << "}\n";
}

void parse_peripheral(const pugi::xml_node& node)
{
    const auto base = std::strtol(node.child_value("baseAddress"), nullptr, 0);

    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)
{
    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<";
    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";

    for (auto n : node.child("fields").children("field"))
        parse_field(name, n);

    std::cout << "        };\n";
}

void parse_field(const char *reg, const pugi::xml_node& node)
{
    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");

    if (name == reg)
        name += "_val";

    std::cout << "            using " << name << " = fr::RegisterMask<"
              << reg << ", (0x" << (1 << width) - 1 << "u << 0x" << offs << "u)>;\n";
}