diff options
| author | Amaury Pouly <amaury.pouly@gmail.com> | 2014-12-14 11:53:55 +0100 |
|---|---|---|
| committer | Amaury Pouly <amaury.pouly@gmail.com> | 2015-09-11 16:40:19 +0200 |
| commit | 1cada1f8339d6b5f8506277f80e62aaef77ab774 (patch) | |
| tree | 8477120e97832d659d2ffc471a8bfde73ad4c36e /utils/regtools/headergen_v1.cpp | |
| parent | c8d3638b9ebc24e4766714da1c9f961e350799c6 (diff) | |
| download | rockbox-1cada1f8339d6b5f8506277f80e62aaef77ab774.zip rockbox-1cada1f8339d6b5f8506277f80e62aaef77ab774.tar.gz rockbox-1cada1f8339d6b5f8506277f80e62aaef77ab774.tar.bz2 rockbox-1cada1f8339d6b5f8506277f80e62aaef77ab774.tar.xz | |
soc_desc: new version of the desc file format
Fix qeditor to use the old soc_desc_v1.
Port hwstub_shell to the new description format.
Change-Id: I9fefbff534bfaa5c3603bb3dd8307a2b76e88cfc
Diffstat (limited to 'utils/regtools/headergen_v1.cpp')
| -rw-r--r-- | utils/regtools/headergen_v1.cpp | 751 |
1 files changed, 751 insertions, 0 deletions
diff --git a/utils/regtools/headergen_v1.cpp b/utils/regtools/headergen_v1.cpp new file mode 100644 index 0000000..7b38366 --- /dev/null +++ b/utils/regtools/headergen_v1.cpp @@ -0,0 +1,751 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * 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 + * 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 "soc_desc_v1.hpp" +#include <stdio.h> +#include <stdlib.h> +#include <algorithm> +#include <map> +#include <sstream> +#include <sys/stat.h> +#include <sys/types.h> +#include <getopt.h> + +using namespace soc_desc_v1; + +#define HEADERGEN_VERSION "2.1.8" + +#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; +std::string g_soc_field; +std::string g_soc_dev_regs_base; + +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; +} +} + +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(); +} + +typedef std::pair< std::string, std::string > xml_ver_t; + +void fprint_copyright(FILE *f, const std::vector< xml_ver_t >& versions, char const *author) +{ + std::ostringstream ver; + time_t t = time(NULL); + struct tm tm = *localtime(&t); + + for(size_t i = 0; i < versions.size(); i++) + ver << " " << versions[i].first << ":" << versions[i].second; + + fprintf(f,"\ +/***************************************************************************\n\ + * __________ __ ___.\n\ + * Open \\______ \\ ____ ____ | | _\\_ |__ _______ ___\n\ + * Source | _// _ \\_/ ___\\| |/ /| __ \\ / _ \\ \\/ /\n\ + * Jukebox | | ( <_> ) \\___| < | \\_\\ ( <_> > < <\n\ + * Firmware |____|_ /\\____/ \\___ >__|_ \\|___ /\\____/__/\\_ \\\n\ + * \\/ \\/ \\/ \\/ \\/\n\ + * This file was automatically generated by headergen, DO NOT EDIT it.\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) "); + fprintf(f, "%d by %s\n", 1900+tm.tm_year, author); + fprintf(f,"\ + *\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 fprint_copyright(FILE *f, const xml_ver_t& version, char const *author) +{ + fprint_copyright(f, std::vector< xml_ver_t >(1, version), author); +} + +void fprint_copyright(FILE *f, char const *author) +{ + fprint_copyright(f, std::vector< xml_ver_t >(), author); +} + +void fprint_include_guard_ex(FILE *f, bool begin, const std::string& name) +{ + if(begin) + { + fprintf(f, "#ifndef %s\n", name.c_str()); + fprintf(f, "#define %s\n", name.c_str()); + } + else + fprintf(f, "#endif /* %s */\n", name.c_str()); +} + +void fprint_include_guard(FILE *f, bool begin) +{ + std::string name = "__HEADERGEN__" + toupper(g_soc_name) + "__" + toupper(g_soc_dev) + + "__H__"; + fprint_include_guard_ex(f, begin, name); +} + +struct limited_column_context_t +{ + limited_column_context_t(size_t nr_col = 80) + :m_nr_col(nr_col), m_prevent_wordcut(true) {} + void set_prefix(const std::string& prefix) { m_prefix = prefix; } + void add(const std::string& text) + { + for(size_t i = 0; i < text.size();) + { + size_t offset = 0; + if(m_cur_line.size() == 0) + m_cur_line = m_prefix; + size_t len = std::min(text.size() - i, m_nr_col - m_cur_line.size()); + // prevent word cut + if(m_prevent_wordcut && !isspace(text[i + len - 1]) && + i + len < text.size() && !isspace(text[i + len])) + { + size_t pos = text.find_last_of(" \t\n\v\r\f", i + len - 1); + if(pos == std::string::npos || pos < i) + len = 0; + else + len = pos - i + 1; + } + size_t pos = text.find('\n', i); + if(pos != std::string::npos && pos <= i + len) + { + offset = 1; + len = pos - i; + } + m_cur_line += text.substr(i, len); + // len == 0 means we need a new line + if(m_cur_line.size() == m_nr_col || len == 0) + { + m_lines.push_back(m_cur_line); + m_cur_line = ""; + } + i += len + offset; + } + } + + std::string to_string() + { + std::string str; + for(size_t i = 0; i < m_lines.size(); i++) + str += m_lines[i] + "\n"; + if(m_cur_line.size() != 0) + str += m_cur_line + "\n"; + return str; + } + + void print(FILE *f) + { + fprintf(f, "%s", to_string().c_str()); + } + + std::vector< std::string > m_lines; + std::string m_cur_line; + std::string m_prefix; + size_t m_nr_col; + bool m_prevent_wordcut; +}; + +struct define_align_context_t +{ + define_align_context_t():m_max_name(0) {} + void add(const std::string& name, const std::string& val) + { + m_lines.push_back(std::make_pair(name, val)); + m_max_name = std::max(m_max_name, name.size()); + } + + void add_raw(const std::string& line) + { + m_lines.push_back(std::make_pair("", line)); + } + + 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++) + { + std::string name = m_lines[i].first; + // raw entry ? + if(name.size() == 0) + { + fprintf(f, "%s", m_lines[i].second.c_str()); + continue; + } + 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; +}; + +limited_column_context_t print_description(const std::string& desc, const std::string& prefix) +{ + limited_column_context_t ctx; + if(desc.size() == 0) + return ctx; + ctx.set_prefix(prefix); + ctx.add(desc); + return ctx; +} + +void fprint_description(FILE *f, const std::string& desc, const std::string& prefix) +{ + limited_column_context_t ctx = print_description(desc, prefix); + ctx.print(f); +} + +void fprint_description(define_align_context_t& ctx, const std::string& desc, const std::string& prefix) +{ + limited_column_context_t ctx2 = print_description(desc, prefix); + ctx.add_raw(ctx2.to_string()); +} + +void gen_soc_field(define_align_context_t& ctx, bool multidev, bool multireg, const soc_reg_field_t& field) +{ + if(field.desc.size() != 0) + { + ctx.add_raw("/* Field: " + field.name + "\n"); + fprint_description(ctx, "Description: " + field.desc + " */\n", " * "); + } + + 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 gen_soc_reg(FILE *f, bool multidev, const soc_reg_t& reg, char const *author, char const *hwprefix) +{ + bool multireg = reg.addr.size() > 1; + + static const char *suffix[] = {"", "_SET", "_CLR", "_TOG"}; + bool sct = !!(reg.flags & REG_HAS_SCT); + + // comment generator + fprintf(f, "/**\n"); + fprintf(f, " * Register: %s%s_%s\n", hwprefix, g_soc_dev.c_str(), g_soc_reg.c_str()); + fprintf(f, " * Address:"); + if(multireg && reg.formula.type == REG_FORMULA_STRING) + { + fprintf(f, " %s\n", reg.formula.string.c_str()); + } + 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"); + if(reg.desc.size() != 0) + fprint_description(f, "Description: " + reg.desc, " * "); + fprintf(f, " */\n"); + + define_align_context_t ctx; + + if (multireg && reg.formula.type != REG_FORMULA_STRING) + { + for(int i=0; i < (int)reg.addr.size(); i++) + { + std::ostringstream name, value; + name << hwprefix << g_soc_dev << "_" << reg.addr[i].name; + if (multidev) + { + name << "(d)"; + } + value << "(*(volatile unsigned long *)(" << g_soc_dev_regs_base; + if (multidev) + { + value << "(d)"; + } + value << " + 0x" << std::hex << reg.addr[i].addr << "))"; + + ctx.add(name.str(), value.str()); + } + } + else + { + for(int i = 0; i < (sct ? 4 : 1); i++) + { + std::ostringstream name; + name << hwprefix << 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) + { + 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_soc_dev_header(const std::string& filename, const xml_ver_t& ver, const soc_dev_t& dev, + char const *author, char const *hwprefix) +{ + /* + 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) + { + printf("Cannot open %s for writing: %m\n", filename.c_str()); + return; + } + fprint_copyright(f, ver, author); + 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"); + g_soc_dev_regs_base = "REGS_" + g_soc_dev + "_BASE"; + fprintf(f, "#define %s", g_soc_dev_regs_base.c_str()); + + 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], author, hwprefix); + } + + fprint_include_guard(f, false); + fclose(f); +} + +void gen_soc_headers(const std::string& prefix, const soc_t& soc, char const *author, char const *hwprefix) +{ + printf("Generate headers for soc %s: use directory %s\n", soc.name.c_str(), + prefix.c_str()); + mkdir(prefix.c_str(), 0770); + + for(size_t i = 0; i < soc.dev.size(); 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], author, hwprefix); + } +} + +void gen_headers(const std::string& prefix, const std::vector< soc_t >& socs, char const *author, char const *hwprefix) +{ + for(size_t i = 0; i < socs.size(); i++) + { + g_soc_name = socs[i].name; + std::string dir = prefix; + if(g_gen_selector) + dir += "/" + socs[i].name; + gen_soc_headers(dir, socs[i], author, hwprefix); + } +} + +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].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< xml_ver_t >& ver, char const *author) +{ + 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, author); + 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++) + { + fprintf(f, "#define %s_INCLUDE \"%s/regs-%s.h\"\n", + toupper(socs[i]).c_str(), tolower(socs[i]).c_str(), + tolower(dev).c_str()); + } + fprintf(f, "\n#include \"regs-select.h\"\n\n"); + for(size_t i = 0; i < socs.size(); i++) + { + fprintf(f, "#undef %s_INCLUDE\n", toupper(socs[i]).c_str()); + } + fprintf(f, "\n"); + fprint_include_guard_ex(f, false, guard); + fclose(f); +} + +void gen_selectors(const std::string& prefix, const std::vector< soc_t >& socs, char const *author) +{ + 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) + { + 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, author); + } +} + +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, char const *author, char const *hwprefix) +{ + 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, author); + 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"(%1$s##reg##_SET, BM_##reg##_##field)\n\ +#define BF_CLR(reg, field) "REG_WRITE"(%1$s##reg##_CLR, BM_##reg##_##field)\n\ +#define BF_TOG(reg, field) "REG_WRITE"(%1$s##reg##_TOG, BM_##reg##_##field)\n\ +\n\ +#define BF_SETV(reg, field, v) "REG_WRITE"(%1$s##reg##_SET, BF_##reg##_##field(v))\n\ +#define BF_CLRV(reg, field, v) "REG_WRITE"(%1$s##reg##_CLR, BF_##reg##_##field(v))\n\ +#define BF_TOGV(reg, field, v) "REG_WRITE"(%1$s##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"(%1$s##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(%1$s##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"(%1$s##reg##_SET(n), BM_##reg##_##field)\n\ +#define BF_CLRn(reg, n, field) "REG_WRITE"(%1$s##reg##_CLR(n), BM_##reg##_##field)\n\ +#define BF_TOGn(reg, n, field) "REG_WRITE"(%1$s##reg##_TOG(n), BM_##reg##_##field)\n\ +\n\ +#define BF_SETVn(reg, n, field, v) "REG_WRITE"(%1$s##reg##_SET(n), BF_##reg##_##field(v))\n\ +#define BF_CLRVn(reg, n, field, v) "REG_WRITE"(%1$s##reg##_CLR(n), BF_##reg##_##field(v))\n\ +#define BF_TOGVn(reg, n, field, v) "REG_WRITE"(%1$s##reg##_TOG(n), BF_##reg##_##field(v))\n\ +\n\ +#define BF_RDn(reg, n, field) BF_RDX(%1$s##reg(n), reg, field)\n\ +#define BF_WRn(reg, n, field, v) BF_WRX(%1$s##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", hwprefix); + + 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, REG_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, __VA_ARGS__)\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 [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(" -p/--reg-prefix \"prefix\" Prefix register names\n"); + printf(" -a/--author \"Author\" Set author name in preamble\n"); + printf("\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 necessary.\n"); + printf("Default option is to not prefix register names\n"); + printf("Default option is \"Unknown Author\" for author in preamble\n"); + exit(1); +} + +int main(int argc, char **argv) +{ + bool force_selector = false; + bool no_variadic = false; + bool no_macro = false; + bool no_include = false; + char const *author = "Unknown Author"; + char const *hwprefix = ""; + + 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'}, + {"reg-prefix", required_argument, 0, 'p'}, + {"author", required_argument, 0, 'a'}, + {0, 0, 0, 0} + }; + + int c = getopt_long(argc, argv, "?smivp:a:", 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; + case 'a' : + author = optarg; + break; + case 'p' : + hwprefix = optarg; + break; + default: + abort(); + } + } + + std::vector< soc_t > socs; + for(int i = optind; i < argc - 1; i++) + { + soc_t s; + if(!parse_xml(argv[i], s)) + { + printf("Cannot parse %s\n", argv[i]); + return 1; + } + socs.push_back(s); + } + + 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, author, hwprefix); + g_macro_filename = "regs-macro.h"; + if(no_include) + g_macro_filename.clear(); + } + if(g_gen_selector) + { + gen_selectors(argv[argc - 1], socs, author); + g_macro_filename.clear(); + } + gen_headers(argv[argc - 1], socs, author, hwprefix); + return 0; +} |