From 73db73dbd3c5c6a27e022a5c724136ca6fc2ffe8 Mon Sep 17 00:00:00 2001 From: Amaury Pouly Date: Thu, 13 Jun 2013 01:50:14 +0200 Subject: regtools: modify description format and refactor tools Change the XML description to unify multi dev/reg in a clean fashion. Move the description parser to its own library. Fix the tester and headergen tools to work with the new format and library. Move the STMP3700/3780 descriptions to the new format (and fixes many errors as well). Drop the hwemulgen tool in favor on the upcoming hwstub tools revamp. Change-Id: I7119a187aab5c8b083cc5228cb1b248ee29f184d --- utils/regtools/headergen.cpp | 311 ++++++++++++++++++++++++++++++------------- 1 file changed, 218 insertions(+), 93 deletions(-) (limited to 'utils/regtools/headergen.cpp') diff --git a/utils/regtools/headergen.cpp b/utils/regtools/headergen.cpp index b6905363d8..fc1ce6fba6 100644 --- a/utils/regtools/headergen.cpp +++ b/utils/regtools/headergen.cpp @@ -7,7 +7,7 @@ * \/ \/ \/ \/ \/ * $Id$ * - * Copyright (C) 2002 by Amaury Pouly + * Copyright (C) 2013 by Amaury Pouly * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -18,22 +18,26 @@ * KIND, either express or implied. * ****************************************************************************/ -#include "desc_parser.hpp" +#include "soc_desc.hpp" #include #include #include #include +#include +#include +#include + +#define HEADERGEN_VERSION "2.1.7" #define error(...) do{ fprintf(stderr, __VA_ARGS__); exit(1); } while(0) std::string g_soc_name; std::string g_soc_dev; std::string g_soc_reg; +std::string g_soc_field; std::string g_soc_dev_regs_base; -std::string g_soc_dev_reg_core_name; namespace { - std::string tolower(const std::string s) { std::string res = s; @@ -47,11 +51,32 @@ std::string toupper(const std::string& s) std::transform(res.begin(), res.end(), res.begin(), ::toupper); return res; } +} + +template< typename T > +std::string to_str(const T& v) +{ + std::ostringstream oss; + oss << v; + return oss.str(); +} +template< typename T > +std::string to_hex(const T& v) +{ + std::ostringstream oss; + oss << std::hex << v; + return oss.str(); } -void fprint_copyright(FILE *f) +typedef std::pair< std::string, std::string > xml_ver_t; + +void fprint_copyright(FILE *f, const std::vector< xml_ver_t >& versions) { + std::ostringstream ver; + for(size_t i = 0; i < versions.size(); i++) + ver << " " << versions[i].first << ":" << versions[i].second; + fprintf(f,"\ /***************************************************************************\n\ * __________ __ ___.\n\ @@ -61,8 +86,10 @@ void fprint_copyright(FILE *f) * Firmware |____|_ /\\____/ \\___ >__|_ \\|___ /\\____/__/\\_ \\\n\ * \\/ \\/ \\/ \\/ \\/\n\ * This file was automatically generated by headergen, DO NOT EDIT it.\n\ + * headergen version: " HEADERGEN_VERSION "\n\ + * XML versions:%s\n\ *\n\ - * Copyright (C) 2012 by Amaury Pouly\n\ + * Copyright (C) 2013 by Amaury Pouly\n\ *\n\ * This program is free software; you can redistribute it and/or\n\ * modify it under the terms of the GNU General Public License\n\ @@ -72,7 +99,13 @@ void fprint_copyright(FILE *f) * This software is distributed on an \"AS IS\" basis, WITHOUT WARRANTY OF ANY\n\ * KIND, either express or implied.\n\ *\n\ - ****************************************************************************/\n"); + ****************************************************************************/\n", +ver.str().c_str()); +} + +void fprint_copyright(FILE *f, const xml_ver_t& version) +{ + fprint_copyright(f, std::vector< xml_ver_t >(1, version)); } void fprint_include_guard_ex(FILE *f, bool begin, const std::string& name) @@ -81,7 +114,6 @@ void fprint_include_guard_ex(FILE *f, bool begin, const std::string& name) { fprintf(f, "#ifndef %s\n", name.c_str()); fprintf(f, "#define %s\n", name.c_str()); - fprintf(f, "\n#include \"imx233.h\"\n"); } else fprintf(f, "#endif /* %s */\n", name.c_str()); @@ -89,108 +121,188 @@ void fprint_include_guard_ex(FILE *f, bool begin, const std::string& name) void fprint_include_guard(FILE *f, bool begin) { - std::string name = "__" + toupper(g_soc_name) + "__" + toupper(g_soc_dev) + std::string name = "__HEADERGEN__" + toupper(g_soc_name) + "__" + toupper(g_soc_dev) + "__H__"; fprint_include_guard_ex(f, begin, name); } -void fprint_fields(FILE *f, const std::vector< soc_reg_field_t >& fields) +struct define_align_context_t { - for(size_t i = 0; i < fields.size(); i++) + define_align_context_t():m_max_name(0) {} + void add(const std::string& name, const std::string& val) { - fprintf(f, "#define BM_%s_%s %#x\n", g_soc_dev_reg_core_name.c_str(), - fields[i].name.c_str(), fields[i].bitmask()); - fprintf(f, "#define BP_%s_%s %d\n", g_soc_dev_reg_core_name.c_str(), - fields[i].name.c_str(), fields[i].first_bit); - fprintf(f, "#define BF_%s_%s(v) (((v) << %d) & %#x)\n", - g_soc_dev_reg_core_name.c_str(), fields[i].name.c_str(), - fields[i].first_bit, fields[i].bitmask()); - if(fields[i].values.size() > 0) - { - fprintf(f, "#define BF_%s_%s_V(sym) ((BV_%s_%s__##sym << %d) & %#x)\n", - g_soc_dev_reg_core_name.c_str(), fields[i].name.c_str(), - g_soc_dev_reg_core_name.c_str(), fields[i].name.c_str(), - fields[i].first_bit, fields[i].bitmask()); - } - for(size_t j = 0; j < fields[i].values.size(); j++) + m_lines.push_back(std::make_pair(name, val)); + m_max_name = std::max(m_max_name, name.size()); + } + + void print(FILE *f) + { + std::string define = "#define "; + size_t align = define.size() + m_max_name + 1; + align = ((align + 3) / 4) * 4; + + for(size_t i = 0; i < m_lines.size(); i++) { - fprintf(f, "#define BV_%s_%s__%s %#x\n", g_soc_dev_reg_core_name.c_str(), - fields[i].name.c_str(), fields[i].values[j].name.c_str(), - fields[i].values[j].value); + std::string name = m_lines[i].first; + name.insert(name.end(), align - define.size() - name.size(), ' '); + fprintf(f, "%s%s%s\n", define.c_str(), name.c_str(), m_lines[i].second.c_str()); } } + + size_t m_max_name; + std::vector< std::pair< std::string, std::string > > m_lines; +}; + +void gen_soc_field(define_align_context_t& ctx, bool multidev, bool multireg, const soc_reg_field_t& field) +{ + std::string prefix = g_soc_dev + "_" + g_soc_reg + "_" + g_soc_field; + ctx.add("BP_" + prefix, to_str(field.first_bit)); + ctx.add("BM_" + prefix, "0x" + to_hex(field.bitmask())); + + for(size_t i = 0; i < field.value.size(); i++) + ctx.add("BV_" + prefix + "__" + field.value[i].name, "0x" + to_hex(field.value[i].value)); + + ctx.add("BF_" + prefix + "(v)", "(((v) << " + to_str(field.first_bit) + ") & 0x" + to_hex(field.bitmask()) + ")"); + + if(field.value.size() > 0) + ctx.add("BF_" + prefix + "_V(v)", "((BV_" + prefix + "__##v" + " << " + to_str(field.first_bit) + ") & 0x" + to_hex(field.bitmask()) + ")"); } -void fprint_reg(FILE *f, const soc_reg_t& reg) +void gen_soc_reg(FILE *f, bool multidev, const soc_reg_t& reg) { - g_soc_dev_reg_core_name = toupper(g_soc_dev) + "_" + toupper(reg.name); + bool multireg = reg.addr.size() > 1; - fprintf(f, "#define RA_%s %#x\n", g_soc_dev_reg_core_name.c_str(), reg.addr); - fprintf(f, "#define HW_%s HW_REG(%s, %s)\n", g_soc_dev_reg_core_name.c_str(), - toupper(g_soc_dev).c_str(), toupper(reg.name).c_str()); - if(reg.flags & REG_HAS_SCT) + static const char *suffix[] = {"", "_SET", "_CLR", "_TOG"}; + bool sct = !!(reg.flags & REG_HAS_SCT); + + fprintf(f, "/**\n"); + fprintf(f, " * Register: HW_%s_%s\n", g_soc_dev.c_str(), g_soc_reg.c_str()); + fprintf(f, " * Address:"); + if(multireg && reg.formula.type == REG_FORMULA_STRING) { - fprintf(f, "#define HW_%s_SET HW_SET(%s, %s)\n", g_soc_dev_reg_core_name.c_str(), - toupper(g_soc_dev).c_str(), toupper(reg.name).c_str()); - fprintf(f, "#define HW_%s_CLR HW_CLR(%s, %s)\n", g_soc_dev_reg_core_name.c_str(), - toupper(g_soc_dev).c_str(), toupper(reg.name).c_str()); - fprintf(f, "#define HW_%s_TOG HW_TOG(%s, %s)\n", g_soc_dev_reg_core_name.c_str(), - toupper(g_soc_dev).c_str(), toupper(reg.name).c_str()); + fprintf(f, " %s\n", reg.formula.string.c_str()); } - fprint_fields(f, reg.fields); - fprintf(f, "\n"); -} + else + { + for(size_t i = 0; i < reg.addr.size(); i++) + fprintf(f, " %#x", reg.addr[i].addr); + fprintf(f, "\n"); + } + fprintf(f, " * SCT: %s\n", sct ? "yes" : "no"); -void fprint_mreg(FILE *f, const soc_multireg_t& mreg) -{ + fprintf(f, "*/\n"); + + define_align_context_t ctx; + + for(int i = 0; i < (sct ? 4 : 1); i++) + { + std::ostringstream name; + name << "HW_" << g_soc_dev << "_" << g_soc_reg << suffix[i]; + if(multidev || multireg) + { + name << "("; + if(multidev) + name << "d"; + if(multidev && multireg) + name << ","; + if(multireg) + name << "n"; + name << ")"; + } + std::ostringstream value; + value << "(*(volatile unsigned long *)(" << g_soc_dev_regs_base; + if(multidev) + value << "(d)"; + value << " + "; + if(multireg) + { + if(reg.formula.type != REG_FORMULA_STRING) + printf("Warning: register HW_%s_%s has no formula !\n", g_soc_dev.c_str(), g_soc_reg.c_str()); + std::string formula = reg.formula.string.c_str(); + size_t pos = formula.find("n"); + while(pos != std::string::npos) + { + formula.replace(pos, 1, "(n)"); + pos = formula.find("n", pos + 2); + } + value << formula; + } + else + value << "0x" << std::hex << reg.addr[0].addr; + + if(sct) + value << " + 0x" << std::hex << (i * 4); + value << "))"; + + ctx.add(name.str(), value.str()); + } + + for(size_t i = 0; i < reg.field.size(); i++) + { + g_soc_field = reg.field[i].name; + gen_soc_field(ctx, multidev, multireg, reg.field[i]); + } + + ctx.print(f); + + fprintf(f, "\n"); } -void gen_dev_header(const std::string& filename, const soc_dev_t& dev) +void gen_soc_dev_header(const std::string& filename, const xml_ver_t& ver, const soc_dev_t& dev) { - g_soc_dev = dev.name; - printf(" Generate header for device %s: write to %s\n", dev.name.c_str(), - filename.c_str()); + /* + printf("Generate headers for soc %s, dev %s: use file %s\n", g_soc_name.c_str(), + g_soc_dev.c_str(), filename.c_str()); + */ FILE *f = fopen(filename.c_str(), "w"); if(f == NULL) - error("Cannot open file %s\n", filename.c_str()); - fprint_copyright(f); + { + printf("Cannot open %s for writing: %m\n", filename.c_str()); + return; + } + fprint_copyright(f, ver); fprint_include_guard(f, true); + + /* print base */ fprintf(f, "\n"); - g_soc_dev_regs_base = "RB_" + toupper(dev.name); - fprintf(f, "#define %s %#x\n", g_soc_dev_regs_base.c_str(), dev.addr); - fprintf(f, "\n"); + g_soc_dev_regs_base = "REGS_" + g_soc_dev + "_BASE"; + fprintf(f, "#define %s", g_soc_dev_regs_base.c_str()); - for(size_t i = 0; i < dev.regs.size(); i++) - fprint_reg(f, dev.regs[i]); - for(size_t i = 0; i < dev.multiregs.size(); i++) - fprint_mreg(f, dev.multiregs[i]); + if(dev.addr.size() > 1) + fprintf(f, "(i)"); + fprintf(f, " ("); + for(size_t i = 0; i < dev.addr.size() - 1; i++) + fprintf(f, "(i) == %d ? %#x : ", (int)i + 1, dev.addr[i].addr); + + fprintf(f, "%#x)\n", dev.addr[dev.addr.size() - 1].addr); + + fprintf(f, "\n"); + + /* print version */ + fprintf(f, "#define REGS_%s_VERSION \"%s\"\n\n", g_soc_dev.c_str(), dev.version.c_str()); + + for(size_t i = 0; i < dev.reg.size(); i++) + { + g_soc_reg = dev.reg[i].name; + gen_soc_reg(f, dev.addr.size() > 1, dev.reg[i]); + } + fprint_include_guard(f, false); fclose(f); } -void gen_mdev_header(const std::string& filename, const soc_multidev_t& dev) -{ - g_soc_dev = dev.name; - printf(" Generate header for multi device %s: write to %s\n", dev.name.c_str(), - filename.c_str()); -} - void gen_soc_headers(const std::string& prefix, const soc_t& soc) { - printf("Generate headers for soc %s: use directory %s (must exists)\n", soc.desc.c_str(), + printf("Generate headers for soc %s: use directory %s\n", soc.desc.c_str(), prefix.c_str()); - for(size_t i = 0; i < soc.devs.size(); i++) - { - std::string name = soc.devs[i].name; - name = tolower(name); - gen_dev_header(prefix + "/regs-" + name + ".h", soc.devs[i]); - } - for(size_t i = 0; i < soc.multidevs.size(); i++) + mkdir(prefix.c_str(), 0770); + + for(size_t i = 0; i < soc.dev.size(); i++) { - std::string name = soc.multidevs[i].name; - name = tolower(name); - gen_mdev_header(prefix + "/regs-" + name + ".h", soc.multidevs[i]); + g_soc_dev = soc.dev[i].name; + xml_ver_t ver(soc.name, soc.dev[i].version); + gen_soc_dev_header(prefix + "/regs-" + tolower(g_soc_dev.c_str()) + ".h", ver, soc.dev[i]); } } @@ -203,31 +315,30 @@ void gen_headers(const std::string& prefix, const std::vector< soc_t >& socs) } } -typedef std::map< std::string, std::vector< std::string > > general_dev_list_t; +typedef std::map< std::string, std::vector< std::pair< size_t, size_t > > > general_dev_list_t; general_dev_list_t build_general_dev_list(const std::vector< soc_t >& socs) { general_dev_list_t map; for(size_t i = 0; i < socs.size(); i++) { - for(size_t j = 0; j < socs[i].devs.size(); j++) - map[tolower(socs[i].devs[j].name)].push_back(socs[i].name); - for(size_t j = 0; j < socs[i].multidevs.size(); j++) - map[tolower(socs[i].multidevs[j].name)].push_back(socs[i].name); + for(size_t j = 0; j < socs[i].dev.size(); j++) + map[tolower(socs[i].dev[j].name)].push_back(std::make_pair(i,j)); } return map; } void gen_select_header(const std::string& filename, const std::string& dev, - const std::vector< std::string >& socs) + const std::vector< std::string >& socs, const std::vector< xml_ver_t >& ver) { + /* printf("Generate select header for device %s: write to %s\n", dev.c_str(), filename.c_str()); - + */ std::string guard = "__SELECT__" + toupper(dev) + "__H__"; FILE *f = fopen(filename.c_str(), "w"); if(f == NULL) error("Cannot open file %s\n", filename.c_str()); - fprint_copyright(f); + fprint_copyright(f, ver); fprint_include_guard_ex(f, true, guard); fprintf(f, "\n"); @@ -251,24 +362,38 @@ void gen_selectors(const std::string& prefix, const std::vector< soc_t >& socs) { general_dev_list_t map = build_general_dev_list(socs); for(general_dev_list_t::iterator it = map.begin(); it != map.end(); ++it) - gen_select_header(prefix + "/regs-" + it->first + ".h", it->first, it->second); + { + std::vector< xml_ver_t > ver; + std::vector< std::string > names; + for(size_t i = 0; i < it->second.size(); i++) + { + size_t soc_nr = it->second[i].first; + size_t dev_in_soc_nr = it->second[i].second; + ver.push_back(std::make_pair(socs[soc_nr].name, socs[soc_nr].dev[dev_in_soc_nr].version)); + names.push_back(socs[soc_nr].name); + } + gen_select_header(prefix + "/regs-" + it->first + ".h", it->first, names, ver); + } } void usage() { - printf("usage: headergen \n"); + printf("usage: headergen \n"); exit(1); } int main(int argc, char **argv) { - if(argc != 3) + if(argc < 3) usage(); std::vector< soc_t > socs; - bool ret = parse_soc_desc(argv[1], socs); - printf("parse result: %d\n", ret); - if(!ret) return 1; - gen_headers(argv[2], socs); - gen_selectors(argv[2], socs); + for(int i = 1; i < argc - 1; i++) + if(!soc_desc_parse_xml(argv[i], socs)) + { + printf("Cannot parse %s\n", argv[i]); + return 1; + } + gen_headers(argv[argc - 1], socs); + gen_selectors(argv[argc - 1], socs); return 0; } \ No newline at end of file -- cgit v1.2.3