vhdlpp: Elaboration & emit support for aggregate initializer expressions in records.

This commit is contained in:
Maciej Suminski 2014-09-17 11:24:16 +02:00
parent 9842035d89
commit 54696e0127
3 changed files with 74 additions and 0 deletions

View File

@ -283,7 +283,9 @@ class ExpAggregate : public Expression {
private:
int elaborate_expr_array_(Entity*ent, Architecture*arc, const VTypeArray*ltype);
int elaborate_expr_record_(Entity*ent, Architecture*arc, const VTypeRecord*ltype);
int emit_array_(ostream&out, Entity*ent, Architecture*arc, const VTypeArray*ltype);
int emit_record_(ostream&out, Entity*ent, Architecture*arc, const VTypeRecord*ltype);
private:
// This is the elements as directly parsed.
@ -575,6 +577,7 @@ class ExpName : public Expression {
bool symbolic_compare(const Expression*that) const;
void dump(ostream&out, int indent = 0) const;
const char* name() const;
inline perm_string peek_name() const { return name_; }
void set_range(Expression*msb, Expression*lsb);

View File

@ -411,6 +411,9 @@ int ExpAggregate::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype
if (const VTypeArray*larray = dynamic_cast<const VTypeArray*>(ltype)) {
return elaborate_expr_array_(ent, arc, larray);
}
else if(const VTypeRecord*lrecord = dynamic_cast<const VTypeRecord*>(ltype)) {
return elaborate_expr_record_(ent, arc, lrecord);
}
cerr << get_fileline() << ": internal error: I don't know how to elaborate aggregate expressions. type=" << typeid(*ltype).name() << endl;
return 1;
@ -476,6 +479,48 @@ int ExpAggregate::elaborate_expr_array_(Entity*ent, Architecture*arc, const VTyp
return errors;
}
int ExpAggregate::elaborate_expr_record_(Entity*ent, Architecture*arc, const VTypeRecord*ltype)
{
int errors = 0;
aggregate_.resize(elements_.size());
// Translate the elements_ array to the aggregate_ array. In
// the target array, each expression is attached to a single
// choice.
for (size_t edx = 0 ; edx < elements_.size() ; edx += 1) {
element_t*ecur = elements_[edx];
// it is invalid to have more than one choice in record assignment
ivl_assert(*this, ecur->count_choices() == 1);
ecur->map_choices(&aggregate_[edx]);
}
// Now run through the more convenient mapping and elaborate
// all the expressions that I find.
for (size_t idx = 0 ; idx < aggregate_.size() ; idx += 1) {
ivl_assert(*this, !aggregate_[idx].alias_flag);
choice_t*ch = aggregate_[idx].choice;
ivl_assert(*this, !ch->others());
// Get the appropriate type for a field
const ExpName*field = dynamic_cast<const ExpName*>(ch->simple_expression(false));
ivl_assert(*this, field);
perm_string field_name = field->peek_name();
const VTypeRecord::element_t*el = ltype->element_by_name(field_name);
errors += aggregate_[idx].expr->elaborate_expr(ent, arc, el->peek_type());
}
// done with the obsolete elements_ vector.
elements_.clear();
return errors;
}
void ExpAggregate::element_t::map_choices(ExpAggregate::choice_element*dst)
{
for (size_t idx = 0 ; idx < fields_.size() ; idx += 1) {

View File

@ -95,6 +95,8 @@ int ExpAggregate::emit(ostream&out, Entity*ent, Architecture*arc)
if (const VTypeArray*atype = dynamic_cast<const VTypeArray*> (use_type))
return emit_array_(out, ent, arc, atype);
else if (const VTypeRecord*arecord = dynamic_cast<const VTypeRecord*> (use_type))
return emit_record_(out, ent, arc, arecord);
out << "/* " << get_fileline() << ": internal error: "
<< "I don't know how to elab/emit aggregate in " << typeid(use_type).name()
@ -271,6 +273,30 @@ int ExpAggregate::emit_array_(ostream&out, Entity*ent, Architecture*arc, const V
return errors;
}
int ExpAggregate::emit_record_(ostream&out, Entity*ent, Architecture*arc, const VTypeRecord*ltype)
{
int errors = 0;
out << "{";
for (size_t idx = 0 ; idx < aggregate_.size() ; idx += 1) {
ivl_assert(*this, !aggregate_[idx].choice->others());
ivl_assert(*this, !aggregate_[idx].choice->range_expressions());
Expression*val = aggregate_[idx].expr;
ivl_assert(*this, val);
if(idx != 0)
out << ",";
errors += val->emit(out, ent, arc);
}
out << "}";
return errors;
}
int ExpAttribute::emit(ostream&out, Entity*ent, Architecture*arc)
{
int errors = 0;