From 72ab7b6515f16a071dee49b9989d37b77c6504e1 Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Sat, 12 Sep 2009 18:46:48 -0700 Subject: [PATCH] Handle initialization propagation of wires. The first input through a net needs to be propagated, since this is used as an initialization for the net. This patch also cleans up wires to not need the width_ member, instead inferring the width from the saved bit value. --- vvp/dff.cc | 12 ++++++++++- vvp/vvp_net_sig.cc | 52 ++++++++++++++++++++++++++++++++++------------ vvp/vvp_net_sig.h | 6 +++--- vvp/words.cc | 2 +- 4 files changed, 54 insertions(+), 18 deletions(-) diff --git a/vvp/dff.cc b/vvp/dff.cc index 264b2aa8d..8c1cf1856 100644 --- a/vvp/dff.cc +++ b/vvp/dff.cc @@ -24,6 +24,7 @@ # include # include # include +# include #ifdef HAVE_MALLOC_H # include #endif @@ -67,7 +68,16 @@ void vvp_dff::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit, break; case 3: // Asynch-D - d_ = bit; + // FIXME! The code generator is writing an input C4 + // no matter what the intent of this device. This is + // almost certainly NOT correct, nor do we want to + // propagate that. But that needs to be fixed later. + if (bit.size() == 1 && bit.value(0)==BIT4_Z) + break; + if (d_.size() > bit.size()) + d_ .copy_bits(bit); + else + d_ = bit; port.ptr()->send_vec4(d_, 0); break; } diff --git a/vvp/vvp_net_sig.cc b/vvp/vvp_net_sig.cc index 8b2e32099..8006f166d 100644 --- a/vvp/vvp_net_sig.cc +++ b/vvp/vvp_net_sig.cc @@ -608,35 +608,57 @@ vvp_wire_base::~vvp_wire_base() } vvp_wire_vec4::vvp_wire_vec4(unsigned wid, vvp_bit4_t init) -: width_(wid), bits4_(wid, init) +: bits4_(wid, init) { + needs_init_ = true; } vvp_net_fil_t::prop_t vvp_wire_vec4::filter_vec4(const vvp_vector4_t&bit, vvp_vector4_t&rep, unsigned base, unsigned vwid) { + // Special case! the input bit is 0 wid. Interpret this as a + // vector of BIT4_X to match the width of the bits4_ vector. + // FIXME! This is a hack to work around some buggy gate + // implementations! This should be removed! + if (base==0 && vwid==0) { + vvp_vector4_t tmp (bits4_.size(), BIT4_X); + if (bits4_ .eeq(tmp) && !needs_init_) return STOP; + bits4_ = tmp; + needs_init_ = false; + return filter_mask_(tmp, force4_, rep, 0); + } + + if (vwid != bits4_.size()) { + cerr << "Internal error: Input vector expected width=" + << bits4_.size() << ", got " + << "bit=" << bit << ", base=" << base << ", vwid=" << vwid + << endl; + } + assert(bits4_.size() == 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) { + if (bits4_ .eeq( bit ) && !needs_init_) return STOP; bits4_ = bit; } else { - if (bits4_.size() == 0) - bits4_ = vvp_vector4_t(vwid, BIT4_Z); - assert(bits4_.size() == vwid); bits4_.set_vec(base, bit); } + + needs_init_ = false; 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, unsigned base, unsigned vwid) { + assert(bits4_.size() == bit.size()); bits4_ = reduce4(bit); return filter_mask_(bit, vvp_vector8_t(force4_,6,6), rep, 0); } unsigned vvp_wire_vec4::filter_size() const { - return width_; + return bits4_.size(); } void vvp_wire_vec4::force_fil_vec4(const vvp_vector4_t&val, vvp_vector2_t mask) @@ -669,7 +691,7 @@ void vvp_wire_vec4::force_fil_real(double val, vvp_vector2_t mask) void vvp_wire_vec4::release(vvp_net_ptr_t ptr, bool net_flag) { // Wires revert to their unforced value after release. - vvp_vector2_t mask (vvp_vector2_t::FILL1, width_); + vvp_vector2_t mask (vvp_vector2_t::FILL1, bits4_.size()); release_mask(mask); if (net_flag) { ptr.ptr()->send_vec4(bits4_, 0); @@ -701,7 +723,7 @@ void vvp_wire_vec4::release_pv(vvp_net_ptr_t ptr, unsigned base, unsigned wid, b unsigned vvp_wire_vec4::value_size() const { - return width_; + return bits4_.size(); } vvp_bit4_t vvp_wire_vec4::filtered_value_(unsigned idx) const @@ -731,8 +753,9 @@ vvp_vector4_t vvp_wire_vec4::vec4_value() const } vvp_wire_vec8::vvp_wire_vec8(unsigned wid) -: width_(wid) +: bits8_(wid) { + needs_init_ = true; } vvp_net_fil_t::prop_t vvp_wire_vec8::filter_vec4(const vvp_vector4_t&bit, vvp_vector4_t&rep, @@ -746,11 +769,13 @@ vvp_net_fil_t::prop_t vvp_wire_vec8::filter_vec4(const vvp_vector4_t&bit, vvp_ve if (rc == REPL) rep = reduce4(rep8); + needs_init_ = false; return rc; } vvp_net_fil_t::prop_t vvp_wire_vec8::filter_vec8(const vvp_vector8_t&bit, vvp_vector8_t&rep, unsigned base, unsigned vwid) { + assert(vwid == bits8_.size()); // 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) { @@ -761,12 +786,13 @@ vvp_net_fil_t::prop_t vvp_wire_vec8::filter_vec8(const vvp_vector8_t&bit, vvp_ve assert(bits8_.size() == vwid); bits8_.set_vec(base, bit); } + needs_init_ = false; return filter_mask_(bit, force8_, rep, base); } unsigned vvp_wire_vec8::filter_size() const { - return width_; + return bits8_.size(); } void vvp_wire_vec8::force_fil_vec4(const vvp_vector4_t&val, vvp_vector2_t mask) @@ -799,7 +825,7 @@ void vvp_wire_vec8::force_fil_real(double val, vvp_vector2_t mask) void vvp_wire_vec8::release(vvp_net_ptr_t ptr, bool net_flag) { // Wires revert to their unforced value after release. - vvp_vector2_t mask (vvp_vector2_t::FILL1, width_); + vvp_vector2_t mask (vvp_vector2_t::FILL1, bits8_.size()); release_mask(mask); if (net_flag) ptr.ptr()->send_vec8(bits8_); @@ -809,9 +835,9 @@ void vvp_wire_vec8::release(vvp_net_ptr_t ptr, bool net_flag) void vvp_wire_vec8::release_pv(vvp_net_ptr_t ptr, unsigned base, unsigned wid, bool net_flag) { - assert(width_ >= base + wid); + assert(bits8_.size() >= base + wid); - vvp_vector2_t mask (vvp_vector2_t::FILL0, width_); + vvp_vector2_t mask (vvp_vector2_t::FILL0, bits8_.size()); for (unsigned idx = 0 ; idx < wid ; idx += 1) mask.set_bit(base+idx, 1); @@ -829,7 +855,7 @@ void vvp_wire_vec8::release_pv(vvp_net_ptr_t ptr, unsigned base, unsigned wid, b unsigned vvp_wire_vec8::value_size() const { - return width_; + return bits8_.size(); } vvp_scalar_t vvp_wire_vec8::filtered_value_(unsigned idx) const diff --git a/vvp/vvp_net_sig.h b/vvp/vvp_net_sig.h index 25e2bd1c7..473a5081e 100644 --- a/vvp/vvp_net_sig.h +++ b/vvp/vvp_net_sig.h @@ -286,7 +286,7 @@ class vvp_wire_base : public vvp_net_fil_t, public vvp_signal_value { class vvp_wire_vec4 : public vvp_wire_base { public: - vvp_wire_vec4(unsigned wid, vvp_bit4_t init=BIT4_X); + vvp_wire_vec4(unsigned wid, vvp_bit4_t init); // The main filter behavior for this class. These methods take // the value that the node is driven to, and applies the firce @@ -317,7 +317,7 @@ class vvp_wire_vec4 : public vvp_wire_base { vvp_bit4_t filtered_value_(unsigned idx) const; private: - unsigned width_; + bool needs_init_; vvp_vector4_t bits4_; // The tracked driven value vvp_vector4_t force4_; // the value being forced }; @@ -355,7 +355,7 @@ class vvp_wire_vec8 : public vvp_wire_base { vvp_scalar_t filtered_value_(unsigned idx) const; private: - unsigned width_; + bool needs_init_; vvp_vector8_t bits8_; vvp_vector8_t force8_; // the value being forced }; diff --git a/vvp/words.cc b/vvp/words.cc index c51a4d4df..3f9779b73 100644 --- a/vvp/words.cc +++ b/vvp/words.cc @@ -89,7 +89,7 @@ static void __compile_var(char*label, char*name, unsigned wid = ((msb > lsb)? msb-lsb : lsb-msb) + 1; vvp_fun_signal_vec*vsig; - vvp_wire_vec4*vfil = new vvp_wire_vec4(wid); + vvp_wire_vec4*vfil = new vvp_wire_vec4(wid, BIT4_X); if (vpip_peek_current_scope()->is_automatic) { vsig = new vvp_fun_signal4_aa(wid); } else {