diff --git a/eval_tree.cc b/eval_tree.cc index 6f744f452..993025568 100644 --- a/eval_tree.cc +++ b/eval_tree.cc @@ -858,7 +858,7 @@ NetExpr* NetEBDiv::eval_tree(int prune_to_width) eval_expr(right_); if (expr_type() == IVL_VT_REAL) return eval_tree_real_(); - + assert(expr_type() == IVL_VT_LOGIC); NetEConst*lc = dynamic_cast(left_); @@ -1228,6 +1228,12 @@ NetExpr* NetEParam::eval_tree(int prune_to_width) << *this << endl; } + if (solving()) { + cerr << get_fileline() << ": warning: Recursive parameter " + "reference found involving " << *this << "." << endl; + return 0; + } + assert(scope_); perm_string name = (*reference_).first; const NetExpr*expr = (*reference_).second.expr; @@ -1239,35 +1245,35 @@ NetExpr* NetEParam::eval_tree(int prune_to_width) << *this << " cannot be evaluated." << endl; return 0; } -// ivl_assert(*this, expr); - - NetExpr*nexpr = expr->dup_expr(); - assert(nexpr); // If the parameter that I refer to is already evaluated, then // return the constant value. - if (NetEConst*tmp = dynamic_cast(nexpr)) { + if (const NetEConst*tmp = dynamic_cast(expr)) { verinum val = tmp->value(); NetEConstParam*ptmp = new NetEConstParam(scope_, name, val); ptmp->set_line(*this); - delete nexpr; return ptmp; } - if (NetECReal*tmp = dynamic_cast(nexpr)) { + if (const NetECReal*tmp = dynamic_cast(expr)) { verireal val = tmp->value(); NetECRealParam*ptmp = new NetECRealParam(scope_, name, val); ptmp->set_line(*this); - delete nexpr; return ptmp; } // Try to evaluate the expression. If I cannot, then the // expression is not a constant expression and I fail here. + + solving(true); + NetExpr*nexpr = expr->dup_expr(); + assert(nexpr); NetExpr*res = nexpr->eval_tree(); + solving(false); if (res == 0) { - cerr << get_fileline() << ": internal error: Unable to evaluate " - << "parameter " << name << " expression: " + cerr << get_fileline() << ": internal error: Unable to evaluate "; + if (expr_type() == IVL_VT_REAL) cerr << "real "; + cerr << "parameter " << name << " expression: " << *nexpr << endl; delete nexpr; return 0; diff --git a/net_design.cc b/net_design.cc index 84c4a55a1..055e620ed 100644 --- a/net_design.cc +++ b/net_design.cc @@ -341,8 +341,7 @@ void NetScope::evaluate_parameter_logic_(Design*des, param_ref_t cur) eval_expr((*cur).second.msb); if (! eval_as_long(msb, (*cur).second.msb)) { cerr << (*cur).second.expr->get_fileline() - << ": internal error: " - << "unable to evaluate msb expression " + << ": error: Unable to evaluate msb expression " << "for parameter " << (*cur).first << ": " << *(*cur).second.msb << endl; des->errors += 1; @@ -357,8 +356,7 @@ void NetScope::evaluate_parameter_logic_(Design*des, param_ref_t cur) eval_expr((*cur).second.lsb); if (! eval_as_long(lsb, (*cur).second.lsb)) { cerr << (*cur).second.expr->get_fileline() - << ": internal error: " - << "unable to evaluate lsb expression " + << ": error: Unable to evaluate lsb expression " << "for parameter " << (*cur).first << ": " << *(*cur).second.lsb << endl; des->errors += 1; @@ -384,10 +382,10 @@ void NetScope::evaluate_parameter_logic_(Design*des, param_ref_t cur) case IVL_VT_REAL: if (! dynamic_cast(expr)) { cerr << expr->get_fileline() - << ": internal error: " - << "unable to evaluate real parameter value: " - << *expr << endl; + << ": error: Unable to evaluate real parameter " + << (*cur).first << " value: " << *expr << endl; des->errors += 1; + (*cur).second.expr = NULL; return; } break; @@ -396,11 +394,10 @@ void NetScope::evaluate_parameter_logic_(Design*des, param_ref_t cur) case IVL_VT_BOOL: if (! dynamic_cast(expr)) { cerr << expr->get_fileline() - << ": internal error: " - << "unable to evaluate parameter " - << (*cur).first - << " value: " << *expr << endl; + << ": error: Unable to evaluate parameter " + << (*cur).first << " value: " << *expr << endl; des->errors += 1; + (*cur).second.expr = NULL; return; } break; @@ -408,8 +405,9 @@ void NetScope::evaluate_parameter_logic_(Design*des, param_ref_t cur) default: cerr << expr->get_fileline() << ": internal error: " - << "unhandled expression type?" << endl; + << "Unhandled expression type?" << endl; des->errors += 1; + (*cur).second.expr = NULL; return; } @@ -522,7 +520,13 @@ void NetScope::evaluate_parameter_real_(Design*des, param_ref_t cur) if (NetECReal*tmp = dynamic_cast(expr)) { res = tmp; } else { - ivl_assert(*expr, 0); + cerr << expr->get_fileline() + << ": error: " + << "Unable to evaluate real parameter " + << (*cur).first << " value: " << *expr << endl; + des->errors += 1; + (*cur).second.expr = NULL; + return; } break; @@ -533,12 +537,23 @@ void NetScope::evaluate_parameter_real_(Design*des, param_ref_t cur) res = new NetECReal(val); res->set_line(*tmp); } else { - ivl_assert(*expr, 0); + cerr << expr->get_fileline() + << ": error: " + << "Unable to evaluate parameter " + << (*cur).first << " value: " << *expr << endl; + des->errors += 1; + (*cur).second.expr = NULL; + return; } break; default: - ivl_assert(*expr, 0); + cerr << expr->get_fileline() + << ": internal error: " + << "Unhandled expression type?" << endl; + des->errors += 1; + (*cur).second.expr = NULL; + return; break; } @@ -586,7 +601,7 @@ void NetScope::evaluate_parameter_real_(Design*des, param_ref_t cur) if (! from_flag) { cerr << res->get_fileline() << ": error: " << "Parameter value " << value - << " is out of range for parameter " << (*cur).first + << " is out of range for real parameter " << (*cur).first << "." << endl; des->errors += 1; } @@ -612,7 +627,7 @@ void NetScope::evaluate_parameters(Design*des) // Resolve the expression type (signed/unsigned) if the // expression is present. It is possible to not be - // present if there are earlier errors en elaboration. + // present if there are earlier errors in elaboration. if (cur->second.expr) cur->second.expr->resolve_pexpr_type(); diff --git a/net_expr.cc b/net_expr.cc index 3b5890caa..1dc1c3cb1 100644 --- a/net_expr.cc +++ b/net_expr.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2009 Stephen Williams (steve@icarus.com) + * Copyright (c) 2002-2010 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -488,18 +488,21 @@ const NetScope* NetECRealParam::scope() const NetEParam::NetEParam() : des_(0), scope_(0) { + solving_ = false; } NetEParam::NetEParam(Design*d, NetScope*s, perm_string n) : des_(d), scope_(s), reference_(scope_->find_parameter(n)) { cast_signed_base_(reference_->second.signed_flag); + solving_ = false; } NetEParam::NetEParam(Design*d, NetScope*s, ref_t ref) : des_(d), scope_(s), reference_(ref) { cast_signed_base_(reference_->second.signed_flag); + solving_ = false; } NetEParam::~NetEParam() @@ -519,10 +522,21 @@ ivl_variable_type_t NetEParam::expr_type() const NetEParam* NetEParam::dup_expr() const { NetEParam*tmp = new NetEParam(des_, scope_, reference_); + tmp->solving(solving_); tmp->set_line(*this); return tmp; } +void NetEParam::solving(bool arg) +{ + solving_ = arg; +} + +bool NetEParam::solving() const +{ + return solving_; +} + NetESelect::NetESelect(NetExpr*exp, NetExpr*base, unsigned wid) : expr_(exp), base_(base) { diff --git a/netlist.h b/netlist.h index 04ef95a06..6c25220eb 100644 --- a/netlist.h +++ b/netlist.h @@ -3574,6 +3574,8 @@ class NetEParam : public NetExpr { virtual ivl_variable_type_t expr_type() const; virtual NetExpr* eval_tree(int prune_to_width = -1); virtual NetEParam* dup_expr() const; + void solving(bool arg); + bool solving() const; virtual void dump(ostream&) const; @@ -3582,6 +3584,7 @@ class NetEParam : public NetExpr { NetScope*scope_; typedef map::iterator ref_t; ref_t reference_; + bool solving_; NetEParam(class Design*des, NetScope*scope, ref_t ref); };