Special handling for forced tran ports.

Tran islands must do their calculations using the forced values,
if any. But the output from a port must also be subject to force
filtering. It's a little ugly, but hopefully won't hurt the more
normal case.
This commit is contained in:
Stephen Williams 2010-05-04 19:20:36 -07:00
parent d779c6d58b
commit 459593cb59
7 changed files with 89 additions and 8 deletions

View File

@ -4060,6 +4060,7 @@ static bool do_release_vec(vthread_t thr, vvp_code_t cp, bool net_flag)
} else {
net->fil->release_pv(ptr, base, width, net_flag);
}
net->fun->force_flag();
return true;
}

View File

@ -213,6 +213,11 @@ void vvp_island_port::recv_vec8_pv(vvp_net_ptr_t p, const vvp_vector8_t&bit,
island_->flag_island();
}
void vvp_island_port::force_flag(void)
{
island_->flag_island();
}
vvp_island_branch::~vvp_island_branch()
{
}

View File

@ -21,6 +21,7 @@
# include "config.h"
# include "vvp_net.h"
# include "vvp_net_sig.h"
# include "symbols.h"
# include "schedule.h"
# include <list>
@ -120,6 +121,7 @@ class vvp_island_port : public vvp_net_fun_t {
explicit vvp_island_port(vvp_island*ip);
~vvp_island_port();
public: // Implement vvp_net_fun_t methods
virtual void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
vvp_context_t);
virtual void recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&bit,
@ -129,6 +131,12 @@ class vvp_island_port : public vvp_net_fun_t {
virtual void recv_vec8_pv(vvp_net_ptr_t p, const vvp_vector8_t&bit,
unsigned base, unsigned wid, unsigned vwid);
// This is painful, but necessary. If the island is connected
// to a forced net, we need to rerun the calculations whenever
// a force/release happens to the net.
virtual void force_flag(void);
public:
vvp_vector8_t invalue;
vvp_vector8_t outvalue;
@ -143,7 +151,24 @@ class vvp_island_port : public vvp_net_fun_t {
inline vvp_vector8_t island_get_value(vvp_net_t*net)
{
vvp_island_port*fun = dynamic_cast<vvp_island_port*>(net->fun);
return fun->invalue;
vvp_wire_vec8*fil = dynamic_cast<vvp_wire_vec8*>(net->fil);
if (fil == 0) {
return fun->invalue;
} else {
// This is painful, but necessary. If the island is
// connected to a forced net, then run the input through
// the force filter first. The island must used the
// forced value for its deliberations.
vvp_vector8_t rep;
switch (fil->filter_input_vec8(fun->invalue, rep)) {
default:
case vvp_net_fil_t::PROP:
return fun->invalue;
case vvp_net_fil_t::REPL:
return rep;
}
}
}
extern void island_send_value(vvp_net_t*net, const vvp_vector8_t&val);

View File

@ -2849,6 +2849,10 @@ void vvp_net_fun_t::recv_long_pv(vvp_net_ptr_t, long, unsigned, unsigned)
assert(0);
}
void vvp_net_fun_t::force_flag(void)
{
}
/* **** vvp_fun_drive methods **** */
vvp_fun_drive::vvp_fun_drive(vvp_bit4_t init, unsigned str0, unsigned str1)

View File

@ -1114,6 +1114,12 @@ class vvp_net_fun_t {
virtual void recv_long_pv(vvp_net_ptr_t port, long bit,
unsigned base, unsigned wid);
// This method is called when the net it forced or
// released. This is very rarely needed; island ports use it
// to know that the net is being forced and that it needs to
// do something about it.
virtual void force_flag(void);
public: // These objects are only permallocated.
static void* operator new(std::size_t size) { return heap_.alloc(size); }
static void operator delete(void*); // not implemented
@ -1150,13 +1156,16 @@ class vvp_net_fil_t : public vvp_vpi_callback {
public:
enum prop_t { STOP=0, PROP, REPL };
// 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.
// Return true if the value is to be propagated, or false if
// propagation is suppressed. The value may be edited by the
// filter, or overridden by the rep argument if present.
// These filter methods are used by the vvp_net_t::send_*()
// methods to test the output (from the functor) bit value
// against any force filters. If none of the bits are forced,
// then the method returns PROP and the caller propagates the
// bit value. If bits were changed by the force mask, then the
// method returns REPL and the caller should propagate the rep
// value instead. If the function returns STOP, then all the
// output bits are filtered by the force mask ans there is
// nothing to propagate.
virtual prop_t filter_vec4(const vvp_vector4_t&bit, vvp_vector4_t&rep,
unsigned base, unsigned vwid);
virtual prop_t filter_vec8(const vvp_vector8_t&val, vvp_vector8_t&rep,
@ -1176,7 +1185,9 @@ class vvp_net_fil_t : public vvp_vpi_callback {
virtual unsigned filter_size() const =0;
public:
// Suport for force methods
// Suport for force methods. These are calloed by the
// vvp_net_t::force_* methods to set the force value and mask
// for the filter.
virtual void force_fil_vec4(const vvp_vector4_t&val, vvp_vector2_t mask) =0;
virtual void force_fil_vec8(const vvp_vector8_t&val, vvp_vector2_t mask) =0;
virtual void force_fil_real(double val, vvp_vector2_t mask) =0;
@ -1215,6 +1226,12 @@ class vvp_net_fil_t : public vvp_vpi_callback {
// native types that are not so expensive to edit in place.
template <class T> prop_t filter_mask_(T&val, T force);
// These templates are similar to filter_mask_, but are
// idempotent. Then do not trigger callbacks or otherwise
// cause any locak changes. These methods are used to test
// arbitrary values against the force mask.
template <class T> prop_t filter_input_mask_(const T&val, const T&force, T&rep) const;
private:
// Mask of forced bits
vvp_vector2_t force_mask_;

View File

@ -71,6 +71,22 @@ template <class T> vvp_net_fil_t::prop_t vvp_net_fil_t::filter_mask_(T&val, T fo
return PROP;
}
template <class T> vvp_net_fil_t::prop_t vvp_net_fil_t::filter_input_mask_(const T&val, const T&force, T&rep) const
{
if (test_force_mask_is_zero())
return PROP;
assert(force_mask_.size() == force.size());
rep = val;
for (unsigned idx = 0 ; idx < val.size() ; idx += 1) {
if (force_mask_.value(idx))
rep.set_bit(idx, force.value(idx));
}
return REPL;
}
vvp_signal_value::~vvp_signal_value()
{
}
@ -85,6 +101,7 @@ void vvp_net_t::force_vec4(const vvp_vector4_t&val, vvp_vector2_t mask)
{
assert(fil);
fil->force_fil_vec4(val, mask);
fun->force_flag();
vvp_send_vec4(out_, val, 0);
}
@ -92,6 +109,7 @@ void vvp_net_t::force_vec8(const vvp_vector8_t&val, vvp_vector2_t mask)
{
assert(fil);
fil->force_fil_vec8(val, mask);
fun->force_flag();
vvp_send_vec8(out_, val);
}
@ -99,6 +117,7 @@ void vvp_net_t::force_real(double val, vvp_vector2_t mask)
{
assert(fil);
fil->force_fil_real(val, mask);
fun->force_flag();
vvp_send_real(out_, val, 0);
}
@ -777,6 +796,11 @@ vvp_net_fil_t::prop_t vvp_wire_vec8::filter_vec8(const vvp_vector8_t&bit, vvp_ve
return filter_mask_(bit, force8_, rep, base);
}
vvp_net_fil_t::prop_t vvp_wire_vec8::filter_input_vec8(const vvp_vector8_t&bit, vvp_vector8_t&rep) const
{
return filter_input_mask_(bit, force8_, rep);
}
unsigned vvp_wire_vec8::filter_size() const
{
return bits8_.size();

View File

@ -324,6 +324,11 @@ class vvp_wire_vec8 : public vvp_wire_base {
prop_t filter_vec8(const vvp_vector8_t&val, vvp_vector8_t&rep,
unsigned base, unsigned vwid);
// island ports use this method to filter arbitrary values
// through the force filter.
prop_t filter_input_vec8(const vvp_vector8_t&val, vvp_vector8_t&rep) const;
// Abstract methods from vvp_vpi_callback
void get_value(struct t_vpi_value*value);
// Abstract methods from vvp_net_fit_t