Skip to content

Commit

Permalink
Do not do lazy processing of part selects.
Browse files Browse the repository at this point in the history
It doesn't really make any sense to do lazy processing of part selects,
but it is possible to use the part select position to more toroughly
check for changes in output and suppress non-changes. In particular,
we only need to check that the output part actually changes, and by the
way we only need to save those bits for the next go-round.

We do want to make sure that the very first input causes an output,
though, so that time-0 values get propagated.
  • Loading branch information
steveicarus committed Jun 9, 2008
1 parent d0f3034 commit c03d76a
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 31 deletions.
45 changes: 24 additions & 21 deletions vvp/part.cc
Expand Up @@ -30,7 +30,7 @@
vvp_fun_part::vvp_fun_part(unsigned base, unsigned wid)
: base_(base), val_(wid)
{
net_ = 0;
needs_push_ = true;
}

vvp_fun_part::~vvp_fun_part()
Expand All @@ -41,23 +41,20 @@ void vvp_fun_part::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit)
{
assert(port.port() == 0);

vvp_vector4_t tmp = val_;
vvp_vector4_t tmp (val_.size());
for (unsigned idx = 0 ; idx < tmp.size() ; idx += 1) {
if ((idx + base_) < bit.size())
tmp.set_bit(idx, bit.value(base_+idx));
else
tmp.set_bit(idx, BIT4_X);
tmp.set_bit(idx, val_.value(idx));
}

if (val_ .eeq( tmp ))
if (val_ .eeq(tmp) && !needs_push_)
return;

val_ = tmp;

if (net_ == 0) {
net_ = port.ptr();
schedule_generic(this, 0, false);
}
needs_push_ = false;
vvp_send_vec4(port.ptr()->out, val_);
}

/*
Expand All @@ -71,25 +68,31 @@ void vvp_fun_part::recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&bit,
{
assert(bit.size() == wid);

// If there is no overlap between input part select and output
// part select, then do nothing.
if (base >= base_+val_.size())
return;
if ((base+wid) <= base_)
return;

vvp_vector4_t tmp = val_;
if (tmp.size() == 0)
tmp = vvp_vector4_t(vwid);
// There is at least some overlap, so build a new output part
// select from the previous output and the new input.
vvp_vector4_t tmp (val_.size());
for (unsigned idx = 0 ; idx < tmp.size() ; idx += 1) {
if ((idx + base_) < base)
tmp.set_bit(idx, val_.value(idx));
else if ((idx + base_) < (base+bit.size()))
tmp.set_bit(idx, bit.value(base_+idx));
else
tmp.set_bit(idx, val_.value(idx));
}

assert(tmp.size() == vwid);
tmp.set_vec(base, bit);
recv_vec4(port, tmp);
}
if (val_ .eeq(tmp) && !needs_push_)
return;

void vvp_fun_part::run_run()
{
vvp_net_t*ptr = net_;
net_ = 0;
vvp_send_vec4(ptr->out, val_);
val_ = tmp;
needs_push_ = false;
vvp_send_vec4(port.ptr()->out, val_);
}

vvp_fun_part_pv::vvp_fun_part_pv(unsigned b, unsigned w, unsigned v)
Expand Down
14 changes: 4 additions & 10 deletions vvp/part.h
Expand Up @@ -19,15 +19,12 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/

# include "schedule.h"

/* vvp_fun_part
* This node takes a part select of the input vector. Input 0 is the
* vector to be selected from, and input 1 is the location where the
* select starts. Input 2, which is typically constant, is the width
* of the result.
* vector to be selected from, and the base and wid are where to pull
* the part from.
*/
class vvp_fun_part : public vvp_net_fun_t, private vvp_gen_event_s {
class vvp_fun_part : public vvp_net_fun_t {

public:
vvp_fun_part(unsigned base, unsigned wid);
Expand All @@ -40,13 +37,10 @@ class vvp_fun_part : public vvp_net_fun_t, private vvp_gen_event_s {
unsigned, unsigned, unsigned);

private:
void run_run();

private:
bool needs_push_;
unsigned base_;
unsigned wid_;
vvp_vector4_t val_;
vvp_net_t*net_;
};

/* vvp_fun_part_pv
Expand Down

0 comments on commit c03d76a

Please sign in to comment.