diff options
Diffstat (limited to 'utils/regtools/swiss_knife.cpp')
| -rw-r--r-- | utils/regtools/swiss_knife.cpp | 259 |
1 files changed, 241 insertions, 18 deletions
diff --git a/utils/regtools/swiss_knife.cpp b/utils/regtools/swiss_knife.cpp index eaa2519..fb65b5c 100644 --- a/utils/regtools/swiss_knife.cpp +++ b/utils/regtools/swiss_knife.cpp @@ -20,11 +20,14 @@ ****************************************************************************/ #include "soc_desc.hpp" #include "soc_desc_v1.hpp" -#include <stdio.h> -#include <stdlib.h> +#include <cstdio> +#include <cstdlib> #include <map> #include <set> #include <cstring> +#include <fstream> +#include <sstream> +#include <cstring> using namespace soc_desc; @@ -88,7 +91,6 @@ bool convert_v1_to_v2(const soc_desc_v1::soc_reg_t& in, node_t& out, error_conte { std::string loc = _loc + "." + in.name; out.name = in.name; - out.desc = in.desc; if(in.formula.type == soc_desc_v1::REG_FORMULA_NONE) { out.instance.resize(in.addr.size()); @@ -133,6 +135,7 @@ bool convert_v1_to_v2(const soc_desc_v1::soc_reg_t& in, node_t& out, error_conte } out.register_.resize(1); out.register_[0].width = 32; + out.register_[0].desc = in.desc; out.register_[0].field.resize(in.field.size()); for(size_t i = 0; i < in.field.size(); i++) if(!convert_v1_to_v2(in.field[i], out.register_[0].field[i], ctx)) @@ -140,15 +143,12 @@ bool convert_v1_to_v2(const soc_desc_v1::soc_reg_t& in, node_t& out, error_conte /* sct */ if(in.flags & soc_desc_v1::REG_HAS_SCT) { - out.node.resize(1); - out.node[0].name = "SCT"; - out.node[0].instance.resize(3); - const char *names[3] = {"SET", "CLR", "TOG"}; + out.register_[0].variant.resize(3); + const char *names[3] = {"set", "clr", "tog"}; for(size_t i = 0; i < 3; i++) { - out.node[0].instance[i].name = names[i]; - out.node[0].instance[i].type = instance_t::SINGLE; - out.node[0].instance[i].addr = 4 + i *4; + out.register_[0].variant[i].type = names[i]; + out.register_[0].variant[i].offset = 4 + i *4; } } return true; @@ -171,10 +171,23 @@ bool convert_v1_to_v2(const soc_desc_v1::soc_dev_t& in, node_t& out, error_conte out.name = in.name; out.title = in.long_name; out.desc = in.desc; - out.instance.resize(in.addr.size()); - for(size_t i = 0; i < in.addr.size(); i++) - if(!convert_v1_to_v2(in.addr[i], out.instance[i], ctx)) - return false; + out.instance.resize(1); + if(in.addr.size() == 1) + { + out.instance[0].type = instance_t::SINGLE; + out.instance[0].name = in.addr[0].name; + out.instance[0].addr = in.addr[0].addr; + } + else + { + out.instance[0].type = instance_t::RANGE; + out.instance[0].name = in.name; + out.instance[0].range.type = range_t::LIST; + out.instance[0].range.first = 1; + out.instance[0].range.list.resize(in.addr.size()); + for(size_t i = 0; i < in.addr.size(); i++) + out.instance[0].range.list[i] = in.addr[i].addr; + } out.node.resize(in.reg.size()); for(size_t i = 0; i < in.reg.size(); i++) if(!convert_v1_to_v2(in.reg[i], out.node[i], ctx, loc)) @@ -195,8 +208,21 @@ bool convert_v1_to_v2(const soc_desc_v1::soc_t& in, soc_t& out, error_context_t& int do_convert(int argc, char **argv) { - if(argc != 2) - return printf("convert mode expects two arguments\n"); + std::vector< std::string > authors; + std::string version; + while(argc >= 2) + { + if(strcmp(argv[0], "--author") == 0) + authors.push_back(argv[1]); + else if(strcmp(argv[0], "--version") == 0) + version = argv[1]; + else + break; + argc -= 2; + argv += 2; + } + if(argc < 2) + return printf("convert mode expects at least one description file and an output file\n"); soc_desc_v1::soc_t soc; if(!soc_desc_v1::parse_xml(argv[0], soc)) return printf("cannot read file '%s'\n", argv[0]); @@ -207,6 +233,8 @@ int do_convert(int argc, char **argv) print_context(ctx); return printf("cannot convert from v1 to v2\n"); } + new_soc.author = authors; + new_soc.version = version; if(!produce_xml(argv[1], new_soc, ctx)) { print_context(ctx); @@ -392,7 +420,7 @@ void check_node(const std::string& _path, const node_t& node, error_context_t& c std::string path = _path + "." + node.name; check_name(_path, node.name, ctx); if(node.instance.empty()) - ctx.add(error_t(error_t::FATAL, path, "subnode with no instances")); + ctx.add(error_t(error_t::WARNING, path, "subnode with no instances")); for(size_t j = 0; j < node.instance.size(); j++) check_instance(path, node.instance[j], ctx); for(size_t i = 0; i < node.register_.size(); i++) @@ -506,6 +534,12 @@ void print_reg(register_ref_t reg, unsigned flags) printf(":[%u-%u]=", (unsigned)(f->pos + f->width - 1), (unsigned)f->pos); printf("%s\n", f->name.c_str()); } + std::vector< variant_ref_t > variants = reg.variants(); + for(size_t i = 0; i < variants.size(); i++) + { + print_path(node, false); + printf(":%s@+0x%x\n", variants[i].type().c_str(), variants[i].offset()); + } } void do_dump(node_ref_t node, unsigned flags) @@ -576,6 +610,178 @@ int do_dump(int argc, char **argv) return 0; } +std::string trim(const std::string& s) +{ + std::string ss = s.substr(s.find_first_not_of(" \t")); + return ss.substr(0, ss.find_last_not_of(" \t") + 1); +} + +bool parse_key(const std::string& key, std::string& dev, std::string& reg) +{ + if(key.substr(0, 3) != "HW.") + return false; + std::string s = key.substr(3); + size_t idx = s.find('.'); + if(idx == std::string::npos) + return false; + dev = s.substr(0, idx); + reg = s.substr(idx + 1); + return true; +} + +bool find_addr(const soc_desc_v1::soc_dev_t& dev, + const std::string& reg, soc_desc_v1::soc_addr_t& addr) +{ + for(size_t i = 0; i < dev.reg.size(); i++) + for(size_t j = 0; j < dev.reg[i].addr.size(); j++) + if(dev.reg[i].addr[j].name == reg) + { + addr += dev.reg[i].addr[j].addr; + return true; + } + return false; +} + +bool find_addr(const soc_desc_v1::soc_t& soc, const std::string& dev, + const std::string& reg, soc_desc_v1::soc_addr_t& addr) +{ + addr = 0; + for(size_t i = 0; i < soc.dev.size(); i++) + for(size_t j = 0; j < soc.dev[i].addr.size(); j++) + if(soc.dev[i].addr[j].name == dev) + { + addr += soc.dev[i].addr[j].addr; + return find_addr(soc.dev[i], reg, addr); + } + return false; +} + +int convert_dump(const std::map< std::string, std::string >& entries, + const soc_desc_v1::soc_t& soc, std::ofstream& fout) +{ + std::map< std::string, std::string >::const_iterator it = entries.begin(); + for(; it != entries.end(); ++it) + { + char *end; + soc_desc_v1::soc_word_t v = strtoul(it->second.c_str(), &end, 0); + if(*end != 0) + { + printf("because of invalid value '%s': ignore key '%s'\n", + it->second.c_str(), it->first.c_str()); + continue; + } + std::string dev, reg; + if(!parse_key(it->first, dev, reg)) + { + printf("invalid key format, ignore key '%s'\n", it->first.c_str()); + continue; + } + soc_desc_v1::soc_addr_t addr; + if(!find_addr(soc, dev, reg, addr)) + { + printf("cannot find register in description, ignore key '%s'\n", + it->first.c_str()); + continue; + } + fout << "0x" << std::hex << addr << " = 0x" << std::hex << v << "\n"; + } + return 0; +} + +int do_convertdump(int argc, char **argv) +{ + if(argc < 3) + { + printf("you must specify at least one description file, one input file and one output file\n"); + return 1; + } + std::vector< soc_desc_v1::soc_t > socs; + for(int i = 0; i < argc - 2; i++) + { + socs.resize(socs.size() + 1); + if(!parse_xml(argv[i], socs.back())) + { + socs.pop_back(); + printf("cannot parse description file '%s'\n", argv[i]); + } + } + std::ifstream fin(argv[argc - 2]); + if(!fin) + { + printf("cannot open input file\n"); + return 1; + } + std::map< std::string, std::string > entries; + std::string line; + while(std::getline(fin, line)) + { + size_t idx = line.find('='); + if(idx == std::string::npos) + { + printf("ignore invalid line '%s'\n", line.c_str()); + continue; + } + std::string key = trim(line.substr(0, idx)); + std::string value = trim(line.substr(idx + 1)); + entries[key] = value; + } + if(entries.find("HW") == entries.end()) + { + printf("invalid dump file: missing HW key\n"); + return 1; + } + std::string soc = entries["HW"]; + soc_desc_v1::soc_t *psoc = 0; + for(size_t i = 0; i < socs.size(); i++) + if(socs[i].name == soc) + psoc = &socs[i]; + if(psoc == 0) + { + printf("cannot convert dump: please provide the description file for the soc '%s'\n", soc.c_str()); + return 1; + } + entries.erase(entries.find("HW")); + std::ofstream fout(argv[argc - 1]); + if(!fout) + { + printf("cannot open output file\n"); + return 1; + } + fout << "soc = " << soc << "\n"; + return convert_dump(entries, *psoc, fout); +} + +int do_normalize(int argc, char **argv) +{ + if(argc != 2) + { + printf("normalize takes two arguments\n"); + return 1; + } + error_context_t ctx; + soc_t soc; + bool ret = parse_xml(argv[0], soc, ctx); + if(ctx.count() != 0) + printf("In file %s:\n", argv[0]); + print_context(ctx); + if(!ret) + { + printf("cannot parse file '%s'\n", argv[1]); + return 2; + } + normalize(soc); + ret = produce_xml(argv[1], soc, ctx); + if(ctx.count() != 0) + printf("In file %s:\n", argv[1]); + print_context(ctx); + if(!ret) + { + printf("cannot write file '%s'\n", argv[1]); + return 3; + } + return 0; +} + void usage() { printf("usage: swiss_knife <mode> [options]\n"); @@ -583,9 +789,22 @@ void usage() printf(" read <files...>\n"); printf(" write <read file> <write file>\n"); printf(" eval [<formula>|--var <name>=<val>]...\n"); - printf(" convert <input file> <output file>\n"); + printf(" convert [--author <auth>] [--version <ver>] <input file> <output file>\n"); printf(" check <files...>\n"); printf(" dump [--nodes] [--instances] [--registers] [--verbose] <files...>\n"); + printf(" convertdump <desc file> ... <desc file> <input dump file> <output dump file>\n"); + printf(" normalize <desc file> <output desc file>\n"); + printf("\n"); + printf("The following operations are performed in each mode:\n"); + printf("* read: open and parse the files, reports any obvious errors\n"); + printf("* write: open, parse a file and write it back, checks the parser/generator match\n"); + printf("* eval: evaluate a formula with the formula parser\n"); + printf("* convert: convert a description file from version 1 to version 2\n"); + printf("* check: performs deep checks on description files\n"); + printf("* dump: debug tool to dump internal structures\n"); + printf("* convertdump: convert a register dump from version 1 to version 2\n"); + printf(" NOTE: description file must be a v1 file\n"); + printf("* normalize: normalise a description file\n"); exit(1); } @@ -606,6 +825,10 @@ int main(int argc, char **argv) return do_check(argc - 2, argv + 2); else if(mode == "dump") return do_dump(argc - 2, argv + 2); + else if(mode == "convertdump") + return do_convertdump(argc - 2, argv + 2); + else if(mode == "normalize") + return do_normalize(argc - 2, argv + 2); else usage(); return 0; |