Change implementation of force/release to use filters.

This is moving towards moving force/release out of the signal
class. The end-game is to remove all of the wire implementation
out of the functor and into the filter. Variables will remain in
the functor.
This commit is contained in:
Stephen Williams 2009-05-04 20:26:41 -07:00
parent 79a5dde7c4
commit ba00c6caf7
4 changed files with 364 additions and 190 deletions

View File

@ -202,22 +202,22 @@ vvp_net_fil_t::~vvp_net_fil_t()
{ {
} }
bool vvp_net_fil_t::filter_vec4(const vvp_vector4_t&) const vvp_vector4_t* vvp_net_fil_t::filter_vec4(const vvp_vector4_t&val)
{
return &val;
}
const vvp_vector8_t* vvp_net_fil_t::filter_vec8(const vvp_vector8_t&val)
{
return &val;
}
bool vvp_net_fil_t::filter_real(double&)
{ {
return true; return true;
} }
bool vvp_net_fil_t::filter_vec8(const vvp_vector8_t&) bool vvp_net_fil_t::filter_long(long&)
{
return true;
}
bool vvp_net_fil_t::filter_real(double)
{
return true;
}
bool vvp_net_fil_t::filter_long(long)
{ {
return true; return true;
} }
@ -387,6 +387,8 @@ void vvp_send_long_pv(vvp_net_ptr_t ptr, long val,
} }
} }
const vvp_vector4_t vvp_vector4_t::nil;
void vvp_vector4_t::copy_bits(const vvp_vector4_t&that) void vvp_vector4_t::copy_bits(const vvp_vector4_t&that)
{ {
@ -2369,6 +2371,8 @@ vvp_vector8_t::vvp_vector8_t(const vvp_vector4_t&that,
} }
const vvp_vector8_t vvp_vector8_t::nil;
vvp_vector8_t& vvp_vector8_t::operator= (const vvp_vector8_t&that) vvp_vector8_t& vvp_vector8_t::operator= (const vvp_vector8_t&that)
{ {
// Assign to self. // Assign to self.

View File

@ -196,6 +196,9 @@ class vvp_vector4_t {
friend class vvp_vector4array_sa; friend class vvp_vector4array_sa;
friend class vvp_vector4array_aa; friend class vvp_vector4array_aa;
public:
static const vvp_vector4_t nil;
public: public:
explicit vvp_vector4_t(unsigned size =0, vvp_bit4_t bits =BIT4_X); explicit vvp_vector4_t(unsigned size =0, vvp_bit4_t bits =BIT4_X);
@ -778,6 +781,10 @@ class vvp_vector8_t {
~vvp_vector8_t(); ~vvp_vector8_t();
static const vvp_vector8_t nil;
public:
unsigned size() const { return size_; } unsigned size() const { return size_; }
vvp_scalar_t value(unsigned idx) const; vvp_scalar_t value(unsigned idx) const;
vvp_vector8_t subvalue(unsigned adr, unsigned width) const; vvp_vector8_t subvalue(unsigned adr, unsigned width) const;
@ -1088,10 +1095,16 @@ class vvp_net_fil_t {
virtual ~vvp_net_fil_t(); virtual ~vvp_net_fil_t();
public: public:
virtual bool filter_vec4(const vvp_vector4_t&bit); // Return a non-empty vector if the filter allows an
virtual bool filter_vec8(const vvp_vector8_t&val); // output. The output result may be different from the
virtual bool filter_real(double val); // input. If the output is nil, then suppress propagation.
virtual bool filter_long(long val); virtual const vvp_vector4_t* filter_vec4(const vvp_vector4_t&bit);
virtual const vvp_vector8_t* filter_vec8(const vvp_vector8_t&val);
// Return true if the value is to be propagated, or false if
// propagation is suppressed. The value may be edited by the filter.
virtual bool filter_real(double&val);
virtual bool filter_long(long&val);
}; };
/* **** Some core net functions **** */ /* **** Some core net functions **** */
@ -1335,10 +1348,11 @@ inline void vvp_net_t::send_vec8_pv(const vvp_vector8_t&val,
inline void vvp_net_t::send_vec4(const vvp_vector4_t&val, vvp_context_t context) inline void vvp_net_t::send_vec4(const vvp_vector4_t&val, vvp_context_t context)
{ {
if (fil && ! fil->filter_vec4(val)) const vvp_vector4_t*val_out = fil? fil->filter_vec4(val) : &val;
if (val_out == 0)
return; return;
vvp_send_vec4(out_, val, context); vvp_send_vec4(out_, *val_out, context);
} }
inline void vvp_net_t::send_vec4_pv(const vvp_vector4_t&val, inline void vvp_net_t::send_vec4_pv(const vvp_vector4_t&val,
@ -1350,10 +1364,11 @@ inline void vvp_net_t::send_vec4_pv(const vvp_vector4_t&val,
inline void vvp_net_t::send_vec8(const vvp_vector8_t&val) inline void vvp_net_t::send_vec8(const vvp_vector8_t&val)
{ {
if (fil && ! fil->filter_vec8(val)) const vvp_vector8_t*val_out = fil? fil->filter_vec8(val) : &val;
if (val_out == 0)
return; return;
vvp_send_vec8(out_, val); vvp_send_vec8(out_, *val_out);
} }
inline void vvp_net_t::send_real(double val, vvp_context_t context) inline void vvp_net_t::send_real(double val, vvp_context_t context)

View File

@ -43,58 +43,205 @@ template <class T> T coerce_to_width(const T&that, unsigned width)
vvp_filter_wire_base::vvp_filter_wire_base() vvp_filter_wire_base::vvp_filter_wire_base()
{ {
continuous_assign_active_ = false;
} }
vvp_filter_wire_base::~vvp_filter_wire_base() vvp_filter_wire_base::~vvp_filter_wire_base()
{ {
} }
bool vvp_filter_wire_base::filter_vec4(const vvp_vector4_t&) const vvp_vector4_t* vvp_filter_wire_base::filter_vec4(const vvp_vector4_t&val)
{
if (force_mask_.size()) {
bool propagate_flag = false;
assert(val.size() == force_mask_.size());
assert(val.size() == force4_.size());
filter4_ = val;
for (unsigned idx = 0 ; idx < val.size() ; idx += 1) {
if (force_mask_.value(idx))
filter4_.set_bit(idx, force4_.value(idx));
else
propagate_flag = true;
}
if (propagate_flag) {
run_vpi_callbacks();
return &filter4_;
} else {
return 0;
}
} else {
run_vpi_callbacks();
return &val;
}
}
const vvp_vector8_t* vvp_filter_wire_base::filter_vec8(const vvp_vector8_t&val)
{
if (force_mask_.size()) {
bool propagate_flag = false;
assert(val.size() == force_mask_.size());
assert(val.size() == force8_.size());
filter8_ = val;
for (unsigned idx = 0 ; idx < val.size() ; idx += 1) {
if (force_mask_.value(idx))
filter8_.set_bit(idx, force8_.value(idx));
else
propagate_flag = true;
}
if (propagate_flag) {
run_vpi_callbacks();
return&filter8_;
} else {
return 0;
}
} else {
run_vpi_callbacks();
return &val;
}
}
bool vvp_filter_wire_base::filter_real(double&val)
{ {
run_vpi_callbacks(); run_vpi_callbacks();
return true; return true;
} }
bool vvp_filter_wire_base::filter_vec8(const vvp_vector8_t&) bool vvp_filter_wire_base::filter_long(long&)
{ {
run_vpi_callbacks(); run_vpi_callbacks();
return true; return true;
} }
bool vvp_filter_wire_base::filter_real(double) void vvp_filter_wire_base::force_vec4(const vvp_vector4_t&val, vvp_vector2_t mask)
{ {
run_vpi_callbacks(); if (force_mask_.size() == 0)
return true; force_mask_ = vvp_vector2_t(vvp_vector2_t::FILL0, mask.size());
if (force4_.size() == 0)
force4_ = val;
assert(force_mask_.size() == mask.size());
for (unsigned idx = 0; idx < mask.size() ; idx += 1) {
if (mask.value(idx) == 0)
continue;
force_mask_.set_bit(idx, 1);
force4_.set_bit(idx, val.value(idx));
}
} }
bool vvp_filter_wire_base::filter_long(long) void vvp_filter_wire_base::force_vec8(const vvp_vector8_t&val, vvp_vector2_t mask)
{ {
run_vpi_callbacks(); if (force_mask_.size() == 0)
return true; force_mask_ = vvp_vector2_t(vvp_vector2_t::FILL0, mask.size());
if (force8_.size() == 0)
force8_ = val;
assert(force_mask_.size() == mask.size());
for (unsigned idx = 0; idx < mask.size() ; idx += 1) {
if (mask.value(idx) == 0)
continue;
force_mask_.set_bit(idx, 1);
force8_.set_bit(idx, val.value(idx));
}
} }
void vvp_filter_wire_base::deassign() void vvp_filter_wire_base::force_real(double val, vvp_vector2_t mask)
{ {
continuous_assign_active_ = false; if (force_mask_.size() == 0)
assign_mask_ = vvp_vector2_t(); force_mask_ = vvp_vector2_t(vvp_vector2_t::FILL0, mask.size());
}
void vvp_filter_wire_base::deassign_pv(unsigned base, unsigned wid) assert(force_mask_.size() == mask.size());
{ for (unsigned idx = 0 ; idx < mask.size() ; idx += 1) {
for (unsigned idx = 0 ; idx < wid ; idx += 1) { if (mask.value(idx) == 0)
assign_mask_.set_bit(base+idx, 0); continue;
force_mask_.set_bit(idx, 1);
} }
if (assign_mask_.is_zero()) { force_real_ = val;
assign_mask_ = vvp_vector2_t(); }
vvp_bit4_t vvp_filter_wire_base::filtered_value(const vvp_vector4_t&val, unsigned idx) const
{
if (force_mask_.size() == 0)
return val.value(idx);
if (force_mask_.value(idx))
return force4_.value(idx);
return val.value(idx);
}
vvp_scalar_t vvp_filter_wire_base::filtered_value(const vvp_vector8_t&val, unsigned idx) const
{
if (force_mask_.size() == 0)
return val.value(idx);
if (force_mask_.value(idx))
return force8_.value(idx);
return val.value(idx);
}
const vvp_vector4_t& vvp_filter_wire_base::filtered_vec4(const vvp_vector4_t&val) const
{
if (force_mask_.size() == 0)
return val;
filter4_ = val;
for (unsigned idx = 0 ; idx < val.size() ; idx += 1) {
if (force_mask_.value(idx))
filter4_.set_bit(idx, force4_.value(idx));
} }
return filter4_;
}
const vvp_vector8_t& vvp_filter_wire_base::filtered_vec8(const vvp_vector8_t&val) const
{
if (force_mask_.size() == 0)
return val;
filter8_ = val;
for (unsigned idx = 0 ; idx < val.size() ; idx += 1) {
if (force_mask_.value(idx))
filter8_.set_bit(idx, force8_.value(idx));
}
return filter8_;
}
double vvp_filter_wire_base::filtered_real(double val) const
{
if (force_mask_.size() == 0)
return val;
if (force_mask_.value(0) == 0)
return val;
return force_real_;
}
void vvp_filter_wire_base::release_mask(vvp_vector2_t mask)
{
if (force_mask_.size() == 0)
return;
assert(force_mask_.size() == mask.size());
for (unsigned idx = 0 ; idx < mask.size() ; idx += 1) {
if (mask.value(idx))
force_mask_.set_bit(idx, 0);
}
if (force_mask_.is_zero())
force_mask_ = vvp_vector2_t();
} }
/* **** vvp_fun_signal methods **** */ /* **** vvp_fun_signal methods **** */
vvp_fun_signal_base::vvp_fun_signal_base() vvp_fun_signal_base::vvp_fun_signal_base()
{ {
continuous_assign_active_ = false;
needs_init_ = true; needs_init_ = true;
force_link = 0; force_link = 0;
cassign_link = 0; cassign_link = 0;
@ -216,17 +363,17 @@ void vvp_fun_signal4_sa::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
break; break;
case 2: // Force value case 2: // Force value
{ vvp_vector4_t tmp (bit);
// Force from a node may not have been sized completely // Force from a node may not have been sized completely
// by the source, so coerce the size here. // by the source, so coerce the size here.
if (bit.size() != size()) if (tmp.size() != size())
force_ = coerce_to_width(bit, size()); tmp = coerce_to_width(tmp, size());
else
force_ = bit;
force_mask_ = vvp_vector2_t(vvp_vector2_t::FILL1, size()); ptr.ptr()->send_vec4(tmp, 0);
calculate_output_(ptr); force_vec4(tmp, vvp_vector2_t(vvp_vector2_t::FILL1,tmp.size()));
break; }
break;
default: default:
fprintf(stderr, "Unsupported port type %d.\n", ptr.port()); fprintf(stderr, "Unsupported port type %d.\n", ptr.port());
@ -285,19 +432,16 @@ void vvp_fun_signal4_sa::recv_vec4_pv(vvp_net_ptr_t ptr, const vvp_vector4_t&bit
break; break;
case 2: // Force value case 2: // Force value
{ vvp_vector2_t mask (vvp_vector2_t::FILL0, vwid);
if (force_mask_.size() == 0) vvp_vector4_t vec (vwid, BIT4_Z);
force_mask_ = vvp_vector2_t(vvp_vector2_t::FILL0, size()); for (unsigned idx = 0 ; idx < wid ; idx += 1) {
if (force_.size() == 0) mask.set_bit(base+idx, 1);
force_ = vvp_vector4_t(vwid, BIT4_Z); vec.set_bit(base+idx, bit.value(idx));
}
for (unsigned idx = 0 ; idx < wid ; idx += 1) { force_vec4(vec, mask);
force_mask_.set_bit(base+idx, 1); calculate_output_(ptr);
force_.set_bit(base+idx, bit.value(idx)); break;
} }
calculate_output_(ptr);
break;
default: default:
fprintf(stderr, "Unsupported port type %d.\n", ptr.port()); fprintf(stderr, "Unsupported port type %d.\n", ptr.port());
@ -314,27 +458,39 @@ void vvp_fun_signal4_sa::recv_vec8_pv(vvp_net_ptr_t ptr, const vvp_vector8_t&bit
void vvp_fun_signal4_sa::calculate_output_(vvp_net_ptr_t ptr) void vvp_fun_signal4_sa::calculate_output_(vvp_net_ptr_t ptr)
{ {
if (force_mask_.size()) { ptr.ptr()->send_vec4(bits4_, 0);
assert(bits4_.size() == force_mask_.size());
assert(bits4_.size() == force_.size());
vvp_vector4_t bits (bits4_);
for (unsigned idx = 0 ; idx < bits.size() ; idx += 1) {
if (force_mask_.value(idx))
bits.set_bit(idx, force_.value(idx));
}
ptr.ptr()->send_vec4(bits, 0);
} else {
ptr.ptr()->send_vec4(bits4_, 0);
}
} }
void vvp_fun_signal_base::deassign()
{
continuous_assign_active_ = false;
assign_mask_ = vvp_vector2_t();
}
void vvp_fun_signal_base::deassign_pv(unsigned base, unsigned wid)
{
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
assign_mask_.set_bit(base+idx, 0);
}
if (assign_mask_.is_zero()) {
assign_mask_ = vvp_vector2_t();
}
}
void vvp_fun_signal4_sa::release(vvp_net_ptr_t ptr, bool net) void vvp_fun_signal4_sa::release(vvp_net_ptr_t ptr, bool net)
{ {
force_mask_ = vvp_vector2_t(); vvp_vector2_t mask (vvp_vector2_t::FILL1, bits4_.size());
if (net) { if (net) {
// If releasing a net, then the output should revert to
// the un-forced value.
release_mask(mask);
ptr.ptr()->send_vec4(bits4_, 0); ptr.ptr()->send_vec4(bits4_, 0);
} else { } else {
bits4_ = force_; // Variables keep their forced value after the release.
bits4_ = filtered_vec4(bits4_);
release_mask(mask);
} }
} }
@ -343,55 +499,38 @@ void vvp_fun_signal4_sa::release_pv(vvp_net_ptr_t ptr, bool net,
{ {
assert(bits4_.size() >= base + wid); assert(bits4_.size() >= base + wid);
for (unsigned idx = 0 ; idx < wid ; idx += 1) { vvp_vector2_t mask (vvp_vector2_t::FILL0, bits4_.size());
force_mask_.set_bit(base+idx, 0); for (unsigned idx = 0 ; idx < wid ; idx += 1)
if (!net) bits4_.set_bit(base+idx, force_.value(base+idx)); mask.set_bit(base+idx, 1);
}
if (force_mask_.is_zero()) force_mask_ = vvp_vector2_t(); if (net) {
release_mask(mask);
calculate_output_(ptr);
} else {
bits4_ = filtered_vec4(bits4_);
release_mask(mask);
}
if (net) calculate_output_(ptr);
} }
unsigned vvp_fun_signal4_sa::size() const unsigned vvp_fun_signal4_sa::size() const
{ {
if (force_mask_.size()) return bits4_.size();
return force_.size();
else
return bits4_.size();
} }
vvp_bit4_t vvp_fun_signal4_sa::value(unsigned idx) const vvp_bit4_t vvp_fun_signal4_sa::value(unsigned idx) const
{ {
if (force_mask_.size() && force_mask_.value(idx)) { return filtered_value(bits4_, idx);
return force_.value(idx);
} else {
return bits4_.value(idx);
}
} }
vvp_scalar_t vvp_fun_signal4_sa::scalar_value(unsigned idx) const vvp_scalar_t vvp_fun_signal4_sa::scalar_value(unsigned idx) const
{ {
if (force_mask_.size() && force_mask_.value(idx)) { return vvp_scalar_t(value(idx), 6, 6);
return vvp_scalar_t(force_.value(idx), 6, 6);
} else {
return vvp_scalar_t(bits4_.value(idx), 6, 6);
}
} }
vvp_vector4_t vvp_fun_signal4_sa::vec4_value() const vvp_vector4_t vvp_fun_signal4_sa::vec4_value() const
{ {
if (force_mask_.size()) { return filtered_vec4(bits4_);
assert(bits4_.size() == force_mask_.size());
assert(bits4_.size() == force_.size());
vvp_vector4_t bits (bits4_);
for (unsigned idx = 0 ; idx < bits.size() ; idx += 1) {
if (force_mask_.value(idx))
bits.set_bit(idx, force_.value(idx));
}
return bits;
} else {
return bits4_;
}
} }
vvp_fun_signal4_aa::vvp_fun_signal4_aa(unsigned wid, vvp_bit4_t init) vvp_fun_signal4_aa::vvp_fun_signal4_aa(unsigned wid, vvp_bit4_t init)
@ -532,17 +671,22 @@ void vvp_fun_signal8::recv_vec8(vvp_net_ptr_t ptr, const vvp_vector8_t&bit)
break; break;
case 2: // Force value case 2: // Force value
{ vvp_vector8_t tmp(bit);
// Force from a node may not have been sized completely // Force from a node may not have been sized completely
// by the source, so coerce the size here. // by the source, so coerce the size here.
if (bit.size() != size()) if (tmp.size() != size())
force_ = coerce_to_width(bit, size()); tmp = coerce_to_width(tmp, size());
else
force_ = bit;
force_mask_ = vvp_vector2_t(vvp_vector2_t::FILL1, size()); // Propagate the forced value before setting the
calculate_output_(ptr); // force mask. This is so that the forced value gets
break; // out to the network before the force filter is set
// up. If the force filter is set up first, then the
// filter will block the exact match.
ptr.ptr()->send_vec8(tmp);
force_vec8(tmp, vvp_vector2_t(vvp_vector2_t::FILL1,tmp.size()));
}
break;
default: default:
fprintf(stderr, "Unsupported port type %d.\n", ptr.port()); fprintf(stderr, "Unsupported port type %d.\n", ptr.port());
@ -582,19 +726,16 @@ void vvp_fun_signal8::recv_vec8_pv(vvp_net_ptr_t ptr, const vvp_vector8_t&bit,
break; break;
case 2: // Force value case 2: // Force value
{ vvp_vector2_t mask (vvp_vector2_t::FILL0, vwid);
if (force_mask_.size() == 0) vvp_vector8_t vec (vvp_vector4_t(vwid, BIT4_Z),6,6);
force_mask_ = vvp_vector2_t(vvp_vector2_t::FILL0, size()); for (unsigned idx = 0 ; idx < wid ; idx += 1) {
if (force_.size() == 0) mask.set_bit(base+idx, 1);
force_ = vvp_vector8_t(vvp_vector4_t(vwid, BIT4_Z),6,6); vec.set_bit(base+idx, bit.value(idx));
}
for (unsigned idx = 0 ; idx < wid ; idx += 1) { force_vec8(vec, mask);
force_mask_.set_bit(base+idx, 1); calculate_output_(ptr);
force_.set_bit(base+idx, bit.value(idx)); break;
} }
calculate_output_(ptr);
break;
default: default:
fprintf(stderr, "Unsupported port type %d.\n", ptr.port()); fprintf(stderr, "Unsupported port type %d.\n", ptr.port());
@ -605,28 +746,22 @@ void vvp_fun_signal8::recv_vec8_pv(vvp_net_ptr_t ptr, const vvp_vector8_t&bit,
void vvp_fun_signal8::calculate_output_(vvp_net_ptr_t ptr) void vvp_fun_signal8::calculate_output_(vvp_net_ptr_t ptr)
{ {
if (force_mask_.size()) { ptr.ptr()->send_vec8(bits8_);
assert(bits8_.size() == force_mask_.size());
assert(bits8_.size() == force_.size());
vvp_vector8_t bits (bits8_);
for (unsigned idx = 0 ; idx < bits.size() ; idx += 1) {
if (force_mask_.value(idx))
bits.set_bit(idx, force_.value(idx));
}
ptr.ptr()->send_vec8(bits);
} else {
ptr.ptr()->send_vec8(bits8_);
}
} }
void vvp_fun_signal8::release(vvp_net_ptr_t ptr, bool net) void vvp_fun_signal8::release(vvp_net_ptr_t ptr, bool net)
{ {
force_mask_ = vvp_vector2_t(); vvp_vector2_t mask (vvp_vector2_t::FILL1, bits8_.size());
if (net) { if (net) {
// If releasing a net, then the output should revert to
// the un-forced value.
release_mask(mask);
ptr.ptr()->send_vec8(bits8_); ptr.ptr()->send_vec8(bits8_);
} else { } else {
bits8_ = force_; // Variables keep their forced value after the release.
bits8_ = filtered_vec8(bits8_);
release_mask(mask);
} }
} }
@ -635,50 +770,37 @@ void vvp_fun_signal8::release_pv(vvp_net_ptr_t ptr, bool net,
{ {
assert(bits8_.size() >= base + wid); assert(bits8_.size() >= base + wid);
for (unsigned idx = 0 ; idx < wid ; idx += 1) { vvp_vector2_t mask (vvp_vector2_t::FILL0, bits8_.size());
force_mask_.set_bit(base+idx, 0); for (unsigned idx = 0 ; idx < wid ; idx += 1)
if (!net) bits8_.set_bit(base+idx, force_.value(base+idx)); mask.set_bit(base+idx, 1);
}
if (force_mask_.is_zero()) force_mask_ = vvp_vector2_t();
if (net) calculate_output_(ptr); if (net) {
release_mask(mask);
calculate_output_(ptr);
} else {
bits8_ = filtered_vec8(bits8_);
release_mask(mask);
}
} }
unsigned vvp_fun_signal8::size() const unsigned vvp_fun_signal8::size() const
{ {
if (force_mask_.size()) return bits8_.size();
return force_.size();
else
return bits8_.size();
} }
vvp_bit4_t vvp_fun_signal8::value(unsigned idx) const vvp_bit4_t vvp_fun_signal8::value(unsigned idx) const
{ {
if (force_mask_.size() && force_mask_.value(idx)) return filtered_value(bits8_, idx).value();
return force_.value(idx).value();
else
return bits8_.value(idx).value();
} }
vvp_vector4_t vvp_fun_signal8::vec4_value() const vvp_vector4_t vvp_fun_signal8::vec4_value() const
{ {
if (force_mask_.size()) { return reduce4(filtered_vec8(bits8_));
vvp_vector8_t bits (bits8_);
for (unsigned idx = 0 ; idx < bits.size() ; idx += 1) {
if (force_mask_.value(idx))
bits.set_bit(idx, force_.value(idx));
}
return reduce4(bits);
} else
return reduce4(bits8_);
} }
vvp_scalar_t vvp_fun_signal8::scalar_value(unsigned idx) const vvp_scalar_t vvp_fun_signal8::scalar_value(unsigned idx) const
{ {
if (force_mask_.size() && force_mask_.value(idx)) return filtered_value(bits8_, idx);
return force_.value(idx);
else
return bits8_.value(idx);
} }
@ -699,10 +821,7 @@ vvp_fun_signal_real_sa::vvp_fun_signal_real_sa()
double vvp_fun_signal_real_sa::real_value() const double vvp_fun_signal_real_sa::real_value() const
{ {
if (force_mask_.size()) return filtered_real(bits_);
return force_;
else
return bits_;
} }
void vvp_fun_signal_real_sa::recv_real(vvp_net_ptr_t ptr, double bit, void vvp_fun_signal_real_sa::recv_real(vvp_net_ptr_t ptr, double bit,
@ -726,8 +845,7 @@ void vvp_fun_signal_real_sa::recv_real(vvp_net_ptr_t ptr, double bit,
break; break;
case 2: // Force value case 2: // Force value
force_mask_ = vvp_vector2_t(1, 1); force_real(bit, vvp_vector2_t(vvp_vector2_t::FILL1, 1));
force_ = bit;
ptr.ptr()->send_real(bit, 0); ptr.ptr()->send_real(bit, 0);
break; break;
@ -740,11 +858,14 @@ void vvp_fun_signal_real_sa::recv_real(vvp_net_ptr_t ptr, double bit,
void vvp_fun_signal_real_sa::release(vvp_net_ptr_t ptr, bool net) void vvp_fun_signal_real_sa::release(vvp_net_ptr_t ptr, bool net)
{ {
force_mask_ = vvp_vector2_t(); vvp_vector2_t mask (vvp_vector2_t::FILL1, 1);
if (net) { if (net) {
release_mask(mask);
ptr.ptr()->send_real(bits_, 0); ptr.ptr()->send_real(bits_, 0);
} else { } else {
bits_ = force_; bits_ = filtered_real(bits_);
release_mask(mask);
} }
} }

View File

@ -134,23 +134,51 @@ class vvp_filter_wire_base : public vvp_net_fil_t, public vvp_vpi_callback {
vvp_filter_wire_base(); vvp_filter_wire_base();
~vvp_filter_wire_base(); ~vvp_filter_wire_base();
bool filter_vec4(const vvp_vector4_t&val); // These are the virtual methods that we implement to perform
bool filter_vec8(const vvp_vector8_t&val); // the wire-style filtering.
bool filter_real(double val); const vvp_vector4_t* filter_vec4(const vvp_vector4_t&val);
bool filter_long(long val); const vvp_vector8_t* filter_vec8(const vvp_vector8_t&val);
bool filter_real(double&val);
bool filter_long(long&val);
public: public:
void deassign(); // Force/release work in the filter by setting the forced
void deassign_pv(unsigned base, unsigned wid); // value using one of the force_* methods. This sets the
// forced value as a mask of the bits of the vector that are
// forced. The filter then automatically runs the filter on
// the outputs that pass through. You can also get at the
// filtering results using the filtered_* methods. The
// release_mask() method releases bits of the vector.
// Enable filter force.
void force_vec4(const vvp_vector4_t&val, vvp_vector2_t mask);
void force_vec8(const vvp_vector8_t&val, vvp_vector2_t mask);
void force_real(double val, vvp_vector2_t mask);
// Test the value against the filter.
vvp_bit4_t filtered_value(const vvp_vector4_t&val, unsigned idx) const;
vvp_scalar_t filtered_value(const vvp_vector8_t&val, unsigned idx) const;
const vvp_vector4_t& filtered_vec4(const vvp_vector4_t&val) const;
const vvp_vector8_t& filtered_vec8(const vvp_vector8_t&val) const;
double filtered_real(double val) const;
// Release the force on the bits set in the mask.
void release_mask(vvp_vector2_t mask);
virtual void release(vvp_net_ptr_t ptr, bool net) =0; virtual void release(vvp_net_ptr_t ptr, bool net) =0;
virtual void release_pv(vvp_net_ptr_t ptr, bool net, virtual void release_pv(vvp_net_ptr_t ptr, bool net,
unsigned base, unsigned wid) =0; unsigned base, unsigned wid) =0;
protected: private:
bool continuous_assign_active_; // Forced value
vvp_vector2_t force_mask_; vvp_vector2_t force_mask_;
vvp_vector2_t assign_mask_; vvp_vector4_t force4_;
vvp_vector8_t force8_;
double force_real_;
// This is used as a static return value.
mutable vvp_vector4_t filter4_;
mutable vvp_vector8_t filter8_;
}; };
class vvp_fun_signal_base : public vvp_net_fun_t, public vvp_filter_wire_base { class vvp_fun_signal_base : public vvp_net_fun_t, public vvp_filter_wire_base {
@ -161,6 +189,9 @@ class vvp_fun_signal_base : public vvp_net_fun_t, public vvp_filter_wire_base {
void recv_long_pv(vvp_net_ptr_t port, long bit, void recv_long_pv(vvp_net_ptr_t port, long bit,
unsigned base, unsigned wid); unsigned base, unsigned wid);
void deassign();
void deassign_pv(unsigned base, unsigned wid);
public: public:
/* The %force/link instruction needs a place to write the /* The %force/link instruction needs a place to write the
@ -169,6 +200,10 @@ class vvp_fun_signal_base : public vvp_net_fun_t, public vvp_filter_wire_base {
struct vvp_net_t*force_link; struct vvp_net_t*force_link;
struct vvp_net_t*cassign_link; struct vvp_net_t*cassign_link;
protected:
bool continuous_assign_active_;
vvp_vector2_t assign_mask_;
protected: protected:
// This is true until at least one propagation happens. // This is true until at least one propagation happens.
@ -232,7 +267,6 @@ class vvp_fun_signal4_sa : public vvp_fun_signal4 {
void calculate_output_(vvp_net_ptr_t ptr); void calculate_output_(vvp_net_ptr_t ptr);
vvp_vector4_t bits4_; vvp_vector4_t bits4_;
vvp_vector4_t force_;
}; };
/* /*