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:
parent
b6ddbc41a5
commit
97b9ade639
1 changed files with 214 additions and 13 deletions
|
@ -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;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue