More expression types work in constant functions.
This commit is contained in:
parent
def9d0ea1d
commit
a5a7050120
300
eval_tree.cc
300
eval_tree.cc
|
|
@ -34,11 +34,11 @@ NetExpr* NetExpr::eval_tree()
|
|||
return 0;
|
||||
}
|
||||
|
||||
static bool get_real_arg_(NetExpr*expr, verireal&val)
|
||||
static bool get_real_arg_(const NetExpr*expr, verireal&val)
|
||||
{
|
||||
switch (expr->expr_type()) {
|
||||
case IVL_VT_REAL: {
|
||||
NetECReal*c = dynamic_cast<NetECReal*> (expr);
|
||||
const NetECReal*c = dynamic_cast<const NetECReal*> (expr);
|
||||
if (c == 0) return false;
|
||||
val = c->value();
|
||||
break;
|
||||
|
|
@ -46,7 +46,7 @@ static bool get_real_arg_(NetExpr*expr, verireal&val)
|
|||
|
||||
case IVL_VT_BOOL:
|
||||
case IVL_VT_LOGIC: {
|
||||
NetEConst*c = dynamic_cast<NetEConst*>(expr);
|
||||
const NetEConst*c = dynamic_cast<const NetEConst*>(expr);
|
||||
if (c == 0) return false;
|
||||
verinum tmp = c->value();
|
||||
val = verireal(tmp.as_double());
|
||||
|
|
@ -60,7 +60,7 @@ static bool get_real_arg_(NetExpr*expr, verireal&val)
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool get_real_arguments(NetExpr*le, NetExpr*re,
|
||||
static bool get_real_arguments(const NetExpr*le, const NetExpr*re,
|
||||
double&lval, double&rval)
|
||||
{
|
||||
verireal val;
|
||||
|
|
@ -82,15 +82,15 @@ bool NetEBinary::get_real_arguments_(verireal&lval, verireal&rval)
|
|||
return true;
|
||||
}
|
||||
|
||||
NetECReal* NetEBAdd::eval_tree_real_()
|
||||
NetECReal* NetEBAdd::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;
|
||||
|
||||
verireal res_val;
|
||||
double res_val;
|
||||
|
||||
switch (op()) {
|
||||
case '+':
|
||||
|
|
@ -103,7 +103,7 @@ NetECReal* NetEBAdd::eval_tree_real_()
|
|||
ivl_assert(*this, 0);
|
||||
}
|
||||
|
||||
NetECReal*res = new NetECReal( res_val );
|
||||
NetECReal*res = new NetECReal( verireal(res_val) );
|
||||
ivl_assert(*this, res);
|
||||
res->set_line(*this);
|
||||
|
||||
|
|
@ -119,52 +119,24 @@ NetExpr* NetEBAdd::eval_tree()
|
|||
eval_expr(left_);
|
||||
eval_expr(right_);
|
||||
|
||||
if (expr_type() == IVL_VT_REAL)
|
||||
return eval_tree_real_();
|
||||
|
||||
NetEConst*lc = dynamic_cast<NetEConst*>(left_);
|
||||
NetEConst*rc = dynamic_cast<NetEConst*>(right_);
|
||||
|
||||
/* If both operands are constant, then replace the entire
|
||||
expression with a constant value. */
|
||||
if (lc != 0 && rc != 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 val;
|
||||
switch (op_) {
|
||||
case '+':
|
||||
val = verinum(lval + rval, wid);
|
||||
break;
|
||||
case '-':
|
||||
val = verinum(lval - rval, wid);
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetEConst *res = new NetEConst(val);
|
||||
ivl_assert(*this, res);
|
||||
res->set_line(*this);
|
||||
|
||||
if (debug_eval_tree)
|
||||
cerr << get_fileline() << ": debug: Evaluated: " << *this
|
||||
<< " --> " << *res << endl;
|
||||
|
||||
// First try to elaborate the expression completely.
|
||||
NetExpr*res = eval_arguments_(left_,right_);
|
||||
if (res != 0)
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Try to combine a right constant value with the right
|
||||
constant value of a sub-expression add. For example, the
|
||||
expression (a + 2) - 1 can be rewritten as a + 1. */
|
||||
// If the expression type is real, then do not attempt the
|
||||
// following alternative processing.
|
||||
if (expr_type() == IVL_VT_REAL)
|
||||
return 0;
|
||||
|
||||
// The expression has not evaluated to a constant. Let's still
|
||||
// try to optimize by trying to combine a right constant value
|
||||
// with the right constant value of a sub-expression add. For
|
||||
// example, the expression (a + 2) - 1 can be rewritten as a + 1.
|
||||
|
||||
NetEBAdd*se = dynamic_cast<NetEBAdd*>(left_);
|
||||
lc = se? dynamic_cast<NetEConst*>(se->right_) : 0;
|
||||
NetEConst*lc = se? dynamic_cast<NetEConst*>(se->right_) : 0;
|
||||
NetEConst*rc = dynamic_cast<NetEConst*>(right_);
|
||||
|
||||
if (lc != 0 && rc != 0) {
|
||||
ivl_assert(*this, se != 0);
|
||||
|
|
@ -200,11 +172,56 @@ NetExpr* NetEBAdd::eval_tree()
|
|||
tmp->set_line(*right_);
|
||||
delete right_;
|
||||
right_ = tmp;
|
||||
/* We've changed the subexpression, but the result is
|
||||
still not constant, so return nil here anyhow. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
// We may have changed the subexpression, but the result is
|
||||
// still not constant, so return nil here anyhow.
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetExpr* NetEBAdd::eval_arguments_(const NetExpr*l, const NetExpr*r) const
|
||||
{
|
||||
if (expr_type() == IVL_VT_REAL)
|
||||
return eval_tree_real_(l,r);
|
||||
|
||||
const NetEConst*lc = dynamic_cast<const NetEConst*>(l);
|
||||
const NetEConst*rc = dynamic_cast<const NetEConst*>(r);
|
||||
|
||||
/* If both operands are constant, then replace the entire
|
||||
expression with a constant value. */
|
||||
if (lc != 0 && rc != 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 val;
|
||||
switch (op_) {
|
||||
case '+':
|
||||
val = verinum(lval + rval, wid);
|
||||
break;
|
||||
case '-':
|
||||
val = verinum(lval - rval, wid);
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetEConst *res = new NetEConst(val);
|
||||
ivl_assert(*this, res);
|
||||
res->set_line(*this);
|
||||
|
||||
if (debug_eval_tree)
|
||||
cerr << get_fileline() << ": debug: Evaluated: " << *this
|
||||
<< " --> " << *res << endl;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/* Nothing more to be done, the value is not constant. */
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -276,13 +293,12 @@ NetEConst* NetEBBits::eval_tree()
|
|||
return new NetEConst(res);
|
||||
}
|
||||
|
||||
NetEConst* NetEBComp::eval_less_()
|
||||
NetEConst* NetEBComp::eval_less_(const NetExpr*le, const NetExpr*re) const
|
||||
{
|
||||
if (right_->expr_type() == IVL_VT_REAL ||
|
||||
left_->expr_type() == IVL_VT_REAL)
|
||||
return eval_leeq_real_(left_, right_, false);
|
||||
if (le->expr_type() == IVL_VT_REAL || re->expr_type() == IVL_VT_REAL)
|
||||
return eval_leeq_real_(le, re, false);
|
||||
|
||||
NetEConst*rc = dynamic_cast<NetEConst*>(right_);
|
||||
const NetEConst*rc = dynamic_cast<const NetEConst*>(re);
|
||||
if (rc == 0) return 0;
|
||||
|
||||
verinum rv = rc->value();
|
||||
|
|
@ -292,12 +308,12 @@ NetEConst* NetEBComp::eval_less_()
|
|||
return res;
|
||||
}
|
||||
|
||||
if (NetEConst*tmp = must_be_leeq_(left_, rv, false)) {
|
||||
if (NetEConst*tmp = must_be_leeq_(le, rv, false)) {
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/* Now go on to the normal test of the values. */
|
||||
NetEConst*lc = dynamic_cast<NetEConst*>(left_);
|
||||
const NetEConst*lc = dynamic_cast<const NetEConst*>(le);
|
||||
if (lc == 0) return 0;
|
||||
|
||||
verinum lv = lc->value();
|
||||
|
|
@ -318,7 +334,7 @@ NetEConst* NetEBComp::eval_less_()
|
|||
}
|
||||
}
|
||||
|
||||
NetEConst* NetEBComp::must_be_leeq_(NetExpr*le, const verinum&rv, bool eq_flag)
|
||||
NetEConst* NetEBComp::must_be_leeq_(const NetExpr*le, const verinum&rv, bool eq_flag) const
|
||||
{
|
||||
assert(le->expr_width() > 0);
|
||||
verinum lv (verinum::V1, le->expr_width());
|
||||
|
|
@ -339,7 +355,7 @@ NetEConst* NetEBComp::must_be_leeq_(NetExpr*le, const verinum&rv, bool eq_flag)
|
|||
return 0;
|
||||
}
|
||||
|
||||
NetEConst* NetEBComp::eval_leeq_real_(NetExpr*le, NetExpr*re, bool eq_flag)
|
||||
NetEConst* NetEBComp::eval_leeq_real_(const NetExpr*le, const NetExpr*re, bool eq_flag) const
|
||||
{
|
||||
double lval;
|
||||
double rval;
|
||||
|
|
@ -358,14 +374,13 @@ NetEConst* NetEBComp::eval_leeq_real_(NetExpr*le, NetExpr*re, bool eq_flag)
|
|||
return res;
|
||||
}
|
||||
|
||||
NetEConst* NetEBComp::eval_leeq_()
|
||||
NetEConst* NetEBComp::eval_leeq_(const NetExpr*le, const NetExpr*re) const
|
||||
{
|
||||
if (right_->expr_type() == IVL_VT_REAL ||
|
||||
left_->expr_type() == IVL_VT_REAL)
|
||||
return eval_leeq_real_(left_, right_, true);
|
||||
if (le->expr_type() == IVL_VT_REAL || re->expr_type() == IVL_VT_REAL)
|
||||
return eval_leeq_real_(le, re, true);
|
||||
// assert(expr_type() == IVL_VT_LOGIC);
|
||||
|
||||
NetEConst*r = dynamic_cast<NetEConst*>(right_);
|
||||
const NetEConst*r = dynamic_cast<const NetEConst*>(re);
|
||||
if (r == 0) return 0;
|
||||
|
||||
verinum rv = r->value();
|
||||
|
|
@ -375,18 +390,18 @@ NetEConst* NetEBComp::eval_leeq_()
|
|||
return res;
|
||||
}
|
||||
|
||||
if (left_->expr_width() == 0) {
|
||||
if (le->expr_width() == 0) {
|
||||
cerr << get_fileline() << ": internal error: Something wrong "
|
||||
<< "with the left side width of <= ?" << endl;
|
||||
cerr << get_fileline() << ": : " << *this << endl;
|
||||
}
|
||||
|
||||
if (NetEConst*tmp = must_be_leeq_(left_, rv, true)) {
|
||||
if (NetEConst*tmp = must_be_leeq_(le, rv, true)) {
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/* Now go on to the normal test of the values. */
|
||||
NetEConst*l = dynamic_cast<NetEConst*>(left_);
|
||||
const NetEConst*l = dynamic_cast<const NetEConst*>(le);
|
||||
if (l == 0) return 0;
|
||||
|
||||
verinum lv = l->value();
|
||||
|
|
@ -407,13 +422,12 @@ NetEConst* NetEBComp::eval_leeq_()
|
|||
}
|
||||
}
|
||||
|
||||
NetEConst* NetEBComp::eval_gt_()
|
||||
NetEConst* NetEBComp::eval_gt_(const NetExpr*le, const NetExpr*re) const
|
||||
{
|
||||
if (right_->expr_type() == IVL_VT_REAL ||
|
||||
left_->expr_type() == IVL_VT_REAL)
|
||||
return eval_leeq_real_(right_, left_, false);
|
||||
if (le->expr_type() == IVL_VT_REAL || re->expr_type() == IVL_VT_REAL)
|
||||
return eval_leeq_real_(re, le, false);
|
||||
|
||||
NetEConst*l = dynamic_cast<NetEConst*>(left_);
|
||||
const NetEConst*l = dynamic_cast<const NetEConst*>(le);
|
||||
if (l == 0) return 0;
|
||||
|
||||
verinum lv = l->value();
|
||||
|
|
@ -423,12 +437,12 @@ NetEConst* NetEBComp::eval_gt_()
|
|||
return res;
|
||||
}
|
||||
|
||||
if (NetEConst*tmp = must_be_leeq_(right_, lv, false)) {
|
||||
if (NetEConst*tmp = must_be_leeq_(re, lv, false)) {
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/* Now go on to the normal test of the values. */
|
||||
NetEConst*r = dynamic_cast<NetEConst*>(right_);
|
||||
const NetEConst*r = dynamic_cast<const NetEConst*>(re);
|
||||
if (r == 0) return 0;
|
||||
|
||||
verinum rv = r->value();
|
||||
|
|
@ -449,13 +463,12 @@ NetEConst* NetEBComp::eval_gt_()
|
|||
}
|
||||
}
|
||||
|
||||
NetEConst* NetEBComp::eval_gteq_()
|
||||
NetEConst* NetEBComp::eval_gteq_(const NetExpr*le, const NetExpr*re) const
|
||||
{
|
||||
if (right_->expr_type() == IVL_VT_REAL ||
|
||||
left_->expr_type() == IVL_VT_REAL)
|
||||
return eval_leeq_real_(right_, left_, true);
|
||||
if (le->expr_type() == IVL_VT_REAL || re->expr_type() == IVL_VT_REAL)
|
||||
return eval_leeq_real_(re, le, true);
|
||||
|
||||
NetEConst*l = dynamic_cast<NetEConst*>(left_);
|
||||
const NetEConst*l = dynamic_cast<const NetEConst*>(left_);
|
||||
if (l == 0) return 0;
|
||||
|
||||
verinum lv = l->value();
|
||||
|
|
@ -465,12 +478,12 @@ NetEConst* NetEBComp::eval_gteq_()
|
|||
return res;
|
||||
}
|
||||
|
||||
if (NetEConst*tmp = must_be_leeq_(right_, lv, true)) {
|
||||
if (NetEConst*tmp = must_be_leeq_(re, lv, true)) {
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/* Now go on to the normal test of the values. */
|
||||
NetEConst*r = dynamic_cast<NetEConst*>(right_);
|
||||
const NetEConst*r = dynamic_cast<const NetEConst*>(re);
|
||||
if (r == 0) return 0;
|
||||
|
||||
verinum rv = r->value();
|
||||
|
|
@ -498,15 +511,15 @@ NetEConst* NetEBComp::eval_gteq_()
|
|||
* are equal, but there are are x/z bits, then the situation is
|
||||
* ambiguous so the result is x.
|
||||
*/
|
||||
NetEConst* NetEBComp::eval_eqeq_real_(bool ne_flag)
|
||||
NetEConst* NetEBComp::eval_eqeq_real_(bool ne_flag, const NetExpr*le, const NetExpr*re) const
|
||||
{
|
||||
verireal lval;
|
||||
verireal rval;
|
||||
double lval;
|
||||
double rval;
|
||||
|
||||
bool flag = get_real_arguments_(lval, rval);
|
||||
bool flag = get_real_arguments(le, re, lval, rval);
|
||||
if (! flag) return 0;
|
||||
|
||||
verinum result(((lval.as_double() == rval.as_double()) ^ ne_flag) ?
|
||||
verinum result(((lval == rval) ^ ne_flag) ?
|
||||
verinum::V1 : verinum::V0, 1);
|
||||
NetEConst*res = new NetEConst(result);
|
||||
ivl_assert(*this, res);
|
||||
|
|
@ -514,14 +527,14 @@ NetEConst* NetEBComp::eval_eqeq_real_(bool ne_flag)
|
|||
return res;
|
||||
}
|
||||
|
||||
NetEConst* NetEBComp::eval_eqeq_(bool ne_flag)
|
||||
NetEConst* NetEBComp::eval_eqeq_(bool ne_flag, const NetExpr*le, const NetExpr*re) const
|
||||
{
|
||||
if (left_->expr_type() == IVL_VT_REAL ||
|
||||
right_->expr_type() == IVL_VT_REAL)
|
||||
return eval_eqeq_real_(ne_flag);
|
||||
if (le->expr_type() == IVL_VT_REAL ||
|
||||
re->expr_type() == IVL_VT_REAL)
|
||||
return eval_eqeq_real_(ne_flag, le, re);
|
||||
|
||||
NetEConst*lc = dynamic_cast<NetEConst*>(left_);
|
||||
NetEConst*rc = dynamic_cast<NetEConst*>(right_);
|
||||
const NetEConst*lc = dynamic_cast<const NetEConst*>(le);
|
||||
const NetEConst*rc = dynamic_cast<const NetEConst*>(re);
|
||||
if (lc == 0 || rc == 0) return 0;
|
||||
|
||||
const verinum&lv = lc->value();
|
||||
|
|
@ -631,10 +644,10 @@ NetEConst* NetEBComp::eval_eqeq_(bool ne_flag)
|
|||
return result;
|
||||
}
|
||||
|
||||
NetEConst* NetEBComp::eval_eqeqeq_(bool ne_flag)
|
||||
NetEConst* NetEBComp::eval_eqeqeq_(bool ne_flag, const NetExpr*le, const NetExpr*re) const
|
||||
{
|
||||
NetEConst*lc = dynamic_cast<NetEConst*>(left_);
|
||||
NetEConst*rc = dynamic_cast<NetEConst*>(right_);
|
||||
const NetEConst*lc = dynamic_cast<const NetEConst*>(le);
|
||||
const NetEConst*rc = dynamic_cast<const NetEConst*>(re);
|
||||
if (lc == 0 || rc == 0) return 0;
|
||||
|
||||
const verinum&lv = lc->value();
|
||||
|
|
@ -687,47 +700,54 @@ NetEConst* NetEBComp::eval_eqeqeq_(bool ne_flag)
|
|||
return result;
|
||||
}
|
||||
|
||||
NetEConst* NetEBComp::eval_arguments_(const NetExpr*l, const NetExpr*r) const
|
||||
{
|
||||
NetEConst*res = 0;
|
||||
|
||||
switch (op_) {
|
||||
case 'E': // Case equality (===)
|
||||
res = eval_eqeqeq_(false, l, r);
|
||||
break;
|
||||
|
||||
case 'e': // Equality (==)
|
||||
res = eval_eqeq_(false, l, r);
|
||||
break;
|
||||
|
||||
case 'G': // >=
|
||||
res = eval_gteq_(l, r);
|
||||
break;
|
||||
|
||||
case 'L': // <=
|
||||
res = eval_leeq_(l, r);
|
||||
break;
|
||||
|
||||
case 'N': // Case inequality (!==)
|
||||
res = eval_eqeqeq_(true, l, r);
|
||||
break;
|
||||
|
||||
case 'n': // not-equal (!=)
|
||||
res = eval_eqeq_(true, l, r);
|
||||
break;
|
||||
|
||||
case '<': // Less than
|
||||
res = eval_less_(l, r);
|
||||
break;
|
||||
|
||||
case '>': // Greater than
|
||||
res = eval_gt_(l, r);
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
NetEConst* NetEBComp::eval_tree()
|
||||
{
|
||||
eval_expr(left_);
|
||||
eval_expr(right_);
|
||||
|
||||
NetEConst*res = 0;
|
||||
|
||||
switch (op_) {
|
||||
case 'E': // Case equality (===)
|
||||
res = eval_eqeqeq_(false);
|
||||
break;
|
||||
|
||||
case 'e': // Equality (==)
|
||||
res = eval_eqeq_(false);
|
||||
break;
|
||||
|
||||
case 'G': // >=
|
||||
res = eval_gteq_();
|
||||
break;
|
||||
|
||||
case 'L': // <=
|
||||
res = eval_leeq_();
|
||||
break;
|
||||
|
||||
case 'N': // Case inequality (!==)
|
||||
res = eval_eqeqeq_(true);
|
||||
break;
|
||||
|
||||
case 'n': // not-equal (!=)
|
||||
res = eval_eqeq_(true);
|
||||
break;
|
||||
|
||||
case '<': // Less than
|
||||
res = eval_less_();
|
||||
break;
|
||||
|
||||
case '>': // Greater than
|
||||
res = eval_gt_();
|
||||
break;
|
||||
|
||||
}
|
||||
NetEConst*res = eval_arguments_(left_, right_);
|
||||
if (res == 0) return 0;
|
||||
res->set_line(*this);
|
||||
|
||||
|
|
@ -1043,9 +1063,13 @@ NetEConst* NetEBShift::eval_tree()
|
|||
{
|
||||
eval_expr(left_);
|
||||
eval_expr(right_);
|
||||
return eval_arguments_(left_,right_);
|
||||
}
|
||||
|
||||
NetEConst*le = dynamic_cast<NetEConst*>(left_);
|
||||
NetEConst*re = dynamic_cast<NetEConst*>(right_);
|
||||
NetEConst* NetEBShift::eval_arguments_(const NetExpr*l, const NetExpr*r) const
|
||||
{
|
||||
const NetEConst*le = dynamic_cast<const NetEConst*>(l);
|
||||
const NetEConst*re = dynamic_cast<const NetEConst*>(r);
|
||||
if (le == 0 || re == 0) return 0;
|
||||
|
||||
NetEConst*res;
|
||||
|
|
|
|||
133
net_func_eval.cc
133
net_func_eval.cc
|
|
@ -18,6 +18,7 @@
|
|||
*/
|
||||
|
||||
# include "netlist.h"
|
||||
# include "compiler.h"
|
||||
# include <typeinfo>
|
||||
# include "ivl_assert.h"
|
||||
|
||||
|
|
@ -29,6 +30,11 @@ NetExpr* NetFuncDef::evaluate_function(const LineInfo&loc, const std::vector<Net
|
|||
map<perm_string,NetExpr*>::iterator ptr;
|
||||
map<perm_string,NetExpr*>context_map;
|
||||
|
||||
if (debug_eval_tree) {
|
||||
cerr << loc.get_fileline() << ": debug: "
|
||||
<< "Evaluate function " << scope_->basename() << endl;
|
||||
}
|
||||
|
||||
// Put the return value into the map...
|
||||
context_map[scope_->basename()] = 0;
|
||||
// Load the input ports into the map...
|
||||
|
|
@ -37,6 +43,11 @@ NetExpr* NetFuncDef::evaluate_function(const LineInfo&loc, const std::vector<Net
|
|||
NetExpr*tmp = args[idx]->dup_expr();
|
||||
perm_string aname = ports_[idx]->name();
|
||||
context_map[aname] = tmp;
|
||||
|
||||
if (debug_eval_tree) {
|
||||
cerr << loc.get_fileline() << ": debug: "
|
||||
<< " input " << aname << " = " << *tmp << endl;
|
||||
}
|
||||
}
|
||||
|
||||
// Perform the evaluation
|
||||
|
|
@ -100,6 +111,13 @@ bool NetAssign::evaluate_function(const LineInfo&loc,
|
|||
map<perm_string,NetExpr*>::iterator ptr = context_map.find(lval->name());
|
||||
if (ptr->second)
|
||||
delete ptr->second;
|
||||
|
||||
if (debug_eval_tree) {
|
||||
cerr << get_fileline() << ": debug: "
|
||||
<< "NetAssign::evaluate_function: " << lval->name()
|
||||
<< " = " << *rval_result << endl;
|
||||
}
|
||||
|
||||
ptr->second = rval_result;
|
||||
|
||||
return true;
|
||||
|
|
@ -123,6 +141,103 @@ bool NetBlock::evaluate_function(const LineInfo&loc,
|
|||
return flag;
|
||||
}
|
||||
|
||||
bool NetWhile::evaluate_function(const LineInfo&loc,
|
||||
map<perm_string,NetExpr*>&context_map) const
|
||||
{
|
||||
bool flag = true;
|
||||
|
||||
if (debug_eval_tree) {
|
||||
cerr << get_fileline() << ": debug: NetWhile::evaluate_fuction: "
|
||||
<< "Start loop" << endl;
|
||||
}
|
||||
|
||||
while (flag) {
|
||||
// Evaluate the condition expression to try and get the
|
||||
// condition for the loop.
|
||||
NetExpr*cond = cond_->evaluate_function(loc, context_map);
|
||||
if (cond == 0) {
|
||||
flag = false;
|
||||
break;
|
||||
}
|
||||
|
||||
NetEConst*cond_const = dynamic_cast<NetEConst*> (cond);
|
||||
ivl_assert(loc, cond_const);
|
||||
|
||||
long val = cond_const->value().as_long();
|
||||
delete cond;
|
||||
|
||||
// If the condition is false, then break.
|
||||
if (val == 0)
|
||||
break;
|
||||
|
||||
// The condition is true, so evalutate the statement
|
||||
// another time.
|
||||
bool tmp_flag = proc_->evaluate_function(loc, context_map);
|
||||
if (! tmp_flag)
|
||||
flag = false;
|
||||
}
|
||||
|
||||
if (debug_eval_tree) {
|
||||
cerr << get_fileline() << ": debug: NetWhile::evaluate_fuction: "
|
||||
<< "Done loop" << endl;
|
||||
}
|
||||
|
||||
return flag;
|
||||
}
|
||||
|
||||
NetExpr* NetEBComp::evaluate_function(const LineInfo&loc,
|
||||
map<perm_string,NetExpr*>&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<perm_string,NetExpr*>&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<perm_string,NetExpr*>&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<perm_string,NetExpr*>&) const
|
||||
|
|
@ -131,3 +246,21 @@ NetExpr* NetEConst::evaluate_function(const LineInfo&,
|
|||
res->set_line(*this);
|
||||
return res;
|
||||
}
|
||||
|
||||
NetExpr* NetESignal::evaluate_function(const LineInfo&,
|
||||
map<perm_string,NetExpr*>&context_map) const
|
||||
{
|
||||
if (word_) {
|
||||
cerr << get_fileline() << ": sorry: I don't know how to evaluate signal word selects at compile time." << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
map<perm_string,NetExpr*>::iterator ptr = context_map.find(name());
|
||||
if (ptr == context_map.end()) {
|
||||
cerr << get_fileline() << ": error: Cannot evaluate " << name()
|
||||
<< " in this context." << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ptr->second->dup_expr();
|
||||
}
|
||||
|
|
|
|||
37
netlist.h
37
netlist.h
|
|
@ -3294,6 +3294,8 @@ class NetWhile : public NetProc {
|
|||
virtual bool emit_proc(struct target_t*) const;
|
||||
virtual void dump(ostream&, unsigned ind) const;
|
||||
virtual DelayType delay_type() const;
|
||||
virtual bool evaluate_function(const LineInfo&loc,
|
||||
map<perm_string,NetExpr*>&ctx) const;
|
||||
|
||||
private:
|
||||
NetExpr* cond_;
|
||||
|
|
@ -3451,10 +3453,14 @@ class NetEBAdd : public NetEBinary {
|
|||
|
||||
virtual NetEBAdd* dup_expr() const;
|
||||
virtual NetExpr* eval_tree();
|
||||
virtual NetExpr* evaluate_function(const LineInfo&loc,
|
||||
std::map<perm_string,NetExpr*>&ctx) const;
|
||||
|
||||
virtual NetNet* synthesize(Design*, NetScope*scope, NetExpr*root);
|
||||
|
||||
private:
|
||||
NetECReal* eval_tree_real_();
|
||||
NetExpr * eval_arguments_(const NetExpr*l, const NetExpr*r) const;
|
||||
NetECReal* eval_tree_real_(const NetExpr*l, const NetExpr*r) const;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -3530,19 +3536,23 @@ class NetEBComp : public NetEBinary {
|
|||
virtual NetEBComp* dup_expr() const;
|
||||
virtual NetEConst* eval_tree();
|
||||
|
||||
virtual NetExpr*evaluate_function(const LineInfo&loc,
|
||||
std::map<perm_string,NetExpr*>&ctx) const;
|
||||
|
||||
virtual NetNet* synthesize(Design*, NetScope*scope, NetExpr*root);
|
||||
|
||||
private:
|
||||
NetEConst* must_be_leeq_(NetExpr*le, const verinum&rv, bool eq_flag);
|
||||
NetEConst* must_be_leeq_(const NetExpr*le, const verinum&rv, bool eq_flag) const;
|
||||
|
||||
NetEConst*eval_eqeq_(bool ne_flag);
|
||||
NetEConst*eval_eqeq_real_(bool ne_flag);
|
||||
NetEConst*eval_less_();
|
||||
NetEConst*eval_leeq_();
|
||||
NetEConst*eval_leeq_real_(NetExpr*le, NetExpr*ri, bool eq_flag);
|
||||
NetEConst*eval_gt_();
|
||||
NetEConst*eval_gteq_();
|
||||
NetEConst*eval_eqeqeq_(bool ne_flag);
|
||||
NetEConst*eval_arguments_(const NetExpr*le, const NetExpr*re) const;
|
||||
NetEConst*eval_eqeq_(bool ne_flag, const NetExpr*le, const NetExpr*re) const;
|
||||
NetEConst*eval_eqeq_real_(bool ne_flag, const NetExpr*le, const NetExpr*re) const;
|
||||
NetEConst*eval_less_(const NetExpr*le, const NetExpr*re) const;
|
||||
NetEConst*eval_leeq_(const NetExpr*le, const NetExpr*re) const;
|
||||
NetEConst*eval_leeq_real_(const NetExpr*le, const NetExpr*ri, bool eq_flag) const;
|
||||
NetEConst*eval_gt_(const NetExpr*le, const NetExpr*re) const;
|
||||
NetEConst*eval_gteq_(const NetExpr*le, const NetExpr*re) const;
|
||||
NetEConst*eval_eqeqeq_(bool ne_flag, const NetExpr*le, const NetExpr*re) const;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -3644,9 +3654,13 @@ class NetEBShift : public NetEBinary {
|
|||
virtual NetEBShift* dup_expr() const;
|
||||
virtual NetEConst* eval_tree();
|
||||
|
||||
virtual NetExpr*evaluate_function(const LineInfo&loc,
|
||||
std::map<perm_string,NetExpr*>&ctx) const;
|
||||
|
||||
virtual NetNet* synthesize(Design*, NetScope*scope, NetExpr*root);
|
||||
|
||||
private:
|
||||
NetEConst* eval_arguments_(const NetExpr*l, const NetExpr*r) const;
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -3978,6 +3992,9 @@ class NetESignal : public NetExpr {
|
|||
NetNet* synthesize(Design*des, NetScope*scope, NetExpr*root);
|
||||
NexusSet* nex_input(bool rem_out = true);
|
||||
|
||||
virtual NetExpr*evaluate_function(const LineInfo&loc,
|
||||
std::map<perm_string,NetExpr*>&ctx) const;
|
||||
|
||||
// This is the expression for selecting an array word, if this
|
||||
// signal refers to an array.
|
||||
const NetExpr* word_index() const;
|
||||
|
|
|
|||
Loading…
Reference in New Issue