diff --git a/vhdlpp/expression_elaborate.cc b/vhdlpp/expression_elaborate.cc index 5b43c0b5e..35d50413f 100644 --- a/vhdlpp/expression_elaborate.cc +++ b/vhdlpp/expression_elaborate.cc @@ -256,6 +256,17 @@ int ExpArithmetic::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltyp return errors; } +const VType* ExpAttribute::probe_type(Entity*ent, Architecture*arc) const +{ + base_->probe_type(ent, arc); + + if (name_ == "length") { + return primitive_INTEGER; + } + + return 0; +} + int ExpAttribute::elaborate_expr(Entity*ent, Architecture*arc, const VType*) { int errors = 0; @@ -377,6 +388,7 @@ const VType* ExpName::probe_type(Entity*ent, Architecture*arc) const int ExpName::elaborate_expr(Entity*, Architecture*, const VType*ltype) { ivl_assert(*this, ltype != 0); + set_type(ltype); return 0; } diff --git a/vhdlpp/expression_emit.cc b/vhdlpp/expression_emit.cc index ddb564729..fcf7a9af0 100644 --- a/vhdlpp/expression_emit.cc +++ b/vhdlpp/expression_emit.cc @@ -148,6 +148,20 @@ int ExpAttribute::emit(ostream&out, Entity*ent, Architecture*arc) return errors; } + /* Special Case: The length attribute can be calculated all + the down to a literal integer at compile time, and all it + needs is the type of the base expression. (The base + expression doesn't even need to be evaluated.) */ + if (name_ == "length") { + int64_t val; + bool rc = evaluate(arc, val); + out << val; + if (rc) + return errors; + else + return errors + 1; + } + out << "$ivl_attribute("; errors += base_->emit(out, ent, arc); out << ", \"" << name_ << "\")"; @@ -339,9 +353,14 @@ int ExpFunc::emit(ostream&out, Entity*ent, Architecture*arc) out << "("; errors += argv_[0]->emit(out, ent, arc); out << ")"; + } else { - cerr << get_fileline() << ": sorry: Don't know how to emit function '" << name_ << "'" << endl; - errors += 1; + out << "\\" << name_ << " ("; + for (size_t idx = 0; idx < argv_.size() ; idx += 1) { + if (idx > 0) out << ", "; + errors += argv_[idx]->emit(out, ent, arc); + } + out << ")"; } return errors;