vhdlpp: Unified Expression::evaluate() method.
This commit is contained in:
parent
23633c498f
commit
2c010d34bb
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}*/
|
||||
|
|
|
|||
Loading…
Reference in New Issue