diff --git a/vvp/arith.cc b/vvp/arith.cc index 70041cc9d..f15c80688 100644 --- a/vvp/arith.cc +++ b/vvp/arith.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: arith.cc,v 1.46 2005/09/15 22:54:04 steve Exp $" +#ident "$Id: arith.cc,v 1.47 2005/11/10 13:27:16 steve Exp $" #endif # include "arith.h" @@ -140,7 +140,20 @@ vvp_arith_mod::~vvp_arith_mod() void vvp_arith_mod::wide_(vvp_net_ptr_t ptr) { - assert(0); + vvp_vector2_t a2 (op_a_); + if (a2.is_NaN()) { + vvp_send_vec4(ptr.ptr()->out, x_val_); + return; + } + + vvp_vector2_t b2 (op_b_); + if (b2.is_NaN()) { + vvp_send_vec4(ptr.ptr()->out, x_val_); + return; + } + + vvp_vector2_t res = a2 % b2; + vvp_send_vec4(ptr.ptr()->out, vector2_to_vector4(res, res.size())); } void vvp_arith_mod::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit) @@ -754,6 +767,9 @@ void vvp_arith_sub_real::recv_real(vvp_net_ptr_t ptr, double bit) /* * $Log: arith.cc,v $ + * Revision 1.47 2005/11/10 13:27:16 steve + * Handle very wide % and / operations using expanded vector2 support. + * * Revision 1.46 2005/09/15 22:54:04 steve * Use iostream instead of stdio. * diff --git a/vvp/delay.cc b/vvp/delay.cc index 039254766..9f6cf2ce2 100644 --- a/vvp/delay.cc +++ b/vvp/delay.cc @@ -17,11 +17,12 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: delay.cc,v 1.10 2005/09/20 18:34:02 steve Exp $" +#ident "$Id: delay.cc,v 1.11 2005/11/10 13:27:16 steve Exp $" #endif #include "delay.h" #include "schedule.h" +#include #include vvp_delay_t::vvp_delay_t(vvp_time64_t rise, vvp_time64_t fall) @@ -108,19 +109,35 @@ vvp_fun_delay::~vvp_fun_delay() } /* - * FIXME: This implementation currently only uses the LSB to determine - * the delay type for the entire vector. It needs to be upgraded to - * account for different delays for different bits by generating a - * stream of vectors that lead up to the actual value. + * FIXME: this implementation currently only uses the maximum delay + * from all the bit changes in the vectors. If there are multiple + * changes with different delays, then the results would be + * wrong. What should happen is that if there are multiple changes, + * multiple vectors approaching the result should be scheduled. */ void vvp_fun_delay::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit) { if (cur_vec4_.eeq(bit)) return; + /* How many bits to compare? */ + unsigned use_wid = cur_vec4_.size(); + if (bit.size() < use_wid) + use_wid = bit.size(); + + /* Scan the vectors looking for delays. Select the maximim + delay encountered. */ vvp_time64_t use_delay; use_delay = delay_.get_delay(cur_vec4_.value(0), bit.value(0)); + for (unsigned idx = 1 ; idx < use_wid ; idx += 1) { + vvp_time64_t tmp; + tmp = delay_.get_delay(cur_vec4_.value(idx), bit.value(idx)); + if (tmp > use_delay) + use_delay = tmp; + } + + /* And propagate it. */ cur_vec4_ = bit; if (use_delay == 0) { vvp_send_vec4(net_->out, cur_vec4_); @@ -163,6 +180,9 @@ void vvp_fun_delay::run_run() /* * $Log: delay.cc,v $ + * Revision 1.11 2005/11/10 13:27:16 steve + * Handle very wide % and / operations using expanded vector2 support. + * * Revision 1.10 2005/09/20 18:34:02 steve * Clean up compiler warnings. * diff --git a/vvp/vvp_net.cc b/vvp/vvp_net.cc index cf0fc9ffb..6696acbd3 100644 --- a/vvp/vvp_net.cc +++ b/vvp/vvp_net.cc @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ -#ident "$Id: vvp_net.cc,v 1.46 2005/10/04 04:41:07 steve Exp $" +#ident "$Id: vvp_net.cc,v 1.47 2005/11/10 13:27:16 steve Exp $" # include "config.h" # include "vvp_net.h" @@ -622,8 +622,7 @@ vvp_vector2_t::vvp_vector2_t(unsigned long v, unsigned wid) vvp_vector2_t::vvp_vector2_t(const vvp_vector4_t&that) { wid_ = that.size(); - const unsigned bits_per_word = 8 * sizeof(vec_[0]); - const unsigned words = (that.size() + bits_per_word-1) / bits_per_word; + const unsigned words = (that.size() + BITS_PER_WORD-1) / BITS_PER_WORD; if (words == 0) { vec_ = 0; @@ -636,8 +635,8 @@ vvp_vector2_t::vvp_vector2_t(const vvp_vector4_t&that) vec_[idx] = 0; for (unsigned idx = 0 ; idx < that.size() ; idx += 1) { - unsigned addr = idx / bits_per_word; - unsigned shift = idx % bits_per_word; + unsigned addr = idx / BITS_PER_WORD; + unsigned shift = idx % BITS_PER_WORD; switch (that.value(idx)) { case BIT4_0: @@ -654,6 +653,207 @@ vvp_vector2_t::vvp_vector2_t(const vvp_vector4_t&that) } } +void vvp_vector2_t::copy_from_that_(const vvp_vector2_t&that) +{ + wid_ = that.wid_; + const unsigned words = (wid_ + BITS_PER_WORD-1) / BITS_PER_WORD; + + if (words == 0) { + vec_ = 0; + wid_ = 0; + return; + } + + vec_ = new unsigned long[words]; + for (unsigned idx = 0 ; idx < words ; idx += 1) + vec_[idx] = that.vec_[idx]; +} + +vvp_vector2_t::vvp_vector2_t(const vvp_vector2_t&that) +{ + copy_from_that_(that); +} + +vvp_vector2_t::vvp_vector2_t(const vvp_vector2_t&that, unsigned newsize) +{ + wid_ = newsize; + if (newsize == 0) { + vec_ = 0; + return; + } + + const unsigned words = (wid_ + BITS_PER_WORD-1) / BITS_PER_WORD; + const unsigned twords = (that.wid_ + BITS_PER_WORD-1) / BITS_PER_WORD; + + vec_ = new unsigned long[words]; + for (unsigned idx = 0 ; idx < words ; idx += 1) { + if (idx < twords) + vec_[idx] = that.vec_[idx]; + else + vec_[idx] = 0; + } +} + +vvp_vector2_t& vvp_vector2_t::operator= (const vvp_vector2_t&that) +{ + if (this == &that) + return *this; + + if (vec_) { + delete[]vec_; + vec_ = 0; + } + + copy_from_that_(that); + return *this; +} + +vvp_vector2_t& vvp_vector2_t::operator <<= (unsigned int shift) +{ + if (wid_ == 0) + return *this; + + const unsigned words = (wid_ + BITS_PER_WORD-1) / BITS_PER_WORD; + + // Number of words to shift + const unsigned wshift = shift / BITS_PER_WORD; + // bits to shift within each word. + const unsigned long oshift = shift % BITS_PER_WORD; + + // If shifting the entire value away, then return zeros. + if (wshift >= words) { + for (unsigned idx = 0 ; idx < words ; idx += 1) + vec_[idx] = 0; + + return *this; + } + + // Do the word shift first. + if (wshift > 0) { + for (unsigned idx = 0 ; idx < words-wshift ; idx += 1) { + unsigned sel = words - idx - 1; + vec_[sel] = vec_[sel-wshift]; + } + + for (unsigned idx = 0 ; idx < wshift ; idx += 1) + vec_[idx] = 0; + } + + // Do the fine shift. + if (oshift != 0) { + unsigned long pad = 0; + for (unsigned idx = 0 ; idx < words ; idx += 1) { + unsigned long next_pad = vec_[idx] >> (BITS_PER_WORD-oshift); + vec_[idx] = (vec_[idx] << oshift) | pad; + pad = next_pad; + } + + // Cleanup the tail bits. + unsigned long mask = -1UL >> (BITS_PER_WORD - wid_%BITS_PER_WORD); + vec_[words-1] &= mask; + } + + return *this; +} + +vvp_vector2_t& vvp_vector2_t::operator >>= (unsigned shift) +{ + if (wid_ == 0) + return *this; + + const unsigned words = (wid_ + BITS_PER_WORD-1) / BITS_PER_WORD; + + // Number of words to shift + const unsigned wshift = shift / BITS_PER_WORD; + // bits to shift within each word. + const unsigned long oshift = shift % BITS_PER_WORD; + + // If shifting the entire value away, then return zeros. + if (wshift >= words) { + for (unsigned idx = 0 ; idx < words ; idx += 1) + vec_[idx] = 0; + + return *this; + } + + if (wshift > 0) { + for (unsigned idx = 0 ; idx < words-wshift ; idx += 1) + vec_[idx] = vec_[idx+wshift]; + + for (unsigned idx = words-wshift ; idx < words ; idx += 1) + vec_[idx] = 0; + } + + if (oshift > 0) { + unsigned long pad = 0; + for (unsigned idx = words ; idx > 0 ; idx -= 1) { + unsigned long new_pad = vec_[idx-1] <<(BITS_PER_WORD-oshift); + vec_[idx-1] = pad | (vec_[idx-1] >> oshift); + pad = new_pad; + } + + // Cleanup the tail bits. + unsigned long mask = -1UL >> (BITS_PER_WORD - wid_%BITS_PER_WORD); + vec_[words-1] &= mask; + } + + return *this; +} + +static unsigned long add_carry(unsigned long a, unsigned long b, + unsigned long&carry) +{ + unsigned long out = carry; + carry = 0; + + if ((ULONG_MAX - out) < a) + carry += 1; + out += a; + + if ((ULONG_MAX - out) < b) + carry += 1; + out += b; + + return out; +} + +vvp_vector2_t& vvp_vector2_t::operator += (const vvp_vector2_t&that) +{ + assert(wid_ == that.wid_); + if (wid_ == 0) + return *this; + + const unsigned words = (wid_ + BITS_PER_WORD-1) / BITS_PER_WORD; + + unsigned long carry = 0; + for (unsigned idx = 0 ; idx < words ; idx += 1) { + vec_[idx] = add_carry(vec_[idx], that.vec_[idx], carry); + } + + + // Cleanup the tail bits. + unsigned long mask = -1UL >> (BITS_PER_WORD - wid_%BITS_PER_WORD); + vec_[words-1] &= mask; + + return *this; +} + +vvp_vector2_t& vvp_vector2_t::operator -= (const vvp_vector2_t&that) +{ + assert(wid_ == that.wid_); + if (wid_ == 0) + return *this; + + const unsigned words = (wid_ + BITS_PER_WORD-1) / BITS_PER_WORD; + + unsigned long carry = 1; + for (unsigned idx = 0 ; idx < words ; idx += 1) { + vec_[idx] = add_carry(vec_[idx], ~that.vec_[idx], carry); + } + + return *this; +} + vvp_vector2_t::~vvp_vector2_t() { if (vec_) delete[]vec_; @@ -684,23 +884,6 @@ bool vvp_vector2_t::is_NaN() const return wid_ == 0; } -static unsigned long add_carry(unsigned long a, unsigned long b, - unsigned long&carry) -{ - unsigned long out = carry; - carry = 0; - - if ((ULONG_MAX - out) < a) - carry += 1; - out += a; - - if ((ULONG_MAX - out) < b) - carry += 1; - out += b; - - return out; -} - static void multiply_long(unsigned long a, unsigned long b, unsigned long&low, unsigned long&high) { @@ -784,6 +967,117 @@ vvp_vector2_t operator * (const vvp_vector2_t&a, const vvp_vector2_t&b) return r; } +static void div_mod (vvp_vector2_t dividend, vvp_vector2_t divisor, + vvp_vector2_t"ient, vvp_vector2_t&remainder) +{ + + quotient = vvp_vector2_t(0, dividend.size()); + + if (dividend < divisor) { + remainder = dividend; + return; + } + + vvp_vector2_t mask (1, dividend.size()); + + vvp_vector2_t divtmp (divisor, dividend.size()); + + while (divtmp < dividend) { + divtmp <<= 1; + mask <<= 1; + } + + while (dividend > divisor) { + if (divtmp <= dividend) { + dividend -= divtmp; + quotient += mask; + } + + divtmp >>= 1; + mask >>= 1; + } + + remainder = dividend; +} + +vvp_vector2_t operator / (const vvp_vector2_t÷nd, + const vvp_vector2_t&divisor) +{ + vvp_vector2_t quot, rem; + div_mod(dividend, divisor, quot, rem); + return quot; +} + +vvp_vector2_t operator % (const vvp_vector2_t÷nd, + const vvp_vector2_t&divisor) +{ + vvp_vector2_t quot, rem; + div_mod(dividend, divisor, quot, rem); + return rem; +} + +bool operator > (const vvp_vector2_t&a, const vvp_vector2_t&b) +{ + const unsigned awords = (a.wid_ + vvp_vector2_t::BITS_PER_WORD-1) / vvp_vector2_t::BITS_PER_WORD; + const unsigned bwords = (b.wid_ + vvp_vector2_t::BITS_PER_WORD-1) / vvp_vector2_t::BITS_PER_WORD; + + const unsigned words = awords > bwords? awords : bwords; + + for (unsigned idx = words ; idx > 0 ; idx -= 1) { + unsigned long aw = (idx <= awords)? a.vec_[idx-1] : 0; + unsigned long bw = (idx <= bwords)? b.vec_[idx-1] : 0; + + if (aw > bw) + return true; + if (aw < bw) + return false; + } + + // If the above loop finishes, then the vectors are equal. + return false; +} + +bool operator < (const vvp_vector2_t&a, const vvp_vector2_t&b) +{ + const unsigned awords = (a.wid_ + vvp_vector2_t::BITS_PER_WORD-1) / vvp_vector2_t::BITS_PER_WORD; + const unsigned bwords = (b.wid_ + vvp_vector2_t::BITS_PER_WORD-1) / vvp_vector2_t::BITS_PER_WORD; + + unsigned words = awords; + if (bwords > words) + words = bwords; + + for (unsigned idx = words ; idx > 0 ; idx -= 1) { + unsigned long aw = (idx <= awords)? a.vec_[idx-1] : 0; + unsigned long bw = (idx <= bwords)? b.vec_[idx-1] : 0; + + if (aw < bw) + return true; + if (aw > bw) + return false; + } + + // If the above loop finishes, then the vectors are equal. + return false; +} + +bool operator <= (const vvp_vector2_t&a, const vvp_vector2_t&b) +{ + // XXXX For now, only support equal width vectors. + assert(a.wid_ == b.wid_); + + const unsigned awords = (a.wid_ + vvp_vector2_t::BITS_PER_WORD-1) / vvp_vector2_t::BITS_PER_WORD; + + for (unsigned idx = awords ; idx > 0 ; idx -= 1) { + if (a.vec_[idx-1] < b.vec_[idx-1]) + return true; + if (a.vec_[idx-1] > b.vec_[idx-1]) + return false; + } + + // If the above loop finishes, then the vectors are equal. + return true; +} + vvp_vector4_t vector2_to_vector4(const vvp_vector2_t&that, unsigned wid) { vvp_vector4_t res (wid); @@ -800,6 +1094,17 @@ vvp_vector4_t vector2_to_vector4(const vvp_vector2_t&that, unsigned wid) return res; } +ostream& operator<< (ostream&out, const vvp_vector2_t&that) +{ + if (that.is_NaN()) { + out << "NaN"; + + } else { + out << vector2_to_vector4(that, that.size()); + } + return out; +} + vvp_vector8_t::vvp_vector8_t(const vvp_vector8_t&that) { size_ = that.size_; @@ -1681,6 +1986,9 @@ vvp_bit4_t compare_gtge_signed(const vvp_vector4_t&a, /* * $Log: vvp_net.cc,v $ + * Revision 1.47 2005/11/10 13:27:16 steve + * Handle very wide % and / operations using expanded vector2 support. + * * Revision 1.46 2005/10/04 04:41:07 steve * Make sure the new size sticks in resize method. * diff --git a/vvp/vvp_net.h b/vvp/vvp_net.h index 2d6ad5e47..7a81ce73b 100644 --- a/vvp/vvp_net.h +++ b/vvp/vvp_net.h @@ -18,7 +18,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ -#ident "$Id: vvp_net.h,v 1.46 2005/09/20 00:51:53 steve Exp $" +#ident "$Id: vvp_net.h,v 1.47 2005/11/10 13:27:16 steve Exp $" # include "config.h" # include @@ -263,28 +263,49 @@ class vvp_vector2_t { const vvp_vector2_t&); friend vvp_vector2_t operator * (const vvp_vector2_t&, const vvp_vector2_t&); + friend bool operator > (const vvp_vector2_t&, const vvp_vector2_t&); + friend bool operator < (const vvp_vector2_t&, const vvp_vector2_t&); + friend bool operator <= (const vvp_vector2_t&, const vvp_vector2_t&); public: vvp_vector2_t(); vvp_vector2_t(const vvp_vector2_t&); + vvp_vector2_t(const vvp_vector2_t&, unsigned newsize); + // Make a vvp_vector2_t from a vvp_vector4_t. If there are X + // or Z bits, then the result becomes a NaN value. explicit vvp_vector2_t(const vvp_vector4_t&that); + // Make from a native long and a specified width. vvp_vector2_t(unsigned long val, unsigned wid); ~vvp_vector2_t(); - vvp_vector2_t operator = (const vvp_vector2_t&); + vvp_vector2_t&operator += (const vvp_vector2_t&that); + vvp_vector2_t&operator -= (const vvp_vector2_t&that); + vvp_vector2_t&operator <<= (unsigned shift); + vvp_vector2_t&operator >>= (unsigned shift); + vvp_vector2_t&operator = (const vvp_vector2_t&); bool is_NaN() const; unsigned size() const; int value(unsigned idx) const; private: + enum { BITS_PER_WORD = 8 * sizeof(unsigned long) }; unsigned long*vec_; unsigned wid_; + + private: + void copy_from_that_(const vvp_vector2_t&that); }; +extern bool operator < (const vvp_vector2_t&, const vvp_vector2_t&); +extern bool operator > (const vvp_vector2_t&, const vvp_vector2_t&); +extern bool operator <= (const vvp_vector2_t&, const vvp_vector2_t&); extern vvp_vector2_t operator + (const vvp_vector2_t&, const vvp_vector2_t&); extern vvp_vector2_t operator * (const vvp_vector2_t&, const vvp_vector2_t&); +extern vvp_vector2_t operator / (const vvp_vector2_t&, const vvp_vector2_t&); +extern vvp_vector2_t operator % (const vvp_vector2_t&, const vvp_vector2_t&); extern vvp_vector4_t vector2_to_vector4(const vvp_vector2_t&, unsigned wid); +extern ostream& operator<< (ostream&, const vvp_vector2_t&); /* * This class represents a scaler value with strength. These are @@ -937,6 +958,9 @@ inline void vvp_send_vec4_pv(vvp_net_ptr_t ptr, const vvp_vector4_t&val, /* * $Log: vvp_net.h,v $ + * Revision 1.47 2005/11/10 13:27:16 steve + * Handle very wide % and / operations using expanded vector2 support. + * * Revision 1.46 2005/09/20 00:51:53 steve * Lazy processing of vvp_fun_part functor. *