diff options
Diffstat (limited to 'utils/regtools/tester.cpp')
-rw-r--r-- | utils/regtools/tester.cpp | 344 |
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 | ||
25 | void print_value_desc(const soc_reg_field_value_t& value) | 27 | template< typename T > |
28 | bool 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 | ||
30 | void print_field_desc(const soc_reg_field_t& field) | 43 | template< typename T > |
44 | bool 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 | ||
38 | std::string compute_sct(soc_reg_flags_t f) | 71 | bool 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 | ||
44 | void print_reg_addr_desc(const soc_reg_addr_t& reg) | 89 | bool 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 | ||
49 | void print_reg_desc(const soc_reg_t& reg) | 114 | bool 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 | ||
59 | void print_dev_addr_desc(const soc_dev_addr_t& dev) | 127 | bool 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 | ||
64 | void print_dev_desc(const soc_dev_t& dev) | 171 | bool 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 | ||
73 | void print_soc_desc(const soc_t& soc) | 184 | bool 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 | |||
221 | bool 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 | |||
242 | int 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 | |||
256 | int 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 | |||
268 | int 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 | |||
295 | int 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 | ||
80 | void usage() | 336 | void 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 | ||
86 | int main(int argc, char **argv) | 347 | int 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 |