vthread no longer accesses any signal methods.

We want the entire force/release subsystem to only reference the
vvp_net_t or vvp_net_fil_t objects in a net. This gives us the
latitude to take wire implementations out of the vvp_net_fun classes.
This commit is contained in:
Stephen Williams 2009-07-05 16:27:14 -07:00
parent 9fe28e09a6
commit 6ef9243a10
4 changed files with 40 additions and 78 deletions

View File

@ -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<vvp_fun_signal4*> (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<vvp_fun_signal4*> (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<vvp_fun_signal8*> (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<vvp_fun_signal_vec*>(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<vvp_fun_signal_vec*>(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. */

View File

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

View File

@ -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<vvp_fun_signal4*> (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)

View File

@ -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_;
};