diff --git a/vvp/vthread.cc b/vvp/vthread.cc index 438a1761c..7e1d13698 100644 --- a/vvp/vthread.cc +++ b/vvp/vthread.cc @@ -179,6 +179,19 @@ void vthread_put_real(struct vthread_s*thr, unsigned addr, double val) thr->words[addr].w_real = val; } +template T coerce_to_width(const T&that, unsigned width) +{ + if (that.size() == width) + return that; + + assert(that.size() > width); + T res (width); + for (unsigned idx = 0 ; idx < width ; idx += 1) + res.set_bit(idx, that.value(idx)); + + return res; +} + static unsigned long* vector_to_array(struct vthread_s*thr, unsigned addr, unsigned wid) { @@ -2288,8 +2301,8 @@ bool of_EVCTLS(vthread_t thr, vvp_code_t cp) static void unlink_force(vvp_net_t*net) { - vvp_fun_signal_base*sig - = reinterpret_cast(net->fun); + vvp_filter_wire_base*sig + = reinterpret_cast(net->fun); /* This node must be a signal... */ assert(sig); /* This signal is being forced. */ @@ -2315,8 +2328,8 @@ bool of_FORCE_LINK(vthread_t thr, vvp_code_t cp) vvp_net_t*dst = cp->net; vvp_net_t*src = cp->net2; - vvp_fun_signal_base*sig - = reinterpret_cast(dst->fun); + vvp_filter_wire_base*sig + = reinterpret_cast(dst->fun); assert(sig); /* Detect the special case that we are already forced the @@ -2359,9 +2372,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); - /* Set the value into port 2 of the destination. */ - vvp_net_ptr_t ptr (net, 2); - vvp_send_vec4(ptr, value, 0); + /* Send the force value to the signal on the node. */ + vvp_fun_signal4*sig = reinterpret_cast (net->fun); + assert(sig); + + if (value.size() != sig->size()) + value = coerce_to_width(value, sig->size()); + sig->force_vec4(value, vvp_vector2_t(vvp_vector2_t::FILL1, sig->size())); return true; } @@ -2371,9 +2388,10 @@ bool of_FORCE_WR(vthread_t thr, vvp_code_t cp) vvp_net_t*net = cp->net; double value = thr->words[cp->bit_idx[0]].w_real; - /* Set the value into port 2 of the destination. */ - vvp_net_ptr_t ptr (net, 2); - vvp_send_real(ptr, value, 0); + vvp_fun_signal_real*sig = reinterpret_cast(net->fun); + assert(sig); + + sig->force_real(value, vvp_vector2_t(vvp_vector2_t::FILL1, 1)); return true; } diff --git a/vvp/vvp_net_sig.cc b/vvp/vvp_net_sig.cc index 9749d20af..f484b5671 100644 --- a/vvp/vvp_net_sig.cc +++ b/vvp/vvp_net_sig.cc @@ -28,19 +28,6 @@ # include #endif -template T coerce_to_width(const T&that, unsigned width) -{ - if (that.size() == width) - return that; - - assert(that.size() > width); - T res (width); - for (unsigned idx = 0 ; idx < width ; idx += 1) - res.set_bit(idx, that.value(idx)); - - return res; -} - vvp_filter_wire_base::vvp_filter_wire_base() { force_propagate_ = false; @@ -285,19 +272,6 @@ void vvp_fun_signal4_sa::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit, calculate_output_(ptr); break; - case 2: // Force value - { vvp_vector4_t tmp (bit); - - // Force from a node may not have been sized completely - // by the source, so coerce the size here. - if (tmp.size() != size()) - tmp = coerce_to_width(tmp, size()); - - force_vec4(tmp, vvp_vector2_t(vvp_vector2_t::FILL1,tmp.size())); - calculate_output_(ptr); - } - break; - default: fprintf(stderr, "Unsupported port type %d.\n", ptr.port()); assert(0); @@ -354,18 +328,6 @@ void vvp_fun_signal4_sa::recv_vec4_pv(vvp_net_ptr_t ptr, const vvp_vector4_t&bit calculate_output_(ptr); break; - case 2: // Force value - { vvp_vector2_t mask (vvp_vector2_t::FILL0, vwid); - vvp_vector4_t vec (vwid, BIT4_Z); - for (unsigned idx = 0 ; idx < wid ; idx += 1) { - mask.set_bit(base+idx, 1); - vec.set_bit(base+idx, bit.value(idx)); - } - force_vec4(vec, mask); - calculate_output_(ptr); - break; - } - default: fprintf(stderr, "Unsupported port type %d.\n", ptr.port()); assert(0); @@ -593,19 +555,6 @@ void vvp_fun_signal8::recv_vec8(vvp_net_ptr_t ptr, const vvp_vector8_t&bit) assert(0); break; - case 2: // Force value - { vvp_vector8_t tmp(bit); - - // Force from a node may not have been sized completely - // by the source, so coerce the size here. - if (tmp.size() != size()) - tmp = coerce_to_width(tmp, size()); - - force_vec8(tmp, vvp_vector2_t(vvp_vector2_t::FILL1,tmp.size())); - calculate_output_(ptr); - } - break; - default: fprintf(stderr, "Unsupported port type %d.\n", ptr.port()); assert(0); @@ -762,11 +711,6 @@ void vvp_fun_signal_real_sa::recv_real(vvp_net_ptr_t ptr, double bit, ptr.ptr()->send_real(bit, 0); break; - case 2: // Force value - force_real(bit, vvp_vector2_t(vvp_vector2_t::FILL1, 1)); - ptr.ptr()->send_real(bit, 0); - break; - default: fprintf(stderr, "Unsupported port type %d.\n", ptr.port()); assert(0); diff --git a/vvp/vvp_net_sig.h b/vvp/vvp_net_sig.h index 82d1f998f..f7a964b2f 100644 --- a/vvp/vvp_net_sig.h +++ b/vvp/vvp_net_sig.h @@ -151,6 +151,11 @@ class vvp_filter_wire_base : public vvp_net_fil_t, public vvp_vpi_callback { virtual void release_pv(vvp_net_ptr_t ptr, bool net, unsigned base, unsigned wid) =0; + /* The %force/link instruction needs a place to write the + source node of the force, so that subsequent %force and + %release instructions can undo the link as needed. */ + struct vvp_net_t*force_link; + protected: // Set bits of the filter force mask void force_mask(vvp_vector2_t mask); @@ -200,10 +205,9 @@ class vvp_fun_signal_base : public vvp_net_fun_t, public vvp_filter_wire_base { public: - /* The %force/link instruction needs a place to write the - source node of the force, so that subsequent %force and - %release instructions can undo the link as needed. */ - struct vvp_net_t*force_link; + /* The %cassign/link instruction needs a place to write the + source node of the force, so that subsequent %cassign and + %deassign instructions can undo the link as needed. */ struct vvp_net_t*cassign_link; protected: