Fix evaluation of logical equality with x bits.

Logical (in)equality needs to look at all the bits of both operands,
and cannot short circuit the test unless defined bits differ. If there
are undefined bits, the equality is undefined at that point, but return
x only if there are not other bits that make the results clearly
unequal.
This commit is contained in:
Stephen Williams 2008-08-13 22:22:59 -07:00
parent 3def0e0dec
commit 50c1533fdd
2 changed files with 19 additions and 11 deletions

View File

@ -561,6 +561,13 @@ NetEConst* NetEBComp::eval_gteq_()
}
}
/*
* Evaluate <A>==<B> or <A>!=<B>. The equality operator checks all the
* bits and returns true(false) if there are any bits in the vector
* that are defined (0 or 1) and different. If all the defined bits
* are equal, but there are are x/z bits, then the situation is
* ambiguous so the result is x.
*/
NetEConst* NetEBComp::eval_eqeq_(bool ne_flag)
{
NetEConst*l = dynamic_cast<NetEConst*>(left_);
@ -581,11 +588,14 @@ NetEConst* NetEBComp::eval_eqeq_(bool ne_flag)
for (unsigned idx = 0 ; idx < top ; idx += 1) {
bool x_bit_present = false;
switch (lv.get(idx)) {
case verinum::Vx:
case verinum::Vz:
res = verinum::Vx;
x_bit_present = true;
break;
default:
@ -597,17 +607,20 @@ NetEConst* NetEBComp::eval_eqeq_(bool ne_flag)
case verinum::Vx:
case verinum::Vz:
res = verinum::Vx;
x_bit_present = true;
break;
default:
break;
}
if (res == verinum::Vx)
break;
if (x_bit_present)
continue;
if (rv.get(idx) != lv.get(idx))
if (rv.get(idx) != lv.get(idx)) {
res = ne_res;
break;
}
}
if (res != verinum::Vx) {

View File

@ -1117,13 +1117,7 @@ static bool of_CMPIU_the_hard_way(vthread_t thr, vvp_code_t cp)
thr_check_addr(thr, idx1+wid-1);
vvp_bit4_t lv = thr_get_bit(thr, idx1);
if (bit4_is_xz(lv)) {
thr_put_bit(thr, 4, BIT4_X);
thr_put_bit(thr, 5, BIT4_X);
thr_put_bit(thr, 6, BIT4_0);
}
vvp_bit4_t eq = BIT4_0;
vvp_bit4_t eq = BIT4_1;
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
vvp_bit4_t rv = (imm & 1UL)? BIT4_1 : BIT4_0;
imm >>= 1UL;
@ -1131,12 +1125,13 @@ static bool of_CMPIU_the_hard_way(vthread_t thr, vvp_code_t cp)
if (bit4_is_xz(lv)) {
eq = BIT4_X;
} else if (lv != rv) {
eq = BIT4_0;
break;
}
if (idx1 >= 4) {
idx1 += 1;
if (idx1 < wid)
if ((idx+1) < wid)
lv = thr_get_bit(thr, idx1);
}
}