From 69ba0094397b8f422c06c52a2306f22dba9ba700 Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Mon, 16 Jun 2008 17:45:08 -0700 Subject: [PATCH] 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. --- vvp/vvp_net.cc | 175 +++++++++++++++++++++++++------------------------ vvp/vvp_net.h | 21 +++++- 2 files changed, 107 insertions(+), 89 deletions(-) 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); /*