1
0
Fork 0
forked from len0rd/rockbox

regtools: fix normalization procedure

The code was not updated when I added support for list and other stuff, and thus
it did not properly sort by addresses.

Change-Id: Iaed0717b607beedfb2856c020c2a760e7a5667c5
This commit is contained in:
Amaury Pouly 2017-01-23 16:07:41 +01:00
parent 28bf763373
commit 6ef3f7c13b

View file

@ -570,20 +570,54 @@ namespace
struct soc_sorter
{
/* returns the first (lowest) address of an instance */
/* returns the lowest address of an instance, or 0 if none
* and 0xffffffff if cannot evaluate */
soc_addr_t first_addr(const instance_t& inst) const
{
if(inst.type == instance_t::SINGLE)
return inst.addr;
/* sanity check */
if(inst.type != instance_t::RANGE)
{
printf("Warning: unknown instance type %d\n", inst.type);
return 0;
}
if(inst.range.type == range_t::STRIDE)
return inst.range.base;
soc_word_t res;
return inst.range.base; /* assume positive stride */
if(inst.range.type == range_t::LIST)
{
soc_addr_t min = 0xffffffff;
for(size_t i = 0; i < inst.range.list.size(); i++)
if(inst.range.list[i] < min)
min = inst.range.list[i];
return min;
}
/* sanity check */
if(inst.range.type != range_t::FORMULA)
{
printf("Warning: unknown range type %d\n", inst.range.type);
return 0;
}
soc_addr_t min = 0xffffffff;
std::map< std::string, soc_word_t > vars;
for(size_t i = 0; i < inst.range.count; i++)
{
soc_word_t res;
vars[inst.range.variable] = inst.range.first;
error_context_t ctx;
if(!evaluate_formula(inst.range.formula, vars, res, "", ctx))
return 0xffffffff;
return res;
if(evaluate_formula(inst.range.formula, vars, res, "", ctx) && res < min)
min = res;
}
return min;
}
/* return smallest address among all instances */
soc_addr_t first_addr(const node_t& node) const
{
soc_addr_t min = 0xffffffff;
for(size_t i = 0; i < node.instance.size(); i++)
min = std::min(min, first_addr(node.instance[i]));
return min;
}
/* sort instances by first address */
@ -596,23 +630,30 @@ struct soc_sorter
* any instance if instances are sorted) */
bool operator()(const node_t& a, const node_t& b) const
{
/* borderline cases: no instances is lower than with instances */
if(a.instance.size() == 0)
return b.instance.size() > 0;
if(b.instance.size() == 0)
return false;
return first_addr(a.instance[0]) < first_addr(b.instance[0]);
soc_addr_t addr_a = first_addr(a);
soc_addr_t addr_b = first_addr(b);
/* It may happen that two nodes have the same first instance address,
* for example if one logically splits a block into two blocks with
* the same base. In this case, sort by name */
if(addr_a == addr_b)
return a.name < b.name;
return addr_a < addr_b;
}
/* sort fields by decreasing position */
bool operator()(const field_t& a, const field_t& b) const
{
/* in the unlikely case where two fields have the same position, use name */
if(a.pos == b.pos)
return a.name < b.name;
return a.pos > b.pos;
}
/* sort enum values by value */
/* sort enum values by value, then by name */
bool operator()(const enum_t& a, const enum_t& b) const
{
if(a.value == b.value)
return a.name < b.name;
return a.value < b.value;
}
};
@ -639,7 +680,7 @@ void normalize(node_t& node)
std::sort(node.instance.begin(), node.instance.end(), soc_sorter());
}
}
} /* namespace */
void normalize(soc_t& soc)
{