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:
Stephen Williams 2009-06-25 22:13:03 -07:00
parent 1940de0110
commit 7df9d60761
6 changed files with 235 additions and 244 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

63
vvp/vvp_vpi_callback.h Normal file
View File

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