summaryrefslogtreecommitdiffstats
path: root/utils
diff options
context:
space:
mode:
authorAmaury Pouly <amaury.pouly@gmail.com>2013-06-13 17:28:15 +0200
committerAmaury Pouly <amaury.pouly@gmail.com>2013-06-15 22:27:33 +0200
commit97b9ade63945fd8b8261fb0cf1dd0aa225c1a319 (patch)
treecfe7b8b740deae73303ed86d11b43488d2daba25 /utils
parentb6ddbc41a51ef066063378ca1101b7f105f7cc6f (diff)
downloadrockbox-97b9ade63945fd8b8261fb0cf1dd0aa225c1a319.tar.gz
rockbox-97b9ade63945fd8b8261fb0cf1dd0aa225c1a319.zip
regtools: improve header generator
The generator now has more options to generate or not selectors. It can also generate a macro header containing lots of using macros for register operations. Change-Id: I9dd6b4bdc7daeabd1a2c9365ce082358475721b5
Diffstat (limited to 'utils')
-rw-r--r--utils/regtools/headergen.cpp227
1 files changed, 214 insertions, 13 deletions
diff --git a/utils/regtools/headergen.cpp b/utils/regtools/headergen.cpp
index fc1ce6fba6..0a65388686 100644
--- a/utils/regtools/headergen.cpp
+++ b/utils/regtools/headergen.cpp
@@ -26,11 +26,16 @@
#include <sstream>
#include <sys/stat.h>
#include <sys/types.h>
+#include <getopt.h>
#define HEADERGEN_VERSION "2.1.7"
#define error(...) do{ fprintf(stderr, __VA_ARGS__); exit(1); } while(0)
+bool g_gen_selector = false;
+
+std::string g_macro_filename;
+
std::string g_soc_name;
std::string g_soc_dev;
std::string g_soc_reg;
@@ -86,8 +91,10 @@ void fprint_copyright(FILE *f, const std::vector< xml_ver_t >& versions)
* Firmware |____|_ /\\____/ \\___ >__|_ \\|___ /\\____/__/\\_ \\\n\
* \\/ \\/ \\/ \\/ \\/\n\
* This file was automatically generated by headergen, DO NOT EDIT it.\n\
- * headergen version: " HEADERGEN_VERSION "\n\
- * XML versions:%s\n\
+ * headergen version: " HEADERGEN_VERSION "\n");
+ if(versions.size() > 0)
+ fprintf(f, " * XML versions:%s\n", ver.str().c_str());
+ fprintf(f,"\
*\n\
* Copyright (C) 2013 by Amaury Pouly\n\
*\n\
@@ -99,8 +106,7 @@ void fprint_copyright(FILE *f, const std::vector< xml_ver_t >& versions)
* This software is distributed on an \"AS IS\" basis, WITHOUT WARRANTY OF ANY\n\
* KIND, either express or implied.\n\
*\n\
- ****************************************************************************/\n",
-ver.str().c_str());
+ ****************************************************************************/\n");
}
void fprint_copyright(FILE *f, const xml_ver_t& version)
@@ -108,6 +114,11 @@ void fprint_copyright(FILE *f, const xml_ver_t& version)
fprint_copyright(f, std::vector< xml_ver_t >(1, version));
}
+void fprint_copyright(FILE *f)
+{
+ fprint_copyright(f, std::vector< xml_ver_t >());
+}
+
void fprint_include_guard_ex(FILE *f, bool begin, const std::string& name)
{
if(begin)
@@ -262,6 +273,8 @@ void gen_soc_dev_header(const std::string& filename, const xml_ver_t& ver, const
}
fprint_copyright(f, ver);
fprint_include_guard(f, true);
+ if(g_macro_filename.size() > 0)
+ fprintf(f, "#include \"%s\"\n", g_macro_filename.c_str());
/* print base */
fprintf(f, "\n");
@@ -311,7 +324,10 @@ void gen_headers(const std::string& prefix, const std::vector< soc_t >& socs)
for(size_t i = 0; i < socs.size(); i++)
{
g_soc_name = socs[i].name;
- gen_soc_headers(prefix + "/" + socs[i].name, socs[i]);
+ std::string dir = prefix;
+ if(g_gen_selector)
+ dir += "/" + socs[i].name;
+ gen_soc_headers(dir, socs[i]);
}
}
@@ -330,16 +346,14 @@ general_dev_list_t build_general_dev_list(const std::vector< soc_t >& socs)
void gen_select_header(const std::string& filename, const std::string& dev,
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, ver);
fprint_include_guard_ex(f, true, guard);
+ if(g_macro_filename.size() > 0)
+ fprintf(f, "#include \"%s\"\n", g_macro_filename.c_str());
fprintf(f, "\n");
for(size_t i = 0; i < socs.size(); i++)
@@ -360,6 +374,7 @@ void gen_select_header(const std::string& filename, const std::string& dev,
void gen_selectors(const std::string& prefix, const std::vector< soc_t >& socs)
{
+ printf("Generate select headers: use directory %s\n", prefix.c_str());
general_dev_list_t map = build_general_dev_list(socs);
for(general_dev_list_t::iterator it = map.begin(); it != map.end(); ++it)
{
@@ -376,24 +391,210 @@ void gen_selectors(const std::string& prefix, const std::vector< soc_t >& socs)
}
}
+void gen_macro_list(FILE *f, const std::string& prefix, int count, int nr_digits,
+ const std::string& sep, int max_per_line = 1000, const std::string& align = "")
+{
+ for(int i = 1; i <= count;)
+ {
+ for(int j = i; j <= std::min(count, i + max_per_line - 1); j++)
+ {
+ fprintf(f, "%s%0*d", prefix.c_str(), nr_digits, j);
+ if(j < count)
+ fprintf(f, "%s", sep.c_str());
+ }
+ i += max_per_line;
+ if(i <= count)
+ fprintf(f, "\\\n%s", align.c_str());
+ }
+}
+
+void gen_macro(const std::string& filename, bool variadic)
+{
+ printf("Generate %smacro header: use %s\n", variadic ? "": "non-variadic ",
+ filename.c_str());
+ std::string guard = "__REGS__MACRO__H__";
+ FILE *f = fopen(filename.c_str(), "w");
+ if(f == NULL)
+ error("Cannot open file %s\n", filename.c_str());
+ fprint_copyright(f);
+ fprint_include_guard_ex(f, true, guard);
+ fprintf(f, "\n");
+
+#define REG_WRITE "REG_WRITE"
+ fprintf(f, "#ifndef %s\n", REG_WRITE);
+ fprintf(f, "#define %s(var,value) ((var) = (value))\n", REG_WRITE);
+ fprintf(f, "#endif /* %s */\n", REG_WRITE);
+ fprintf(f, "\n");
+
+#define REG_READ "REG_READ"
+ fprintf(f, "#ifndef %s\n", REG_READ);
+ fprintf(f, "#define %s(var) (var)\n", REG_READ);
+ fprintf(f, "#endif /* %s */\n", REG_READ);
+ fprintf(f, "\n");
+
+ const int MAX_NARGS = 32;
+
+ fprintf(f, "\
+#define BF_SET(reg, field) "REG_WRITE"(HW_##reg##_SET, BM_##reg##_##field)\n\
+#define BF_CLR(reg, field) "REG_WRITE"(HW_##reg##_CLR, BM_##reg##_##field)\n\
+#define BF_TOG(reg, field) "REG_WRITE"(HW_##reg##_TOG, BM_##reg##_##field)\n\
+\n\
+#define BF_SETV(reg, field, v) "REG_WRITE"(HW_##reg##_SET, BF_##reg##_##field(v))\n\
+#define BF_CLRV(reg, field, v) "REG_WRITE"(HW_##reg##_CLR, BF_##reg##_##field(v))\n\
+#define BF_TOGV(reg, field, v) "REG_WRITE"(HW_##reg##_TOG, BF_##reg##_##field(v))\n\
+\n\
+#define BF_RDX(val, reg, field) (("REG_READ"(val) & BM_##reg##_##field) >> BP_##reg##_##field)\n\
+#define BF_RD(reg, field) BF_RDX("REG_READ"(HW_##reg), reg, field)\n\
+#define BF_WRX(val, reg, field, v) "REG_WRITE"(val, ("REG_READ"(val) & ~BM_##reg##_##field) | (((v) << BP_##reg##_##field) & BM_##reg##_##field))\n\
+#define BF_WR(reg, field, v) BF_WRX(HW_##reg, reg, field, v)\n\
+#define BF_WR_V(reg, field, sy) BF_WR(reg, field, BV_##reg##_##field##__##sy)\n\
+#define BF_WR_VX(val, reg, field, sy) BF_WRX(val, reg, field, BV_##reg##_##field##__##sy)\n\
+\n\
+#define BF_SETn(reg, n, field) "REG_WRITE"(HW_##reg##_SET(n), BM_##reg##_##field)\n\
+#define BF_CLRn(reg, n, field) "REG_WRITE"(HW_##reg##_CLR(n), BM_##reg##_##field)\n\
+#define BF_TOGn(reg, n, field) "REG_WRITE"(HW_##reg##_TOG(n), BM_##reg##_##field)\n\
+\n\
+#define BF_SETVn(reg, n, field, v) "REG_WRITE"(HW_##reg##_SET(n), BF_##reg##_##field(v))\n\
+#define BF_CLRVn(reg, n, field, v) "REG_WRITE"(HW_##reg##_CLR(n), BF_##reg##_##field(v))\n\
+#define BF_TOGVn(reg, n, field, v) "REG_WRITE"(HW_##reg##_TOG(n), BF_##reg##_##field(v))\n\
+\n\
+#define BF_RDn(reg, n, field) BF_RDX(HW_##reg(n), reg, field)\n\
+#define BF_WRn(reg, n, field, v) BF_WRX(HW_##reg(n), reg, field, v)\n\
+#define BF_WRn_V(reg, n, field, sy) BF_WRn(reg, n, field, BV_##reg##_##field##__##sy)\n\
+\n");
+
+ for(int nargs = 1; nargs <= MAX_NARGS; nargs++)
+ {
+ fprintf(f, "#define BM_OR%d(reg, ", nargs);
+ gen_macro_list(f, "f", nargs, 2, ", ", 10, " ");
+ fprintf(f, ") \\\n (");
+ gen_macro_list(f, "BM_##reg##_##f", nargs, 2, " | ", 4, " ");
+ fprintf(f, ")\n");
+ }
+ fprintf(f, "\n");
+
+ for(int nargs = 1; nargs <= MAX_NARGS; nargs++)
+ {
+ fprintf(f, "#define BF_OR%d(reg, ", nargs);
+ gen_macro_list(f, "f", nargs, 2, ", ", 10, " ");
+ fprintf(f, ") \\\n (");
+ gen_macro_list(f, "BF_##reg##_##f", nargs, 2, " | ", 4, " ");
+ fprintf(f, ")\n");
+ }
+ fprintf(f, "\n");
+
+ if(variadic)
+ {
+ fprintf(f, "#define REG_NARG(...) REG_NARGS_(__VA_ARGS__");
+ for(int i = MAX_NARGS; i >= 1; i--)
+ fprintf(f, ", %d", i);
+ fprintf(f, ")\n");
+ fprintf(f, "#define REG_NARGS_(");
+ gen_macro_list(f, "_", MAX_NARGS, 1, ", ");
+ fprintf(f, ", N, ...) N\n\n");
+
+ fprintf(f, "#define REG_VARIADIC(macro, reg, ...) REG_VARIADIC_(macro, NARG(__VA_ARGS__), reg, __VA_ARGS__)\n");
+ fprintf(f, "#define REG_VARIADIC_(macro, cnt, reg, ...) REG_VARIADIC__(macro, cnt, reg, __VA_ARGS__)\n");
+ fprintf(f, "#define REG_VARIADIC__(macro, cnt, reg, ...) REG_VARIADIC___(macro##cnt, reg, ...)\n");
+ fprintf(f, "#define REG_VARIADIC___(macro, reg, ...) macro(reg, __VA_ARGS__)\n\n");
+
+ fprintf(f, "#define BM_OR(reg, ...) REG_VARIADIC(BM_OR, reg, __VA_ARGS__)\n");
+ fprintf(f, "#define BF_OR(reg, ...) REG_VARIADIC(BF_OR, reg, __VA_ARGS__)\n");
+ }
+
+ fprint_include_guard_ex(f, false, guard);
+ fclose(f);
+}
+
void usage()
{
- printf("usage: headergen <desc files...> <output directory>\n");
+ printf("usage: headergen [options] <desc files...> <output directory>\n");
+ printf("options:\n");
+ printf(" -?/--help Dispaly this help\n");
+ printf(" -s/--selector Always produce selector files\n");
+ printf(" -m/--no-macro Do not generate a macro file with helpers\n");
+ printf(" -i/--no-include Do not include the macro file in the headers\n");
+ printf(" -v/--no-variadic Do not generate variadic macros\n");
+ printf("Default option is to generate a macro file with variadic macros.\n");
+ printf("Default option is to include the macro file in the headers.\n");
+ printf("Default option is to generate selector files only for two or more socs.\n");
+ printf("Default option is to create one subdirectory per soc, except if no\n");
+ printf("selector files are needed. The subdirectories will be created if\n");
+ printf("necessary.\n");
exit(1);
}
int main(int argc, char **argv)
{
- if(argc < 3)
+ bool force_selector = false;
+ bool no_variadic = false;
+ bool no_macro = false;
+ bool no_include = false;
+ if(argc <= 1)
usage();
+
+ while(1)
+ {
+ static struct option long_options[] =
+ {
+ {"help", no_argument, 0, '?'},
+ {"selector", no_argument, 0, 's'},
+ {"no-macro", no_argument, 0, 'm'},
+ {"no-include", no_argument, 0, 'i'},
+ {"no-variadic", no_argument, 0, 'v'},
+ {0, 0, 0, 0}
+ };
+
+ int c = getopt_long(argc, argv, "?smiv", long_options, NULL);
+ if(c == -1)
+ break;
+ switch(c)
+ {
+ case -1:
+ break;
+ case '?':
+ usage();
+ break;
+ case 's':
+ force_selector = true;
+ break;
+ case 'm':
+ no_macro = true;
+ break;
+ case 'i':
+ no_include = true;
+ break;
+ case 'v':
+ no_variadic = true;
+ break;
+ default:
+ abort();
+ }
+ }
+
std::vector< soc_t > socs;
- for(int i = 1; i < argc - 1; i++)
+ for(int i = optind; i < argc - 1; i++)
if(!soc_desc_parse_xml(argv[i], socs))
{
printf("Cannot parse %s\n", argv[i]);
return 1;
}
+
+ g_gen_selector = force_selector || socs.size() > 1;
+
+ if(!no_macro)
+ {
+ g_macro_filename = std::string(argv[argc - 1]) + "/regs-macro.h";
+ gen_macro(g_macro_filename, !no_variadic);
+ g_macro_filename = "regs-macro.h";
+ if(no_include)
+ g_macro_filename.clear();
+ }
+ if(g_gen_selector)
+ {
+ gen_selectors(argv[argc - 1], socs);
+ g_macro_filename.clear();
+ }
gen_headers(argv[argc - 1], socs);
- gen_selectors(argv[argc - 1], socs);
return 0;
} \ No newline at end of file