More expression types work in constant functions.
This commit is contained in:
parent
def9d0ea1d
commit
a5a7050120
298
eval_tree.cc
298
eval_tree.cc
|
|
@ -34,11 +34,11 @@ NetExpr* NetExpr::eval_tree()
|
||||||
return 0;
|
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()) {
|
switch (expr->expr_type()) {
|
||||||
case IVL_VT_REAL: {
|
case IVL_VT_REAL: {
|
||||||
NetECReal*c = dynamic_cast<NetECReal*> (expr);
|
const NetECReal*c = dynamic_cast<const NetECReal*> (expr);
|
||||||
if (c == 0) return false;
|
if (c == 0) return false;
|
||||||
val = c->value();
|
val = c->value();
|
||||||
break;
|
break;
|
||||||
|
|
@ -46,7 +46,7 @@ static bool get_real_arg_(NetExpr*expr, verireal&val)
|
||||||
|
|
||||||
case IVL_VT_BOOL:
|
case IVL_VT_BOOL:
|
||||||
case IVL_VT_LOGIC: {
|
case IVL_VT_LOGIC: {
|
||||||
NetEConst*c = dynamic_cast<NetEConst*>(expr);
|
const NetEConst*c = dynamic_cast<const NetEConst*>(expr);
|
||||||
if (c == 0) return false;
|
if (c == 0) return false;
|
||||||
verinum tmp = c->value();
|
verinum tmp = c->value();
|
||||||
val = verireal(tmp.as_double());
|
val = verireal(tmp.as_double());
|
||||||
|
|
@ -60,7 +60,7 @@ static bool get_real_arg_(NetExpr*expr, verireal&val)
|
||||||
return true;
|
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)
|
double&lval, double&rval)
|
||||||
{
|
{
|
||||||
verireal val;
|
verireal val;
|
||||||
|
|
@ -82,15 +82,15 @@ bool NetEBinary::get_real_arguments_(verireal&lval, verireal&rval)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
NetECReal* NetEBAdd::eval_tree_real_()
|
NetECReal* NetEBAdd::eval_tree_real_(const NetExpr*l, const NetExpr*r) const
|
||||||
{
|
{
|
||||||
verireal lval;
|
double lval;
|
||||||
verireal rval;
|
double rval;
|
||||||
|
|
||||||
bool flag = get_real_arguments_(lval, rval);
|
bool flag = get_real_arguments(l, r, lval, rval);
|
||||||
if (!flag) return 0;
|
if (!flag) return 0;
|
||||||
|
|
||||||
verireal res_val;
|
double res_val;
|
||||||
|
|
||||||
switch (op()) {
|
switch (op()) {
|
||||||
case '+':
|
case '+':
|
||||||
|
|
@ -103,7 +103,7 @@ NetECReal* NetEBAdd::eval_tree_real_()
|
||||||
ivl_assert(*this, 0);
|
ivl_assert(*this, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
NetECReal*res = new NetECReal( res_val );
|
NetECReal*res = new NetECReal( verireal(res_val) );
|
||||||
ivl_assert(*this, res);
|
ivl_assert(*this, res);
|
||||||
res->set_line(*this);
|
res->set_line(*this);
|
||||||
|
|
||||||
|
|
@ -119,52 +119,24 @@ NetExpr* NetEBAdd::eval_tree()
|
||||||
eval_expr(left_);
|
eval_expr(left_);
|
||||||
eval_expr(right_);
|
eval_expr(right_);
|
||||||
|
|
||||||
if (expr_type() == IVL_VT_REAL)
|
// First try to elaborate the expression completely.
|
||||||
return eval_tree_real_();
|
NetExpr*res = eval_arguments_(left_,right_);
|
||||||
|
if (res != 0)
|
||||||
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;
|
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
|
||||||
|
|
||||||
/* Try to combine a right constant value with the right
|
// If the expression type is real, then do not attempt the
|
||||||
constant value of a sub-expression add. For example, the
|
// following alternative processing.
|
||||||
expression (a + 2) - 1 can be rewritten as a + 1. */
|
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_);
|
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) {
|
if (lc != 0 && rc != 0) {
|
||||||
ivl_assert(*this, se != 0);
|
ivl_assert(*this, se != 0);
|
||||||
|
|
@ -200,11 +172,56 @@ NetExpr* NetEBAdd::eval_tree()
|
||||||
tmp->set_line(*right_);
|
tmp->set_line(*right_);
|
||||||
delete right_;
|
delete right_;
|
||||||
right_ = tmp;
|
right_ = tmp;
|
||||||
/* We've changed the subexpression, but the result is
|
}
|
||||||
still not constant, so return nil here anyhow. */
|
|
||||||
|
// We may have changed the subexpression, but the result is
|
||||||
|
// still not constant, so return nil here anyhow.
|
||||||
return 0;
|
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. */
|
/* Nothing more to be done, the value is not constant. */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -276,13 +293,12 @@ NetEConst* NetEBBits::eval_tree()
|
||||||
return new NetEConst(res);
|
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 ||
|
if (le->expr_type() == IVL_VT_REAL || re->expr_type() == IVL_VT_REAL)
|
||||||
left_->expr_type() == IVL_VT_REAL)
|
return eval_leeq_real_(le, re, false);
|
||||||
return eval_leeq_real_(left_, right_, false);
|
|
||||||
|
|
||||||
NetEConst*rc = dynamic_cast<NetEConst*>(right_);
|
const NetEConst*rc = dynamic_cast<const NetEConst*>(re);
|
||||||
if (rc == 0) return 0;
|
if (rc == 0) return 0;
|
||||||
|
|
||||||
verinum rv = rc->value();
|
verinum rv = rc->value();
|
||||||
|
|
@ -292,12 +308,12 @@ NetEConst* NetEBComp::eval_less_()
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NetEConst*tmp = must_be_leeq_(left_, rv, false)) {
|
if (NetEConst*tmp = must_be_leeq_(le, rv, false)) {
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now go on to the normal test of the values. */
|
/* 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;
|
if (lc == 0) return 0;
|
||||||
|
|
||||||
verinum lv = lc->value();
|
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);
|
assert(le->expr_width() > 0);
|
||||||
verinum lv (verinum::V1, le->expr_width());
|
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;
|
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 lval;
|
||||||
double rval;
|
double rval;
|
||||||
|
|
@ -358,14 +374,13 @@ NetEConst* NetEBComp::eval_leeq_real_(NetExpr*le, NetExpr*re, bool eq_flag)
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
NetEConst* NetEBComp::eval_leeq_()
|
NetEConst* NetEBComp::eval_leeq_(const NetExpr*le, const NetExpr*re) const
|
||||||
{
|
{
|
||||||
if (right_->expr_type() == IVL_VT_REAL ||
|
if (le->expr_type() == IVL_VT_REAL || re->expr_type() == IVL_VT_REAL)
|
||||||
left_->expr_type() == IVL_VT_REAL)
|
return eval_leeq_real_(le, re, true);
|
||||||
return eval_leeq_real_(left_, right_, true);
|
|
||||||
// assert(expr_type() == IVL_VT_LOGIC);
|
// 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;
|
if (r == 0) return 0;
|
||||||
|
|
||||||
verinum rv = r->value();
|
verinum rv = r->value();
|
||||||
|
|
@ -375,18 +390,18 @@ NetEConst* NetEBComp::eval_leeq_()
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (left_->expr_width() == 0) {
|
if (le->expr_width() == 0) {
|
||||||
cerr << get_fileline() << ": internal error: Something wrong "
|
cerr << get_fileline() << ": internal error: Something wrong "
|
||||||
<< "with the left side width of <= ?" << endl;
|
<< "with the left side width of <= ?" << endl;
|
||||||
cerr << get_fileline() << ": : " << *this << 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;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now go on to the normal test of the values. */
|
/* 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;
|
if (l == 0) return 0;
|
||||||
|
|
||||||
verinum lv = l->value();
|
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 ||
|
if (le->expr_type() == IVL_VT_REAL || re->expr_type() == IVL_VT_REAL)
|
||||||
left_->expr_type() == IVL_VT_REAL)
|
return eval_leeq_real_(re, le, false);
|
||||||
return eval_leeq_real_(right_, left_, false);
|
|
||||||
|
|
||||||
NetEConst*l = dynamic_cast<NetEConst*>(left_);
|
const NetEConst*l = dynamic_cast<const NetEConst*>(le);
|
||||||
if (l == 0) return 0;
|
if (l == 0) return 0;
|
||||||
|
|
||||||
verinum lv = l->value();
|
verinum lv = l->value();
|
||||||
|
|
@ -423,12 +437,12 @@ NetEConst* NetEBComp::eval_gt_()
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NetEConst*tmp = must_be_leeq_(right_, lv, false)) {
|
if (NetEConst*tmp = must_be_leeq_(re, lv, false)) {
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now go on to the normal test of the values. */
|
/* 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;
|
if (r == 0) return 0;
|
||||||
|
|
||||||
verinum rv = r->value();
|
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 ||
|
if (le->expr_type() == IVL_VT_REAL || re->expr_type() == IVL_VT_REAL)
|
||||||
left_->expr_type() == IVL_VT_REAL)
|
return eval_leeq_real_(re, le, true);
|
||||||
return eval_leeq_real_(right_, left_, true);
|
|
||||||
|
|
||||||
NetEConst*l = dynamic_cast<NetEConst*>(left_);
|
const NetEConst*l = dynamic_cast<const NetEConst*>(left_);
|
||||||
if (l == 0) return 0;
|
if (l == 0) return 0;
|
||||||
|
|
||||||
verinum lv = l->value();
|
verinum lv = l->value();
|
||||||
|
|
@ -465,12 +478,12 @@ NetEConst* NetEBComp::eval_gteq_()
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NetEConst*tmp = must_be_leeq_(right_, lv, true)) {
|
if (NetEConst*tmp = must_be_leeq_(re, lv, true)) {
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now go on to the normal test of the values. */
|
/* 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;
|
if (r == 0) return 0;
|
||||||
|
|
||||||
verinum rv = r->value();
|
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
|
* are equal, but there are are x/z bits, then the situation is
|
||||||
* ambiguous so the result is x.
|
* 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;
|
double lval;
|
||||||
verireal rval;
|
double rval;
|
||||||
|
|
||||||
bool flag = get_real_arguments_(lval, rval);
|
bool flag = get_real_arguments(le, re, lval, rval);
|
||||||
if (! flag) return 0;
|
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);
|
verinum::V1 : verinum::V0, 1);
|
||||||
NetEConst*res = new NetEConst(result);
|
NetEConst*res = new NetEConst(result);
|
||||||
ivl_assert(*this, res);
|
ivl_assert(*this, res);
|
||||||
|
|
@ -514,14 +527,14 @@ NetEConst* NetEBComp::eval_eqeq_real_(bool ne_flag)
|
||||||
return res;
|
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 ||
|
if (le->expr_type() == IVL_VT_REAL ||
|
||||||
right_->expr_type() == IVL_VT_REAL)
|
re->expr_type() == IVL_VT_REAL)
|
||||||
return eval_eqeq_real_(ne_flag);
|
return eval_eqeq_real_(ne_flag, le, re);
|
||||||
|
|
||||||
NetEConst*lc = dynamic_cast<NetEConst*>(left_);
|
const NetEConst*lc = dynamic_cast<const NetEConst*>(le);
|
||||||
NetEConst*rc = dynamic_cast<NetEConst*>(right_);
|
const NetEConst*rc = dynamic_cast<const NetEConst*>(re);
|
||||||
if (lc == 0 || rc == 0) return 0;
|
if (lc == 0 || rc == 0) return 0;
|
||||||
|
|
||||||
const verinum&lv = lc->value();
|
const verinum&lv = lc->value();
|
||||||
|
|
@ -631,10 +644,10 @@ NetEConst* NetEBComp::eval_eqeq_(bool ne_flag)
|
||||||
return result;
|
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_);
|
const NetEConst*lc = dynamic_cast<const NetEConst*>(le);
|
||||||
NetEConst*rc = dynamic_cast<NetEConst*>(right_);
|
const NetEConst*rc = dynamic_cast<const NetEConst*>(re);
|
||||||
if (lc == 0 || rc == 0) return 0;
|
if (lc == 0 || rc == 0) return 0;
|
||||||
|
|
||||||
const verinum&lv = lc->value();
|
const verinum&lv = lc->value();
|
||||||
|
|
@ -687,47 +700,54 @@ NetEConst* NetEBComp::eval_eqeqeq_(bool ne_flag)
|
||||||
return result;
|
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()
|
NetEConst* NetEBComp::eval_tree()
|
||||||
{
|
{
|
||||||
eval_expr(left_);
|
eval_expr(left_);
|
||||||
eval_expr(right_);
|
eval_expr(right_);
|
||||||
|
|
||||||
NetEConst*res = 0;
|
NetEConst*res = eval_arguments_(left_, right_);
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
}
|
|
||||||
if (res == 0) return 0;
|
if (res == 0) return 0;
|
||||||
res->set_line(*this);
|
res->set_line(*this);
|
||||||
|
|
||||||
|
|
@ -1043,9 +1063,13 @@ NetEConst* NetEBShift::eval_tree()
|
||||||
{
|
{
|
||||||
eval_expr(left_);
|
eval_expr(left_);
|
||||||
eval_expr(right_);
|
eval_expr(right_);
|
||||||
|
return eval_arguments_(left_,right_);
|
||||||
|
}
|
||||||
|
|
||||||
NetEConst*le = dynamic_cast<NetEConst*>(left_);
|
NetEConst* NetEBShift::eval_arguments_(const NetExpr*l, const NetExpr*r) const
|
||||||
NetEConst*re = dynamic_cast<NetEConst*>(right_);
|
{
|
||||||
|
const NetEConst*le = dynamic_cast<const NetEConst*>(l);
|
||||||
|
const NetEConst*re = dynamic_cast<const NetEConst*>(r);
|
||||||
if (le == 0 || re == 0) return 0;
|
if (le == 0 || re == 0) return 0;
|
||||||
|
|
||||||
NetEConst*res;
|
NetEConst*res;
|
||||||
|
|
|
||||||
133
net_func_eval.cc
133
net_func_eval.cc
|
|
@ -18,6 +18,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
# include "netlist.h"
|
# include "netlist.h"
|
||||||
|
# include "compiler.h"
|
||||||
# include <typeinfo>
|
# include <typeinfo>
|
||||||
# include "ivl_assert.h"
|
# 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*>::iterator ptr;
|
||||||
map<perm_string,NetExpr*>context_map;
|
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...
|
// Put the return value into the map...
|
||||||
context_map[scope_->basename()] = 0;
|
context_map[scope_->basename()] = 0;
|
||||||
// Load the input ports into the map...
|
// 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();
|
NetExpr*tmp = args[idx]->dup_expr();
|
||||||
perm_string aname = ports_[idx]->name();
|
perm_string aname = ports_[idx]->name();
|
||||||
context_map[aname] = tmp;
|
context_map[aname] = tmp;
|
||||||
|
|
||||||
|
if (debug_eval_tree) {
|
||||||
|
cerr << loc.get_fileline() << ": debug: "
|
||||||
|
<< " input " << aname << " = " << *tmp << endl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Perform the evaluation
|
// 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());
|
map<perm_string,NetExpr*>::iterator ptr = context_map.find(lval->name());
|
||||||
if (ptr->second)
|
if (ptr->second)
|
||||||
delete 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;
|
ptr->second = rval_result;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -123,6 +141,103 @@ bool NetBlock::evaluate_function(const LineInfo&loc,
|
||||||
return flag;
|
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&,
|
NetExpr* NetEConst::evaluate_function(const LineInfo&,
|
||||||
map<perm_string,NetExpr*>&) const
|
map<perm_string,NetExpr*>&) const
|
||||||
|
|
@ -131,3 +246,21 @@ NetExpr* NetEConst::evaluate_function(const LineInfo&,
|
||||||
res->set_line(*this);
|
res->set_line(*this);
|
||||||
return res;
|
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 bool emit_proc(struct target_t*) const;
|
||||||
virtual void dump(ostream&, unsigned ind) const;
|
virtual void dump(ostream&, unsigned ind) const;
|
||||||
virtual DelayType delay_type() const;
|
virtual DelayType delay_type() const;
|
||||||
|
virtual bool evaluate_function(const LineInfo&loc,
|
||||||
|
map<perm_string,NetExpr*>&ctx) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NetExpr* cond_;
|
NetExpr* cond_;
|
||||||
|
|
@ -3451,10 +3453,14 @@ class NetEBAdd : public NetEBinary {
|
||||||
|
|
||||||
virtual NetEBAdd* dup_expr() const;
|
virtual NetEBAdd* dup_expr() const;
|
||||||
virtual NetExpr* eval_tree();
|
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);
|
virtual NetNet* synthesize(Design*, NetScope*scope, NetExpr*root);
|
||||||
|
|
||||||
private:
|
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 NetEBComp* dup_expr() const;
|
||||||
virtual NetEConst* eval_tree();
|
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);
|
virtual NetNet* synthesize(Design*, NetScope*scope, NetExpr*root);
|
||||||
|
|
||||||
private:
|
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_arguments_(const NetExpr*le, const NetExpr*re) const;
|
||||||
NetEConst*eval_eqeq_real_(bool ne_flag);
|
NetEConst*eval_eqeq_(bool ne_flag, const NetExpr*le, const NetExpr*re) const;
|
||||||
NetEConst*eval_less_();
|
NetEConst*eval_eqeq_real_(bool ne_flag, const NetExpr*le, const NetExpr*re) const;
|
||||||
NetEConst*eval_leeq_();
|
NetEConst*eval_less_(const NetExpr*le, const NetExpr*re) const;
|
||||||
NetEConst*eval_leeq_real_(NetExpr*le, NetExpr*ri, bool eq_flag);
|
NetEConst*eval_leeq_(const NetExpr*le, const NetExpr*re) const;
|
||||||
NetEConst*eval_gt_();
|
NetEConst*eval_leeq_real_(const NetExpr*le, const NetExpr*ri, bool eq_flag) const;
|
||||||
NetEConst*eval_gteq_();
|
NetEConst*eval_gt_(const NetExpr*le, const NetExpr*re) const;
|
||||||
NetEConst*eval_eqeqeq_(bool ne_flag);
|
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 NetEBShift* dup_expr() const;
|
||||||
virtual NetEConst* eval_tree();
|
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);
|
virtual NetNet* synthesize(Design*, NetScope*scope, NetExpr*root);
|
||||||
|
|
||||||
private:
|
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);
|
NetNet* synthesize(Design*des, NetScope*scope, NetExpr*root);
|
||||||
NexusSet* nex_input(bool rem_out = true);
|
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
|
// This is the expression for selecting an array word, if this
|
||||||
// signal refers to an array.
|
// signal refers to an array.
|
||||||
const NetExpr* word_index() const;
|
const NetExpr* word_index() const;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue