diff options
author | Amaury Pouly <amaury.pouly@gmail.com> | 2016-02-06 15:01:24 +0000 |
---|---|---|
committer | Amaury Pouly <amaury.pouly@gmail.com> | 2016-02-06 15:12:55 +0000 |
commit | 0f701a64bee43e79f95970ae9c0ec43ea7fcdf17 (patch) | |
tree | c8ac6b5516eac120797eb6a06f633919e9f48f9b /utils/regtools/lib | |
parent | 16c915ec1826dcef2e58ecc055a3f5dfcefb235a (diff) | |
download | rockbox-0f701a64bee43e79f95970ae9c0ec43ea7fcdf17.tar.gz rockbox-0f701a64bee43e79f95970ae9c0ec43ea7fcdf17.zip |
regtools: update v2 specification, library and tools
A v2 register description file can now include register variants and instances
addresses can now be a list (previously it could only be a stride or a formula).
Update the library to deal with that. The convert option of swiss_knife was
updated and one incompatible change was introduce: if a v1 device has several
addresses, those are converted to a single v2 instance with list (instead of
several single instances). This should have been the behaviour from the start.
Swiss_knife can now also convert regdumps, in which case it needs to be given
both the dump and register description file. Also introduce two register
descriptions files (vsoc1000 and vsoc2000) which give more complicated examples
of v2 register description files.
Change-Id: Id9415b8363269ffaf9216abfc6dd1bd1adbfcf8d
Diffstat (limited to 'utils/regtools/lib')
-rw-r--r-- | utils/regtools/lib/soc_desc.cpp | 473 |
1 files changed, 442 insertions, 31 deletions
diff --git a/utils/regtools/lib/soc_desc.cpp b/utils/regtools/lib/soc_desc.cpp index 4e0e46f00e..e6c58d4814 100644 --- a/utils/regtools/lib/soc_desc.cpp +++ b/utils/regtools/lib/soc_desc.cpp | |||
@@ -308,13 +308,28 @@ bool parse_field_elem(xmlNode *node, field_t& field, error_context_t& ctx) | |||
308 | return ret; | 308 | return ret; |
309 | } | 309 | } |
310 | 310 | ||
311 | bool parse_variant_elem(xmlNode *node, variant_t& variant, error_context_t& ctx) | ||
312 | { | ||
313 | bool ret = true; | ||
314 | bool has_type = false, has_offset = false; | ||
315 | BEGIN_NODE_MATCH(node->children) | ||
316 | MATCH_UNIQUE_TEXT_NODE("type", variant.type, has_type, parse_name_elem, ctx) | ||
317 | MATCH_UNIQUE_TEXT_NODE("offset", variant.offset, has_offset, parse_unsigned_elem, ctx) | ||
318 | END_NODE_MATCH() | ||
319 | CHECK_HAS(node, "type", has_type, ctx) | ||
320 | CHECK_HAS(node, "offset", has_offset, ctx) | ||
321 | return ret; | ||
322 | } | ||
323 | |||
311 | bool parse_register_elem(xmlNode *node, register_t& reg, error_context_t& ctx) | 324 | bool parse_register_elem(xmlNode *node, register_t& reg, error_context_t& ctx) |
312 | { | 325 | { |
313 | bool ret = true; | 326 | bool ret = true; |
314 | bool has_width = false; | 327 | bool has_width = false, has_desc = false; |
315 | BEGIN_NODE_MATCH(node->children) | 328 | BEGIN_NODE_MATCH(node->children) |
329 | MATCH_UNIQUE_TEXT_NODE("desc", reg.desc, has_desc, parse_text_elem, ctx) | ||
316 | MATCH_UNIQUE_TEXT_NODE("width", reg.width, has_width, parse_unsigned_elem, ctx) | 330 | MATCH_UNIQUE_TEXT_NODE("width", reg.width, has_width, parse_unsigned_elem, ctx) |
317 | MATCH_ELEM_NODE("field", reg.field, parse_field_elem, ctx) | 331 | MATCH_ELEM_NODE("field", reg.field, parse_field_elem, ctx) |
332 | MATCH_ELEM_NODE("variant", reg.variant, parse_variant_elem, ctx) | ||
318 | END_NODE_MATCH() | 333 | END_NODE_MATCH() |
319 | if(!has_width) | 334 | if(!has_width) |
320 | reg.width = 32; | 335 | reg.width = 32; |
@@ -344,21 +359,37 @@ bool parse_range_elem(xmlNode *node, range_t& range, error_context_t& ctx) | |||
344 | MATCH_UNIQUE_TEXT_NODE("stride", range.stride, has_stride, parse_unsigned_elem, ctx) | 359 | MATCH_UNIQUE_TEXT_NODE("stride", range.stride, has_stride, parse_unsigned_elem, ctx) |
345 | MATCH_UNIQUE_ELEM_NODE("formula", range, has_formula_attr, parse_formula_elem, ctx) | 360 | MATCH_UNIQUE_ELEM_NODE("formula", range, has_formula_attr, parse_formula_elem, ctx) |
346 | MATCH_UNIQUE_TEXT_NODE("formula", range.formula, has_formula, parse_text_elem, ctx) | 361 | MATCH_UNIQUE_TEXT_NODE("formula", range.formula, has_formula, parse_text_elem, ctx) |
362 | MATCH_TEXT_NODE("address", range.list, parse_unsigned_elem, ctx) | ||
347 | END_NODE_MATCH() | 363 | END_NODE_MATCH() |
348 | CHECK_HAS(node, "first", has_first, ctx) | 364 | CHECK_HAS(node, "first", has_first, ctx) |
349 | CHECK_HAS(node, "count", has_count, ctx) | 365 | if(range.list.size() == 0) |
350 | if(!has_base && !has_formula) | 366 | { |
351 | ret = ret && parse_missing_error(node, "base> or <formula", ctx); | 367 | CHECK_HAS(node, "count", has_count, ctx) |
352 | if(has_base && has_formula) | 368 | if(!has_base && !has_formula) |
353 | return parse_conflict_error(node, "base", "formula", ctx); | 369 | ret = ret && parse_missing_error(node, "base> or <formula", ctx); |
354 | if(has_base) | 370 | if(has_base && has_formula) |
355 | CHECK_HAS(node, "stride", has_stride, ctx) | 371 | return parse_conflict_error(node, "base", "formula", ctx); |
356 | if(has_stride && !has_base) | 372 | if(has_base) |
357 | ret = ret && parse_conflict_error(node, "stride", "formula", ctx); | 373 | CHECK_HAS(node, "stride", has_stride, ctx) |
358 | if(has_stride) | 374 | if(has_stride && !has_base) |
359 | range.type = range_t::STRIDE; | 375 | ret = ret && parse_conflict_error(node, "stride", "formula", ctx); |
376 | if(has_stride) | ||
377 | range.type = range_t::STRIDE; | ||
378 | else | ||
379 | range.type = range_t::FORMULA; | ||
380 | } | ||
360 | else | 381 | else |
361 | range.type = range_t::FORMULA; | 382 | { |
383 | if(has_base) | ||
384 | ret = ret && parse_conflict_error(node, "base", "addr", ctx); | ||
385 | if(has_count) | ||
386 | ret = ret && parse_conflict_error(node, "count", "addr", ctx); | ||
387 | if(has_formula) | ||
388 | ret = ret && parse_conflict_error(node, "formula", "addr", ctx); | ||
389 | if(has_stride) | ||
390 | ret = ret && parse_conflict_error(node, "stride", "addr", ctx); | ||
391 | range.type = range_t::LIST; | ||
392 | } | ||
362 | return ret; | 393 | return ret; |
363 | } | 394 | } |
364 | 395 | ||
@@ -400,7 +431,6 @@ bool parse_node_elem(xmlNode *node_, node_t& node, error_context_t& ctx) | |||
400 | MATCH_ELEM_NODE("instance", node.instance, parse_instance_elem, ctx) | 431 | MATCH_ELEM_NODE("instance", node.instance, parse_instance_elem, ctx) |
401 | END_NODE_MATCH() | 432 | END_NODE_MATCH() |
402 | CHECK_HAS(node_, "name", has_name, ctx) | 433 | CHECK_HAS(node_, "name", has_name, ctx) |
403 | CHECK_HAS(node_, "instance", !node.instance.empty(), ctx) | ||
404 | if(has_register) | 434 | if(has_register) |
405 | node.register_.push_back(reg); | 435 | node.register_.push_back(reg); |
406 | return ret; | 436 | return ret; |
@@ -466,6 +496,93 @@ bool parse_xml(const std::string& filename, soc_t& soc, | |||
466 | } | 496 | } |
467 | 497 | ||
468 | /** | 498 | /** |
499 | * Normalizer | ||
500 | */ | ||
501 | |||
502 | namespace | ||
503 | { | ||
504 | |||
505 | struct soc_sorter | ||
506 | { | ||
507 | /* returns the first (lowest) address of an instance */ | ||
508 | soc_addr_t first_addr(const instance_t& inst) const | ||
509 | { | ||
510 | if(inst.type == instance_t::SINGLE) | ||
511 | return inst.addr; | ||
512 | if(inst.range.type == range_t::STRIDE) | ||
513 | return inst.range.base; | ||
514 | soc_word_t res; | ||
515 | std::map< std::string, soc_word_t > vars; | ||
516 | vars[inst.range.variable] = inst.range.first; | ||
517 | error_context_t ctx; | ||
518 | if(!evaluate_formula(inst.range.formula, vars, res, "", ctx)) | ||
519 | return 0xffffffff; | ||
520 | return res; | ||
521 | } | ||
522 | |||
523 | /* sort instances by first address */ | ||
524 | bool operator()(const instance_t& a, const instance_t& b) const | ||
525 | { | ||
526 | return first_addr(a) < first_addr(b); | ||
527 | } | ||
528 | |||
529 | /* sort nodes by first address of first instance (which is the lowest of | ||
530 | * any instance if instances are sorted) */ | ||
531 | bool operator()(const node_t& a, const node_t& b) const | ||
532 | { | ||
533 | /* borderline cases: no instances is lower than with instances */ | ||
534 | if(a.instance.size() == 0) | ||
535 | return b.instance.size() > 0; | ||
536 | if(b.instance.size() == 0) | ||
537 | return false; | ||
538 | return first_addr(a.instance[0]) < first_addr(b.instance[0]); | ||
539 | } | ||
540 | |||
541 | /* sort fields by decreasing position */ | ||
542 | bool operator()(const field_t& a, const field_t& b) const | ||
543 | { | ||
544 | return a.pos > b.pos; | ||
545 | } | ||
546 | |||
547 | /* sort enum values by value */ | ||
548 | bool operator()(const enum_t& a, const enum_t& b) const | ||
549 | { | ||
550 | return a.value < b.value; | ||
551 | } | ||
552 | }; | ||
553 | |||
554 | void normalize(field_t& field) | ||
555 | { | ||
556 | std::sort(field.enum_.begin(), field.enum_.end(), soc_sorter()); | ||
557 | } | ||
558 | |||
559 | void normalize(register_t& reg) | ||
560 | { | ||
561 | for(size_t i = 0; i < reg.field.size(); i++) | ||
562 | normalize(reg.field[i]); | ||
563 | std::sort(reg.field.begin(), reg.field.end(), soc_sorter()); | ||
564 | } | ||
565 | |||
566 | void normalize(node_t& node) | ||
567 | { | ||
568 | for(size_t i = 0; i < node.register_.size(); i++) | ||
569 | normalize(node.register_[i]); | ||
570 | for(size_t i = 0; i < node.node.size(); i++) | ||
571 | normalize(node.node[i]); | ||
572 | std::sort(node.node.begin(), node.node.end(), soc_sorter()); | ||
573 | std::sort(node.instance.begin(), node.instance.end(), soc_sorter()); | ||
574 | } | ||
575 | |||
576 | } | ||
577 | |||
578 | void normalize(soc_t& soc) | ||
579 | { | ||
580 | for(size_t i = 0; i < soc.node.size(); i++) | ||
581 | normalize(soc.node[i]); | ||
582 | std::sort(soc.node.begin(), soc.node.end(), soc_sorter()); | ||
583 | } | ||
584 | |||
585 | /** | ||
469 | * Producer | 586 | * Producer |
470 | */ | 587 | */ |
471 | 588 | ||
@@ -488,17 +605,20 @@ int produce_range(xmlTextWriterPtr writer, const range_t& range, error_context_t | |||
488 | SAFE(xmlTextWriterStartElement(writer, BAD_CAST "range")); | 605 | SAFE(xmlTextWriterStartElement(writer, BAD_CAST "range")); |
489 | /* <first/> */ | 606 | /* <first/> */ |
490 | SAFE(xmlTextWriterWriteFormatElement(writer, BAD_CAST "first", "%lu", range.first)); | 607 | SAFE(xmlTextWriterWriteFormatElement(writer, BAD_CAST "first", "%lu", range.first)); |
491 | /* <count/> */ | ||
492 | SAFE(xmlTextWriterWriteFormatElement(writer, BAD_CAST "count", "%lu", range.count)); | ||
493 | /* <base/><stride/> */ | ||
494 | if(range.type == range_t::STRIDE) | 608 | if(range.type == range_t::STRIDE) |
495 | { | 609 | { |
610 | /* <count/> */ | ||
611 | SAFE(xmlTextWriterWriteFormatElement(writer, BAD_CAST "count", "%lu", range.count)); | ||
612 | /* <base/> */ | ||
496 | SAFE(xmlTextWriterWriteFormatElement(writer, BAD_CAST "base", "0x%x", range.base)); | 613 | SAFE(xmlTextWriterWriteFormatElement(writer, BAD_CAST "base", "0x%x", range.base)); |
614 | /* <stride/> */ | ||
497 | SAFE(xmlTextWriterWriteFormatElement(writer, BAD_CAST "stride", "0x%x", range.stride)); | 615 | SAFE(xmlTextWriterWriteFormatElement(writer, BAD_CAST "stride", "0x%x", range.stride)); |
498 | } | 616 | } |
499 | /* <formula> */ | 617 | /* <formula> */ |
500 | else if(range.type == range_t::FORMULA) | 618 | else if(range.type == range_t::FORMULA) |
501 | { | 619 | { |
620 | /* <count/> */ | ||
621 | SAFE(xmlTextWriterWriteFormatElement(writer, BAD_CAST "count", "%lu", range.count)); | ||
502 | /* <formula> */ | 622 | /* <formula> */ |
503 | SAFE(xmlTextWriterStartElement(writer, BAD_CAST "formula")); | 623 | SAFE(xmlTextWriterStartElement(writer, BAD_CAST "formula")); |
504 | /* variable */ | 624 | /* variable */ |
@@ -508,6 +628,11 @@ int produce_range(xmlTextWriterPtr writer, const range_t& range, error_context_t | |||
508 | /* </formula> */ | 628 | /* </formula> */ |
509 | SAFE(xmlTextWriterEndElement(writer)); | 629 | SAFE(xmlTextWriterEndElement(writer)); |
510 | } | 630 | } |
631 | else if(range.type == range_t::LIST) | ||
632 | { | ||
633 | for(size_t i = 0; i < range.list.size(); i++) | ||
634 | SAFE(xmlTextWriterWriteFormatElement(writer, BAD_CAST "address", "0x%x", range.list[i])); | ||
635 | } | ||
511 | /* </range> */ | 636 | /* </range> */ |
512 | SAFE(xmlTextWriterEndElement(writer)); | 637 | SAFE(xmlTextWriterEndElement(writer)); |
513 | 638 | ||
@@ -575,6 +700,19 @@ int produce_field(xmlTextWriterPtr writer, const field_t& field, error_context_t | |||
575 | return 0; | 700 | return 0; |
576 | } | 701 | } |
577 | 702 | ||
703 | int produce_variant(xmlTextWriterPtr writer, const variant_t& variant, error_context_t& ctx) | ||
704 | { | ||
705 | /* <variant> */ | ||
706 | SAFE(xmlTextWriterStartElement(writer, BAD_CAST "variant")); | ||
707 | /* <name/> */ | ||
708 | SAFE(xmlTextWriterWriteElement(writer, BAD_CAST "type", BAD_CAST variant.type.c_str())); | ||
709 | /* <position/> */ | ||
710 | SAFE(xmlTextWriterWriteFormatElement(writer, BAD_CAST "offset", "%lu", (unsigned long)variant.offset)); | ||
711 | /* </variant> */ | ||
712 | SAFE(xmlTextWriterEndElement(writer)); | ||
713 | return 0; | ||
714 | } | ||
715 | |||
578 | int produce_register(xmlTextWriterPtr writer, const register_t& reg, error_context_t& ctx) | 716 | int produce_register(xmlTextWriterPtr writer, const register_t& reg, error_context_t& ctx) |
579 | { | 717 | { |
580 | /* <register> */ | 718 | /* <register> */ |
@@ -582,9 +720,15 @@ int produce_register(xmlTextWriterPtr writer, const register_t& reg, error_conte | |||
582 | /* <width/> */ | 720 | /* <width/> */ |
583 | if(reg.width != 32) | 721 | if(reg.width != 32) |
584 | SAFE(xmlTextWriterWriteFormatElement(writer, BAD_CAST "width", "%lu", reg.width)); | 722 | SAFE(xmlTextWriterWriteFormatElement(writer, BAD_CAST "width", "%lu", reg.width)); |
723 | /* <desc/> */ | ||
724 | if(!reg.desc.empty()) | ||
725 | SAFE(xmlTextWriterWriteElement(writer, BAD_CAST "desc", BAD_CAST reg.desc.c_str())); | ||
585 | /* fields */ | 726 | /* fields */ |
586 | for(size_t i = 0; i < reg.field.size(); i++) | 727 | for(size_t i = 0; i < reg.field.size(); i++) |
587 | SAFE(produce_field(writer, reg.field[i], ctx)); | 728 | SAFE(produce_field(writer, reg.field[i], ctx)); |
729 | /* variants */ | ||
730 | for(size_t i = 0; i < reg.variant.size(); i++) | ||
731 | SAFE(produce_variant(writer, reg.variant[i], ctx)); | ||
588 | /* </register> */ | 732 | /* </register> */ |
589 | SAFE(xmlTextWriterEndElement(writer)); | 733 | SAFE(xmlTextWriterEndElement(writer)); |
590 | return 0; | 734 | return 0; |
@@ -671,6 +815,24 @@ Lerr: | |||
671 | } | 815 | } |
672 | 816 | ||
673 | /** | 817 | /** |
818 | * utils | ||
819 | */ | ||
820 | |||
821 | namespace | ||
822 | { | ||
823 | |||
824 | template< typename T > | ||
825 | soc_id_t gen_fresh_id(const std::vector< T >& list) | ||
826 | { | ||
827 | soc_id_t id = 0; | ||
828 | for(size_t i = 0; i < list.size(); i++) | ||
829 | id = std::max(id, list[i].id); | ||
830 | return id + 1; | ||
831 | } | ||
832 | |||
833 | } | ||
834 | |||
835 | /** | ||
674 | * soc_ref_t | 836 | * soc_ref_t |
675 | */ | 837 | */ |
676 | 838 | ||
@@ -707,6 +869,11 @@ node_inst_t soc_ref_t::root_inst() const | |||
707 | return node_inst_t(*this); | 869 | return node_inst_t(*this); |
708 | } | 870 | } |
709 | 871 | ||
872 | void soc_ref_t::reset() | ||
873 | { | ||
874 | m_soc = 0; | ||
875 | } | ||
876 | |||
710 | /** | 877 | /** |
711 | * node_ref_t */ | 878 | * node_ref_t */ |
712 | 879 | ||
@@ -733,6 +900,11 @@ bool node_ref_t::is_root() const | |||
733 | return m_path.empty(); | 900 | return m_path.empty(); |
734 | } | 901 | } |
735 | 902 | ||
903 | void node_ref_t::reset() | ||
904 | { | ||
905 | m_soc.reset(); | ||
906 | } | ||
907 | |||
736 | namespace | 908 | namespace |
737 | { | 909 | { |
738 | 910 | ||
@@ -789,14 +961,20 @@ soc_ref_t node_ref_t::soc() const | |||
789 | return m_soc; | 961 | return m_soc; |
790 | } | 962 | } |
791 | 963 | ||
792 | node_ref_t node_ref_t::parent() const | 964 | node_ref_t node_ref_t::parent(unsigned level) const |
793 | { | 965 | { |
966 | if(level > depth()) | ||
967 | return node_ref_t(); | ||
794 | std::vector< soc_id_t > path = m_path; | 968 | std::vector< soc_id_t > path = m_path; |
795 | if(!path.empty()) | 969 | path.resize(depth() - level); |
796 | path.pop_back(); | ||
797 | return node_ref_t(m_soc, path); | 970 | return node_ref_t(m_soc, path); |
798 | } | 971 | } |
799 | 972 | ||
973 | unsigned node_ref_t::depth() const | ||
974 | { | ||
975 | return m_path.size(); | ||
976 | } | ||
977 | |||
800 | register_ref_t node_ref_t::reg() const | 978 | register_ref_t node_ref_t::reg() const |
801 | { | 979 | { |
802 | node_t *n = get(); | 980 | node_t *n = get(); |
@@ -808,6 +986,18 @@ register_ref_t node_ref_t::reg() const | |||
808 | return register_ref_t(*this); | 986 | return register_ref_t(*this); |
809 | } | 987 | } |
810 | 988 | ||
989 | register_ref_t node_ref_t::create_reg(size_t width) const | ||
990 | { | ||
991 | node_t *n = get(); | ||
992 | if(n == 0) | ||
993 | return register_ref_t(); | ||
994 | if(!n->register_.empty()) | ||
995 | return register_ref_t(); | ||
996 | n->register_.resize(1); | ||
997 | n->register_[0].width = width; | ||
998 | return register_ref_t(*this); | ||
999 | } | ||
1000 | |||
811 | node_ref_t node_ref_t::child(const std::string& name) const | 1001 | node_ref_t node_ref_t::child(const std::string& name) const |
812 | { | 1002 | { |
813 | /* check the node exists */ | 1003 | /* check the node exists */ |
@@ -867,6 +1057,41 @@ bool node_ref_t::operator==(const node_ref_t& ref) const | |||
867 | return m_soc == ref.m_soc && m_path == ref.m_path; | 1057 | return m_soc == ref.m_soc && m_path == ref.m_path; |
868 | } | 1058 | } |
869 | 1059 | ||
1060 | void node_ref_t::remove() | ||
1061 | { | ||
1062 | if(is_root()) | ||
1063 | { | ||
1064 | soc_t *s = soc().get(); | ||
1065 | if(s) | ||
1066 | s->node.clear(); | ||
1067 | } | ||
1068 | else | ||
1069 | { | ||
1070 | std::vector< node_t > *list = get_children(parent()); | ||
1071 | if(list == 0) | ||
1072 | return; | ||
1073 | for(size_t i = 0; i < list->size(); i++) | ||
1074 | if((*list)[i].id == m_path.back()) | ||
1075 | { | ||
1076 | list->erase(list->begin() + i); | ||
1077 | return; | ||
1078 | } | ||
1079 | } | ||
1080 | } | ||
1081 | |||
1082 | node_ref_t node_ref_t::create() const | ||
1083 | { | ||
1084 | std::vector< node_t > *list = get_children(*this); | ||
1085 | if(list == 0) | ||
1086 | return node_ref_t(); | ||
1087 | node_t n; | ||
1088 | n.id = gen_fresh_id(*list); | ||
1089 | list->push_back(n); | ||
1090 | std::vector< soc_id_t > path = m_path; | ||
1091 | path.push_back(n.id); | ||
1092 | return node_ref_t(soc(), path); | ||
1093 | } | ||
1094 | |||
870 | /** | 1095 | /** |
871 | * register_ref_t | 1096 | * register_ref_t |
872 | */ | 1097 | */ |
@@ -885,6 +1110,11 @@ bool register_ref_t::valid() const | |||
885 | return get() != 0; | 1110 | return get() != 0; |
886 | } | 1111 | } |
887 | 1112 | ||
1113 | void register_ref_t::reset() | ||
1114 | { | ||
1115 | m_node.reset(); | ||
1116 | } | ||
1117 | |||
888 | register_t *register_ref_t::get() const | 1118 | register_t *register_ref_t::get() const |
889 | { | 1119 | { |
890 | node_t *n = m_node.get(); | 1120 | node_t *n = m_node.get(); |
@@ -909,6 +1139,17 @@ std::vector< field_ref_t > register_ref_t::fields() const | |||
909 | return fields; | 1139 | return fields; |
910 | } | 1140 | } |
911 | 1141 | ||
1142 | std::vector< variant_ref_t > register_ref_t::variants() const | ||
1143 | { | ||
1144 | std::vector< variant_ref_t > variants; | ||
1145 | register_t *r = get(); | ||
1146 | if(r == 0) | ||
1147 | return variants; | ||
1148 | for(size_t i = 0; i < r->variant.size(); i++) | ||
1149 | variants.push_back(variant_ref_t(*this, r->variant[i].id)); | ||
1150 | return variants; | ||
1151 | } | ||
1152 | |||
912 | field_ref_t register_ref_t::field(const std::string& name) const | 1153 | field_ref_t register_ref_t::field(const std::string& name) const |
913 | { | 1154 | { |
914 | register_t *r = get(); | 1155 | register_t *r = get(); |
@@ -920,6 +1161,46 @@ field_ref_t register_ref_t::field(const std::string& name) const | |||
920 | return field_ref_t(); | 1161 | return field_ref_t(); |
921 | } | 1162 | } |
922 | 1163 | ||
1164 | variant_ref_t register_ref_t::variant(const std::string& type) const | ||
1165 | { | ||
1166 | register_t *r = get(); | ||
1167 | if(r == 0) | ||
1168 | return variant_ref_t(); | ||
1169 | for(size_t i = 0; i < r->variant.size(); i++) | ||
1170 | if(r->variant[i].type == type) | ||
1171 | return variant_ref_t(*this, r->variant[i].id); | ||
1172 | return variant_ref_t(); | ||
1173 | } | ||
1174 | |||
1175 | void register_ref_t::remove() | ||
1176 | { | ||
1177 | node_t *n = node().get(); | ||
1178 | if(n) | ||
1179 | n->register_.clear(); | ||
1180 | } | ||
1181 | |||
1182 | field_ref_t register_ref_t::create_field() const | ||
1183 | { | ||
1184 | register_t *r = get(); | ||
1185 | if(r == 0) | ||
1186 | return field_ref_t(); | ||
1187 | field_t f; | ||
1188 | f.id = gen_fresh_id(r->field); | ||
1189 | r->field.push_back(f); | ||
1190 | return field_ref_t(*this, f.id); | ||
1191 | } | ||
1192 | |||
1193 | variant_ref_t register_ref_t::create_variant() const | ||
1194 | { | ||
1195 | register_t *r = get(); | ||
1196 | if(r == 0) | ||
1197 | return variant_ref_t(); | ||
1198 | variant_t v; | ||
1199 | v.id = gen_fresh_id(r->variant); | ||
1200 | r->variant.push_back(v); | ||
1201 | return variant_ref_t(*this, v.id); | ||
1202 | } | ||
1203 | |||
923 | /** | 1204 | /** |
924 | * field_ref_t | 1205 | * field_ref_t |
925 | */ | 1206 | */ |
@@ -938,6 +1219,11 @@ bool field_ref_t::valid() const | |||
938 | return get() != 0; | 1219 | return get() != 0; |
939 | } | 1220 | } |
940 | 1221 | ||
1222 | void field_ref_t::reset() | ||
1223 | { | ||
1224 | m_reg.reset(); | ||
1225 | } | ||
1226 | |||
941 | field_t *field_ref_t::get() const | 1227 | field_t *field_ref_t::get() const |
942 | { | 1228 | { |
943 | register_t *reg = m_reg.get(); | 1229 | register_t *reg = m_reg.get(); |
@@ -949,11 +1235,123 @@ field_t *field_ref_t::get() const | |||
949 | return 0; | 1235 | return 0; |
950 | } | 1236 | } |
951 | 1237 | ||
1238 | std::vector< enum_ref_t > field_ref_t::enums() const | ||
1239 | { | ||
1240 | std::vector< enum_ref_t > enums; | ||
1241 | field_t *f = get(); | ||
1242 | if(f == 0) | ||
1243 | return enums; | ||
1244 | for(size_t i = 0; i < f->enum_.size(); i++) | ||
1245 | enums.push_back(enum_ref_t(*this, f->enum_[i].id)); | ||
1246 | return enums; | ||
1247 | } | ||
1248 | |||
952 | register_ref_t field_ref_t::reg() const | 1249 | register_ref_t field_ref_t::reg() const |
953 | { | 1250 | { |
954 | return m_reg; | 1251 | return m_reg; |
955 | } | 1252 | } |
956 | 1253 | ||
1254 | enum_ref_t field_ref_t::create_enum() const | ||
1255 | { | ||
1256 | field_t *f = get(); | ||
1257 | if(f == 0) | ||
1258 | return enum_ref_t(); | ||
1259 | enum_t e; | ||
1260 | e.id = gen_fresh_id(f->enum_); | ||
1261 | f->enum_.push_back(e); | ||
1262 | return enum_ref_t(*this, e.id); | ||
1263 | } | ||
1264 | |||
1265 | /** | ||
1266 | * enum_ref_t | ||
1267 | */ | ||
1268 | |||
1269 | enum_ref_t::enum_ref_t(field_ref_t field, soc_id_t id) | ||
1270 | :m_field(field), m_id(id) | ||
1271 | { | ||
1272 | } | ||
1273 | |||
1274 | enum_ref_t::enum_ref_t() | ||
1275 | { | ||
1276 | } | ||
1277 | |||
1278 | bool enum_ref_t::valid() const | ||
1279 | { | ||
1280 | return get() != 0; | ||
1281 | } | ||
1282 | |||
1283 | void enum_ref_t::reset() | ||
1284 | { | ||
1285 | m_field.reset(); | ||
1286 | } | ||
1287 | |||
1288 | enum_t *enum_ref_t::get() const | ||
1289 | { | ||
1290 | field_t *field = m_field.get(); | ||
1291 | if(field == 0) | ||
1292 | return 0; | ||
1293 | for(size_t i = 0; i < field->enum_.size(); i++) | ||
1294 | if(field->enum_[i].id == m_id) | ||
1295 | return &field->enum_[i]; | ||
1296 | return 0; | ||
1297 | } | ||
1298 | |||
1299 | field_ref_t enum_ref_t::field() const | ||
1300 | { | ||
1301 | return m_field; | ||
1302 | } | ||
1303 | |||
1304 | /** | ||
1305 | * variant_ref_t | ||
1306 | */ | ||
1307 | |||
1308 | variant_ref_t::variant_ref_t(register_ref_t reg, soc_id_t id) | ||
1309 | :m_reg(reg), m_id(id) | ||
1310 | { | ||
1311 | } | ||
1312 | |||
1313 | variant_ref_t::variant_ref_t() | ||
1314 | { | ||
1315 | } | ||
1316 | |||
1317 | bool variant_ref_t::valid() const | ||
1318 | { | ||
1319 | return get() != 0; | ||
1320 | } | ||
1321 | |||
1322 | void variant_ref_t::reset() | ||
1323 | { | ||
1324 | m_reg.reset(); | ||
1325 | } | ||
1326 | |||
1327 | variant_t *variant_ref_t::get() const | ||
1328 | { | ||
1329 | register_t *reg = m_reg.get(); | ||
1330 | if(reg == 0) | ||
1331 | return 0; | ||
1332 | for(size_t i = 0; i < reg->variant.size(); i++) | ||
1333 | if(reg->variant[i].id == m_id) | ||
1334 | return ®->variant[i]; | ||
1335 | return 0; | ||
1336 | } | ||
1337 | |||
1338 | register_ref_t variant_ref_t::reg() const | ||
1339 | { | ||
1340 | return m_reg; | ||
1341 | } | ||
1342 | |||
1343 | std::string variant_ref_t::type() const | ||
1344 | { | ||
1345 | variant_t *v = get(); | ||
1346 | return v ? v->type : std::string(); | ||
1347 | } | ||
1348 | |||
1349 | soc_word_t variant_ref_t::offset() const | ||
1350 | { | ||
1351 | variant_t *v = get(); | ||
1352 | return v ? v->offset : 0; | ||
1353 | } | ||
1354 | |||
957 | /** | 1355 | /** |
958 | * node_inst_t | 1356 | * node_inst_t |
959 | */ | 1357 | */ |
@@ -965,8 +1363,8 @@ const size_t INST_NO_INDEX = std::numeric_limits<std::size_t>::max(); | |||
965 | 1363 | ||
966 | bool get_inst_addr(range_t& range, size_t index, soc_addr_t& addr) | 1364 | bool get_inst_addr(range_t& range, size_t index, soc_addr_t& addr) |
967 | { | 1365 | { |
968 | if(index < range.first || index >= range.first + range.count) | 1366 | if(index < range.first || index >= range.first + range.size()) |
969 | return false; | 1367 | return false; |
970 | switch(range.type) | 1368 | switch(range.type) |
971 | { | 1369 | { |
972 | case range_t::STRIDE: | 1370 | case range_t::STRIDE: |
@@ -983,6 +1381,9 @@ bool get_inst_addr(range_t& range, size_t index, soc_addr_t& addr) | |||
983 | addr += res; | 1381 | addr += res; |
984 | return true; | 1382 | return true; |
985 | } | 1383 | } |
1384 | case range_t::LIST: | ||
1385 | addr += range.list[index - range.first]; | ||
1386 | return true; | ||
986 | default: | 1387 | default: |
987 | return false; | 1388 | return false; |
988 | } | 1389 | } |
@@ -1030,6 +1431,11 @@ bool node_inst_t::valid() const | |||
1030 | return is_root() || get() != 0; | 1431 | return is_root() || get() != 0; |
1031 | } | 1432 | } |
1032 | 1433 | ||
1434 | void node_inst_t::reset() | ||
1435 | { | ||
1436 | m_node.reset(); | ||
1437 | } | ||
1438 | |||
1033 | node_ref_t node_inst_t::node() const | 1439 | node_ref_t node_inst_t::node() const |
1034 | { | 1440 | { |
1035 | return m_node; | 1441 | return m_node; |
@@ -1045,15 +1451,20 @@ bool node_inst_t::is_root() const | |||
1045 | return m_node.is_root(); | 1451 | return m_node.is_root(); |
1046 | } | 1452 | } |
1047 | 1453 | ||
1048 | node_inst_t node_inst_t::parent() const | 1454 | node_inst_t node_inst_t::parent(unsigned level) const |
1049 | { | 1455 | { |
1456 | if(level > depth()) | ||
1457 | return node_inst_t(); | ||
1050 | std::vector< soc_id_t > ids = m_id_path; | 1458 | std::vector< soc_id_t > ids = m_id_path; |
1051 | std::vector< size_t > indexes = m_index_path; | 1459 | std::vector< size_t > indexes = m_index_path; |
1052 | if(!ids.empty()) | 1460 | ids.resize(depth() - level); |
1053 | ids.pop_back(); | 1461 | indexes.resize(depth() - level); |
1054 | if(!indexes.empty()) | 1462 | return node_inst_t(m_node.parent(level), ids, indexes); |
1055 | indexes.pop_back(); | 1463 | } |
1056 | return node_inst_t(m_node.parent(), ids, indexes); | 1464 | |
1465 | unsigned node_inst_t::depth() const | ||
1466 | { | ||
1467 | return m_id_path.size(); | ||
1057 | } | 1468 | } |
1058 | 1469 | ||
1059 | instance_t *node_inst_t::get() const | 1470 | instance_t *node_inst_t::get() const |
@@ -1069,7 +1480,7 @@ instance_t *node_inst_t::get() const | |||
1069 | 1480 | ||
1070 | soc_addr_t node_inst_t::addr() const | 1481 | soc_addr_t node_inst_t::addr() const |
1071 | { | 1482 | { |
1072 | if(is_root()) | 1483 | if(!valid() || is_root()) |
1073 | return 0; | 1484 | return 0; |
1074 | soc_addr_t addr = parent().addr(); | 1485 | soc_addr_t addr = parent().addr(); |
1075 | if(!get_inst_addr(get(), m_index_path.back(), addr)) | 1486 | if(!get_inst_addr(get(), m_index_path.back(), addr)) |
@@ -1100,7 +1511,7 @@ node_inst_t node_inst_t::child(const std::string& name, size_t index) const | |||
1100 | std::vector< soc_id_t > ids = m_id_path; | 1511 | std::vector< soc_id_t > ids = m_id_path; |
1101 | std::vector< size_t > indexes = m_index_path; | 1512 | std::vector< size_t > indexes = m_index_path; |
1102 | ids.push_back(node.instance[j].id); | 1513 | ids.push_back(node.instance[j].id); |
1103 | ids.push_back(index); | 1514 | indexes.push_back(index); |
1104 | return node_inst_t(child_node, ids, indexes); | 1515 | return node_inst_t(child_node, ids, indexes); |
1105 | } | 1516 | } |
1106 | child_node.m_path.pop_back(); | 1517 | child_node.m_path.pop_back(); |
@@ -1133,7 +1544,7 @@ std::vector< node_inst_t > node_inst_t::children() const | |||
1133 | i_path.pop_back(); | 1544 | i_path.pop_back(); |
1134 | break; | 1545 | break; |
1135 | case instance_t::RANGE: | 1546 | case instance_t::RANGE: |
1136 | for(size_t i = 0; i < inst.range.count; i++) | 1547 | for(size_t i = 0; i < inst.range.size(); i++) |
1137 | { | 1548 | { |
1138 | i_path.push_back(inst.range.first + i); | 1549 | i_path.push_back(inst.range.first + i); |
1139 | list.push_back(node_inst_t(child_node, n_path, i_path)); | 1550 | list.push_back(node_inst_t(child_node, n_path, i_path)); |