From 8bbb7ff7dbca8fb62e17116505453df122341ebb Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Mon, 27 Jul 2009 21:42:04 -0700 Subject: [PATCH] Create the vvp_wire_base class to handle wires. Take wires out of the signals/variables and move them into a filter instead. This is a big shift, and finally starts us on the path to divide wires out of signals. --- vvp/array.cc | 4 +- vvp/vpi_callback.cc | 27 +++-- vvp/vpi_signal.cc | 42 ++++---- vvp/vthread.cc | 67 ++++++------ vvp/vvp_net.h | 2 +- vvp/vvp_net_sig.cc | 252 +++++++++++++++++++++++++++++++++++++------- vvp/vvp_net_sig.h | 145 ++++++++++++++++++------- vvp/words.cc | 48 ++++----- 8 files changed, 423 insertions(+), 164 deletions(-) diff --git a/vvp/array.cc b/vvp/array.cc index 839f59eb7..24fe3d21c 100644 --- a/vvp/array.cc +++ b/vvp/array.cc @@ -870,9 +870,9 @@ vvp_vector4_t array_get_word(vvp_array_t arr, unsigned address) vpiHandle word = arr->nets[0]; struct __vpiSignal*vsig = vpip_signal_from_handle(word); assert(vsig); - vvp_fun_signal_vec*sig = dynamic_cast (vsig->node->fun); + vvp_signal_value*sig = dynamic_cast (vsig->node->fun); assert(sig); - return vvp_vector4_t(sig->size(), BIT4_X); + return vvp_vector4_t(sig->value_size(), BIT4_X); } vpiHandle word = arr->nets[address]; diff --git a/vvp/vpi_callback.cc b/vvp/vpi_callback.cc index 829a7a537..eb05dc8e3 100644 --- a/vvp/vpi_callback.cc +++ b/vvp/vpi_callback.cc @@ -157,12 +157,12 @@ static struct __vpiCallback* make_value_change(p_cb_data data) struct __vpiSignal*sig; sig = reinterpret_cast<__vpiSignal*>(data->obj); - vvp_fun_signal_base*sig_fun; - sig_fun = dynamic_cast(sig->node->fun); - assert(sig_fun); + vvp_net_fil_t*sig_fil; + sig_fil = dynamic_cast(sig->node->fil); + assert(sig_fil); /* Attach the __vpiCallback object to the signal. */ - sig_fun->add_vpi_callback(obj); + sig_fil->add_vpi_callback(obj); break; case vpiRealVar: @@ -577,7 +577,7 @@ void vvp_vpi_callback::run_vpi_callbacks() } } -void vvp_fun_signal4::get_value(struct t_vpi_value*vp) +void vvp_signal_value::get_signal_value(struct t_vpi_value*vp) { switch (vp->format) { case vpiScalarVal: @@ -595,7 +595,7 @@ void vvp_fun_signal4::get_value(struct t_vpi_value*vp) case vpiVectorVal: case vpiStringVal: case vpiRealVal: { - unsigned wid = size(); + unsigned wid = value_size(); vvp_vector4_t vec4(wid); for (unsigned idx = 0; idx < wid; idx += 1) { vec4.set_bit(idx, value(idx)); @@ -614,6 +614,11 @@ void vvp_fun_signal4::get_value(struct t_vpi_value*vp) } } +void vvp_fun_signal4::get_value(struct t_vpi_value*vp) +{ + get_signal_value(vp); +} + void vvp_fun_signal8::get_value(struct t_vpi_value*vp) { switch (vp->format) { @@ -688,3 +693,13 @@ void vvp_fun_signal_real::get_value(struct t_vpi_value*vp) vp->format); } } + +void vvp_wire_vec4::get_value(struct t_vpi_value*value) +{ + get_signal_value(value); +} + +void vvp_wire_vec8::get_value(struct t_vpi_value*value) +{ + assert(0); +} diff --git a/vvp/vpi_signal.cc b/vvp/vpi_signal.cc index 4ae87285e..a3c6ca6ff 100644 --- a/vvp/vpi_signal.cc +++ b/vvp/vpi_signal.cc @@ -134,13 +134,13 @@ char *generic_get_str(int code, vpiHandle ref, const char *name, const char *ind * They work with full or partial signals. */ -static void format_vpiBinStrVal(vvp_fun_signal_vec*sig, int base, unsigned wid, +static void format_vpiBinStrVal(vvp_signal_value*sig, int base, unsigned wid, s_vpi_value*vp) { char *rbuf = need_result_buf(wid+1, RBUF_VAL); long offset = wid - 1 + base; long end = base + (signed)wid; - long ssize = (signed)sig->size(); + long ssize = (signed)sig->value_size(); for (long idx = base ; idx < end ; idx += 1) { if (idx < 0 || idx >= ssize) { @@ -154,13 +154,13 @@ static void format_vpiBinStrVal(vvp_fun_signal_vec*sig, int base, unsigned wid, vp->value.str = rbuf; } -static void format_vpiOctStrVal(vvp_fun_signal_vec*sig, int base, unsigned wid, +static void format_vpiOctStrVal(vvp_signal_value*sig, int base, unsigned wid, s_vpi_value*vp) { unsigned dwid = (wid + 2) / 3; char *rbuf = need_result_buf(dwid+1, RBUF_VAL); long end = base + (signed)wid; - long ssize = (signed)sig->size(); + long ssize = (signed)sig->value_size(); unsigned val = 0; rbuf[dwid] = 0; @@ -210,13 +210,13 @@ static void format_vpiOctStrVal(vvp_fun_signal_vec*sig, int base, unsigned wid, vp->value.str = rbuf; } -static void format_vpiHexStrVal(vvp_fun_signal_vec*sig, int base, unsigned wid, +static void format_vpiHexStrVal(vvp_signal_value*sig, int base, unsigned wid, s_vpi_value*vp) { unsigned dwid = (wid + 3) / 4; char *rbuf = need_result_buf(dwid+1, RBUF_VAL); long end = base + (signed)wid; - long ssize = (signed)sig->size(); + long ssize = (signed)sig->value_size(); unsigned val = 0; rbuf[dwid] = 0; @@ -270,12 +270,12 @@ static void format_vpiHexStrVal(vvp_fun_signal_vec*sig, int base, unsigned wid, vp->value.str = rbuf; } -static void format_vpiDecStrVal(vvp_fun_signal_vec*sig, int base, unsigned wid, +static void format_vpiDecStrVal(vvp_signal_value*sig, int base, unsigned wid, int signed_flag, s_vpi_value*vp) { - unsigned hwid = (sig->size()+2) / 3 + 1; + unsigned hwid = (sig->value_size()+2) / 3 + 1; char *rbuf = need_result_buf(hwid, RBUF_VAL); - long ssize = (signed)sig->size(); + long ssize = (signed)sig->value_size(); long end = base + (signed)wid; /* Do we have an end outside of the real signal vector. */ @@ -313,7 +313,7 @@ static void format_vpiDecStrVal(vvp_fun_signal_vec*sig, int base, unsigned wid, vp->value.str = rbuf; } -static void format_vpiIntVal(vvp_fun_signal_vec*sig, int base, unsigned wid, +static void format_vpiIntVal(vvp_signal_value*sig, int base, unsigned wid, int signed_flag, s_vpi_value*vp) { vvp_vector4_t sub = sig->vec4_value().subvalue(base, wid); @@ -322,11 +322,11 @@ static void format_vpiIntVal(vvp_fun_signal_vec*sig, int base, unsigned wid, vp->value.integer = val; } -static void format_vpiRealVal(vvp_fun_signal_vec*sig, int base, unsigned wid, +static void format_vpiRealVal(vvp_signal_value*sig, int base, unsigned wid, int signed_flag, s_vpi_value*vp) { vvp_vector4_t vec4(wid); - long ssize = (signed)sig->size(); + long ssize = (signed)sig->value_size(); long end = base + (signed)wid; if (end > ssize) end = ssize; @@ -338,7 +338,7 @@ static void format_vpiRealVal(vvp_fun_signal_vec*sig, int base, unsigned wid, vector4_to_value(vec4, vp->value.real, signed_flag); } -static void format_vpiStringVal(vvp_fun_signal_vec*sig, int base, unsigned wid, +static void format_vpiStringVal(vvp_signal_value*sig, int base, unsigned wid, s_vpi_value*vp) { /* The result will use a character for each 8 bits of the @@ -351,7 +351,7 @@ static void format_vpiStringVal(vvp_fun_signal_vec*sig, int base, unsigned wid, for (long idx = base+(signed)wid-1; idx >= base; idx -= 1) { tmp <<= 1; - if (idx >=0 && idx < (signed)sig->size() && + if (idx >=0 && idx < (signed)sig->value_size() && sig->value(idx) == BIT4_1) { tmp |= 1; } @@ -371,10 +371,10 @@ static void format_vpiStringVal(vvp_fun_signal_vec*sig, int base, unsigned wid, vp->value.str = rbuf; } -static void format_vpiScalarVal(vvp_fun_signal_vec*sig, int base, +static void format_vpiScalarVal(vvp_signal_value*sig, int base, s_vpi_value*vp) { - if (base >= 0 && base < (signed)sig->size()) { + if (base >= 0 && base < (signed)sig->value_size()) { switch (sig->value(base)) { case BIT4_0: vp->value.scalar = vpi0; @@ -398,7 +398,7 @@ static void format_vpiScalarVal(vvp_fun_signal_vec*sig, int base, } } -static void format_vpiStrengthVal(vvp_fun_signal_vec*sig, int base, +static void format_vpiStrengthVal(vvp_signal_value*sig, int base, unsigned wid, s_vpi_value*vp) { long end = base + (signed)wid; @@ -408,7 +408,7 @@ static void format_vpiStrengthVal(vvp_fun_signal_vec*sig, int base, need_result_buf(wid * sizeof(s_vpi_strengthval), RBUF_VAL); for (long idx = base ; idx < end ; idx += 1) { - if (idx >=0 && idx < (signed)sig->size()) { + if (idx >=0 && idx < (signed)sig->value_size()) { vvp_scalar_t val = sig->scalar_value(idx); /* vvp_scalar_t strengths are 0-7, but the vpi strength @@ -452,7 +452,7 @@ static void format_vpiStrengthVal(vvp_fun_signal_vec*sig, int base, vp->value.strength = op; } -static void format_vpiVectorVal(vvp_fun_signal_vec*sig, int base, unsigned wid, +static void format_vpiVectorVal(vvp_signal_value*sig, int base, unsigned wid, s_vpi_value*vp) { long end = base + (signed)wid; @@ -465,7 +465,7 @@ static void format_vpiVectorVal(vvp_fun_signal_vec*sig, int base, unsigned wid, op->aval = op->bval = 0; for (long idx = base ; idx < end ; idx += 1) { - if (base >= 0 && base < (signed)sig->size()) { + if (base >= 0 && base < (signed)sig->value_size()) { switch (sig->value(idx)) { case BIT4_0: op->aval &= ~(1 << obit); @@ -659,7 +659,7 @@ static void signal_get_value(vpiHandle ref, s_vpi_value*vp) unsigned wid = signal_width(rfp); - vvp_fun_signal_vec*vsig = dynamic_cast(rfp->node->fun); + vvp_signal_value*vsig = dynamic_cast(rfp->node->fil); assert(vsig); switch (vp->format) { diff --git a/vvp/vthread.cc b/vvp/vthread.cc index 2496f183f..31d246539 100644 --- a/vvp/vthread.cc +++ b/vvp/vthread.cc @@ -989,12 +989,12 @@ bool of_ASSIGN_V0X1(vthread_t thr, vvp_code_t cp) unsigned delay = cp->bit_idx[0]; unsigned bit = cp->bit_idx[1]; - vvp_fun_signal_vec*sig - = reinterpret_cast (cp->net->fun); + vvp_signal_value*sig + = reinterpret_cast (cp->net->fun); assert(sig); // We fell off the MSB end. - if (off >= (long)sig->size()) return true; + if (off >= (long)sig->value_size()) return true; else if (off < 0 ) { // We fell off the LSB end. if ((unsigned)-off >= wid ) return true; @@ -1009,7 +1009,7 @@ bool of_ASSIGN_V0X1(vthread_t thr, vvp_code_t cp) vvp_vector4_t value = vthread_bits_to_vector(thr, bit, wid); vvp_net_ptr_t ptr (cp->net, 0); - schedule_assign_vector(ptr, off, sig->size(), value, delay); + schedule_assign_vector(ptr, off, sig->value_size(), value, delay); return true; } @@ -1026,12 +1026,12 @@ bool of_ASSIGN_V0X1D(vthread_t thr, vvp_code_t cp) vvp_time64_t delay = thr->words[cp->bit_idx[0]].w_int; unsigned bit = cp->bit_idx[1]; - vvp_fun_signal_vec*sig - = reinterpret_cast (cp->net->fun); + vvp_signal_value*sig + = reinterpret_cast (cp->net->fun); assert(sig); // We fell off the MSB end. - if (off >= (long)sig->size()) return true; + if (off >= (long)sig->value_size()) return true; else if (off < 0 ) { // We fell off the LSB end. if ((unsigned)-off >= wid ) return true; @@ -1046,7 +1046,7 @@ bool of_ASSIGN_V0X1D(vthread_t thr, vvp_code_t cp) vvp_vector4_t value = vthread_bits_to_vector(thr, bit, wid); vvp_net_ptr_t ptr (cp->net, 0); - schedule_assign_vector(ptr, off, sig->size(), value, delay); + schedule_assign_vector(ptr, off, sig->value_size(), value, delay); return true; } @@ -1062,12 +1062,12 @@ bool of_ASSIGN_V0X1E(vthread_t thr, vvp_code_t cp) long off = thr->words[1].w_int; unsigned bit = cp->bit_idx[0]; - vvp_fun_signal_vec*sig - = reinterpret_cast (cp->net->fun); + vvp_signal_value*sig + = dynamic_cast (cp->net->fun); assert(sig); // We fell off the MSB end. - if (off >= (long)sig->size()) { + if (off >= (long)sig->value_size()) { thr->event = 0; thr->ecount = 0; return true; @@ -1091,9 +1091,9 @@ bool of_ASSIGN_V0X1E(vthread_t thr, vvp_code_t cp) vvp_net_ptr_t ptr (cp->net, 0); // If the count is zero then just put the value. if (thr->ecount == 0) { - schedule_assign_vector(ptr, off, sig->size(), value, 0); + schedule_assign_vector(ptr, off, sig->value_size(), value, 0); } else { - schedule_evctl(ptr, value, off, sig->size(), thr->event, + schedule_evctl(ptr, value, off, sig->value_size(), thr->event, thr->ecount); } @@ -1307,12 +1307,12 @@ bool of_CASSIGN_X0(vthread_t thr, vvp_code_t cp) // X0 register. long index = thr->words[0].w_int; - vvp_fun_signal_vec*sig = dynamic_cast (net->fun); + vvp_signal_value*sig = dynamic_cast (net->fun); if (index < 0 && (wid <= (unsigned)-index)) return true; - if (index >= (long)sig->size()) + if (index >= (long)sig->value_size()) return true; if (index < 0) { @@ -1320,13 +1320,13 @@ bool of_CASSIGN_X0(vthread_t thr, vvp_code_t cp) index = 0; } - if (index+wid > sig->size()) - wid = sig->size() - index; + if (index+wid > sig->value_size()) + wid = sig->value_size() - index; vvp_vector4_t vector = vthread_bits_to_vector(thr, base, wid); vvp_net_ptr_t ptr (net, 1); - vvp_send_vec4_pv(ptr, vector, index, wid, sig->size(), 0); + vvp_send_vec4_pv(ptr, vector, index, wid, sig->value_size(), 0); return true; } @@ -1738,7 +1738,7 @@ bool of_DEASSIGN(vthread_t thr, vvp_code_t cp) unsigned base = cp->bit_idx[0]; unsigned width = cp->bit_idx[1]; - vvp_fun_signal_vec*sig = reinterpret_cast(net->fun); + vvp_fun_signal_vec*sig = dynamic_cast(net->fun); assert(sig); if (base >= sig->size()) return true; @@ -2341,10 +2341,10 @@ bool of_FORCE_V(vthread_t thr, vvp_code_t cp) /* Send the force value to the filter on the node. */ assert(net->fil); - if (value.size() != net->fil->size()) - value = coerce_to_width(value, net->fil->size()); + if (value.size() != net->fil->filter_size()) + value = coerce_to_width(value, net->fil->filter_size()); - net->force_vec4(value, vvp_vector2_t(vvp_vector2_t::FILL1, net->fil->size())); + net->force_vec4(value, vvp_vector2_t(vvp_vector2_t::FILL1, net->fil->filter_size())); return true; } @@ -2380,7 +2380,7 @@ bool of_FORCE_X0(vthread_t thr, vvp_code_t cp) index = 0; } - unsigned use_size = net->fil->size(); + unsigned use_size = net->fil->filter_size(); if (index >= (long)use_size) @@ -3055,13 +3055,13 @@ bool of_LOAD_X1P(vthread_t thr, vvp_code_t cp) // For the %load to work, the functor must actually be a // signal functor. Only signals save their vector value. - vvp_fun_signal_vec*sig = dynamic_cast (net->fun); + vvp_signal_value*sig = dynamic_cast (net->fun); assert(sig); for (long idx = 0 ; idx < wid ; idx += 1) { long use_index = index + idx; vvp_bit4_t val; - if (use_index < 0 || use_index >= (signed)sig->size()) + if (use_index < 0 || use_index >= (signed)sig->value_size()) val = BIT4_X; else val = sig->value(use_index); @@ -3910,10 +3910,11 @@ static bool do_release_vec(vthread_t thr, vvp_code_t cp, bool net_flag) assert(net->fil); - if (base >= net->fil->size()) return true; - if (base+width > net->fil->size()) width = net->fil->size() - base; + if (base >= net->fil->filter_size()) return true; + if (base+width > net->fil->filter_size()) + width = net->fil->filter_size() - base; - bool full_sig = base == 0 && width == net->fil->size(); + bool full_sig = base == 0 && width == net->fil->filter_size(); // XXXX Can't really do this if this is a partial release? net->fil->force_unlink(); @@ -4049,7 +4050,7 @@ bool of_SET_X0(vthread_t thr, vvp_code_t cp) // X0 register. long index = thr->words[0].w_int; - vvp_fun_signal_vec*sig = dynamic_cast (net->fun); + vvp_signal_value*sig = dynamic_cast (net->fun); // If the entire part is below the beginning of the vector, // then we are done. @@ -4058,7 +4059,7 @@ bool of_SET_X0(vthread_t thr, vvp_code_t cp) // If the entire part is above then end of the vector, then we // are done. - if (index >= (long)sig->size()) + if (index >= (long)sig->value_size()) return true; // If the part starts below the vector, then skip the first @@ -4071,8 +4072,8 @@ bool of_SET_X0(vthread_t thr, vvp_code_t cp) } // Reduce the width to keep the part inside the vector. - if (index+wid > sig->size()) - wid = sig->size() - index; + if (index+wid > sig->value_size()) + wid = sig->value_size() - index; vvp_vector4_t bit_vec(wid); for (unsigned idx = 0 ; idx < wid ; idx += 1) { @@ -4083,7 +4084,7 @@ bool of_SET_X0(vthread_t thr, vvp_code_t cp) } vvp_net_ptr_t ptr (net, 0); - vvp_send_vec4_pv(ptr, bit_vec, index, wid, sig->size(), thr->wt_context); + vvp_send_vec4_pv(ptr, bit_vec, index, wid, sig->value_size(), thr->wt_context); return true; } diff --git a/vvp/vvp_net.h b/vvp/vvp_net.h index e5acc925f..e3943bf78 100644 --- a/vvp/vvp_net.h +++ b/vvp/vvp_net.h @@ -1129,7 +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; + virtual unsigned filter_size() const =0; public: // Suport for force methods diff --git a/vvp/vvp_net_sig.cc b/vvp/vvp_net_sig.cc index 758de51db..ce993e194 100644 --- a/vvp/vvp_net_sig.cc +++ b/vvp/vvp_net_sig.cc @@ -65,6 +65,10 @@ template bool vvp_net_fil_t::filter_mask_(T&val) return true; } +vvp_signal_value::~vvp_signal_value() +{ +} + const vvp_vector4_t* vvp_fun_signal4::filter_vec4(const vvp_vector4_t&val) { return filter_mask_(val, force4_, filter4_); @@ -80,9 +84,14 @@ bool vvp_fun_signal_real::filter_real(double&val) return filter_mask_(val); } -unsigned vvp_fun_signal_real::size() const +unsigned vvp_fun_signal_real::filter_size() const { - return 1; + return size(); +} + +unsigned vvp_fun_signal4::filter_size() const +{ + return value_size(); } void vvp_fun_signal4::force_fil_vec4(const vvp_vector4_t&val, vvp_vector2_t mask) @@ -378,17 +387,11 @@ void vvp_fun_signal_base::deassign_pv(unsigned base, unsigned wid) void vvp_fun_signal4_sa::release(vvp_net_ptr_t ptr, bool net) { vvp_vector2_t mask (vvp_vector2_t::FILL1, bits4_.size()); + assert(!net); - if (net) { - // If releasing a net, then the output should revert to - // the un-forced value. - release_mask(mask); - ptr.ptr()->send_vec4(bits4_, 0); - } else { - // Variables keep their forced value after the release. - bits4_ = filtered_vec4(bits4_); - release_mask(mask); - } + // Variables keep their forced value after the release. + bits4_ = filtered_vec4(bits4_); + release_mask(mask); } void vvp_fun_signal4_sa::release_pv(vvp_net_ptr_t ptr, bool net, @@ -400,17 +403,11 @@ void vvp_fun_signal4_sa::release_pv(vvp_net_ptr_t ptr, bool net, for (unsigned idx = 0 ; idx < wid ; idx += 1) mask.set_bit(base+idx, 1); - if (net) { - release_mask(mask); - ptr.ptr()->send_vec4(bits4_,0); - } else { - bits4_ = filtered_vec4(bits4_); - release_mask(mask); - } - + bits4_ = filtered_vec4(bits4_); + release_mask(mask); } -unsigned vvp_fun_signal4_sa::size() const +unsigned vvp_fun_signal4_sa::value_size() const { return bits4_.size(); } @@ -509,7 +506,7 @@ void vvp_fun_signal4_aa::release_pv(vvp_net_ptr_t ptr, bool net, assert(0); } -unsigned vvp_fun_signal4_aa::size() const +unsigned vvp_fun_signal4_aa::value_size() const { return size_; } @@ -603,19 +600,7 @@ void vvp_fun_signal8::recv_vec8_pv(vvp_net_ptr_t ptr, const vvp_vector8_t&bit, * strength aware. */ assert(0); break; -#if 0 - case 2: // Force value - { vvp_vector2_t mask (vvp_vector2_t::FILL0, vwid); - vvp_vector8_t vec (vvp_vector4_t(vwid, BIT4_Z),6,6); - for (unsigned idx = 0 ; idx < wid ; idx += 1) { - mask.set_bit(base+idx, 1); - vec.set_bit(base+idx, bit.value(idx)); - } - force_vec8(vec, mask); - calculate_output_(ptr); - break; - } -#endif + default: fprintf(stderr, "Unsupported port type %d.\n", ptr.port()); assert(0); @@ -657,7 +642,12 @@ void vvp_fun_signal8::release_pv(vvp_net_ptr_t ptr, bool net, } } -unsigned vvp_fun_signal8::size() const +unsigned vvp_fun_signal8::filter_size() const +{ + return value_size(); +} + +unsigned vvp_fun_signal8::value_size() const { return bits8_.size(); } @@ -828,7 +818,7 @@ void vvp_fun_force::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit, vvp_net_t*dst = net->port[3].ptr(); assert(dst->fil); - dst->force_vec4(coerce_to_width(bit, dst->fil->size()), vvp_vector2_t(vvp_vector2_t::FILL1, dst->fil->size())); + dst->force_vec4(coerce_to_width(bit, dst->fil->filter_size()), vvp_vector2_t(vvp_vector2_t::FILL1, dst->fil->filter_size())); } void vvp_fun_force::recv_real(vvp_net_ptr_t ptr, double bit, vvp_context_t) @@ -838,3 +828,191 @@ void vvp_fun_force::recv_real(vvp_net_ptr_t ptr, double bit, vvp_context_t) vvp_net_t*dst = net->port[3].ptr(); dst->force_real(bit, vvp_vector2_t(vvp_vector2_t::FILL1, 1)); } + +vvp_wire_base::vvp_wire_base() +{ +} + +vvp_wire_base::~vvp_wire_base() +{ +} + +vvp_wire_vec4::vvp_wire_vec4(unsigned wid, vvp_bit4_t init) +: width_(wid) +{ +} + +const vvp_vector4_t* vvp_wire_vec4::filter_vec4(const vvp_vector4_t&bit) +{ + return filter_mask_(bit, force4_, filter4_); +} + +const vvp_vector8_t* vvp_wire_vec4::filter_vec8(const vvp_vector8_t&bit) +{ + assert(0); + return 0; +} + +unsigned vvp_wire_vec4::filter_size() const +{ + return width_; +} + +void vvp_wire_vec4::force_fil_vec4(const vvp_vector4_t&val, vvp_vector2_t mask) +{ + force_mask(mask); + + if (force4_.size() == 0) { + force4_ = val; + } else { + for (unsigned idx = 0; idx < mask.size() ; idx += 1) { + if (mask.value(idx) == 0) + continue; + + force4_.set_bit(idx, val.value(idx)); + } + } +} + +void vvp_wire_vec4::force_fil_vec8(const vvp_vector8_t&val, vvp_vector2_t mask) +{ + assert(0); +} + +void vvp_wire_vec4::force_fil_real(double val, vvp_vector2_t mask) +{ + assert(0); +} + +void vvp_wire_vec4::release(vvp_net_ptr_t ptr, bool net) +{ + assert(net); + + // Wires revert to their unforced value after release. + vvp_vector2_t mask (vvp_vector2_t::FILL1, width_); + release_mask(mask); + ptr.ptr()->send_vec4(bits4_, 0); +} + +void vvp_wire_vec4::release_pv(vvp_net_ptr_t ptr, bool net, + unsigned base, unsigned wid) +{ + assert(bits4_.size() >= base + wid); + assert(net); + + vvp_vector2_t mask (vvp_vector2_t::FILL0, bits4_.size()); + for (unsigned idx = 0 ; idx < wid ; idx += 1) + mask.set_bit(base+idx, 1); + + release_mask(mask); + ptr.ptr()->send_vec4(bits4_,0); +} + +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 +{ + if (test_force_mask(idx)) + return force4_.value(idx); + else + return val.value(idx); +} + +vvp_bit4_t vvp_wire_vec4::value(unsigned idx) const +{ + return filtered_value_(bits4_, idx); +} + +vvp_scalar_t vvp_wire_vec4::scalar_value(unsigned idx) const +{ + assert(0); +} + +vvp_vector4_t vvp_wire_vec4::vec4_value() const +{ + assert(0); +} + +vvp_wire_vec8::vvp_wire_vec8(unsigned wid) +: width_(wid) +{ +} + +const vvp_vector4_t* vvp_wire_vec8::filter_vec4(const vvp_vector4_t&bit) +{ + assert(0); + return 0; +} + +const vvp_vector8_t* vvp_wire_vec8::filter_vec8(const vvp_vector8_t&bit) +{ + assert(0); + return 0; +} + +unsigned vvp_wire_vec8::filter_size() const +{ + return width_; +} + +void vvp_wire_vec8::force_fil_vec4(const vvp_vector4_t&val, vvp_vector2_t mask) +{ + assert(0); +} + +void vvp_wire_vec8::force_fil_vec8(const vvp_vector8_t&val, vvp_vector2_t mask) +{ + assert(0); +} + +void vvp_wire_vec8::force_fil_real(double val, vvp_vector2_t mask) +{ + assert(0); +} + +void vvp_wire_vec8::release(vvp_net_ptr_t ptr, bool net) +{ + assert(net); + + // Wires revert to their unforced value after release. + vvp_vector2_t mask (vvp_vector2_t::FILL1, width_); + release_mask(mask); + ptr.ptr()->send_vec8(bits8_); +} + +void vvp_wire_vec8::release_pv(vvp_net_ptr_t ptr, bool net, + unsigned base, unsigned wid) +{ + assert(width_ >= base + wid); + assert(net); + + vvp_vector2_t mask (vvp_vector2_t::FILL0, width_); + for (unsigned idx = 0 ; idx < wid ; idx += 1) + mask.set_bit(base+idx, 1); + + release_mask(mask); + ptr.ptr()->send_vec8(bits8_); +} + +unsigned vvp_wire_vec8::value_size() const +{ + return width_; +} + +vvp_bit4_t vvp_wire_vec8::value(unsigned idx) const +{ + assert(0); +} + +vvp_scalar_t vvp_wire_vec8::scalar_value(unsigned idx) const +{ + assert(0); +} + +vvp_vector4_t vvp_wire_vec8::vec4_value() const +{ + assert(0); +} diff --git a/vvp/vvp_net_sig.h b/vvp/vvp_net_sig.h index acaf6d2eb..d6f530671 100644 --- a/vvp/vvp_net_sig.h +++ b/vvp/vvp_net_sig.h @@ -62,32 +62,6 @@ using namespace std; * off again. Writing into this port can be done in behavioral code * using the %cassign/v instruction, or can be done by the network by * hooking the output of a vvp_net_t to this port. - * - * Force assignments are made through port-2. When a value is written - * here, force mode is activated. In force mode, port-0 data (or - * port-1 data if in continuous assign mode) is tracked but not - * propagated. The force value is propagated and is what is readable - * through the value method. - * - * Port-3 is a command port, intended for use by procedural - * instructions. The client must write long values to this port to - * invoke the command of interest. The command values are: - * - * 1 -- deassign - * The deassign command takes the node out of continuous - * assignment mode. The output value is unchanged, and force - * mode, if active, remains in effect. - * - * 2 -- release/net - * The release/net command takes the node out of force mode, - * and propagates the tracked port-0 value to the signal - * output. This acts like a release of a net signal. - * - * 3 -- release/reg - * The release/reg command is similar to the release/net - * command, but the port-0 value is not propagated. Changes - * to port-0 (or port-1 if continuous assign is active) will - * propagate starting at the next input change. */ @@ -117,17 +91,27 @@ class vvp_fun_signal_base : public vvp_net_fun_t, public vvp_net_fil_t { }; /* - * This abstract class is a little more specific than the signal_base - * class, in that it adds vector access methods. + * Variables and wires can have their values accessed, so this base + * class offers the unified concept of an acessible value. */ -class vvp_fun_signal_vec : public vvp_fun_signal_base { - +class vvp_signal_value { public: - // For vector signal types, this returns the vector count. - virtual unsigned size() const =0; + virtual ~vvp_signal_value() =0; + virtual unsigned value_size() const =0; virtual vvp_bit4_t value(unsigned idx) const =0; virtual vvp_scalar_t scalar_value(unsigned idx) const =0; virtual vvp_vector4_t vec4_value() const =0; + + virtual void get_signal_value(struct t_vpi_value*vp); +}; + +/* + * This abstract class is a little more specific than the signal_base + * class, in that it adds vector access methods. + */ +class vvp_fun_signal_vec : public vvp_fun_signal_base, public vvp_signal_value { + public: + unsigned size() const { return value_size(); } }; class vvp_fun_signal4 : public vvp_fun_signal_vec { @@ -146,6 +130,7 @@ class vvp_fun_signal4 : public vvp_fun_signal_vec { // Test the value against the filter. vvp_bit4_t filtered_value(const vvp_vector4_t&val, unsigned idx) const; const vvp_vector4_t& filtered_vec4(const vvp_vector4_t&val) const; + unsigned filter_size() const; private: vvp_vector4_t force4_; @@ -172,7 +157,7 @@ class vvp_fun_signal4_sa : public vvp_fun_signal4 { unsigned base, unsigned wid, unsigned vwid); // Get information about the vector value. - unsigned size() const; + unsigned value_size() const; vvp_bit4_t value(unsigned idx) const; vvp_scalar_t scalar_value(unsigned idx) const; vvp_vector4_t vec4_value() const; @@ -209,7 +194,7 @@ class vvp_fun_signal4_aa : public vvp_fun_signal4, public automatic_hooks_s { vvp_context_t); // Get information about the vector value. - unsigned size() const; + unsigned value_size() const; vvp_bit4_t value(unsigned idx) const; vvp_scalar_t scalar_value(unsigned idx) const; vvp_vector4_t vec4_value() const; @@ -241,7 +226,7 @@ class vvp_fun_signal8 : public vvp_fun_signal_vec { unsigned base, unsigned wid, unsigned vwid); // Get information about the vector value. - unsigned size() const; + unsigned value_size() const; vvp_bit4_t value(unsigned idx) const; vvp_scalar_t scalar_value(unsigned idx) const; vvp_vector4_t vec4_value() const; @@ -263,6 +248,7 @@ class vvp_fun_signal8 : public vvp_fun_signal_vec { // 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; + unsigned filter_size() const; private: vvp_vector8_t bits8_; @@ -290,7 +276,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; + unsigned size() const { return 1; } + virtual unsigned filter_size() const; private: double force_real_; @@ -350,4 +337,90 @@ class vvp_fun_signal_real_aa : public vvp_fun_signal_real, public automatic_hook }; +/* vvp_wire + * The vvp_wire is different from vvp_variable objects in that it + * exists only as a filter. The vvp_wire class tree is for + * implementing verilog wires/nets (as opposed to regs/variables). + */ + +class vvp_wire_base : public vvp_net_fil_t, public vvp_signal_value { + + public: + vvp_wire_base(); + ~vvp_wire_base(); + + // The main filter behavior for this class + const vvp_vector4_t* filter_vec4(const vvp_vector4_t&bit) =0; + const vvp_vector8_t* filter_vec8(const vvp_vector8_t&val) =0; + +}; + +class vvp_wire_vec4 : public vvp_wire_base { + + public: + vvp_wire_vec4(unsigned wid, vvp_bit4_t init=BIT4_X); + + // The main filter behavior for this class. These methods take + // 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); + + // Abstract methods from vvp_vpi_callback + void get_value(struct t_vpi_value*value); + // Abstract methods from vvp_net_fit_t + unsigned filter_size() const; + 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); + void release(vvp_net_ptr_t ptr, bool net); + void release_pv(vvp_net_ptr_t ptr, bool net, unsigned base, unsigned wid); + + // Implementation of vvp_signal_value methods + unsigned value_size() const; + vvp_bit4_t value(unsigned idx) const; + vvp_scalar_t scalar_value(unsigned idx) const; + vvp_vector4_t vec4_value() const; + + private: + vvp_bit4_t filtered_value_(const vvp_vector4_t&val, 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 { + + public: + 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); + + // Abstract methods from vvp_vpi_callback + void get_value(struct t_vpi_value*value); + // Abstract methods from vvp_net_fit_t + unsigned filter_size() const; + 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); + void release(vvp_net_ptr_t ptr, bool net); + void release_pv(vvp_net_ptr_t ptr, bool net, unsigned base, unsigned wid); + + // Implementation of vvp_signal_value methods + unsigned value_size() const; + vvp_bit4_t value(unsigned idx) const; + vvp_scalar_t scalar_value(unsigned idx) const; + vvp_vector4_t vec4_value() const; + + private: + unsigned width_; + vvp_vector8_t bits8_; +}; + #endif diff --git a/vvp/words.cc b/vvp/words.cc index f7d5173de..534ec7785 100644 --- a/vvp/words.cc +++ b/vvp/words.cc @@ -148,40 +148,36 @@ void compile_variablew(char*label, vvp_array_t array, /* * Here we handle .net records from the vvp source: * - *