diff options
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 |