Evaluate VHDL <name>'length attribute at compile time.

This commit is contained in:
Stephen Williams 2011-09-18 17:45:06 -07:00
parent 677a22d353
commit 873a447b5c
2 changed files with 33 additions and 2 deletions

View File

@ -256,6 +256,17 @@ int ExpArithmetic::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltyp
return errors; 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 ExpAttribute::elaborate_expr(Entity*ent, Architecture*arc, const VType*)
{ {
int errors = 0; 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) int ExpName::elaborate_expr(Entity*, Architecture*, const VType*ltype)
{ {
ivl_assert(*this, ltype != 0); ivl_assert(*this, ltype != 0);
set_type(ltype);
return 0; return 0;
} }

View File

@ -148,6 +148,20 @@ int ExpAttribute::emit(ostream&out, Entity*ent, Architecture*arc)
return errors; 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("; out << "$ivl_attribute(";
errors += base_->emit(out, ent, arc); errors += base_->emit(out, ent, arc);
out << ", \"" << name_ << "\")"; out << ", \"" << name_ << "\")";
@ -339,9 +353,14 @@ int ExpFunc::emit(ostream&out, Entity*ent, Architecture*arc)
out << "("; out << "(";
errors += argv_[0]->emit(out, ent, arc); errors += argv_[0]->emit(out, ent, arc);
out << ")"; out << ")";
} else { } else {
cerr << get_fileline() << ": sorry: Don't know how to emit function '" << name_ << "'" << endl; out << "\\" << name_ << " (";
errors += 1; for (size_t idx = 0; idx < argv_.size() ; idx += 1) {
if (idx > 0) out << ", ";
errors += argv_[idx]->emit(out, ent, arc);
}
out << ")";
} }
return errors; return errors;