summaryrefslogtreecommitdiff
path: root/utils/regtools/swiss_knife.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'utils/regtools/swiss_knife.cpp')
-rw-r--r--utils/regtools/swiss_knife.cpp259
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
29using namespace soc_desc; 32using 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
196int do_convert(int argc, char **argv) 209int 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
511void do_dump(node_ref_t node, unsigned flags) 545void 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
613std::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
619bool 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
632bool 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
645bool 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
659int 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
691int 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
754int 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
579void usage() 785void 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;