diff options
author | Amaury Pouly <amaury.pouly@gmail.com> | 2013-06-12 19:49:26 +0200 |
---|---|---|
committer | Amaury Pouly <amaury.pouly@gmail.com> | 2013-06-12 19:49:26 +0200 |
commit | 7143ea681c377fe5901bd79801366a26ae0d394a (patch) | |
tree | 34fdaaa83590130b57b187878a89394505950b82 /utils/regtools/hwemulgen.cpp | |
parent | 11da9d23fe323ce452fcd04a10a0ddf78eaa63ea (diff) | |
download | rockbox-7143ea681c377fe5901bd79801366a26ae0d394a.tar.gz rockbox-7143ea681c377fe5901bd79801366a26ae0d394a.zip |
imxtools: move regtools to its own directory
The register tools are in no way stmp specific. The XML
description of the registers is powerful enough to describe
the STMP register which should be more than enough to describe
virtually all other SoCs. The generators follow the STMP coding
convention but others could be used as well.
Change-Id: If1a9f56e4a3594161688de34adbea698e5aaecd8
Diffstat (limited to 'utils/regtools/hwemulgen.cpp')
-rw-r--r-- | utils/regtools/hwemulgen.cpp | 387 |
1 files changed, 387 insertions, 0 deletions
diff --git a/utils/regtools/hwemulgen.cpp b/utils/regtools/hwemulgen.cpp new file mode 100644 index 0000000000..ae8b9dbec5 --- /dev/null +++ b/utils/regtools/hwemulgen.cpp @@ -0,0 +1,387 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2002 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 + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#include "desc_parser.hpp" +#include <stdio.h> +#include <stdlib.h> +#include <algorithm> +#include <map> + +#define error(...) do{ fprintf(stderr, __VA_ARGS__); exit(1); } while(0) + +int g_soc_count; +int g_reg_count; +int g_field_count; + +namespace { + +std::string tolower(const std::string s) +{ + std::string res = s; + std::transform(res.begin(), res.end(), res.begin(), ::tolower); + return res; +} + +std::string toupper(const std::string& s) +{ + std::string res = s; + std::transform(res.begin(), res.end(), res.begin(), ::toupper); + return res; +} + +bool lex_comp(const std::string& a, const std::string& b) +{ + return std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end()); +} + +} + +void fprint_copyright(FILE *f) +{ + fprintf(f,"\ +/***************************************************************************\n\ + * __________ __ ___.\n\ + * Open \\______ \\ ____ ____ | | _\\_ |__ _______ ___\n\ + * Source | _// _ \\_/ ___\\| |/ /| __ \\ / _ \\ \\/ /\n\ + * Jukebox | | ( <_> ) \\___| < | \\_\\ ( <_> > < <\n\ + * Firmware |____|_ /\\____/ \\___ >__|_ \\|___ /\\____/__/\\_ \\\n\ + * \\/ \\/ \\/ \\/ \\/\n\ + * This file was automatically generated by hwemulgen, DO NOT EDIT it.\n\ + *\n\ + * Copyright (C) 2012 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\ + * as published by the Free Software Foundation; either version 2\n\ + * of the License, or (at your option) any later version.\n\ + *\n\ + * This software is distributed on an \"AS IS\" basis, WITHOUT WARRANTY OF ANY\n\ + * KIND, either express or implied.\n\ + *\n\ + ****************************************************************************/\n"); +} + +void gen_header(const std::string& filename) +{ + FILE *f = fopen(filename.c_str(), "w"); + if(f == NULL) + error("Cannot open file %s\n", filename.c_str()); + fprint_copyright(f); + fprintf(f, "#ifndef __HWEMUL_SOC_HEADER__\n"); + fprintf(f, "#define __HWEMUL_SOC_HEADER__\n"); + fprintf(f, "\n"); + fprintf(f, "#include \"stddef.h\"\n"); + fprintf(f, "#include \"stdint.h\"\n"); + + fprintf(f, "\n\ +#define HWEMUL_SOC_REG_HAS_SCT (1 << 0)\n\ +\n\ +struct hwemul_soc_reg_field_t\n\ +{\n\ + const char *name;\n\ + unsigned short first_bit, last_bit;\n\ +};\n\ +\n\ +struct hwemul_soc_reg_t\n\ +{\n\ + const char *name;\n\ + uint32_t addr;\n\ + uint32_t flags;\n\ + size_t nr_fields;\n\ + struct hwemul_soc_reg_field_t *fields_by_name[]; /* ordered by lexicographic order */\n\ +};\n\ +\n\ +struct hwemul_soc_t\n\ +{\n\ + const char *name;\n\ + size_t nr_regs;\n\ + struct hwemul_soc_reg_t *regs_by_name[]; /* ordered by lexicographic order */\n\ +};\n\ +\n\ +struct hwemul_soc_list_t\n\ +{\n\ + size_t nr_socs;\n\ + struct hwemul_soc_t *socs[];\n\ +};\n\ +\n\ +struct hwemul_soc_list_t *hwemul_get_soc_list(void);\n\ +\n"); + + fprintf(f, "#endif\n"); + fclose(f); +} + +std::string extract_last_part(std::string s) +{ + size_t pos = s.find_last_of("/\\"); + if(pos != std::string::npos) + s = s.substr(pos + 1); + pos = s.find_last_of("."); + if(pos != std::string::npos) + s = s.substr(0, pos); + return s; +} + +std::vector< std::string > gen_fields(FILE *f, std::string prefix, + const std::vector< soc_reg_field_t >& fields) +{ + std::vector< std::string > list; + + for(size_t i = 0; i < fields.size(); i++) + { + g_field_count++; + std::string var_name = prefix + tolower(fields[i].name); + list.push_back(var_name); + + fprintf(f, "\ +static struct hwemul_soc_reg_field_t %s =\n\ +{\n\ + \"%s\",\n\ + %d, %d\n\ +};\n\ +\n", var_name.c_str(), fields[i].name.c_str(), fields[i].first_bit, fields[i].last_bit); + } + + return list; +} + +std::vector< std::string > gen_common_regs(FILE *f, std::string prefix, std::string devname, + soc_addr_t devaddr, const std::vector< soc_reg_t >& regs, + const std::vector< soc_multireg_t >& multiregs) +{ + std::vector< std::string > list; + + for(size_t i = 0; i < regs.size(); i++) + { + g_reg_count++; + std::string var_name = prefix + tolower(regs[i].name); + + list.push_back(var_name); + + std::vector< std::string > field_vars = gen_fields(f, var_name + "_", + regs[i].fields); + + std::sort(field_vars.begin(), field_vars.end(), lex_comp); + + fprintf(f, "\ +static struct hwemul_soc_reg_t %s =\n\ +{\n\ + \"HW_%s_%s\",\n\ + %#x,\n\ + 0", var_name.c_str(), devname.c_str(), regs[i].name.c_str(), devaddr + regs[i].addr); + if(regs[i].flags & REG_HAS_SCT) + fprintf(f, " | HWEMUL_SOC_REG_HAS_SCT"); + fprintf(f, ",\n"); + fprintf(f, "\ + %u,\n\ + {", (unsigned)field_vars.size()); + if(field_vars.size() != 0) + fprintf(f, "\n"); + for(size_t j = 0; j < field_vars.size(); j++) + fprintf(f, " &%s,\n", field_vars[j].c_str()); + if(field_vars.size() != 0) + fprintf(f, " "); + fprintf(f,"\ +}\n};\n\ +\n"); + } + + for(size_t i = 0; i < multiregs.size(); i++) + { + g_reg_count++; + std::vector< std::string > field_vars = gen_fields(f, + prefix + tolower(multiregs[i].name) + "_", multiregs[i].fields); + std::sort(field_vars.begin(), field_vars.end(), lex_comp); + + for(size_t j = 0; j < multiregs[i].regs.size(); j++) + { + g_reg_count++; + std::string var_name = prefix + tolower(multiregs[i].regs[j].name); + + list.push_back(var_name); + + fprintf(f, "\ +static struct hwemul_soc_reg_t %s =\n\ +{\n\ + \"HW_%s_%s\",\n\ + %#x,\n\ + 0", var_name.c_str(), devname.c_str(), multiregs[i].regs[j].name.c_str(), devaddr + multiregs[i].regs[j].addr); + if(multiregs[i].flags & REG_HAS_SCT) + fprintf(f, " | HWEMUL_SOC_REG_HAS_SCT"); + fprintf(f, ",\n"); + fprintf(f,"\ + %u,\n\ + {", (unsigned)field_vars.size()); + if(field_vars.size() != 0) + fprintf(f, "\n"); + for(size_t k = 0; k < field_vars.size(); k++) + fprintf(f, " &%s,\n", field_vars[k].c_str()); + if(field_vars.size() != 0) + fprintf(f, " "); + fprintf(f,"\ +}\n};\n\ +\n"); + } + } + + return list; +} + +std::vector< std::string > gen_dev_regs(FILE *f, std::string prefix, const soc_dev_t& dev) +{ + return gen_common_regs(f, prefix + tolower(dev.name) + "_", dev.name, dev.addr, + dev.regs, dev.multiregs); +} + +std::vector< std::string > gen_multidev_regs(FILE *f, std::string prefix, const soc_multidev_t& mdev) +{ + std::vector< std::string > list; + + for(size_t i = 0; i < mdev.devs.size(); i++) + { + std::vector< std::string > sub_list = gen_common_regs(f, + prefix + tolower(mdev.devs[i].name) + "_", mdev.devs[i].name, + mdev.devs[i].addr, mdev.regs, mdev.multiregs); + list.insert(list.end(), sub_list.begin(), sub_list.end()); + } + + return list; +} + +std::vector< std::string > gen_regs(FILE *f, std::string prefix, const soc_t& soc) +{ + std::vector< std::string > list; + + for(size_t i = 0; i < soc.devs.size(); i++) + { + std::vector< std::string > sub_list = gen_dev_regs(f, + prefix, soc.devs[i]); + list.insert(list.end(), sub_list.begin(), sub_list.end()); + } + + for(size_t i = 0; i < soc.multidevs.size(); i++) + { + std::vector< std::string > sub_list = gen_multidev_regs(f, + prefix, soc.multidevs[i]); + list.insert(list.end(), sub_list.begin(), sub_list.end()); + } + + return list; +} + +std::vector< std::string > gen_socs(FILE *f, std::string prefix, const std::vector< soc_t >& socs) +{ + std::vector< std::string > list; + for(size_t i = 0; i < socs.size(); i++) + { + g_soc_count++; + std::string var_name = prefix + socs[i].name; + list.push_back(var_name); + + std::vector< std::string > reg_vars = gen_regs(f, var_name + "_", socs[i]); + + std::sort(reg_vars.begin(), reg_vars.end(), lex_comp); + + fprintf(f, "\ +static struct hwemul_soc_t %s =\n\ +{\n\ + \"%s\",\n\ + %u,\n\ + {\n", var_name.c_str(), socs[i].name.c_str(), (unsigned)reg_vars.size()); + + for(size_t j = 0; j < reg_vars.size(); j++) + fprintf(f, " &%s,\n", reg_vars[j].c_str()); + fprintf(f, "\ + }\n\ +};\n\ +\n"); + } + + return list; +} + +void gen_impl(const std::string& filename, const std::vector< soc_t >& socs) +{ + FILE *f = fopen(filename.c_str(), "w"); + if(f == NULL) + error("Cannot open file %s\n", filename.c_str()); + fprint_copyright(f); + std::string last_part = extract_last_part(filename); + fprintf(f, "#include \"%s.h\"\n\n", last_part.c_str()); + + std::vector< std::string > socs_var = gen_socs(f, "soc_", socs); + + fprintf(f, "\ +static struct hwemul_soc_list_t hwemul_soc_list =\n\ +{\n\ + %u,\n\ + {", (unsigned) socs_var.size()); + + for(size_t i = 0; i < socs_var.size(); i++) + { + fprintf(f, "&%s", socs_var[i].c_str()); + if(i + 1 != socs_var.size()) + fprintf(f, ", "); + } + fprintf(f, "\ +}\n\ +};\n\ +\n"); + + fprintf(f,"\ +struct hwemul_soc_list_t *hwemul_get_soc_list(void)\n\ +{\n\ + return &hwemul_soc_list;\n\ +}\n\ +\n"); + + fclose(f); +} + +void gen_files(const std::string& output, const std::vector< soc_t >& socs) +{ + gen_header(output + ".h"); + gen_impl(output + ".c", socs); +} + +void usage() +{ + printf("usage: headergen <desc file list> <output file prefix>\n"); + exit(1); +} + +int main(int argc, char **argv) +{ + if(argc < 3) + usage(); + std::vector< soc_t > socs; + for(int i = 1; i < argc - 1; i++) + { + bool ret = parse_soc_desc(argv[i], socs); + if(!ret) + { + printf("Cannot parse '%s'\n", argv[i]); + return 1; + } + } + gen_files(argv[argc - 1], socs); + printf("%d socs, %d registers and %d fields dumped!\n", g_soc_count, g_reg_count, g_field_count); + return 0; +}
\ No newline at end of file |