diff --git a/vhdlpp/expression.cc b/vhdlpp/expression.cc index baa0ce554..52b77439e 100644 --- a/vhdlpp/expression.cc +++ b/vhdlpp/expression.cc @@ -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; diff --git a/vhdlpp/expression.h b/vhdlpp/expression.h index eb83474df..45ba5f9ec 100644 --- a/vhdlpp/expression.h +++ b/vhdlpp/expression.h @@ -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; diff --git a/vhdlpp/expression_elaborate.cc b/vhdlpp/expression_elaborate.cc index de5b9c598..f7b3d055b 100644 --- a/vhdlpp/expression_elaborate.cc +++ b/vhdlpp/expression_elaborate.cc @@ -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(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); diff --git a/vhdlpp/expression_emit.cc b/vhdlpp/expression_emit.cc index 41436a933..1623037cf 100644 --- a/vhdlpp/expression_emit.cc +++ b/vhdlpp/expression_emit.cc @@ -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; } diff --git a/vhdlpp/expression_evaluate.cc b/vhdlpp/expression_evaluate.cc index 0d7ef1634..b88e40032 100644 --- a/vhdlpp/expression_evaluate.cc +++ b/vhdlpp/expression_evaluate.cc @@ -25,26 +25,16 @@ # include # include -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(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(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(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); }*/