diff --git a/vvp/vpi_callback.cc b/vvp/vpi_callback.cc index 71ddcb924..153bc54e8 100644 --- a/vvp/vpi_callback.cc +++ b/vvp/vpi_callback.cc @@ -761,7 +761,7 @@ void vvp_wire_vec4::get_value(struct t_vpi_value*value) void vvp_wire_vec8::get_value(struct t_vpi_value*value) { - assert(0); + get_signal_value(value); } void vvp_wire_real::get_value(struct t_vpi_value*value) diff --git a/vvp/vvp_net.cc b/vvp/vvp_net.cc index 99565d8e0..f5d11d7ee 100644 --- a/vvp/vvp_net.cc +++ b/vvp/vvp_net.cc @@ -206,14 +206,14 @@ vvp_net_fil_t::~vvp_net_fil_t() assert(force_link_ == 0); } -const vvp_vector4_t* vvp_net_fil_t::filter_vec4(const vvp_vector4_t&val) +vvp_net_fil_t::prop_t vvp_net_fil_t::filter_vec4(const vvp_vector4_t&val, vvp_vector4_t&) { - return &val; + return PROP; } -const vvp_vector8_t* vvp_net_fil_t::filter_vec8(const vvp_vector8_t&val) +vvp_net_fil_t::prop_t vvp_net_fil_t::filter_vec8(const vvp_vector8_t&val, vvp_vector8_t&) { - return &val; + return PROP; } bool vvp_net_fil_t::filter_real(double&) diff --git a/vvp/vvp_net.h b/vvp/vvp_net.h index b42eafb49..964ce5a4e 100644 --- a/vvp/vvp_net.h +++ b/vvp/vvp_net.h @@ -1119,14 +1119,17 @@ class vvp_net_fil_t : public vvp_vpi_callback { virtual ~vvp_net_fil_t(); public: + enum prop_t { STOP=0, PROP, REPL }; + // Return a non-empty vector if the filter allows an // output. The output result may be different from the // input. If the output is nil, then suppress propagation. - 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. + // 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 bool filter_real(double&val); virtual bool filter_long(long&val); @@ -1162,7 +1165,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 const T*filter_mask_(const T&val, const T&force, T&buf); + template prop_t filter_mask_(const T&val, const T&force, T&rep); // This template method is a scalar value of the above. It // leaves the val, or it replaces it iwth a forced value. // (Not really implemented, yet.) @@ -1440,11 +1443,22 @@ 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) { - const vvp_vector4_t*val_out = fil? fil->filter_vec4(val) : &val; - if (val_out == 0) + if (fil == 0) { + vvp_send_vec4(out_, val, context); return; + } - vvp_send_vec4(out_, *val_out, context); + vvp_vector4_t rep; + switch (fil->filter_vec4(val, rep)) { + case vvp_net_fil_t::STOP: + break; + case vvp_net_fil_t::PROP: + vvp_send_vec4(out_, val, context); + break; + case vvp_net_fil_t::REPL: + vvp_send_vec4(out_, rep, context); + break; + } } inline void vvp_net_t::send_vec4_pv(const vvp_vector4_t&val, @@ -1456,11 +1470,22 @@ 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) { - const vvp_vector8_t*val_out = fil? fil->filter_vec8(val) : &val; - if (val_out == 0) + if (fil == 0) { + vvp_send_vec8(out_, val); return; + } - vvp_send_vec8(out_, *val_out); + vvp_vector8_t rep; + switch (fil->filter_vec8(val, rep)) { + case vvp_net_fil_t::STOP: + break; + case vvp_net_fil_t::PROP: + vvp_send_vec8(out_, val); + break; + case vvp_net_fil_t::REPL: + vvp_send_vec8(out_, rep); + break; + } } inline void vvp_net_t::send_real(double val, vvp_context_t context) diff --git a/vvp/vvp_net_sig.cc b/vvp/vvp_net_sig.cc index b46f26c32..745185038 100644 --- a/vvp/vvp_net_sig.cc +++ b/vvp/vvp_net_sig.cc @@ -30,7 +30,7 @@ # include -template const 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) { if (!test_force_mask_is_zero()) { bool propagate_flag = force_propagate_; @@ -48,14 +48,14 @@ template const T*vvp_net_fil_t::filter_mask_(const T&val, const T&forc if (propagate_flag) { run_vpi_callbacks(); - return &filter; + return REPL; } else { - return 0; + return STOP; } } else { run_vpi_callbacks(); - return &val; + return PROP; } } @@ -75,24 +75,6 @@ double vvp_signal_value::real_value() const return 0; } -#if 0 -const vvp_vector4_t* vvp_fun_signal4::filter_vec4(const vvp_vector4_t&val) -{ - return filter_mask_(val, force4_, filter4_); -} -#endif -#if 0 -const vvp_vector8_t* vvp_fun_signal8::filter_vec8(const vvp_vector8_t&val) -{ - return filter_mask_(val, force8_, filter8_); -} -#endif -#if 0 -bool vvp_fun_signal_real::filter_real(double&val) -{ - return filter_mask_(val); -} -#endif unsigned vvp_fun_signal_real::filter_size() const { return size(); @@ -876,19 +858,18 @@ vvp_wire_vec4::vvp_wire_vec4(unsigned wid, vvp_bit4_t init) { } -const vvp_vector4_t* vvp_wire_vec4::filter_vec4(const vvp_vector4_t&bit) +vvp_net_fil_t::prop_t vvp_wire_vec4::filter_vec4(const vvp_vector4_t&bit, vvp_vector4_t&rep) { // Keep track of the value being driven from this net, even if // it is not ultimately what survives the force filter. bits4_ = bit; - const vvp_vector4_t*tmp = filter_mask_(bit, force4_, filter4_); - return tmp; + return filter_mask_(bit, force4_, rep); } -const vvp_vector8_t* vvp_wire_vec4::filter_vec8(const vvp_vector8_t&bit) +vvp_net_fil_t::prop_t vvp_wire_vec4::filter_vec8(const vvp_vector8_t&bit, vvp_vector8_t&) { assert(0); - return 0; + return PROP; } unsigned vvp_wire_vec4::filter_size() const @@ -951,17 +932,17 @@ unsigned vvp_wire_vec4::value_size() const return width_; } -vvp_bit4_t vvp_wire_vec4::filtered_value_(const vvp_vector4_t&val, unsigned idx) const +vvp_bit4_t vvp_wire_vec4::filtered_value_(unsigned idx) const { if (test_force_mask(idx)) return force4_.value(idx); else - return val.value(idx); + return bits4_.value(idx); } vvp_bit4_t vvp_wire_vec4::value(unsigned idx) const { - return filtered_value_(bits4_, idx); + return filtered_value_(idx); } vvp_scalar_t vvp_wire_vec4::scalar_value(unsigned idx) const @@ -973,7 +954,7 @@ vvp_vector4_t vvp_wire_vec4::vec4_value() const { vvp_vector4_t tmp = bits4_; for (unsigned idx = 0 ; idx < bits4_.size() ; idx += 1) - tmp.set_bit(idx, filtered_value_(bits4_, idx)); + tmp.set_bit(idx, filtered_value_(idx)); return tmp; } @@ -982,19 +963,25 @@ vvp_wire_vec8::vvp_wire_vec8(unsigned wid) { } -const vvp_vector4_t* vvp_wire_vec8::filter_vec4(const vvp_vector4_t&bit) +vvp_net_fil_t::prop_t vvp_wire_vec8::filter_vec4(const vvp_vector4_t&bit, vvp_vector4_t&rep) { - assert(0); - return 0; + // 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); + if (rc == REPL) + rep = reduce4(rep8); + + return rc; } -const vvp_vector8_t* vvp_wire_vec8::filter_vec8(const vvp_vector8_t&bit) +vvp_net_fil_t::prop_t vvp_wire_vec8::filter_vec8(const vvp_vector8_t&bit, vvp_vector8_t&rep) { // Keep track of the value being driven from this net, even if // it is not ultimately what survives the force filter. bits8_ = bit; - const vvp_vector8_t*tmp = filter_mask_(bit, force8_, filter8_); - return tmp; + return filter_mask_(bit, force8_, rep); } unsigned vvp_wire_vec8::filter_size() const @@ -1046,19 +1033,35 @@ unsigned vvp_wire_vec8::value_size() const return width_; } +vvp_scalar_t vvp_wire_vec8::filtered_value_(unsigned idx) const +{ + if (test_force_mask(idx)) + return force8_.value(idx); + else + return bits8_.value(idx); +} + vvp_bit4_t vvp_wire_vec8::value(unsigned idx) const { - assert(0); + return filtered_value_(idx).value(); } vvp_scalar_t vvp_wire_vec8::scalar_value(unsigned idx) const { - assert(0); + return filtered_value_(idx); +} + +vvp_vector8_t vvp_wire_vec8::vec8_value() const +{ + vvp_vector8_t tmp = bits8_; + for (unsigned idx = 0 ; idx < bits8_.size() ; idx += 1) + tmp.set_bit(idx, filtered_value_(idx)); + return tmp; } vvp_vector4_t vvp_wire_vec8::vec4_value() const { - assert(0); + return reduce4(vec8_value()); } vvp_wire_real::vvp_wire_real() diff --git a/vvp/vvp_net_sig.h b/vvp/vvp_net_sig.h index 64662edfa..93d83aa20 100644 --- a/vvp/vvp_net_sig.h +++ b/vvp/vvp_net_sig.h @@ -127,7 +127,6 @@ class vvp_fun_signal4 : public vvp_fun_signal_vec { void force_fil_vec4(const vvp_vector4_t&val, vvp_vector2_t mask); void force_fil_vec8(const vvp_vector8_t&val, vvp_vector2_t mask); void force_fil_real(double val, vvp_vector2_t mask); - const vvp_vector4_t* filter_vec4(const vvp_vector4_t&val); // Test the value against the filter. vvp_bit4_t filtered_value(const vvp_vector4_t&val, unsigned idx) const; @@ -246,7 +245,6 @@ class vvp_fun_signal8 : public vvp_fun_signal_vec { void force_fil_vec4(const vvp_vector4_t&val, vvp_vector2_t mask); void force_fil_vec8(const vvp_vector8_t&val, vvp_vector2_t mask); void force_fil_real(double val, vvp_vector2_t mask); - const vvp_vector8_t* filter_vec8(const vvp_vector8_t&val); // Test the value against the filter. vvp_scalar_t filtered_value(const vvp_vector8_t&val, unsigned idx) const; const vvp_vector8_t& filtered_vec8(const vvp_vector8_t&val) const; @@ -274,7 +272,6 @@ class vvp_fun_signal_real : public vvp_fun_signal_base { void force_fil_vec8(const vvp_vector8_t&val, vvp_vector2_t mask); void force_fil_real(double val, vvp_vector2_t mask); - bool filter_real(double&val); // Test the value against the filter. double filtered_real(double val) const; @@ -361,8 +358,8 @@ 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. - const vvp_vector4_t* filter_vec4(const vvp_vector4_t&bit); - const vvp_vector8_t* filter_vec8(const vvp_vector8_t&val); + 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); // Abstract methods from vvp_vpi_callback void get_value(struct t_vpi_value*value); @@ -381,13 +378,12 @@ class vvp_wire_vec4 : public vvp_wire_base { vvp_vector4_t vec4_value() const; private: - vvp_bit4_t filtered_value_(const vvp_vector4_t&val, unsigned idx) const; + vvp_bit4_t filtered_value_(unsigned idx) const; private: unsigned width_; vvp_vector4_t bits4_; // The tracked driven value vvp_vector4_t force4_; // the value being forced - vvp_vector4_t filter4_; // scratch space for filter_mask_ function. }; class vvp_wire_vec8 : public vvp_wire_base { @@ -396,8 +392,8 @@ class vvp_wire_vec8 : public vvp_wire_base { vvp_wire_vec8(unsigned wid); // The main filter behavior for this class - const vvp_vector4_t* filter_vec4(const vvp_vector4_t&bit); - const vvp_vector8_t* filter_vec8(const vvp_vector8_t&val); + 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); // Abstract methods from vvp_vpi_callback void get_value(struct t_vpi_value*value); @@ -414,12 +410,16 @@ class vvp_wire_vec8 : public vvp_wire_base { vvp_bit4_t value(unsigned idx) const; vvp_scalar_t scalar_value(unsigned idx) const; vvp_vector4_t vec4_value() const; + // This is new to vvp_wire_vec8 + vvp_vector8_t vec8_value() const; + + private: + vvp_scalar_t filtered_value_(unsigned idx) const; private: unsigned width_; vvp_vector8_t bits8_; vvp_vector8_t force8_; // the value being forced - vvp_vector8_t filter8_; // scratch space for filter_mask_ function. }; class vvp_wire_real : public vvp_wire_base {