summaryrefslogtreecommitdiffstats
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 @@
****************************************************************************/
#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;