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:
parent
d779c6d58b
commit
459593cb59
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
{
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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_;
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue