1
0
Fork 0
forked from len0rd/rockbox

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
This commit is contained in:
Amaury Pouly 2013-06-13 17:28:15 +02:00
parent b6ddbc41a5
commit 97b9ade639

View file

@ -26,11 +26,16 @@
#include <sstream> #include <sstream>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/types.h> #include <sys/types.h>
#include <getopt.h>
#define HEADERGEN_VERSION "2.1.7" #define HEADERGEN_VERSION "2.1.7"
#define error(...) do{ fprintf(stderr, __VA_ARGS__); exit(1); } while(0) #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_name;
std::string g_soc_dev; std::string g_soc_dev;
std::string g_soc_reg; std::string g_soc_reg;
@ -86,8 +91,10 @@ void fprint_copyright(FILE *f, const std::vector< xml_ver_t >& versions)
* Firmware |____|_ /\\____/ \\___ >__|_ \\|___ /\\____/__/\\_ \\\n\ * Firmware |____|_ /\\____/ \\___ >__|_ \\|___ /\\____/__/\\_ \\\n\
* \\/ \\/ \\/ \\/ \\/\n\ * \\/ \\/ \\/ \\/ \\/\n\
* This file was automatically generated by headergen, DO NOT EDIT it.\n\ * This file was automatically generated by headergen, DO NOT EDIT it.\n\
* headergen version: " HEADERGEN_VERSION "\n\ * headergen version: " HEADERGEN_VERSION "\n");
* XML versions:%s\n\ if(versions.size() > 0)
fprintf(f, " * XML versions:%s\n", ver.str().c_str());
fprintf(f,"\
*\n\ *\n\
* Copyright (C) 2013 by Amaury Pouly\n\ * Copyright (C) 2013 by Amaury Pouly\n\
*\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\ * This software is distributed on an \"AS IS\" basis, WITHOUT WARRANTY OF ANY\n\
* KIND, either express or implied.\n\ * KIND, either express or implied.\n\
*\n\ *\n\
****************************************************************************/\n", ****************************************************************************/\n");
ver.str().c_str());
} }
void fprint_copyright(FILE *f, const xml_ver_t& version) 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)); 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) void fprint_include_guard_ex(FILE *f, bool begin, const std::string& name)
{ {
if(begin) 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_copyright(f, ver);
fprint_include_guard(f, true); fprint_include_guard(f, true);
if(g_macro_filename.size() > 0)
fprintf(f, "#include \"%s\"\n", g_macro_filename.c_str());
/* print base */ /* print base */
fprintf(f, "\n"); 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++) for(size_t i = 0; i < socs.size(); i++)
{ {
g_soc_name = socs[i].name; 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, 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) 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__"; std::string guard = "__SELECT__" + toupper(dev) + "__H__";
FILE *f = fopen(filename.c_str(), "w"); FILE *f = fopen(filename.c_str(), "w");
if(f == NULL) if(f == NULL)
error("Cannot open file %s\n", filename.c_str()); error("Cannot open file %s\n", filename.c_str());
fprint_copyright(f, ver); fprint_copyright(f, ver);
fprint_include_guard_ex(f, true, guard); 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"); fprintf(f, "\n");
for(size_t i = 0; i < socs.size(); i++) 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) 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); general_dev_list_t map = build_general_dev_list(socs);
for(general_dev_list_t::iterator it = map.begin(); it != map.end(); ++it) 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() 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); exit(1);
} }
int main(int argc, char **argv) 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(); 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; 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)) if(!soc_desc_parse_xml(argv[i], socs))
{ {
printf("Cannot parse %s\n", argv[i]); printf("Cannot parse %s\n", argv[i]);
return 1; 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_headers(argv[argc - 1], socs);
gen_selectors(argv[argc - 1], socs);
return 0; return 0;
} }