Cleanup the resolver function.

First, handle the trivial (but possibly common) resolution cases in
inlined code, and only call the complete function for the complicated
cases. Then clean up the complex function for readability, and account
for the constraints that the front-end function established.
This commit is contained in:
Stephen Williams 2008-06-16 17:45:08 -07:00
parent 86e5762b1c
commit 69ba009439
2 changed files with 107 additions and 89 deletions

View File

@ -2862,16 +2862,13 @@ ostream& operator <<(ostream&out, vvp_scalar_t a)
return out;
}
vvp_scalar_t resolve(vvp_scalar_t a, vvp_scalar_t b)
/*
* This function is only called if the actual interface function rules
* out some of the eazy cases. If we get here, we can assume that
* neither of the values is HiZ, and the values are not exactly equal.
*/
vvp_scalar_t fully_featured_resolv_(vvp_scalar_t a, vvp_scalar_t b)
{
// If the value is 0, that is the same as HiZ. In that case,
// resolution is simply a matter of returning the *other* value.
if (a.value_ == 0)
return b;
if (b.value_ == 0)
return a;
vvp_scalar_t res = a;
if (UNAMBIG(a.value_) && UNAMBIG(b.value_)) {
@ -2880,108 +2877,112 @@ vvp_scalar_t resolve(vvp_scalar_t a, vvp_scalar_t b)
but different values, then this becomes
ambiguous. */
if (a.value_ == b.value_) {
if ((b.value_&0x07) > (a.value_&0x07)) {
/* values are equal. do nothing. */
/* b value is stronger. Take it. */
return b;
} else if ((b.value_&0x07) > (res.value_&0x07)) {
} else if ((b.value_&0x77) == (a.value_&0x77)) {
/* New value is stronger. Take it. */
res.value_ = b.value_;
} else if ((b.value_&0x77) == (res.value_&0x77)) {
/* Strengths are the same. Make value ambiguous. */
res.value_ = (res.value_&0x70) | (b.value_&0x07) | 0x80;
// Strengths are the same. Since we know already
// that the values are not the same, Make value
// into "x".
vvp_scalar_t tmp (a);
tmp.value_ = (tmp.value_&0x77) | 0x80;
return tmp;
} else {
/* Must be res is the stronger one. */
/* Must be "a" is the stronger one. */
return a;
}
} else if (UNAMBIG(res.value_)) {
unsigned tmp = 0;
}
if ((res.value_&0x70) > (b.value_&0x70))
tmp |= res.value_&0xf0;
/* If one of the signals is unambiguous, then it
will sweep up the weaker parts of the ambiguous
signal. The result may be ambiguous, or maybe not. */
if (UNAMBIG(a.value_)) {
vvp_scalar_t res;
if ((a.value_&0x70) > (b.value_&0x70))
res.value_ |= a.value_&0xf0;
else
tmp |= b.value_&0xf0;
res.value_ |= b.value_&0xf0;
if ((res.value_&0x07) > (b.value_&0x07))
tmp |= res.value_&0x0f;
if ((a.value_&0x07) > (b.value_&0x07))
res.value_ |= a.value_&0x0f;
else
tmp |= b.value_&0x0f;
res.value_ |= b.value_&0x0f;
res.value_ = tmp;
return res;
} else if (UNAMBIG(b.value_)) {
/* If one of the signals is unambiguous, then it
will sweep up the weaker parts of the ambiguous
signal. The result may be ambiguous, or maybe not. */
vvp_scalar_t res;
unsigned tmp = 0;
if ((b.value_&0x70) > (res.value_&0x70))
tmp |= b.value_&0xf0;
if ((b.value_&0x70) > (a.value_&0x70))
res.value_ |= b.value_&0xf0;
else
tmp |= res.value_&0xf0;
res.value_ |= a.value_&0xf0;
if ((b.value_&0x07) > (res.value_&0x07))
tmp |= b.value_&0x0f;
if ((b.value_&0x07) > (a.value_&0x07))
res.value_ |= b.value_&0x0f;
else
tmp |= res.value_&0x0f;
res.value_ |= a.value_&0x0f;
res.value_ = tmp;
return res;
} else {
/* If both signals are ambiguous, then the result
has an even wider ambiguity. */
unsigned tmp = 0;
int sv1a = a.value_&0x80 ? STREN1(a.value_) : - STREN1(a.value_);
int sv0a = a.value_&0x08 ? STREN0(a.value_) : - STREN0(a.value_);
int sv1b = b.value_&0x80 ? STREN1(b.value_) : - STREN1(b.value_);
int sv0b = b.value_&0x08 ? STREN0(b.value_) : - STREN0(b.value_);
int sv1 = sv1a;
int sv0 = sv0a;
if (sv0a > sv1)
sv1 = sv0a;
if (sv1b > sv1)
sv1 = sv1b;
if (sv0b > sv1)
sv1 = sv0b;
if (sv1a < sv0)
sv0 = sv1a;
if (sv1b < sv0)
sv0 = sv1b;
if (sv0b < sv0)
sv0 = sv0b;
if (sv1 > 0) {
tmp |= 0x80;
tmp |= sv1 << 4;
} else {
/* Set the MSB when both arguments MSBs are set. This
can only happen if both one strengths are zero. */
tmp |= (a.value_&b.value_)&0x80;
tmp |= (-sv1) << 4;
}
if (sv0 > 0) {
tmp |= 0x08;
tmp |= sv0;
} else {
tmp |= (-sv0);
}
res.value_ = tmp;
}
/* If both signals are ambiguous, then the result
has an even wider ambiguity. */
unsigned tmp = 0;
int sv1a = a.value_&0x80 ? STREN1(a.value_) : - STREN1(a.value_);
int sv0a = a.value_&0x08 ? STREN0(a.value_) : - STREN0(a.value_);
int sv1b = b.value_&0x80 ? STREN1(b.value_) : - STREN1(b.value_);
int sv0b = b.value_&0x08 ? STREN0(b.value_) : - STREN0(b.value_);
int sv1 = sv1a;
int sv0 = sv0a;
if (sv0a > sv1)
sv1 = sv0a;
if (sv1b > sv1)
sv1 = sv1b;
if (sv0b > sv1)
sv1 = sv0b;
if (sv1a < sv0)
sv0 = sv1a;
if (sv1b < sv0)
sv0 = sv1b;
if (sv0b < sv0)
sv0 = sv0b;
if (sv1 > 0) {
tmp |= 0x80;
tmp |= sv1 << 4;
} else {
/* Set the MSB when both arguments MSBs are set. This
can only happen if both one strengths are zero. */
tmp |= (a.value_&b.value_)&0x80;
tmp |= (-sv1) << 4;
}
if (sv0 > 0) {
tmp |= 0x08;
tmp |= sv0;
} else {
tmp |= (-sv0);
}
vvp_scalar_t res;
res.value_ = tmp;
/* Canonicalize the HiZ value. */
if ((res.value_&0x77) == 0)
res.value_ = 0;

View File

@ -516,7 +516,7 @@ inline unsigned vvp_vector2_t::size() const
*/
class vvp_scalar_t {
friend vvp_scalar_t resolve(vvp_scalar_t a, vvp_scalar_t b);
friend vvp_scalar_t fully_featured_resolv_(vvp_scalar_t a, vvp_scalar_t b);
public:
// Make a HiZ value.
@ -580,7 +580,24 @@ inline vvp_bit4_t vvp_scalar_t::value() const
}
extern vvp_scalar_t resolve(vvp_scalar_t a, vvp_scalar_t b);
inline vvp_scalar_t resolve(vvp_scalar_t a, vvp_scalar_t b)
{
extern vvp_scalar_t fully_featured_resolv_(vvp_scalar_t a, vvp_scalar_t b);
// If the value is HiZ, resolution is simply a matter of
// returning the *other* value.
if (a.is_hiz())
return b;
if (b.is_hiz())
return a;
// If the values are the identical, then resolution is simply
// returning *either* value.
if (a .eeq( b ))
return a;
return fully_featured_resolv_(a,b);
}
extern ostream& operator<< (ostream&, vvp_scalar_t);
/*