summaryrefslogtreecommitdiff
path: root/utils/regtools/tester.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'utils/regtools/tester.cpp')
-rw-r--r--utils/regtools/tester.cpp344
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 @@
21#include "soc_desc.hpp" 21#include "soc_desc.hpp"
22#include <stdio.h> 22#include <stdio.h>
23#include <stdlib.h> 23#include <stdlib.h>
24#include <map>
25#include <cstring>
24 26
25void print_value_desc(const soc_reg_field_value_t& value) 27template< typename T >
28bool build_map(const char *type, const std::vector< T >& vec,
29 std::map< std::string, size_t >& map)
26{ 30{
27 printf(" VALUE %s (%#x)\n", value.name.c_str(), value.value); 31 for(size_t i = 0; i < vec.size(); i++)
32 {
33 if(map.find(vec[i].name) != map.end())
34 {
35 printf("soc has duplicate %s '%s'\n", type, vec[i].name.c_str());
36 return false;
37 }
38 map[vec[i].name] = i;
39 }
40 return true;
28} 41}
29 42
30void print_field_desc(const soc_reg_field_t& field) 43template< typename T >
44bool build_map(const char *type, const std::vector< T >& a, const std::vector< T >& b,
45 std::vector< std::pair< size_t, size_t > >& m)
31{ 46{
32 printf(" FIELD %s (%d:%d)\n", field.name.c_str(), field.last_bit, 47 std::map< std::string, size_t > ma, mb;
33 field.first_bit); 48 if(!build_map(type, a, ma) || !build_map(type, b, mb))
34 for(size_t i = 0; i < field.value.size(); i++) 49 return false;
35 print_value_desc(field.value[i]); 50 std::map< std::string, size_t >::iterator it;
51 for(it = ma.begin(); it != ma.end(); ++it)
52 {
53 if(mb.find(it->first) == mb.end())
54 {
55 printf("%s '%s' exists in only one file\n", type, it->first.c_str());
56 return false;
57 }
58 m.push_back(std::make_pair(it->second, mb[it->first]));
59 }
60 for(it = mb.begin(); it != mb.end(); ++it)
61 {
62 if(ma.find(it->first) == ma.end())
63 {
64 printf("%s '%s' exists in only one file\n", type, it->first.c_str());
65 return false;
66 }
67 }
68 return true;
36} 69}
37 70
38std::string compute_sct(soc_reg_flags_t f) 71bool compare_value(const soc_t& soc, const soc_dev_t& dev, const soc_reg_t& reg,
72 const soc_reg_field_t& field, const soc_reg_field_value_t& a, const soc_reg_field_value_t& b)
39{ 73{
40 if(f & REG_HAS_SCT) return "SCT"; 74 if(a.value != b.value)
41 else return ""; 75 {
76 printf("register field value '%s.%s.%s.%s.%s' have different values\n", soc.name.c_str(),
77 dev.name.c_str(), reg.name.c_str(), field.name.c_str(), a.name.c_str());
78 return false;
79 }
80 if(a.desc != b.desc)
81 {
82 printf("register field value '%s.%s.%s.%s.%s' have different descriptions\n", soc.name.c_str(),
83 dev.name.c_str(), reg.name.c_str(), field.name.c_str(), a.name.c_str());
84 return false;
85 }
86 return true;
42} 87}
43 88
44void print_reg_addr_desc(const soc_reg_addr_t& reg) 89bool compare_field(const soc_t& soc, const soc_dev_t& dev, const soc_reg_t& reg,
90 const soc_reg_field_t& a, const soc_reg_field_t& b)
45{ 91{
46 printf(" ADDR %s %#x\n", reg.name.c_str(), reg.addr); 92 if(a.first_bit != b.first_bit || a.last_bit != b.last_bit)
93 {
94 printf("register address '%s.%s.%s.%s' have different bit ranges\n", soc.name.c_str(),
95 dev.name.c_str(), reg.name.c_str(), a.name.c_str());
96 return false;
97 }
98 if(a.desc != b.desc)
99 {
100 printf("register address '%s.%s.%s.%s' have different descriptions\n", soc.name.c_str(),
101 dev.name.c_str(), reg.name.c_str(), a.name.c_str());
102 return false;
103 }
104 /* values */
105 std::vector< std::pair< size_t, size_t > > map;
106 if(!build_map("field value", a.value, b.value, map))
107 return false;
108 for(size_t i = 0; i < map.size(); i++)
109 if(!compare_value(soc, dev, reg, a, a.value[map[i].first], b.value[map[i].second]))
110 return false;
111 return true;
47} 112}
48 113
49void print_reg_desc(const soc_reg_t& reg) 114bool compare_reg_addr(const soc_t& soc, const soc_dev_t& dev, const soc_reg_t& reg,
115 const soc_reg_addr_t& a, const soc_reg_addr_t& b)
50{ 116{
51 std::string sct = compute_sct(reg.flags); 117 if(a.addr != b.addr)
52 printf(" REG %s %s\n", reg.name.c_str(), sct.c_str()); 118 {
53 for(size_t i = 0; i < reg.addr.size(); i++) 119 printf("register address '%s.%s.%s.%s' have different values\n", soc.name.c_str(),
54 print_reg_addr_desc(reg.addr[i]); 120 dev.name.c_str(), reg.name.c_str(), a.name.c_str());
55 for(size_t i = 0; i < reg.field.size(); i++) 121 return false;
56 print_field_desc(reg.field[i]); 122 }
123 else
124 return true;
57} 125}
58 126
59void print_dev_addr_desc(const soc_dev_addr_t& dev) 127bool compare_reg(const soc_t& soc, const soc_dev_t& dev, const soc_reg_t& a,
128 const soc_reg_t& b)
60{ 129{
61 printf(" ADDR %s %#x\n", dev.name.c_str(), dev.addr); 130 if(a.desc != b.desc)
131 {
132 printf("register '%s.%s.%s' have different descriptions\n", soc.name.c_str(),
133 dev.name.c_str(), a.name.c_str());
134 return false;
135 }
136 if(a.flags != b.flags)
137 {
138 printf("device '%s.%s.%s' have different flags\n", soc.name.c_str(),
139 dev.name.c_str(), a.name.c_str());
140 return false;
141 }
142 if(a.formula.type != b.formula.type)
143 {
144 printf("device '%s.%s.%s' have different formula types\n", soc.name.c_str(),
145 dev.name.c_str(), a.name.c_str());
146 return false;
147 }
148 if(a.formula.string != b.formula.string)
149 {
150 printf("device '%s.%s.%s' have different formula string\n", soc.name.c_str(),
151 dev.name.c_str(), a.name.c_str());
152 return false;
153 }
154 /* addresses */
155 std::vector< std::pair< size_t, size_t > > map;
156 if(!build_map("register address", a.addr, b.addr, map))
157 return false;
158 for(size_t i = 0; i < map.size(); i++)
159 if(!compare_reg_addr(soc, dev, a, a.addr[map[i].first], b.addr[map[i].second]))
160 return false;
161 /* field */
162 map.clear();
163 if(!build_map("field", a.field, b.field, map))
164 return false;
165 for(size_t i = 0; i < map.size(); i++)
166 if(!compare_field(soc, dev, a, a.field[map[i].first], b.field[map[i].second]))
167 return false;
168 return true;
62} 169}
63 170
64void print_dev_desc(const soc_dev_t& dev) 171bool compare_dev_addr(const soc_t& soc, const soc_dev_t& dev, const soc_dev_addr_t& a,
172 const soc_dev_addr_t& b)
65{ 173{
66 printf(" DEV %s\n", dev.name.c_str()); 174 if(a.addr != b.addr)
67 for(size_t i = 0; i < dev.addr.size(); i++) 175 {
68 print_dev_addr_desc(dev.addr[i]); 176 printf("device address '%s.%s.%s' have different values\n", soc.name.c_str(),
69 for(size_t i = 0; i < dev.reg.size(); i++) 177 dev.name.c_str(), a.name.c_str());
70 print_reg_desc(dev.reg[i]); 178 return false;
179 }
180 else
181 return true;
71} 182}
72 183
73void print_soc_desc(const soc_t& soc) 184bool compare_dev(const soc_t& soc, const soc_dev_t& a, const soc_dev_t& b)
74{ 185{
75 printf("SOC %s (%s)\n", soc.name.c_str(), soc.desc.c_str()); 186 if(a.long_name != b.long_name)
76 for(size_t i = 0; i < soc.dev.size(); i++) 187 {
77 print_dev_desc(soc.dev[i]); 188 printf("device '%s.%s' have different long names\n", soc.name.c_str(),
189 a.name.c_str());
190 return false;
191 }
192 if(a.desc != b.desc)
193 {
194 printf("device '%s.%s' have different descriptions\n", soc.name.c_str(),
195 a.name.c_str());
196 return false;
197 }
198 if(a.version != b.version)
199 {
200 printf("device '%s.%s' have different versions\n", soc.name.c_str(),
201 a.name.c_str());
202 return false;
203 }
204 /* addresses */
205 std::vector< std::pair< size_t, size_t > > map;
206 if(!build_map("device address", a.addr, b.addr, map))
207 return false;
208 for(size_t i = 0; i < map.size(); i++)
209 if(!compare_dev_addr(soc, a, a.addr[map[i].first], b.addr[map[i].second]))
210 return false;
211 /* reg */
212 map.clear();
213 if(!build_map("register", a.reg, b.reg, map))
214 return false;
215 for(size_t i = 0; i < map.size(); i++)
216 if(!compare_reg(soc, a, a.reg[map[i].first], b.reg[map[i].second]))
217 return false;
218 return true;
219}
220
221bool compare_soc(const soc_t& a, const soc_t& b)
222{
223 if(a.name != b.name)
224 {
225 return printf("soc have different names\n");
226 return false;
227 }
228 if(a.desc != b.desc)
229 {
230 printf("soc '%s' have different descriptions\n", a.name.c_str());
231 return false;
232 }
233 std::vector< std::pair< size_t, size_t > > map;
234 if(!build_map("device", a.dev, b.dev, map))
235 return false;
236 for(size_t i = 0; i< map.size(); i++)
237 if(!compare_dev(a, a.dev[map[i].first], b.dev[map[i].second]))
238 return false;
239 return true;
240}
241
242int do_compare(int argc, char **argv)
243{
244 if(argc != 2)
245 return printf("compare mode expects two arguments\n");
246 soc_t soc[2];
247 if(!soc_desc_parse_xml(argv[0], soc[0]))
248 return printf("cannot read file '%s'\n", argv[0]);
249 if(!soc_desc_parse_xml(argv[1], soc[1]))
250 return printf("cannot read file '%s'\n", argv[1]);
251 if(compare_soc(soc[0], soc[1]))
252 printf("Files are identical.\n");
253 return 0;
254}
255
256int do_write(int argc, char **argv)
257{
258 if(argc != 2)
259 return printf("write mode expects two arguments\n");
260 soc_t soc;
261 if(!soc_desc_parse_xml(argv[0], soc))
262 return printf("cannot read file '%s'\n", argv[0]);
263 if(!soc_desc_produce_xml(argv[1], soc))
264 return printf("cannot write file '%s'\n", argv[1]);
265 return 0;
266}
267
268int do_check(int argc, char **argv)
269{
270 for(int i = 0; i < argc; i++)
271 {
272 soc_t soc;
273 if(!soc_desc_parse_xml(argv[i], soc))
274 {
275 printf("cannot read file '%s'\n", argv[i]);
276 continue;
277 }
278 printf("[%s]\n", argv[i]);
279 std::vector< soc_error_t > errs = soc.errors(true);
280 for(size_t i = 0; i < errs.size(); i++)
281 {
282 const soc_error_t& e = errs[i];
283 switch(e.level)
284 {
285 case SOC_ERROR_WARNING: printf("[WARN ] "); break;
286 case SOC_ERROR_FATAL: printf("[FATAL] "); break;
287 default: printf("[ UNK ] "); break;
288 }
289 printf("%s: %s\n", e.location.c_str(), e.message.c_str());
290 }
291 }
292 return 0;
293}
294
295int do_eval(int argc, char **argv)
296{
297 std::map< std::string, soc_word_t > map;
298 for(int i = 0; i < argc; i++)
299 {
300 std::string error;
301 std::string formula(argv[i]);
302 soc_word_t result;
303 if(strcmp(argv[i], "--var") == 0)
304 {
305 if(i + 1 >= argc)
306 break;
307 i++;
308 std::string str(argv[i]);
309 size_t pos = str.find('=');
310 if(pos == std::string::npos)
311 {
312 printf("invalid variable string '%s'\n", str.c_str());
313 continue;
314 }
315 std::string name = str.substr(0, pos);
316 std::string val = str.substr(pos + 1);
317 char *end;
318 soc_word_t v = strtoul(val.c_str(), &end, 0);
319 if(*end)
320 {
321 printf("invalid variable string '%s'\n", str.c_str());
322 continue;
323 }
324 printf("%s = %#lx\n", name.c_str(), (unsigned long)v);
325 map[name] = v;
326 continue;
327 }
328 if(!soc_desc_evaluate_formula(formula, map, result, error))
329 printf("error: %s\n", error.c_str());
330 else
331 printf("result: %lu (%#lx)\n", (unsigned long)result, (unsigned long)result);
332 }
333 return 0;
78} 334}
79 335
80void usage() 336void usage()
81{ 337{
82 printf("usage: tester <desc file>\n"); 338 printf("usage: tester <mode> [options]\n");
339 printf("modes:\n");
340 printf(" compare <desc file> <desc file>\n");
341 printf(" write <read file> <write file>\n");
342 printf(" check <files...>\n");
343 printf(" eval [<formula>|--var <name>=<val>]...\n");
83 exit(1); 344 exit(1);
84} 345}
85 346
86int main(int argc, char **argv) 347int main(int argc, char **argv)
87{ 348{
88 if(argc != 2) 349 if(argc < 2)
350 usage();
351 std::string mode = argv[1];
352 if(mode == "compare")
353 return do_compare(argc - 2, argv + 2);
354 else if(mode == "write")
355 return do_write(argc - 2, argv + 2);
356 else if(mode == "check")
357 return do_check(argc - 2, argv + 2);
358 else if(mode == "eval")
359 return do_eval(argc - 2, argv + 2);
360 else
89 usage(); 361 usage();
90 std::vector< soc_t > socs;
91 bool ret = soc_desc_parse_xml(argv[1], socs);
92 printf("parse result: %d\n", ret);
93 if(ret)
94 for(size_t i = 0; i < socs.size(); i++)
95 print_soc_desc(socs[i]);
96 return 0; 362 return 0;
97} \ No newline at end of file 363} \ No newline at end of file