V0.9: back port fixes from development.
This patch back ports some fixes from development. It adds the ability to do signed === and !== correctly, adds support for && and || of real values in eval_tree and fixes an obscure bug in t-dll.cc.
This commit is contained in:
parent
29a69bacd0
commit
1c8e191918
186
eval_tree.cc
186
eval_tree.cc
|
|
@ -738,53 +738,61 @@ NetEConst* NetEBComp::eval_eqeq_(bool ne_flag)
|
||||||
return new NetEConst(verinum(res));
|
return new NetEConst(verinum(res));
|
||||||
}
|
}
|
||||||
|
|
||||||
NetEConst* NetEBComp::eval_eqeqeq_()
|
NetEConst* NetEBComp::eval_eqeqeq_(bool ne_flag)
|
||||||
{
|
{
|
||||||
NetEConst*l = dynamic_cast<NetEConst*>(left_);
|
NetEConst*lc = dynamic_cast<NetEConst*>(left_);
|
||||||
if (l == 0) return 0;
|
NetEConst*rc = dynamic_cast<NetEConst*>(right_);
|
||||||
NetEConst*r = dynamic_cast<NetEConst*>(right_);
|
if (lc == 0 || rc == 0) return 0;
|
||||||
if (r == 0) return 0;
|
|
||||||
|
|
||||||
const verinum&lv = l->value();
|
const verinum&lv = lc->value();
|
||||||
const verinum&rv = r->value();
|
const verinum&rv = rc->value();
|
||||||
|
|
||||||
verinum::V res = verinum::V1;
|
verinum::V res = verinum::V1;
|
||||||
|
|
||||||
|
// Find the smallest argument length.
|
||||||
unsigned cnt = lv.len();
|
unsigned cnt = lv.len();
|
||||||
if (cnt > rv.len())
|
if (cnt > rv.len()) cnt = rv.len();
|
||||||
cnt = rv.len();
|
|
||||||
|
|
||||||
|
// Check the common bits.
|
||||||
for (unsigned idx = 0 ; idx < cnt ; idx += 1)
|
for (unsigned idx = 0 ; idx < cnt ; idx += 1)
|
||||||
if (lv.get(idx) != rv.get(idx))
|
if (lv.get(idx) != rv.get(idx)) {
|
||||||
res = verinum::V0;
|
res = verinum::V0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
for (unsigned idx = cnt ; idx < lv.len() ; idx += 1)
|
bool is_signed = lv.has_sign() && rv.has_sign();
|
||||||
if (lv.get(idx) != verinum::V0)
|
|
||||||
res = verinum::V0;
|
|
||||||
|
|
||||||
for (unsigned idx = cnt ; idx < rv.len() ; idx += 1)
|
// If the left value is longer check it against the pad bit.
|
||||||
if (rv.get(idx) != verinum::V0)
|
if (res == verinum::V1) {
|
||||||
res = verinum::V0;
|
verinum::V pad = verinum::V0;
|
||||||
|
if (is_signed) pad = rv.get(rv.len()-1);
|
||||||
|
for (unsigned idx = cnt ; idx < lv.len() ; idx += 1)
|
||||||
|
if (lv.get(idx) != pad) {
|
||||||
|
res = verinum::V0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return new NetEConst(verinum(res, 1));
|
// If the right value is longer check it against the pad bit.
|
||||||
}
|
if (res == verinum::V1) {
|
||||||
|
verinum::V pad = verinum::V0;
|
||||||
|
if (is_signed) pad = lv.get(lv.len()-1);
|
||||||
|
for (unsigned idx = cnt ; idx < rv.len() ; idx += 1)
|
||||||
|
if (rv.get(idx) != pad) {
|
||||||
|
res = verinum::V0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
NetEConst* NetEBComp::eval_neeqeq_()
|
if (ne_flag) {
|
||||||
{
|
if (res == verinum::V0) res = verinum::V1;
|
||||||
NetEConst*tmp = eval_eqeqeq_();
|
else res = verinum::V0;
|
||||||
if (tmp == 0)
|
}
|
||||||
return 0;
|
|
||||||
|
|
||||||
NetEConst*res;
|
NetEConst*result = new NetEConst(verinum(res, 1));
|
||||||
|
ivl_assert(*this, result);
|
||||||
if (tmp->value().get(0) == verinum::V0)
|
result->set_line(*this);
|
||||||
res = new NetEConst(verinum(verinum::V1,1));
|
return result;
|
||||||
else
|
|
||||||
res = new NetEConst(verinum(verinum::V0,1));
|
|
||||||
|
|
||||||
delete tmp;
|
|
||||||
res->set_line(*this);
|
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NetEConst* NetEBComp::eval_tree(int prune_to_width)
|
NetEConst* NetEBComp::eval_tree(int prune_to_width)
|
||||||
|
|
@ -794,7 +802,7 @@ NetEConst* NetEBComp::eval_tree(int prune_to_width)
|
||||||
|
|
||||||
switch (op_) {
|
switch (op_) {
|
||||||
case 'E': // Case equality (===)
|
case 'E': // Case equality (===)
|
||||||
return eval_eqeqeq_();
|
return eval_eqeqeq_(false);
|
||||||
|
|
||||||
case 'e': // Equality (==)
|
case 'e': // Equality (==)
|
||||||
return eval_eqeq_(false);
|
return eval_eqeq_(false);
|
||||||
|
|
@ -806,7 +814,7 @@ NetEConst* NetEBComp::eval_tree(int prune_to_width)
|
||||||
return eval_leeq_();
|
return eval_leeq_();
|
||||||
|
|
||||||
case 'N': // Case inequality (!==)
|
case 'N': // Case inequality (!==)
|
||||||
return eval_neeqeq_();
|
return eval_eqeqeq_(true);
|
||||||
|
|
||||||
case 'n': // not-equal (!=)
|
case 'n': // not-equal (!=)
|
||||||
return eval_eqeq_(true);
|
return eval_eqeq_(true);
|
||||||
|
|
@ -884,11 +892,57 @@ NetExpr* NetEBDiv::eval_tree(int prune_to_width)
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NetEConst* NetEBLogic::eval_tree_real_()
|
||||||
|
{
|
||||||
|
verireal lval;
|
||||||
|
verireal rval;
|
||||||
|
|
||||||
|
bool flag = get_real_arguments_(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))
|
||||||
|
res = verinum::V1;
|
||||||
|
else
|
||||||
|
res = verinum::V0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'o': { // Logical OR (||)
|
||||||
|
if ((lval.as_double() != 0.0) || (rval.as_double() != 0.0))
|
||||||
|
res = verinum::V1;
|
||||||
|
else
|
||||||
|
res = verinum::V0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
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* NetEBLogic::eval_tree(int prune_to_width)
|
NetEConst* NetEBLogic::eval_tree(int prune_to_width)
|
||||||
{
|
{
|
||||||
eval_expr(left_);
|
eval_expr(left_);
|
||||||
eval_expr(right_);
|
eval_expr(right_);
|
||||||
|
|
||||||
|
if (left_->expr_type() == IVL_VT_REAL ||
|
||||||
|
right_->expr_type() == IVL_VT_REAL)
|
||||||
|
return eval_tree_real_();
|
||||||
|
assert(expr_type() == IVL_VT_LOGIC);
|
||||||
|
|
||||||
NetEConst*lc = dynamic_cast<NetEConst*>(left_);
|
NetEConst*lc = dynamic_cast<NetEConst*>(left_);
|
||||||
NetEConst*rc = dynamic_cast<NetEConst*>(right_);
|
NetEConst*rc = dynamic_cast<NetEConst*>(right_);
|
||||||
if (lc == 0 || rc == 0) return 0;
|
if (lc == 0 || rc == 0) return 0;
|
||||||
|
|
@ -898,57 +952,61 @@ NetEConst* NetEBLogic::eval_tree(int prune_to_width)
|
||||||
|
|
||||||
verinum v = lc->value();
|
verinum v = lc->value();
|
||||||
for (unsigned idx = 0 ; idx < v.len() ; idx += 1)
|
for (unsigned idx = 0 ; idx < v.len() ; idx += 1)
|
||||||
if (v.get(idx) == verinum::V1)
|
if (v.get(idx) == verinum::V1) {
|
||||||
lv = verinum::V1;
|
lv = verinum::V1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (lv == verinum::V0)
|
if (lv == verinum::V0 && ! v.is_defined()) lv = verinum::Vx;
|
||||||
for (unsigned idx = 0 ; idx < v.len() ; idx += 1)
|
|
||||||
if (v.get(idx) != verinum::V0)
|
|
||||||
lv = verinum::Vx;
|
|
||||||
|
|
||||||
v = rc->value();
|
v = rc->value();
|
||||||
for (unsigned idx = 0 ; idx < v.len() ; idx += 1)
|
for (unsigned idx = 0 ; idx < v.len() ; idx += 1)
|
||||||
if (v.get(idx) == verinum::V1)
|
if (v.get(idx) == verinum::V1) {
|
||||||
rv = verinum::V1;
|
rv = verinum::V1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (rv == verinum::V0)
|
if (rv == verinum::V0 && ! v.is_defined()) rv = verinum::Vx;
|
||||||
for (unsigned idx = 0 ; idx < v.len() ; idx += 1)
|
|
||||||
if (v.get(idx) != verinum::V0)
|
|
||||||
rv = verinum::Vx;
|
|
||||||
|
|
||||||
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;
|
||||||
|
|
||||||
else if ((lv == verinum::V1) && (rv == verinum::V1))
|
else if ((lv == verinum::V1) && (rv == verinum::V1))
|
||||||
res = verinum::V1;
|
res = verinum::V1;
|
||||||
|
|
||||||
else
|
else
|
||||||
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;
|
||||||
|
|
||||||
else if ((lv == verinum::V0) && (rv == verinum::V0))
|
else if ((lv == verinum::V0) && (rv == verinum::V0))
|
||||||
res = verinum::V0;
|
res = verinum::V0;
|
||||||
|
|
||||||
else
|
else
|
||||||
res = verinum::Vx;
|
res = verinum::Vx;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3386,8 +3386,7 @@ class NetEBComp : public NetEBinary {
|
||||||
NetEConst*eval_leeq_real_(NetExpr*le, NetExpr*ri, bool eq_flag);
|
NetEConst*eval_leeq_real_(NetExpr*le, NetExpr*ri, bool eq_flag);
|
||||||
NetEConst*eval_gt_();
|
NetEConst*eval_gt_();
|
||||||
NetEConst*eval_gteq_();
|
NetEConst*eval_gteq_();
|
||||||
NetEConst*eval_eqeqeq_();
|
NetEConst*eval_eqeqeq_(bool ne_flag);
|
||||||
NetEConst*eval_neeqeq_();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -3409,6 +3408,7 @@ class NetEBLogic : public NetEBinary {
|
||||||
virtual NetNet* synthesize(Design*, NetScope*scope, NetExpr*root);
|
virtual NetNet* synthesize(Design*, NetScope*scope, NetExpr*root);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
NetEConst* eval_tree_real_();
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
||||||
2
t-dll.cc
2
t-dll.cc
|
|
@ -377,7 +377,7 @@ static void nexus_lpm_add(ivl_nexus_t nex, ivl_lpm_t net, unsigned pin,
|
||||||
|
|
||||||
nex->ptrs_[top].type_= __NEXUS_PTR_LPM;
|
nex->ptrs_[top].type_= __NEXUS_PTR_LPM;
|
||||||
nex->ptrs_[top].drive0 = drive0;
|
nex->ptrs_[top].drive0 = drive0;
|
||||||
nex->ptrs_[top].drive1 = drive0;
|
nex->ptrs_[top].drive1 = drive1;
|
||||||
nex->ptrs_[top].pin_ = pin;
|
nex->ptrs_[top].pin_ = pin;
|
||||||
nex->ptrs_[top].l.lpm= net;
|
nex->ptrs_[top].l.lpm= net;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue