#include "pugixml.hpp" #include #include #include #include #include #include #include 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 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 registers; Peripheral() = default; Peripheral(const pugi::xml_node& node); Peripheral(const pugi::xml_node& node, const Peripheral& derived); void operator()(); }; std::map device; 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; for (auto node : doc.child("device") .child("peripherals") .children("peripheral")) { 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"; } 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)) { if (name == reg) name = "val"; } void Field::operator()() { std::cout << " using " << name << " = RegisterMask<" << reg << ", (0x" << (1 << width) - 1 << "u << 0x" << offset << "u)>;\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); } } 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) { 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 + offset << "> {\n"; for (auto& f : fields) f(); std::cout << " };\n"; } Peripheral::Peripheral(const pugi::xml_node& node): name(node.child_value("name")), base(std::strtol(node.child_value("baseAddress"), nullptr, 0)) { for (auto n : node.child("registers").children("register")) { registers.emplace_back(name, n); group += registers.back().name; group += ", "; } } 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 += ", "; } } 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"; }