Make eval_tree mixed case div/mod work.
This patch makes constant mixed case division or modulus optimize correctly. The modulus is only done if the gn_icarus_misc_flag is set.
This commit is contained in:
parent
f2f7933708
commit
f993e78185
119
eval_tree.cc
119
eval_tree.cc
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1999-2008 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 1999-2009 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -818,6 +818,31 @@ NetEConst* NetEBComp::eval_tree(int prune_to_width)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NetExpr* NetEBDiv::eval_tree_real_()
|
||||||
|
{
|
||||||
|
verireal lval;
|
||||||
|
verireal rval;
|
||||||
|
|
||||||
|
bool flag = get_real_arguments_(lval, rval);
|
||||||
|
if (! flag) return 0;
|
||||||
|
|
||||||
|
NetECReal*res = 0;
|
||||||
|
switch (op_) {
|
||||||
|
case '/':
|
||||||
|
res = new NetECReal(lval / rval);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '%':
|
||||||
|
// Since this could be called early we don't want this to leak functionality.
|
||||||
|
if (!gn_icarus_misc_flag) return 0;
|
||||||
|
res = new NetECReal(verireal(fmod(lval.as_double(), rval.as_double())));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ivl_assert(*this, res);
|
||||||
|
res->set_line(*this);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The NetEBDiv operator includes the / and % operators. First evaluate
|
* The NetEBDiv operator includes the / and % operators. First evaluate
|
||||||
* the sub-expressions, then perform the required operation.
|
* the sub-expressions, then perform the required operation.
|
||||||
|
|
@ -827,77 +852,31 @@ NetExpr* NetEBDiv::eval_tree(int prune_to_width)
|
||||||
eval_expr(left_);
|
eval_expr(left_);
|
||||||
eval_expr(right_);
|
eval_expr(right_);
|
||||||
|
|
||||||
if (expr_type() == IVL_VT_REAL) {
|
if (expr_type() == IVL_VT_REAL) return eval_tree_real_();
|
||||||
NetECReal*lc = dynamic_cast<NetECReal*>(left_);
|
|
||||||
if (lc == 0) return 0;
|
assert(expr_type() == IVL_VT_LOGIC);
|
||||||
|
|
||||||
verireal lval = lc->value();
|
NetEConst*lc = dynamic_cast<NetEConst*>(left_);
|
||||||
|
NetEConst*rc = dynamic_cast<NetEConst*>(right_);
|
||||||
|
if (lc == 0 || rc == 0) return 0;
|
||||||
|
|
||||||
if (NetECReal*rcr = dynamic_cast<NetECReal*>(right_)) {
|
// Make sure the expression is evaluated at the
|
||||||
NetECReal*tmp = 0;
|
// expression width.
|
||||||
verireal rval = rcr->value();
|
verinum lval = pad_to_width(lc->value(), expr_width());
|
||||||
|
verinum rval = pad_to_width(rc->value(), expr_width());
|
||||||
|
|
||||||
switch (op_) {
|
NetExpr*tmp = 0;
|
||||||
case '/':
|
switch (op_) {
|
||||||
tmp = new NetECReal(lval / rval);
|
case '/':
|
||||||
break;
|
tmp = new NetEConst(lval / rval);
|
||||||
|
break;
|
||||||
case '%':
|
case '%':
|
||||||
tmp = new NetECReal(lval % rval);
|
tmp = new NetEConst(lval % rval);
|
||||||
}
|
break;
|
||||||
|
|
||||||
assert(tmp);
|
|
||||||
tmp->set_line(*this);
|
|
||||||
return tmp;
|
|
||||||
|
|
||||||
} else if (NetEConst*rc = dynamic_cast<NetEConst*>(right_)) {
|
|
||||||
|
|
||||||
NetECReal*tmp = 0;
|
|
||||||
verinum rval = rc->value();
|
|
||||||
|
|
||||||
switch (op_) {
|
|
||||||
case '/':
|
|
||||||
tmp = new NetECReal(lval / rval);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case '%':
|
|
||||||
tmp = new NetECReal(lval % rval);
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(tmp);
|
|
||||||
tmp->set_line(*this);
|
|
||||||
return tmp;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
} else {
|
|
||||||
assert(expr_type() == IVL_VT_LOGIC);
|
|
||||||
NetEConst*lc = dynamic_cast<NetEConst*>(left_);
|
|
||||||
if (lc == 0) return 0;
|
|
||||||
NetEConst*rc = dynamic_cast<NetEConst*>(right_);
|
|
||||||
if (rc == 0) return 0;
|
|
||||||
|
|
||||||
// Make sure the expression is evaluated at the
|
|
||||||
// expression width.
|
|
||||||
verinum lval = pad_to_width(lc->value(), expr_width());
|
|
||||||
verinum rval = pad_to_width(rc->value(), expr_width());
|
|
||||||
|
|
||||||
NetExpr*tmp = 0;
|
|
||||||
switch (op_) {
|
|
||||||
case '/':
|
|
||||||
tmp = new NetEConst(lval / rval);
|
|
||||||
break;
|
|
||||||
case '%':
|
|
||||||
tmp = new NetEConst(lval % rval);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
ivl_assert(*this, tmp);
|
|
||||||
tmp->set_line(*this);
|
|
||||||
return tmp;
|
|
||||||
}
|
}
|
||||||
|
ivl_assert(*this, tmp);
|
||||||
return 0;
|
tmp->set_line(*this);
|
||||||
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
NetEConst* NetEBLogic::eval_tree(int prune_to_width)
|
NetEConst* NetEBLogic::eval_tree(int prune_to_width)
|
||||||
|
|
@ -976,7 +955,6 @@ NetExpr* NetEBMult::eval_tree_real_()
|
||||||
bool flag = get_real_arguments_(lval, rval);
|
bool flag = get_real_arguments_(lval, rval);
|
||||||
if (! flag) return 0;
|
if (! flag) return 0;
|
||||||
|
|
||||||
|
|
||||||
NetECReal*res = new NetECReal(lval * rval);
|
NetECReal*res = new NetECReal(lval * rval);
|
||||||
res->set_line(*this);
|
res->set_line(*this);
|
||||||
return res;
|
return res;
|
||||||
|
|
@ -987,8 +965,7 @@ NetExpr* NetEBMult::eval_tree(int prune_to_width)
|
||||||
eval_expr(left_);
|
eval_expr(left_);
|
||||||
eval_expr(right_);
|
eval_expr(right_);
|
||||||
|
|
||||||
if (expr_type() == IVL_VT_REAL)
|
if (expr_type() == IVL_VT_REAL) return eval_tree_real_();
|
||||||
return eval_tree_real_();
|
|
||||||
|
|
||||||
assert(expr_type() == IVL_VT_LOGIC);
|
assert(expr_type() == IVL_VT_LOGIC);
|
||||||
|
|
||||||
|
|
|
||||||
10
netlist.h
10
netlist.h
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef __netlist_H
|
#ifndef __netlist_H
|
||||||
#define __netlist_H
|
#define __netlist_H
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1998-2008 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 1998-2009 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -3276,6 +3276,9 @@ class NetEBDiv : public NetEBinary {
|
||||||
virtual NetEBDiv* dup_expr() const;
|
virtual NetEBDiv* dup_expr() const;
|
||||||
virtual NetExpr* eval_tree(int prune_to_width = -1);
|
virtual NetExpr* eval_tree(int prune_to_width = -1);
|
||||||
virtual NetNet* synthesize(Design*, NetScope*scope, NetExpr*root);
|
virtual NetNet* synthesize(Design*, NetScope*scope, NetExpr*root);
|
||||||
|
|
||||||
|
private:
|
||||||
|
NetExpr* eval_tree_real_();
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -3386,7 +3389,6 @@ class NetEBMinMax : public NetEBinary {
|
||||||
virtual ivl_variable_type_t expr_type() const;
|
virtual ivl_variable_type_t expr_type() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -3406,9 +3408,7 @@ class NetEBMult : public NetEBinary {
|
||||||
virtual NetNet* synthesize(Design*, NetScope*scope, NetExpr*root);
|
virtual NetNet* synthesize(Design*, NetScope*scope, NetExpr*root);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
NetExpr* eval_tree_real_();
|
NetExpr* eval_tree_real_();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -3428,9 +3428,7 @@ class NetEBPow : public NetEBinary {
|
||||||
virtual NetNet* synthesize(Design*, NetScope*scope, NetExpr*root);
|
virtual NetNet* synthesize(Design*, NetScope*scope, NetExpr*root);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
NetExpr* eval_tree_real_();
|
NetExpr* eval_tree_real_();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue