Change implementation of force/release to use filters.
This is moving towards moving force/release out of the signal class. The end-game is to remove all of the wire implementation out of the functor and into the filter. Variables will remain in the functor.
This commit is contained in:
parent
79a5dde7c4
commit
ba00c6caf7
|
|
@ -202,22 +202,22 @@ vvp_net_fil_t::~vvp_net_fil_t()
|
|||
{
|
||||
}
|
||||
|
||||
bool vvp_net_fil_t::filter_vec4(const vvp_vector4_t&)
|
||||
const vvp_vector4_t* vvp_net_fil_t::filter_vec4(const vvp_vector4_t&val)
|
||||
{
|
||||
return &val;
|
||||
}
|
||||
|
||||
const vvp_vector8_t* vvp_net_fil_t::filter_vec8(const vvp_vector8_t&val)
|
||||
{
|
||||
return &val;
|
||||
}
|
||||
|
||||
bool vvp_net_fil_t::filter_real(double&)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool vvp_net_fil_t::filter_vec8(const vvp_vector8_t&)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool vvp_net_fil_t::filter_real(double)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool vvp_net_fil_t::filter_long(long)
|
||||
bool vvp_net_fil_t::filter_long(long&)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
|
@ -387,6 +387,8 @@ void vvp_send_long_pv(vvp_net_ptr_t ptr, long val,
|
|||
}
|
||||
}
|
||||
|
||||
const vvp_vector4_t vvp_vector4_t::nil;
|
||||
|
||||
void vvp_vector4_t::copy_bits(const vvp_vector4_t&that)
|
||||
{
|
||||
|
||||
|
|
@ -2369,6 +2371,8 @@ vvp_vector8_t::vvp_vector8_t(const vvp_vector4_t&that,
|
|||
|
||||
}
|
||||
|
||||
const vvp_vector8_t vvp_vector8_t::nil;
|
||||
|
||||
vvp_vector8_t& vvp_vector8_t::operator= (const vvp_vector8_t&that)
|
||||
{
|
||||
// Assign to self.
|
||||
|
|
|
|||
|
|
@ -196,6 +196,9 @@ class vvp_vector4_t {
|
|||
friend class vvp_vector4array_sa;
|
||||
friend class vvp_vector4array_aa;
|
||||
|
||||
public:
|
||||
static const vvp_vector4_t nil;
|
||||
|
||||
public:
|
||||
explicit vvp_vector4_t(unsigned size =0, vvp_bit4_t bits =BIT4_X);
|
||||
|
||||
|
|
@ -778,6 +781,10 @@ class vvp_vector8_t {
|
|||
|
||||
~vvp_vector8_t();
|
||||
|
||||
static const vvp_vector8_t nil;
|
||||
|
||||
public:
|
||||
|
||||
unsigned size() const { return size_; }
|
||||
vvp_scalar_t value(unsigned idx) const;
|
||||
vvp_vector8_t subvalue(unsigned adr, unsigned width) const;
|
||||
|
|
@ -1088,10 +1095,16 @@ class vvp_net_fil_t {
|
|||
virtual ~vvp_net_fil_t();
|
||||
|
||||
public:
|
||||
virtual bool filter_vec4(const vvp_vector4_t&bit);
|
||||
virtual bool filter_vec8(const vvp_vector8_t&val);
|
||||
virtual bool filter_real(double val);
|
||||
virtual bool filter_long(long val);
|
||||
// Return a non-empty vector if the filter allows an
|
||||
// output. The output result may be different from the
|
||||
// input. If the output is nil, then suppress propagation.
|
||||
virtual const vvp_vector4_t* filter_vec4(const vvp_vector4_t&bit);
|
||||
virtual const vvp_vector8_t* filter_vec8(const vvp_vector8_t&val);
|
||||
|
||||
// Return true if the value is to be propagated, or false if
|
||||
// propagation is suppressed. The value may be edited by the filter.
|
||||
virtual bool filter_real(double&val);
|
||||
virtual bool filter_long(long&val);
|
||||
};
|
||||
|
||||
/* **** Some core net functions **** */
|
||||
|
|
@ -1335,10 +1348,11 @@ inline void vvp_net_t::send_vec8_pv(const vvp_vector8_t&val,
|
|||
|
||||
inline void vvp_net_t::send_vec4(const vvp_vector4_t&val, vvp_context_t context)
|
||||
{
|
||||
if (fil && ! fil->filter_vec4(val))
|
||||
const vvp_vector4_t*val_out = fil? fil->filter_vec4(val) : &val;
|
||||
if (val_out == 0)
|
||||
return;
|
||||
|
||||
vvp_send_vec4(out_, val, context);
|
||||
vvp_send_vec4(out_, *val_out, context);
|
||||
}
|
||||
|
||||
inline void vvp_net_t::send_vec4_pv(const vvp_vector4_t&val,
|
||||
|
|
@ -1350,10 +1364,11 @@ inline void vvp_net_t::send_vec4_pv(const vvp_vector4_t&val,
|
|||
|
||||
inline void vvp_net_t::send_vec8(const vvp_vector8_t&val)
|
||||
{
|
||||
if (fil && ! fil->filter_vec8(val))
|
||||
const vvp_vector8_t*val_out = fil? fil->filter_vec8(val) : &val;
|
||||
if (val_out == 0)
|
||||
return;
|
||||
|
||||
vvp_send_vec8(out_, val);
|
||||
vvp_send_vec8(out_, *val_out);
|
||||
}
|
||||
|
||||
inline void vvp_net_t::send_real(double val, vvp_context_t context)
|
||||
|
|
|
|||
|
|
@ -43,58 +43,205 @@ template <class T> T coerce_to_width(const T&that, unsigned width)
|
|||
|
||||
vvp_filter_wire_base::vvp_filter_wire_base()
|
||||
{
|
||||
continuous_assign_active_ = false;
|
||||
}
|
||||
|
||||
vvp_filter_wire_base::~vvp_filter_wire_base()
|
||||
{
|
||||
}
|
||||
|
||||
bool vvp_filter_wire_base::filter_vec4(const vvp_vector4_t&)
|
||||
const vvp_vector4_t* vvp_filter_wire_base::filter_vec4(const vvp_vector4_t&val)
|
||||
{
|
||||
if (force_mask_.size()) {
|
||||
bool propagate_flag = false;
|
||||
assert(val.size() == force_mask_.size());
|
||||
assert(val.size() == force4_.size());
|
||||
|
||||
filter4_ = val;
|
||||
for (unsigned idx = 0 ; idx < val.size() ; idx += 1) {
|
||||
if (force_mask_.value(idx))
|
||||
filter4_.set_bit(idx, force4_.value(idx));
|
||||
else
|
||||
propagate_flag = true;
|
||||
}
|
||||
|
||||
if (propagate_flag) {
|
||||
run_vpi_callbacks();
|
||||
return &filter4_;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
} else {
|
||||
run_vpi_callbacks();
|
||||
return &val;
|
||||
}
|
||||
}
|
||||
|
||||
const vvp_vector8_t* vvp_filter_wire_base::filter_vec8(const vvp_vector8_t&val)
|
||||
{
|
||||
if (force_mask_.size()) {
|
||||
bool propagate_flag = false;
|
||||
assert(val.size() == force_mask_.size());
|
||||
assert(val.size() == force8_.size());
|
||||
|
||||
filter8_ = val;
|
||||
for (unsigned idx = 0 ; idx < val.size() ; idx += 1) {
|
||||
if (force_mask_.value(idx))
|
||||
filter8_.set_bit(idx, force8_.value(idx));
|
||||
else
|
||||
propagate_flag = true;
|
||||
}
|
||||
|
||||
if (propagate_flag) {
|
||||
run_vpi_callbacks();
|
||||
return&filter8_;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
run_vpi_callbacks();
|
||||
return &val;
|
||||
}
|
||||
}
|
||||
|
||||
bool vvp_filter_wire_base::filter_real(double&val)
|
||||
{
|
||||
run_vpi_callbacks();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool vvp_filter_wire_base::filter_vec8(const vvp_vector8_t&)
|
||||
bool vvp_filter_wire_base::filter_long(long&)
|
||||
{
|
||||
run_vpi_callbacks();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool vvp_filter_wire_base::filter_real(double)
|
||||
void vvp_filter_wire_base::force_vec4(const vvp_vector4_t&val, vvp_vector2_t mask)
|
||||
{
|
||||
run_vpi_callbacks();
|
||||
return true;
|
||||
if (force_mask_.size() == 0)
|
||||
force_mask_ = vvp_vector2_t(vvp_vector2_t::FILL0, mask.size());
|
||||
if (force4_.size() == 0)
|
||||
force4_ = val;
|
||||
|
||||
assert(force_mask_.size() == mask.size());
|
||||
for (unsigned idx = 0; idx < mask.size() ; idx += 1) {
|
||||
if (mask.value(idx) == 0)
|
||||
continue;
|
||||
|
||||
force_mask_.set_bit(idx, 1);
|
||||
force4_.set_bit(idx, val.value(idx));
|
||||
}
|
||||
}
|
||||
|
||||
bool vvp_filter_wire_base::filter_long(long)
|
||||
void vvp_filter_wire_base::force_vec8(const vvp_vector8_t&val, vvp_vector2_t mask)
|
||||
{
|
||||
run_vpi_callbacks();
|
||||
return true;
|
||||
if (force_mask_.size() == 0)
|
||||
force_mask_ = vvp_vector2_t(vvp_vector2_t::FILL0, mask.size());
|
||||
if (force8_.size() == 0)
|
||||
force8_ = val;
|
||||
|
||||
assert(force_mask_.size() == mask.size());
|
||||
for (unsigned idx = 0; idx < mask.size() ; idx += 1) {
|
||||
if (mask.value(idx) == 0)
|
||||
continue;
|
||||
|
||||
force_mask_.set_bit(idx, 1);
|
||||
force8_.set_bit(idx, val.value(idx));
|
||||
}
|
||||
}
|
||||
|
||||
void vvp_filter_wire_base::deassign()
|
||||
void vvp_filter_wire_base::force_real(double val, vvp_vector2_t mask)
|
||||
{
|
||||
continuous_assign_active_ = false;
|
||||
assign_mask_ = vvp_vector2_t();
|
||||
}
|
||||
if (force_mask_.size() == 0)
|
||||
force_mask_ = vvp_vector2_t(vvp_vector2_t::FILL0, mask.size());
|
||||
|
||||
void vvp_filter_wire_base::deassign_pv(unsigned base, unsigned wid)
|
||||
{
|
||||
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
|
||||
assign_mask_.set_bit(base+idx, 0);
|
||||
assert(force_mask_.size() == mask.size());
|
||||
for (unsigned idx = 0 ; idx < mask.size() ; idx += 1) {
|
||||
if (mask.value(idx) == 0)
|
||||
continue;
|
||||
|
||||
force_mask_.set_bit(idx, 1);
|
||||
}
|
||||
|
||||
if (assign_mask_.is_zero()) {
|
||||
assign_mask_ = vvp_vector2_t();
|
||||
force_real_ = val;
|
||||
}
|
||||
|
||||
vvp_bit4_t vvp_filter_wire_base::filtered_value(const vvp_vector4_t&val, unsigned idx) const
|
||||
{
|
||||
if (force_mask_.size() == 0)
|
||||
return val.value(idx);
|
||||
if (force_mask_.value(idx))
|
||||
return force4_.value(idx);
|
||||
|
||||
return val.value(idx);
|
||||
}
|
||||
|
||||
vvp_scalar_t vvp_filter_wire_base::filtered_value(const vvp_vector8_t&val, unsigned idx) const
|
||||
{
|
||||
if (force_mask_.size() == 0)
|
||||
return val.value(idx);
|
||||
if (force_mask_.value(idx))
|
||||
return force8_.value(idx);
|
||||
|
||||
return val.value(idx);
|
||||
}
|
||||
|
||||
const vvp_vector4_t& vvp_filter_wire_base::filtered_vec4(const vvp_vector4_t&val) const
|
||||
{
|
||||
if (force_mask_.size() == 0)
|
||||
return val;
|
||||
|
||||
filter4_ = val;
|
||||
for (unsigned idx = 0 ; idx < val.size() ; idx += 1) {
|
||||
if (force_mask_.value(idx))
|
||||
filter4_.set_bit(idx, force4_.value(idx));
|
||||
}
|
||||
return filter4_;
|
||||
}
|
||||
|
||||
const vvp_vector8_t& vvp_filter_wire_base::filtered_vec8(const vvp_vector8_t&val) const
|
||||
{
|
||||
if (force_mask_.size() == 0)
|
||||
return val;
|
||||
|
||||
filter8_ = val;
|
||||
for (unsigned idx = 0 ; idx < val.size() ; idx += 1) {
|
||||
if (force_mask_.value(idx))
|
||||
filter8_.set_bit(idx, force8_.value(idx));
|
||||
}
|
||||
return filter8_;
|
||||
}
|
||||
|
||||
double vvp_filter_wire_base::filtered_real(double val) const
|
||||
{
|
||||
if (force_mask_.size() == 0)
|
||||
return val;
|
||||
if (force_mask_.value(0) == 0)
|
||||
return val;
|
||||
|
||||
return force_real_;
|
||||
}
|
||||
|
||||
void vvp_filter_wire_base::release_mask(vvp_vector2_t mask)
|
||||
{
|
||||
if (force_mask_.size() == 0)
|
||||
return;
|
||||
|
||||
assert(force_mask_.size() == mask.size());
|
||||
for (unsigned idx = 0 ; idx < mask.size() ; idx += 1) {
|
||||
if (mask.value(idx))
|
||||
force_mask_.set_bit(idx, 0);
|
||||
}
|
||||
|
||||
if (force_mask_.is_zero())
|
||||
force_mask_ = vvp_vector2_t();
|
||||
}
|
||||
|
||||
/* **** vvp_fun_signal methods **** */
|
||||
|
||||
vvp_fun_signal_base::vvp_fun_signal_base()
|
||||
{
|
||||
continuous_assign_active_ = false;
|
||||
needs_init_ = true;
|
||||
force_link = 0;
|
||||
cassign_link = 0;
|
||||
|
|
@ -216,17 +363,17 @@ void vvp_fun_signal4_sa::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
|||
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 (bit.size() != size())
|
||||
force_ = coerce_to_width(bit, size());
|
||||
else
|
||||
force_ = 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_mask_ = vvp_vector2_t(vvp_vector2_t::FILL1, size());
|
||||
calculate_output_(ptr);
|
||||
break;
|
||||
ptr.ptr()->send_vec4(tmp, 0);
|
||||
force_vec4(tmp, vvp_vector2_t(vvp_vector2_t::FILL1,tmp.size()));
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "Unsupported port type %d.\n", ptr.port());
|
||||
|
|
@ -285,19 +432,16 @@ void vvp_fun_signal4_sa::recv_vec4_pv(vvp_net_ptr_t ptr, const vvp_vector4_t&bit
|
|||
break;
|
||||
|
||||
case 2: // Force value
|
||||
|
||||
if (force_mask_.size() == 0)
|
||||
force_mask_ = vvp_vector2_t(vvp_vector2_t::FILL0, size());
|
||||
if (force_.size() == 0)
|
||||
force_ = vvp_vector4_t(vwid, BIT4_Z);
|
||||
|
||||
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
|
||||
force_mask_.set_bit(base+idx, 1);
|
||||
force_.set_bit(base+idx, bit.value(idx));
|
||||
}
|
||||
|
||||
calculate_output_(ptr);
|
||||
break;
|
||||
{ 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());
|
||||
|
|
@ -314,27 +458,39 @@ void vvp_fun_signal4_sa::recv_vec8_pv(vvp_net_ptr_t ptr, const vvp_vector8_t&bit
|
|||
|
||||
void vvp_fun_signal4_sa::calculate_output_(vvp_net_ptr_t ptr)
|
||||
{
|
||||
if (force_mask_.size()) {
|
||||
assert(bits4_.size() == force_mask_.size());
|
||||
assert(bits4_.size() == force_.size());
|
||||
vvp_vector4_t bits (bits4_);
|
||||
for (unsigned idx = 0 ; idx < bits.size() ; idx += 1) {
|
||||
if (force_mask_.value(idx))
|
||||
bits.set_bit(idx, force_.value(idx));
|
||||
}
|
||||
ptr.ptr()->send_vec4(bits, 0);
|
||||
} else {
|
||||
ptr.ptr()->send_vec4(bits4_, 0);
|
||||
}
|
||||
ptr.ptr()->send_vec4(bits4_, 0);
|
||||
}
|
||||
|
||||
|
||||
void vvp_fun_signal_base::deassign()
|
||||
{
|
||||
continuous_assign_active_ = false;
|
||||
assign_mask_ = vvp_vector2_t();
|
||||
}
|
||||
|
||||
void vvp_fun_signal_base::deassign_pv(unsigned base, unsigned wid)
|
||||
{
|
||||
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
|
||||
assign_mask_.set_bit(base+idx, 0);
|
||||
}
|
||||
|
||||
if (assign_mask_.is_zero()) {
|
||||
assign_mask_ = vvp_vector2_t();
|
||||
}
|
||||
}
|
||||
void vvp_fun_signal4_sa::release(vvp_net_ptr_t ptr, bool net)
|
||||
{
|
||||
force_mask_ = vvp_vector2_t();
|
||||
vvp_vector2_t mask (vvp_vector2_t::FILL1, bits4_.size());
|
||||
|
||||
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 {
|
||||
bits4_ = force_;
|
||||
// Variables keep their forced value after the release.
|
||||
bits4_ = filtered_vec4(bits4_);
|
||||
release_mask(mask);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -343,55 +499,38 @@ void vvp_fun_signal4_sa::release_pv(vvp_net_ptr_t ptr, bool net,
|
|||
{
|
||||
assert(bits4_.size() >= base + wid);
|
||||
|
||||
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
|
||||
force_mask_.set_bit(base+idx, 0);
|
||||
if (!net) bits4_.set_bit(base+idx, force_.value(base+idx));
|
||||
}
|
||||
if (force_mask_.is_zero()) force_mask_ = vvp_vector2_t();
|
||||
vvp_vector2_t mask (vvp_vector2_t::FILL0, bits4_.size());
|
||||
for (unsigned idx = 0 ; idx < wid ; idx += 1)
|
||||
mask.set_bit(base+idx, 1);
|
||||
|
||||
if (net) {
|
||||
release_mask(mask);
|
||||
calculate_output_(ptr);
|
||||
} else {
|
||||
bits4_ = filtered_vec4(bits4_);
|
||||
release_mask(mask);
|
||||
}
|
||||
|
||||
if (net) calculate_output_(ptr);
|
||||
}
|
||||
|
||||
unsigned vvp_fun_signal4_sa::size() const
|
||||
{
|
||||
if (force_mask_.size())
|
||||
return force_.size();
|
||||
else
|
||||
return bits4_.size();
|
||||
return bits4_.size();
|
||||
}
|
||||
|
||||
vvp_bit4_t vvp_fun_signal4_sa::value(unsigned idx) const
|
||||
{
|
||||
if (force_mask_.size() && force_mask_.value(idx)) {
|
||||
return force_.value(idx);
|
||||
} else {
|
||||
return bits4_.value(idx);
|
||||
}
|
||||
return filtered_value(bits4_, idx);
|
||||
}
|
||||
|
||||
vvp_scalar_t vvp_fun_signal4_sa::scalar_value(unsigned idx) const
|
||||
{
|
||||
if (force_mask_.size() && force_mask_.value(idx)) {
|
||||
return vvp_scalar_t(force_.value(idx), 6, 6);
|
||||
} else {
|
||||
return vvp_scalar_t(bits4_.value(idx), 6, 6);
|
||||
}
|
||||
return vvp_scalar_t(value(idx), 6, 6);
|
||||
}
|
||||
|
||||
vvp_vector4_t vvp_fun_signal4_sa::vec4_value() const
|
||||
{
|
||||
if (force_mask_.size()) {
|
||||
assert(bits4_.size() == force_mask_.size());
|
||||
assert(bits4_.size() == force_.size());
|
||||
vvp_vector4_t bits (bits4_);
|
||||
for (unsigned idx = 0 ; idx < bits.size() ; idx += 1) {
|
||||
if (force_mask_.value(idx))
|
||||
bits.set_bit(idx, force_.value(idx));
|
||||
}
|
||||
return bits;
|
||||
} else {
|
||||
return bits4_;
|
||||
}
|
||||
return filtered_vec4(bits4_);
|
||||
}
|
||||
|
||||
vvp_fun_signal4_aa::vvp_fun_signal4_aa(unsigned wid, vvp_bit4_t init)
|
||||
|
|
@ -532,17 +671,22 @@ void vvp_fun_signal8::recv_vec8(vvp_net_ptr_t ptr, const vvp_vector8_t&bit)
|
|||
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 (bit.size() != size())
|
||||
force_ = coerce_to_width(bit, size());
|
||||
else
|
||||
force_ = 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_mask_ = vvp_vector2_t(vvp_vector2_t::FILL1, size());
|
||||
calculate_output_(ptr);
|
||||
break;
|
||||
// Propagate the forced value before setting the
|
||||
// force mask. This is so that the forced value gets
|
||||
// out to the network before the force filter is set
|
||||
// up. If the force filter is set up first, then the
|
||||
// filter will block the exact match.
|
||||
ptr.ptr()->send_vec8(tmp);
|
||||
force_vec8(tmp, vvp_vector2_t(vvp_vector2_t::FILL1,tmp.size()));
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "Unsupported port type %d.\n", ptr.port());
|
||||
|
|
@ -582,19 +726,16 @@ void vvp_fun_signal8::recv_vec8_pv(vvp_net_ptr_t ptr, const vvp_vector8_t&bit,
|
|||
break;
|
||||
|
||||
case 2: // Force value
|
||||
|
||||
if (force_mask_.size() == 0)
|
||||
force_mask_ = vvp_vector2_t(vvp_vector2_t::FILL0, size());
|
||||
if (force_.size() == 0)
|
||||
force_ = vvp_vector8_t(vvp_vector4_t(vwid, BIT4_Z),6,6);
|
||||
|
||||
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
|
||||
force_mask_.set_bit(base+idx, 1);
|
||||
force_.set_bit(base+idx, bit.value(idx));
|
||||
}
|
||||
|
||||
calculate_output_(ptr);
|
||||
break;
|
||||
{ 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;
|
||||
}
|
||||
|
||||
default:
|
||||
fprintf(stderr, "Unsupported port type %d.\n", ptr.port());
|
||||
|
|
@ -605,28 +746,22 @@ void vvp_fun_signal8::recv_vec8_pv(vvp_net_ptr_t ptr, const vvp_vector8_t&bit,
|
|||
|
||||
void vvp_fun_signal8::calculate_output_(vvp_net_ptr_t ptr)
|
||||
{
|
||||
if (force_mask_.size()) {
|
||||
assert(bits8_.size() == force_mask_.size());
|
||||
assert(bits8_.size() == force_.size());
|
||||
vvp_vector8_t bits (bits8_);
|
||||
for (unsigned idx = 0 ; idx < bits.size() ; idx += 1) {
|
||||
if (force_mask_.value(idx))
|
||||
bits.set_bit(idx, force_.value(idx));
|
||||
}
|
||||
ptr.ptr()->send_vec8(bits);
|
||||
|
||||
} else {
|
||||
ptr.ptr()->send_vec8(bits8_);
|
||||
}
|
||||
ptr.ptr()->send_vec8(bits8_);
|
||||
}
|
||||
|
||||
void vvp_fun_signal8::release(vvp_net_ptr_t ptr, bool net)
|
||||
{
|
||||
force_mask_ = vvp_vector2_t();
|
||||
vvp_vector2_t mask (vvp_vector2_t::FILL1, bits8_.size());
|
||||
|
||||
if (net) {
|
||||
// If releasing a net, then the output should revert to
|
||||
// the un-forced value.
|
||||
release_mask(mask);
|
||||
ptr.ptr()->send_vec8(bits8_);
|
||||
} else {
|
||||
bits8_ = force_;
|
||||
// Variables keep their forced value after the release.
|
||||
bits8_ = filtered_vec8(bits8_);
|
||||
release_mask(mask);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -635,50 +770,37 @@ void vvp_fun_signal8::release_pv(vvp_net_ptr_t ptr, bool net,
|
|||
{
|
||||
assert(bits8_.size() >= base + wid);
|
||||
|
||||
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
|
||||
force_mask_.set_bit(base+idx, 0);
|
||||
if (!net) bits8_.set_bit(base+idx, force_.value(base+idx));
|
||||
}
|
||||
if (force_mask_.is_zero()) force_mask_ = vvp_vector2_t();
|
||||
vvp_vector2_t mask (vvp_vector2_t::FILL0, bits8_.size());
|
||||
for (unsigned idx = 0 ; idx < wid ; idx += 1)
|
||||
mask.set_bit(base+idx, 1);
|
||||
|
||||
if (net) calculate_output_(ptr);
|
||||
if (net) {
|
||||
release_mask(mask);
|
||||
calculate_output_(ptr);
|
||||
} else {
|
||||
bits8_ = filtered_vec8(bits8_);
|
||||
release_mask(mask);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned vvp_fun_signal8::size() const
|
||||
{
|
||||
if (force_mask_.size())
|
||||
return force_.size();
|
||||
else
|
||||
return bits8_.size();
|
||||
return bits8_.size();
|
||||
}
|
||||
|
||||
vvp_bit4_t vvp_fun_signal8::value(unsigned idx) const
|
||||
{
|
||||
if (force_mask_.size() && force_mask_.value(idx))
|
||||
return force_.value(idx).value();
|
||||
else
|
||||
return bits8_.value(idx).value();
|
||||
return filtered_value(bits8_, idx).value();
|
||||
}
|
||||
|
||||
vvp_vector4_t vvp_fun_signal8::vec4_value() const
|
||||
{
|
||||
if (force_mask_.size()) {
|
||||
vvp_vector8_t bits (bits8_);
|
||||
for (unsigned idx = 0 ; idx < bits.size() ; idx += 1) {
|
||||
if (force_mask_.value(idx))
|
||||
bits.set_bit(idx, force_.value(idx));
|
||||
}
|
||||
return reduce4(bits);
|
||||
} else
|
||||
return reduce4(bits8_);
|
||||
return reduce4(filtered_vec8(bits8_));
|
||||
}
|
||||
|
||||
vvp_scalar_t vvp_fun_signal8::scalar_value(unsigned idx) const
|
||||
{
|
||||
if (force_mask_.size() && force_mask_.value(idx))
|
||||
return force_.value(idx);
|
||||
else
|
||||
return bits8_.value(idx);
|
||||
return filtered_value(bits8_, idx);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -699,10 +821,7 @@ vvp_fun_signal_real_sa::vvp_fun_signal_real_sa()
|
|||
|
||||
double vvp_fun_signal_real_sa::real_value() const
|
||||
{
|
||||
if (force_mask_.size())
|
||||
return force_;
|
||||
else
|
||||
return bits_;
|
||||
return filtered_real(bits_);
|
||||
}
|
||||
|
||||
void vvp_fun_signal_real_sa::recv_real(vvp_net_ptr_t ptr, double bit,
|
||||
|
|
@ -726,8 +845,7 @@ void vvp_fun_signal_real_sa::recv_real(vvp_net_ptr_t ptr, double bit,
|
|||
break;
|
||||
|
||||
case 2: // Force value
|
||||
force_mask_ = vvp_vector2_t(1, 1);
|
||||
force_ = bit;
|
||||
force_real(bit, vvp_vector2_t(vvp_vector2_t::FILL1, 1));
|
||||
ptr.ptr()->send_real(bit, 0);
|
||||
break;
|
||||
|
||||
|
|
@ -740,11 +858,14 @@ void vvp_fun_signal_real_sa::recv_real(vvp_net_ptr_t ptr, double bit,
|
|||
|
||||
void vvp_fun_signal_real_sa::release(vvp_net_ptr_t ptr, bool net)
|
||||
{
|
||||
force_mask_ = vvp_vector2_t();
|
||||
vvp_vector2_t mask (vvp_vector2_t::FILL1, 1);
|
||||
|
||||
if (net) {
|
||||
release_mask(mask);
|
||||
ptr.ptr()->send_real(bits_, 0);
|
||||
} else {
|
||||
bits_ = force_;
|
||||
bits_ = filtered_real(bits_);
|
||||
release_mask(mask);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -134,23 +134,51 @@ class vvp_filter_wire_base : public vvp_net_fil_t, public vvp_vpi_callback {
|
|||
vvp_filter_wire_base();
|
||||
~vvp_filter_wire_base();
|
||||
|
||||
bool filter_vec4(const vvp_vector4_t&val);
|
||||
bool filter_vec8(const vvp_vector8_t&val);
|
||||
bool filter_real(double val);
|
||||
bool filter_long(long val);
|
||||
// These are the virtual methods that we implement to perform
|
||||
// the wire-style filtering.
|
||||
const vvp_vector4_t* filter_vec4(const vvp_vector4_t&val);
|
||||
const vvp_vector8_t* filter_vec8(const vvp_vector8_t&val);
|
||||
bool filter_real(double&val);
|
||||
bool filter_long(long&val);
|
||||
|
||||
public:
|
||||
void deassign();
|
||||
void deassign_pv(unsigned base, unsigned wid);
|
||||
// Force/release work in the filter by setting the forced
|
||||
// value using one of the force_* methods. This sets the
|
||||
// forced value as a mask of the bits of the vector that are
|
||||
// forced. The filter then automatically runs the filter on
|
||||
// the outputs that pass through. You can also get at the
|
||||
// filtering results using the filtered_* methods. The
|
||||
// release_mask() method releases bits of the vector.
|
||||
|
||||
// Enable filter force.
|
||||
void force_vec4(const vvp_vector4_t&val, vvp_vector2_t mask);
|
||||
void force_vec8(const vvp_vector8_t&val, vvp_vector2_t mask);
|
||||
void force_real(double val, vvp_vector2_t mask);
|
||||
|
||||
// Test the value against the filter.
|
||||
vvp_bit4_t filtered_value(const vvp_vector4_t&val, unsigned idx) const;
|
||||
vvp_scalar_t filtered_value(const vvp_vector8_t&val, unsigned idx) const;
|
||||
|
||||
const vvp_vector4_t& filtered_vec4(const vvp_vector4_t&val) const;
|
||||
const vvp_vector8_t& filtered_vec8(const vvp_vector8_t&val) const;
|
||||
double filtered_real(double val) const;
|
||||
|
||||
// Release the force on the bits set in the mask.
|
||||
void release_mask(vvp_vector2_t mask);
|
||||
|
||||
virtual void release(vvp_net_ptr_t ptr, bool net) =0;
|
||||
virtual void release_pv(vvp_net_ptr_t ptr, bool net,
|
||||
unsigned base, unsigned wid) =0;
|
||||
|
||||
protected:
|
||||
bool continuous_assign_active_;
|
||||
private:
|
||||
// Forced value
|
||||
vvp_vector2_t force_mask_;
|
||||
vvp_vector2_t assign_mask_;
|
||||
|
||||
vvp_vector4_t force4_;
|
||||
vvp_vector8_t force8_;
|
||||
double force_real_;
|
||||
// This is used as a static return value.
|
||||
mutable vvp_vector4_t filter4_;
|
||||
mutable vvp_vector8_t filter8_;
|
||||
};
|
||||
|
||||
class vvp_fun_signal_base : public vvp_net_fun_t, public vvp_filter_wire_base {
|
||||
|
|
@ -161,6 +189,9 @@ class vvp_fun_signal_base : public vvp_net_fun_t, public vvp_filter_wire_base {
|
|||
void recv_long_pv(vvp_net_ptr_t port, long bit,
|
||||
unsigned base, unsigned wid);
|
||||
|
||||
void deassign();
|
||||
void deassign_pv(unsigned base, unsigned wid);
|
||||
|
||||
public:
|
||||
|
||||
/* The %force/link instruction needs a place to write the
|
||||
|
|
@ -169,6 +200,10 @@ class vvp_fun_signal_base : public vvp_net_fun_t, public vvp_filter_wire_base {
|
|||
struct vvp_net_t*force_link;
|
||||
struct vvp_net_t*cassign_link;
|
||||
|
||||
protected:
|
||||
bool continuous_assign_active_;
|
||||
vvp_vector2_t assign_mask_;
|
||||
|
||||
protected:
|
||||
|
||||
// This is true until at least one propagation happens.
|
||||
|
|
@ -232,7 +267,6 @@ class vvp_fun_signal4_sa : public vvp_fun_signal4 {
|
|||
void calculate_output_(vvp_net_ptr_t ptr);
|
||||
|
||||
vvp_vector4_t bits4_;
|
||||
vvp_vector4_t force_;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
|||
Loading…
Reference in New Issue