diff options
Diffstat (limited to 'utils/regtools/tester.cpp')
-rw-r--r-- | utils/regtools/tester.cpp | 344 |
1 files changed, 305 insertions, 39 deletions
diff --git a/utils/regtools/tester.cpp b/utils/regtools/tester.cpp index 1fa21c6894..1beba5fe9b 100644 --- a/utils/regtools/tester.cpp +++ b/utils/regtools/tester.cpp @@ -21,77 +21,343 @@ #include "soc_desc.hpp" #include <stdio.h> #include <stdlib.h> +#include <map> +#include <cstring> -void print_value_desc(const soc_reg_field_value_t& value) +template< typename T > +bool build_map(const char *type, const std::vector< T >& vec, + std::map< std::string, size_t >& map) { - printf(" VALUE %s (%#x)\n", value.name.c_str(), value.value); + for(size_t i = 0; i < vec.size(); i++) + { + if(map.find(vec[i].name) != map.end()) + { + printf("soc has duplicate %s '%s'\n", type, vec[i].name.c_str()); + return false; + } + map[vec[i].name] = i; + } + return true; } -void print_field_desc(const soc_reg_field_t& field) +template< typename T > +bool build_map(const char *type, const std::vector< T >& a, const std::vector< T >& b, + std::vector< std::pair< size_t, size_t > >& m) { - printf(" FIELD %s (%d:%d)\n", field.name.c_str(), field.last_bit, - field.first_bit); - for(size_t i = 0; i < field.value.size(); i++) - print_value_desc(field.value[i]); + std::map< std::string, size_t > ma, mb; + if(!build_map(type, a, ma) || !build_map(type, b, mb)) + return false; + std::map< std::string, size_t >::iterator it; + for(it = ma.begin(); it != ma.end(); ++it) + { + if(mb.find(it->first) == mb.end()) + { + printf("%s '%s' exists in only one file\n", type, it->first.c_str()); + return false; + } + m.push_back(std::make_pair(it->second, mb[it->first])); + } + for(it = mb.begin(); it != mb.end(); ++it) + { + if(ma.find(it->first) == ma.end()) + { + printf("%s '%s' exists in only one file\n", type, it->first.c_str()); + return false; + } + } + return true; } -std::string compute_sct(soc_reg_flags_t f) +bool compare_value(const soc_t& soc, const soc_dev_t& dev, const soc_reg_t& reg, + const soc_reg_field_t& field, const soc_reg_field_value_t& a, const soc_reg_field_value_t& b) { - if(f & REG_HAS_SCT) return "SCT"; - else return ""; + if(a.value != b.value) + { + printf("register field value '%s.%s.%s.%s.%s' have different values\n", soc.name.c_str(), + dev.name.c_str(), reg.name.c_str(), field.name.c_str(), a.name.c_str()); + return false; + } + if(a.desc != b.desc) + { + printf("register field value '%s.%s.%s.%s.%s' have different descriptions\n", soc.name.c_str(), + dev.name.c_str(), reg.name.c_str(), field.name.c_str(), a.name.c_str()); + return false; + } + return true; } -void print_reg_addr_desc(const soc_reg_addr_t& reg) +bool compare_field(const soc_t& soc, const soc_dev_t& dev, const soc_reg_t& reg, + const soc_reg_field_t& a, const soc_reg_field_t& b) { - printf(" ADDR %s %#x\n", reg.name.c_str(), reg.addr); + if(a.first_bit != b.first_bit || a.last_bit != b.last_bit) + { + printf("register address '%s.%s.%s.%s' have different bit ranges\n", soc.name.c_str(), + dev.name.c_str(), reg.name.c_str(), a.name.c_str()); + return false; + } + if(a.desc != b.desc) + { + printf("register address '%s.%s.%s.%s' have different descriptions\n", soc.name.c_str(), + dev.name.c_str(), reg.name.c_str(), a.name.c_str()); + return false; + } + /* values */ + std::vector< std::pair< size_t, size_t > > map; + if(!build_map("field value", a.value, b.value, map)) + return false; + for(size_t i = 0; i < map.size(); i++) + if(!compare_value(soc, dev, reg, a, a.value[map[i].first], b.value[map[i].second])) + return false; + return true; } -void print_reg_desc(const soc_reg_t& reg) +bool compare_reg_addr(const soc_t& soc, const soc_dev_t& dev, const soc_reg_t& reg, + const soc_reg_addr_t& a, const soc_reg_addr_t& b) { - std::string sct = compute_sct(reg.flags); - printf(" REG %s %s\n", reg.name.c_str(), sct.c_str()); - for(size_t i = 0; i < reg.addr.size(); i++) - print_reg_addr_desc(reg.addr[i]); - for(size_t i = 0; i < reg.field.size(); i++) - print_field_desc(reg.field[i]); + if(a.addr != b.addr) + { + printf("register address '%s.%s.%s.%s' have different values\n", soc.name.c_str(), + dev.name.c_str(), reg.name.c_str(), a.name.c_str()); + return false; + } + else + return true; } -void print_dev_addr_desc(const soc_dev_addr_t& dev) +bool compare_reg(const soc_t& soc, const soc_dev_t& dev, const soc_reg_t& a, + const soc_reg_t& b) { - printf(" ADDR %s %#x\n", dev.name.c_str(), dev.addr); + if(a.desc != b.desc) + { + printf("register '%s.%s.%s' have different descriptions\n", soc.name.c_str(), + dev.name.c_str(), a.name.c_str()); + return false; + } + if(a.flags != b.flags) + { + printf("device '%s.%s.%s' have different flags\n", soc.name.c_str(), + dev.name.c_str(), a.name.c_str()); + return false; + } + if(a.formula.type != b.formula.type) + { + printf("device '%s.%s.%s' have different formula types\n", soc.name.c_str(), + dev.name.c_str(), a.name.c_str()); + return false; + } + if(a.formula.string != b.formula.string) + { + printf("device '%s.%s.%s' have different formula string\n", soc.name.c_str(), + dev.name.c_str(), a.name.c_str()); + return false; + } + /* addresses */ + std::vector< std::pair< size_t, size_t > > map; + if(!build_map("register address", a.addr, b.addr, map)) + return false; + for(size_t i = 0; i < map.size(); i++) + if(!compare_reg_addr(soc, dev, a, a.addr[map[i].first], b.addr[map[i].second])) + return false; + /* field */ + map.clear(); + if(!build_map("field", a.field, b.field, map)) + return false; + for(size_t i = 0; i < map.size(); i++) + if(!compare_field(soc, dev, a, a.field[map[i].first], b.field[map[i].second])) + return false; + return true; } -void print_dev_desc(const soc_dev_t& dev) +bool compare_dev_addr(const soc_t& soc, const soc_dev_t& dev, const soc_dev_addr_t& a, + const soc_dev_addr_t& b) { - printf(" DEV %s\n", dev.name.c_str()); - for(size_t i = 0; i < dev.addr.size(); i++) - print_dev_addr_desc(dev.addr[i]); - for(size_t i = 0; i < dev.reg.size(); i++) - print_reg_desc(dev.reg[i]); + if(a.addr != b.addr) + { + printf("device address '%s.%s.%s' have different values\n", soc.name.c_str(), + dev.name.c_str(), a.name.c_str()); + return false; + } + else + return true; } -void print_soc_desc(const soc_t& soc) +bool compare_dev(const soc_t& soc, const soc_dev_t& a, const soc_dev_t& b) { - printf("SOC %s (%s)\n", soc.name.c_str(), soc.desc.c_str()); - for(size_t i = 0; i < soc.dev.size(); i++) - print_dev_desc(soc.dev[i]); + if(a.long_name != b.long_name) + { + printf("device '%s.%s' have different long names\n", soc.name.c_str(), + a.name.c_str()); + return false; + } + if(a.desc != b.desc) + { + printf("device '%s.%s' have different descriptions\n", soc.name.c_str(), + a.name.c_str()); + return false; + } + if(a.version != b.version) + { + printf("device '%s.%s' have different versions\n", soc.name.c_str(), + a.name.c_str()); + return false; + } + /* addresses */ + std::vector< std::pair< size_t, size_t > > map; + if(!build_map("device address", a.addr, b.addr, map)) + return false; + for(size_t i = 0; i < map.size(); i++) + if(!compare_dev_addr(soc, a, a.addr[map[i].first], b.addr[map[i].second])) + return false; + /* reg */ + map.clear(); + if(!build_map("register", a.reg, b.reg, map)) + return false; + for(size_t i = 0; i < map.size(); i++) + if(!compare_reg(soc, a, a.reg[map[i].first], b.reg[map[i].second])) + return false; + return true; +} + +bool compare_soc(const soc_t& a, const soc_t& b) +{ + if(a.name != b.name) + { + return printf("soc have different names\n"); + return false; + } + if(a.desc != b.desc) + { + printf("soc '%s' have different descriptions\n", a.name.c_str()); + return false; + } + std::vector< std::pair< size_t, size_t > > map; + if(!build_map("device", a.dev, b.dev, map)) + return false; + for(size_t i = 0; i< map.size(); i++) + if(!compare_dev(a, a.dev[map[i].first], b.dev[map[i].second])) + return false; + return true; +} + +int do_compare(int argc, char **argv) +{ + if(argc != 2) + return printf("compare mode expects two arguments\n"); + soc_t soc[2]; + if(!soc_desc_parse_xml(argv[0], soc[0])) + return printf("cannot read file '%s'\n", argv[0]); + if(!soc_desc_parse_xml(argv[1], soc[1])) + return printf("cannot read file '%s'\n", argv[1]); + if(compare_soc(soc[0], soc[1])) + printf("Files are identical.\n"); + return 0; +} + +int do_write(int argc, char **argv) +{ + if(argc != 2) + return printf("write mode expects two arguments\n"); + soc_t soc; + if(!soc_desc_parse_xml(argv[0], soc)) + return printf("cannot read file '%s'\n", argv[0]); + if(!soc_desc_produce_xml(argv[1], soc)) + return printf("cannot write file '%s'\n", argv[1]); + return 0; +} + +int do_check(int argc, char **argv) +{ + for(int i = 0; i < argc; i++) + { + soc_t soc; + if(!soc_desc_parse_xml(argv[i], soc)) + { + printf("cannot read file '%s'\n", argv[i]); + continue; + } + printf("[%s]\n", argv[i]); + std::vector< soc_error_t > errs = soc.errors(true); + for(size_t i = 0; i < errs.size(); i++) + { + const soc_error_t& e = errs[i]; + switch(e.level) + { + case SOC_ERROR_WARNING: printf("[WARN ] "); break; + case SOC_ERROR_FATAL: printf("[FATAL] "); break; + default: printf("[ UNK ] "); break; + } + printf("%s: %s\n", e.location.c_str(), e.message.c_str()); + } + } + return 0; +} + +int do_eval(int argc, char **argv) +{ + std::map< std::string, soc_word_t > map; + for(int i = 0; i < argc; i++) + { + std::string error; + std::string formula(argv[i]); + soc_word_t result; + if(strcmp(argv[i], "--var") == 0) + { + if(i + 1 >= argc) + break; + i++; + std::string str(argv[i]); + size_t pos = str.find('='); + if(pos == std::string::npos) + { + printf("invalid variable string '%s'\n", str.c_str()); + continue; + } + std::string name = str.substr(0, pos); + std::string val = str.substr(pos + 1); + char *end; + soc_word_t v = strtoul(val.c_str(), &end, 0); + if(*end) + { + printf("invalid variable string '%s'\n", str.c_str()); + continue; + } + printf("%s = %#lx\n", name.c_str(), (unsigned long)v); + map[name] = v; + continue; + } + if(!soc_desc_evaluate_formula(formula, map, result, error)) + printf("error: %s\n", error.c_str()); + else + printf("result: %lu (%#lx)\n", (unsigned long)result, (unsigned long)result); + } + return 0; } void usage() { - printf("usage: tester <desc file>\n"); + printf("usage: tester <mode> [options]\n"); + printf("modes:\n"); + printf(" compare <desc file> <desc file>\n"); + printf(" write <read file> <write file>\n"); + printf(" check <files...>\n"); + printf(" eval [<formula>|--var <name>=<val>]...\n"); exit(1); } int main(int argc, char **argv) { - if(argc != 2) + if(argc < 2) + usage(); + std::string mode = argv[1]; + if(mode == "compare") + return do_compare(argc - 2, argv + 2); + else if(mode == "write") + return do_write(argc - 2, argv + 2); + else if(mode == "check") + return do_check(argc - 2, argv + 2); + else if(mode == "eval") + return do_eval(argc - 2, argv + 2); + else usage(); - std::vector< soc_t > socs; - bool ret = soc_desc_parse_xml(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 |