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 eaa2519a27..fb65b5ca24 100644 --- a/utils/regtools/swiss_knife.cpp +++ b/utils/regtools/swiss_knife.cpp | |||
@@ -20,11 +20,14 @@ | |||
20 | ****************************************************************************/ | 20 | ****************************************************************************/ |
21 | #include "soc_desc.hpp" | 21 | #include "soc_desc.hpp" |
22 | #include "soc_desc_v1.hpp" | 22 | #include "soc_desc_v1.hpp" |
23 | #include <stdio.h> | 23 | #include <cstdio> |
24 | #include <stdlib.h> | 24 | #include <cstdlib> |
25 | #include <map> | 25 | #include <map> |
26 | #include <set> | 26 | #include <set> |
27 | #include <cstring> | 27 | #include <cstring> |
28 | #include <fstream> | ||
29 | #include <sstream> | ||
30 | #include <cstring> | ||
28 | 31 | ||
29 | using namespace soc_desc; | 32 | using namespace soc_desc; |
30 | 33 | ||
@@ -88,7 +91,6 @@ bool convert_v1_to_v2(const soc_desc_v1::soc_reg_t& in, node_t& out, error_conte | |||
88 | { | 91 | { |
89 | std::string loc = _loc + "." + in.name; | 92 | std::string loc = _loc + "." + in.name; |
90 | out.name = in.name; | 93 | out.name = in.name; |
91 | out.desc = in.desc; | ||
92 | if(in.formula.type == soc_desc_v1::REG_FORMULA_NONE) | 94 | if(in.formula.type == soc_desc_v1::REG_FORMULA_NONE) |
93 | { | 95 | { |
94 | out.instance.resize(in.addr.size()); | 96 | 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 | |||
133 | } | 135 | } |
134 | out.register_.resize(1); | 136 | out.register_.resize(1); |
135 | out.register_[0].width = 32; | 137 | out.register_[0].width = 32; |
138 | out.register_[0].desc = in.desc; | ||
136 | out.register_[0].field.resize(in.field.size()); | 139 | out.register_[0].field.resize(in.field.size()); |
137 | for(size_t i = 0; i < in.field.size(); i++) | 140 | for(size_t i = 0; i < in.field.size(); i++) |
138 | if(!convert_v1_to_v2(in.field[i], out.register_[0].field[i], ctx)) | 141 | 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 | |||
140 | /* sct */ | 143 | /* sct */ |
141 | if(in.flags & soc_desc_v1::REG_HAS_SCT) | 144 | if(in.flags & soc_desc_v1::REG_HAS_SCT) |
142 | { | 145 | { |
143 | out.node.resize(1); | 146 | out.register_[0].variant.resize(3); |
144 | out.node[0].name = "SCT"; | 147 | const char *names[3] = {"set", "clr", "tog"}; |
145 | out.node[0].instance.resize(3); | ||
146 | const char *names[3] = {"SET", "CLR", "TOG"}; | ||
147 | for(size_t i = 0; i < 3; i++) | 148 | for(size_t i = 0; i < 3; i++) |
148 | { | 149 | { |
149 | out.node[0].instance[i].name = names[i]; | 150 | out.register_[0].variant[i].type = names[i]; |
150 | out.node[0].instance[i].type = instance_t::SINGLE; | 151 | out.register_[0].variant[i].offset = 4 + i *4; |
151 | out.node[0].instance[i].addr = 4 + i *4; | ||
152 | } | 152 | } |
153 | } | 153 | } |
154 | return true; | 154 | return true; |
@@ -171,10 +171,23 @@ bool convert_v1_to_v2(const soc_desc_v1::soc_dev_t& in, node_t& out, error_conte | |||
171 | out.name = in.name; | 171 | out.name = in.name; |
172 | out.title = in.long_name; | 172 | out.title = in.long_name; |
173 | out.desc = in.desc; | 173 | out.desc = in.desc; |
174 | out.instance.resize(in.addr.size()); | 174 | out.instance.resize(1); |
175 | for(size_t i = 0; i < in.addr.size(); i++) | 175 | if(in.addr.size() == 1) |
176 | if(!convert_v1_to_v2(in.addr[i], out.instance[i], ctx)) | 176 | { |
177 | return false; | 177 | out.instance[0].type = instance_t::SINGLE; |
178 | out.instance[0].name = in.addr[0].name; | ||
179 | out.instance[0].addr = in.addr[0].addr; | ||
180 | } | ||
181 | else | ||
182 | { | ||
183 | out.instance[0].type = instance_t::RANGE; | ||
184 | out.instance[0].name = in.name; | ||
185 | out.instance[0].range.type = range_t::LIST; | ||
186 | out.instance[0].range.first = 1; | ||
187 | out.instance[0].range.list.resize(in.addr.size()); | ||
188 | for(size_t i = 0; i < in.addr.size(); i++) | ||
189 | out.instance[0].range.list[i] = in.addr[i].addr; | ||
190 | } | ||
178 | out.node.resize(in.reg.size()); | 191 | out.node.resize(in.reg.size()); |
179 | for(size_t i = 0; i < in.reg.size(); i++) | 192 | for(size_t i = 0; i < in.reg.size(); i++) |
180 | if(!convert_v1_to_v2(in.reg[i], out.node[i], ctx, loc)) | 193 | 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& | |||
195 | 208 | ||
196 | int do_convert(int argc, char **argv) | 209 | int do_convert(int argc, char **argv) |
197 | { | 210 | { |
198 | if(argc != 2) | 211 | std::vector< std::string > authors; |
199 | return printf("convert mode expects two arguments\n"); | 212 | std::string version; |
213 | while(argc >= 2) | ||
214 | { | ||
215 | if(strcmp(argv[0], "--author") == 0) | ||
216 | authors.push_back(argv[1]); | ||
217 | else if(strcmp(argv[0], "--version") == 0) | ||
218 | version = argv[1]; | ||
219 | else | ||
220 | break; | ||
221 | argc -= 2; | ||
222 | argv += 2; | ||
223 | } | ||
224 | if(argc < 2) | ||
225 | return printf("convert mode expects at least one description file and an output file\n"); | ||
200 | soc_desc_v1::soc_t soc; | 226 | soc_desc_v1::soc_t soc; |
201 | if(!soc_desc_v1::parse_xml(argv[0], soc)) | 227 | if(!soc_desc_v1::parse_xml(argv[0], soc)) |
202 | return printf("cannot read file '%s'\n", argv[0]); | 228 | return printf("cannot read file '%s'\n", argv[0]); |
@@ -207,6 +233,8 @@ int do_convert(int argc, char **argv) | |||
207 | print_context(ctx); | 233 | print_context(ctx); |
208 | return printf("cannot convert from v1 to v2\n"); | 234 | return printf("cannot convert from v1 to v2\n"); |
209 | } | 235 | } |
236 | new_soc.author = authors; | ||
237 | new_soc.version = version; | ||
210 | if(!produce_xml(argv[1], new_soc, ctx)) | 238 | if(!produce_xml(argv[1], new_soc, ctx)) |
211 | { | 239 | { |
212 | print_context(ctx); | 240 | print_context(ctx); |
@@ -392,7 +420,7 @@ void check_node(const std::string& _path, const node_t& node, error_context_t& c | |||
392 | std::string path = _path + "." + node.name; | 420 | std::string path = _path + "." + node.name; |
393 | check_name(_path, node.name, ctx); | 421 | check_name(_path, node.name, ctx); |
394 | if(node.instance.empty()) | 422 | if(node.instance.empty()) |
395 | ctx.add(error_t(error_t::FATAL, path, "subnode with no instances")); | 423 | ctx.add(error_t(error_t::WARNING, path, "subnode with no instances")); |
396 | for(size_t j = 0; j < node.instance.size(); j++) | 424 | for(size_t j = 0; j < node.instance.size(); j++) |
397 | check_instance(path, node.instance[j], ctx); | 425 | check_instance(path, node.instance[j], ctx); |
398 | for(size_t i = 0; i < node.register_.size(); i++) | 426 | for(size_t i = 0; i < node.register_.size(); i++) |
@@ -506,6 +534,12 @@ void print_reg(register_ref_t reg, unsigned flags) | |||
506 | printf(":[%u-%u]=", (unsigned)(f->pos + f->width - 1), (unsigned)f->pos); | 534 | printf(":[%u-%u]=", (unsigned)(f->pos + f->width - 1), (unsigned)f->pos); |
507 | printf("%s\n", f->name.c_str()); | 535 | printf("%s\n", f->name.c_str()); |
508 | } | 536 | } |
537 | std::vector< variant_ref_t > variants = reg.variants(); | ||
538 | for(size_t i = 0; i < variants.size(); i++) | ||
539 | { | ||
540 | print_path(node, false); | ||
541 | printf(":%s@+0x%x\n", variants[i].type().c_str(), variants[i].offset()); | ||
542 | } | ||
509 | } | 543 | } |
510 | 544 | ||
511 | void do_dump(node_ref_t node, unsigned flags) | 545 | void do_dump(node_ref_t node, unsigned flags) |
@@ -576,6 +610,178 @@ int do_dump(int argc, char **argv) | |||
576 | return 0; | 610 | return 0; |
577 | } | 611 | } |
578 | 612 | ||
613 | std::string trim(const std::string& s) | ||
614 | { | ||
615 | std::string ss = s.substr(s.find_first_not_of(" \t")); | ||
616 | return ss.substr(0, ss.find_last_not_of(" \t") + 1); | ||
617 | } | ||
618 | |||
619 | bool parse_key(const std::string& key, std::string& dev, std::string& reg) | ||
620 | { | ||
621 | if(key.substr(0, 3) != "HW.") | ||
622 | return false; | ||
623 | std::string s = key.substr(3); | ||
624 | size_t idx = s.find('.'); | ||
625 | if(idx == std::string::npos) | ||
626 | return false; | ||
627 | dev = s.substr(0, idx); | ||
628 | reg = s.substr(idx + 1); | ||
629 | return true; | ||
630 | } | ||
631 | |||
632 | bool find_addr(const soc_desc_v1::soc_dev_t& dev, | ||
633 | const std::string& reg, soc_desc_v1::soc_addr_t& addr) | ||
634 | { | ||
635 | for(size_t i = 0; i < dev.reg.size(); i++) | ||
636 | for(size_t j = 0; j < dev.reg[i].addr.size(); j++) | ||
637 | if(dev.reg[i].addr[j].name == reg) | ||
638 | { | ||
639 | addr += dev.reg[i].addr[j].addr; | ||
640 | return true; | ||
641 | } | ||
642 | return false; | ||
643 | } | ||
644 | |||
645 | bool find_addr(const soc_desc_v1::soc_t& soc, const std::string& dev, | ||
646 | const std::string& reg, soc_desc_v1::soc_addr_t& addr) | ||
647 | { | ||
648 | addr = 0; | ||
649 | for(size_t i = 0; i < soc.dev.size(); i++) | ||
650 | for(size_t j = 0; j < soc.dev[i].addr.size(); j++) | ||
651 | if(soc.dev[i].addr[j].name == dev) | ||
652 | { | ||
653 | addr += soc.dev[i].addr[j].addr; | ||
654 | return find_addr(soc.dev[i], reg, addr); | ||
655 | } | ||
656 | return false; | ||
657 | } | ||
658 | |||
659 | int convert_dump(const std::map< std::string, std::string >& entries, | ||
660 | const soc_desc_v1::soc_t& soc, std::ofstream& fout) | ||
661 | { | ||
662 | std::map< std::string, std::string >::const_iterator it = entries.begin(); | ||
663 | for(; it != entries.end(); ++it) | ||
664 | { | ||
665 | char *end; | ||
666 | soc_desc_v1::soc_word_t v = strtoul(it->second.c_str(), &end, 0); | ||
667 | if(*end != 0) | ||
668 | { | ||
669 | printf("because of invalid value '%s': ignore key '%s'\n", | ||
670 | it->second.c_str(), it->first.c_str()); | ||
671 | continue; | ||
672 | } | ||
673 | std::string dev, reg; | ||
674 | if(!parse_key(it->first, dev, reg)) | ||
675 | { | ||
676 | printf("invalid key format, ignore key '%s'\n", it->first.c_str()); | ||
677 | continue; | ||
678 | } | ||
679 | soc_desc_v1::soc_addr_t addr; | ||
680 | if(!find_addr(soc, dev, reg, addr)) | ||
681 | { | ||
682 | printf("cannot find register in description, ignore key '%s'\n", | ||
683 | it->first.c_str()); | ||
684 | continue; | ||
685 | } | ||
686 | fout << "0x" << std::hex << addr << " = 0x" << std::hex << v << "\n"; | ||
687 | } | ||
688 | return 0; | ||
689 | } | ||
690 | |||
691 | int do_convertdump(int argc, char **argv) | ||
692 | { | ||
693 | if(argc < 3) | ||
694 | { | ||
695 | printf("you must specify at least one description file, one input file and one output file\n"); | ||
696 | return 1; | ||
697 | } | ||
698 | std::vector< soc_desc_v1::soc_t > socs; | ||
699 | for(int i = 0; i < argc - 2; i++) | ||
700 | { | ||
701 | socs.resize(socs.size() + 1); | ||
702 | if(!parse_xml(argv[i], socs.back())) | ||
703 | { | ||
704 | socs.pop_back(); | ||
705 | printf("cannot parse description file '%s'\n", argv[i]); | ||
706 | } | ||
707 | } | ||
708 | std::ifstream fin(argv[argc - 2]); | ||
709 | if(!fin) | ||
710 | { | ||
711 | printf("cannot open input file\n"); | ||
712 | return 1; | ||
713 | } | ||
714 | std::map< std::string, std::string > entries; | ||
715 | std::string line; | ||
716 | while(std::getline(fin, line)) | ||
717 | { | ||
718 | size_t idx = line.find('='); | ||
719 | if(idx == std::string::npos) | ||
720 | { | ||
721 | printf("ignore invalid line '%s'\n", line.c_str()); | ||
722 | continue; | ||
723 | } | ||
724 | std::string key = trim(line.substr(0, idx)); | ||
725 | std::string value = trim(line.substr(idx + 1)); | ||
726 | entries[key] = value; | ||
727 | } | ||
728 | if(entries.find("HW") == entries.end()) | ||
729 | { | ||
730 | printf("invalid dump file: missing HW key\n"); | ||
731 | return 1; | ||
732 | } | ||
733 | std::string soc = entries["HW"]; | ||
734 | soc_desc_v1::soc_t *psoc = 0; | ||
735 | for(size_t i = 0; i < socs.size(); i++) | ||
736 | if(socs[i].name == soc) | ||
737 | psoc = &socs[i]; | ||
738 | if(psoc == 0) | ||
739 | { | ||
740 | printf("cannot convert dump: please provide the description file for the soc '%s'\n", soc.c_str()); | ||
741 | return 1; | ||
742 | } | ||
743 | entries.erase(entries.find("HW")); | ||
744 | std::ofstream fout(argv[argc - 1]); | ||
745 | if(!fout) | ||
746 | { | ||
747 | printf("cannot open output file\n"); | ||
748 | return 1; | ||
749 | } | ||
750 | fout << "soc = " << soc << "\n"; | ||
751 | return convert_dump(entries, *psoc, fout); | ||
752 | } | ||
753 | |||
754 | int do_normalize(int argc, char **argv) | ||
755 | { | ||
756 | if(argc != 2) | ||
757 | { | ||
758 | printf("normalize takes two arguments\n"); | ||
759 | return 1; | ||
760 | } | ||
761 | error_context_t ctx; | ||
762 | soc_t soc; | ||
763 | bool ret = parse_xml(argv[0], soc, ctx); | ||
764 | if(ctx.count() != 0) | ||
765 | printf("In file %s:\n", argv[0]); | ||
766 | print_context(ctx); | ||
767 | if(!ret) | ||
768 | { | ||
769 | printf("cannot parse file '%s'\n", argv[1]); | ||
770 | return 2; | ||
771 | } | ||
772 | normalize(soc); | ||
773 | ret = produce_xml(argv[1], soc, ctx); | ||
774 | if(ctx.count() != 0) | ||
775 | printf("In file %s:\n", argv[1]); | ||
776 | print_context(ctx); | ||
777 | if(!ret) | ||
778 | { | ||
779 | printf("cannot write file '%s'\n", argv[1]); | ||
780 | return 3; | ||
781 | } | ||
782 | return 0; | ||
783 | } | ||
784 | |||
579 | void usage() | 785 | void usage() |
580 | { | 786 | { |
581 | printf("usage: swiss_knife <mode> [options]\n"); | 787 | printf("usage: swiss_knife <mode> [options]\n"); |
@@ -583,9 +789,22 @@ void usage() | |||
583 | printf(" read <files...>\n"); | 789 | printf(" read <files...>\n"); |
584 | printf(" write <read file> <write file>\n"); | 790 | printf(" write <read file> <write file>\n"); |
585 | printf(" eval [<formula>|--var <name>=<val>]...\n"); | 791 | printf(" eval [<formula>|--var <name>=<val>]...\n"); |
586 | printf(" convert <input file> <output file>\n"); | 792 | printf(" convert [--author <auth>] [--version <ver>] <input file> <output file>\n"); |
587 | printf(" check <files...>\n"); | 793 | printf(" check <files...>\n"); |
588 | printf(" dump [--nodes] [--instances] [--registers] [--verbose] <files...>\n"); | 794 | printf(" dump [--nodes] [--instances] [--registers] [--verbose] <files...>\n"); |
795 | printf(" convertdump <desc file> ... <desc file> <input dump file> <output dump file>\n"); | ||
796 | printf(" normalize <desc file> <output desc file>\n"); | ||
797 | printf("\n"); | ||
798 | printf("The following operations are performed in each mode:\n"); | ||
799 | printf("* read: open and parse the files, reports any obvious errors\n"); | ||
800 | printf("* write: open, parse a file and write it back, checks the parser/generator match\n"); | ||
801 | printf("* eval: evaluate a formula with the formula parser\n"); | ||
802 | printf("* convert: convert a description file from version 1 to version 2\n"); | ||
803 | printf("* check: performs deep checks on description files\n"); | ||
804 | printf("* dump: debug tool to dump internal structures\n"); | ||
805 | printf("* convertdump: convert a register dump from version 1 to version 2\n"); | ||
806 | printf(" NOTE: description file must be a v1 file\n"); | ||
807 | printf("* normalize: normalise a description file\n"); | ||
589 | exit(1); | 808 | exit(1); |
590 | } | 809 | } |
591 | 810 | ||
@@ -606,6 +825,10 @@ int main(int argc, char **argv) | |||
606 | return do_check(argc - 2, argv + 2); | 825 | return do_check(argc - 2, argv + 2); |
607 | else if(mode == "dump") | 826 | else if(mode == "dump") |
608 | return do_dump(argc - 2, argv + 2); | 827 | return do_dump(argc - 2, argv + 2); |
828 | else if(mode == "convertdump") | ||
829 | return do_convertdump(argc - 2, argv + 2); | ||
830 | else if(mode == "normalize") | ||
831 | return do_normalize(argc - 2, argv + 2); | ||
609 | else | 832 | else |
610 | usage(); | 833 | usage(); |
611 | return 0; | 834 | return 0; |