diff options
Diffstat (limited to 'utils/regtools/lib/soc_desc.cpp')
-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)); |