mirror of
https://github.com/steveicarus/iverilog.git
synced 2026-08-23 06:16:47 +02:00
Compare commits
7
Commits
s20260301
...
performance
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
afa2478801 | ||
|
|
79feb44f10 | ||
|
|
c03d76a0d7 | ||
|
|
d0f303463d | ||
|
|
35fe8fae00 | ||
|
|
2e95a740da | ||
|
|
2f4e5bf5b6 |
+4
-4
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user