diff options
Diffstat (limited to 'utils')
-rw-r--r-- | utils/imxtools/regtools/Makefile | 28 | ||||
-rw-r--r-- | utils/imxtools/regtools/desc_parser.cpp | 265 | ||||
-rw-r--r-- | utils/imxtools/regtools/desc_parser.hpp | 108 | ||||
-rw-r--r-- | utils/imxtools/regtools/headergen.cpp | 274 | ||||
-rw-r--r-- | utils/imxtools/regtools/hwemulgen.cpp | 387 | ||||
-rw-r--r-- | utils/imxtools/regtools/tester.cpp | 126 |
6 files changed, 1188 insertions, 0 deletions
diff --git a/utils/imxtools/regtools/Makefile b/utils/imxtools/regtools/Makefile new file mode 100644 index 0000000000..5dad380e7b --- /dev/null +++ b/utils/imxtools/regtools/Makefile @@ -0,0 +1,28 @@ +DEFINES= +CC=gcc +CXX=g++ +LD=g++ +CFLAGS=-g -std=c99 -W -Wall `xml2-config --cflags` $(DEFINES) +CXXFLAGS=-g -W -Wall `xml2-config --cflags` $(DEFINES) +LDFLAGS=`xml2-config --libs` +BINS= tester headergen hwemulgen + +all: $(BINS) + +%.o: %.c + $(CC) $(CFLAGS) -c -o $@ $< + +%.o: %.cpp + $(CXX) $(CXXFLAGS) -c -o $@ $< + +headergen: headergen.o desc_parser.o + $(LD) -o $@ $^ $(LDFLAGS) + +hwemulgen: hwemulgen.o desc_parser.o + $(LD) -o $@ $^ $(LDFLAGS) + +tester: tester.o desc_parser.o + $(LD) -o $@ $^ $(LDFLAGS) + +clean: + rm -fr *.o $(BINS) diff --git a/utils/imxtools/regtools/desc_parser.cpp b/utils/imxtools/regtools/desc_parser.cpp new file mode 100644 index 0000000000..940a619f5c --- /dev/null +++ b/utils/imxtools/regtools/desc_parser.cpp @@ -0,0 +1,265 @@ +/*************************************************************************** + * __________ __ ___. + * 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 <libxml/parser.h> +#include <libxml/tree.h> +#include <stdio.h> +#include <string.h> + +#define XML_CHAR_TO_CHAR(s) ((const char *)(s)) + +#define BEGIN_ATTR_MATCH(attr) \ + for(xmlAttr *a = attr; a; a = a->next) { + +#define MATCH_X_ATTR(attr_name, hook, ...) \ + if(strcmp(XML_CHAR_TO_CHAR(a->name), attr_name) == 0) { \ + std::string s; \ + if(!parse_text_attr(a, s) || !hook(s, __VA_ARGS__)) \ + return false; \ + } + +#define SOFT_MATCH_X_ATTR(attr_name, hook, ...) \ + if(strcmp(XML_CHAR_TO_CHAR(a->name), attr_name) == 0) { \ + std::string s; \ + if(parse_text_attr(a, s)) \ + hook(s, __VA_ARGS__); \ + } + +#define SOFT_MATCH_SCT_ATTR(attr_name, var) \ + SOFT_MATCH_X_ATTR(attr_name, validate_sct_hook, var) + +#define MATCH_TEXT_ATTR(attr_name, var) \ + MATCH_X_ATTR(attr_name, validate_string_hook, var) + +#define MATCH_UINT32_ATTR(attr_name, var) \ + MATCH_X_ATTR(attr_name, validate_uint32_hook, var) + +#define MATCH_BITRANGE_ATTR(attr_name, first, last) \ + MATCH_X_ATTR(attr_name, validate_bitrange_hook, first, last) + +#define END_ATTR_MATCH() \ + } + +#define BEGIN_NODE_MATCH(node) \ + for(xmlNode *sub = node; sub; sub = sub->next) { + +#define MATCH_ELEM_NODE(node_name, array, parse_fn) \ + if(sub->type == XML_ELEMENT_NODE && strcmp(XML_CHAR_TO_CHAR(sub->name), node_name) == 0) { \ + array.resize(array.size() + 1); \ + if(!parse_fn(sub, array[array.size() - 1])) \ + return false; \ + } + +#define SOFT_MATCH_ELEM_NODE(node_name, array, parse_fn) \ + if(sub->type == XML_ELEMENT_NODE && strcmp(XML_CHAR_TO_CHAR(sub->name), node_name) == 0) { \ + array.resize(array.size() + 1); \ + if(!parse_fn(sub, array[array.size() - 1])) \ + array.pop_back(); \ + } + +#define END_NODE_MATCH() \ + } + +bool validate_string_hook(const std::string& str, std::string& s) +{ + s = str; + return true; +} + +bool validate_sct_hook(const std::string& str, soc_reg_flags_t& flags) +{ + if(str == "yes") flags |= REG_HAS_SCT; + else if(str != "no") return false; + return true; +} + +bool validate_unsigned_long_hook(const std::string& str, unsigned long& s) +{ + char *end; + s = strtoul(str.c_str(), &end, 0); + return *end == 0; +} + +bool validate_uint32_hook(const std::string& str, uint32_t& s) +{ + unsigned long u; + if(!validate_unsigned_long_hook(str, u)) return false; +#if ULONG_MAX > UINT32_MAX + if(u > UINT32_MAX) return false; +#endif + s = u; + return true; +} + +bool validate_bitrange_hook(const std::string& str, unsigned& first, unsigned& last) +{ + unsigned long a, b; + size_t sep = str.find(':'); + if(sep == std::string::npos) return false; + if(!validate_unsigned_long_hook(str.substr(0, sep), a)) return false; + if(!validate_unsigned_long_hook(str.substr(sep + 1), b)) return false; + if(a > 31 || b > 31 || a < b) return false; + first = b; + last = a; + return true; +} + +bool parse_text_attr(xmlAttr *attr, std::string& s) +{ + if(attr->children != attr->last) + return false; + if(attr->children->type != XML_TEXT_NODE) + return false; + s = XML_CHAR_TO_CHAR(attr->children->content); + return true; +} + +bool parse_value_elem(xmlNode *node, soc_reg_field_value_t& value) +{ + BEGIN_ATTR_MATCH(node->properties) + MATCH_TEXT_ATTR("name", value.name) + MATCH_UINT32_ATTR("value", value.value) + END_ATTR_MATCH() + + return true; +} + +bool parse_field_elem(xmlNode *node, soc_reg_field_t& field) +{ + BEGIN_ATTR_MATCH(node->properties) + MATCH_TEXT_ATTR("name", field.name) + MATCH_BITRANGE_ATTR("bitrange", field.first_bit, field.last_bit) + END_ATTR_MATCH() + + BEGIN_NODE_MATCH(node->children) + SOFT_MATCH_ELEM_NODE("value", field.values, parse_value_elem) + END_NODE_MATCH() + + return true; +} + +bool parse_reg_elem(xmlNode *node, soc_reg_t& reg) +{ + BEGIN_ATTR_MATCH(node->properties) + MATCH_TEXT_ATTR("name", reg.name) + MATCH_UINT32_ATTR("addr", reg.addr) + SOFT_MATCH_SCT_ATTR("sct", reg.flags) + END_ATTR_MATCH() + + BEGIN_NODE_MATCH(node->children) + MATCH_ELEM_NODE("field", reg.fields, parse_field_elem) + END_NODE_MATCH() + + return true; +} + +bool parse_multireg_elem(xmlNode *node, soc_multireg_t& mreg) +{ + BEGIN_ATTR_MATCH(node->properties) + MATCH_TEXT_ATTR("name", mreg.name) + MATCH_UINT32_ATTR("base", mreg.base) + MATCH_UINT32_ATTR("count", mreg.count) + MATCH_UINT32_ATTR("offset", mreg.offset) + SOFT_MATCH_SCT_ATTR("sct", mreg.flags) + END_ATTR_MATCH() + + BEGIN_NODE_MATCH(node->children) + MATCH_ELEM_NODE("reg", mreg.regs, parse_reg_elem) + MATCH_ELEM_NODE("field", mreg.fields, parse_field_elem) + END_NODE_MATCH() + + return true; +} + +bool parse_dev_elem(xmlNode *node, soc_dev_t& dev) +{ + BEGIN_ATTR_MATCH(node->properties) + MATCH_TEXT_ATTR("name", dev.name) + MATCH_UINT32_ATTR("addr", dev.addr) + MATCH_TEXT_ATTR("long_name", dev.long_name) + MATCH_TEXT_ATTR("desc", dev.desc) + END_ATTR_MATCH() + + BEGIN_NODE_MATCH(node->children) + MATCH_ELEM_NODE("multireg", dev.multiregs, parse_multireg_elem) + MATCH_ELEM_NODE("reg", dev.regs, parse_reg_elem) + END_NODE_MATCH() + + return true; +} + +bool parse_multidev_elem(xmlNode *node, soc_multidev_t& dev) +{ + BEGIN_ATTR_MATCH(node->properties) + MATCH_TEXT_ATTR("name", dev.name) + MATCH_TEXT_ATTR("long_name", dev.long_name) + MATCH_TEXT_ATTR("desc", dev.desc) + END_ATTR_MATCH() + + BEGIN_NODE_MATCH(node->children) + MATCH_ELEM_NODE("dev", dev.devs, parse_dev_elem) + MATCH_ELEM_NODE("multireg", dev.multiregs, parse_multireg_elem) + MATCH_ELEM_NODE("reg", dev.regs, parse_reg_elem) + END_NODE_MATCH() + + return true; +} + +bool parse_soc_elem(xmlNode *node, soc_t& soc) +{ + BEGIN_ATTR_MATCH(node->properties) + MATCH_TEXT_ATTR("name", soc.name) + MATCH_TEXT_ATTR("desc", soc.desc) + END_ATTR_MATCH() + + BEGIN_NODE_MATCH(node->children) + MATCH_ELEM_NODE("dev", soc.devs, parse_dev_elem) + MATCH_ELEM_NODE("multidev", soc.multidevs, parse_multidev_elem) + END_NODE_MATCH() + + return true; +} + +bool parse_root_elem(xmlNode *node, std::vector< soc_t >& socs) +{ + BEGIN_NODE_MATCH(node) + MATCH_ELEM_NODE("soc", socs, parse_soc_elem) + END_NODE_MATCH() + return true; +} + +bool parse_soc_desc(const std::string& filename, std::vector< soc_t >& socs) +{ + LIBXML_TEST_VERSION + + xmlDoc *doc = xmlReadFile(filename.c_str(), NULL, 0); + if(doc == NULL) + return false; + + xmlNode *root_element = xmlDocGetRootElement(doc); + + bool ret = parse_root_elem(root_element, socs); + + xmlFreeDoc(doc); + xmlCleanupParser(); + + return ret; +}
\ No newline at end of file diff --git a/utils/imxtools/regtools/desc_parser.hpp b/utils/imxtools/regtools/desc_parser.hpp new file mode 100644 index 0000000000..908cff8940 --- /dev/null +++ b/utils/imxtools/regtools/desc_parser.hpp @@ -0,0 +1,108 @@ +/*************************************************************************** + * __________ __ ___. + * 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. + * + ****************************************************************************/ +#ifndef __DESC_PARSER__ +#define __DESC_PARSER__ + +#include <stdint.h> +#include <vector> +#include <string> + +typedef uint32_t soc_addr_t; +typedef uint32_t soc_word_t; +typedef uint32_t soc_reg_flags_t; + +const soc_addr_t SOC_NO_ADDR = 0xffffffff; +const soc_reg_flags_t REG_HAS_SCT = 1 << 0; + +struct soc_reg_field_value_t +{ + std::string name; + soc_word_t value; +}; + +struct soc_reg_field_t +{ + std::string name; + unsigned first_bit, last_bit; + + soc_word_t bitmask() const + { + return ((1 << (last_bit - first_bit + 1)) - 1) << first_bit; + } + + std::vector< soc_reg_field_value_t > values; +}; + +struct soc_reg_t +{ + std::string name; + soc_addr_t addr; + soc_reg_flags_t flags; + + std::vector< soc_reg_field_t > fields; +}; + +struct soc_multireg_t +{ + std::string name; + soc_addr_t base; + unsigned count; + soc_addr_t offset; + soc_reg_flags_t flags; + + std::vector< soc_reg_t > regs; + std::vector< soc_reg_field_t > fields; +}; + +struct soc_dev_t +{ + std::string name; + std::string long_name; + std::string desc; + soc_addr_t addr; + + std::vector< soc_multireg_t > multiregs; + std::vector< soc_reg_t > regs; +}; + +struct soc_multidev_t +{ + std::string name; + std::string long_name; + std::string desc; + + std::vector< soc_dev_t > devs; + std::vector< soc_multireg_t > multiregs; + std::vector< soc_reg_t > regs; +}; + +struct soc_t +{ + std::string name; + std::string desc; + + std::vector< soc_dev_t > devs; + std::vector< soc_multidev_t > multidevs; +}; + +bool parse_soc_desc(const std::string& filename, std::vector< soc_t >& soc); + +#endif /* __DESC_PARSER__ */
\ No newline at end of file diff --git a/utils/imxtools/regtools/headergen.cpp b/utils/imxtools/regtools/headergen.cpp new file mode 100644 index 0000000000..b6905363d8 --- /dev/null +++ b/utils/imxtools/regtools/headergen.cpp @@ -0,0 +1,274 @@ +/*************************************************************************** + * __________ __ ___. + * 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) + +std::string g_soc_name; +std::string g_soc_dev; +std::string g_soc_reg; +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; + 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; +} + +} + +void fprint_copyright(FILE *f) +{ + 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\ + *\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 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()); + fprintf(f, "\n#include \"imx233.h\"\n"); + } + else + fprintf(f, "#endif /* %s */\n", name.c_str()); +} + +void fprint_include_guard(FILE *f, bool begin) +{ + std::string name = "__" + 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) +{ + for(size_t i = 0; i < fields.size(); i++) + { + 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++) + { + 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); + } + } +} + +void fprint_reg(FILE *f, const soc_reg_t& reg) +{ + g_soc_dev_reg_core_name = toupper(g_soc_dev) + "_" + toupper(reg.name); + + 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) + { + 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()); + } + fprint_fields(f, reg.fields); + fprintf(f, "\n"); +} + +void fprint_mreg(FILE *f, const soc_multireg_t& mreg) +{ +} + +void gen_dev_header(const std::string& filename, 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()); + 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(f, true); + 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"); + + 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]); + + 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(), + 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++) + { + std::string name = soc.multidevs[i].name; + name = tolower(name); + gen_mdev_header(prefix + "/regs-" + name + ".h", soc.multidevs[i]); + } +} + +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]); + } +} + +typedef std::map< std::string, std::vector< std::string > > 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); + } + return map; +} + +void gen_select_header(const std::string& filename, const std::string& dev, + const std::vector< std::string >& socs) +{ + 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_include_guard_ex(f, true, guard); + 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) +{ + 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); +} + +void usage() +{ + printf("usage: headergen <desc file> <output prefix>\n"); + exit(1); +} + +int main(int argc, char **argv) +{ + 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); + return 0; +}
\ No newline at end of file diff --git a/utils/imxtools/regtools/hwemulgen.cpp b/utils/imxtools/regtools/hwemulgen.cpp new file mode 100644 index 0000000000..ae8b9dbec5 --- /dev/null +++ b/utils/imxtools/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 diff --git a/utils/imxtools/regtools/tester.cpp b/utils/imxtools/regtools/tester.cpp new file mode 100644 index 0000000000..a46d310f2a --- /dev/null +++ b/utils/imxtools/regtools/tester.cpp @@ -0,0 +1,126 @@ +/*************************************************************************** + * __________ __ ___. + * 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> + +void print_value_desc(const soc_reg_field_value_t& value) +{ + printf(" VALUE %s (%#x)\n", value.name.c_str(), value.value); +} + +void print_field_desc(const soc_reg_field_t& field) +{ + printf(" FIELD %s (%d:%d)\n", field.name.c_str(), field.last_bit, + field.first_bit); + for(size_t i = 0; i < field.values.size(); i++) + print_value_desc(field.values[i]); +} + +std::string compute_sct(soc_reg_flags_t f) +{ + if(f & REG_HAS_SCT) return "SCT"; + else return ""; +} + +void print_reg_desc(const soc_reg_t& reg, bool in_multi) +{ + if(in_multi) + { + printf(" REG %s (%#x)\n", reg.name.c_str(), reg.addr); + } + else + { + std::string sct = compute_sct(reg.flags); + printf(" REG %s %s(%#x)\n", reg.name.c_str(), sct.c_str(), reg.addr); + for(size_t i = 0; i < reg.fields.size(); i++) + print_field_desc(reg.fields[i]); + } +} + +void print_multireg_desc(const soc_multireg_t& mreg) +{ + std::string sct = compute_sct(mreg.flags); + printf(" MULTIREG %s %s(%#x * %d, +%#x)\n", mreg.name.c_str(), sct.c_str(), + mreg.base, mreg.count, mreg.offset); + for(size_t i = 0; i < mreg.regs.size(); i++) + print_reg_desc(mreg.regs[i], true); + for(size_t i = 0; i < mreg.fields.size(); i++) + print_field_desc(mreg.fields[i]); +} + + +void print_dev_desc(const soc_dev_t& dev, bool in_multi) +{ + if(in_multi) + { + printf(" DEV %s (%#x)\n", dev.name.c_str(), dev.addr); + } + else + { + printf(" DEV %s (%#x, %s, %s)\n", dev.name.c_str(), dev.addr, + dev.long_name.c_str(), dev.desc.c_str()); + for(size_t i = 0; i < dev.multiregs.size(); i++) + print_multireg_desc(dev.multiregs[i]); + for(size_t i = 0; i < dev.regs.size(); i++) + print_reg_desc(dev.regs[i], false); + } +} + +void print_multidev_desc(const soc_multidev_t& dev) +{ + printf(" MULTIDEV %s (%s, %s)\n", dev.name.c_str(), dev.long_name.c_str(), + dev.desc.c_str()); + for(size_t i = 0; i < dev.devs.size(); i++) + print_dev_desc(dev.devs[i], true); + for(size_t i = 0; i < dev.multiregs.size(); i++) + print_multireg_desc(dev.multiregs[i]); + for(size_t i = 0; i < dev.regs.size(); i++) + print_reg_desc(dev.regs[i], false); +} + +void print_soc_desc(const soc_t& soc) +{ + printf("SOC %s (%s)\n", soc.name.c_str(), soc.desc.c_str()); + for(size_t i = 0; i < soc.devs.size(); i++) + print_dev_desc(soc.devs[i], false); + for(size_t i = 0; i < soc.multidevs.size(); i++) + print_multidev_desc(soc.multidevs[i]); +} + +void usage() +{ + printf("usage: tester <desc file>\n"); + exit(1); +} + +int main(int argc, char **argv) +{ + if(argc != 2) + usage(); + std::vector< soc_t > socs; + bool ret = parse_soc_desc(argv[1], socs); + printf("parse result: %d\n", ret); + if(ret) + for(size_t i = 0; i < socs.size(); i++) + print_soc_desc(socs[i]); + return 0; +}
\ No newline at end of file |