summaryrefslogtreecommitdiff
path: root/utils/regtools/lib
diff options
context:
space:
mode:
authorAmaury Pouly <amaury.pouly@gmail.com>2014-04-07 11:28:04 +0200
committerAmaury Pouly <amaury.pouly@gmail.com>2014-05-01 19:34:18 +0200
commit4356666101e0e7985e65a19f86bc4a74519e93f9 (patch)
treebf8de8057d93d0fab0a30cae92a90f5a4edc79dc /utils/regtools/lib
parent3754624edc48539c5cc5acbf426ce909477e87d8 (diff)
downloadrockbox-4356666101e0e7985e65a19f86bc4a74519e93f9.tar.gz
rockbox-4356666101e0e7985e65a19f86bc4a74519e93f9.zip
regtools: completely rework qeditor, improve soc desc library and tools
The graphical editor can now display and editor description files. The library has been improved to provide more useful function. The XML format has been slightly changed: only one soc is allowed per file (this is was already de facto the case since <soc> was the root tag). Also introduce a DTD to validate the files. Change-Id: If70ba35b6dc0242bdb87411cf4baee9597798aac
Diffstat (limited to 'utils/regtools/lib')
-rw-r--r--utils/regtools/lib/soc_desc.cpp700
-rw-r--r--utils/regtools/lib/soc_desc.hpp49
2 files changed, 739 insertions, 10 deletions
diff --git a/utils/regtools/lib/soc_desc.cpp b/utils/regtools/lib/soc_desc.cpp
index 6a6d47648f..1c9eaf7972 100644
--- a/utils/regtools/lib/soc_desc.cpp
+++ b/utils/regtools/lib/soc_desc.cpp
@@ -21,8 +21,12 @@
21#include "soc_desc.hpp" 21#include "soc_desc.hpp"
22#include <libxml/parser.h> 22#include <libxml/parser.h>
23#include <libxml/tree.h> 23#include <libxml/tree.h>
24#include <libxml/xmlsave.h>
25#include <libxml/xmlwriter.h>
24#include <stdio.h> 26#include <stdio.h>
25#include <string.h> 27#include <string.h>
28#include <algorithm>
29#include <cctype>
26 30
27#define XML_CHAR_TO_CHAR(s) ((const char *)(s)) 31#define XML_CHAR_TO_CHAR(s) ((const char *)(s))
28 32
@@ -78,6 +82,9 @@
78#define END_NODE_MATCH() \ 82#define END_NODE_MATCH() \
79 } 83 }
80 84
85namespace
86{
87
81bool validate_string_hook(const std::string& str, std::string& s) 88bool validate_string_hook(const std::string& str, std::string& s)
82{ 89{
83 s = str; 90 s = str;
@@ -137,6 +144,7 @@ bool parse_value_elem(xmlNode *node, soc_reg_field_value_t& value)
137 BEGIN_ATTR_MATCH(node->properties) 144 BEGIN_ATTR_MATCH(node->properties)
138 MATCH_TEXT_ATTR("name", value.name) 145 MATCH_TEXT_ATTR("name", value.name)
139 MATCH_UINT32_ATTR("value", value.value) 146 MATCH_UINT32_ATTR("value", value.value)
147 MATCH_TEXT_ATTR("desc", value.desc)
140 END_ATTR_MATCH() 148 END_ATTR_MATCH()
141 149
142 return true; 150 return true;
@@ -256,28 +264,706 @@ bool parse_soc_elem(xmlNode *node, soc_t& soc)
256 return true; 264 return true;
257} 265}
258 266
259bool parse_root_elem(xmlNode *node, std::vector< soc_t >& soc) 267bool parse_root_elem(xmlNode *node, soc_t& soc)
260{ 268{
269 std::vector< soc_t > socs;
261 BEGIN_NODE_MATCH(node) 270 BEGIN_NODE_MATCH(node)
262 MATCH_ELEM_NODE("soc", soc, parse_soc_elem) 271 MATCH_ELEM_NODE("soc", socs, parse_soc_elem)
263 END_NODE_MATCH() 272 END_NODE_MATCH()
273 if(socs.size() != 1)
274 {
275 fprintf(stderr, "A description file must contain exactly one soc element\n");
276 return false;
277 }
278 soc = socs[0];
264 return true; 279 return true;
265} 280}
266 281
267bool soc_desc_parse_xml(const std::string& filename, std::vector< soc_t >& socs) 282}
283
284bool soc_desc_parse_xml(const std::string& filename, soc_t& socs)
268{ 285{
269 LIBXML_TEST_VERSION 286 LIBXML_TEST_VERSION
270 287
271 xmlDoc *doc = xmlReadFile(filename.c_str(), NULL, 0); 288 xmlDocPtr doc = xmlReadFile(filename.c_str(), NULL, 0);
272 if(doc == NULL) 289 if(doc == NULL)
273 return false; 290 return false;
274 291
275 xmlNode *root_element = xmlDocGetRootElement(doc); 292 xmlNodePtr root_element = xmlDocGetRootElement(doc);
276
277 bool ret = parse_root_elem(root_element, socs); 293 bool ret = parse_root_elem(root_element, socs);
278 294
279 xmlFreeDoc(doc); 295 xmlFreeDoc(doc);
280 xmlCleanupParser(); 296 xmlCleanupParser();
281 297
282 return ret; 298 return ret;
283} \ No newline at end of file 299}
300
301namespace
302{
303
304int produce_field(xmlTextWriterPtr writer, const soc_reg_field_t& field)
305{
306#define SAFE(x) if((x) < 0) return -1;
307 /* <field> */
308 SAFE(xmlTextWriterStartElement(writer, BAD_CAST "field"));
309 /* name */
310 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "name", BAD_CAST field.name.c_str()));
311 /* desc */
312 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "desc", BAD_CAST field.desc.c_str()));
313 /* bitrange */
314 SAFE(xmlTextWriterWriteFormatAttribute(writer, BAD_CAST "bitrange", "%d:%d",
315 field.last_bit, field.first_bit));
316 /* values */
317 for(size_t i = 0; i < field.value.size(); i++)
318 {
319 /* <value> */
320 SAFE(xmlTextWriterStartElement(writer, BAD_CAST "value"));
321 /* name */
322 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "name", BAD_CAST field.value[i].name.c_str()));
323 /* value */
324 SAFE(xmlTextWriterWriteFormatAttribute(writer, BAD_CAST "value", "0x%x", field.value[i].value));
325 /* name */
326 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "desc", BAD_CAST field.value[i].desc.c_str()));
327 /* </value> */
328 SAFE(xmlTextWriterEndElement(writer));
329 }
330 /* </field> */
331 SAFE(xmlTextWriterEndElement(writer));
332#undef SAFE
333 return 0;
334}
335
336int produce_reg(xmlTextWriterPtr writer, const soc_reg_t& reg)
337{
338#define SAFE(x) if((x) < 0) return -1;
339 /* <reg> */
340 SAFE(xmlTextWriterStartElement(writer, BAD_CAST "reg"));
341 /* name */
342 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "name", BAD_CAST reg.name.c_str()));
343 /* name */
344 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "desc", BAD_CAST reg.desc.c_str()));
345 /* flags */
346 if(reg.flags & REG_HAS_SCT)
347 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "sct", BAD_CAST "yes"));
348 /* formula */
349 if(reg.formula.type != REG_FORMULA_NONE)
350 {
351 /* <formula> */
352 SAFE(xmlTextWriterStartElement(writer, BAD_CAST "formula"));
353 switch(reg.formula.type)
354 {
355 case REG_FORMULA_STRING:
356 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "string",
357 BAD_CAST reg.formula.string.c_str()));
358 break;
359 default:
360 break;
361 }
362 /* </formula> */
363 SAFE(xmlTextWriterEndElement(writer));
364 }
365 /* addresses */
366 for(size_t i = 0; i < reg.addr.size(); i++)
367 {
368 /* <addr> */
369 SAFE(xmlTextWriterStartElement(writer, BAD_CAST "addr"));
370 /* name */
371 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "name", BAD_CAST reg.addr[i].name.c_str()));
372 /* addr */
373 SAFE(xmlTextWriterWriteFormatAttribute(writer, BAD_CAST "addr", "0x%x", reg.addr[i].addr));
374 /* </addr> */
375 SAFE(xmlTextWriterEndElement(writer));
376 }
377 /* fields */
378 for(size_t i = 0; i < reg.field.size(); i++)
379 produce_field(writer, reg.field[i]);
380 /* </reg> */
381 SAFE(xmlTextWriterEndElement(writer));
382#undef SAFE
383 return 0;
384}
385
386int produce_dev(xmlTextWriterPtr writer, const soc_dev_t& dev)
387{
388#define SAFE(x) if((x) < 0) return -1;
389 /* <dev> */
390 SAFE(xmlTextWriterStartElement(writer, BAD_CAST "dev"));
391 /* name */
392 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "name", BAD_CAST dev.name.c_str()));
393 /* long_name */
394 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "long_name", BAD_CAST dev.long_name.c_str()));
395 /* desc */
396 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "desc", BAD_CAST dev.desc.c_str()));
397 /* version */
398 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "version", BAD_CAST dev.version.c_str()));
399 /* addresses */
400 for(size_t i = 0; i < dev.addr.size(); i++)
401 {
402 /* <addr> */
403 SAFE(xmlTextWriterStartElement(writer, BAD_CAST "addr"));
404 /* name */
405 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "name", BAD_CAST dev.addr[i].name.c_str()));
406 /* addr */
407 SAFE(xmlTextWriterWriteFormatAttribute(writer, BAD_CAST "addr", "0x%x", dev.addr[i].addr));
408 /* </addr> */
409 SAFE(xmlTextWriterEndElement(writer));
410 }
411 /* registers */
412 for(size_t i = 0; i < dev.reg.size(); i++)
413 produce_reg(writer, dev.reg[i]);
414 /* </dev> */
415 SAFE(xmlTextWriterEndElement(writer));
416#undef SAFE
417 return 0;
418}
419
420}
421
422bool soc_desc_produce_xml(const std::string& filename, const soc_t& soc)
423{
424 LIBXML_TEST_VERSION
425
426 xmlTextWriterPtr writer = xmlNewTextWriterFilename(filename.c_str(), 0);
427 if(writer == NULL)
428 return false;
429#define SAFE(x) if((x) < 0) goto Lerr
430 SAFE(xmlTextWriterSetIndent(writer, 1));
431 SAFE(xmlTextWriterSetIndentString(writer, BAD_CAST " "));
432 /* <xml> */
433 SAFE(xmlTextWriterStartDocument(writer, NULL, NULL, NULL));
434 /* <soc> */
435 SAFE(xmlTextWriterStartElement(writer, BAD_CAST "soc"));
436 /* name */
437 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "name", BAD_CAST soc.name.c_str()));
438 /* desc */
439 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "desc", BAD_CAST soc.desc.c_str()));
440 /* devices */
441 for(size_t i = 0; i < soc.dev.size(); i++)
442 SAFE(produce_dev(writer, soc.dev[i]));
443 /* end <soc> */
444 SAFE(xmlTextWriterEndElement(writer));
445 /* </xml> */
446 SAFE(xmlTextWriterEndDocument(writer));
447 xmlFreeTextWriter(writer);
448 return true;
449#undef SAFE
450Lerr:
451 xmlFreeTextWriter(writer);
452 return false;
453}
454
455namespace
456{
457
458struct soc_sorter
459{
460 bool operator()(const soc_dev_t& a, const soc_dev_t& b) const
461 {
462 return a.name < b.name;
463 }
464
465 bool operator()(const soc_dev_addr_t& a, const soc_dev_addr_t& b) const
466 {
467 return a.name < b.name;
468 }
469
470 bool operator()(const soc_reg_t& a, const soc_reg_t& b) const
471 {
472 soc_addr_t aa = a.addr.size() > 0 ? a.addr[0].addr : 0;
473 soc_addr_t ab = b.addr.size() > 0 ? b.addr[0].addr : 0;
474 return aa < ab;
475 }
476
477 bool operator()(const soc_reg_addr_t& a, const soc_reg_addr_t& b) const
478 {
479 return a.addr < b.addr;
480 }
481
482 bool operator()(const soc_reg_field_t& a, const soc_reg_field_t& b) const
483 {
484 return a.last_bit > b.last_bit;
485 }
486
487 bool operator()(const soc_reg_field_value_t a, const soc_reg_field_value_t& b) const
488 {
489 return a.value < b.value;
490 }
491};
492
493void normalize(soc_reg_field_t& field)
494{
495 std::sort(field.value.begin(), field.value.end(), soc_sorter());
496}
497
498void normalize(soc_reg_t& reg)
499{
500 std::sort(reg.addr.begin(), reg.addr.end(), soc_sorter());
501 std::sort(reg.field.begin(), reg.field.end(), soc_sorter());
502 for(size_t i = 0; i < reg.field.size(); i++)
503 normalize(reg.field[i]);
504}
505
506void normalize(soc_dev_t& dev)
507{
508 std::sort(dev.addr.begin(), dev.addr.end(), soc_sorter());
509 std::sort(dev.reg.begin(), dev.reg.end(), soc_sorter());
510 for(size_t i = 0; i < dev.reg.size(); i++)
511 normalize(dev.reg[i]);
512}
513
514}
515
516void soc_desc_normalize(soc_t& soc)
517{
518 std::sort(soc.dev.begin(), soc.dev.end(), soc_sorter());
519 for(size_t i = 0; i < soc.dev.size(); i++)
520 normalize(soc.dev[i]);
521}
522
523namespace
524{
525 soc_error_t make_error(soc_error_level_t lvl, std::string at, std::string what)
526 {
527 soc_error_t err;
528 err.level = lvl;
529 err.location = at;
530 err.message = what;
531 return err;
532 }
533
534 soc_error_t make_warning(std::string at, std::string what)
535 {
536 return make_error(SOC_ERROR_WARNING, at, what);
537 }
538
539 soc_error_t make_fatal(std::string at, std::string what)
540 {
541 return make_error(SOC_ERROR_FATAL, at, what);
542 }
543
544 soc_error_t prefix(soc_error_t err, const std::string& prefix_at)
545 {
546 err.location = prefix_at + "." + err.location;
547 return err;
548 }
549
550 void add_errors(std::vector< soc_error_t >& errors,
551 const std::vector< soc_error_t >& new_errors, const std::string& prefix_at)
552 {
553 for(size_t i = 0; i < new_errors.size(); i++)
554 errors.push_back(prefix(new_errors[i], prefix_at));
555 }
556
557 std::vector< soc_error_t > no_error()
558 {
559 std::vector< soc_error_t > s;
560 return s;
561 }
562
563 std::vector< soc_error_t > one_error(const soc_error_t& err)
564 {
565 std::vector< soc_error_t > s;
566 s.push_back(err);
567 return s;
568 }
569
570 bool name_valid(char c)
571 {
572 return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') ||
573 (c >= 'A' && c <= 'Z') || c == '_';
574 }
575
576 bool name_valid(const std::string& s)
577 {
578 for(size_t i = 0; i < s.size(); i++)
579 if(!name_valid(s[i]))
580 return false;
581 return true;
582 }
583}
584
585std::vector< soc_error_t > soc_reg_field_value_t::errors(bool recursive)
586{
587 (void) recursive;
588 if(name.size() == 0)
589 return one_error(make_fatal(name, "empty name"));
590 else if(!name_valid(name))
591 return one_error(make_fatal(name, "invalid name"));
592 else
593 return no_error();
594}
595
596std::vector< soc_error_t > soc_reg_field_t::errors(bool recursive)
597{
598 std::vector< soc_error_t > err;
599 std::string at(name);
600 if(name.size() == 0)
601 err.push_back(make_fatal(at, "empty name"));
602 else if(!name_valid(name))
603 err.push_back(make_fatal(at, "invalid name"));
604 if(last_bit > 31)
605 err.push_back(make_fatal(at, "last bit is greater than 31"));
606 if(first_bit > last_bit)
607 err.push_back(make_fatal(at, "last bit is greater than first bit"));
608 for(size_t i = 0; i < value.size(); i++)
609 {
610 for(size_t j = 0; j < value.size(); j++)
611 {
612 if(i == j)
613 continue;
614 if(value[i].name == value[j].name)
615 err.push_back(prefix(make_fatal(value[i].name,
616 "there are several values with the same name"), at));
617 if(value[i].value == value[j].value)
618 err.push_back(prefix(make_warning(value[i].name,
619 "there are several values with the same value"), at));
620 }
621 if(value[i].value > (bitmask() >> first_bit))
622 err.push_back(prefix(make_warning(at, "value doesn't fit into the field"), value[i].name));
623 if(recursive)
624 add_errors(err, value[i].errors(true), at);
625 }
626 return err;
627}
628
629std::vector< soc_error_t > soc_reg_addr_t::errors(bool recursive)
630{
631 (void) recursive;
632 if(name.size() == 0)
633 return one_error(make_fatal("", "empty name"));
634 else if(!name_valid(name))
635 return one_error(make_fatal(name, "invalid name"));
636 else
637 return no_error();
638}
639
640std::vector< soc_error_t > soc_reg_formula_t::errors(bool recursive)
641{
642 (void) recursive;
643 if(type == REG_FORMULA_STRING && string.size() == 0)
644 return one_error(make_fatal("", "empty string formula"));
645 else
646 return no_error();
647}
648
649namespace
650{
651
652bool field_overlap(const soc_reg_field_t& a, const soc_reg_field_t& b)
653{
654 return !(a.first_bit > b.last_bit || b.first_bit > a.last_bit);
655}
656
657}
658
659std::vector< soc_error_t > soc_reg_t::errors(bool recursive)
660{
661 std::vector< soc_error_t > err;
662 std::string at(name);
663 if(name.size() == 0)
664 err.push_back(make_fatal(at, "empty name"));
665 else if(!name_valid(name))
666 err.push_back(make_fatal(at, "invalid name"));
667 for(size_t i = 0; i < addr.size(); i++)
668 {
669 for(size_t j = 0; j < addr.size(); j++)
670 {
671 if(i == j)
672 continue;
673 if(addr[i].name == addr[j].name)
674 err.push_back(prefix(make_fatal(addr[i].name,
675 "there are several instances with the same name"), at));
676 if(addr[i].addr == addr[j].addr)
677 err.push_back(prefix(make_fatal(addr[i].name,
678 "there are several instances with the same address"), at));
679 }
680 if(recursive)
681 add_errors(err, addr[i].errors(true), at);
682 }
683 if(recursive)
684 add_errors(err, formula.errors(true), at);
685 for(size_t i = 0; i < field.size(); i++)
686 {
687 for(size_t j = 0; j < field.size(); j++)
688 {
689 if(i == j)
690 continue;
691 if(field[i].name == field[j].name)
692 err.push_back(prefix(make_fatal(field[i].name,
693 "there are several fields with the same name"), at));
694 if(field_overlap(field[i], field[j]))
695 err.push_back(prefix(make_fatal(field[i].name,
696 "there are overlapping fields"), at));
697 }
698 if(recursive)
699 add_errors(err, field[i].errors(true), at);
700 }
701 return err;
702}
703
704std::vector< soc_error_t > soc_dev_addr_t::errors(bool recursive)
705{
706 (void) recursive;
707 if(name.size() == 0)
708 return one_error(make_fatal("", "empty name"));
709 else if(!name_valid(name))
710 return one_error(make_fatal(name, "invalid name"));
711 else
712 return no_error();
713}
714
715std::vector< soc_error_t > soc_dev_t::errors(bool recursive)
716{
717 std::vector< soc_error_t > err;
718 std::string at(name);
719 if(name.size() == 0)
720 err.push_back(make_fatal(at, "empty name"));
721 else if(!name_valid(name))
722 err.push_back(make_fatal(at, "invalid name"));
723 for(size_t i = 0; i < addr.size(); i++)
724 {
725 for(size_t j = 0; j < addr.size(); j++)
726 {
727 if(i == j)
728 continue;
729 if(addr[i].name == addr[j].name)
730 err.push_back(prefix(make_fatal(addr[i].name,
731 "there are several instances with the same name"), at));
732 if(addr[i].addr == addr[j].addr)
733 err.push_back(prefix(make_fatal(addr[i].name,
734 "there are several instances with the same address"), at));
735 }
736 if(recursive)
737 add_errors(err, addr[i].errors(true), at);
738 }
739 for(size_t i = 0; i < reg.size(); i++)
740 {
741 for(size_t j = 0; j < reg.size(); j++)
742 {
743 if(i == j)
744 continue;
745 if(reg[i].name == reg[j].name)
746 err.push_back(prefix(make_fatal(reg[i].name,
747 "there are several registers with the same name"), at));
748 }
749 if(recursive)
750 add_errors(err, reg[i].errors(true), at);
751 }
752 return err;
753}
754
755std::vector< soc_error_t > soc_t::errors(bool recursive)
756{
757 std::vector< soc_error_t > err;
758 std::string at(name);
759 for(size_t i = 0; i < dev.size(); i++)
760 {
761 for(size_t j = 0; j < dev.size(); j++)
762 {
763 if(i == j)
764 continue;
765 if(dev[i].name == dev[j].name)
766 err.push_back(prefix(make_fatal(dev[i].name,
767 "there are several devices with the same name"), at));
768 }
769 if(recursive)
770 add_errors(err, dev[i].errors(true), at);
771 }
772 return err;
773}
774
775namespace
776{
777
778struct formula_evaluator
779{
780 std::string formula;
781 size_t pos;
782 std::string error;
783
784 bool err(const char *fmt, ...)
785 {
786 char buffer[256];
787 va_list args;
788 va_start(args, fmt);
789 vsnprintf(buffer,sizeof(buffer), fmt, args);
790 va_end(args);
791 error = buffer;
792 return false;
793 }
794
795 formula_evaluator(const std::string& s):pos(0)
796 {
797 for(size_t i = 0; i < s.size(); i++)
798 if(!isspace(s[i]))
799 formula.push_back(s[i]);
800 }
801
802 void adv()
803 {
804 pos++;
805 }
806
807 char cur()
808 {
809 return end() ? 0 : formula[pos];
810 }
811
812 bool end()
813 {
814 return pos >= formula.size();
815 }
816
817 bool parse_digit(char c, int basis, soc_word_t& res)
818 {
819 c = tolower(c);
820 if(isdigit(c))
821 {
822 res = c - '0';
823 return true;
824 }
825 if(basis == 16 && isxdigit(c))
826 {
827 res = c + 10 - 'a';
828 return true;
829 }
830 return err("invalid digit '%c'", c);
831 }
832
833 bool parse_signed(soc_word_t& res)
834 {
835 char op = cur();
836 if(op == '+' || op == '-')
837 {
838 adv();
839 if(!parse_signed(res))
840 return false;
841 if(op == '-')
842 res *= -1;
843 return true;
844 }
845 else if(op == '(')
846 {
847 adv();
848 if(!parse_expression(res))
849 return false;
850 if(cur() != ')')
851 return err("expected ')', got '%c'", cur());
852 adv();
853 return true;
854 }
855 else if(isdigit(op))
856 {
857 res = op - '0';
858 adv();
859 int basis = 10;
860 if(op == '0' && cur() == 'x')
861 {
862 basis = 16;
863 adv();
864 }
865 soc_word_t digit = 0;
866 while(parse_digit(cur(), basis, digit))
867 {
868 res = res * basis + digit;
869 adv();
870 }
871 return true;
872 }
873 else if(isalpha(op) || op == '_')
874 {
875 std::string name;
876 while(isalnum(cur()) || cur() == '_')
877 {
878 name.push_back(cur());
879 adv();
880 }
881 return get_variable(name, res);
882 }
883 else
884 return err("express signed expression, got '%c'", op);
885 }
886
887 bool parse_term(soc_word_t& res)
888 {
889 if(!parse_signed(res))
890 return false;
891 while(cur() == '*' || cur() == '/' || cur() == '%')
892 {
893 char op = cur();
894 adv();
895 soc_word_t tmp;
896 if(!parse_signed(tmp))
897 return false;
898 if(op == '*')
899 res *= tmp;
900 else if(tmp != 0)
901 res = op == '/' ? res / tmp : res % tmp;
902 else
903 return err("division by 0");
904 }
905 return true;
906 }
907
908 bool parse_expression(soc_word_t& res)
909 {
910 if(!parse_term(res))
911 return false;
912 while(!end() && (cur() == '+' || cur() == '-'))
913 {
914 char op = cur();
915 adv();
916 soc_word_t tmp;
917 if(!parse_term(tmp))
918 return false;
919 if(op == '+')
920 res += tmp;
921 else
922 res -= tmp;
923 }
924 return true;
925 }
926
927 bool parse(soc_word_t& res, std::string& _error)
928 {
929 bool ok = parse_expression(res);
930 if(ok && !end())
931 err("unexpected character '%c'", cur());
932 _error = error;
933 return ok && end();
934 }
935
936 virtual bool get_variable(std::string name, soc_word_t& res)
937 {
938 return err("unknown variable '%s'", name.c_str());
939 }
940};
941
942struct my_evaluator : public formula_evaluator
943{
944 const std::map< std::string, soc_word_t>& var;
945
946 my_evaluator(const std::string& formula, const std::map< std::string, soc_word_t>& _var)
947 :formula_evaluator(formula), var(_var) {}
948
949 virtual bool get_variable(std::string name, soc_word_t& res)
950 {
951 std::map< std::string, soc_word_t>::const_iterator it = var.find(name);
952 if(it == var.end())
953 return formula_evaluator::get_variable(name, res);
954 else
955 {
956 res = it->second;
957 return true;
958 }
959 }
960};
961
962}
963
964bool soc_desc_evaluate_formula(const std::string& formula,
965 const std::map< std::string, soc_word_t>& var, soc_word_t& result, std::string& error)
966{
967 my_evaluator e(formula, var);
968 return e.parse(result, error);
969}
diff --git a/utils/regtools/lib/soc_desc.hpp b/utils/regtools/lib/soc_desc.hpp
index efaf813eb2..d9dbf0cc20 100644
--- a/utils/regtools/lib/soc_desc.hpp
+++ b/utils/regtools/lib/soc_desc.hpp
@@ -25,6 +25,7 @@
25#include <vector> 25#include <vector>
26#include <list> 26#include <list>
27#include <string> 27#include <string>
28#include <map>
28 29
29/** 30/**
30 * These data structures represent the SoC register in a convenient way. 31 * These data structures represent the SoC register in a convenient way.
@@ -50,6 +51,21 @@ typedef uint32_t soc_addr_t;
50typedef uint32_t soc_word_t; 51typedef uint32_t soc_word_t;
51typedef uint32_t soc_reg_flags_t; 52typedef uint32_t soc_reg_flags_t;
52 53
54/** SoC error gravity level */
55enum soc_error_level_t
56{
57 SOC_ERROR_WARNING,
58 SOC_ERROR_FATAL,
59};
60
61/** SoC description error */
62struct soc_error_t
63{
64 soc_error_level_t level; /// level (warning, fatal, ...)
65 std::string location; /// human description of the location
66 std::string message; /// message
67};
68
53/** SoC register generic formula */ 69/** SoC register generic formula */
54enum soc_reg_formula_type_t 70enum soc_reg_formula_type_t
55{ 71{
@@ -66,6 +82,8 @@ struct soc_reg_field_value_t
66 std::string name; /// name of the value 82 std::string name; /// name of the value
67 soc_word_t value; /// numeric value 83 soc_word_t value; /// numeric value
68 std::string desc; /// human description 84 std::string desc; /// human description
85
86 std::vector< soc_error_t > errors(bool recursive);
69}; 87};
70 88
71/** SoC register field */ 89/** SoC register field */
@@ -90,6 +108,8 @@ struct soc_reg_field_t
90 } 108 }
91 109
92 std::vector< soc_reg_field_value_t > value; 110 std::vector< soc_reg_field_value_t > value;
111
112 std::vector< soc_error_t > errors(bool recursive);
93}; 113};
94 114
95/** SoC register address */ 115/** SoC register address */
@@ -97,6 +117,8 @@ struct soc_reg_addr_t
97{ 117{
98 std::string name; /// actual register name 118 std::string name; /// actual register name
99 soc_addr_t addr; /// actual register address (relative to device) 119 soc_addr_t addr; /// actual register address (relative to device)
120
121 std::vector< soc_error_t > errors(bool recursive);
100}; 122};
101 123
102/** SoC register formula */ 124/** SoC register formula */
@@ -104,6 +126,8 @@ struct soc_reg_formula_t
104{ 126{
105 enum soc_reg_formula_type_t type; 127 enum soc_reg_formula_type_t type;
106 std::string string; /// for STRING 128 std::string string; /// for STRING
129
130 std::vector< soc_error_t > errors(bool recursive);
107}; 131};
108 132
109/** SoC register */ 133/** SoC register */
@@ -116,6 +140,8 @@ struct soc_reg_t
116 soc_reg_flags_t flags; /// ORed value 140 soc_reg_flags_t flags; /// ORed value
117 141
118 std::vector< soc_reg_field_t > field; 142 std::vector< soc_reg_field_t > field;
143
144 std::vector< soc_error_t > errors(bool recursive);
119}; 145};
120 146
121/** Soc device address */ 147/** Soc device address */
@@ -123,6 +149,8 @@ struct soc_dev_addr_t
123{ 149{
124 std::string name; /// actual device name 150 std::string name; /// actual device name
125 soc_addr_t addr; 151 soc_addr_t addr;
152
153 std::vector< soc_error_t > errors(bool recursive);
126}; 154};
127 155
128/** SoC device */ 156/** SoC device */
@@ -135,6 +163,8 @@ struct soc_dev_t
135 std::vector< soc_dev_addr_t > addr; 163 std::vector< soc_dev_addr_t > addr;
136 164
137 std::vector< soc_reg_t > reg; 165 std::vector< soc_reg_t > reg;
166
167 std::vector< soc_error_t > errors(bool recursive);
138}; 168};
139 169
140/** SoC */ 170/** SoC */
@@ -144,10 +174,23 @@ struct soc_t
144 std::string desc; /// SoC name 174 std::string desc; /// SoC name
145 175
146 std::vector< soc_dev_t > dev; 176 std::vector< soc_dev_t > dev;
177
178 std::vector< soc_error_t > errors(bool recursive);
147}; 179};
148 180
149/** Parse a SoC description from a XML file, append it to <soc>. A file 181/** Parse a SoC description from a XML file, append it to <soc>. */
150 * can contain multiple SoC descriptions */ 182bool soc_desc_parse_xml(const std::string& filename, soc_t& soc);
151bool soc_desc_parse_xml(const std::string& filename, std::vector< soc_t >& soc); 183/** Write a SoC description to a XML file, overwriting it. A file can contain
184 * multiple Soc descriptions */
185bool soc_desc_produce_xml(const std::string& filename, const soc_t& soc);
186/** Normalise a soc description by reordering elemnts so that:
187 * - devices are sorted by first name
188 * - registers are sorted by first address
189 * - fields are sorted by last bit
190 * - values are sorted by value */
191void soc_desc_normalize(soc_t& soc);
192/** Formula parser: try to parse and evaluate a formula to a specific value of 'n' */
193bool soc_desc_evaluate_formula(const std::string& formula,
194 const std::map< std::string, soc_word_t>& var, soc_word_t& result, std::string& error);
152 195
153#endif /* __SOC_DESC__ */ \ No newline at end of file 196#endif /* __SOC_DESC__ */ \ No newline at end of file