diff options
Diffstat (limited to 'utils/regtools/tester_v1.cpp')
-rw-r--r-- | utils/regtools/tester_v1.cpp | 365 |
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 | |||
27 | using namespace soc_desc_v1; | ||
28 | |||
29 | template< typename T > | ||
30 | bool 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 | |||
45 | template< typename T > | ||
46 | bool 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 | |||
73 | bool 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 | |||
91 | bool 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 | |||
116 | bool 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 | |||
129 | bool 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 | |||
173 | bool 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 | |||
186 | bool 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 | |||
223 | bool 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 | |||
244 | int 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 | |||
258 | int 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 | |||
270 | int 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 | |||
297 | int 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 | |||
338 | void 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 | |||
349 | int 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 | ||