diff --git a/vvp/logic.cc b/vvp/logic.cc index dd0faafbe..1372f9700 100644 --- a/vvp/logic.cc +++ b/vvp/logic.cc @@ -63,10 +63,11 @@ void vvp_fun_boolean_::recv_vec4_pv(vvp_net_ptr_t ptr, const vvp_vector4_t&bit, assert(bit.size() == wid); assert(base + wid <= vwid); - if (input_[port].subvalue(base, wid) .eeq( bit )) + // Set the part for the input. If nothing changes, then break. + bool flag = input_[port] .set_vec(base, bit); + if (flag == false) return; - input_[port] .set_vec(base, bit); if (net_ == 0) { net_ = ptr.ptr(); schedule_functor(this); @@ -151,10 +152,11 @@ void vvp_fun_buf::recv_vec4_pv(vvp_net_ptr_t ptr, const vvp_vector4_t&bit, assert(bit.size() == wid); assert(base + wid <= vwid); - if (input_.subvalue(base, wid) .eeq( bit )) + // Set the input part. If nothing changes, then break. + bool flag = input_.set_vec(base, bit); + if (flag == false) return; - input_.set_vec(base, bit); if (net_ == 0) { net_ = ptr.ptr(); schedule_functor(this); @@ -370,16 +372,17 @@ void vvp_fun_muxz::recv_vec4_pv(vvp_net_ptr_t ptr, const vvp_vector4_t&bit, { assert(bit.size() == wid); assert(base + wid <= vwid); + bool flag; switch (ptr.port()) { case 0: - if (a_.subvalue(base, wid) .eeq(bit) && has_run_) return; - a_.set_vec(base, bit); + flag = a_.set_vec(base, bit); + if (flag == false && has_run_) return; if (select_ == SEL_PORT1) return; // The other port is selected. break; case 1: - if (b_.subvalue(base, wid) .eeq(bit) && has_run_) return; - b_.set_vec(base, bit); + flag = b_.set_vec(base, bit); + if (flag == false && has_run_) return; if (select_ == SEL_PORT0) return; // The other port is selected. break; case 2: @@ -475,10 +478,11 @@ void vvp_fun_not::recv_vec4_pv(vvp_net_ptr_t ptr, const vvp_vector4_t&bit, assert(bit.size() == wid); assert(base + wid <= vwid); - if (input_.subvalue(base, wid) .eeq( bit )) + // Set the part value. If nothing changes, then break. + bool flag = input_.set_vec(base, bit); + if (flag == false) return; - input_.set_vec(base, bit); if (net_ == 0) { net_ = ptr.ptr(); schedule_functor(this); diff --git a/vvp/vvp_net.cc b/vvp/vvp_net.cc index d0128940e..aadaa61c9 100644 --- a/vvp/vvp_net.cc +++ b/vvp/vvp_net.cc @@ -1023,9 +1023,10 @@ void vvp_vector4_t::setarray(unsigned adr, unsigned wid, const unsigned long*val * into the addressed part of this vector. Use bit masking and word * copies to go as fast as reasonably possible. */ -void vvp_vector4_t::set_vec(unsigned adr, const vvp_vector4_t&that) +bool vvp_vector4_t::set_vec(unsigned adr, const vvp_vector4_t&that) { assert(adr+that.size_ <= size_); + bool diff_flag = false; if (size_ <= BITS_PER_WORD) { @@ -1046,12 +1047,16 @@ void vvp_vector4_t::set_vec(unsigned adr, const vvp_vector4_t&that) hmask = (1UL << (adr+that.size_)) - 1; unsigned long mask = hmask & ~lmask; - abits_val_ = - (abits_val_ & ~mask) - | ((that.abits_val_< BITS_PER_WORD) { unsigned tail = doff + that.size_ - BITS_PER_WORD; mask = (1UL << tail) - 1; dptr += 1; - abits_ptr_[dptr] = - (abits_ptr_[dptr] & ~mask) - | ((that.abits_val_ >> (that.size_-tail)) & mask); - bbits_ptr_[dptr] = - (bbits_ptr_[dptr] & ~mask) - | ((that.bbits_val_ >> (that.size_-tail)) & mask); + tmp = (that.abits_val_ >> (that.size_-tail)) & mask; + if ((abits_ptr_[dptr] & mask) != tmp) { + diff_flag = true; + abits_ptr_[dptr] = (abits_ptr_[dptr] & ~mask) | tmp; + } + tmp = (that.bbits_val_ >> (that.size_-tail)) & mask; + if ((bbits_ptr_[dptr] & mask) != tmp) { + diff_flag = true; + bbits_ptr_[dptr] = (bbits_ptr_[dptr] & ~mask) | tmp; + } } } else if (adr%BITS_PER_WORD == 0) { @@ -1102,8 +1116,14 @@ void vvp_vector4_t::set_vec(unsigned adr, const vvp_vector4_t&that) unsigned sptr = 0; unsigned dptr = adr / BITS_PER_WORD; while (remain >= BITS_PER_WORD) { - abits_ptr_[dptr] = that.abits_ptr_[sptr]; - bbits_ptr_[dptr] = that.bbits_ptr_[sptr]; + if (abits_ptr_[dptr] != that.abits_ptr_[sptr]) { + diff_flag = true; + abits_ptr_[dptr] = that.abits_ptr_[sptr]; + } + if (bbits_ptr_[dptr] != that.bbits_ptr_[sptr]) { + diff_flag = true; + bbits_ptr_[dptr] = that.bbits_ptr_[sptr]; + } dptr += 1; sptr += 1; remain -= BITS_PER_WORD; @@ -1111,12 +1131,18 @@ void vvp_vector4_t::set_vec(unsigned adr, const vvp_vector4_t&that) if (remain > 0) { unsigned long mask = (1UL << remain) - 1; - abits_ptr_[dptr] = - (abits_ptr_[dptr] & ~mask) - | (that.abits_ptr_[sptr] & mask); - bbits_ptr_[dptr] = - (bbits_ptr_[dptr] & ~mask) - | (that.bbits_ptr_[sptr] & mask); + unsigned long tmp; + + tmp = that.abits_ptr_[sptr] & mask; + if ((abits_ptr_[dptr] & mask) != tmp) { + diff_flag = true; + abits_ptr_[dptr] = (abits_ptr_[dptr] & ~mask) | tmp; + } + tmp = that.bbits_ptr_[sptr] & mask; + if ((bbits_ptr_[dptr] & mask) != tmp) { + diff_flag = true; + bbits_ptr_[dptr] = (bbits_ptr_[dptr] & ~mask) | tmp; + } } } else { @@ -1131,20 +1157,30 @@ void vvp_vector4_t::set_vec(unsigned adr, const vvp_vector4_t&that) unsigned long lmask = (1UL << doff) - 1; unsigned ndoff = BITS_PER_WORD - doff; while (remain >= BITS_PER_WORD) { - abits_ptr_[dptr] = - (abits_ptr_[dptr] & lmask) - | ((that.abits_ptr_[sptr] << doff) & ~lmask); - bbits_ptr_[dptr] = - (bbits_ptr_[dptr] & lmask) - | ((that.bbits_ptr_[sptr] << doff) & ~lmask); + unsigned long tmp; + + tmp = (that.abits_ptr_[sptr] << doff) & ~lmask; + if ((abits_ptr_[dptr] & ~lmask) != tmp) { + diff_flag = true; + abits_ptr_[dptr] = (abits_ptr_[dptr] & lmask) | tmp; + } + tmp = (that.bbits_ptr_[sptr] << doff) & ~lmask; + if ((bbits_ptr_[dptr] & ~lmask) != tmp) { + diff_flag = true; + bbits_ptr_[dptr] = (bbits_ptr_[dptr] & lmask) | tmp; + } dptr += 1; - abits_ptr_[dptr] = - (abits_ptr_[dptr] & ~lmask) - | ((that.abits_ptr_[sptr] >> ndoff) & lmask); - bbits_ptr_[dptr] = - (bbits_ptr_[dptr] & ~lmask) - | ((that.bbits_ptr_[sptr] >> ndoff) & lmask); + tmp = (that.abits_ptr_[sptr] >> ndoff) & lmask; + if ((abits_ptr_[dptr] & lmask) != tmp) { + diff_flag = true; + abits_ptr_[dptr] = (abits_ptr_[dptr] & ~lmask) | tmp; + } + tmp = (that.bbits_ptr_[sptr] >> ndoff) & lmask; + if ((bbits_ptr_[dptr] & lmask) != tmp) { + diff_flag = true; + bbits_ptr_[dptr] = (bbits_ptr_[dptr] & ~lmask) | tmp; + } remain -= BITS_PER_WORD; sptr += 1; @@ -1159,11 +1195,18 @@ void vvp_vector4_t::set_vec(unsigned adr, const vvp_vector4_t&that) hmask = (1UL << (doff+remain)) - 1; unsigned long mask = hmask & ~lmask; + unsigned long tmp; - abits_ptr_[dptr] = (abits_ptr_[dptr] & ~mask) - | ((that.abits_ptr_[sptr] << doff) & mask); - bbits_ptr_[dptr] = (bbits_ptr_[dptr] & ~mask) - | ((that.bbits_ptr_[sptr] << doff) & mask); + tmp = (that.abits_ptr_[sptr] << doff) & mask; + if ((abits_ptr_[dptr] & mask) != tmp) { + diff_flag = true; + abits_ptr_[dptr] = (abits_ptr_[dptr] & ~mask) | tmp; + } + tmp = (that.bbits_ptr_[sptr] << doff) & mask; + if ((bbits_ptr_[dptr] & mask) != tmp) { + diff_flag = true; + bbits_ptr_[dptr] = (bbits_ptr_[dptr] & ~mask) | tmp; + } if ((doff + remain) > BITS_PER_WORD) { unsigned tail = doff + remain - BITS_PER_WORD; @@ -1173,14 +1216,22 @@ void vvp_vector4_t::set_vec(unsigned adr, const vvp_vector4_t&that) mask = (1UL << tail) - 1; dptr += 1; - abits_ptr_[dptr] = (abits_ptr_[dptr] & ~mask) | - ((that.abits_ptr_[sptr] >> (remain-tail))&mask); - bbits_ptr_[dptr] = (bbits_ptr_[dptr] & ~mask) | - ((that.bbits_ptr_[sptr] >> (remain-tail))&mask); + + tmp = (that.abits_ptr_[sptr] >> (remain-tail))&mask; + if ((abits_ptr_[dptr] & mask) != tmp) { + diff_flag = true; + abits_ptr_[dptr] = (abits_ptr_[dptr] & ~mask) | tmp; + } + tmp = (that.bbits_ptr_[sptr] >> (remain-tail))&mask; + if ((bbits_ptr_[dptr] & mask) != tmp) { + diff_flag = true; + bbits_ptr_[dptr] = (bbits_ptr_[dptr] & ~mask) | tmp; + } } } } + return diff_flag; } void vvp_vector4_t::mov(unsigned dst, unsigned src, unsigned cnt) diff --git a/vvp/vvp_net.h b/vvp/vvp_net.h index e9c55c78a..e3456bbc7 100644 --- a/vvp/vvp_net.h +++ b/vvp/vvp_net.h @@ -234,8 +234,10 @@ class vvp_vector4_t { unsigned long*subarray(unsigned idx, unsigned size) const; void setarray(unsigned idx, unsigned size, const unsigned long*val); + // Set a 4-value bit or subvector into the vector. Return true + // if any bits of the vector change as a result of this operation. void set_bit(unsigned idx, vvp_bit4_t val); - void set_vec(unsigned idx, const vvp_vector4_t&that); + bool set_vec(unsigned idx, const vvp_vector4_t&that); // Get the bits from another vector, but keep my size. void copy_bits(const vvp_vector4_t&that); @@ -1188,11 +1190,10 @@ class vvp_net_fun_t { /* * A vvp_net_fil_t is a filter object that filters an output from a - * vvp_net_t. The send_*() methods of the vvp_net_t object call the + * vvp_net_t. The send_*() methods of the vvp_net_t object invoke the * filter of the output being transmitted. The filter function will - * decide if this value is to be propagated, and return true or - * false. If false, then send_*() continues as usual. If false, output - * propagation is stopped. + * decide if this value is to be propagated, and how, and return a + * prop_t enumeration to reflect the choice. * * The filter object also provides an implementation hooks for * force/release. diff --git a/vvp/vvp_net_sig.cc b/vvp/vvp_net_sig.cc index 183c81b8e..f0f7423ff 100644 --- a/vvp/vvp_net_sig.cc +++ b/vvp/vvp_net_sig.cc @@ -30,9 +30,26 @@ # include +/* + * The filter_mask_ method takes as an input the value to propagate, + * the mask of what is being forced, and returns a propagation + * mode. In the process, it may update the filtered output value. + * + * The input value is the subvector "val" that is placed as "base" in + * the output. The val may be shorter then the target vector. + * + * The "force" vector in the value being force, with the force_mask_ + * member a bit mask of which parts of the force vector really apply. + */ template vvp_net_fil_t::prop_t vvp_net_fil_t::filter_mask_(const T&val, const T&force, T&filter, unsigned base) { if (!test_force_mask_is_zero()) { + // Some bits are being forced. Go through the + // force_mask_ and force value to see which bits are + // propogated and which are kept from the forced + // value. Update the filter with the filtered result and + // return REPL to indicate that some bits have changed, + // or STOP if no bits change. bool propagate_flag = force_propagate_; force_propagate_ = false; assert(force_mask_.size() == force.size()); @@ -639,7 +656,8 @@ vvp_net_fil_t::prop_t vvp_wire_vec4::filter_vec4(const vvp_vector4_t&bit, vvp_ve if (bits4_ .eeq( bit ) && !needs_init_) return STOP; bits4_ = bit; } else { - bits4_.set_vec(base, bit); + bool rc = bits4_.set_vec(base, bit); + if (rc == false && !needs_init_) return STOP; } needs_init_ = false; @@ -660,7 +678,8 @@ vvp_net_fil_t::prop_t vvp_wire_vec4::filter_vec8(const vvp_vector8_t&bit, if (bits4_ .eeq( bit4 ) && !needs_init_) return STOP; bits4_ = bit4; } else { - bits4_.set_vec(base, bit4); + bool rc = bits4_.set_vec(base, bit4); + if (rc == false && !needs_init_) return STOP; } needs_init_ = false;