More eval_tree rework and add support for ! of a real.
This commit is contained in:
parent
ccf01cc665
commit
ab8557eaf0
|
|
@ -1325,6 +1325,9 @@ void NetEBinary::dump(ostream&o) const
|
||||||
case 'a':
|
case 'a':
|
||||||
o << "&&";
|
o << "&&";
|
||||||
break;
|
break;
|
||||||
|
case 'A':
|
||||||
|
o << "~&";
|
||||||
|
break;
|
||||||
case 'E':
|
case 'E':
|
||||||
o << "===";
|
o << "===";
|
||||||
break;
|
break;
|
||||||
|
|
@ -1498,12 +1501,18 @@ void NetEUFunc::dump(ostream&o) const
|
||||||
void NetEUnary::dump(ostream&o) const
|
void NetEUnary::dump(ostream&o) const
|
||||||
{
|
{
|
||||||
switch (op_) {
|
switch (op_) {
|
||||||
|
case 'A':
|
||||||
|
o << "~&";
|
||||||
|
break;
|
||||||
case 'm':
|
case 'm':
|
||||||
o << "abs";
|
o << "abs";
|
||||||
break;
|
break;
|
||||||
case 'N':
|
case 'N':
|
||||||
o << "~|";
|
o << "~|";
|
||||||
break;
|
break;
|
||||||
|
case 'X':
|
||||||
|
o << "~^";
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
o << op_;
|
o << op_;
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
140
eval_tree.cc
140
eval_tree.cc
|
|
@ -899,21 +899,19 @@ NetEConst* NetEBLogic::eval_tree_real_()
|
||||||
|
|
||||||
verinum::V res;
|
verinum::V res;
|
||||||
switch (op_) {
|
switch (op_) {
|
||||||
case 'a': { // Logical AND (&&)
|
case 'a': // Logical AND (&&)
|
||||||
if ((lval.as_double() != 0.0) && (rval.as_double() != 0.0))
|
if ((lval.as_double() != 0.0) && (rval.as_double() != 0.0))
|
||||||
res = verinum::V1;
|
res = verinum::V1;
|
||||||
else
|
else
|
||||||
res = verinum::V0;
|
res = verinum::V0;
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
case 'o': { // Logical OR (||)
|
case 'o': // Logical OR (||)
|
||||||
if ((lval.as_double() != 0.0) || (rval.as_double() != 0.0))
|
if ((lval.as_double() != 0.0) || (rval.as_double() != 0.0))
|
||||||
res = verinum::V1;
|
res = verinum::V1;
|
||||||
else
|
else
|
||||||
res = verinum::V0;
|
res = verinum::V0;
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -967,7 +965,7 @@ NetEConst* NetEBLogic::eval_tree(int)
|
||||||
|
|
||||||
verinum::V res;
|
verinum::V res;
|
||||||
switch (op_) {
|
switch (op_) {
|
||||||
case 'a': { // Logical AND (&&)
|
case 'a': // Logical AND (&&)
|
||||||
if ((lv == verinum::V0) || (rv == verinum::V0))
|
if ((lv == verinum::V0) || (rv == verinum::V0))
|
||||||
res = verinum::V0;
|
res = verinum::V0;
|
||||||
|
|
||||||
|
|
@ -978,9 +976,8 @@ NetEConst* NetEBLogic::eval_tree(int)
|
||||||
res = verinum::Vx;
|
res = verinum::Vx;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
case 'o': { // Logical OR (||)
|
case 'o': // Logical OR (||)
|
||||||
if ((lv == verinum::V1) || (rv == verinum::V1))
|
if ((lv == verinum::V1) || (rv == verinum::V1))
|
||||||
res = verinum::V1;
|
res = verinum::V1;
|
||||||
|
|
||||||
|
|
@ -991,7 +988,6 @@ NetEConst* NetEBLogic::eval_tree(int)
|
||||||
res = verinum::Vx;
|
res = verinum::Vx;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -1612,26 +1608,29 @@ NetExpr* NetEUnary::eval_tree_real_()
|
||||||
switch (op_) {
|
switch (op_) {
|
||||||
case '+':
|
case '+':
|
||||||
res = new NetECReal(val->value());
|
res = new NetECReal(val->value());
|
||||||
res->set_line(*this);
|
ivl_assert(*this, res);
|
||||||
return res;
|
break;
|
||||||
|
|
||||||
case '-':
|
case '-':
|
||||||
res = new NetECReal(-(val->value()));
|
res = new NetECReal(-(val->value()));
|
||||||
res->set_line(*this);
|
ivl_assert(*this, res);
|
||||||
return res;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
res->set_line(*this);
|
||||||
|
|
||||||
|
if (debug_eval_tree)
|
||||||
|
cerr << get_fileline() << ": debug: Evaluated (real): " << *this
|
||||||
|
<< " --> " << *res << endl;
|
||||||
|
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
NetExpr* NetEUnary::eval_tree(int prune_to_width)
|
NetExpr* NetEUnary::eval_tree(int prune_to_width)
|
||||||
{
|
{
|
||||||
if (debug_eval_tree) {
|
|
||||||
cerr << get_fileline() << ": debug: Evaluating expression:"
|
|
||||||
<< *this << ", prune_to_width=" << prune_to_width << endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
eval_expr(expr_);
|
eval_expr(expr_);
|
||||||
if (expr_type() == IVL_VT_REAL) return eval_tree_real_();
|
if (expr_type() == IVL_VT_REAL) return eval_tree_real_();
|
||||||
|
|
||||||
|
|
@ -1644,24 +1643,20 @@ NetExpr* NetEUnary::eval_tree(int prune_to_width)
|
||||||
|
|
||||||
case '+':
|
case '+':
|
||||||
/* Unary + is a no-op. */
|
/* Unary + is a no-op. */
|
||||||
return new NetEConst(val);
|
break;
|
||||||
|
|
||||||
case '-': {
|
case '-':
|
||||||
if (val.is_defined()) {
|
if (val.is_defined()) {
|
||||||
|
|
||||||
verinum tmp (verinum::V0, val.len());
|
verinum tmp (verinum::V0, val.len());
|
||||||
tmp.has_sign(val.has_sign());
|
tmp.has_sign(val.has_sign());
|
||||||
val = tmp - val;
|
val = tmp - val;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
for (unsigned idx = 0 ; idx < val.len() ; idx += 1)
|
for (unsigned idx = 0 ; idx < val.len() ; idx += 1)
|
||||||
val.set(idx, verinum::Vx);
|
val.set(idx, verinum::Vx);
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
return new NetEConst(val);
|
case '~':
|
||||||
}
|
|
||||||
|
|
||||||
case '~': {
|
|
||||||
/* Bitwise not is even simpler then logical
|
/* Bitwise not is even simpler then logical
|
||||||
not. Just invert all the bits of the operand and
|
not. Just invert all the bits of the operand and
|
||||||
make the new value with the same dimensions. */
|
make the new value with the same dimensions. */
|
||||||
|
|
@ -1677,14 +1672,23 @@ NetExpr* NetEUnary::eval_tree(int prune_to_width)
|
||||||
val.set(idx, verinum::Vx);
|
val.set(idx, verinum::Vx);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new NetEConst(val);
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
case '!':
|
case '!':
|
||||||
assert(0);
|
assert(0);
|
||||||
default:
|
default:
|
||||||
return 0;
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1693,18 +1697,37 @@ NetExpr* NetEUBits::eval_tree(int prune_to_width)
|
||||||
return NetEUnary::eval_tree(prune_to_width);
|
return NetEUnary::eval_tree(prune_to_width);
|
||||||
}
|
}
|
||||||
|
|
||||||
NetEConst* NetEUReduce::eval_tree(int prune_to_width)
|
NetEConst* NetEUReduce::eval_tree_real_()
|
||||||
{
|
{
|
||||||
if (debug_eval_tree) {
|
ivl_assert(*this, op_ == '!');
|
||||||
cerr << get_fileline() << ": debug: Evaluating expression:"
|
|
||||||
<< *this << ", prune_to_width=" << prune_to_width << endl;
|
NetECReal*val= dynamic_cast<NetECReal*> (expr_);
|
||||||
|
if (val == 0) return 0;
|
||||||
|
|
||||||
|
verinum::V res = val->value().as_double() == 0.0 ? verinum::V1 :
|
||||||
|
verinum::V0;
|
||||||
|
|
||||||
|
NetEConst*tmp = new NetEConst(verinum(res, 1));
|
||||||
|
ivl_assert(*this, tmp);
|
||||||
|
tmp->set_line(*this);
|
||||||
|
|
||||||
|
if (debug_eval_tree)
|
||||||
|
cerr << get_fileline() << ": debug: Evaluated (real): " << *this
|
||||||
|
<< " --> " << *tmp << endl;
|
||||||
|
|
||||||
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NetEConst* NetEUReduce::eval_tree(int)
|
||||||
|
{
|
||||||
eval_expr(expr_);
|
eval_expr(expr_);
|
||||||
|
if (expr_type() == IVL_VT_REAL) return eval_tree_real_();
|
||||||
|
|
||||||
NetEConst*rval = dynamic_cast<NetEConst*>(expr_);
|
NetEConst*rval = dynamic_cast<NetEConst*>(expr_);
|
||||||
if (rval == 0) return 0;
|
if (rval == 0) return 0;
|
||||||
|
|
||||||
verinum val = rval->value();
|
verinum val = rval->value();
|
||||||
|
|
||||||
verinum::V res;
|
verinum::V res;
|
||||||
bool invert = false;
|
bool invert = false;
|
||||||
|
|
||||||
|
|
@ -1717,16 +1740,16 @@ NetEConst* NetEUReduce::eval_tree(int prune_to_width)
|
||||||
the result of ! is V0. If there are no V1 bits
|
the result of ! is V0. If there are no V1 bits
|
||||||
but there are some Vx/Vz bits, the result is
|
but there are some Vx/Vz bits, the result is
|
||||||
unknown. Otherwise, the result is V1. */
|
unknown. Otherwise, the result is V1. */
|
||||||
unsigned v1 = 0, vx = 0;
|
bool v1 = false, vx = false;
|
||||||
for (unsigned idx = 0 ; idx < val.len() ; idx += 1) {
|
for (unsigned idx = 0 ; idx < val.len() && !v1 ; idx += 1) {
|
||||||
switch (val.get(idx)) {
|
switch (val.get(idx)) {
|
||||||
case verinum::V0:
|
case verinum::V0:
|
||||||
break;
|
break;
|
||||||
case verinum::V1:
|
case verinum::V1:
|
||||||
v1 += 1;
|
v1 = true;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
vx += 1;
|
vx = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1781,15 +1804,27 @@ NetEConst* NetEUReduce::eval_tree(int prune_to_width)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (invert) res = ~res;
|
if (invert) res = ~res;
|
||||||
return new NetEConst(verinum(res, 1));
|
|
||||||
|
NetEConst*tmp = new NetEConst(verinum(res, 1));
|
||||||
|
ivl_assert(*this, tmp);
|
||||||
|
tmp->set_line(*this);
|
||||||
|
|
||||||
|
if (debug_eval_tree)
|
||||||
|
cerr << get_fileline() << ": debug: Evaluated: " << *this
|
||||||
|
<< " --> " << *tmp << endl;
|
||||||
|
|
||||||
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
NetExpr* evaluate_clog2(NetExpr*&arg_)
|
NetExpr* evaluate_clog2(NetExpr*&arg_)
|
||||||
{
|
{
|
||||||
eval_expr(arg_);
|
eval_expr(arg_);
|
||||||
|
|
||||||
NetEConst*tmpi = dynamic_cast<NetEConst *>(arg_);
|
NetEConst*tmpi = dynamic_cast<NetEConst *>(arg_);
|
||||||
NetECReal*tmpr = dynamic_cast<NetECReal *>(arg_);
|
NetECReal*tmpr = dynamic_cast<NetECReal *>(arg_);
|
||||||
if (tmpi || tmpr) {
|
|
||||||
|
if (tmpi == 0 && tmpr == 0) return 0;
|
||||||
|
|
||||||
verinum arg;
|
verinum arg;
|
||||||
if (tmpi) {
|
if (tmpi) {
|
||||||
arg = tmpi->value();
|
arg = tmpi->value();
|
||||||
|
|
@ -1797,16 +1832,19 @@ NetExpr* evaluate_clog2(NetExpr*&arg_)
|
||||||
arg = verinum(tmpr->value().as_double(), true);
|
arg = verinum(tmpr->value().as_double(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NetEConst*rtn;
|
||||||
|
|
||||||
/* If we have an x in the verinum we return 'bx. */
|
/* If we have an x in the verinum we return 'bx. */
|
||||||
if (!arg.is_defined()) {
|
if (!arg.is_defined()) {
|
||||||
verinum tmp (verinum::Vx, integer_width);
|
verinum tmp (verinum::Vx, integer_width);
|
||||||
tmp.has_sign(true);
|
tmp.has_sign(true);
|
||||||
NetEConst*rtn = new NetEConst(tmp);
|
|
||||||
return rtn;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
rtn = new NetEConst(tmp);
|
||||||
|
ivl_assert(*arg_, rtn);
|
||||||
|
} else {
|
||||||
bool is_neg = false;
|
bool is_neg = false;
|
||||||
uint64_t res = 0;
|
uint64_t res = 0;
|
||||||
|
|
||||||
if (arg.is_negative()) {
|
if (arg.is_negative()) {
|
||||||
is_neg = true;
|
is_neg = true;
|
||||||
// If the length is not defined, then work with
|
// If the length is not defined, then work with
|
||||||
|
|
@ -1829,11 +1867,12 @@ NetExpr* evaluate_clog2(NetExpr*&arg_)
|
||||||
|
|
||||||
verinum tmp (res, integer_width);
|
verinum tmp (res, integer_width);
|
||||||
tmp.has_sign(true);
|
tmp.has_sign(true);
|
||||||
NetEConst*rtn = new NetEConst(tmp);
|
|
||||||
return rtn;
|
rtn = new NetEConst(tmp);
|
||||||
|
ivl_assert(*arg_, rtn);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return rtn;
|
||||||
}
|
}
|
||||||
|
|
||||||
NetExpr* evaluate_math_one_arg(NetExpr*&arg_, const char*name)
|
NetExpr* evaluate_math_one_arg(NetExpr*&arg_, const char*name)
|
||||||
|
|
@ -1987,11 +2026,8 @@ NetExpr* evaluate_min_max(NetExpr*&arg0_, NetExpr*&arg1_, const char*name)
|
||||||
|
|
||||||
NetExpr* NetESFunc::eval_tree(int prune_to_width)
|
NetExpr* NetESFunc::eval_tree(int prune_to_width)
|
||||||
{
|
{
|
||||||
if (debug_eval_tree) {
|
// assert(prune_to_width <= 0);
|
||||||
cerr << get_fileline() << ": debug: Evaluating expression:"
|
// HERE
|
||||||
<< *this << ", prune_to_width=" << prune_to_width << endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If we are not targeting at least Verilog-2005, Verilog-AMS
|
/* If we are not targeting at least Verilog-2005, Verilog-AMS
|
||||||
* or using the Icarus misc flag then we do not support these
|
* or using the Icarus misc flag then we do not support these
|
||||||
* functions as constant. */
|
* functions as constant. */
|
||||||
|
|
@ -2080,10 +2116,10 @@ NetExpr* NetESFunc::eval_tree(int prune_to_width)
|
||||||
|
|
||||||
if (rtn != 0) {
|
if (rtn != 0) {
|
||||||
rtn->set_line(*this);
|
rtn->set_line(*this);
|
||||||
if (debug_eval_tree) {
|
|
||||||
cerr << get_fileline() << ": debug: Evaluate constant "
|
if (debug_eval_tree)
|
||||||
<< nm << "." << endl;
|
cerr << get_fileline() << ": debug: Evaluated: " << *this
|
||||||
}
|
<< " --> " << *rtn << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
return rtn;
|
return rtn;
|
||||||
|
|
|
||||||
|
|
@ -3832,6 +3832,9 @@ class NetEUReduce : public NetEUnary {
|
||||||
virtual NetEUReduce* dup_expr() const;
|
virtual NetEUReduce* dup_expr() const;
|
||||||
virtual NetEConst* eval_tree(int prune_to_width = -1);
|
virtual NetEConst* eval_tree(int prune_to_width = -1);
|
||||||
virtual ivl_variable_type_t expr_type() const;
|
virtual ivl_variable_type_t expr_type() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
virtual NetEConst* eval_tree_real_();
|
||||||
};
|
};
|
||||||
|
|
||||||
class NetECast : public NetEUnary {
|
class NetECast : public NetEUnary {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue