Compare commits

...
7 Commits
Author SHA1 Message Date
Stephen Williams afa2478801 Merge branch 'master' of ssh://[email protected]/home/u/icarus/steve/git/verilog 2008-06-09 16:58:21 -07:00
Stephen Williams 79feb44f10 Turn of concat output scheduling.
We really want lazy processing of concatenation because it has multiple
inputs and lazy processing should (in theory) prevent redundant and
useless propagations through the net.

But enabling it seems to cause many tests in the regression test suite
to fail to compare their results. There are races in many tests that
are interacting badly with this feature. So for now, ifdef it out.
2008-06-09 16:57:51 -07:00
Stephen Williams c03d76a0d7 Do not do lazy processing of part selects.
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.
2008-06-09 16:46:06 -07:00
Stephen Williams d0f303463d ASSIGN transfer data to scheduler efficiently/permalloc vvp_net_t objects.
The vvp_net_t objects are never deleted, so overload the new operator
to do a more space efficient permanent allocation.

The %assign/v instruction copied the vvp_vector4_t object needlessly
on its way to the scheduler. Eliminate that duplication.
2008-06-06 19:50:44 -07:00
Stephen Williams 35fe8fae00 Have vvp_vector8_t avoid allocating tiny scalar arrays. 2008-06-06 16:36:43 -07:00
Stephen Williams 2e95a740da Rework scheduling of concat, part, buf/not and resolv for efficiency.
The concat and resolv functors are best evaluated lazily, because each
evaluation is costly and there is a high probability that an evaluation
will be invalidated when new input comes in.

Also optimization the recv_vec4_pv method of the resolver, which is
commonly used, and adjust the order of handling of vvp_fun_part to
work more efficiently.
2008-06-06 15:31:22 -07:00
Stephen Williams 2f4e5bf5b6 Obvious optimizations of vvp_vector8_t handling.
The vvp_vector8_t constructor and destructor involve memory allocation
so it is best to pass these objects by reference as much as possible.

Also rework the resolver functor to only perform resolution after inputs
are in so that it doesn't get needlessly repeated. This eliminates many
resolve function calls, as well as activations throughout the net.

Also have the islands take more care not to perform resolution if the
inputs aren't really different.
2008-06-06 11:12:07 -07:00
20 changed files with 432 additions and 327 deletions
+4 -4
View File
@@ -1399,16 +1399,16 @@ void compile_resolver(char*label, char*type, unsigned argc, struct symb_s*argv)
vvp_net_fun_t* obj = 0;
if (strcmp(type,"tri") == 0) {
obj = new resolv_functor(vvp_scalar_t(BIT4_Z, 0));
obj = new resolv_functor(vvp_scalar_t(BIT4_Z, 0,0));
} else if (strncmp(type,"tri$",4) == 0) {
obj = new resolv_functor(vvp_scalar_t(BIT4_Z, 0), strdup(type+4));
obj = new resolv_functor(vvp_scalar_t(BIT4_Z, 0,0), strdup(type+4));
} else if (strcmp(type,"tri0") == 0) {
obj = new resolv_functor(vvp_scalar_t(BIT4_0, 5));
obj = new resolv_functor(vvp_scalar_t(BIT4_0, 5,5));
} else if (strcmp(type,"tri1") == 0) {
obj = new resolv_functor(vvp_scalar_t(BIT4_1, 5));
obj = new resolv_functor(vvp_scalar_t(BIT4_1, 5,5));
} else if (strcmp(type,"triand") == 0) {
obj = new resolv_triand;
+62 -16
View File
@@ -20,6 +20,7 @@
# include "compile.h"
# include "vvp_net.h"
# include "schedule.h"
# include <stdlib.h>
# include <iostream>
#ifdef HAVE_MALLOC_H
@@ -27,18 +28,43 @@
#endif
# include <assert.h>
# define SCHEDULE_OUTPUT 0
/* vvp_fun_concat
* This node function creates vectors (vvp_vector4_t) from the
* concatenation of the inputs. The inputs (4) may be vector or
* vector8 objects, but they are reduced to vector4 values and
* strength information lost.
*
* The expected widths of the input vectors must be given up front so
* that the positions in the output vector (and also the size of the
* output vector) can be worked out. The input vectors must match the
* expected width.
*/
class vvp_fun_concat : public vvp_net_fun_t, private vvp_gen_event_s {
public:
vvp_fun_concat(unsigned w0, unsigned w1,
unsigned w2, unsigned w3);
~vvp_fun_concat();
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit);
private:
void run_run();
vvp_net_t*net_;
vvp_vector4_t input_[4];
};
vvp_fun_concat::vvp_fun_concat(unsigned w0, unsigned w1,
unsigned w2, unsigned w3)
: val_(w0+w1+w2+w3)
: net_(0)
{
wid_[0] = w0;
wid_[1] = w1;
wid_[2] = w2;
wid_[3] = w3;
for (unsigned idx = 0 ; idx < val_.size() ; idx += 1)
val_.set_bit(idx, BIT4_X);
input_[0] = vvp_vector4_t(w0);
input_[1] = vvp_vector4_t(w1);
input_[2] = vvp_vector4_t(w2);
input_[3] = vvp_vector4_t(w3);
}
vvp_fun_concat::~vvp_fun_concat()
@@ -49,22 +75,42 @@ void vvp_fun_concat::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit)
{
unsigned pdx = port.port();
if (bit.size() != wid_[pdx]) {
if (bit.size() != input_[pdx].size()) {
cerr << "internal error: port " << pdx
<< " expects wid=" << wid_[pdx]
<< " expects wid=" << input_[pdx].size()
<< ", got wid=" << bit.size() << endl;
assert(0);
}
unsigned off = 0;
for (unsigned idx = 0 ; idx < pdx ; idx += 1)
off += wid_[idx];
if (input_[pdx] .eeq(bit))
return;
for (unsigned idx = 0 ; idx < wid_[pdx] ; idx += 1) {
val_.set_bit(off+idx, bit.value(idx));
input_[pdx] = bit;
if (net_ == 0) {
net_ = port.ptr();
if (SCHEDULE_OUTPUT)
schedule_generic(this, 0, false);
else
run_run();
}
}
void vvp_fun_concat::run_run()
{
vvp_net_t*ptr = net_;
net_ = 0;
unsigned off = 0;
unsigned owid = input_[0].size() + input_[1].size() + input_[2].size() + input_[3].size();
vvp_vector4_t res (owid);
for (unsigned idx = 0 ; idx < 4 && (off<owid) ; idx += 1) {
res.set_vec(off, input_[idx]);
off += input_[idx].size();
}
vvp_send_vec4(port.ptr()->out, val_);
vvp_send_vec4(ptr->out, res);
}
void compile_concat(char*label, unsigned w0, unsigned w1,
+1 -1
View File
@@ -242,7 +242,7 @@ void vvp_fun_delay::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit)
}
}
void vvp_fun_delay::recv_vec8(vvp_net_ptr_t port, vvp_vector8_t bit)
void vvp_fun_delay::recv_vec8(vvp_net_ptr_t port, const vvp_vector8_t&bit)
{
assert(port.port() == 0);
+1 -1
View File
@@ -86,7 +86,7 @@ class vvp_fun_delay : public vvp_net_fun_t, private vvp_gen_event_s {
~vvp_fun_delay();
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit);
void recv_vec8(vvp_net_ptr_t port, vvp_vector8_t bit);
void recv_vec8(vvp_net_ptr_t port, const vvp_vector8_t&bit);
void recv_real(vvp_net_ptr_t port, double bit);
//void recv_long(vvp_net_ptr_t port, long bit);
+5 -37
View File
@@ -140,7 +140,6 @@ void vvp_fun_eeq::run_run()
vvp_fun_buf::vvp_fun_buf()
{
net_ = 0;
count_functors_logic += 1;
}
@@ -157,25 +156,12 @@ void vvp_fun_buf::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
if (ptr.port() != 0)
return;
if (input_ .eeq( bit ))
if (input_ .eq_xz( bit ))
return;
input_ = bit;
if (net_ == 0) {
net_ = ptr.ptr();
schedule_generic(this, 0, false);
}
}
void vvp_fun_buf::run_run()
{
vvp_net_t*ptr = net_;
net_ = 0;
vvp_vector4_t tmp (input_);
tmp.change_z2x();
vvp_send_vec4(ptr->out, tmp);
input_.change_z2x();
vvp_send_vec4(ptr.ptr()->out, input_);
}
vvp_fun_bufz::vvp_fun_bufz()
@@ -394,7 +380,6 @@ void vvp_fun_muxz::run_run()
vvp_fun_not::vvp_fun_not()
{
net_ = 0;
count_functors_logic += 1;
}
@@ -411,30 +396,13 @@ void vvp_fun_not::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
if (ptr.port() != 0)
return;
if (input_ .eeq( bit ))
if (input_ .eq_xz( bit ))
return;
input_ = bit;
if (net_ == 0) {
net_ = ptr.ptr();
schedule_generic(this, 0, false);
}
vvp_send_vec4(ptr.ptr()->out, ~input_);
}
void vvp_fun_not::run_run()
{
vvp_net_t*ptr = net_;
net_ = 0;
vvp_vector4_t result (input_);
for (unsigned idx = 0 ; idx < result.size() ; idx += 1) {
vvp_bit4_t bitbit = ~ result.value(idx);
result.set_bit(idx, bitbit);
}
vvp_send_vec4(ptr->out, result);
}
vvp_fun_or::vvp_fun_or(unsigned wid, bool invert)
: vvp_fun_boolean_(wid), invert_(invert)
+2 -10
View File
@@ -69,7 +69,7 @@ class vvp_fun_eeq : public vvp_fun_boolean_ {
* The retransmitted vector has all Z values changed to X, just like
* the buf(Q,D) gate in Verilog.
*/
class vvp_fun_buf: public vvp_net_fun_t, private vvp_gen_event_s {
class vvp_fun_buf: public vvp_net_fun_t {
public:
explicit vvp_fun_buf();
@@ -77,12 +77,8 @@ class vvp_fun_buf: public vvp_net_fun_t, private vvp_gen_event_s {
void recv_vec4(vvp_net_ptr_t p, const vvp_vector4_t&bit);
private:
void run_run();
private:
vvp_vector4_t input_;
vvp_net_t*net_;
};
/*
@@ -152,7 +148,7 @@ class vvp_fun_muxr : public vvp_net_fun_t, private vvp_gen_event_s {
sel_type select_;
};
class vvp_fun_not: public vvp_net_fun_t, private vvp_gen_event_s {
class vvp_fun_not: public vvp_net_fun_t {
public:
explicit vvp_fun_not();
@@ -160,12 +156,8 @@ class vvp_fun_not: public vvp_net_fun_t, private vvp_gen_event_s {
void recv_vec4(vvp_net_ptr_t p, const vvp_vector4_t&bit);
private:
void run_run();
private:
vvp_vector4_t input_;
vvp_net_t*net_;
};
class vvp_fun_or : public vvp_fun_boolean_ {
+6 -5
View File
@@ -279,9 +279,11 @@ int main(int argc, char*argv[])
vpi_mcd_printf(1, " %8lu bufif\n", count_functors_bufif);
vpi_mcd_printf(1, " %8lu resolv\n",count_functors_resolv);
vpi_mcd_printf(1, " %8lu signals\n", count_functors_sig);
vpi_mcd_printf(1, " ... %8lu opcodes (%lu bytes)\n",
vpi_mcd_printf(1, " ... %8lu opcodes (%zu bytes)\n",
count_opcodes, (unsigned long)size_opcodes);
vpi_mcd_printf(1, " ... %8lu nets\n", count_vpi_nets);
vpi_mcd_printf(1, " ... %8lu vvp_nets (%zu bytes)\n",
count_vvp_nets, size_vvp_nets);
vpi_mcd_printf(1, " ... %8lu memories\n", count_vpi_memories);
vpi_mcd_printf(1, " ... %8lu scopes\n", count_vpi_scopes);
}
@@ -299,12 +301,11 @@ int main(int argc, char*argv[])
my_getrusage(cycles+2);
print_rusage(cycles+2, cycles+1);
vpi_mcd_printf(1, "Event counts: (event pool = %lu)\n",
count_event_pool);
vpi_mcd_printf(1, "Event counts:\n");
vpi_mcd_printf(1, " %8lu time steps (pool=%lu)\n",
count_time_events, count_time_pool);
vpi_mcd_printf(1, " %8lu thread schedule events\n",
count_thread_events);
vpi_mcd_printf(1, " %8lu propagation events\n",
count_prop_events);
vpi_mcd_printf(1, " %8lu assign events\n",
count_assign_events);
vpi_mcd_printf(1, " %8lu other events\n",
+6 -6
View File
@@ -33,7 +33,7 @@ void vvp_fun_pmos_::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
/* Data input is processed through eh recv_vec8 method,
because the strength must be preserved. */
if (ptr.port() == 0) {
vvp_vector8_t tmp = bit;
vvp_vector8_t tmp = vvp_vector8_t(bit,6,6);
recv_vec8(ptr, tmp);
return;
}
@@ -86,7 +86,7 @@ vvp_fun_pmos::vvp_fun_pmos(bool enable_invert)
{
}
void vvp_fun_pmos::recv_vec8(vvp_net_ptr_t ptr, vvp_vector8_t bit)
void vvp_fun_pmos::recv_vec8(vvp_net_ptr_t ptr, const vvp_vector8_t&bit)
{
if (ptr.port() == 1) {
recv_vec4(ptr, reduce4(bit));
@@ -105,7 +105,7 @@ vvp_fun_rpmos::vvp_fun_rpmos(bool enable_invert)
{
}
void vvp_fun_rpmos::recv_vec8(vvp_net_ptr_t ptr, vvp_vector8_t bit)
void vvp_fun_rpmos::recv_vec8(vvp_net_ptr_t ptr, const vvp_vector8_t&bit)
{
if (ptr.port() == 1) {
recv_vec4(ptr, reduce4(bit));
@@ -133,7 +133,7 @@ void vvp_fun_cmos_::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t &bit)
/* Data input is processed through the recv_vec8 method,
because the strength must be preserved. */
if (ptr.port() == 0) {
vvp_vector8_t tmp = bit;
vvp_vector8_t tmp = vvp_vector8_t(bit,6,6);
recv_vec8(ptr, tmp);
return;
}
@@ -187,7 +187,7 @@ vvp_fun_cmos::vvp_fun_cmos()
{
}
void vvp_fun_cmos::recv_vec8(vvp_net_ptr_t ptr, vvp_vector8_t bit)
void vvp_fun_cmos::recv_vec8(vvp_net_ptr_t ptr, const vvp_vector8_t&bit)
{
if (ptr.port() == 1 || ptr.port() == 2) {
recv_vec4(ptr, reduce4(bit));
@@ -206,7 +206,7 @@ vvp_fun_rcmos::vvp_fun_rcmos()
{
}
void vvp_fun_rcmos::recv_vec8(vvp_net_ptr_t ptr, vvp_vector8_t bit)
void vvp_fun_rcmos::recv_vec8(vvp_net_ptr_t ptr, const vvp_vector8_t&bit)
{
if (ptr.port() == 1) {
recv_vec4(ptr, reduce4(bit));
+4 -4
View File
@@ -66,7 +66,7 @@ class vvp_fun_pmos : public vvp_fun_pmos_ {
public:
explicit vvp_fun_pmos(bool enable_invert);
void recv_vec8(vvp_net_ptr_t port, vvp_vector8_t bit);
void recv_vec8(vvp_net_ptr_t port, const vvp_vector8_t&bit);
};
/*
@@ -79,7 +79,7 @@ class vvp_fun_rpmos : public vvp_fun_pmos_ {
public:
explicit vvp_fun_rpmos(bool enable_invert);
void recv_vec8(vvp_net_ptr_t port, vvp_vector8_t bit);
void recv_vec8(vvp_net_ptr_t port, const vvp_vector8_t&bit);
};
/*
@@ -121,14 +121,14 @@ class vvp_fun_cmos : public vvp_fun_cmos_ {
public:
explicit vvp_fun_cmos();
void recv_vec8(vvp_net_ptr_t port, vvp_vector8_t bit);
void recv_vec8(vvp_net_ptr_t port, const vvp_vector8_t&bit);
};
class vvp_fun_rcmos : public vvp_fun_cmos_ {
public:
explicit vvp_fun_rcmos();
void recv_vec8(vvp_net_ptr_t port, vvp_vector8_t bit);
void recv_vec8(vvp_net_ptr_t port, const vvp_vector8_t&bit);
};
#endif
+37 -27
View File
@@ -28,9 +28,9 @@
# include <assert.h>
vvp_fun_part::vvp_fun_part(unsigned base, unsigned wid)
: base_(base), wid_(wid)
: base_(base), val_(wid)
{
net_ = 0;
needs_push_ = true;
}
vvp_fun_part::~vvp_fun_part()
@@ -41,15 +41,20 @@ void vvp_fun_part::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit)
{
assert(port.port() == 0);
if (val_ .eeq( bit ))
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, val_.value(idx));
}
if (val_ .eeq(tmp) && !needs_push_)
return;
val_ = bit;
if (net_ == 0) {
net_ = port.ptr();
schedule_generic(this, 0, false);
}
val_ = tmp;
needs_push_ = false;
vvp_send_vec4(port.ptr()->out, val_);
}
/*
@@ -63,26 +68,31 @@ void vvp_fun_part::recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&bit,
{
assert(bit.size() == wid);
vvp_vector4_t tmp = val_;
if (tmp.size() == 0)
tmp = vvp_vector4_t(vwid);
// 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;
assert(tmp.size() == vwid);
tmp.set_vec(base, bit);
recv_vec4(port, tmp);
}
void vvp_fun_part::run_run()
{
vvp_net_t*ptr = net_;
net_ = 0;
vvp_vector4_t res (wid_, BIT4_X);
for (unsigned idx = 0 ; idx < wid_ ; idx += 1) {
if (idx + base_ < val_.size())
res.set_bit(idx, val_.value(base_+idx));
// 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));
}
vvp_send_vec4(ptr->out, res);
if (val_ .eeq(tmp) && !needs_push_)
return;
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)
+4 -10
View File
@@ -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);
@@ -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
+23 -15
View File
@@ -26,7 +26,7 @@
resolv_functor::resolv_functor(vvp_scalar_t hiz_value, const char*debug_l)
: hiz_(hiz_value), debug_label_(debug_l)
: net_(0), hiz_(hiz_value), debug_label_(debug_l)
{
count_functors_resolv += 1;
}
@@ -37,28 +37,24 @@ resolv_functor::~resolv_functor()
void resolv_functor::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit)
{
recv_vec8(port, vvp_vector8_t(bit, 6 /* STRONG */));
recv_vec8(port, vvp_vector8_t(bit, 6,6 /* STRONG */));
}
void resolv_functor::recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&bit,
unsigned base, unsigned wid, unsigned vwid)
{
assert(bit.size() == wid);
vvp_vector4_t res (vwid);
for (unsigned idx = 0 ; idx < base ; idx += 1)
res.set_bit(idx, BIT4_Z);
vvp_vector8_t tmp (bit,6,6);
vvp_vector8_t tmpw (vwid);
for (unsigned idx = 0 ; idx < wid ; idx += 1)
res.set_bit(idx+base, bit.value(idx));
tmpw.set_bit(idx+base, tmp.value(idx));
for (unsigned idx = base+wid ; idx < vwid ; idx += 1)
res.set_bit(idx, BIT4_Z);
recv_vec4(port, res);
recv_vec8(port, tmpw);
}
void resolv_functor::recv_vec8(vvp_net_ptr_t port, vvp_vector8_t bit)
void resolv_functor::recv_vec8(vvp_net_ptr_t port, const vvp_vector8_t&bit)
{
unsigned pdx = port.port();
vvp_net_t*ptr = port.ptr();
@@ -68,14 +64,26 @@ void resolv_functor::recv_vec8(vvp_net_ptr_t port, vvp_vector8_t bit)
val_[pdx] = bit;
vvp_vector8_t out (bit);
if (net_ == 0) {
net_ = ptr;
schedule_generic(this, 0, false);
}
}
void resolv_functor::run_run()
{
vvp_net_t*ptr = net_;
net_ = 0;
vvp_vector8_t out;
for (unsigned idx = 0 ; idx < 4 ; idx += 1) {
if (idx == pdx)
continue;
if (val_[idx].size() == 0)
continue;
out = resolve(out, val_[idx]);
if (out.size()==0)
out = val_[idx];
else
out = resolve(out, val_[idx]);
}
if (! hiz_.is_hiz()) {
+6 -2
View File
@@ -21,6 +21,7 @@
# include "config.h"
# include "vvp_net.h"
# include "schedule.h"
/*
* This functor type resolves its inputs using the Verilog method of
@@ -34,19 +35,22 @@
* strong values (or HiZ) for the sake of resolution. In any case, the
* propagated value is a vvp_vector8_t value.
*/
class resolv_functor : public vvp_net_fun_t {
class resolv_functor : public vvp_net_fun_t, private vvp_gen_event_s {
public:
explicit resolv_functor(vvp_scalar_t hiz_value, const char* debug =0);
~resolv_functor();
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit);
void recv_vec8(vvp_net_ptr_t port, vvp_vector8_t bit);
void recv_vec8(vvp_net_ptr_t port, const vvp_vector8_t&bit);
void recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&bit,
unsigned base, unsigned wid, unsigned vwid);
private:
vvp_net_t*net_;
void run_run();
vvp_vector8_t val_[4];
// Bit value to emit for HiZ bits.
vvp_scalar_t hiz_;
+21 -2
View File
@@ -30,9 +30,9 @@
unsigned long count_assign_events = 0;
unsigned long count_gen_events = 0;
unsigned long count_prop_events = 0;
unsigned long count_thread_events = 0;
unsigned long count_event_pool = 0;
// Count the time events (A time cell created)
unsigned long count_time_events = 0;
unsigned long count_time_pool = 0;
@@ -96,6 +96,12 @@ void del_thr_event_s::run_run(void)
}
struct assign_vector4_event_s : public event_s {
/* The default constructor. */
assign_vector4_event_s() { }
/* A constructor that makes the val directly. */
assign_vector4_event_s(const vvp_vector4_t&that, unsigned adr, unsigned wid)
: val(that,adr,wid) { }
/* Where to do the assign. */
vvp_net_ptr_t ptr;
/* Value to assign. */
@@ -485,6 +491,19 @@ void schedule_assign_vector(vvp_net_ptr_t ptr,
schedule_event_(cur, delay, SEQ_NBASSIGN);
}
void schedule_assign_plucked_vector(vvp_net_ptr_t ptr,
vvp_time64_t delay,
const vvp_vector4_t&src,
unsigned adr, unsigned wid)
{
struct assign_vector4_event_s*cur
= new struct assign_vector4_event_s(src,adr,wid);
cur->ptr = ptr;
cur->vwid = 0;
cur->base = 0;
schedule_event_(cur, delay, SEQ_NBASSIGN);
}
void schedule_assign_array_word(vvp_array_t mem,
unsigned word_addr,
unsigned off,
+4
View File
@@ -50,6 +50,10 @@ extern void schedule_assign_vector(vvp_net_ptr_t ptr,
extern void schedule_assign_vector(vvp_net_ptr_t ptr,
const vvp_vector4_t&val,
vvp_time64_t delay);
extern void schedule_assign_plucked_vector(vvp_net_ptr_t ptr,
vvp_time64_t delay,
const vvp_vector4_t&val,
unsigned adr, unsigned wid);
extern void schedule_assign_array_word(vvp_array_t mem,
unsigned word_address,
+5
View File
@@ -27,10 +27,15 @@ extern unsigned long count_functors_logic;
extern unsigned long count_functors_bufif;
extern unsigned long count_functors_resolv;
extern unsigned long count_functors_sig;
extern unsigned long count_vvp_nets;
extern unsigned long count_vpi_nets;
extern unsigned long count_vpi_scopes;
extern unsigned long count_vpi_memories;
extern unsigned long count_time_events;
extern unsigned long count_time_pool;
extern size_t size_opcodes;
extern size_t size_vvp_nets;
#endif
+15 -6
View File
@@ -700,10 +700,15 @@ bool of_ASSIGN_V0(vthread_t thr, vvp_code_t cp)
unsigned delay = cp->bit_idx[0];
unsigned bit = cp->bit_idx[1];
vvp_vector4_t value = vthread_bits_to_vector(thr, bit, wid);
vvp_net_ptr_t ptr (cp->net, 0);
schedule_assign_vector(ptr, value, delay);
if (bit >= 4) {
// If the vector is not a synthetic one, then have the
// scheduler pluck it direcly out of my vector space.
schedule_assign_plucked_vector(ptr, delay, thr->bits4, bit, wid);
} else {
vvp_vector4_t value = vthread_bits_to_vector(thr, bit, wid);
schedule_assign_vector(ptr, value, delay);
}
return true;
}
@@ -721,10 +726,14 @@ bool of_ASSIGN_V0D(vthread_t thr, vvp_code_t cp)
unsigned long delay = thr->words[cp->bit_idx[0]].w_int;
unsigned bit = cp->bit_idx[1];
vvp_vector4_t value = vthread_bits_to_vector(thr, bit, wid);
vvp_net_ptr_t ptr (cp->net, 0);
schedule_assign_vector(ptr, value, delay);
if (bit >= 4) {
schedule_assign_plucked_vector(ptr, delay, thr->bits4, bit, wid);
} else {
vvp_vector4_t value = vthread_bits_to_vector(thr, bit, wid);
schedule_assign_vector(ptr, value, delay);
}
return true;
}
+26 -12
View File
@@ -127,9 +127,10 @@ class vvp_island_port : public vvp_net_fun_t {
virtual void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit);
virtual void recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&bit,
unsigned base, unsigned wid, unsigned vwid);
virtual void recv_vec8(vvp_net_ptr_t port, const vvp_vector8_t bit);
virtual void recv_vec8(vvp_net_ptr_t port, const vvp_vector8_t&bit);
vvp_vector8_t invalue;
vvp_vector8_t outvalue;
private:
vvp_island*island_;
@@ -139,6 +140,22 @@ class vvp_island_port : public vvp_net_fun_t {
vvp_island_port& operator = (const vvp_island_port&);
};
static vvp_vector8_t get_value(vvp_net_t*net)
{
vvp_island_port*fun = dynamic_cast<vvp_island_port*>(net->fun);
return fun->invalue;
}
static void send_value(vvp_net_t*net, const vvp_vector8_t&val)
{
vvp_island_port*fun = dynamic_cast<vvp_island_port*>(net->fun);
if (fun->outvalue .eeq(val))
return;
fun->outvalue = val;
vvp_send_vec8(net->out, fun->outvalue);
}
/*
* Branches are connected together to form a mesh of brances. Each
* endpoint (there are two) connects circularly to other branch
@@ -316,8 +333,11 @@ void vvp_island_port::recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&bit,
}
void vvp_island_port::recv_vec8(vvp_net_ptr_t port, const vvp_vector8_t bit)
void vvp_island_port::recv_vec8(vvp_net_ptr_t port, const vvp_vector8_t&bit)
{
if (invalue .eeq(bit))
return;
invalue = bit;
island_->flag_island();
}
@@ -388,12 +408,6 @@ static void collect_node(list<vvp_branch_ptr_t>&conn, vvp_branch_ptr_t cur)
conn.push_back(idx);
}
static vvp_vector8_t get_value(vvp_net_t*net)
{
vvp_island_port*fun = dynamic_cast<vvp_island_port*>(net->fun);
return fun->invalue;
}
static void mark_done_flags(list<vvp_branch_ptr_t>&connections)
{
for (list<vvp_branch_ptr_t>::iterator idx = connections.begin()
@@ -511,13 +525,13 @@ static void push_value_through_branches(const vvp_vector8_t&val,
if (tmp_ptr->width == 0) {
// Mark this end as done
tmp_ptr->flags |= (1 << other_ab);
vvp_send_vec8(other_net->out, val);
send_value(other_net, val);
} if (other_ab == 1) {
// Mark as done
tmp_ptr->flags |= (1 << other_ab);
vvp_vector8_t tmp = val.subvalue(tmp_ptr->offset, tmp_ptr->part);
vvp_send_vec8(other_net->out, tmp);
send_value(other_net, tmp);
} else {
// Otherwise, the other side is not fully
// specified, so we can't take this shortcut.
@@ -553,7 +567,7 @@ void vvp_island_branch::run_resolution()
resolve_values_from_connections(val, connections);
// A side is done.
vvp_send_vec8(a->out, val);
send_value(a, val);
// Clear the visited flags. This must be done so that other
// branches can read this input value.
@@ -599,7 +613,7 @@ void vvp_island_branch::run_resolution()
clear_visited_flags(connections);
}
vvp_send_vec8(b->out, val);
send_value(b, val);
}
/* **** COMPILE/LINK SUPPORT **** */
+101 -123
View File
@@ -30,6 +30,31 @@
# include <math.h>
# include <assert.h>
// Allocate around 1Megbytes/chunk.
static const size_t VVP_NET_CHUNK = 1024*1024/sizeof(vvp_net_t);
static vvp_net_t*vvp_net_alloc_table = 0;
static size_t vvp_net_alloc_remaining = 0;
// For statistics, count the vvp_nets allocated and the bytes of alloc
// chunks allocated.
unsigned long count_vvp_nets = 0;
size_t size_vvp_nets = 0;
void* vvp_net_t::operator new (size_t size)
{
assert(size == sizeof(vvp_net_t));
if (vvp_net_alloc_remaining == 0) {
vvp_net_alloc_table = ::new vvp_net_t[VVP_NET_CHUNK];
vvp_net_alloc_remaining = VVP_NET_CHUNK;
size_vvp_nets += size*VVP_NET_CHUNK;
}
vvp_net_t*return_this = vvp_net_alloc_table;
vvp_net_alloc_table += 1;
vvp_net_alloc_remaining -= 1;
count_vvp_nets += 1;
return return_this;
}
/* *** BIT operations *** */
vvp_bit4_t add_with_carry(vvp_bit4_t a, vvp_bit4_t b, vvp_bit4_t&c)
{
@@ -129,7 +154,7 @@ int edge(vvp_bit4_t from, vvp_bit4_t to)
return 0;
}
void vvp_send_vec8(vvp_net_ptr_t ptr, vvp_vector8_t val)
void vvp_send_vec8(vvp_net_ptr_t ptr, const vvp_vector8_t&val)
{
while (struct vvp_net_t*cur = ptr.ptr()) {
vvp_net_ptr_t next = cur->port[ptr.port()];
@@ -779,6 +804,41 @@ bool vvp_vector4_t::eeq(const vvp_vector4_t&that) const
return true;
}
bool vvp_vector4_t::eq_xz(const vvp_vector4_t&that) const
{
if (size_ != that.size_)
return false;
if (size_ < BITS_PER_WORD) {
unsigned long mask = (1UL << size_) - 1;
return ((abits_val_|bbits_val_)&mask) == ((that.abits_val_|that.bbits_val_)&mask)
&& (bbits_val_&mask) == (that.bbits_val_&mask);
}
if (size_ == BITS_PER_WORD) {
return ((abits_val_|bbits_val_) == (that.abits_val_|that.bbits_val_))
&& (bbits_val_ == that.bbits_val_);
}
unsigned words = size_ / BITS_PER_WORD;
for (unsigned idx = 0 ; idx < words ; idx += 1) {
if ((abits_ptr_[idx]|bbits_ptr_[idx]) != (that.abits_ptr_[idx]|that.bbits_ptr_[idx]))
return false;
if (bbits_ptr_[idx] != that.bbits_ptr_[idx])
return false;
}
unsigned long mask = size_%BITS_PER_WORD;
if (mask > 0) {
mask = (1UL << mask) - 1;
return ((abits_ptr_[words]|bbits_ptr_[words])&mask) == ((that.abits_ptr_[words]|that.bbits_ptr_[words])&mask)
&& (bbits_ptr_[words]&mask) == (that.bbits_ptr_[words]&mask);
}
return true;
}
bool vvp_vector4_t::has_xz() const
{
if (size_ < BITS_PER_WORD) {
@@ -1751,64 +1811,42 @@ ostream& operator<< (ostream&out, const vvp_vector2_t&that)
vvp_vector8_t::vvp_vector8_t(const vvp_vector8_t&that)
{
size_ = that.size_;
bits_ = new vvp_scalar_t[size_];
for (unsigned idx = 0 ; idx < size_ ; idx += 1)
bits_[idx] = that.bits_[idx];
}
vvp_vector8_t::vvp_vector8_t(unsigned size)
: size_(size)
{
if (size_ == 0) {
bits_ = 0;
return;
if (size_ <= PTR_THRESH) {
memcpy(val_, that.val_, sizeof(val_));
} else {
ptr_ = new vvp_scalar_t[size_];
for (unsigned idx = 0 ; idx < size_ ; idx += 1)
ptr_[idx] = that.ptr_[idx];
}
bits_ = new vvp_scalar_t[size_];
}
vvp_vector8_t::vvp_vector8_t(const vvp_vector4_t&that, unsigned str)
: size_(that.size())
{
if (size_ == 0) {
bits_ = 0;
return;
}
bits_ = new vvp_scalar_t[size_];
for (unsigned idx = 0 ; idx < size_ ; idx += 1)
bits_[idx] = vvp_scalar_t (that.value(idx), str);
}
vvp_vector8_t::vvp_vector8_t(const vvp_vector4_t&that,
unsigned str0, unsigned str1)
: size_(that.size())
{
if (size_ == 0) {
bits_ = 0;
if (size_ == 0)
return;
}
bits_ = new vvp_scalar_t[size_];
vvp_scalar_t*tmp;
if (size_ <= PTR_THRESH)
tmp = new (val_) vvp_scalar_t[PTR_THRESH];
else
tmp = ptr_ = new vvp_scalar_t[size_];
for (unsigned idx = 0 ; idx < size_ ; idx += 1)
bits_[idx] = vvp_scalar_t (that.value(idx), str0, str1);
tmp[idx] = vvp_scalar_t (that.value(idx), str0, str1);
}
vvp_vector8_t& vvp_vector8_t::operator= (const vvp_vector8_t&that)
{
// Assign to self.
if (size_ > 0 && bits_ == that.bits_)
if (size_ > PTR_THRESH && that.size_ > PTR_THRESH && ptr_ == that.ptr_)
return *this;
if (size_ != that.size_) {
if (size_ > 0)
delete[]bits_;
if (size_ > PTR_THRESH)
delete[]ptr_;
size_ = 0;
}
@@ -1817,40 +1855,33 @@ vvp_vector8_t& vvp_vector8_t::operator= (const vvp_vector8_t&that)
return *this;
}
if (that.size_ <= PTR_THRESH) {
size_ = that.size_;
memcpy(val_, that.val_, sizeof(val_));
return *this;
}
if (size_ == 0) {
size_ = that.size_;
bits_ = new vvp_scalar_t[size_];
ptr_ = new vvp_scalar_t[size_];
}
for (unsigned idx = 0 ; idx < size_ ; idx += 1)
bits_[idx] = that.bits_[idx];
ptr_[idx] = that.ptr_[idx];
return *this;
}
bool vvp_vector8_t::eeq(const vvp_vector8_t&that) const
{
if (size_ != that.size_)
return false;
if (size_ == 0)
return true;
for (unsigned idx = 0 ; idx < size_ ; idx += 1) {
if (! bits_[idx] .eeq( that.bits_[idx] ))
return false;
}
return true;
}
vvp_vector8_t vvp_vector8_t::subvalue(unsigned base, unsigned wid) const
{
vvp_vector8_t tmp (wid);
vvp_scalar_t* tmp_ptr = tmp.size_<=PTR_THRESH? reinterpret_cast<vvp_scalar_t*>(tmp.val_) : tmp.ptr_;
const vvp_scalar_t* ptr = size_<=PTR_THRESH? reinterpret_cast<const vvp_scalar_t*>(val_) : ptr_;
unsigned idx = 0;
while ((idx < wid) && (base+idx < size_)) {
tmp.bits_[idx] = bits_[base+idx];
tmp_ptr[idx] = ptr[base+idx];
idx += 1;
}
@@ -1862,10 +1893,13 @@ vvp_vector8_t part_expand(const vvp_vector8_t&that, unsigned wid, unsigned off)
assert(off < wid);
vvp_vector8_t tmp (wid);
vvp_scalar_t* tmp_ptr = tmp.size_<=vvp_vector8_t::PTR_THRESH? reinterpret_cast<vvp_scalar_t*>(tmp.val_) : tmp.ptr_;
const vvp_scalar_t* that_ptr = that.size_<=vvp_vector8_t::PTR_THRESH? reinterpret_cast<const vvp_scalar_t*>(that.val_) : that.ptr_;
unsigned idx = off;
while (idx < wid && that.size_ > (idx-off)) {
tmp.bits_[idx] = that.bits_[idx-off];
tmp_ptr[idx] = that_ptr[idx-off];
idx += 1;
}
@@ -1907,7 +1941,7 @@ void vvp_net_fun_t::recv_vec4_pv(vvp_net_ptr_t, const vvp_vector4_t&bits,
assert(0);
}
void vvp_net_fun_t::recv_vec8(vvp_net_ptr_t port, vvp_vector8_t bit)
void vvp_net_fun_t::recv_vec8(vvp_net_ptr_t port, const vvp_vector8_t&bit)
{
recv_vec4(port, reduce4(bit));
}
@@ -2200,7 +2234,7 @@ void vvp_fun_signal::calculate_output_(vvp_net_ptr_t ptr)
run_vpi_callbacks();
}
void vvp_fun_signal::recv_vec8(vvp_net_ptr_t ptr, vvp_vector8_t bit)
void vvp_fun_signal::recv_vec8(vvp_net_ptr_t ptr, const vvp_vector8_t&bit)
{
recv_vec4(ptr, reduce4(bit));
}
@@ -2279,10 +2313,10 @@ vvp_fun_signal8::vvp_fun_signal8(unsigned wid)
void vvp_fun_signal8::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
{
recv_vec8(ptr, bit);
recv_vec8(ptr, vvp_vector8_t(bit,6,6));
}
void vvp_fun_signal8::recv_vec8(vvp_net_ptr_t ptr, vvp_vector8_t bit)
void vvp_fun_signal8::recv_vec8(vvp_net_ptr_t ptr, const vvp_vector8_t&bit)
{
switch (ptr.port()) {
case 0: // Normal input (feed from net, or set from process)
@@ -2323,10 +2357,10 @@ void vvp_fun_signal8::recv_vec8(vvp_net_ptr_t ptr, vvp_vector8_t bit)
void vvp_fun_signal8::recv_vec4_pv(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
unsigned base, unsigned wid, unsigned vwid)
{
recv_vec8_pv(ptr, bit, base, wid, vwid);
recv_vec8_pv(ptr, vvp_vector8_t(bit,6,6), base, wid, vwid);
}
void vvp_fun_signal8::recv_vec8_pv(vvp_net_ptr_t ptr, vvp_vector8_t bit,
void vvp_fun_signal8::recv_vec8_pv(vvp_net_ptr_t ptr, const vvp_vector8_t&bit,
unsigned base, unsigned wid, unsigned vwid)
{
assert(bit.size() == wid);
@@ -2354,7 +2388,7 @@ void vvp_fun_signal8::recv_vec8_pv(vvp_net_ptr_t ptr, vvp_vector8_t bit,
if (force_mask_.size() == 0)
force_mask_ = vvp_vector2_t(vvp_vector2_t::FILL0, size());
if (force_.size() == 0)
force_ = vvp_vector8_t(vvp_vector4_t(vwid, BIT4_Z));
force_ = vvp_vector8_t(vvp_vector4_t(vwid, BIT4_Z),6,6);
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
force_mask_.set_bit(base+idx, 1);
@@ -2668,51 +2702,8 @@ void vvp_wide_fun_t::recv_real(vvp_net_ptr_t port, double bit)
*/
# define UNAMBIG(v) (((v) & 0x0f) == (((v) >> 4) & 0x0f))
#if 0
# define STREN1(v) ( ((v)&0x80)? ((v)&0xf0) : (0x70 - ((v)&0xf0)) )
# define STREN0(v) ( ((v)&0x08)? ((v)&0x0f) : (0x07 - ((v)&0x0f)) )
#else
# define STREN1(v) (((v)&0x70) >> 4)
# define STREN0(v) ((v)&0x07)
#endif
vvp_scalar_t::vvp_scalar_t(vvp_bit4_t val, unsigned str0, unsigned str1)
{
assert(str0 <= 7);
assert(str1 <= 7);
if (str0 == 0 && str1 == 0) {
value_ = 0x00;
} else switch (val) {
case BIT4_0:
value_ = str0 | (str0<<4);
break;
case BIT4_1:
value_ = str1 | (str1<<4) | 0x88;
break;
case BIT4_X:
value_ = str0 | (str1<<4) | 0x80;
break;
case BIT4_Z:
value_ = 0x00;
break;
}
}
vvp_bit4_t vvp_scalar_t::value() const
{
if (value_ == 0) {
return BIT4_Z;
} else switch (value_ & 0x88) {
case 0x00:
return BIT4_0;
case 0x88:
return BIT4_1;
default:
return BIT4_X;
}
}
unsigned vvp_scalar_t::strength0() const
{
@@ -2871,19 +2862,6 @@ vvp_scalar_t resolve(vvp_scalar_t a, vvp_scalar_t b)
return res;
}
vvp_vector8_t resolve(const vvp_vector8_t&a, const vvp_vector8_t&b)
{
assert(a.size() == b.size());
vvp_vector8_t out (a.size());
for (unsigned idx = 0 ; idx < out.size() ; idx += 1) {
out.set_bit(idx, resolve(a.value(idx), b.value(idx)));
}
return out;
}
vvp_vector8_t resistive_reduction(const vvp_vector8_t&that)
{
static unsigned rstr[8] = {
+99 -46
View File
@@ -21,6 +21,7 @@
# include "config.h"
# include <stddef.h>
# include <new>
# include <assert.h>
#ifdef HAVE_IOSFWD
@@ -40,7 +41,6 @@ class vvp_net_t;
class vvp_net_fun_t;
/* Core net function types. */
class vvp_fun_concat;
class vvp_fun_drive;
class vvp_fun_part;
@@ -154,6 +154,8 @@ class vvp_vector4_t {
// Test that the vectors are exactly equal
bool eeq(const vvp_vector4_t&that) const;
// Test that the vectors are equal, with x and z comparing equal.
bool eq_xz(const vvp_vector4_t&that) const;
// Return true if there is an X or Z anywhere in the vector.
bool has_xz() const;
@@ -483,7 +485,6 @@ class vvp_scalar_t {
explicit vvp_scalar_t();
// Make an unambiguous value.
explicit vvp_scalar_t(vvp_bit4_t val, unsigned str);
explicit vvp_scalar_t(vvp_bit4_t val, unsigned str0, unsigned str1);
// Get the vvp_bit4_t version of the value
@@ -503,21 +504,22 @@ inline vvp_scalar_t::vvp_scalar_t()
value_ = 0;
}
inline vvp_scalar_t::vvp_scalar_t(vvp_bit4_t val, unsigned str)
inline vvp_scalar_t::vvp_scalar_t(vvp_bit4_t val, unsigned str0, unsigned str1)
{
assert(str <= 7);
assert(str0 <= 7);
assert(str1 <= 7);
if (str == 0) {
if (str0 == 0 && str1 == 0) {
value_ = 0x00;
} else switch (val) {
case BIT4_0:
value_ = str | (str<<4);
value_ = str0 | (str0<<4);
break;
case BIT4_1:
value_ = str | (str<<4) | 0x88;
value_ = str1 | (str1<<4) | 0x88;
break;
case BIT4_X:
value_ = str | (str<<4) | 0x80;
value_ = str0 | (str1<<4) | 0x80;
break;
case BIT4_Z:
value_ = 0x00;
@@ -525,6 +527,21 @@ inline vvp_scalar_t::vvp_scalar_t(vvp_bit4_t val, unsigned str)
}
}
inline vvp_bit4_t vvp_scalar_t::value() const
{
if (value_ == 0) {
return BIT4_Z;
} else switch (value_ & 0x88) {
case 0x00:
return BIT4_0;
case 0x88:
return BIT4_1;
default:
return BIT4_X;
}
}
extern vvp_scalar_t resolve(vvp_scalar_t a, vvp_scalar_t b);
extern ostream& operator<< (ostream&, vvp_scalar_t);
@@ -546,8 +563,8 @@ class vvp_vector8_t {
public:
explicit vvp_vector8_t(unsigned size =0);
// Make a vvp_vector8_t from a vector4 and a specified strength.
vvp_vector8_t(const vvp_vector4_t&that, unsigned str =6);
// Make a vvp_vector8_t from a vector4 and a specified
// strength.
explicit vvp_vector8_t(const vvp_vector4_t&that,
unsigned str0,
unsigned str1);
@@ -566,13 +583,31 @@ class vvp_vector8_t {
vvp_vector8_t& operator= (const vvp_vector8_t&that);
private:
// This is the number of vvp_scalar_t objects we can keep in
// the val_ buffer. If the vector8 is bigger then this, then
// resort to allocations to get a larger buffer.
enum { PTR_THRESH = 8 };
unsigned size_;
vvp_scalar_t*bits_;
union {
vvp_scalar_t*ptr_;
char val_[PTR_THRESH * sizeof(vvp_scalar_t)];
};
};
/* Resolve uses the default Verilog resolver algorithm to resolve
two drive vectors to a single output. */
extern vvp_vector8_t resolve(const vvp_vector8_t&a, const vvp_vector8_t&b);
inline vvp_vector8_t resolve(const vvp_vector8_t&a, const vvp_vector8_t&b)
{
assert(a.size() == b.size());
vvp_vector8_t out (a.size());
for (unsigned idx = 0 ; idx < out.size() ; idx += 1) {
out.set_bit(idx, resolve(a.value(idx), b.value(idx)));
}
return out;
}
/* This function implements the strength reduction implied by
Verilog standard resistive devices. */
extern vvp_vector8_t resistive_reduction(const vvp_vector8_t&a);
@@ -583,22 +618,58 @@ extern vvp_vector8_t part_expand(const vvp_vector8_t&a, unsigned wid, unsigned o
/* Print a vector8 value to a stream. */
extern ostream& operator<< (ostream&, const vvp_vector8_t&);
inline vvp_vector8_t::vvp_vector8_t(unsigned size)
: size_(size)
{
if (size_ <= PTR_THRESH) {
new (val_) vvp_scalar_t[PTR_THRESH];
} else {
ptr_ = new vvp_scalar_t[size_];
}
}
inline vvp_vector8_t::~vvp_vector8_t()
{
if (size_ > 0)
delete[]bits_;
if (size_ > PTR_THRESH)
delete[]ptr_;
}
inline vvp_scalar_t vvp_vector8_t::value(unsigned idx) const
{
assert(idx < size_);
return bits_[idx];
if (size_ <= PTR_THRESH)
return reinterpret_cast<const vvp_scalar_t*>(val_) [idx];
else
return ptr_[idx];
}
inline void vvp_vector8_t::set_bit(unsigned idx, vvp_scalar_t val)
{
assert(idx < size_);
bits_[idx] = val;
if (size_ <= PTR_THRESH)
reinterpret_cast<vvp_scalar_t*>(val_) [idx] = val;
else
ptr_[idx] = val;
}
// Exactly-equal for vvp_vector8_t is common and should be as tight
// as possible.
inline bool vvp_vector8_t::eeq(const vvp_vector8_t&that) const
{
if (size_ != that.size_)
return false;
if (size_ == 0)
return true;
if (size_ <= PTR_THRESH)
return 0 == memcmp(val_, that.val_, sizeof(val_));
for (unsigned idx = 0 ; idx < size_ ; idx += 1) {
if (! ptr_[idx] .eeq( that.ptr_[idx] ))
return false;
}
return true;
}
/*
@@ -690,6 +761,13 @@ struct vvp_net_t {
vvp_net_ptr_t port[4];
vvp_net_ptr_t out;
vvp_net_fun_t*fun;
public: // Need a better new for these objects.
static void* operator new(std::size_t size);
static void operator delete(void*); // not implemented
private: // not implemented
static void* operator new[](std::size_t size);
static void operator delete[](void*);
};
/*
@@ -721,7 +799,7 @@ class vvp_net_fun_t {
virtual ~vvp_net_fun_t();
virtual void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit);
virtual void recv_vec8(vvp_net_ptr_t port, vvp_vector8_t bit);
virtual void recv_vec8(vvp_net_ptr_t port, const vvp_vector8_t&bit);
virtual void recv_real(vvp_net_ptr_t port, double bit);
virtual void recv_long(vvp_net_ptr_t port, long bit);
@@ -738,31 +816,6 @@ class vvp_net_fun_t {
/* **** Some core net functions **** */
/* vvp_fun_concat
* This node function creates vectors (vvp_vector4_t) from the
* concatenation of the inputs. The inputs (4) may be vector or
* vector8 objects, but they are reduced to vector4 values and
* strength information lost.
*
* The expected widths of the input vectors must be given up front so
* that the positions in the output vector (and also the size of the
* output vector) can be worked out. The input vectors must match the
* expected width.
*/
class vvp_fun_concat : public vvp_net_fun_t {
public:
vvp_fun_concat(unsigned w0, unsigned w1,
unsigned w2, unsigned w3);
~vvp_fun_concat();
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit);
private:
unsigned wid_[4];
vvp_vector4_t val_;
};
/* 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
@@ -962,7 +1015,7 @@ class vvp_fun_signal : public vvp_fun_signal_vec {
explicit vvp_fun_signal(unsigned wid, vvp_bit4_t init=BIT4_X);
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit);
void recv_vec8(vvp_net_ptr_t port, vvp_vector8_t bit);
void recv_vec8(vvp_net_ptr_t port, const vvp_vector8_t&bit);
// Part select variants of above
void recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&bit,
@@ -994,12 +1047,12 @@ class vvp_fun_signal8 : public vvp_fun_signal_vec {
explicit vvp_fun_signal8(unsigned wid);
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit);
void recv_vec8(vvp_net_ptr_t port, vvp_vector8_t bit);
void recv_vec8(vvp_net_ptr_t port, const vvp_vector8_t&bit);
// Part select variants of above
void recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&bit,
unsigned base, unsigned wid, unsigned vwid);
void recv_vec8_pv(vvp_net_ptr_t port, vvp_vector8_t bit,
void recv_vec8_pv(vvp_net_ptr_t port, const vvp_vector8_t&bit,
unsigned base, unsigned wid, unsigned vwid);
// Get information about the vector value.
@@ -1135,7 +1188,7 @@ inline void vvp_send_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&val)
}
}
extern void vvp_send_vec8(vvp_net_ptr_t ptr, vvp_vector8_t val);
extern void vvp_send_vec8(vvp_net_ptr_t ptr, const vvp_vector8_t&val);
extern void vvp_send_real(vvp_net_ptr_t ptr, double val);
extern void vvp_send_long(vvp_net_ptr_t ptr, long val);
extern void vvp_send_long_pv(vvp_net_ptr_t ptr, long val,