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