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:
parent
86e5762b1c
commit
69ba009439
175
vvp/vvp_net.cc
175
vvp/vvp_net.cc
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
/*
|
||||
|
|
|
|||
Loading…
Reference in New Issue