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*src = cp->net2;
|
||||
|
||||
vvp_filter_wire_base*sig
|
||||
= dynamic_cast<vvp_filter_wire_base*>(dst->fun);
|
||||
assert(sig);
|
||||
|
||||
sig->force_link(dst, src);
|
||||
assert(dst->fil);
|
||||
dst->fil->force_link(dst, src);
|
||||
|
||||
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);
|
||||
assert(sig);
|
||||
assert(net->fil);
|
||||
|
||||
if (base >= sig->size()) return true;
|
||||
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();
|
||||
|
||||
// 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? */
|
||||
vvp_net_ptr_t ptr (net, 0);
|
||||
if (full_sig) {
|
||||
sig->release(ptr, true);
|
||||
net->fil->release(ptr, true);
|
||||
} else {
|
||||
sig->release_pv(ptr, true, base, width);
|
||||
net->fil->release_pv(ptr, true, base, width);
|
||||
}
|
||||
|
||||
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);
|
||||
assert(sig);
|
||||
assert(net->fil);
|
||||
|
||||
if (base >= sig->size()) return true;
|
||||
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();
|
||||
|
||||
// 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.
|
||||
/* Do we release all or part of the net? */
|
||||
vvp_net_ptr_t ptr (net, 0);
|
||||
if (full_sig) {
|
||||
sig->release(ptr, false);
|
||||
net->fil->release(ptr, false);
|
||||
} else {
|
||||
sig->release_pv(ptr, false, base, width);
|
||||
net->fil->release_pv(ptr, false, base, width);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
@ -3992,14 +3991,12 @@ bool of_RELEASE_WR(vthread_t thr, vvp_code_t cp)
|
|||
vvp_net_t*net = cp->net;
|
||||
unsigned type = cp->bit_idx[0];
|
||||
|
||||
vvp_fun_signal_real*sig = reinterpret_cast<vvp_fun_signal_real*>(net->fun);
|
||||
assert(sig);
|
||||
|
||||
sig->force_unlink();
|
||||
assert(net->fil);
|
||||
net->fil->force_unlink();
|
||||
|
||||
// Send a command to this signal to unforce itself.
|
||||
vvp_net_ptr_t ptr (net, 0);
|
||||
sig->release(ptr, type==0);
|
||||
net->fil->release(ptr, type==0);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -194,12 +194,16 @@ void vvp_net_fun_t::operator delete(void*)
|
|||
assert(0);
|
||||
}
|
||||
|
||||
|
||||
vvp_net_fil_t::vvp_net_fil_t()
|
||||
{
|
||||
force_link_ = 0;
|
||||
force_propagate_ = false;
|
||||
}
|
||||
|
||||
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)
|
||||
|
|
@ -222,6 +226,81 @@ bool vvp_net_fil_t::filter_long(long&)
|
|||
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 *** */
|
||||
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 "vpi_user.h"
|
||||
# include "vvp_vpi_callback.h"
|
||||
# include <stddef.h>
|
||||
# include <stdlib.h>
|
||||
# include <string.h>
|
||||
|
|
@ -1097,10 +1098,10 @@ class vvp_net_fun_t {
|
|||
* false. If false, then send_*() continues as usual. If false, output
|
||||
* propagation is stopped.
|
||||
*
|
||||
* The filter object can be used to implement force/release, and also
|
||||
* can be used to implement vpi net object.
|
||||
* The filter object also provides an implementation hooks for
|
||||
* force/release.
|
||||
*/
|
||||
class vvp_net_fil_t {
|
||||
class vvp_net_fil_t : public vvp_vpi_callback {
|
||||
|
||||
public:
|
||||
vvp_net_fil_t();
|
||||
|
|
@ -1117,6 +1118,37 @@ class vvp_net_fil_t {
|
|||
// propagation is suppressed. The value may be edited by the filter.
|
||||
virtual bool filter_real(double&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 **** */
|
||||
|
|
@ -1147,6 +1179,27 @@ class vvp_fun_concat : public vvp_net_fun_t {
|
|||
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
|
||||
* 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
|
||||
|
|
@ -1391,4 +1444,24 @@ inline void vvp_net_t::send_real(double val, vvp_context_t 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
|
||||
|
|
|
|||
|
|
@ -30,20 +30,9 @@
|
|||
|
||||
# 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;
|
||||
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()) {
|
||||
if (!test_force_mask_is_zero()) {
|
||||
bool propagate_flag = force_propagate_;
|
||||
force_propagate_ = false;
|
||||
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
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 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)
|
||||
template <class T> bool vvp_net_fil_t::filter_mask_(T&val)
|
||||
{
|
||||
run_vpi_callbacks();
|
||||
return true;
|
||||
|
|
@ -136,11 +80,6 @@ bool vvp_fun_signal_real::filter_real(double&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)
|
||||
{
|
||||
force_mask(mask);
|
||||
|
|
@ -255,36 +194,6 @@ double vvp_fun_signal_real::filtered_real(double val) const
|
|||
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_base::vvp_fun_signal_base()
|
||||
|
|
|
|||
|
|
@ -36,43 +36,6 @@ class ostream;
|
|||
|
||||
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
|
||||
* This node is the place holder in a vvp network for signals,
|
||||
* 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 {
|
||||
|
||||
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 {
|
||||
class vvp_fun_signal_base : public vvp_net_fun_t, public vvp_net_fil_t {
|
||||
|
||||
public:
|
||||
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
|
||||
|
|
|
|||
|
|
@ -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