vhdlpp: Unified Expression::evaluate() method.

This commit is contained in:
Maciej Suminski 2015-12-14 14:36:23 +01:00
parent 23633c498f
commit 2c010d34bb
5 changed files with 77 additions and 148 deletions

View File

@ -88,14 +88,14 @@ ExpBinary::~ExpBinary()
delete operand2_;
}
bool ExpBinary::eval_operand1(ScopeBase*scope, int64_t&val) const
bool ExpBinary::eval_operand1(Entity*ent, ScopeBase*scope, int64_t&val) const
{
return operand1_->evaluate(scope, val);
return operand1_->evaluate(ent, scope, val);
}
bool ExpBinary::eval_operand2(ScopeBase*scope, int64_t&val) const
bool ExpBinary::eval_operand2(Entity*ent, ScopeBase*scope, int64_t&val) const
{
return operand2_->evaluate(scope, val);
return operand2_->evaluate(ent, scope, val);
}
void ExpBinary::visit(ExprVisitor& func)
@ -493,7 +493,7 @@ ExpInteger::~ExpInteger()
{
}
bool ExpInteger::evaluate(ScopeBase*, int64_t&val) const
bool ExpInteger::evaluate(Entity*, ScopeBase*, int64_t&val) const
{
val = value_;
return true;

View File

@ -107,8 +107,8 @@ class Expression : public LineInfo {
// to constant literal values. Return true and set the val
// argument if the evaluation works, or return false if it
// cannot be done.
virtual bool evaluate(ScopeBase*scope, int64_t&val) const;
virtual bool evaluate(Entity*ent, ScopeBase*scope, int64_t&val) const;
virtual bool evaluate(Entity*, ScopeBase*, int64_t&) const { return false; }
bool evaluate(ScopeBase*scope, int64_t&val) const { return evaluate(NULL, scope, val); }
// The symbolic compare returns true if the two expressions
// are equal without actually calculating the value.
@ -205,8 +205,8 @@ class ExpBinary : public Expression {
int emit_operand1(ostream&out, Entity*ent, ScopeBase*scope);
int emit_operand2(ostream&out, Entity*ent, ScopeBase*scope);
bool eval_operand1(ScopeBase*scope, int64_t&val) const;
bool eval_operand2(ScopeBase*scope, int64_t&val) const;
bool eval_operand1(Entity*ent, ScopeBase*scope, int64_t&val) const;
bool eval_operand2(Entity*ent, ScopeBase*scope, int64_t&val) const;
inline void write_to_stream_operand1(std::ostream&out) const
{ operand1_->write_to_stream(out); }
@ -343,7 +343,7 @@ class ExpArithmetic : public ExpBinary {
int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype);
void write_to_stream(std::ostream&fd) const;
int emit(ostream&out, Entity*ent, ScopeBase*scope);
virtual bool evaluate(ScopeBase*scope, int64_t&val) const;
virtual bool evaluate(Entity*ent, ScopeBase*scope, int64_t&val) const;
void dump(ostream&out, int indent = 0) const;
private:
@ -369,7 +369,6 @@ class ExpAttribute : public Expression {
void write_to_stream(std::ostream&fd) const;
int emit(ostream&out, Entity*ent, ScopeBase*scope);
// Some attributes can be evaluated at compile time
bool evaluate(ScopeBase*scope, int64_t&val) const;
bool evaluate(Entity*ent, ScopeBase*scope, int64_t&val) const;
void dump(ostream&out, int indent = 0) const;
void visit(ExprVisitor& func);
@ -440,7 +439,6 @@ class ExpConcat : public Expression {
int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype);
void write_to_stream(std::ostream&fd) const;
int emit(ostream&out, Entity*ent, ScopeBase*scope);
virtual bool evaluate(ScopeBase*scope, int64_t&val) const;
bool is_primary(void) const;
void dump(ostream&out, int indent = 0) const;
void visit(ExprVisitor& func);
@ -583,7 +581,7 @@ class ExpInteger : public Expression {
int emit(ostream&out, Entity*ent, ScopeBase*scope);
int emit_package(std::ostream&out);
bool is_primary(void) const { return true; }
bool evaluate(ScopeBase*scope, int64_t&val) const;
bool evaluate(Entity*ent, ScopeBase*scope, int64_t&val) const;
void dump(ostream&out, int indent = 0) const;
virtual ostream& dump_inline(ostream&out) const;
@ -665,7 +663,6 @@ class ExpName : public Expression {
void write_to_stream(std::ostream&fd) const;
int emit(ostream&out, Entity*ent, ScopeBase*scope);
bool is_primary(void) const;
bool evaluate(ScopeBase*scope, int64_t&val) const;
bool evaluate(Entity*ent, ScopeBase*scope, int64_t&val) const;
bool symbolic_compare(const Expression*that) const;
void dump(ostream&out, int indent = 0) const;
@ -773,7 +770,7 @@ class ExpShift : public ExpBinary {
int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype);
void write_to_stream(std::ostream&fd) const;
int emit(ostream&out, Entity*ent, ScopeBase*scope);
virtual bool evaluate(ScopeBase*scope, int64_t&val) const;
bool evaluate(Entity*ent, ScopeBase*scope, int64_t&val) const;
void dump(ostream&out, int indent = 0) const;
private:
@ -891,7 +888,6 @@ class ExpTime : public Expression {
int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype);
void write_to_stream(std::ostream&) const;
int emit(ostream&out, Entity*ent, ScopeBase*scope);
//bool evaluate(ScopeBase*scope, int64_t&val) const;
//bool evaluate(Entity*ent, ScopeBase*scope, int64_t&val) const;
void dump(ostream&out, int indent = 0) const;

View File

@ -57,7 +57,8 @@ const VType* Expression::fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*
return res;
}
const VType*ExpName::elaborate_adjust_type_with_range_(Entity*, ScopeBase*scope, const VType*type)
const VType*ExpName::elaborate_adjust_type_with_range_(Entity*ent, ScopeBase*scope,
const VType*type)
{
// Unfold typedefs
while (const VTypeDef*tdef = dynamic_cast<const VTypeDef*>(type)) {
@ -76,9 +77,9 @@ const VType*ExpName::elaborate_adjust_type_with_range_(Entity*, ScopeBase*scope,
int64_t use_msb, use_lsb;
bool flag;
flag = index_->evaluate(scope, use_msb);
flag = index_->evaluate(ent, scope, use_msb);
ivl_assert(*this, flag);
flag = lsb_->evaluate(scope, use_lsb);
flag = lsb_->evaluate(ent, scope, use_lsb);
ivl_assert(*this, flag);
type = new VTypeArray(array->element_type(), use_msb, use_lsb);

View File

@ -337,7 +337,7 @@ int ExpAttribute::emit(ostream&out, Entity*ent, ScopeBase*scope)
// Try to evaluate first
int64_t val;
if(evaluate(scope, val)) {
if(evaluate(ent, scope, val)) {
out << val;
return 0;
}

View File

@ -25,26 +25,16 @@
# include <limits>
# include <cmath>
bool Expression::evaluate(ScopeBase*, int64_t&) const
{
return false;
}
bool Expression::evaluate(Entity*, ScopeBase*scope, int64_t&val) const
{
return evaluate(scope, val);
}
bool ExpArithmetic::evaluate(ScopeBase*scope, int64_t&val) const
bool ExpArithmetic::evaluate(Entity*ent, ScopeBase*scope, int64_t&val) const
{
int64_t val1, val2;
bool rc;
rc = eval_operand1(scope, val1);
rc = eval_operand1(ent, scope, val1);
if (rc == false)
return false;
rc = eval_operand2(scope, val2);
rc = eval_operand2(ent, scope, val2);
if (rc == false)
return false;
@ -83,151 +73,97 @@ bool ExpArithmetic::evaluate(ScopeBase*scope, int64_t&val) const
return true;
}
bool ExpAttribute::evaluate(ScopeBase*scope, int64_t&val) const
{
/* Special Case: The array attributes can sometimes 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" || name_ == "right" || name_ == "left") {
const VType*base_type = base_->peek_type();
if(!base_type) {
const ExpName*name = NULL;
if(scope && (name = dynamic_cast<const ExpName*>(base_))) {
const perm_string& n = name->peek_name();
if(const Variable*var = scope->find_variable(n))
base_type = var->peek_type();
else if(const Signal*sig = scope->find_signal(n))
base_type = sig->peek_type();
else if(const InterfacePort*port = scope->find_param(n))
base_type = port->type;
}
}
if(!base_type)
return false; // I tried really hard, sorry
const VTypeArray*arr = dynamic_cast<const VTypeArray*>(base_type);
if (arr == 0) {
cerr << endl << get_fileline() << ": error: "
<< "Cannot apply the '" << name_ << " attribute to non-array objects"
<< endl;
ivl_assert(*this, false);
return false;
}
if(name_ == "length") {
int64_t size = arr->get_width(scope);
if(size > 0)
val = size;
else
return false;
} else if(name_ == "left") {
arr->dimension(0).msb()->evaluate(scope, val);
} else if(name_ == "right") {
arr->dimension(0).lsb()->evaluate(scope, val);
} else ivl_assert(*this, false);
return true;
}
return false;
}
bool ExpAttribute::evaluate(Entity*ent, ScopeBase*scope, int64_t&val) const
{
if (!ent || !scope) { // it's impossible to evaluate, probably it is inside a subprogram
return false;
}
const VType*base_type = base_->peek_type();
if (base_type == NULL)
base_type = base_->probe_type(ent, scope);
if (base_type == NULL)
return false;
if (name_ == "left" || name_ == "right") {
const VType*base_type = base_->peek_type();
if (base_type == 0)
base_type = base_->probe_type(ent, scope);
ivl_assert(*this, base_type);
const VTypeArray*arr = dynamic_cast<const VTypeArray*>(base_type);
if (arr == 0) {
if (arr == NULL) {
cerr << endl << get_fileline() << ": error: "
<< "Cannot apply the '" << name_
<< " attribute to non-array objects" << endl;
ivl_assert(*this, false);
return false;
}
ivl_assert(*this, arr->dimensions() == 1);
if(name_ == "left")
arr->dimension(0).msb()->evaluate(ent, scope, val);
else // "right"
arr->dimension(0).lsb()->evaluate(ent, scope, val);
if (arr->dimensions() != 1) {
cerr << endl << get_fileline() << ": error: "
<< "Cannot apply the '" << name_
<< " attribute to multidimensional arrays" << endl;
return false;
}
return true;
if (arr->dimension(0).is_box())
return false;
if (name_ == "left") {
return arr->dimension(0).msb()->evaluate(ent, scope, val);
} else if (name_ == "right") {
return arr->dimension(0).lsb()->evaluate(ent, scope, val);
} else {
ivl_assert(*this, false);
}
}
return evaluate(scope, val);
}
else if (name_ == "length") {
int64_t size = base_type->get_width(scope);
if (size > 0) {
val = size;
return true;
}
}
/*
* I don't yet know how to evaluate concatenations. It is not likely
* to come up anyhow.
*/
bool ExpConcat::evaluate(ScopeBase*, int64_t&) const
{
return false;
}
bool ExpName::evaluate(ScopeBase*scope, int64_t&val) const
{
const VType*type;
Expression*exp;
if (prefix_.get()) {
cerr << get_fileline() << ": sorry: I don't know how to evaluate ExpName prefix parts." << endl;
return false;
}
if (!scope)
return false;
if (!scope->find_constant(name_, type, exp))
return false;
return exp->evaluate(scope, val);
}
bool ExpName::evaluate(Entity*ent, ScopeBase*scope, int64_t&val) const
{
if (prefix_.get()) {
cerr << get_fileline() << ": sorry: I don't know how to evaluate ExpName prefix parts." << endl;
return false;
cerr << get_fileline() << ": sorry: I don't know how to evaluate "
<< "ExpName prefix parts." << endl;
return false;
}
const InterfacePort*gen = ent->find_generic(name_);
if (gen) {
cerr << get_fileline() << ": sorry: I don't necessarily handle generic overrides." << endl;
if (ent) {
const InterfacePort*gen = ent->find_generic(name_);
if (gen) {
cerr << get_fileline() << ": sorry: I don't necessarily "
<< "handle generic overrides." << endl;
// Evaluate the default expression and use that.
if (gen->expr)
return gen->expr->evaluate(ent, scope, val);
// Evaluate the default expression and use that.
if (gen->expr)
return gen->expr->evaluate(ent, scope, val);
}
}
return evaluate(scope, val);
if (scope) {
const VType*type;
Expression*exp;
if (scope->find_constant(name_, type, exp))
return exp->evaluate(ent, scope, val);
}
return false;
}
bool ExpShift::evaluate(ScopeBase*scope, int64_t&val) const
bool ExpShift::evaluate(Entity*ent, ScopeBase*scope, int64_t&val) const
{
int64_t val1, val2;
bool rc;
rc = eval_operand1(scope, val1);
rc = eval_operand1(ent, scope, val1);
if (rc == false)
return false;
rc = eval_operand2(scope, val2);
rc = eval_operand2(ent, scope, val2);
if (rc == false)
return false;
@ -252,7 +188,7 @@ bool ExpShift::evaluate(ScopeBase*scope, int64_t&val) const
return true;
}
/*bool ExpTime::evaluate(ScopeBase*, int64_t&val) const
/*bool ExpTime::evaluate(Entity*, ScopeBase*, int64_t&val) const
{
double v = to_fs();
@ -265,8 +201,4 @@ bool ExpShift::evaluate(ScopeBase*scope, int64_t&val) const
val = v;
return true;
}
bool ExpTime::evaluate(Entity*, ScopeBase*, int64_t&val) const
{
return evaluate(NULL, val);
}*/