Short circuit propagation of part selects when possible
Full vector assigns are able to short circuit the propagation of the value if it finds that there are no value changes. This patch supports that behavior in writes to parts as well. Put this change to use in logic devices as well.
This commit is contained in:
parent
e1c0fa5feb
commit
b3ef8171e2
24
vvp/logic.cc
24
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);
|
||||
|
|
|
|||
145
vvp/vvp_net.cc
145
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_<<adr) & mask);
|
||||
bbits_val_ =
|
||||
(bbits_val_ & ~mask)
|
||||
| ((that.bbits_val_<<adr) & mask);
|
||||
unsigned long tmp = (that.abits_val_<<adr)&mask;
|
||||
if ((abits_val_&mask) != tmp) {
|
||||
diff_flag = true;
|
||||
abits_val_ = (abits_val_ & ~mask) | tmp;
|
||||
}
|
||||
tmp = (that.bbits_val_<<adr) & mask;
|
||||
if ((bbits_val_&mask) != tmp) {
|
||||
diff_flag = true;
|
||||
bbits_val_ = (bbits_val_ & ~mask) | tmp;
|
||||
}
|
||||
|
||||
} else if (that.size_ <= BITS_PER_WORD) {
|
||||
|
||||
|
|
@ -1071,25 +1076,34 @@ void vvp_vector4_t::set_vec(unsigned adr, const vvp_vector4_t&that)
|
|||
hmask = (1UL << hshift) - 1UL;
|
||||
|
||||
unsigned long mask = hmask & ~lmask;
|
||||
unsigned long tmp;
|
||||
|
||||
abits_ptr_[dptr] =
|
||||
(abits_ptr_[dptr] & ~mask)
|
||||
| ((that.abits_val_ << doff) & mask);
|
||||
bbits_ptr_[dptr] =
|
||||
(bbits_ptr_[dptr] & ~mask)
|
||||
| ((that.bbits_val_ << doff) & mask);
|
||||
tmp = (that.abits_val_ << doff) & mask;
|
||||
if ((abits_ptr_[dptr] & mask) != tmp) {
|
||||
diff_flag = true;
|
||||
abits_ptr_[dptr] = (abits_ptr_[dptr] & ~mask) | tmp;
|
||||
}
|
||||
tmp = (that.bbits_val_ << doff) & mask;
|
||||
if ((bbits_ptr_[dptr] & mask) != tmp) {
|
||||
diff_flag = true;
|
||||
bbits_ptr_[dptr] = (bbits_ptr_[dptr] & ~mask) | tmp;
|
||||
}
|
||||
|
||||
if ((doff + that.size_) > 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)
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -30,9 +30,26 @@
|
|||
|
||||
# include <iostream>
|
||||
|
||||
/*
|
||||
* 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 <class T> 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;
|
||||
|
|
|
|||
Loading…
Reference in New Issue