diff --git a/vhdlpp/architec_elaborate.cc b/vhdlpp/architec_elaborate.cc index 23dc837f2..812fc1f2f 100644 --- a/vhdlpp/architec_elaborate.cc +++ b/vhdlpp/architec_elaborate.cc @@ -28,6 +28,19 @@ int Architecture::elaborate(Entity*entity) { int errors = 0; + // Constant assignments in the architecture get their types + // from the constant declaration itself. Elaborate the value + // expression with the declared type. + + for (map::iterator cur = old_constants_.begin() + ; cur != old_constants_.end() ; ++cur) { + cur->second->val->elaborate_expr(entity, this, cur->second->typ); + } + for (map::iterator cur = new_constants_.begin() + ; cur != new_constants_.end() ; ++cur) { + cur->second->val->elaborate_expr(entity, this, cur->second->typ); + } + for (list::iterator cur = statements_.begin() ; cur != statements_.end() ; ++cur) { @@ -35,7 +48,12 @@ int Architecture::elaborate(Entity*entity) errors += cur_errors; } - cerr << errors << " errors in " << name_ << " architecture of " << entity->get_name() << "." << endl; + if (errors > 0) { + cerr << errors << " errors in " + << name_ << " architecture of " + << entity->get_name() << "." << endl; + } + return errors; } diff --git a/vhdlpp/expression.h b/vhdlpp/expression.h index 5004e2ce6..4736a5d06 100644 --- a/vhdlpp/expression.h +++ b/vhdlpp/expression.h @@ -491,6 +491,8 @@ class ExpName : public Expression { const VType* probe_prefix_type_(Entity*ent, Architecture*arc) const; const VType* probe_prefixed_type_(Entity*ent, Architecture*arc) const; + int emit_as_prefix_(ostream&out, Entity*ent, Architecture*arc); + private: std::auto_ptr prefix_; perm_string name_; diff --git a/vhdlpp/expression_elaborate.cc b/vhdlpp/expression_elaborate.cc index 8e3d4588d..05c8fd4e3 100644 --- a/vhdlpp/expression_elaborate.cc +++ b/vhdlpp/expression_elaborate.cc @@ -306,8 +306,8 @@ int ExpAggregate::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype /* * Elaboration of array aggregates is elaboration of the element - * expressions using the element type as the ltype for the - * subexpression. + * expressions (the elements_ member) using the element type as the + * ltype for the subexpression. */ int ExpAggregate::elaborate_expr_array_(Entity*ent, Architecture*arc, const VTypeArray*ltype) { @@ -315,22 +315,42 @@ int ExpAggregate::elaborate_expr_array_(Entity*ent, Architecture*arc, const VTyp int errors = 0; size_t choice_count = 0; + // Figure out how many total elements we have here. Note that + // each parsed element may be bound to multiple choices, so + // account for that. for (size_t edx = 0 ; edx < elements_.size() ; edx += 1) { element_t*ecur = elements_[edx]; - choice_count += ecur->count_choices(); + if (ecur->count_choices() == 0) + choice_count += 1; + else + choice_count += ecur->count_choices(); } aggregate_.resize(choice_count); + // Translate the elements_ array to the aggregate_ array. In + // the target array, each expression is attached to a single + // choice. size_t cdx = 0; for (size_t edx = 0 ; edx < elements_.size() ; edx += 1) { element_t*ecur = elements_[edx]; - ecur->map_choices(&aggregate_[cdx]); - cdx += ecur->count_choices(); + if (ecur->count_choices() == 0) { + // positional associations have no "choice" + // associated with them. + aggregate_[cdx].choice = 0; + aggregate_[cdx].expr = ecur->extract_expression(); + aggregate_[cdx].alias_flag; + cdx += 1; + } else { + ecur->map_choices(&aggregate_[cdx]); + cdx += ecur->count_choices(); + } } ivl_assert(*this, cdx == choice_count); + // 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) { if (aggregate_[idx].alias_flag) continue; @@ -338,7 +358,9 @@ int ExpAggregate::elaborate_expr_array_(Entity*ent, Architecture*arc, const VTyp errors += aggregate_[idx].expr->elaborate_expr(ent, arc, element_type); } + // done with the obsolete elements_ vector. elements_.clear(); + return errors; } diff --git a/vhdlpp/expression_emit.cc b/vhdlpp/expression_emit.cc index 30b66dbfc..371cb3af6 100644 --- a/vhdlpp/expression_emit.cc +++ b/vhdlpp/expression_emit.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 Stephen Williams (steve@icarus.com) + * Copyright (c) 2011-2012 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -70,10 +70,19 @@ int ExpUnary::emit_operand1(ostream&out, Entity*ent, Architecture*arc) int ExpAggregate::emit(ostream&out, Entity*ent, Architecture*arc) { + if (peek_type() == 0) { + out << "/* " << get_fileline() << ": internal error: " + << "Aggregate literal needs well defined type." << endl; + return 1; + } + if (const VTypeArray*atype = dynamic_cast (peek_type())) return emit_array_(out, ent, arc, atype); - return Expression::emit(out, ent, arc); + out << "/* " << get_fileline() << ": internal error: " + << "I don't know how to elaborate aggregate in " << typeid(peek_type()).name() + << " type context. */"; + return 1; } int ExpAggregate::emit_array_(ostream&out, Entity*ent, Architecture*arc, const VTypeArray*atype) @@ -126,27 +135,7 @@ int ExpAggregate::emit_array_(ostream&out, Entity*ent, Architecture*arc, const V const VTypeArray::range_t&rang = atype->dimension(0); assert(! rang.is_box()); - map 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(ent, arc, tmp_val)) { - cerr << tmp->get_fileline() << ": error: Unable to evaluate aggregate choice expression." << endl; - errors += 1; - continue; - } - - element_map[tmp_val] = &aggregate_[idx]; - } - + // Fully calculate the range numbers. int64_t use_msb, use_lsb; bool rc; rc = rang.msb()->evaluate(ent, arc, use_msb); @@ -155,16 +144,68 @@ int ExpAggregate::emit_array_(ostream&out, Entity*ent, Architecture*arc, const V ivl_assert(*this, rc); ivl_assert(*this, use_msb >= use_lsb); + map element_map; + choice_element*element_other = 0; + + bool positional_section = true; + int64_t positional_idx = use_msb; + + for (size_t idx = 0 ; idx < aggregate_.size() ; idx += 1) { + + if (aggregate_[idx].choice == 0) { + // positional association! + if (!positional_section) { + cerr << get_fileline() << ": error: " + << "All positional associations must be before" + << " any named associations." << endl; + errors += 1; + } + element_map[positional_idx] = &aggregate_[idx]; + positional_idx -= 1; + continue; + } + + if (aggregate_[idx].choice->others()) { + ivl_assert(*this, element_other == 0); + element_other = &aggregate_[idx]; + continue; + } + + int64_t tmp_val; + Expression*tmp = aggregate_[idx].choice->simple_expression(false); + + // Named aggregate element. Once we see one of + // these, we can no longer accept positional + // elements so disable further positional + // processing. + positional_section = false; + if (! tmp->evaluate(ent, arc, tmp_val)) { + cerr << tmp->get_fileline() << ": error: " + << "Unable to evaluate aggregate choice expression." << endl; + errors += 1; + continue; + } + + element_map[tmp_val] = &aggregate_[idx]; + } + + // Emit the elements as a concatenation. This works great for + // vectors of bits. We implement VHDL arrays as packed arrays, + // so this should be generally correct. out << "{"; for (int64_t idx = use_msb ; idx >= use_lsb ; idx -= 1) { choice_element*cur = element_map[idx]; if (cur == 0) cur = element_other; - ivl_assert(*this, cur != 0); if (idx < use_msb) out << ", "; - errors += cur->expr->emit(out, ent, arc); + if (cur == 0) { + out << "/* Missing element " << idx << " */"; + errors += 1; + } else { + errors += cur->expr->emit(out, ent, arc); + } } out << "}"; @@ -511,13 +552,25 @@ int ExpLogical::emit(ostream&out, Entity*ent, Architecture*arc) return errors; } +int ExpName::emit_as_prefix_(ostream&out, Entity*ent, Architecture*arc) +{ + int errors = 0; + if (prefix_.get()) { + errors += prefix_->emit_as_prefix_(out, ent, arc); + } + + out << "\\" << name_ << " "; + ivl_assert(*this, index_ == 0); + out << "."; + return errors; +} + int ExpName::emit(ostream&out, Entity*ent, Architecture*arc) { int errors = 0; if (prefix_.get()) { - cerr << get_fileline() << ": sorry: I don't know how to emit ExpName prefix parts." << endl; - errors += 1; + errors += prefix_->emit_as_prefix_(out, ent, arc); } out << "\\" << name_ << " "; diff --git a/vhdlpp/vtype_emit.cc b/vhdlpp/vtype_emit.cc index e6042f0e7..8225bc917 100644 --- a/vhdlpp/vtype_emit.cc +++ b/vhdlpp/vtype_emit.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 Stephen Williams (steve@icarus.com) + * Copyright (c) 2011-2012 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -162,14 +162,24 @@ int VTypeRange::emit_decl(ostream&out, perm_string name, bool reg_flag) const int VTypeRecord::emit_def(ostream&out, perm_string name) const { int errors = 0; - assert(0); + out << "struct packed {"; + + for (vector::const_iterator cur = elements_.begin() + ; cur != elements_.end() ; ++cur) { + perm_string element_name = (*cur)->peek_name(); + const VType*element_type = (*cur)->peek_type(); + element_type->emit_def(out, element_name); + out << "; "; + } + + out << "} "; return errors; } int VTypeRecord::emit_decl(ostream&out, perm_string name, bool reg_flag) const { int errors = 0; - assert(0); + errors += emit_def(out, name); return errors; }