diff --git a/vvp/vvp_net.cc b/vvp/vvp_net.cc index 806237dc4..a91503871 100644 --- a/vvp/vvp_net.cc +++ b/vvp/vvp_net.cc @@ -1758,12 +1758,12 @@ ostream& operator<< (ostream&out, const vvp_vector2_t&that) vvp_vector8_t::vvp_vector8_t(const vvp_vector8_t&that) { size_ = that.size_; - if (size_==0) { - bits_ = 0; + if (size_ <= PTR_THRESH) { + memcpy(val_, that.val_, sizeof(val_)); } else { - bits_ = new vvp_scalar_t[size_]; + ptr_ = new vvp_scalar_t[size_]; for (unsigned idx = 0 ; idx < size_ ; idx += 1) - bits_[idx] = that.bits_[idx]; + ptr_[idx] = that.ptr_[idx]; } } @@ -1771,26 +1771,29 @@ vvp_vector8_t::vvp_vector8_t(const vvp_vector4_t&that, unsigned str0, unsigned str1) : size_(that.size()) { - if (size_ == 0) { - bits_ = 0; + if (size_ == 0) return; - } - bits_ = new vvp_scalar_t[size_]; + vvp_scalar_t*tmp; + if (size_ <= PTR_THRESH) + tmp = new (val_) vvp_scalar_t[PTR_THRESH]; + else + tmp = ptr_ = new vvp_scalar_t[size_]; + for (unsigned idx = 0 ; idx < size_ ; idx += 1) - bits_[idx] = vvp_scalar_t (that.value(idx), str0, str1); + tmp[idx] = vvp_scalar_t (that.value(idx), str0, str1); } vvp_vector8_t& vvp_vector8_t::operator= (const vvp_vector8_t&that) { // Assign to self. - if (size_ > 0 && bits_ == that.bits_) + if (size_ > PTR_THRESH && that.size_ > PTR_THRESH && ptr_ == that.ptr_) return *this; if (size_ != that.size_) { - if (size_ > 0) - delete[]bits_; + if (size_ > PTR_THRESH) + delete[]ptr_; size_ = 0; } @@ -1799,13 +1802,19 @@ vvp_vector8_t& vvp_vector8_t::operator= (const vvp_vector8_t&that) return *this; } + if (that.size_ <= PTR_THRESH) { + size_ = that.size_; + memcpy(val_, that.val_, sizeof(val_)); + return *this; + } + if (size_ == 0) { size_ = that.size_; - bits_ = new vvp_scalar_t[size_]; + ptr_ = new vvp_scalar_t[size_]; } for (unsigned idx = 0 ; idx < size_ ; idx += 1) - bits_[idx] = that.bits_[idx]; + ptr_[idx] = that.ptr_[idx]; return *this; } @@ -1814,9 +1823,12 @@ vvp_vector8_t vvp_vector8_t::subvalue(unsigned base, unsigned wid) const { vvp_vector8_t tmp (wid); + vvp_scalar_t* tmp_ptr = tmp.size_<=PTR_THRESH? reinterpret_cast(tmp.val_) : tmp.ptr_; + const vvp_scalar_t* ptr = size_<=PTR_THRESH? reinterpret_cast(val_) : ptr_; + unsigned idx = 0; while ((idx < wid) && (base+idx < size_)) { - tmp.bits_[idx] = bits_[base+idx]; + tmp_ptr[idx] = ptr[base+idx]; idx += 1; } @@ -1828,10 +1840,13 @@ vvp_vector8_t part_expand(const vvp_vector8_t&that, unsigned wid, unsigned off) assert(off < wid); vvp_vector8_t tmp (wid); + vvp_scalar_t* tmp_ptr = tmp.size_<=vvp_vector8_t::PTR_THRESH? reinterpret_cast(tmp.val_) : tmp.ptr_; + const vvp_scalar_t* that_ptr = that.size_<=vvp_vector8_t::PTR_THRESH? reinterpret_cast(that.val_) : that.ptr_; + unsigned idx = off; while (idx < wid && that.size_ > (idx-off)) { - tmp.bits_[idx] = that.bits_[idx-off]; + tmp_ptr[idx] = that_ptr[idx-off]; idx += 1; } diff --git a/vvp/vvp_net.h b/vvp/vvp_net.h index 1acfaabd3..6bbd95555 100644 --- a/vvp/vvp_net.h +++ b/vvp/vvp_net.h @@ -21,6 +21,7 @@ # include "config.h" # include +# include # include #ifdef HAVE_IOSFWD @@ -581,8 +582,15 @@ class vvp_vector8_t { vvp_vector8_t& operator= (const vvp_vector8_t&that); private: + // This is the number of vvp_scalar_t objects we can keep in + // the val_ buffer. If the vector8 is bigger then this, then + // resort to allocations to get a larger buffer. + enum { PTR_THRESH = 8 }; unsigned size_; - vvp_scalar_t*bits_; + union { + vvp_scalar_t*ptr_; + char val_[PTR_THRESH * sizeof(vvp_scalar_t)]; + }; }; /* Resolve uses the default Verilog resolver algorithm to resolve @@ -612,17 +620,35 @@ extern ostream& operator<< (ostream&, const vvp_vector8_t&); inline vvp_vector8_t::vvp_vector8_t(unsigned size) : size_(size) { - if (size_ == 0) { - bits_ = 0; - return; + if (size_ <= PTR_THRESH) { + new (val_) vvp_scalar_t[PTR_THRESH]; + } else { + ptr_ = new vvp_scalar_t[size_]; } - bits_ = new vvp_scalar_t[size_]; } inline vvp_vector8_t::~vvp_vector8_t() { - if (size_ > 0) - delete[]bits_; + if (size_ > PTR_THRESH) + delete[]ptr_; +} + +inline vvp_scalar_t vvp_vector8_t::value(unsigned idx) const +{ + assert(idx < size_); + if (size_ <= PTR_THRESH) + return reinterpret_cast(val_) [idx]; + else + return ptr_[idx]; +} + +inline void vvp_vector8_t::set_bit(unsigned idx, vvp_scalar_t val) +{ + assert(idx < size_); + if (size_ <= PTR_THRESH) + reinterpret_cast(val_) [idx] = val; + else + ptr_[idx] = val; } // Exactly-equal for vvp_vector8_t is common and should be as tight @@ -634,26 +660,17 @@ inline bool vvp_vector8_t::eeq(const vvp_vector8_t&that) const if (size_ == 0) return true; + if (size_ <= PTR_THRESH) + return 0 == memcmp(val_, that.val_, sizeof(val_)); + for (unsigned idx = 0 ; idx < size_ ; idx += 1) { - if (! bits_[idx] .eeq( that.bits_[idx] )) + if (! ptr_[idx] .eeq( that.ptr_[idx] )) return false; } return true; } -inline vvp_scalar_t vvp_vector8_t::value(unsigned idx) const -{ - assert(idx < size_); - return bits_[idx]; -} - -inline void vvp_vector8_t::set_bit(unsigned idx, vvp_scalar_t val) -{ - assert(idx < size_); - bits_[idx] = val; -} - /* * This class implements a pointer that points to an item within a * target. The ptr() method returns a pointer to the vvp_net_t, and