Collapse vvp_filter_wire_base into vvp_net_fil_t.
The vvp_filter_wire_base class was not really used, and by collapsing into vvp_net_fil_t some casts are eliminated.
This commit is contained in:
parent
1940de0110
commit
7df9d60761
|
|
@ -2311,11 +2311,8 @@ bool of_FORCE_LINK(vthread_t thr, vvp_code_t cp)
|
||||||
vvp_net_t*dst = cp->net;
|
vvp_net_t*dst = cp->net;
|
||||||
vvp_net_t*src = cp->net2;
|
vvp_net_t*src = cp->net2;
|
||||||
|
|
||||||
vvp_filter_wire_base*sig
|
assert(dst->fil);
|
||||||
= dynamic_cast<vvp_filter_wire_base*>(dst->fun);
|
dst->fil->force_link(dst, src);
|
||||||
assert(sig);
|
|
||||||
|
|
||||||
sig->force_link(dst, src);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -3936,6 +3933,7 @@ bool of_RELEASE_NET(vthread_t thr, vvp_code_t cp)
|
||||||
|
|
||||||
vvp_fun_signal_vec*sig = reinterpret_cast<vvp_fun_signal_vec*>(net->fun);
|
vvp_fun_signal_vec*sig = reinterpret_cast<vvp_fun_signal_vec*>(net->fun);
|
||||||
assert(sig);
|
assert(sig);
|
||||||
|
assert(net->fil);
|
||||||
|
|
||||||
if (base >= sig->size()) return true;
|
if (base >= sig->size()) return true;
|
||||||
if (base+width > sig->size()) width = sig->size() - base;
|
if (base+width > sig->size()) width = sig->size() - base;
|
||||||
|
|
@ -3943,14 +3941,14 @@ bool of_RELEASE_NET(vthread_t thr, vvp_code_t cp)
|
||||||
bool full_sig = base == 0 && width == sig->size();
|
bool full_sig = base == 0 && width == sig->size();
|
||||||
|
|
||||||
// XXXX Can't really do this if this is a partial release?
|
// XXXX Can't really do this if this is a partial release?
|
||||||
sig->force_unlink();
|
net->fil->force_unlink();
|
||||||
|
|
||||||
/* Do we release all or part of the net? */
|
/* Do we release all or part of the net? */
|
||||||
vvp_net_ptr_t ptr (net, 0);
|
vvp_net_ptr_t ptr (net, 0);
|
||||||
if (full_sig) {
|
if (full_sig) {
|
||||||
sig->release(ptr, true);
|
net->fil->release(ptr, true);
|
||||||
} else {
|
} else {
|
||||||
sig->release_pv(ptr, true, base, width);
|
net->fil->release_pv(ptr, true, base, width);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -3965,6 +3963,7 @@ bool of_RELEASE_REG(vthread_t thr, vvp_code_t cp)
|
||||||
|
|
||||||
vvp_fun_signal_vec*sig = reinterpret_cast<vvp_fun_signal_vec*>(net->fun);
|
vvp_fun_signal_vec*sig = reinterpret_cast<vvp_fun_signal_vec*>(net->fun);
|
||||||
assert(sig);
|
assert(sig);
|
||||||
|
assert(net->fil);
|
||||||
|
|
||||||
if (base >= sig->size()) return true;
|
if (base >= sig->size()) return true;
|
||||||
if (base+width > sig->size()) width = sig->size() - base;
|
if (base+width > sig->size()) width = sig->size() - base;
|
||||||
|
|
@ -3972,15 +3971,15 @@ bool of_RELEASE_REG(vthread_t thr, vvp_code_t cp)
|
||||||
bool full_sig = base == 0 && width == sig->size();
|
bool full_sig = base == 0 && width == sig->size();
|
||||||
|
|
||||||
// XXXX Can't really do this if this is a partial release?
|
// XXXX Can't really do this if this is a partial release?
|
||||||
sig->force_unlink();
|
net->fil->force_unlink();
|
||||||
|
|
||||||
// Send a command to this signal to unforce itself.
|
// Send a command to this signal to unforce itself.
|
||||||
/* Do we release all or part of the net? */
|
/* Do we release all or part of the net? */
|
||||||
vvp_net_ptr_t ptr (net, 0);
|
vvp_net_ptr_t ptr (net, 0);
|
||||||
if (full_sig) {
|
if (full_sig) {
|
||||||
sig->release(ptr, false);
|
net->fil->release(ptr, false);
|
||||||
} else {
|
} else {
|
||||||
sig->release_pv(ptr, false, base, width);
|
net->fil->release_pv(ptr, false, base, width);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -3992,14 +3991,12 @@ bool of_RELEASE_WR(vthread_t thr, vvp_code_t cp)
|
||||||
vvp_net_t*net = cp->net;
|
vvp_net_t*net = cp->net;
|
||||||
unsigned type = cp->bit_idx[0];
|
unsigned type = cp->bit_idx[0];
|
||||||
|
|
||||||
vvp_fun_signal_real*sig = reinterpret_cast<vvp_fun_signal_real*>(net->fun);
|
assert(net->fil);
|
||||||
assert(sig);
|
net->fil->force_unlink();
|
||||||
|
|
||||||
sig->force_unlink();
|
|
||||||
|
|
||||||
// Send a command to this signal to unforce itself.
|
// Send a command to this signal to unforce itself.
|
||||||
vvp_net_ptr_t ptr (net, 0);
|
vvp_net_ptr_t ptr (net, 0);
|
||||||
sig->release(ptr, type==0);
|
net->fil->release(ptr, type==0);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -194,12 +194,16 @@ void vvp_net_fun_t::operator delete(void*)
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
vvp_net_fil_t::vvp_net_fil_t()
|
vvp_net_fil_t::vvp_net_fil_t()
|
||||||
{
|
{
|
||||||
|
force_link_ = 0;
|
||||||
|
force_propagate_ = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
vvp_net_fil_t::~vvp_net_fil_t()
|
vvp_net_fil_t::~vvp_net_fil_t()
|
||||||
{
|
{
|
||||||
|
assert(force_link_ == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
const vvp_vector4_t* vvp_net_fil_t::filter_vec4(const vvp_vector4_t&val)
|
const vvp_vector4_t* vvp_net_fil_t::filter_vec4(const vvp_vector4_t&val)
|
||||||
|
|
@ -222,6 +226,81 @@ bool vvp_net_fil_t::filter_long(long&)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void vvp_net_fil_t::force_mask(vvp_vector2_t mask)
|
||||||
|
{
|
||||||
|
if (force_mask_.size() == 0)
|
||||||
|
force_mask_ = vvp_vector2_t(vvp_vector2_t::FILL0, mask.size());
|
||||||
|
|
||||||
|
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);
|
||||||
|
force_propagate_ = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void vvp_net_fil_t::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();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Force link/unlink uses a thunk vvp_net_t node with a vvp_fun_force
|
||||||
|
* functor to translate the net values to filter commands. The ports
|
||||||
|
* of this vvp_net_t object are use a little differently:
|
||||||
|
*
|
||||||
|
* port[3] - Point to the destination node where the forced
|
||||||
|
* filter resides.
|
||||||
|
*
|
||||||
|
* port[2] - Point to the input node that drives port[0] for use
|
||||||
|
* by the unlink method.
|
||||||
|
*
|
||||||
|
* port[0] - This is the normal input.
|
||||||
|
*/
|
||||||
|
void vvp_net_fil_t::force_link(vvp_net_t*dst, vvp_net_t*src)
|
||||||
|
{
|
||||||
|
assert(dst->fil == this);
|
||||||
|
|
||||||
|
if (force_link_ == 0) {
|
||||||
|
force_link_ = new vvp_net_t;
|
||||||
|
// Use port[3] to hold the force destination.
|
||||||
|
force_link_->port[3] = vvp_net_ptr_t(dst, 0);
|
||||||
|
force_link_->port[2] = vvp_net_ptr_t(0,0);
|
||||||
|
force_link_->fun = new vvp_fun_force;
|
||||||
|
}
|
||||||
|
|
||||||
|
force_unlink();
|
||||||
|
assert(force_link_->port[2] == vvp_net_ptr_t(0,0));
|
||||||
|
|
||||||
|
// Use port[2] to hold the force source.
|
||||||
|
force_link_->port[2] = vvp_net_ptr_t(src,0);
|
||||||
|
|
||||||
|
vvp_net_ptr_t dst_ptr(force_link_, 0);
|
||||||
|
src->link(dst_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void vvp_net_fil_t::force_unlink(void)
|
||||||
|
{
|
||||||
|
if (force_link_ == 0) return;
|
||||||
|
vvp_net_t*src = force_link_->port[2].ptr();
|
||||||
|
if (src == 0) return;
|
||||||
|
|
||||||
|
src->unlink(vvp_net_ptr_t(force_link_,0));
|
||||||
|
force_link_->port[2] = vvp_net_ptr_t(0,0);
|
||||||
|
}
|
||||||
|
|
||||||
/* *** BIT operations *** */
|
/* *** BIT operations *** */
|
||||||
vvp_bit4_t add_with_carry(vvp_bit4_t a, vvp_bit4_t b, vvp_bit4_t&c)
|
vvp_bit4_t add_with_carry(vvp_bit4_t a, vvp_bit4_t b, vvp_bit4_t&c)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@
|
||||||
|
|
||||||
# include "config.h"
|
# include "config.h"
|
||||||
# include "vpi_user.h"
|
# include "vpi_user.h"
|
||||||
|
# include "vvp_vpi_callback.h"
|
||||||
# include <stddef.h>
|
# include <stddef.h>
|
||||||
# include <stdlib.h>
|
# include <stdlib.h>
|
||||||
# include <string.h>
|
# include <string.h>
|
||||||
|
|
@ -1097,10 +1098,10 @@ class vvp_net_fun_t {
|
||||||
* false. If false, then send_*() continues as usual. If false, output
|
* false. If false, then send_*() continues as usual. If false, output
|
||||||
* propagation is stopped.
|
* propagation is stopped.
|
||||||
*
|
*
|
||||||
* The filter object can be used to implement force/release, and also
|
* The filter object also provides an implementation hooks for
|
||||||
* can be used to implement vpi net object.
|
* force/release.
|
||||||
*/
|
*/
|
||||||
class vvp_net_fil_t {
|
class vvp_net_fil_t : public vvp_vpi_callback {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
vvp_net_fil_t();
|
vvp_net_fil_t();
|
||||||
|
|
@ -1117,6 +1118,37 @@ class vvp_net_fil_t {
|
||||||
// propagation is suppressed. The value may be edited by the filter.
|
// propagation is suppressed. The value may be edited by the filter.
|
||||||
virtual bool filter_real(double&val);
|
virtual bool filter_real(double&val);
|
||||||
virtual bool filter_long(long&val);
|
virtual bool filter_long(long&val);
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
// The %force/link instruction needs a place to write the
|
||||||
|
// source node of the force, so that subsequent %force and
|
||||||
|
// %release instructions can undo the link as needed. */
|
||||||
|
void force_link(vvp_net_t*dst, vvp_net_t*src);
|
||||||
|
void force_unlink(void);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// Set bits of the filter force mask
|
||||||
|
void force_mask(vvp_vector2_t mask);
|
||||||
|
// Release the force on the bits set in the mask.
|
||||||
|
void release_mask(vvp_vector2_t mask);
|
||||||
|
// Test bits of the filter force mask;
|
||||||
|
bool test_force_mask(unsigned bit) const;
|
||||||
|
bool test_force_mask_is_zero() const;
|
||||||
|
|
||||||
|
template <class T> const T*filter_mask_(const T&val, const T&force, T&buf);
|
||||||
|
template <class T> bool filter_mask_(T&val);
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Mask of forced bits
|
||||||
|
vvp_vector2_t force_mask_;
|
||||||
|
// True if the next filter must propagate. Need this to allow
|
||||||
|
// the forced value to get through.
|
||||||
|
bool force_propagate_;
|
||||||
|
// force link back.
|
||||||
|
struct vvp_net_t*force_link_;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* **** Some core net functions **** */
|
/* **** Some core net functions **** */
|
||||||
|
|
@ -1147,6 +1179,27 @@ class vvp_fun_concat : public vvp_net_fun_t {
|
||||||
vvp_vector4_t val_;
|
vvp_vector4_t val_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The vvp_fun_force class objects are net functors that use their input
|
||||||
|
* to force the associated filter. They do not actually have an
|
||||||
|
* output, they instead drive the force_* methods of the net filter.
|
||||||
|
*
|
||||||
|
* This functor is also special in that we know a priori that only
|
||||||
|
* port-0 is used, so we can use ports 1-3 for local storage. See the
|
||||||
|
* implementation of vvp_filter_wire_base::force_link in
|
||||||
|
* vvp_net_sig.cc for details.
|
||||||
|
*/
|
||||||
|
class vvp_fun_force : public vvp_net_fun_t {
|
||||||
|
|
||||||
|
public:
|
||||||
|
vvp_fun_force();
|
||||||
|
~vvp_fun_force();
|
||||||
|
|
||||||
|
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||||
|
vvp_context_t context);
|
||||||
|
void recv_real(vvp_net_ptr_t port, double bit, vvp_context_t);
|
||||||
|
};
|
||||||
|
|
||||||
/* vvp_fun_repeat
|
/* vvp_fun_repeat
|
||||||
* This node function create vectors by repeating the input. The width
|
* This node function create vectors by repeating the input. The width
|
||||||
* is the width of the output vector, and the repeat is the number of
|
* is the width of the output vector, and the repeat is the number of
|
||||||
|
|
@ -1391,4 +1444,24 @@ inline void vvp_net_t::send_real(double val, vvp_context_t context)
|
||||||
vvp_send_real(out_, val, context);
|
vvp_send_real(out_, val, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline bool vvp_net_fil_t::test_force_mask(unsigned bit) const
|
||||||
|
{
|
||||||
|
if (bit >= force_mask_.size())
|
||||||
|
return false;
|
||||||
|
if (force_mask_.value(bit))
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool vvp_net_fil_t::test_force_mask_is_zero(void) const
|
||||||
|
{
|
||||||
|
if (force_mask_.size() == 0)
|
||||||
|
return true;
|
||||||
|
if (force_mask_.is_zero())
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -30,20 +30,9 @@
|
||||||
|
|
||||||
# include <iostream>
|
# include <iostream>
|
||||||
|
|
||||||
vvp_filter_wire_base::vvp_filter_wire_base()
|
template <class T> const T*vvp_net_fil_t::filter_mask_(const T&val, const T&force, T&filter)
|
||||||
{
|
{
|
||||||
force_propagate_ = false;
|
if (!test_force_mask_is_zero()) {
|
||||||
force_link_ = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
vvp_filter_wire_base::~vvp_filter_wire_base()
|
|
||||||
{
|
|
||||||
assert(force_link_ == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T> const T*vvp_filter_wire_base::filter_mask_(const T&val, const T&force, T&filter)
|
|
||||||
{
|
|
||||||
if (force_mask_.size()) {
|
|
||||||
bool propagate_flag = force_propagate_;
|
bool propagate_flag = force_propagate_;
|
||||||
force_propagate_ = false;
|
force_propagate_ = false;
|
||||||
assert(val.size() == force_mask_.size());
|
assert(val.size() == force_mask_.size());
|
||||||
|
|
@ -70,52 +59,7 @@ template <class T> const T*vvp_filter_wire_base::filter_mask_(const T&val, const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
template <class T> bool vvp_net_fil_t::filter_mask_(T&val)
|
||||||
* Force link/unlink uses a thunk vvp_net_t node with a vvp_fun_force
|
|
||||||
* functor to translate the net values to filter commands. The ports
|
|
||||||
* of this vvp_net_t object are use a little differently:
|
|
||||||
*
|
|
||||||
* port[3] - Point to the destination node where the forced
|
|
||||||
* filter resides.
|
|
||||||
*
|
|
||||||
* port[2] - Point to the input node that drives port[0] for use
|
|
||||||
* by the unlink method.
|
|
||||||
*
|
|
||||||
* port[0] - This is the normal input.
|
|
||||||
*/
|
|
||||||
void vvp_filter_wire_base::force_link(vvp_net_t*dst, vvp_net_t*src)
|
|
||||||
{
|
|
||||||
assert(dst->fil == this);
|
|
||||||
|
|
||||||
if (force_link_ == 0) {
|
|
||||||
force_link_ = new vvp_net_t;
|
|
||||||
// Use port[3] to hold the force destination.
|
|
||||||
force_link_->port[3] = vvp_net_ptr_t(dst, 0);
|
|
||||||
force_link_->port[2] = vvp_net_ptr_t(0,0);
|
|
||||||
force_link_->fun = new vvp_fun_force;
|
|
||||||
}
|
|
||||||
|
|
||||||
force_unlink();
|
|
||||||
assert(force_link_->port[2] == vvp_net_ptr_t(0,0));
|
|
||||||
|
|
||||||
// Use port[2] to hold the force source.
|
|
||||||
force_link_->port[2] = vvp_net_ptr_t(src,0);
|
|
||||||
|
|
||||||
vvp_net_ptr_t dst_ptr(force_link_, 0);
|
|
||||||
src->link(dst_ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void vvp_filter_wire_base::force_unlink(void)
|
|
||||||
{
|
|
||||||
if (force_link_ == 0) return;
|
|
||||||
vvp_net_t*src = force_link_->port[2].ptr();
|
|
||||||
if (src == 0) return;
|
|
||||||
|
|
||||||
src->unlink(vvp_net_ptr_t(force_link_,0));
|
|
||||||
force_link_->port[2] = vvp_net_ptr_t(0,0);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T> bool vvp_filter_wire_base::filter_mask_(T&val)
|
|
||||||
{
|
{
|
||||||
run_vpi_callbacks();
|
run_vpi_callbacks();
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -136,11 +80,6 @@ bool vvp_fun_signal_real::filter_real(double&val)
|
||||||
return filter_mask_(val);
|
return filter_mask_(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool vvp_filter_wire_base::filter_long(long&val)
|
|
||||||
{
|
|
||||||
return filter_mask_(val);
|
|
||||||
}
|
|
||||||
|
|
||||||
void vvp_fun_signal4::force_fil_vec4(const vvp_vector4_t&val, vvp_vector2_t mask)
|
void vvp_fun_signal4::force_fil_vec4(const vvp_vector4_t&val, vvp_vector2_t mask)
|
||||||
{
|
{
|
||||||
force_mask(mask);
|
force_mask(mask);
|
||||||
|
|
@ -255,36 +194,6 @@ double vvp_fun_signal_real::filtered_real(double val) const
|
||||||
return force_real_;
|
return force_real_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void vvp_filter_wire_base::force_mask(vvp_vector2_t mask)
|
|
||||||
{
|
|
||||||
if (force_mask_.size() == 0)
|
|
||||||
force_mask_ = vvp_vector2_t(vvp_vector2_t::FILL0, mask.size());
|
|
||||||
|
|
||||||
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);
|
|
||||||
force_propagate_ = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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 methods **** */
|
||||||
|
|
||||||
vvp_fun_signal_base::vvp_fun_signal_base()
|
vvp_fun_signal_base::vvp_fun_signal_base()
|
||||||
|
|
|
||||||
|
|
@ -36,43 +36,6 @@ class ostream;
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
/*
|
|
||||||
* Things derived from vvp_vpi_callback may have callbacks
|
|
||||||
* attached. This is how vpi callbacks are attached to the vvp
|
|
||||||
* structure.
|
|
||||||
*
|
|
||||||
* Things derived from vvp_vpi_callback may also be array'ed, so it
|
|
||||||
* includes some members that arrays use.
|
|
||||||
*/
|
|
||||||
class vvp_vpi_callback {
|
|
||||||
|
|
||||||
public:
|
|
||||||
vvp_vpi_callback();
|
|
||||||
virtual ~vvp_vpi_callback();
|
|
||||||
|
|
||||||
void attach_as_word(class __vpiArray* arr, unsigned long addr);
|
|
||||||
|
|
||||||
void add_vpi_callback(struct __vpiCallback*);
|
|
||||||
#ifdef CHECK_WITH_VALGRIND
|
|
||||||
/* This has only been tested at EOS. */
|
|
||||||
void clear_all_callbacks(void);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Derived classes implement this method to provide a way for
|
|
||||||
// vpi to get at the vvp value of the object.
|
|
||||||
virtual void get_value(struct t_vpi_value*value) =0;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
// Derived classes call this method to indicate that it is
|
|
||||||
// time to call the callback.
|
|
||||||
void run_vpi_callbacks();
|
|
||||||
|
|
||||||
private:
|
|
||||||
struct __vpiCallback*vpi_callbacks_;
|
|
||||||
class __vpiArray* array_;
|
|
||||||
unsigned long array_word_;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* vvp_fun_signal
|
/* vvp_fun_signal
|
||||||
* This node is the place holder in a vvp network for signals,
|
* This node is the place holder in a vvp network for signals,
|
||||||
* including nets of various sort. The output from a signal follows
|
* including nets of various sort. The output from a signal follows
|
||||||
|
|
@ -128,78 +91,7 @@ class vvp_vpi_callback {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
class vvp_filter_wire_base : public vvp_net_fil_t, public vvp_vpi_callback {
|
class vvp_fun_signal_base : public vvp_net_fun_t, public vvp_net_fil_t {
|
||||||
|
|
||||||
public:
|
|
||||||
vvp_filter_wire_base();
|
|
||||||
~vvp_filter_wire_base();
|
|
||||||
|
|
||||||
// The filter_long is a placeholder here. This should be moved
|
|
||||||
// to a vvp_fun_signal_long when such a thing is implemented.
|
|
||||||
bool filter_long(long&val);
|
|
||||||
|
|
||||||
public:
|
|
||||||
// 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.
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
/* The %force/link instruction needs a place to write the
|
|
||||||
source node of the force, so that subsequent %force and
|
|
||||||
%release instructions can undo the link as needed. */
|
|
||||||
void force_link(vvp_net_t*dst, vvp_net_t*src);
|
|
||||||
void force_unlink(void);
|
|
||||||
|
|
||||||
private:
|
|
||||||
struct vvp_net_t*force_link_;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
// Set bits of the filter force mask
|
|
||||||
void force_mask(vvp_vector2_t mask);
|
|
||||||
// Release the force on the bits set in the mask.
|
|
||||||
void release_mask(vvp_vector2_t mask);
|
|
||||||
// Test bits of the filter force mask;
|
|
||||||
bool test_force_mask(unsigned bit) const;
|
|
||||||
bool test_force_mask_is_zero() const;
|
|
||||||
|
|
||||||
template <class T> const T*filter_mask_(const T&val, const T&force, T&buf);
|
|
||||||
template <class T> bool filter_mask_(T&val);
|
|
||||||
|
|
||||||
private:
|
|
||||||
// Forced value
|
|
||||||
vvp_vector2_t force_mask_;
|
|
||||||
// True if the next filter must propagate. Need this to allow
|
|
||||||
// the forced value to get through.
|
|
||||||
bool force_propagate_;
|
|
||||||
};
|
|
||||||
|
|
||||||
inline bool vvp_filter_wire_base::test_force_mask(unsigned bit) const
|
|
||||||
{
|
|
||||||
if (bit >= force_mask_.size())
|
|
||||||
return false;
|
|
||||||
if (force_mask_.value(bit))
|
|
||||||
return true;
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool vvp_filter_wire_base::test_force_mask_is_zero(void) const
|
|
||||||
{
|
|
||||||
if (force_mask_.size() == 0)
|
|
||||||
return true;
|
|
||||||
if (force_mask_.is_zero())
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
class vvp_fun_signal_base : public vvp_net_fun_t, public vvp_filter_wire_base {
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
vvp_fun_signal_base();
|
vvp_fun_signal_base();
|
||||||
|
|
@ -449,26 +341,4 @@ class vvp_fun_signal_real_aa : public vvp_fun_signal_real, public automatic_hook
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The vvp_fun_force class objects are net functors that use their input
|
|
||||||
* to force the associated filter. They do not actually have an
|
|
||||||
* output, they instead drive the force_* methods of the net filter.
|
|
||||||
*
|
|
||||||
* This functor is also special in that we know a priori that only
|
|
||||||
* port-0 is used, so we can use ports 1-3 for local storage. See the
|
|
||||||
* implementation of vvp_filter_wire_base::force_link in
|
|
||||||
* vvp_net_sig.cc for details.
|
|
||||||
*/
|
|
||||||
class vvp_fun_force : public vvp_net_fun_t {
|
|
||||||
|
|
||||||
public:
|
|
||||||
vvp_fun_force();
|
|
||||||
~vvp_fun_force();
|
|
||||||
|
|
||||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
|
||||||
vvp_context_t context);
|
|
||||||
void recv_real(vvp_net_ptr_t port, double bit, vvp_context_t);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,63 @@
|
||||||
|
#ifndef __vvp_vpi_callback_H
|
||||||
|
#define __vvp_vpi_callback_H
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2009 Stephen Williams (steve@icarus.com)
|
||||||
|
*
|
||||||
|
* This source code is free software; you can redistribute it
|
||||||
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
* General Public License as published by the Free Software
|
||||||
|
* Foundation; either version 2 of the License, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
# include "config.h"
|
||||||
|
# include "vpi_user.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Things derived from vvp_vpi_callback may have callbacks
|
||||||
|
* attached. This is how vpi callbacks are attached to the vvp
|
||||||
|
* structure.
|
||||||
|
*
|
||||||
|
* Things derived from vvp_vpi_callback may also be array'ed, so it
|
||||||
|
* includes some members that arrays use.
|
||||||
|
*/
|
||||||
|
class vvp_vpi_callback {
|
||||||
|
|
||||||
|
public:
|
||||||
|
vvp_vpi_callback();
|
||||||
|
virtual ~vvp_vpi_callback();
|
||||||
|
|
||||||
|
void attach_as_word(class __vpiArray* arr, unsigned long addr);
|
||||||
|
|
||||||
|
void add_vpi_callback(struct __vpiCallback*);
|
||||||
|
#ifdef CHECK_WITH_VALGRIND
|
||||||
|
/* This has only been tested at EOS. */
|
||||||
|
void clear_all_callbacks(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Derived classes implement this method to provide a way for
|
||||||
|
// vpi to get at the vvp value of the object.
|
||||||
|
virtual void get_value(struct t_vpi_value*value) =0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// Derived classes call this method to indicate that it is
|
||||||
|
// time to call the callback.
|
||||||
|
void run_vpi_callbacks();
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct __vpiCallback*vpi_callbacks_;
|
||||||
|
class __vpiArray* array_;
|
||||||
|
unsigned long array_word_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
Loading…
Reference in New Issue