diff --git a/vvp/vthread.cc b/vvp/vthread.cc index 69e705d03..2496f183f 100644 --- a/vvp/vthread.cc +++ b/vvp/vthread.cc @@ -2338,14 +2338,13 @@ bool of_FORCE_V(vthread_t thr, vvp_code_t cp) /* Collect the thread bits into a vector4 item. */ vvp_vector4_t value = vthread_bits_to_vector(thr, base, wid); - /* Send the force value to the signal on the node. */ - vvp_fun_signal4*sig = reinterpret_cast (net->fun); - assert(sig); + /* Send the force value to the filter on the node. */ - if (value.size() != sig->size()) - value = coerce_to_width(value, sig->size()); + assert(net->fil); + if (value.size() != net->fil->size()) + value = coerce_to_width(value, net->fil->size()); - net->force_vec4(value, vvp_vector2_t(vvp_vector2_t::FILL1, sig->size())); + net->force_vec4(value, vvp_vector2_t(vvp_vector2_t::FILL1, net->fil->size())); return true; } @@ -2367,6 +2366,8 @@ bool of_FORCE_X0(vthread_t thr, vvp_code_t cp) unsigned base = cp->bit_idx[0]; unsigned wid = cp->bit_idx[1]; + assert(net->fil); + // Implicitly, we get the base into the target vector from the // X0 register. long index = thr->words[0].w_int; @@ -2379,49 +2380,25 @@ bool of_FORCE_X0(vthread_t thr, vvp_code_t cp) index = 0; } - if (vvp_fun_signal4*sig = dynamic_cast (net->fun)) { + unsigned use_size = net->fil->size(); - if (index >= (long)sig->size()) - return true; - - if (index+wid > sig->size()) - wid = sig->size() - index; - - vvp_vector2_t mask(vvp_vector2_t::FILL0, sig->size()); - for (unsigned idx = 0 ; idx < wid ; idx += 1) - mask.set_bit(index+idx, 1); - - vvp_vector4_t vector = vthread_bits_to_vector(thr, base, wid); - vvp_vector4_t value(sig->size(), BIT4_Z); - value.set_vec(index, vector); - - net->force_vec4(value, mask); + if (index >= (long)use_size) return true; - } - if (vvp_fun_signal8*sig = dynamic_cast (net->fun)) { + if (index+wid > use_size) + wid = use_size - index; - if (index >= (long)sig->size()) - return true; + vvp_vector2_t mask(vvp_vector2_t::FILL0, use_size); + for (unsigned idx = 0 ; idx < wid ; idx += 1) + mask.set_bit(index+idx, 1); - if (index+wid > sig->size()) - wid = sig->size() - index; + vvp_vector4_t vector = vthread_bits_to_vector(thr, base, wid); + vvp_vector4_t value(use_size, BIT4_Z); + value.set_vec(index, vector); - vvp_vector2_t mask(vvp_vector2_t::FILL0, sig->size()); - for (unsigned idx = 0 ; idx < wid ; idx += 1) - mask.set_bit(index+idx, 1); + net->force_vec4(value, mask); - vvp_vector4_t vec4 = vthread_bits_to_vector(thr, base, wid); - vvp_vector4_t val4(sig->size(), BIT4_Z); - val4.set_vec(index, vec4); - - net->force_vec8(vvp_vector8_t(val4,6,6), mask); - - return true; - } - - assert(0); return true; } @@ -3925,20 +3902,18 @@ bool of_POW_WR(vthread_t thr, vvp_code_t cp) * the release/reg command instead. These are very similar to the * %deassign instruction. */ -bool of_RELEASE_NET(vthread_t thr, vvp_code_t cp) +static bool do_release_vec(vthread_t thr, vvp_code_t cp, bool net_flag) { vvp_net_t*net = cp->net; unsigned base = cp->bit_idx[0]; unsigned width = cp->bit_idx[1]; - vvp_fun_signal_vec*sig = reinterpret_cast(net->fun); - assert(sig); assert(net->fil); - if (base >= sig->size()) return true; - if (base+width > sig->size()) width = sig->size() - base; + if (base >= net->fil->size()) return true; + if (base+width > net->fil->size()) width = net->fil->size() - base; - bool full_sig = base == 0 && width == sig->size(); + bool full_sig = base == 0 && width == net->fil->size(); // XXXX Can't really do this if this is a partial release? net->fil->force_unlink(); @@ -3946,43 +3921,23 @@ bool of_RELEASE_NET(vthread_t thr, vvp_code_t cp) /* Do we release all or part of the net? */ vvp_net_ptr_t ptr (net, 0); if (full_sig) { - net->fil->release(ptr, true); + net->fil->release(ptr, net_flag); } else { - net->fil->release_pv(ptr, true, base, width); + net->fil->release_pv(ptr, net_flag, base, width); } return true; } +bool of_RELEASE_NET(vthread_t thr, vvp_code_t cp) +{ + return do_release_vec(thr, cp, true); +} + bool of_RELEASE_REG(vthread_t thr, vvp_code_t cp) { - vvp_net_t*net = cp->net; - unsigned base = cp->bit_idx[0]; - unsigned width = cp->bit_idx[1]; - - vvp_fun_signal_vec*sig = reinterpret_cast(net->fun); - assert(sig); - assert(net->fil); - - if (base >= sig->size()) return true; - if (base+width > sig->size()) width = sig->size() - base; - - bool full_sig = base == 0 && width == sig->size(); - - // XXXX Can't really do this if this is a partial release? - net->fil->force_unlink(); - - // Send a command to this signal to unforce itself. - /* Do we release all or part of the net? */ - vvp_net_ptr_t ptr (net, 0); - if (full_sig) { - net->fil->release(ptr, false); - } else { - net->fil->release_pv(ptr, false, base, width); - } - - return true; + return do_release_vec(thr, cp, false); } /* The type is 1 for registers and 0 for everything else. */ diff --git a/vvp/vvp_net.h b/vvp/vvp_net.h index 500b4ef66..e5acc925f 100644 --- a/vvp/vvp_net.h +++ b/vvp/vvp_net.h @@ -1129,6 +1129,7 @@ class vvp_net_fil_t : public vvp_vpi_callback { void force_link(vvp_net_t*dst, vvp_net_t*src); void force_unlink(void); + virtual unsigned size() const =0; public: // Suport for force methods diff --git a/vvp/vvp_net_sig.cc b/vvp/vvp_net_sig.cc index c5314e160..758de51db 100644 --- a/vvp/vvp_net_sig.cc +++ b/vvp/vvp_net_sig.cc @@ -80,6 +80,11 @@ bool vvp_fun_signal_real::filter_real(double&val) return filter_mask_(val); } +unsigned vvp_fun_signal_real::size() const +{ + return 1; +} + void vvp_fun_signal4::force_fil_vec4(const vvp_vector4_t&val, vvp_vector2_t mask) { force_mask(mask); @@ -821,10 +826,9 @@ void vvp_fun_force::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit, vvp_net_t*net = ptr.ptr(); vvp_net_t*dst = net->port[3].ptr(); - vvp_fun_signal4*sig = dynamic_cast (dst->fil); - assert(sig); + assert(dst->fil); - dst->force_vec4(coerce_to_width(bit, sig->size()), vvp_vector2_t(vvp_vector2_t::FILL1, sig->size())); + dst->force_vec4(coerce_to_width(bit, dst->fil->size()), vvp_vector2_t(vvp_vector2_t::FILL1, dst->fil->size())); } void vvp_fun_force::recv_real(vvp_net_ptr_t ptr, double bit, vvp_context_t) diff --git a/vvp/vvp_net_sig.h b/vvp/vvp_net_sig.h index 3c7a1455e..acaf6d2eb 100644 --- a/vvp/vvp_net_sig.h +++ b/vvp/vvp_net_sig.h @@ -290,6 +290,8 @@ class vvp_fun_signal_real : public vvp_fun_signal_base { // Test the value against the filter. double filtered_real(double val) const; + virtual unsigned size() const; + private: double force_real_; };