diff --git a/vvp/vvp_net.cc b/vvp/vvp_net.cc index 9f9a76065..bad2894e7 100644 --- a/vvp/vvp_net.cc +++ b/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; diff --git a/vvp/vvp_net.h b/vvp/vvp_net.h index 604f4b65d..c9a0fe70f 100644 --- a/vvp/vvp_net.h +++ b/vvp/vvp_net.h @@ -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); /*