summaryrefslogtreecommitdiff
path: root/utils/regtools/lib/soc_desc.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'utils/regtools/lib/soc_desc.cpp')
-rw-r--r--utils/regtools/lib/soc_desc.cpp73
1 files changed, 57 insertions, 16 deletions
diff --git a/utils/regtools/lib/soc_desc.cpp b/utils/regtools/lib/soc_desc.cpp
index ef8aeb5a17..1cfbdac1f4 100644
--- a/utils/regtools/lib/soc_desc.cpp
+++ b/utils/regtools/lib/soc_desc.cpp
@@ -570,20 +570,54 @@ namespace
570 570
571struct soc_sorter 571struct soc_sorter
572{ 572{
573 /* returns the first (lowest) address of an instance */ 573 /* returns the lowest address of an instance, or 0 if none
574 * and 0xffffffff if cannot evaluate */
574 soc_addr_t first_addr(const instance_t& inst) const 575 soc_addr_t first_addr(const instance_t& inst) const
575 { 576 {
576 if(inst.type == instance_t::SINGLE) 577 if(inst.type == instance_t::SINGLE)
577 return inst.addr; 578 return inst.addr;
579 /* sanity check */
580 if(inst.type != instance_t::RANGE)
581 {
582 printf("Warning: unknown instance type %d\n", inst.type);
583 return 0;
584 }
578 if(inst.range.type == range_t::STRIDE) 585 if(inst.range.type == range_t::STRIDE)
579 return inst.range.base; 586 return inst.range.base; /* assume positive stride */
580 soc_word_t res; 587 if(inst.range.type == range_t::LIST)
588 {
589 soc_addr_t min = 0xffffffff;
590 for(size_t i = 0; i < inst.range.list.size(); i++)
591 if(inst.range.list[i] < min)
592 min = inst.range.list[i];
593 return min;
594 }
595 /* sanity check */
596 if(inst.range.type != range_t::FORMULA)
597 {
598 printf("Warning: unknown range type %d\n", inst.range.type);
599 return 0;
600 }
601 soc_addr_t min = 0xffffffff;
581 std::map< std::string, soc_word_t > vars; 602 std::map< std::string, soc_word_t > vars;
582 vars[inst.range.variable] = inst.range.first; 603 for(size_t i = 0; i < inst.range.count; i++)
583 error_context_t ctx; 604 {
584 if(!evaluate_formula(inst.range.formula, vars, res, "", ctx)) 605 soc_word_t res;
585 return 0xffffffff; 606 vars[inst.range.variable] = inst.range.first;
586 return res; 607 error_context_t ctx;
608 if(evaluate_formula(inst.range.formula, vars, res, "", ctx) && res < min)
609 min = res;
610 }
611 return min;
612 }
613
614 /* return smallest address among all instances */
615 soc_addr_t first_addr(const node_t& node) const
616 {
617 soc_addr_t min = 0xffffffff;
618 for(size_t i = 0; i < node.instance.size(); i++)
619 min = std::min(min, first_addr(node.instance[i]));
620 return min;
587 } 621 }
588 622
589 /* sort instances by first address */ 623 /* sort instances by first address */
@@ -596,23 +630,30 @@ struct soc_sorter
596 * any instance if instances are sorted) */ 630 * any instance if instances are sorted) */
597 bool operator()(const node_t& a, const node_t& b) const 631 bool operator()(const node_t& a, const node_t& b) const
598 { 632 {
599 /* borderline cases: no instances is lower than with instances */ 633 soc_addr_t addr_a = first_addr(a);
600 if(a.instance.size() == 0) 634 soc_addr_t addr_b = first_addr(b);
601 return b.instance.size() > 0; 635 /* It may happen that two nodes have the same first instance address,
602 if(b.instance.size() == 0) 636 * for example if one logically splits a block into two blocks with
603 return false; 637 * the same base. In this case, sort by name */
604 return first_addr(a.instance[0]) < first_addr(b.instance[0]); 638 if(addr_a == addr_b)
639 return a.name < b.name;
640 return addr_a < addr_b;
605 } 641 }
606 642
607 /* sort fields by decreasing position */ 643 /* sort fields by decreasing position */
608 bool operator()(const field_t& a, const field_t& b) const 644 bool operator()(const field_t& a, const field_t& b) const
609 { 645 {
646 /* in the unlikely case where two fields have the same position, use name */
647 if(a.pos == b.pos)
648 return a.name < b.name;
610 return a.pos > b.pos; 649 return a.pos > b.pos;
611 } 650 }
612 651
613 /* sort enum values by value */ 652 /* sort enum values by value, then by name */
614 bool operator()(const enum_t& a, const enum_t& b) const 653 bool operator()(const enum_t& a, const enum_t& b) const
615 { 654 {
655 if(a.value == b.value)
656 return a.name < b.name;
616 return a.value < b.value; 657 return a.value < b.value;
617 } 658 }
618}; 659};
@@ -639,7 +680,7 @@ void normalize(node_t& node)
639 std::sort(node.instance.begin(), node.instance.end(), soc_sorter()); 680 std::sort(node.instance.begin(), node.instance.end(), soc_sorter());
640} 681}
641 682
642} 683} /* namespace */
643 684
644void normalize(soc_t& soc) 685void normalize(soc_t& soc)
645{ 686{