diff --git a/eval_tree.cc b/eval_tree.cc index d677e774d..af2382380 100644 --- a/eval_tree.cc +++ b/eval_tree.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2011 Stephen Williams (steve@icarus.com) + * Copyright (c) 1999-2013 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 @@ -77,12 +77,10 @@ static bool get_real_arguments(const NetExpr*le, const NetExpr*re, return true; } -bool NetEBinary::get_real_arguments_(verireal&lval, verireal&rval) +NetExpr* NetEBinary::eval_arguments_(const NetExpr*, const NetExpr*) const { - if (!get_real_arg_(left_, lval)) return false; - if (!get_real_arg_(right_, rval)) return false; - - return true; + ivl_assert(*this, 0); + return 0; } NetECReal* NetEBAdd::eval_tree_real_(const NetExpr*l, const NetExpr*r) const @@ -231,16 +229,16 @@ NetExpr* NetEBAdd::eval_arguments_(const NetExpr*l, const NetExpr*r) const NetEConst* NetEBBits::eval_tree() { - if (debug_eval_tree) { - cerr << get_fileline() << ": debug: Evaluating expression:" - << *this << endl; - } - eval_expr(left_); eval_expr(right_); - NetEConst*lc = dynamic_cast(left_); - NetEConst*rc = dynamic_cast(right_); + return eval_arguments_(left_, right_); +} + +NetEConst* NetEBBits::eval_arguments_(const NetExpr*l, const NetExpr*r) const +{ + const NetEConst*lc = dynamic_cast(l); + const NetEConst*rc = dynamic_cast(r); if (lc == 0 || rc == 0) return 0; /* Notice the special case where one of the operands is 0 and @@ -293,7 +291,15 @@ NetEConst* NetEBBits::eval_tree() return 0; } - return new NetEConst(res); + NetEConst*tmp = new NetEConst(res); + ivl_assert(*this, tmp); + tmp->set_line(*this); + + if (debug_eval_tree) + cerr << get_fileline() << ": debug: Evaluated: " << *this + << " --> " << *tmp << endl; + + return tmp; } NetEConst* NetEBComp::eval_less_(const NetExpr*le, const NetExpr*re) const @@ -764,27 +770,28 @@ NetEConst* NetEBComp::eval_tree() return res; } -NetExpr* NetEBDiv::eval_tree_real_() +NetExpr* NetEBDiv::eval_tree_real_(const NetExpr*l, const NetExpr*r) const { - verireal lval; - verireal rval; + double lval; + double rval; - bool flag = get_real_arguments_(lval, rval); + bool flag = get_real_arguments(l, r, lval, rval); if (! flag) return 0; - NetECReal*res = 0; + double res_val = 0.0; switch (op_) { case '/': - res = new NetECReal(lval / rval); + res_val = lval / rval; break; case '%': // Since this could/may be called early we don't want to // leak functionality. if (!gn_icarus_misc_flag) return 0; - res = new NetECReal(lval % rval); + res_val = fmod(lval, rval); break; } + NetECReal*res = new NetECReal( verireal(res_val) ); ivl_assert(*this, res); res->set_line(*this); @@ -804,11 +811,16 @@ NetExpr* NetEBDiv::eval_tree() eval_expr(left_); eval_expr(right_); - if (expr_type() == IVL_VT_REAL) return eval_tree_real_(); + return eval_arguments_(left_, right_); +} + +NetExpr* NetEBDiv::eval_arguments_(const NetExpr*l, const NetExpr*r) const +{ + if (expr_type() == IVL_VT_REAL) return eval_tree_real_(l,r); assert(expr_type() == IVL_VT_LOGIC); - NetEConst*lc = dynamic_cast(left_); - NetEConst*rc = dynamic_cast(right_); + const NetEConst*lc = dynamic_cast(l); + const NetEConst*rc = dynamic_cast(r); if (lc == 0 || rc == 0) return 0; verinum lval = lc->value(); @@ -841,25 +853,25 @@ NetExpr* NetEBDiv::eval_tree() return tmp; } -NetEConst* NetEBLogic::eval_tree_real_() +NetEConst* NetEBLogic::eval_tree_real_(const NetExpr*l, const NetExpr*r) const { - verireal lval; - verireal rval; + double lval; + double rval; - bool flag = get_real_arguments_(lval, rval); + bool flag = get_real_arguments(l, r, lval, rval); if (! flag) return 0; verinum::V res; switch (op_) { case 'a': // Logical AND (&&) - if ((lval.as_double() != 0.0) && (rval.as_double() != 0.0)) + if ((lval != 0.0) && (rval != 0.0)) res = verinum::V1; else res = verinum::V0; break; case 'o': // Logical OR (||) - if ((lval.as_double() != 0.0) || (rval.as_double() != 0.0)) + if ((lval != 0.0) || (rval != 0.0)) res = verinum::V1; else res = verinum::V0; @@ -885,13 +897,17 @@ NetEConst* NetEBLogic::eval_tree() eval_expr(left_); eval_expr(right_); - if (left_->expr_type() == IVL_VT_REAL || - right_->expr_type() == IVL_VT_REAL) - return eval_tree_real_(); + return eval_arguments_(left_, right_); +} + +NetEConst* NetEBLogic::eval_arguments_(const NetExpr*l, const NetExpr*r) const +{ + if (l->expr_type() == IVL_VT_REAL || r->expr_type() == IVL_VT_REAL) + return eval_tree_real_(l,r); assert(expr_type() == IVL_VT_LOGIC); - NetEConst*lc = dynamic_cast(left_); - NetEConst*rc = dynamic_cast(right_); + const NetEConst*lc = dynamic_cast(l); + const NetEConst*rc = dynamic_cast(r); if (lc == 0 || rc == 0) return 0; verinum::V lv = verinum::V0; @@ -956,6 +972,87 @@ NetEConst* NetEBLogic::eval_tree() return tmp; } +NetExpr* NetEBMinMax::eval_tree_real_(const NetExpr*l, const NetExpr*r) const +{ + double lval; + double rval; + + bool flag = get_real_arguments(l, r, lval, rval); + if (! flag) return 0; + + double res_val; + switch (op()) { + case 'm': + res_val = lval < rval ? lval : rval; + break; + case 'M': + res_val = lval > rval ? lval : rval; + break; + default: + ivl_assert(*this, 0); + } + + NetECReal*res = new NetECReal( verireal(res_val) ); + ivl_assert(*this, res); + res->set_line(*this); + + if (debug_eval_tree) + cerr << get_fileline() << ": debug: Evaluated (real): " << *this + << " --> " << *res << endl; + + return res; +} + +NetExpr* NetEBMinMax::eval_tree() +{ + eval_expr(left_); + eval_expr(right_); + + return eval_arguments_(left_, right_); +} + +NetExpr* NetEBMinMax::eval_arguments_(const NetExpr*l, const NetExpr*r) const +{ + if (expr_type() == IVL_VT_REAL) return eval_tree_real_(l,r); + assert(expr_type() == IVL_VT_LOGIC); + + const NetEConst*lc = dynamic_cast(l); + const NetEConst*rc = dynamic_cast(r); + if (lc == 0 || rc == 0) return 0; + + verinum lval = lc->value(); + verinum rval = rc->value(); + + unsigned wid = expr_width(); + ivl_assert(*this, wid > 0); + ivl_assert(*this, lval.len() == wid); + ivl_assert(*this, rval.len() == wid); + + verinum res_val; + if (lval.is_defined() && rval.is_defined()) { + switch (op()) { + case 'm': + res_val = lval < rval ? lval : rval; + break; + case 'M': + res_val = lval > rval ? lval : rval; + break; + default: + ivl_assert(*this, 0); + } + } else { + res_val = verinum(verinum::Vx, wid); + } + NetEConst*res = new NetEConst(res_val); + ivl_assert(*this, res); + res->set_line(*this); + + if (debug_eval_tree) + cerr << get_fileline() << ": debug: Evaluated: " << *this + << " --> " << *res << endl; + + return res; +} NetExpr* NetEBMult::eval_tree_real_(const NetExpr*l, const NetExpr*r) const { @@ -1013,15 +1110,15 @@ NetExpr* NetEBMult::eval_arguments_(const NetExpr*l, const NetExpr*r) const return tmp; } -NetExpr* NetEBPow::eval_tree_real_() +NetExpr* NetEBPow::eval_tree_real_(const NetExpr*l, const NetExpr*r) const { - verireal lval; - verireal rval; + double lval; + double rval; - bool flag = get_real_arguments_(lval, rval); + bool flag = get_real_arguments(l, r, lval, rval); if (! flag) return 0; - NetECReal*res = new NetECReal( pow(lval,rval) ); + NetECReal*res = new NetECReal( verireal( pow(lval,rval) ) ); ivl_assert(*this, res); res->set_line(*this); @@ -1037,11 +1134,16 @@ NetExpr* NetEBPow::eval_tree() eval_expr(left_); eval_expr(right_); - if (expr_type() == IVL_VT_REAL) return eval_tree_real_(); + return eval_arguments_(left_, right_); +} + +NetExpr* NetEBPow::eval_arguments_(const NetExpr*l, const NetExpr*r) const +{ + if (expr_type() == IVL_VT_REAL) return eval_tree_real_(l,r); assert(expr_type() == IVL_VT_LOGIC); - NetEConst*lc = dynamic_cast(left_); - NetEConst*rc = dynamic_cast(right_); + const NetEConst*lc = dynamic_cast(l); + const NetEConst*rc = dynamic_cast(r); if (lc == 0 || rc == 0) return 0; verinum lval = lc->value(); @@ -1071,6 +1173,7 @@ NetEConst* NetEBShift::eval_tree() { eval_expr(left_); eval_expr(right_); + return eval_arguments_(left_,right_); } diff --git a/net_func_eval.cc b/net_func_eval.cc index 69020c2db..1187e9433 100644 --- a/net_func_eval.cc +++ b/net_func_eval.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Stephen Williams (steve@icarus.com) + * Copyright (c) 2012-2013 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 @@ -267,26 +267,8 @@ bool NetWhile::evaluate_function(const LineInfo&loc, return flag; } -NetExpr* NetEBComp::evaluate_function(const LineInfo&loc, - map&context_map) const -{ - NetExpr*lval = left_->evaluate_function(loc, context_map); - NetExpr*rval = right_->evaluate_function(loc, context_map); - - if (lval == 0 || rval == 0) { - delete lval; - delete rval; - return 0; - } - - NetEConst*res = eval_arguments_(lval, rval); - delete lval; - delete rval; - return res; -} - -NetExpr* NetEBAdd::evaluate_function(const LineInfo&loc, - map&context_map) const +NetExpr* NetEBinary::evaluate_function(const LineInfo&loc, + map&context_map) const { NetExpr*lval = left_->evaluate_function(loc, context_map); NetExpr*rval = right_->evaluate_function(loc, context_map); @@ -303,42 +285,6 @@ NetExpr* NetEBAdd::evaluate_function(const LineInfo&loc, return res; } -NetExpr* NetEBMult::evaluate_function(const LineInfo&loc, - map&context_map) const -{ - NetExpr*lval = left_->evaluate_function(loc, context_map); - NetExpr*rval = right_->evaluate_function(loc, context_map); - - if (lval == 0 || rval == 0) { - delete lval; - delete rval; - return 0; - } - - NetExpr*res = eval_arguments_(lval, rval); - delete lval; - delete rval; - return res; -} - -NetExpr* NetEBShift::evaluate_function(const LineInfo&loc, - map&context_map) const -{ - NetExpr*lval = left_->evaluate_function(loc, context_map); - NetExpr*rval = right_->evaluate_function(loc, context_map); - - if (lval == 0 || rval == 0) { - delete lval; - delete rval; - return 0; - } - - NetEConst*res = eval_arguments_(lval, rval); - delete lval; - delete rval; - return res; -} - NetExpr* NetEConst::evaluate_function(const LineInfo&, map&) const { diff --git a/netlist.h b/netlist.h index 5fef754b0..7c08f1061 100644 --- a/netlist.h +++ b/netlist.h @@ -3527,6 +3527,8 @@ class NetEBinary : public NetExpr { virtual bool has_width() const; virtual NetEBinary* dup_expr() const; + virtual NetExpr* evaluate_function(const LineInfo&loc, + std::map&ctx) const; virtual NexusSet* nex_input(bool rem_out = true); virtual void expr_scan(struct expr_scan_t*) const; @@ -3537,7 +3539,7 @@ class NetEBinary : public NetExpr { NetExpr* left_; NetExpr* right_; - bool get_real_arguments_(verireal&lv, verireal&rv); + virtual NetExpr* eval_arguments_(const NetExpr*l, const NetExpr*r) const; }; /* @@ -3557,9 +3559,6 @@ class NetEBAdd : public NetEBinary { virtual NetEBAdd* dup_expr() const; virtual NetExpr* eval_tree(); - virtual NetExpr* evaluate_function(const LineInfo&loc, - std::map&ctx) const; - virtual NetNet* synthesize(Design*, NetScope*scope, NetExpr*root); private: @@ -3585,7 +3584,8 @@ class NetEBDiv : public NetEBinary { virtual NetNet* synthesize(Design*, NetScope*scope, NetExpr*root); private: - NetExpr* eval_tree_real_(); + NetExpr* eval_arguments_(const NetExpr*l, const NetExpr*r) const; + NetExpr* eval_tree_real_(const NetExpr*l, const NetExpr*r) const; }; /* @@ -3610,8 +3610,10 @@ class NetEBBits : public NetEBinary { virtual NetEBBits* dup_expr() const; virtual NetEConst* eval_tree(); - virtual NetNet* synthesize(Design*, NetScope*scope, NetExpr*root); + + private: + NetEConst* eval_arguments_(const NetExpr*l, const NetExpr*r) const; }; /* @@ -3639,10 +3641,6 @@ class NetEBComp : public NetEBinary { virtual ivl_variable_type_t expr_type() const; virtual NetEBComp* dup_expr() const; virtual NetEConst* eval_tree(); - - virtual NetExpr*evaluate_function(const LineInfo&loc, - std::map&ctx) const; - virtual NetNet* synthesize(Design*, NetScope*scope, NetExpr*root); private: @@ -3677,7 +3675,8 @@ class NetEBLogic : public NetEBinary { virtual NetNet* synthesize(Design*, NetScope*scope, NetExpr*root); private: - NetEConst* eval_tree_real_(); + NetEConst* eval_arguments_(const NetExpr*l, const NetExpr*r) const; + NetEConst* eval_tree_real_(const NetExpr*l, const NetExpr*r) const; }; /* @@ -3695,7 +3694,11 @@ class NetEBMinMax : public NetEBinary { virtual ivl_variable_type_t expr_type() const; + virtual NetExpr* eval_tree(); + private: + NetExpr* eval_arguments_(const NetExpr*l, const NetExpr*r) const; + NetExpr* eval_tree_real_(const NetExpr*l, const NetExpr*r) const; }; /* @@ -3711,8 +3714,6 @@ class NetEBMult : public NetEBinary { virtual NetEBMult* dup_expr() const; virtual NetExpr* eval_tree(); - virtual NetExpr* evaluate_function(const LineInfo&loc, - std::map&ctx) const; virtual NetNet* synthesize(Design*, NetScope*scope, NetExpr*root); private: @@ -3736,13 +3737,13 @@ class NetEBPow : public NetEBinary { virtual NetNet* synthesize(Design*, NetScope*scope, NetExpr*root); private: - NetExpr* eval_tree_real_(); + NetExpr* eval_arguments_(const NetExpr*l, const NetExpr*r) const; + NetExpr* eval_tree_real_(const NetExpr*l, const NetExpr*r) const; }; /* - * The binary logical operators are those that return boolean - * results. The supported operators are: + * Support the binary shift operators. The supported operators are: * * l -- left shift (<<) * r -- right shift (>>) @@ -3760,10 +3761,6 @@ class NetEBShift : public NetEBinary { virtual NetEBShift* dup_expr() const; virtual NetEConst* eval_tree(); - - virtual NetExpr*evaluate_function(const LineInfo&loc, - std::map&ctx) const; - virtual NetNet* synthesize(Design*, NetScope*scope, NetExpr*root); private: