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.
This commit is contained in:
Stephen Williams 2009-07-27 21:42:04 -07:00
parent 6ef9243a10
commit 8bbb7ff7db
8 changed files with 423 additions and 164 deletions

View File

@ -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<vvp_fun_signal_vec*> (vsig->node->fun);
vvp_signal_value*sig = dynamic_cast<vvp_signal_value*> (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];

View File

@ -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<vvp_fun_signal_base*>(sig->node->fun);
assert(sig_fun);
vvp_net_fil_t*sig_fil;
sig_fil = dynamic_cast<vvp_net_fil_t*>(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);
}

View File

@ -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<vvp_fun_signal_vec*>(rfp->node->fun);
vvp_signal_value*vsig = dynamic_cast<vvp_signal_value*>(rfp->node->fil);
assert(vsig);
switch (vp->format) {

View File

@ -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<vvp_fun_signal_vec*> (cp->net->fun);
vvp_signal_value*sig
= reinterpret_cast<vvp_signal_value*> (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<vvp_fun_signal_vec*> (cp->net->fun);
vvp_signal_value*sig
= reinterpret_cast<vvp_signal_value*> (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<vvp_fun_signal_vec*> (cp->net->fun);
vvp_signal_value*sig
= dynamic_cast<vvp_signal_value*> (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<vvp_fun_signal_vec*> (net->fun);
vvp_signal_value*sig = dynamic_cast<vvp_signal_value*> (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<vvp_fun_signal_vec*>(net->fun);
vvp_fun_signal_vec*sig = dynamic_cast<vvp_fun_signal_vec*>(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<vvp_fun_signal_vec*> (net->fun);
vvp_signal_value*sig = dynamic_cast<vvp_signal_value*> (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<vvp_fun_signal_vec*> (net->fun);
vvp_signal_value*sig = dynamic_cast<vvp_signal_value*> (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;
}

View File

@ -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

View File

@ -65,6 +65,10 @@ template <class T> 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);
}

View File

@ -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

View File

@ -148,40 +148,36 @@ void compile_variablew(char*label, vvp_array_t array,
/*
* Here we handle .net records from the vvp source:
*
* <label> .net <name>, <msb>, <lsb>, <input> ;
* <label> .net/s <name>, <msb>, <lsb>, <input> ;
* <label> .net8 <name>, <msb>, <lsb>, <input> ;
* <label> .net8/s <name>, <msb>, <lsb>, <input> ;
* .net <name>, <msb>, <lsb>, <input> ;
* .net/s <name>, <msb>, <lsb>, <input> ;
* .net8 <name>, <msb>, <lsb>, <input> ;
* .net8/s <name>, <msb>, <lsb>, <input> ;
*
* Create a VPI handle to represent it, and fill that handle in with
* references into the net.
*/
static void __compile_net(char*label, char*name,
char*array_label, unsigned long array_addr,
static void __compile_net(char*label,
char*name, char*array_label, unsigned long array_addr,
int msb, int lsb,
bool signed_flag, bool net8_flag, bool local_flag,
unsigned argc, struct symb_s*argv)
{
unsigned wid = ((msb > lsb)? msb-lsb : lsb-msb) + 1;
vvp_net_t*node = new vvp_net_t;
vvp_array_t array = array_label ? array_find(array_label) : 0;
assert(array_label ? array!=0 : true);
vvp_fun_signal_base*vsig = net8_flag
? dynamic_cast<vvp_fun_signal_base*>(new vvp_fun_signal8(wid))
: dynamic_cast<vvp_fun_signal_base*>(new vvp_fun_signal4_sa(wid,BIT4_Z));
node->fun = vsig;
node->fil = vsig;
/* Add the label into the functor symbol table. */
define_functor_symbol(label, node);
// XXXX Forgot how to implement net arrays...
assert(array_label == 0);
assert(argc == 1);
vvp_net_t*node = vvp_net_lookup(argv[0].text);
assert(node);
/* Connect the source to my input. */
inputs_connect(node, 1, argv);
vvp_wire_base*vsig = net8_flag
? dynamic_cast<vvp_wire_base*>(new vvp_wire_vec8(wid))
: dynamic_cast<vvp_wire_base*>(new vvp_wire_vec4(wid,BIT4_Z));
// Assume (for now) that there is only 1 filter per node.
assert(node->fil == 0);
node->fil = vsig;
vpiHandle obj = 0;
if (! local_flag) {
@ -190,11 +186,8 @@ static void __compile_net(char*label, char*name,
/* This attaches the label to the vpiHandle */
compile_vpi_symbol(label, obj);
}
/* If this is an array word, then attach it to the
array. Otherwise, attach it to the current scope. */
if (array)
array_attach_word(array, array_addr, obj);
else if (obj)
if (obj)
vpip_attach_to_current_scope(obj);
free(label);
@ -203,8 +196,7 @@ static void __compile_net(char*label, char*name,
free(argv);
}
void compile_net(char*label, char*name,
int msb, int lsb,
void compile_net(char*label, char*name, int msb, int lsb,
bool signed_flag, bool net8_flag, bool local_flag,
unsigned argc, struct symb_s*argv)
{