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:
parent
9c516a9d53
commit
a58c02899b
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
vvp_send_vec4_pv(out_, val, base, wid, vwid, 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:
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
bits4_ = bit;
|
||||
return filter_mask_(bit, force4_, rep);
|
||||
if (base==0 && bit.size()==vwid) {
|
||||
bits4_ = bit;
|
||||
} 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.
|
||||
bits8_ = bit;
|
||||
return filter_mask_(bit, force8_, rep);
|
||||
if (base==0 && bit.size()==vwid) {
|
||||
bits8_ = bit;
|
||||
} 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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Reference in New Issue