summaryrefslogtreecommitdiffstats
path: root/utils/regtools/headergen.cpp
diff options
context:
space:
mode:
authorAmaury Pouly <amaury.pouly@gmail.com>2013-06-13 01:50:14 +0200
committerAmaury Pouly <amaury.pouly@gmail.com>2013-06-13 02:25:08 +0200
commit73db73dbd3c5c6a27e022a5c724136ca6fc2ffe8 (patch)
tree5e73c4b4477b2f47f4581f68d800ef4cb7b8a37a /utils/regtools/headergen.cpp
parent7143ea681c377fe5901bd79801366a26ae0d394a (diff)
downloadrockbox-73db73dbd3c5c6a27e022a5c724136ca6fc2ffe8.tar.gz
rockbox-73db73dbd3c5c6a27e022a5c724136ca6fc2ffe8.zip
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
Diffstat (limited to 'utils/regtools/headergen.cpp')
-rw-r--r--utils/regtools/headergen.cpp311
1 files changed, 218 insertions, 93 deletions
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 <stdio.h>
#include <stdlib.h>
#include <algorithm>
#include <map>
+#include <sstream>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#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 <desc file> <output prefix>\n");
+ printf("usage: headergen <desc files...> <output directory>\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