diff --git a/vvp/vvp_net.cc b/vvp/vvp_net.cc index a0d3b6ca2..f779ecddd 100644 --- a/vvp/vvp_net.cc +++ b/vvp/vvp_net.cc @@ -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); diff --git a/vvp/vvp_net.h b/vvp/vvp_net.h index 5d8ef49ac..8cc43d931 100644 --- a/vvp/vvp_net.h +++ b/vvp/vvp_net.h @@ -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 prop_t filter_mask_(const T&val, const T&force, T&rep); + template 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 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: diff --git a/vvp/vvp_net_sig.cc b/vvp/vvp_net_sig.cc index 63de72f89..b2dd3543a 100644 --- a/vvp/vvp_net_sig.cc +++ b/vvp/vvp_net_sig.cc @@ -30,18 +30,18 @@ # include -template vvp_net_fil_t::prop_t vvp_net_fil_t::filter_mask_(const T&val, const T&force, T&filter) +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()) { 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 diff --git a/vvp/vvp_net_sig.h b/vvp/vvp_net_sig.h index ab3b49af6..3e0dbed07 100644 --- a/vvp/vvp_net_sig.h +++ b/vvp/vvp_net_sig.h @@ -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);