Handle filtered part selects.

filters need to be able to cope with parts of vectors moving through
the net. It makes the most sense to handle every filter as a part-
selected filter.
This commit is contained in:
Stephen Williams 2009-09-08 21:42:50 -07:00
parent 9c516a9d53
commit a58c02899b
4 changed files with 73 additions and 27 deletions

View File

@ -206,12 +206,12 @@ vvp_net_fil_t::~vvp_net_fil_t()
assert(force_link_ == 0);
}
vvp_net_fil_t::prop_t vvp_net_fil_t::filter_vec4(const vvp_vector4_t&val, vvp_vector4_t&)
vvp_net_fil_t::prop_t vvp_net_fil_t::filter_vec4(const vvp_vector4_t&val, vvp_vector4_t&, unsigned, unsigned)
{
return PROP;
}
vvp_net_fil_t::prop_t vvp_net_fil_t::filter_vec8(const vvp_vector8_t&val, vvp_vector8_t&)
vvp_net_fil_t::prop_t vvp_net_fil_t::filter_vec8(const vvp_vector8_t&val, vvp_vector8_t&, unsigned, unsigned)
{
return PROP;
}
@ -2514,6 +2514,13 @@ vvp_vector8_t vvp_vector8_t::subvalue(unsigned base, unsigned wid) const
return tmp;
}
void vvp_vector8_t::set_vec(unsigned base, const vvp_vector8_t&that)
{
assert((base+that.size()) <= size());
for (unsigned idx = 0 ; idx < that.size() ; idx += 1)
set_bit(base+idx, that.value(idx));
}
vvp_vector8_t part_expand(const vvp_vector8_t&that, unsigned wid, unsigned off)
{
assert(off < wid);

View File

@ -796,6 +796,7 @@ class vvp_vector8_t {
vvp_scalar_t value(unsigned idx) const;
vvp_vector8_t subvalue(unsigned adr, unsigned width) const;
void set_bit(unsigned idx, vvp_scalar_t val);
void set_vec(unsigned idx, const vvp_vector8_t&that);
// Test that the vectors are exactly equal
bool eeq(const vvp_vector8_t&that) const;
@ -1128,8 +1129,10 @@ class vvp_net_fil_t : public vvp_vpi_callback {
// Return true if the value is to be propagated, or false if
// propagation is suppressed. The value may be edited by the
// filter, or overridden by the rep argument if present.
virtual prop_t filter_vec4(const vvp_vector4_t&bit, vvp_vector4_t&rep);
virtual prop_t filter_vec8(const vvp_vector8_t&val, vvp_vector8_t&rep);
virtual prop_t filter_vec4(const vvp_vector4_t&bit, vvp_vector4_t&rep,
unsigned base, unsigned vwid);
virtual prop_t filter_vec8(const vvp_vector8_t&val, vvp_vector8_t&rep,
unsigned base, unsigned vwid);
virtual prop_t filter_real(double&val);
virtual prop_t filter_long(long&val);
@ -1164,7 +1167,7 @@ class vvp_net_fil_t : public vvp_vpi_callback {
// currently forced value, and the buf is a value that this
// method will use to hold a filtered value, if needed. This
// method returns a pointer to val or buf.
template <class T> prop_t filter_mask_(const T&val, const T&force, T&rep);
template <class T> prop_t filter_mask_(const T&val, const T&force, T&rep, unsigned addr);
// This template method is similar to the above, but works for
// native types that are not so expensive to edit in place.
template <class T> prop_t filter_mask_(T&val, T force);
@ -1447,7 +1450,7 @@ inline void vvp_net_t::send_vec4(const vvp_vector4_t&val, vvp_context_t context)
}
vvp_vector4_t rep;
switch (fil->filter_vec4(val, rep)) {
switch (fil->filter_vec4(val, rep, 0, val.size())) {
case vvp_net_fil_t::STOP:
break;
case vvp_net_fil_t::PROP:
@ -1463,7 +1466,23 @@ inline void vvp_net_t::send_vec4_pv(const vvp_vector4_t&val,
unsigned base, unsigned wid, unsigned vwid,
vvp_context_t context)
{
if (fil == 0) {
vvp_send_vec4_pv(out_, val, base, wid, vwid, context);
return;
}
assert(val.size() == wid);
vvp_vector4_t rep;
switch (fil->filter_vec4(val, rep, base, vwid)) {
case vvp_net_fil_t::STOP:
break;
case vvp_net_fil_t::PROP:
vvp_send_vec4_pv(out_, val, base, wid, vwid, context);
break;
case vvp_net_fil_t::REPL:
vvp_send_vec4_pv(out_, rep, base, wid, vwid, context);
break;
}
}
inline void vvp_net_t::send_vec8(const vvp_vector8_t&val)
@ -1474,7 +1493,7 @@ inline void vvp_net_t::send_vec8(const vvp_vector8_t&val)
}
vvp_vector8_t rep;
switch (fil->filter_vec8(val, rep)) {
switch (fil->filter_vec8(val, rep, 0, val.size())) {
case vvp_net_fil_t::STOP:
break;
case vvp_net_fil_t::PROP:

View File

@ -30,18 +30,18 @@
# include <iostream>
template <class T> vvp_net_fil_t::prop_t vvp_net_fil_t::filter_mask_(const T&val, const T&force, T&filter)
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()) {
bool propagate_flag = force_propagate_;
force_propagate_ = false;
assert(val.size() == force_mask_.size());
assert(val.size() == force.size());
assert(force_mask_.size() == force.size());
assert((base+val.size()) <= force_mask_.size());
filter = val;
for (unsigned idx = 0 ; idx < val.size() ; idx += 1) {
if (force_mask_.value(idx))
filter.set_bit(idx, force.value(idx));
if (force_mask_.value(base+idx))
filter.set_bit(idx, force.value(base+idx));
else
propagate_flag = true;
}
@ -612,18 +612,26 @@ vvp_wire_vec4::vvp_wire_vec4(unsigned wid, vvp_bit4_t init)
{
}
vvp_net_fil_t::prop_t vvp_wire_vec4::filter_vec4(const vvp_vector4_t&bit, vvp_vector4_t&rep)
vvp_net_fil_t::prop_t vvp_wire_vec4::filter_vec4(const vvp_vector4_t&bit, vvp_vector4_t&rep,
unsigned base, unsigned vwid)
{
// Keep track of the value being driven from this net, even if
// it is not ultimately what survives the force filter.
if (base==0 && bit.size()==vwid) {
bits4_ = bit;
return filter_mask_(bit, force4_, rep);
} else {
if (bits4_.size() == 0)
bits4_ = vvp_vector4_t(vwid, BIT4_Z);
assert(bits4_.size() == vwid);
bits4_.set_vec(base, bit);
}
return filter_mask_(bit, force4_, rep, base);
}
vvp_net_fil_t::prop_t vvp_wire_vec4::filter_vec8(const vvp_vector8_t&bit, vvp_vector8_t&rep)
vvp_net_fil_t::prop_t vvp_wire_vec4::filter_vec8(const vvp_vector8_t&bit, vvp_vector8_t&rep, unsigned base, unsigned vwid)
{
bits4_ = reduce4(bit);
return filter_mask_(bit, vvp_vector8_t(force4_,6,6), rep);
return filter_mask_(bit, vvp_vector8_t(force4_,6,6), rep, 0);
}
unsigned vvp_wire_vec4::filter_size() const
@ -716,25 +724,33 @@ vvp_wire_vec8::vvp_wire_vec8(unsigned wid)
{
}
vvp_net_fil_t::prop_t vvp_wire_vec8::filter_vec4(const vvp_vector4_t&bit, vvp_vector4_t&rep)
vvp_net_fil_t::prop_t vvp_wire_vec8::filter_vec4(const vvp_vector4_t&bit, vvp_vector4_t&rep,
unsigned base, unsigned vwid)
{
// QUESTION: Is it really correct to propagate a vec4 if this
// is a vec8 node? In fact, it is really possible for a vec4
// value to get through to a vec8 filter?
vvp_vector8_t rep8;
prop_t rc = filter_vec8(vvp_vector8_t(bit,6,6), rep8);
prop_t rc = filter_vec8(vvp_vector8_t(bit,6,6), rep8, 0, vwid);
if (rc == REPL)
rep = reduce4(rep8);
return rc;
}
vvp_net_fil_t::prop_t vvp_wire_vec8::filter_vec8(const vvp_vector8_t&bit, vvp_vector8_t&rep)
vvp_net_fil_t::prop_t vvp_wire_vec8::filter_vec8(const vvp_vector8_t&bit, vvp_vector8_t&rep, unsigned base, unsigned vwid)
{
// Keep track of the value being driven from this net, even if
// it is not ultimately what survives the force filter.
if (base==0 && bit.size()==vwid) {
bits8_ = bit;
return filter_mask_(bit, force8_, rep);
} else {
if (bits8_.size() == 0)
bits8_ = vvp_vector8_t(vwid);
assert(bits8_.size() == vwid);
bits8_.set_vec(base, bit);
}
return filter_mask_(bit, force8_, rep, base);
}
unsigned vvp_wire_vec8::filter_size() const

View File

@ -293,8 +293,10 @@ class vvp_wire_vec4 : public vvp_wire_base {
// the value that the node is driven to, and applies the firce
// filters. In wires, this also saves the driven value, so
// that when a force is released, we can revert to the driven value.
prop_t filter_vec4(const vvp_vector4_t&bit, vvp_vector4_t&rep);
prop_t filter_vec8(const vvp_vector8_t&val, vvp_vector8_t&rep);
prop_t filter_vec4(const vvp_vector4_t&bit, vvp_vector4_t&rep,
unsigned base, unsigned vwid);
prop_t filter_vec8(const vvp_vector8_t&val, vvp_vector8_t&rep,
unsigned base, unsigned vwid);
// Abstract methods from vvp_vpi_callback
void get_value(struct t_vpi_value*value);
@ -327,8 +329,10 @@ class vvp_wire_vec8 : public vvp_wire_base {
vvp_wire_vec8(unsigned wid);
// The main filter behavior for this class
prop_t filter_vec4(const vvp_vector4_t&bit, vvp_vector4_t&rep);
prop_t filter_vec8(const vvp_vector8_t&val, vvp_vector8_t&rep);
prop_t filter_vec4(const vvp_vector4_t&bit, vvp_vector4_t&rep,
unsigned base, unsigned vwid);
prop_t filter_vec8(const vvp_vector8_t&val, vvp_vector8_t&rep,
unsigned base, unsigned vwid);
// Abstract methods from vvp_vpi_callback
void get_value(struct t_vpi_value*value);