Handle vhdh array aggregate expressions.

Support the more general case of explicit element expressions
defined at various index positions, mixed with "others" records.
This commit is contained in:
Stephen Williams 2011-09-11 17:08:22 -07:00
parent 3497e2e663
commit 1d02f89a09
2 changed files with 51 additions and 3 deletions

View File

@ -217,6 +217,7 @@ class ExpAggregate : public Expression {
private: private:
int elaborate_expr_array_(Entity*ent, Architecture*arc, const VTypeArray*ltype); int elaborate_expr_array_(Entity*ent, Architecture*arc, const VTypeArray*ltype);
int emit_array_(ostream&out, Entity*ent, Architecture*arc, const VTypeArray*ltype);
private: private:
// This is the elements as directly parsed. // This is the elements as directly parsed.

View File

@ -19,9 +19,11 @@
# include "expression.h" # include "expression.h"
# include "vtype.h" # include "vtype.h"
# include "architec.h"
# include <typeinfo> # include <typeinfo>
# include <iostream> # include <iostream>
# include <cstdlib> # include <cstdlib>
# include "ivl_assert.h"
# include <cassert> # include <cassert>
using namespace std; using namespace std;
@ -67,13 +69,19 @@ int ExpUnary::emit_operand1(ostream&out, Entity*ent, Architecture*arc)
} }
int ExpAggregate::emit(ostream&out, Entity*ent, Architecture*arc) int ExpAggregate::emit(ostream&out, Entity*ent, Architecture*arc)
{
if (const VTypeArray*atype = dynamic_cast<const VTypeArray*> (peek_type()))
return emit_array_(out, ent, arc, atype);
return Expression::emit(out, ent, arc);
}
int ExpAggregate::emit_array_(ostream&out, Entity*ent, Architecture*arc, const VTypeArray*atype)
{ {
int errors = 0; int errors = 0;
// Special case: The aggregate is a single "others" item. // Special case: The aggregate is a single "others" item.
if (aggregate_.size() == 1 && aggregate_[0].choice->others()) { if (aggregate_.size() == 1 && aggregate_[0].choice->others()) {
const VTypeArray*atype = dynamic_cast<const VTypeArray*> (peek_type());
assert(atype);
assert(atype->dimensions() == 1); assert(atype->dimensions() == 1);
const VTypeArray::range_t&rang = atype->dimension(0); const VTypeArray::range_t&rang = atype->dimension(0);
@ -87,7 +95,46 @@ int ExpAggregate::emit(ostream&out, Entity*ent, Architecture*arc)
return errors; return errors;
} }
return Expression::emit(out, ent, arc); const VTypeArray::range_t&rang = atype->dimension(0);
assert(! rang.is_box());
map<int64_t,choice_element*> element_map;
choice_element*element_other = 0;
for (size_t idx = 0 ; idx < aggregate_.size() ; idx += 1) {
if (aggregate_[idx].choice->others()) {
ivl_assert(*this, element_other == 0);
element_other = &aggregate_[idx];
continue;
}
Expression*tmp = aggregate_[idx].choice->simple_expression(false);
int64_t tmp_val;
if (! tmp->evaluate(arc, tmp_val)) {
cerr << tmp->get_fileline() << ": error: Unable to evaluate aggregate choice expression." << endl;
errors += 1;
continue;
}
element_map[tmp_val] = &aggregate_[idx];
}
ivl_assert(*this, rang.msb() >= rang.lsb());
out << "{";
for (int idx = rang.msb() ; idx >= rang.lsb() ; idx -= 1) {
choice_element*cur = element_map[idx];
if (cur == 0)
cur = element_other;
ivl_assert(*this, cur != 0);
if (idx < rang.msb())
out << ", ";
errors += cur->expr->emit(out, ent, arc);
}
out << "}";
return errors;
} }
int ExpAttribute::emit(ostream&out, Entity*ent, Architecture*arc) int ExpAttribute::emit(ostream&out, Entity*ent, Architecture*arc)