diff --git a/vhdlpp/expression.h b/vhdlpp/expression.h index 2cf89b78c..df1b9bf81 100644 --- a/vhdlpp/expression.h +++ b/vhdlpp/expression.h @@ -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); diff --git a/vhdlpp/expression_elaborate.cc b/vhdlpp/expression_elaborate.cc index a53b7d23c..1987be699 100644 --- a/vhdlpp/expression_elaborate.cc +++ b/vhdlpp/expression_elaborate.cc @@ -56,6 +56,10 @@ const VType* Expression::fit_type(Entity*ent, Architecture*arc, const VTypeArray const VType*ExpName::elaborate_adjust_type_with_range_(Entity*, Architecture*arc, const VType*type) { + // Unfold typedefs + while (const VTypeDef*tdef = dynamic_cast(type)) { + type = tdef->peek_definition(); + } if (const VTypeArray*array = dynamic_cast(type)) { if (index_ && !lsb_) { @@ -411,6 +415,9 @@ int ExpAggregate::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype if (const VTypeArray*larray = dynamic_cast(ltype)) { return elaborate_expr_array_(ent, arc, larray); } + else if(const VTypeRecord*lrecord = dynamic_cast(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 +483,46 @@ 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()); + choice_element tmp; + int idx; + + // 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(&tmp); + choice_t*ch = tmp.choice; + + ivl_assert(*this, !ch->others()); + ivl_assert(*this, !tmp.alias_flag); + + // Get the appropriate type for a field + const ExpName*field = dynamic_cast(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, &idx); + + aggregate_[idx] = tmp; + 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) { diff --git a/vhdlpp/expression_emit.cc b/vhdlpp/expression_emit.cc index 63bde19e1..ac42aa94a 100644 --- a/vhdlpp/expression_emit.cc +++ b/vhdlpp/expression_emit.cc @@ -95,6 +95,8 @@ int ExpAggregate::emit(ostream&out, Entity*ent, Architecture*arc) if (const VTypeArray*atype = dynamic_cast (use_type)) return emit_array_(out, ent, arc, atype); + else if (const VTypeRecord*arecord = dynamic_cast (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,34 @@ 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*) +{ + 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*name = aggregate_[idx].choice->simple_expression(false); + //ivl_assert(*this, name); + Expression*val = aggregate_[idx].expr; + ivl_assert(*this, val); + + if(idx != 0) + out << ","; + + //errors += name->emit(out, ent, arc); + //out << ": "; + errors += val->emit(out, ent, arc); + } + + out << "}"; + + return errors; +} + int ExpAttribute::emit(ostream&out, Entity*ent, Architecture*arc) { int errors = 0; diff --git a/vhdlpp/vsignal.cc b/vhdlpp/vsignal.cc index c9d77c56e..e8bc87a35 100644 --- a/vhdlpp/vsignal.cc +++ b/vhdlpp/vsignal.cc @@ -37,21 +37,7 @@ SigVarBase::~SigVarBase() void SigVarBase::elaborate_init_expr(Entity*ent, Architecture*arc) { if(init_expr_) { - // convert the initializing string to bitstring if applicable - const ExpString*string = dynamic_cast(init_expr_); - if(string) { - const std::vector& val = string->get_value(); - char buf[val.size() + 1]; - std::copy(val.begin(), val.end(), buf); - buf[val.size()] = 0; - - ExpBitstring*bitstring = new ExpBitstring(buf); - delete init_expr_; - init_expr_ = bitstring; - } - else { init_expr_->elaborate_expr(ent, arc, peek_type()); - } } } diff --git a/vhdlpp/vtype.cc b/vhdlpp/vtype.cc index 208482877..a7f9233aa 100644 --- a/vhdlpp/vtype.cc +++ b/vhdlpp/vtype.cc @@ -205,13 +205,17 @@ void VTypeRecord::show(ostream&out) const write_to_stream(out); } -const VTypeRecord::element_t* VTypeRecord::element_by_name(perm_string name) const +const VTypeRecord::element_t* VTypeRecord::element_by_name(perm_string name, int*index) const { for (vector::const_iterator cur = elements_.begin() ; cur != elements_.end() ; ++cur) { element_t*curp = *cur; - if (curp->peek_name() == name) + if (curp->peek_name() == name) { + if (index) + *index = std::distance(elements_.begin(), cur); + return curp; + } } return 0; diff --git a/vhdlpp/vtype.h b/vhdlpp/vtype.h index 09a44231d..247af6b51 100644 --- a/vhdlpp/vtype.h +++ b/vhdlpp/vtype.h @@ -288,8 +288,7 @@ class VTypeRecord : public VType { int emit_def(std::ostream&out, perm_string name) const; bool can_be_packed() const { return true; } - - const element_t* element_by_name(perm_string name) const; + const element_t* element_by_name(perm_string name, int*index = NULL) const; private: std::vector elements_;