summaryrefslogtreecommitdiff
path: root/utils/regtools/lib/soc_desc_v1.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'utils/regtools/lib/soc_desc_v1.cpp')
-rw-r--r--utils/regtools/lib/soc_desc_v1.cpp990
1 files changed, 990 insertions, 0 deletions
diff --git a/utils/regtools/lib/soc_desc_v1.cpp b/utils/regtools/lib/soc_desc_v1.cpp
new file mode 100644
index 0000000000..d585485493
--- /dev/null
+++ b/utils/regtools/lib/soc_desc_v1.cpp
@@ -0,0 +1,990 @@
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 <libxml/parser.h>
23#include <libxml/tree.h>
24#include <libxml/xmlsave.h>
25#include <libxml/xmlwriter.h>
26#include <stdio.h>
27#include <string.h>
28#include <algorithm>
29#include <cctype>
30
31namespace soc_desc_v1
32{
33
34#define XML_CHAR_TO_CHAR(s) ((const char *)(s))
35
36#define BEGIN_ATTR_MATCH(attr) \
37 for(xmlAttr *a = attr; a; a = a->next) {
38
39#define MATCH_X_ATTR(attr_name, hook, ...) \
40 if(strcmp(XML_CHAR_TO_CHAR(a->name), attr_name) == 0) { \
41 std::string s; \
42 if(!parse_text_attr(a, s) || !hook(s, __VA_ARGS__)) \
43 return false; \
44 }
45
46#define SOFT_MATCH_X_ATTR(attr_name, hook, ...) \
47 if(strcmp(XML_CHAR_TO_CHAR(a->name), attr_name) == 0) { \
48 std::string s; \
49 if(parse_text_attr(a, s)) \
50 hook(s, __VA_ARGS__); \
51 }
52
53#define SOFT_MATCH_SCT_ATTR(attr_name, var) \
54 SOFT_MATCH_X_ATTR(attr_name, validate_sct_hook, var)
55
56#define MATCH_TEXT_ATTR(attr_name, var) \
57 MATCH_X_ATTR(attr_name, validate_string_hook, var)
58
59#define MATCH_UINT32_ATTR(attr_name, var) \
60 MATCH_X_ATTR(attr_name, validate_uint32_hook, var)
61
62#define MATCH_BITRANGE_ATTR(attr_name, first, last) \
63 MATCH_X_ATTR(attr_name, validate_bitrange_hook, first, last)
64
65#define END_ATTR_MATCH() \
66 }
67
68#define BEGIN_NODE_MATCH(node) \
69 for(xmlNode *sub = node; sub; sub = sub->next) {
70
71#define MATCH_ELEM_NODE(node_name, array, parse_fn) \
72 if(sub->type == XML_ELEMENT_NODE && strcmp(XML_CHAR_TO_CHAR(sub->name), node_name) == 0) { \
73 array.resize(array.size() + 1); \
74 if(!parse_fn(sub, array.back())) \
75 return false; \
76 }
77
78#define SOFT_MATCH_ELEM_NODE(node_name, array, parse_fn) \
79 if(sub->type == XML_ELEMENT_NODE && strcmp(XML_CHAR_TO_CHAR(sub->name), node_name) == 0) { \
80 array.resize(array.size() + 1); \
81 if(!parse_fn(sub, array.back())) \
82 array.pop_back(); \
83 }
84
85#define END_NODE_MATCH() \
86 }
87
88namespace
89{
90
91bool validate_string_hook(const std::string& str, std::string& s)
92{
93 s = str;
94 return true;
95}
96
97bool validate_sct_hook(const std::string& str, soc_reg_flags_t& flags)
98{
99 if(str == "yes") flags |= REG_HAS_SCT;
100 else if(str != "no") return false;
101 return true;
102}
103
104bool validate_unsigned_long_hook(const std::string& str, unsigned long& s)
105{
106 char *end;
107 s = strtoul(str.c_str(), &end, 0);
108 return *end == 0;
109}
110
111bool validate_uint32_hook(const std::string& str, uint32_t& s)
112{
113 unsigned long u;
114 if(!validate_unsigned_long_hook(str, u)) return false;
115#if ULONG_MAX > 0xffffffff
116 if(u > 0xffffffff) return false;
117#endif
118 s = u;
119 return true;
120}
121
122bool validate_bitrange_hook(const std::string& str, unsigned& first, unsigned& last)
123{
124 unsigned long a, b;
125 size_t sep = str.find(':');
126 if(sep == std::string::npos) return false;
127 if(!validate_unsigned_long_hook(str.substr(0, sep), a)) return false;
128 if(!validate_unsigned_long_hook(str.substr(sep + 1), b)) return false;
129 if(a > 31 || b > 31 || a < b) return false;
130 first = b;
131 last = a;
132 return true;
133}
134
135bool parse_text_attr(xmlAttr *attr, std::string& s)
136{
137 if(attr->children != attr->last)
138 return false;
139 if(attr->children->type != XML_TEXT_NODE)
140 return false;
141 s = XML_CHAR_TO_CHAR(attr->children->content);
142 return true;
143}
144
145bool parse_value_elem(xmlNode *node, soc_reg_field_value_t& value)
146{
147 BEGIN_ATTR_MATCH(node->properties)
148 MATCH_TEXT_ATTR("name", value.name)
149 MATCH_UINT32_ATTR("value", value.value)
150 MATCH_TEXT_ATTR("desc", value.desc)
151 END_ATTR_MATCH()
152
153 return true;
154}
155
156bool parse_field_elem(xmlNode *node, soc_reg_field_t& field)
157{
158 BEGIN_ATTR_MATCH(node->properties)
159 MATCH_TEXT_ATTR("name", field.name)
160 MATCH_BITRANGE_ATTR("bitrange", field.first_bit, field.last_bit)
161 MATCH_TEXT_ATTR("desc", field.desc)
162 END_ATTR_MATCH()
163
164 BEGIN_NODE_MATCH(node->children)
165 SOFT_MATCH_ELEM_NODE("value", field.value, parse_value_elem)
166 END_NODE_MATCH()
167
168 return true;
169}
170
171bool parse_reg_addr_elem(xmlNode *node, soc_reg_addr_t& addr)
172{
173 BEGIN_ATTR_MATCH(node->properties)
174 MATCH_TEXT_ATTR("name", addr.name)
175 MATCH_UINT32_ATTR("addr", addr.addr)
176 END_ATTR_MATCH()
177
178 return true;
179}
180
181bool parse_reg_formula_elem(xmlNode *node, soc_reg_formula_t& formula)
182{
183 BEGIN_ATTR_MATCH(node->properties)
184 MATCH_TEXT_ATTR("string", formula.string)
185 END_ATTR_MATCH()
186
187 formula.type = REG_FORMULA_STRING;
188
189 return true;
190}
191
192bool parse_add_trivial_addr(const std::string& str, soc_reg_t& reg)
193{
194 soc_reg_addr_t a;
195 a.name = reg.name;
196 if(!validate_uint32_hook(str, a.addr))
197 return false;
198 reg.addr.push_back(a);
199 return true;
200}
201
202bool parse_reg_elem(xmlNode *node, soc_reg_t& reg)
203{
204 std::list< soc_reg_formula_t > formulas;
205 BEGIN_ATTR_MATCH(node->properties)
206 MATCH_TEXT_ATTR("name", reg.name)
207 SOFT_MATCH_SCT_ATTR("sct", reg.flags)
208 SOFT_MATCH_X_ATTR("addr", parse_add_trivial_addr, reg)
209 MATCH_TEXT_ATTR("desc", reg.desc)
210 END_ATTR_MATCH()
211
212 BEGIN_NODE_MATCH(node->children)
213 MATCH_ELEM_NODE("addr", reg.addr, parse_reg_addr_elem)
214 MATCH_ELEM_NODE("formula", formulas, parse_reg_formula_elem)
215 MATCH_ELEM_NODE("field", reg.field, parse_field_elem)
216 END_NODE_MATCH()
217
218 if(formulas.size() > 1)
219 {
220 fprintf(stderr, "Only one formula is allowed per register\n");
221 return false;
222 }
223 if(formulas.size() == 1)
224 reg.formula = formulas.front();
225
226 return true;
227}
228
229bool parse_dev_addr_elem(xmlNode *node, soc_dev_addr_t& addr)
230{
231 BEGIN_ATTR_MATCH(node->properties)
232 MATCH_TEXT_ATTR("name", addr.name)
233 MATCH_UINT32_ATTR("addr", addr.addr)
234 END_ATTR_MATCH()
235
236 return true;
237}
238
239bool parse_dev_elem(xmlNode *node, soc_dev_t& dev)
240{
241 BEGIN_ATTR_MATCH(node->properties)
242 MATCH_TEXT_ATTR("name", dev.name)
243 MATCH_TEXT_ATTR("long_name", dev.long_name)
244 MATCH_TEXT_ATTR("desc", dev.desc)
245 MATCH_TEXT_ATTR("version", dev.version)
246 END_ATTR_MATCH()
247
248 BEGIN_NODE_MATCH(node->children)
249 MATCH_ELEM_NODE("addr", dev.addr, parse_dev_addr_elem)
250 MATCH_ELEM_NODE("reg", dev.reg, parse_reg_elem)
251 END_NODE_MATCH()
252
253 return true;
254}
255
256bool parse_soc_elem(xmlNode *node, soc_t& soc)
257{
258 BEGIN_ATTR_MATCH(node->properties)
259 MATCH_TEXT_ATTR("name", soc.name)
260 MATCH_TEXT_ATTR("desc", soc.desc)
261 END_ATTR_MATCH()
262
263 BEGIN_NODE_MATCH(node->children)
264 MATCH_ELEM_NODE("dev", soc.dev, parse_dev_elem)
265 END_NODE_MATCH()
266
267 return true;
268}
269
270bool parse_root_elem(xmlNode *node, soc_t& soc)
271{
272 std::vector< soc_t > socs;
273 BEGIN_NODE_MATCH(node)
274 MATCH_ELEM_NODE("soc", socs, parse_soc_elem)
275 END_NODE_MATCH()
276 if(socs.size() != 1)
277 {
278 fprintf(stderr, "A description file must contain exactly one soc element\n");
279 return false;
280 }
281 soc = socs[0];
282 return true;
283}
284
285}
286
287bool parse_xml(const std::string& filename, soc_t& socs)
288{
289 LIBXML_TEST_VERSION
290
291 xmlDocPtr doc = xmlReadFile(filename.c_str(), NULL, 0);
292 if(doc == NULL)
293 return false;
294
295 xmlNodePtr root_element = xmlDocGetRootElement(doc);
296 bool ret = parse_root_elem(root_element, socs);
297
298 xmlFreeDoc(doc);
299
300 return ret;
301}
302
303namespace
304{
305
306int produce_field(xmlTextWriterPtr writer, const soc_reg_field_t& field)
307{
308#define SAFE(x) if((x) < 0) return -1;
309 /* <field> */
310 SAFE(xmlTextWriterStartElement(writer, BAD_CAST "field"));
311 /* name */
312 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "name", BAD_CAST field.name.c_str()));
313 /* desc */
314 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "desc", BAD_CAST field.desc.c_str()));
315 /* bitrange */
316 SAFE(xmlTextWriterWriteFormatAttribute(writer, BAD_CAST "bitrange", "%d:%d",
317 field.last_bit, field.first_bit));
318 /* values */
319 for(size_t i = 0; i < field.value.size(); i++)
320 {
321 /* <value> */
322 SAFE(xmlTextWriterStartElement(writer, BAD_CAST "value"));
323 /* name */
324 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "name", BAD_CAST field.value[i].name.c_str()));
325 /* value */
326 SAFE(xmlTextWriterWriteFormatAttribute(writer, BAD_CAST "value", "0x%x", field.value[i].value));
327 /* name */
328 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "desc", BAD_CAST field.value[i].desc.c_str()));
329 /* </value> */
330 SAFE(xmlTextWriterEndElement(writer));
331 }
332 /* </field> */
333 SAFE(xmlTextWriterEndElement(writer));
334#undef SAFE
335 return 0;
336}
337
338int produce_reg(xmlTextWriterPtr writer, const soc_reg_t& reg)
339{
340#define SAFE(x) if((x) < 0) return -1;
341 /* <reg> */
342 SAFE(xmlTextWriterStartElement(writer, BAD_CAST "reg"));
343 /* name */
344 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "name", BAD_CAST reg.name.c_str()));
345 /* name */
346 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "desc", BAD_CAST reg.desc.c_str()));
347 /* flags */
348 if(reg.flags & REG_HAS_SCT)
349 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "sct", BAD_CAST "yes"));
350 /* formula */
351 if(reg.formula.type != REG_FORMULA_NONE)
352 {
353 /* <formula> */
354 SAFE(xmlTextWriterStartElement(writer, BAD_CAST "formula"));
355 switch(reg.formula.type)
356 {
357 case REG_FORMULA_STRING:
358 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "string",
359 BAD_CAST reg.formula.string.c_str()));
360 break;
361 default:
362 break;
363 }
364 /* </formula> */
365 SAFE(xmlTextWriterEndElement(writer));
366 }
367 /* addresses */
368 for(size_t i = 0; i < reg.addr.size(); i++)
369 {
370 /* <addr> */
371 SAFE(xmlTextWriterStartElement(writer, BAD_CAST "addr"));
372 /* name */
373 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "name", BAD_CAST reg.addr[i].name.c_str()));
374 /* addr */
375 SAFE(xmlTextWriterWriteFormatAttribute(writer, BAD_CAST "addr", "0x%x", reg.addr[i].addr));
376 /* </addr> */
377 SAFE(xmlTextWriterEndElement(writer));
378 }
379 /* fields */
380 for(size_t i = 0; i < reg.field.size(); i++)
381 produce_field(writer, reg.field[i]);
382 /* </reg> */
383 SAFE(xmlTextWriterEndElement(writer));
384#undef SAFE
385 return 0;
386}
387
388int produce_dev(xmlTextWriterPtr writer, const soc_dev_t& dev)
389{
390#define SAFE(x) if((x) < 0) return -1;
391 /* <dev> */
392 SAFE(xmlTextWriterStartElement(writer, BAD_CAST "dev"));
393 /* name */
394 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "name", BAD_CAST dev.name.c_str()));
395 /* long_name */
396 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "long_name", BAD_CAST dev.long_name.c_str()));
397 /* desc */
398 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "desc", BAD_CAST dev.desc.c_str()));
399 /* version */
400 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "version", BAD_CAST dev.version.c_str()));
401 /* addresses */
402 for(size_t i = 0; i < dev.addr.size(); i++)
403 {
404 /* <addr> */
405 SAFE(xmlTextWriterStartElement(writer, BAD_CAST "addr"));
406 /* name */
407 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "name", BAD_CAST dev.addr[i].name.c_str()));
408 /* addr */
409 SAFE(xmlTextWriterWriteFormatAttribute(writer, BAD_CAST "addr", "0x%x", dev.addr[i].addr));
410 /* </addr> */
411 SAFE(xmlTextWriterEndElement(writer));
412 }
413 /* registers */
414 for(size_t i = 0; i < dev.reg.size(); i++)
415 produce_reg(writer, dev.reg[i]);
416 /* </dev> */
417 SAFE(xmlTextWriterEndElement(writer));
418#undef SAFE
419 return 0;
420}
421
422}
423
424bool produce_xml(const std::string& filename, const soc_t& soc)
425{
426 LIBXML_TEST_VERSION
427
428 xmlTextWriterPtr writer = xmlNewTextWriterFilename(filename.c_str(), 0);
429 if(writer == NULL)
430 return false;
431#define SAFE(x) if((x) < 0) goto Lerr
432 SAFE(xmlTextWriterSetIndent(writer, 1));
433 SAFE(xmlTextWriterSetIndentString(writer, BAD_CAST " "));
434 /* <xml> */
435 SAFE(xmlTextWriterStartDocument(writer, NULL, NULL, NULL));
436 /* <soc> */
437 SAFE(xmlTextWriterStartElement(writer, BAD_CAST "soc"));
438 /* name */
439 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "name", BAD_CAST soc.name.c_str()));
440 /* desc */
441 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "desc", BAD_CAST soc.desc.c_str()));
442 /* devices */
443 for(size_t i = 0; i < soc.dev.size(); i++)
444 SAFE(produce_dev(writer, soc.dev[i]));
445 /* end <soc> */
446 SAFE(xmlTextWriterEndElement(writer));
447 /* </xml> */
448 SAFE(xmlTextWriterEndDocument(writer));
449 xmlFreeTextWriter(writer);
450 return true;
451#undef SAFE
452Lerr:
453 xmlFreeTextWriter(writer);
454 return false;
455}
456
457namespace
458{
459
460struct soc_sorter
461{
462 bool operator()(const soc_dev_t& a, const soc_dev_t& b) const
463 {
464 return a.name < b.name;
465 }
466
467 bool operator()(const soc_dev_addr_t& a, const soc_dev_addr_t& b) const
468 {
469 return a.name < b.name;
470 }
471
472 bool operator()(const soc_reg_t& a, const soc_reg_t& b) const
473 {
474 soc_addr_t aa = a.addr.size() > 0 ? a.addr[0].addr : 0;
475 soc_addr_t ab = b.addr.size() > 0 ? b.addr[0].addr : 0;
476 return aa < ab;
477 }
478
479 bool operator()(const soc_reg_addr_t& a, const soc_reg_addr_t& b) const
480 {
481 return a.addr < b.addr;
482 }
483
484 bool operator()(const soc_reg_field_t& a, const soc_reg_field_t& b) const
485 {
486 return a.last_bit > b.last_bit;
487 }
488
489 bool operator()(const soc_reg_field_value_t a, const soc_reg_field_value_t& b) const
490 {
491 return a.value < b.value;
492 }
493};
494
495void normalize(soc_reg_field_t& field)
496{
497 std::sort(field.value.begin(), field.value.end(), soc_sorter());
498}
499
500void normalize(soc_reg_t& reg)
501{
502 std::sort(reg.addr.begin(), reg.addr.end(), soc_sorter());
503 std::sort(reg.field.begin(), reg.field.end(), soc_sorter());
504 for(size_t i = 0; i < reg.field.size(); i++)
505 normalize(reg.field[i]);
506}
507
508void normalize(soc_dev_t& dev)
509{
510 std::sort(dev.addr.begin(), dev.addr.end(), soc_sorter());
511 std::sort(dev.reg.begin(), dev.reg.end(), soc_sorter());
512 for(size_t i = 0; i < dev.reg.size(); i++)
513 normalize(dev.reg[i]);
514}
515
516}
517
518void normalize(soc_t& soc)
519{
520 std::sort(soc.dev.begin(), soc.dev.end(), soc_sorter());
521 for(size_t i = 0; i < soc.dev.size(); i++)
522 normalize(soc.dev[i]);
523}
524
525namespace
526{
527 soc_error_t make_error(soc_error_level_t lvl, std::string at, std::string what)
528 {
529 soc_error_t err;
530 err.level = lvl;
531 err.location = at;
532 err.message = what;
533 return err;
534 }
535
536 soc_error_t make_warning(std::string at, std::string what)
537 {
538 return make_error(SOC_ERROR_WARNING, at, what);
539 }
540
541 soc_error_t make_fatal(std::string at, std::string what)
542 {
543 return make_error(SOC_ERROR_FATAL, at, what);
544 }
545
546 soc_error_t prefix(soc_error_t err, const std::string& prefix_at)
547 {
548 err.location = prefix_at + "." + err.location;
549 return err;
550 }
551
552 void add_errors(std::vector< soc_error_t >& errors,
553 const std::vector< soc_error_t >& new_errors, const std::string& prefix_at)
554 {
555 for(size_t i = 0; i < new_errors.size(); i++)
556 errors.push_back(prefix(new_errors[i], prefix_at));
557 }
558
559 std::vector< soc_error_t > no_error()
560 {
561 std::vector< soc_error_t > s;
562 return s;
563 }
564
565 std::vector< soc_error_t > one_error(const soc_error_t& err)
566 {
567 std::vector< soc_error_t > s;
568 s.push_back(err);
569 return s;
570 }
571
572 bool name_valid(char c)
573 {
574 return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') ||
575 (c >= 'A' && c <= 'Z') || c == '_';
576 }
577
578 bool name_valid(const std::string& s)
579 {
580 for(size_t i = 0; i < s.size(); i++)
581 if(!name_valid(s[i]))
582 return false;
583 return true;
584 }
585}
586
587std::vector< soc_error_t > soc_reg_field_value_t::errors(bool recursive)
588{
589 (void) recursive;
590 if(name.size() == 0)
591 return one_error(make_fatal(name, "empty name"));
592 else if(!name_valid(name))
593 return one_error(make_fatal(name, "invalid name"));
594 else
595 return no_error();
596}
597
598std::vector< soc_error_t > soc_reg_field_t::errors(bool recursive)
599{
600 std::vector< soc_error_t > err;
601 std::string at(name);
602 if(name.size() == 0)
603 err.push_back(make_fatal(at, "empty name"));
604 else if(!name_valid(name))
605 err.push_back(make_fatal(at, "invalid name"));
606 if(last_bit > 31)
607 err.push_back(make_fatal(at, "last bit is greater than 31"));
608 if(first_bit > last_bit)
609 err.push_back(make_fatal(at, "last bit is greater than first bit"));
610 for(size_t i = 0; i < value.size(); i++)
611 {
612 for(size_t j = 0; j < value.size(); j++)
613 {
614 if(i == j)
615 continue;
616 if(value[i].name == value[j].name)
617 err.push_back(prefix(make_fatal(value[i].name,
618 "there are several values with the same name"), at));
619 if(value[i].value == value[j].value)
620 err.push_back(prefix(make_warning(value[i].name,
621 "there are several values with the same value"), at));
622 }
623 if(value[i].value > (bitmask() >> first_bit))
624 err.push_back(prefix(make_warning(at, "value doesn't fit into the field"), value[i].name));
625 if(recursive)
626 add_errors(err, value[i].errors(true), at);
627 }
628 return err;
629}
630
631std::vector< soc_error_t > soc_reg_addr_t::errors(bool recursive)
632{
633 (void) recursive;
634 if(name.size() == 0)
635 return one_error(make_fatal("", "empty name"));
636 else if(!name_valid(name))
637 return one_error(make_fatal(name, "invalid name"));
638 else
639 return no_error();
640}
641
642std::vector< soc_error_t > soc_reg_formula_t::errors(bool recursive)
643{
644 (void) recursive;
645 if(type == REG_FORMULA_STRING && string.size() == 0)
646 return one_error(make_fatal("", "empty string formula"));
647 else
648 return no_error();
649}
650
651namespace
652{
653
654bool field_overlap(const soc_reg_field_t& a, const soc_reg_field_t& b)
655{
656 return !(a.first_bit > b.last_bit || b.first_bit > a.last_bit);
657}
658
659}
660
661std::vector< soc_error_t > soc_reg_t::errors(bool recursive)
662{
663 std::vector< soc_error_t > err;
664 std::string at(name);
665 if(name.size() == 0)
666 err.push_back(make_fatal(at, "empty name"));
667 else if(!name_valid(name))
668 err.push_back(make_fatal(at, "invalid name"));
669 for(size_t i = 0; i < addr.size(); i++)
670 {
671 for(size_t j = 0; j < addr.size(); j++)
672 {
673 if(i == j)
674 continue;
675 if(addr[i].name == addr[j].name)
676 err.push_back(prefix(make_fatal(addr[i].name,
677 "there are several instances with the same name"), at));
678 if(addr[i].addr == addr[j].addr)
679 err.push_back(prefix(make_fatal(addr[i].name,
680 "there are several instances with the same address"), at));
681 }
682 if(recursive)
683 add_errors(err, addr[i].errors(true), at);
684 }
685 if(recursive)
686 add_errors(err, formula.errors(true), at);
687 for(size_t i = 0; i < field.size(); i++)
688 {
689 for(size_t j = 0; j < field.size(); j++)
690 {
691 if(i == j)
692 continue;
693 if(field[i].name == field[j].name)
694 err.push_back(prefix(make_fatal(field[i].name,
695 "there are several fields with the same name"), at));
696 if(field_overlap(field[i], field[j]))
697 err.push_back(prefix(make_fatal(field[i].name,
698 "there are overlapping fields"), at));
699 }
700 if(recursive)
701 add_errors(err, field[i].errors(true), at);
702 }
703 return err;
704}
705
706std::vector< soc_error_t > soc_dev_addr_t::errors(bool recursive)
707{
708 (void) recursive;
709 if(name.size() == 0)
710 return one_error(make_fatal("", "empty name"));
711 else if(!name_valid(name))
712 return one_error(make_fatal(name, "invalid name"));
713 else
714 return no_error();
715}
716
717std::vector< soc_error_t > soc_dev_t::errors(bool recursive)
718{
719 std::vector< soc_error_t > err;
720 std::string at(name);
721 if(name.size() == 0)
722 err.push_back(make_fatal(at, "empty name"));
723 else if(!name_valid(name))
724 err.push_back(make_fatal(at, "invalid name"));
725 for(size_t i = 0; i < addr.size(); i++)
726 {
727 for(size_t j = 0; j < addr.size(); j++)
728 {
729 if(i == j)
730 continue;
731 if(addr[i].name == addr[j].name)
732 err.push_back(prefix(make_fatal(addr[i].name,
733 "there are several instances with the same name"), at));
734 if(addr[i].addr == addr[j].addr)
735 err.push_back(prefix(make_fatal(addr[i].name,
736 "there are several instances with the same address"), at));
737 }
738 if(recursive)
739 add_errors(err, addr[i].errors(true), at);
740 }
741 for(size_t i = 0; i < reg.size(); i++)
742 {
743 for(size_t j = 0; j < reg.size(); j++)
744 {
745 if(i == j)
746 continue;
747 if(reg[i].name == reg[j].name)
748 err.push_back(prefix(make_fatal(reg[i].name,
749 "there are several registers with the same name"), at));
750 }
751 if(recursive)
752 add_errors(err, reg[i].errors(true), at);
753 }
754 return err;
755}
756
757std::vector< soc_error_t > soc_t::errors(bool recursive)
758{
759 std::vector< soc_error_t > err;
760 std::string at(name);
761 for(size_t i = 0; i < dev.size(); i++)
762 {
763 for(size_t j = 0; j < dev.size(); j++)
764 {
765 if(i == j)
766 continue;
767 if(dev[i].name == dev[j].name)
768 err.push_back(prefix(make_fatal(dev[i].name,
769 "there are several devices with the same name"), at));
770 }
771 if(recursive)
772 add_errors(err, dev[i].errors(true), at);
773 }
774 return err;
775}
776
777namespace
778{
779
780struct formula_evaluator
781{
782 std::string formula;
783 size_t pos;
784 std::string error;
785
786 bool err(const char *fmt, ...)
787 {
788 char buffer[256];
789 va_list args;
790 va_start(args, fmt);
791 vsnprintf(buffer,sizeof(buffer), fmt, args);
792 va_end(args);
793 error = buffer;
794 return false;
795 }
796
797 formula_evaluator(const std::string& s):pos(0)
798 {
799 for(size_t i = 0; i < s.size(); i++)
800 if(!isspace(s[i]))
801 formula.push_back(s[i]);
802 }
803
804 void adv()
805 {
806 pos++;
807 }
808
809 char cur()
810 {
811 return end() ? 0 : formula[pos];
812 }
813
814 bool end()
815 {
816 return pos >= formula.size();
817 }
818
819 bool parse_digit(char c, int basis, soc_word_t& res)
820 {
821 c = tolower(c);
822 if(isdigit(c))
823 {
824 res = c - '0';
825 return true;
826 }
827 if(basis == 16 && isxdigit(c))
828 {
829 res = c + 10 - 'a';
830 return true;
831 }
832 return err("invalid digit '%c'", c);
833 }
834
835 bool parse_signed(soc_word_t& res)
836 {
837 char op = cur();
838 if(op == '+' || op == '-')
839 {
840 adv();
841 if(!parse_signed(res))
842 return false;
843 if(op == '-')
844 res *= -1;
845 return true;
846 }
847 else if(op == '(')
848 {
849 adv();
850 if(!parse_expression(res))
851 return false;
852 if(cur() != ')')
853 return err("expected ')', got '%c'", cur());
854 adv();
855 return true;
856 }
857 else if(isdigit(op))
858 {
859 res = op - '0';
860 adv();
861 int basis = 10;
862 if(op == '0' && cur() == 'x')
863 {
864 basis = 16;
865 adv();
866 }
867 soc_word_t digit = 0;
868 while(parse_digit(cur(), basis, digit))
869 {
870 res = res * basis + digit;
871 adv();
872 }
873 return true;
874 }
875 else if(isalpha(op) || op == '_')
876 {
877 std::string name;
878 while(isalnum(cur()) || cur() == '_')
879 {
880 name.push_back(cur());
881 adv();
882 }
883 return get_variable(name, res);
884 }
885 else
886 return err("express signed expression, got '%c'", op);
887 }
888
889 bool parse_term(soc_word_t& res)
890 {
891 if(!parse_signed(res))
892 return false;
893 while(cur() == '*' || cur() == '/' || cur() == '%')
894 {
895 char op = cur();
896 adv();
897 soc_word_t tmp;
898 if(!parse_signed(tmp))
899 return false;
900 if(op == '*')
901 res *= tmp;
902 else if(tmp != 0)
903 res = op == '/' ? res / tmp : res % tmp;
904 else
905 return err("division by 0");
906 }
907 return true;
908 }
909
910 bool parse_expression(soc_word_t& res)
911 {
912 if(!parse_term(res))
913 return false;
914 while(!end() && (cur() == '+' || cur() == '-'))
915 {
916 char op = cur();
917 adv();
918 soc_word_t tmp;
919 if(!parse_term(tmp))
920 return false;
921 if(op == '+')
922 res += tmp;
923 else
924 res -= tmp;
925 }
926 return true;
927 }
928
929 bool parse(soc_word_t& res, std::string& _error)
930 {
931 bool ok = parse_expression(res);
932 if(ok && !end())
933 err("unexpected character '%c'", cur());
934 _error = error;
935 return ok && end();
936 }
937
938 virtual bool get_variable(std::string name, soc_word_t& res)
939 {
940 return err("unknown variable '%s'", name.c_str());
941 }
942};
943
944struct my_evaluator : public formula_evaluator
945{
946 const std::map< std::string, soc_word_t>& var;
947
948 my_evaluator(const std::string& formula, const std::map< std::string, soc_word_t>& _var)
949 :formula_evaluator(formula), var(_var) {}
950
951 virtual bool get_variable(std::string name, soc_word_t& res)
952 {
953 std::map< std::string, soc_word_t>::const_iterator it = var.find(name);
954 if(it == var.end())
955 return formula_evaluator::get_variable(name, res);
956 else
957 {
958 res = it->second;
959 return true;
960 }
961 }
962};
963
964}
965
966bool evaluate_formula(const std::string& formula,
967 const std::map< std::string, soc_word_t>& var, soc_word_t& result, std::string& error)
968{
969 my_evaluator e(formula, var);
970 return e.parse(result, error);
971}
972
973/** WARNING we need to call xmlInitParser() to init libxml2 but it needs to
974 * called from the main thread, which is a super strong requirement, so do it
975 * using a static constructor */
976namespace
977{
978class xml_parser_init
979{
980public:
981 xml_parser_init()
982 {
983 xmlInitParser();
984 }
985};
986
987xml_parser_init __xml_parser_init;
988}
989
990} // soc_desc_v1